From 10c32b2c97b65a064764c70a8bcc64c9cb9841a3 Mon Sep 17 00:00:00 2001 From: WuYongJie Date: Mon, 24 Aug 2026 16:40:58 +0800 Subject: [PATCH] fix(intake): preserve basic info confirmation after factory sync --- .../workspaces/preview/previewState.test.ts | 89 +++++++++++++++++++ .../workspaces/preview/previewState.ts | 83 +++++++++-------- ...basic-info-confirmation-validation.test.ts | 8 ++ .../basic-info-confirmation-validation.ts | 6 -- 4 files changed, 145 insertions(+), 41 deletions(-) create mode 100644 furniture-3d-system/src/app/intake/non-integrated/workspaces/preview/previewState.test.ts diff --git a/furniture-3d-system/src/app/intake/non-integrated/workspaces/preview/previewState.test.ts b/furniture-3d-system/src/app/intake/non-integrated/workspaces/preview/previewState.test.ts new file mode 100644 index 00000000..66361f89 --- /dev/null +++ b/furniture-3d-system/src/app/intake/non-integrated/workspaces/preview/previewState.test.ts @@ -0,0 +1,89 @@ +import type { NonIntegratedSkuItem } from "../../nonIntegratedStorage"; +import { buildSkuContentRevisionSignature } from "./previewState"; + +function createSku( + overrides: Partial = {}, +): NonIntegratedSkuItem { + return { + id: "sku-1", + skuSequence: 1, + batchNo: 1, + packageGroupId: "", + packageSuffix: "", + image: "image.png", + imageName: "image.png", + model: "SZ0230K01", + skuCode: "SZ023001", + setCount: "1", + specName: "款式一 140/60/75 胡桃色", + barcode: "SZ023001V01", + size: "140/60/75", + color: "胡桃色", + material: "橡胶木", + boardMaterialType: "ENF级", + versionNo: "V01", + attributeCode: "N", + drawingId: "SZ0230K01NV01", + installMethod: "拆装", + executeStandard: "GB/T 3324", + nationalStandardCompliant: "是", + manufacturer: "", + manufacturerCode: "", + minimumOrderQuantity: "", + salesStatus: "销售", + tagMaterial: "", + model3dPreviewNodes: [], + componentDetails: [], + holePoints: [], + ...overrides, + }; +} + +function buildSignature(sku: NonIntegratedSkuItem) { + return buildSkuContentRevisionSignature({ + skuItems: [sku], + skuBatchCount: 1, + skuBatchFlowNos: { 1: "DD20260824001" }, + skuBatchChangeTypes: { 1: "新品" }, + }); +} + +describe("buildSkuContentRevisionSignature", () => { + it("keeps basic information confirmed when factory supplier data is projected back", () => { + const beforeFactory = createSku(); + const afterFactory = createSku({ + manufacturer: "兰考华兰家具", + manufacturerCode: "N1280", + barcode: "SZ023001N1280V01", + }); + + expect(buildSignature(afterFactory)).toBe(buildSignature(beforeFactory)); + }); + + it("still detects a manual barcode change", () => { + const autoBarcode = createSku({ + manufacturer: "兰考华兰家具", + manufacturerCode: "N1280", + barcode: "SZ023001N1280V01", + }); + const manualBarcode = createSku({ + manufacturer: "兰考华兰家具", + manufacturerCode: "N1280", + barcode: "MANUAL-BARCODE-001", + }); + + expect(buildSignature(manualBarcode)).not.toBe(buildSignature(autoBarcode)); + }); + + it("still detects a cleared barcode", () => { + expect(buildSignature(createSku({ barcode: "" }))).not.toBe( + buildSignature(createSku()), + ); + }); + + it("still detects a design-owned basic information change", () => { + expect(buildSignature(createSku({ material: "岩板" }))).not.toBe( + buildSignature(createSku()), + ); + }); +}); diff --git a/furniture-3d-system/src/app/intake/non-integrated/workspaces/preview/previewState.ts b/furniture-3d-system/src/app/intake/non-integrated/workspaces/preview/previewState.ts index d1ebd12f..70a2bffc 100644 --- a/furniture-3d-system/src/app/intake/non-integrated/workspaces/preview/previewState.ts +++ b/furniture-3d-system/src/app/intake/non-integrated/workspaces/preview/previewState.ts @@ -6,6 +6,7 @@ import type { NonIntegratedSkuHolePoint, NonIntegratedSkuItem, } from "../../nonIntegratedStorage"; +import { buildAutoBarcode } from "../basic-info/skuAutoHelpers"; export type PreviewNodeOffsetMap = Record; export type PreviewNodeRotationMap = Record< @@ -152,41 +153,53 @@ export function buildSkuContentRevisionSignature({ skuBatchCount, skuBatchFlowNos, skuBatchChangeTypes, - skuItems: skuItems.map((item) => ({ - id: item.id, - skuSequence: item.skuSequence, - batchNo: item.batchNo, - packageGroupId: item.packageGroupId, - packageSuffix: item.packageSuffix, - image: item.image, - imageName: item.imageName, - model: item.model, - skuCode: item.skuCode, - setCount: item.setCount, - specName: item.specName, - barcode: item.barcode, - size: item.size, - color: item.color, - material: item.material, - boardMaterialType: item.boardMaterialType ?? "", - versionNo: item.versionNo, - attributeCode: item.attributeCode, - drawingId: item.drawingId, - installMethod: item.installMethod, - executeStandard: item.executeStandard, - nationalStandardCompliant: item.nationalStandardCompliant, - manufacturer: item.manufacturer, - manufacturerCode: item.manufacturerCode, - salesStatus: item.salesStatus, - tagMaterial: item.tagMaterial, - model3dPreviewNodes: item.model3dPreviewNodes ?? [], - componentDetails: item.componentDetails ?? [], - holePoints: item.holePoints ?? [], - source: item.source ?? "", - sourceTable: item.sourceTable ?? "", - sourceSkuId: item.sourceSkuId ?? "", - contentLocked: item.contentLocked === true, - })), + skuItems: skuItems.map((item) => { + const normalizedBarcode = item.barcode.trim().toUpperCase(); + const supplierBarcode = buildAutoBarcode( + item.skuCode, + item.manufacturerCode, + item.versionNo, + ); + // Supplier data belongs to factory confirmation; manual barcodes stay revision-sensitive. + const revisionBarcode = + normalizedBarcode && normalizedBarcode === supplierBarcode + ? buildAutoBarcode(item.skuCode, "", item.versionNo) + : item.barcode; + + return { + id: item.id, + skuSequence: item.skuSequence, + batchNo: item.batchNo, + packageGroupId: item.packageGroupId, + packageSuffix: item.packageSuffix, + image: item.image, + imageName: item.imageName, + model: item.model, + skuCode: item.skuCode, + setCount: item.setCount, + specName: item.specName, + barcode: revisionBarcode, + size: item.size, + color: item.color, + material: item.material, + boardMaterialType: item.boardMaterialType ?? "", + versionNo: item.versionNo, + attributeCode: item.attributeCode, + drawingId: item.drawingId, + installMethod: item.installMethod, + executeStandard: item.executeStandard, + nationalStandardCompliant: item.nationalStandardCompliant, + salesStatus: item.salesStatus, + tagMaterial: item.tagMaterial, + model3dPreviewNodes: item.model3dPreviewNodes ?? [], + componentDetails: item.componentDetails ?? [], + holePoints: item.holePoints ?? [], + source: item.source ?? "", + sourceTable: item.sourceTable ?? "", + sourceSkuId: item.sourceSkuId ?? "", + contentLocked: item.contentLocked === true, + }; + }), }); } diff --git a/furniture-3d-system/src/lib/open-product/basic-info-confirmation-validation.test.ts b/furniture-3d-system/src/lib/open-product/basic-info-confirmation-validation.test.ts index 45e9fd7f..2df16811 100644 --- a/furniture-3d-system/src/lib/open-product/basic-info-confirmation-validation.test.ts +++ b/furniture-3d-system/src/lib/open-product/basic-info-confirmation-validation.test.ts @@ -46,6 +46,14 @@ describe("basicInfoConfirmationValidation", () => { ).toBeNull(); }); + it("does not require supplier name or supplier code", () => { + expect( + getBasicInfoConfirmationValidationMessage([ + createSku({ manufacturer: "", manufacturerCode: "" }), + ]), + ).toBeNull(); + }); + it("lists each incomplete SKU and its missing required fields", () => { const incompleteSkus = getBasicInfoConfirmationIncompleteSkus([ createSku({ skuCode: "", setCount: "", batchNo: 0 }), diff --git a/furniture-3d-system/src/lib/open-product/basic-info-confirmation-validation.ts b/furniture-3d-system/src/lib/open-product/basic-info-confirmation-validation.ts index e0bb2b1e..74e4f426 100644 --- a/furniture-3d-system/src/lib/open-product/basic-info-confirmation-validation.ts +++ b/furniture-3d-system/src/lib/open-product/basic-info-confirmation-validation.ts @@ -14,8 +14,6 @@ type BasicInfoRequiredSkuField = | "installMethod" | "executeStandard" | "nationalStandardCompliant" - | "manufacturer" - | "manufacturerCode" | "batchNo"; type BasicInfoConfirmationSku = { @@ -35,8 +33,6 @@ type BasicInfoConfirmationSku = { installMethod: string; executeStandard: string; nationalStandardCompliant: string; - manufacturer: string; - manufacturerCode: string; batchNo: number; }; @@ -59,8 +55,6 @@ export const BASIC_INFO_CONFIRMATION_REQUIRED_FIELDS: ReadonlyArray<{ { key: "installMethod", label: "安装方式" }, { key: "executeStandard", label: "执行标准" }, { key: "nationalStandardCompliant", label: "符合国标" }, - { key: "manufacturer", label: "供应商名称" }, - { key: "manufacturerCode", label: "供应商代码" }, { key: "batchNo", label: "创建批次" }, ];