import { err, ok, type CommandContext } from "@tailor-platform/erp-kit/core"; import { pipelineItemLifecycle } from "../db/pipelineItem.lifecycle.generated"; import type { Transaction } from "../generated/kysely-tailordb"; import { ItemNotFoundError, ItemNotOpenError } from "../lib/errors.generated"; export interface ClosePipelineItemInput { itemId: string; } export async function run(db: Transaction, input: ClosePipelineItemInput, ctx: CommandContext) { const item = await db .selectFrom("PipelineItem") .selectAll() .where("id", "=", input.itemId) .forUpdate() .executeTakeFirst(); if (!item) { return err(new ItemNotFoundError(input.itemId)); } const nextLifecycle = pipelineItemLifecycle.tryTransition(item.lifecycle, "close"); if (!nextLifecycle) { return err(new ItemNotOpenError(input.itemId)); } const now = new Date(); const closedItem = await db .updateTable("PipelineItem") .set({ lifecycle: nextLifecycle, updatedAt: now, }) .where("id", "=", input.itemId) .returningAll() .executeTakeFirst(); await db .insertInto("PipelineItemChange") .values({ itemId: item.id, changedByUserId: ctx.actorId, changeType: "LIFECYCLE", fieldName: "LIFECYCLE", prevValue: item.lifecycle, newValue: nextLifecycle, createdAt: now, }) .execute(); return ok({ item: closedItem ?? { ...item, lifecycle: nextLifecycle, updatedAt: now }, }); }