import { ok, err } from "@tailor-platform/erp-kit/core"; import type { Transaction } from "../generated/kysely-tailordb"; import { AssignmentNotFoundError, ProductNotFoundError, ProductArchivedError, AxisStructureLockedError, } from "../lib/errors.generated"; export interface RemoveAttributeValueFromProductInput { productId: string; attributeId: string; valueId: string; } /** * Function: removeAttributeValueFromProduct * * Removes an attribute value assignment from a product. * Identified by the composite key (productId, attributeId, valueId). * * Status-based rules: * - DRAFT: freely removable * - ACTIVE: removal is blocked (axis structure locked) * - ARCHIVED: all changes blocked */ export async function run(db: Transaction, input: RemoveAttributeValueFromProductInput) { const { productId, attributeId, valueId } = input; // Check product exists const product = await db .selectFrom("Product") .selectAll() .where("id", "=", productId) .executeTakeFirst(); if (!product) { return err(new ProductNotFoundError(productId)); } // Status-based rules if (product.status === "ARCHIVED") { return err(new ProductArchivedError(productId)); } if (product.status === "ACTIVE") { return err(new AxisStructureLockedError(productId)); } // Find the assignment const assignment = await db .selectFrom("ProductAttributeAssignment") .selectAll() .where("productId", "=", productId) .where("attributeId", "=", attributeId) .where("valueId", "=", valueId) .forUpdate() .executeTakeFirst(); if (!assignment) { return err(new AssignmentNotFoundError(`${productId}:${attributeId}:${valueId}`)); } await db.deleteFrom("ProductAttributeAssignment").where("id", "=", assignment.id).execute(); return ok({ id: assignment.id }); }