fix(intake): preserve basic info confirmation after factory sync

This commit is contained in:
WuYongJie 2026-08-24 16:40:58 +08:00
parent b1cebf0707
commit 10c32b2c97
4 changed files with 145 additions and 41 deletions

View File

@ -0,0 +1,89 @@
import type { NonIntegratedSkuItem } from "../../nonIntegratedStorage";
import { buildSkuContentRevisionSignature } from "./previewState";
function createSku(
overrides: Partial<NonIntegratedSkuItem> = {},
): 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()),
);
});
});

View File

@ -6,6 +6,7 @@ import type {
NonIntegratedSkuHolePoint,
NonIntegratedSkuItem,
} from "../../nonIntegratedStorage";
import { buildAutoBarcode } from "../basic-info/skuAutoHelpers";
export type PreviewNodeOffsetMap = Record<string, [number, number, number]>;
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,
};
}),
});
}

View File

@ -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 }),

View File

@ -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: "创建批次" },
];