import { ok, err, type CommandContext } from "@tailor-platform/erp-kit/core"; import type { Transaction } from "../generated/kysely-tailordb"; import { MissingRequiredFieldError, InvalidDateRangeError } from "../lib/errors.generated"; export interface CreateShiftScheduleInput { startDate: Date; endDate: Date; } /** * Function: createShiftSchedule * Description: Opens a shiftSchedule period in DRAFT. The period is exactly the from/to a planner * enters when generating shifts, so a generation run creates one ShiftSchedule and hangs its Shifts * off it. Overlapping periods are deliberately allowed: membership is the explicit Shift.shiftScheduleId * FK, so two shiftSchedules covering the same dates (a second site, a supplementary 応援 shiftSchedule, a * partial revision) are unambiguous rather than a conflict to reject. */ export async function run>( db: Transaction, input: CreateShiftScheduleInput & CF, _ctx: CommandContext, ) { const { startDate, endDate, ...customFields } = input; if (!startDate || !endDate) { return err(new MissingRequiredFieldError("startDate/endDate")); } if (endDate < startDate) { return err(new InvalidDateRangeError(`${startDate.toISOString()}..${endDate.toISOString()}`)); } const shiftSchedule = await db .insertInto("ShiftSchedule") .values({ ...(customFields as Record), startDate, endDate, status: "DRAFT", confirmedAt: null, }) .returningAll() .executeTakeFirstOrThrow(); return ok({ shiftSchedule }); }