import { ok, err } from "@tailor-platform/erp-kit/core"; import type { Transaction, Updateable } from "../generated/kysely-tailordb"; import { MissingRequiredFieldsError, NodeNotFoundError } from "../lib/errors.generated"; export type UpdateTaxonomyNodeInput = ( | { id: string; } | { code: string; } ) & { name?: string; }; /** * Function: updateTaxonomyNode * * Updates the display name of an existing taxonomy node. * The node can be looked up by id or code. */ export async function run>( db: Transaction, input: UpdateTaxonomyNodeInput & Omit, "status">, ) { const { name } = input; const KNOWN_KEYS = new Set(["id", "code", "name"]); const customFields: Record = {}; for (const [key, value] of Object.entries(input as Record)) { if (!KNOWN_KEYS.has(key)) { customFields[key] = value; } } // 1. Check node exists (lookup by id or code) const node = "id" in input ? await db .selectFrom("TaxonomyNode") .selectAll() .where("id", "=", (input as { id: string }).id) .forUpdate() .executeTakeFirst() : await db .selectFrom("TaxonomyNode") .selectAll() .where("code", "=", (input as { code: string }).code) .forUpdate() .executeTakeFirst(); if (!node) { const key = "id" in input ? (input as { id: string }).id : (input as { code: string }).code; return err(new NodeNotFoundError(key)); } // 2. Name must be provided and non-empty (unless custom fields provided) const hasCustomFields = Object.keys(customFields).length > 0; if (!name && !hasCustomFields) { return err(new MissingRequiredFieldsError("name")); } // 3. Update fields const updates: Updateable<"TaxonomyNode"> = { ...(customFields as Updateable<"TaxonomyNode">), }; if (name !== undefined) updates.name = name; const updatedNode = await db .updateTable("TaxonomyNode") .set(updates) .where("id", "=", node.id) .returningAll() .executeTakeFirstOrThrow(); return ok({ taxonomyNode: updatedNode }); }