feat(db,shared): add overbookingAcknowledged field and conflict check types

- 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 <noreply@anthropic.com>
This commit is contained in:
2026-04-09 10:11:02 +02:00
parent 60d267fa0a
commit b944a17572
2 changed files with 37 additions and 3 deletions
+1
View File
@@ -1334,6 +1334,7 @@ model Assignment {
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])
@@ -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<typeof FillDemandRequirementSch
export type FillOpenDemandByAllocationInput = z.infer<typeof FillOpenDemandByAllocationSchema>;
export type ShiftProjectInput = z.infer<typeof ShiftProjectSchema>;
export type UpdateAllocationHoursInput = z.infer<typeof UpdateAllocationHoursSchema>;
// ─── 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;
}