import { err, ok, type CommandContext } from "@tailor-platform/erp-kit/core"; import type { Transaction } from "../generated/kysely-tailordb"; import { KeyImmutableError, TimeEntryCodeNotFoundError } from "../lib/errors.generated"; export type UpdateTimeEntryCodeInput = { id: string; } & { displayName?: string; category?: string; payMapKey?: string; }; /** * Function: updateTimeEntryCode * Description: Corrects a TimeEntryCode's displayName, category, or * payMapKey. The key itself is immutable — it is never accepted as part of * this command's input — so a genuinely new time type must be created as a * new code, not a rename of an existing one. */ export async function run(db: Transaction, input: UpdateTimeEntryCodeInput, _ctx: CommandContext) { const timeEntryCode = await db .selectFrom("TimeEntryCode") .selectAll() .where("id", "=", input.id) .forUpdate() .executeTakeFirst(); if (!timeEntryCode) { return err(new TimeEntryCodeNotFoundError(input.id)); } // `key` is a natural/lookup key, not a mutable field — it is intentionally // absent from UpdateTimeEntryCodeInput. Guard against a caller bypassing // the type and attempting to change it directly. if ("key" in input) { return err(new KeyImmutableError(timeEntryCode.key)); } const updates: { displayName?: string; category?: string; payMapKey?: string; } = {}; if (input.displayName !== undefined) updates.displayName = input.displayName; if (input.category !== undefined) updates.category = input.category; if (input.payMapKey !== undefined) updates.payMapKey = input.payMapKey; const updated = await db .updateTable("TimeEntryCode") .set(updates) .where("id", "=", input.id) .returningAll() .executeTakeFirstOrThrow(); return ok({ timeEntryCode: updated }); }