feat(intake): add sku batch workflow

This commit is contained in:
WuYongJie 2026-05-08 18:28:04 +08:00
parent 2f02681a69
commit 0e9db44bc4
3 changed files with 1082 additions and 276 deletions

View File

@ -270,6 +270,7 @@ const NON_INTEGRATED_UPLOAD_CATEGORY_MAP: Record<string, string> = {
export type NonIntegratedSkuItem = {
id: string;
skuSequence: number;
batchNo: number;
packageGroupId: string;
packageSuffix: string;
image: string;
@ -282,6 +283,7 @@ export type NonIntegratedSkuItem = {
size: string;
color: string;
material: string;
versionNo: string;
attributeCode: string;
drawingId: string;
installMethod: string;
@ -520,6 +522,8 @@ export type NonIntegratedProductRecord = {
reviewSheets?: NonIntegratedReviewRound[];
qualityInspectionSheet: NonIntegratedQualityInspectionSheet;
skuItems: NonIntegratedSkuItem[];
skuBatchCount?: number;
skuBatchFlowNos?: Record<string, string>;
factoryRows: NonIntegratedFactoryRow[];
pricingRows: NonIntegratedPricingRow[];
sampleMeasurementRows: NonIntegratedSampleMeasurementRow[];
@ -947,6 +951,18 @@ function normalizeDocumentWorkspaceApprovedAt(value: unknown) {
) as NonIntegratedDocumentWorkspaceApprovalMap;
}
function normalizeSkuBatchFlowNos(value: unknown): Record<string, string> {
if (!value || typeof value !== "object" || Array.isArray(value)) {
return {};
}
return Object.fromEntries(
Object.entries(value as Record<string, unknown>)
.map(([key, flowNo]) => [key, normalizeString(flowNo)])
.filter(([, flowNo]) => flowNo.length > 0),
);
}
function normalizeSkuItem(
item: Partial<NonIntegratedSkuItem>,
): NonIntegratedSkuItem | null {
@ -958,6 +974,10 @@ function normalizeSkuItem(
typeof item.skuSequence === "number" && Number.isFinite(item.skuSequence)
? item.skuSequence
: 0,
batchNo:
typeof item.batchNo === "number" && Number.isFinite(item.batchNo)
? Math.max(1, Math.floor(item.batchNo))
: 1,
packageGroupId: normalizeString(item.packageGroupId),
packageSuffix: normalizeString(item.packageSuffix),
image: normalizeNonIntegratedAssetUrl(normalizeString(item.image)),
@ -975,6 +995,10 @@ function normalizeSkuItem(
size: normalizeString(item.size),
color: normalizeString(item.color),
material: normalizeString(item.material),
versionNo:
typeof item.versionNo === "string"
? normalizeString(item.versionNo)
: "V01",
attributeCode: normalizeString(item.attributeCode),
drawingId: normalizeString(item.drawingId),
installMethod: normalizeString(item.installMethod),
@ -1468,6 +1492,21 @@ function toProductRecord(
return null;
}
const normalizedSkuItems = Array.isArray(item.skuItems)
? item.skuItems
.map((entry) => normalizeSkuItem(entry))
.filter((entry): entry is NonIntegratedSkuItem => entry !== null)
: [];
const normalizedSkuBatchCount =
typeof item.skuBatchCount === "number" &&
Number.isFinite(item.skuBatchCount)
? Math.max(1, Math.floor(item.skuBatchCount))
: undefined;
const hasSkuBatchCount = normalizedSkuBatchCount !== undefined;
const skuItems = hasSkuBatchCount
? normalizedSkuItems
: normalizedSkuItems.map((entry) => ({ ...entry, batchNo: 1 }));
return {
id: item.id,
spu: item.spu,
@ -1552,11 +1591,9 @@ function toProductRecord(
qualityInspectionSheet: normalizeQualityInspectionSheet(
item.qualityInspectionSheet,
),
skuItems: Array.isArray(item.skuItems)
? item.skuItems
.map((entry) => normalizeSkuItem(entry))
.filter((entry): entry is NonIntegratedSkuItem => entry !== null)
: [],
skuItems,
skuBatchCount: normalizedSkuBatchCount,
skuBatchFlowNos: normalizeSkuBatchFlowNos(item.skuBatchFlowNos),
factoryRows: Array.isArray(item.factoryRows)
? item.factoryRows
.map((entry) => normalizeFactoryRow(entry))

View File

@ -10,12 +10,15 @@ export type NonIntegratedSkuExportRow = {
size: string
color: string
material: string
versionNo: string
attributeCode: string
drawingId: string
installMethod: string
executeStandard: string
manufacturer: string
manufacturerCode: string
batchNo: string
dingTalkFlowNo: string
}
const EXCEL_MIME_TYPE =
@ -31,12 +34,15 @@ const TEMPLATE_COLUMNS: { key: keyof NonIntegratedSkuExportRow; label: string; w
{ key: 'size', label: '尺寸', width: 16 },
{ key: 'color', label: '颜色', width: 14 },
{ key: 'material', label: '材质', width: 18 },
{ key: 'versionNo', label: '版本号', width: 10 },
{ key: 'attributeCode', label: '属性代码', width: 12 },
{ key: 'drawingId', label: '图纸ID', width: 22 },
{ key: 'installMethod', label: '安装方式', width: 14 },
{ key: 'executeStandard', label: '执行标准', width: 18 },
{ key: 'manufacturer', label: '供应商名称', width: 18 },
{ key: 'manufacturerCode', label: '供应商代码', width: 14 },
{ key: 'batchNo', label: '创建批次', width: 12 },
{ key: 'dingTalkFlowNo', label: '钉钉流程号', width: 18 },
]
function escapeXml(value: string) {