L13 Planung: Plantafel-, Einplan-, Empfehlungs-, Live- und Verzugsdienste mit API und Meldungen
Services board/schedule (L2 assign+update in inTransaction, Versionskonflikt, Audit), recommend (Luftlinie + freie Kolonnenzeit), live (Kolonnen, ohne Geräte-Koordinaten), watch (Verzug ab 80 %, Überschreitung, gefährdete Folgeaufträge, früher fertig mit Vorschlägen), Kolonnenkapazität. Job planning-watch alle 5 min, Events planning.capacity_freed/overrun/followup_at_risk (In-App an Backoffice + Teamleiter, Dedupe im Audit-Log), L12-Adapter für source/approvalStatus/manual. API /api/v1/planning/{board,schedule,recommendations,live} + OpenAPI. Tests core, recommend, live, watch.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
import { z } from "zod";
|
||||
import { writeAuditLog } from "@/server/audit";
|
||||
import { assertCan, ServiceError, type ServiceCtx } from "@/server/services/context";
|
||||
import { parseInput } from "@/server/services/work-orders/_shared";
|
||||
|
||||
/** Planning settings of a team = crew (L13): crew working day in minutes + working days bit mask. */
|
||||
|
||||
const settingsSchema = z.object({
|
||||
dailyCapacityMinutes: z.coerce.number().int().min(0).max(24 * 60),
|
||||
workingDays: z.coerce.number().int().min(0).max(127),
|
||||
});
|
||||
export type TeamPlanningSettingsInput = z.input<typeof settingsSchema>;
|
||||
|
||||
export async function updateTeamPlanningSettings(ctx: ServiceCtx, teamId: string, raw: TeamPlanningSettingsInput) {
|
||||
assertCan(ctx, "team:manage");
|
||||
const input = parseInput(settingsSchema, raw);
|
||||
const before = await ctx.db.team.findFirst({
|
||||
where: { id: teamId, deletedAt: null },
|
||||
select: { id: true, dailyCapacityMinutes: true, workingDays: true },
|
||||
});
|
||||
if (!before) throw new ServiceError("not_found", "team_not_found");
|
||||
const after = await ctx.db.team.update({
|
||||
where: { id: teamId },
|
||||
data: input,
|
||||
select: { id: true, dailyCapacityMinutes: true, workingDays: true },
|
||||
});
|
||||
await writeAuditLog({ tenantId: ctx.tenantId, actorId: ctx.userId, action: "update", entity: "team", entityId: teamId, before, after });
|
||||
return after;
|
||||
}
|
||||
Reference in New Issue
Block a user