merge: fix/size-chart-local-size-code-dev into develop (local only, not pushed)
This commit is contained in:
@@ -33,6 +33,43 @@ describe('SDS product detail mapper', () => {
|
|||||||
expect(chart.rows[0].measurements[0]).toEqual({ key: 'bodyLength', cm: '71', in: '27.95' });
|
expect(chart.rows[0].measurements[0]).toEqual({ key: 'bodyLength', cm: '71', in: '27.95' });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('drops the local size-code column (P/M/G/GG) named 尺码 when all values are non-numeric', () => {
|
||||||
|
// 巴西/西语市场的 SDS 上游在表头第二列再放一个「尺码」列,值是本地尺码码
|
||||||
|
// P/M/G/GG(=S/M/L/XL),与行首尺码重复且非测量值,应整列丢弃
|
||||||
|
const raw = JSON.stringify([
|
||||||
|
['尺码', '尺码(cm/in)', '肩宽(cm/in)', '胸围(cm/in)'].map((content) => ({ content, remark: '' })),
|
||||||
|
['S', 'P', '52', '106'].map((content) => ({ content, remark: '' })),
|
||||||
|
['M', 'M', '55', '112'].map((content) => ({ content, remark: '' })),
|
||||||
|
['L', 'G', '58', '118'].map((content) => ({ content, remark: '' })),
|
||||||
|
['XL', 'GG', '61', '124'].map((content) => ({ content, remark: '' })),
|
||||||
|
]);
|
||||||
|
const chart = parseSizeChart(raw) as any;
|
||||||
|
expect(chart.columns.map((c: any) => c.name)).toEqual(['肩宽', '胸围']);
|
||||||
|
expect(chart.rows[0].measurements.map((m: any) => m.key)).toEqual(['shoulder', 'chest']);
|
||||||
|
expect(chart.rows[0].measurements[0]).toEqual({ key: 'shoulder', cm: '52', in: '20.47' });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('keeps a 尺码-named column when its values are numeric', () => {
|
||||||
|
const raw = JSON.stringify([
|
||||||
|
['尺码', '尺码(cm/in)', '胸围(cm/in)'].map((content) => ({ content, remark: '' })),
|
||||||
|
['S', '1', '106'].map((content) => ({ content, remark: '' })),
|
||||||
|
['M', '2', '112'].map((content) => ({ content, remark: '' })),
|
||||||
|
]);
|
||||||
|
const chart = parseSizeChart(raw) as any;
|
||||||
|
expect(chart.columns).toHaveLength(2);
|
||||||
|
expect(chart.rows[0].measurements[0].cm).toBe('1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('keeps non-numeric reference columns like 身高/体重', () => {
|
||||||
|
const raw = JSON.stringify([
|
||||||
|
['尺码', '身高(cm/in)', '体重(cm/in)'].map((content) => ({ content, remark: '' })),
|
||||||
|
['S', '50-60', '3-4kg'].map((content) => ({ content, remark: '' })),
|
||||||
|
['M', '60-70', '4-5kg'].map((content) => ({ content, remark: '' })),
|
||||||
|
]);
|
||||||
|
const chart = parseSizeChart(raw) as any;
|
||||||
|
expect(chart.columns.map((c: any) => c.name)).toEqual(['身高', '体重']);
|
||||||
|
});
|
||||||
|
|
||||||
it('parses packaging dimensions and weights', () => {
|
it('parses packaging dimensions and weights', () => {
|
||||||
const specs = parsePackageSpecs(packageTable) as any;
|
const specs = parsePackageSpecs(packageTable) as any;
|
||||||
expect(specs.rows).toHaveLength(2);
|
expect(specs.rows).toHaveLength(2);
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ export function parseSizeChart(raw: unknown): Prisma.InputJsonValue | null {
|
|||||||
const table = parseTable(raw);
|
const table = parseTable(raw);
|
||||||
if (!table) return null;
|
if (!table) return null;
|
||||||
const [header, ...body] = table;
|
const [header, ...body] = table;
|
||||||
const columns = header.slice(1).map((item, index) => {
|
let columns = header.slice(1).map((item, index) => {
|
||||||
const name = text(item.content)?.replace(/\s*\(cm\/in\)\s*/i, '') ?? `规格${index + 1}`;
|
const name = text(item.content)?.replace(/\s*\(cm\/in\)\s*/i, '') ?? `规格${index + 1}`;
|
||||||
return { key: measurementKey(name, index + 1), name };
|
return { key: measurementKey(name, index + 1), name };
|
||||||
});
|
});
|
||||||
@@ -117,6 +117,25 @@ export function parseSizeChart(raw: unknown): Prisma.InputJsonValue | null {
|
|||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter((row): row is NonNullable<typeof row> => row !== null);
|
.filter((row): row is NonNullable<typeof row> => row !== null);
|
||||||
|
// 巴西/西语市场上游会在表里再放一个「尺码」列,值是本地尺码码(P/M/G/GG = S/M/L/XL),
|
||||||
|
// 与行首尺码重复且不是测量值 → 整列丢弃。其他非数字列(身高/体重等参考信息)保留。
|
||||||
|
const sizeCodeColumns = new Set(
|
||||||
|
columns
|
||||||
|
.filter((column) => /^尺码$/.test(column.name))
|
||||||
|
.filter((column) =>
|
||||||
|
rows.every((row) => {
|
||||||
|
const cm = row.measurements.find((m) => m.key === column.key)?.cm;
|
||||||
|
return cm === null || cm === undefined || !Number.isFinite(Number(cm));
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.map((column) => column.key),
|
||||||
|
);
|
||||||
|
if (sizeCodeColumns.size > 0) {
|
||||||
|
columns = columns.filter((column) => !sizeCodeColumns.has(column.key));
|
||||||
|
for (const row of rows) {
|
||||||
|
row.measurements = row.measurements.filter((m) => !sizeCodeColumns.has(m.key));
|
||||||
|
}
|
||||||
|
}
|
||||||
return { columns, rows } as Prisma.InputJsonValue;
|
return { columns, rows } as Prisma.InputJsonValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user