From b944a17572b2a062b2011d7250bb6ff536cd8a38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hartmut=20N=C3=B6renberg?= Date: Thu, 9 Apr 2026 10:11:02 +0200 Subject: [PATCH] feat(db,shared): add overbookingAcknowledged field and conflict check types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Assignment.overbookingAcknowledged Boolean @default(false) — audit trail for intentional overbookings - CreateAssignmentBaseSchema gets allowOverbooking?: boolean flag so callers can explicitly opt in to overbooking - Export AllocationConflictCheckResult, AllocationConflictDay, AllocationVacationOverlap types from @capakraken/shared for use in the new conflict-check API procedure and AllocationModal Co-Authored-By: Claude Sonnet 4.6 --- packages/db/prisma/schema.prisma | 7 ++-- .../shared/src/schemas/allocation.schema.ts | 33 +++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/packages/db/prisma/schema.prisma b/packages/db/prisma/schema.prisma index 777a3a1..1b13c80 100644 --- a/packages/db/prisma/schema.prisma +++ b/packages/db/prisma/schema.prisma @@ -1331,9 +1331,10 @@ model Assignment { percentage Float role String? roleId String? - dailyCostCents Int - status AllocationStatus @default(PROPOSED) - metadata Json @db.JsonB @default("{}") + dailyCostCents Int + status AllocationStatus @default(PROPOSED) + metadata Json @db.JsonB @default("{}") + overbookingAcknowledged Boolean @default(false) demandRequirement DemandRequirement? @relation(fields: [demandRequirementId], references: [id]) resource Resource @relation(fields: [resourceId], references: [id]) diff --git a/packages/shared/src/schemas/allocation.schema.ts b/packages/shared/src/schemas/allocation.schema.ts index 51c62c0..140ba5b 100644 --- a/packages/shared/src/schemas/allocation.schema.ts +++ b/packages/shared/src/schemas/allocation.schema.ts @@ -43,6 +43,8 @@ export const CreateAssignmentBaseSchema = z.object({ dailyCostCents: z.number().int().min(0).optional(), status: z.nativeEnum(AllocationStatus).default(AllocationStatus.PROPOSED), metadata: z.record(z.string(), z.unknown()).default({}), + /** When true the caller acknowledges the resource will be overbooked. */ + allowOverbooking: z.boolean().optional().default(false), }); /** @@ -119,3 +121,34 @@ export type FillDemandRequirementInput = z.infer; export type ShiftProjectInput = z.infer; export type UpdateAllocationHoursInput = z.infer; + +// ─── Conflict check ─────────────────────────────────────────────────────────── + +export interface AllocationConflictDay { + /** ISO date string (YYYY-MM-DD) */ + date: string; + availableHours: number; + existingHours: number; + requestedHours: number; + overageHours: number; +} + +export interface AllocationVacationOverlap { + startDate: string; + endDate: string; + /** VacationType enum value */ + type: string; + isHalfDay: boolean; +} + +export interface AllocationConflictCheckResult { + isOverbooking: boolean; + overbooking: { + conflictDays: AllocationConflictDay[]; + totalConflictDays: number; + /** Highest single-day overage as a percentage above capacity */ + maxOverbookPercent: number; + } | null; + vacationOverlap: AllocationVacationOverlap[]; + hasVacationOverlap: boolean; +}