Files
craftvia/src/server/services/planning/time-tracking.ts
T
msolarczekandClaude Opus 5 5e10523df6 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>
2026-09-15 10:13:39 +02:00

31 lines
1.6 KiB
TypeScript

import { Prisma } from "@prisma/client";
/**
* Adapter to the time tracking model of lane L12 (read-only use in planning).
*
* L12 adds `TimeEntry.source` (tracked | manual), `TimeEntry.approvalStatus` (approved | pending |
* rejected) and `WorkSession.manual`. Planning rules:
* - live situation / delay evaluation: only `source = tracked` entries of non-manual sessions,
* - actual duration of completed orders: only `approvalStatus = approved` entries.
* The filters are enabled automatically as soon as the generated Prisma client knows the fields
* (after the L12 merge); before that they are no-ops, so this lane compiles against both schemas.
*/
const entryFields = new Set<string>(Object.values(Prisma.TimeEntryScalarFieldEnum));
const sessionFields = new Set<string>(Object.values(Prisma.WorkSessionScalarFieldEnum));
export const TIME_TRACKING_FIELDS = {
entrySource: entryFields.has("source"),
entryApproval: entryFields.has("approvalStatus"),
sessionManual: sessionFields.has("manual"),
} as const;
/** Time entries recorded by the running clock (no manual additions). */
export const trackedEntryWhere = (TIME_TRACKING_FIELDS.entrySource ? { source: "tracked" } : {}) as unknown as Prisma.TimeEntryWhereInput;
/** Approved time entries (actual duration of completed orders). */
export const approvedEntryWhere = (TIME_TRACKING_FIELDS.entryApproval ? { approvalStatus: "approved" } : {}) as unknown as Prisma.TimeEntryWhereInput;
/** Sessions started by the clock (manual after-the-fact sessions excluded). */
export const trackedSessionWhere = (TIME_TRACKING_FIELDS.sessionManual ? { manual: false } : {}) as unknown as Prisma.WorkSessionWhereInput;