import { type CommonReservedFields, type NoReservedFields, defaultGqlPermission, defaultPermission, } from "@tailor-platform/erp-kit/core"; import { db, type TailorAnyDBField, type TailorAnyDBType } from "@tailor-platform/sdk"; // Normalized blockType enum values: WORK/BREAK/STEP_OUT const BLOCK_TYPES = ["WORK", "BREAK", "STEP_OUT"] as const; // Normalized sourceKind enum values: how the block was formed const SOURCE_KINDS = ["PUNCH_DERIVED", "MANUAL", "IMPORT"] as const; const builtins = (params: { assignmentType?: TailorAnyDBType }) => { // Cross-module FK: relation only when the foreign type is injected; plain uuid at codegen const assignmentId = db .uuid() .description("Foreign key to the workforce Assignment effective on workDate"); return { assignmentId: params.assignmentType ? assignmentId.relation({ type: "n-1", toward: { type: params.assignmentType, as: "assignment" }, backward: "reportedTimeBlocks", }) : assignmentId, // Day-breaker assigned workday, which may differ from a punch's occurredAt date workDate: db .date() .description("Workday this block belongs to, as assigned by the day-breaker"), blockType: db.enum(BLOCK_TYPES).description("Normalized block type (WORK/BREAK/STEP_OUT)"), sourceKind: db .enum(SOURCE_KINDS) .description("How this block was formed (PUNCH_DERIVED/MANUAL/IMPORT)"), startAt: db .datetime() .description("Interval start; bounds a non-negative interval on workDate"), endAt: db .datetime() .description( "Interval end; may be after midnight for an overnight block while still belonging to workDate", ), // Reserved for corrections (ADR-014); absent on an original first declaration correctionReason: db .string({ optional: true }) .description( "Reason for this correction; required on a correction block, absent on an original declaration", ), // Self-reference: supersede chain (ADR-014). Absence of this field marks the block current. supersededByBlockId: db .uuid({ optional: true }) .relation({ type: "n-1", toward: { type: "self" }, backward: "supersedes" }) .description( "Foreign key to the replacement block that superseded this one; absent means this block is current", ), }; }; type ReservedFields = keyof ReturnType | CommonReservedFields; export interface CreateReportedTimeBlockTypeParams> { fields?: NoReservedFields; assignmentType?: TailorAnyDBType; } export function createReportedTimeBlockType>( params: CreateReportedTimeBlockTypeParams, ) { return db .table("ReportedTimeBlock", { ...builtins(params), ...((params.fields ?? {}) as F), ...db.fields.timestamps(), }) .permission(defaultPermission) .gqlPermission(defaultGqlPermission); } // Codegen instance with no cross-module types; real FK injected via module.ts export const reportedTimeBlock = createReportedTimeBlockType({});