import { DEFAULT_PAGE_SIZE, buildPaginatedResult, err, ok, type PaginationInput, type ReadonlyDB, } from "@tailor-platform/erp-kit/core"; import type { DB } from "../generated/kysely-tailordb"; import { LeaveTypeNotFoundError } from "../lib/errors.generated"; type LeaveGrantOrderByField = "expirationDate" | "grantedDate"; export interface ListLeaveGrantsByWorkerInput extends PaginationInput { workerId: string; leaveTypeKey?: string; } /** * Function: listLeaveGrantsByWorker * Lists a worker's LeaveGrant history (optionally scoped to a leave type), * including expired and fully-consumed grants, ordered by expirationDate * ascending (soonest-expiring first) — mirroring the FIFO order consumption * itself uses. The ledger is keyed to the Worker, not a specific employment * or assignment. */ export async function run(db: ReadonlyDB, input: ListLeaveGrantsByWorkerInput) { if (input.leaveTypeKey !== undefined) { const leaveType = await db .selectFrom("LeaveType") .select("id") .where("key", "=", input.leaveTypeKey) .executeTakeFirst(); if (!leaveType) { return err(new LeaveTypeNotFoundError(input.leaveTypeKey)); } } // NOTE: workerId references workforce's Worker (cross-module), and there is no query // injection wired into module.ts yet, so we cannot proactively verify the Worker exists // here (see WORKER_NOT_FOUND in the doc). Following the precedent in // modules/workforce/command/createWorker.ts, we skip that check; referential integrity // for workerId is left to the DB-level FK constraint. const limit = input.limit ?? DEFAULT_PAGE_SIZE; const offset = input.offset ?? 0; const orderBy = input.orderBy ?? "expirationDate"; const orderDirection = input.orderDirection ?? "asc"; let query = db.selectFrom("LeaveGrant").selectAll().where("workerId", "=", input.workerId); if (input.leaveTypeKey !== undefined) { query = query.where("leaveTypeKey", "=", input.leaveTypeKey); } const grants = await query .orderBy(orderBy, orderDirection) .limit(limit + 1) .offset(offset) .execute(); return ok(buildPaginatedResult(grants, limit)); }