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' });
|
||||
});
|
||||
|
||||
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', () => {
|
||||
const specs = parsePackageSpecs(packageTable) as any;
|
||||
expect(specs.rows).toHaveLength(2);
|
||||
|
||||
@@ -94,7 +94,7 @@ export function parseSizeChart(raw: unknown): Prisma.InputJsonValue | null {
|
||||
const table = parseTable(raw);
|
||||
if (!table) return null;
|
||||
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}`;
|
||||
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);
|
||||
// 巴西/西语市场上游会在表里再放一个「尺码」列,值是本地尺码码(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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user