import { ok, err } from "@tailor-platform/erp-kit/core"; import type { Transaction } from "../generated/kysely-tailordb"; import { DuplicateAssignmentError, ItemNotFoundError, NodeNotFoundError, } from "../lib/errors.generated"; export interface AssignItemToTaxonomyInput { itemId: string; taxonomyNodeId: string; } /** * Function: assignItemToTaxonomy * * Creates a link between an item and a taxonomy node for many-to-many classification. */ export async function run(db: Transaction, input: AssignItemToTaxonomyInput) { const { itemId, taxonomyNodeId } = input; // 1. Check item exists (validation only — not writing to Item) const item = await db.selectFrom("Item").selectAll().where("id", "=", itemId).executeTakeFirst(); if (!item) { return err(new ItemNotFoundError(itemId)); } // 2. Check node exists (validation only — not writing to TaxonomyNode) const node = await db .selectFrom("TaxonomyNode") .selectAll() .where("id", "=", taxonomyNodeId) .executeTakeFirst(); if (!node) { return err(new NodeNotFoundError(taxonomyNodeId)); } // 3. Check for duplicate assignment (uniqueness before insert — lock) const existing = await db .selectFrom("ItemTaxonomyAssignment") .selectAll() .where("itemId", "=", itemId) .where("taxonomyNodeId", "=", taxonomyNodeId) .forUpdate() .executeTakeFirst(); if (existing) { return err(new DuplicateAssignmentError(`${itemId} in ${taxonomyNodeId}`)); } // 4. Create assignment const assignment = await db .insertInto("ItemTaxonomyAssignment") .values({ itemId, taxonomyNodeId, }) .returningAll() .executeTakeFirstOrThrow(); return ok({ assignment: assignment }); }