feat(public): family-first contract — goodId=familyId, strict 5-dim price matrix
公开契约族化(前端只需知道款号/族): - GET /public/goods 一族一条(goodId=族ID,price=族起价,分页作用于分组后); 无族商品(自定义)不进任何公开端点(列表/首页/分类树/标签统计) - GET /public/goods/:goodId 仅认族 ID;公共字段取代表 Good,变体=全体成员并集, 尺码表/包装规格=族物化并集;旧 SDS 链接 ID 寻址 404 - priceMatrix 严格五维:尺码×颜色×印花数量×工艺×物流;维度来源改为链接级 标签(人工接管按人工标签),弃用原始 craftLabel;CUSTOM 成员尊重显式标签 - 名称派生补裸「单面/双面」写法(直喷双面→双面印花+直喷,18 条存量链接修复) - family_price_overrides 加 print_count 列(五键唯一),PUT/DELETE/校验五键化 - admin 编辑弹窗矩阵消费适配(SKU 列直读 printCount,成员格子三维匹配, 改价 payload 带 printCount) - 存量 339 族已全量重算;api 162/162、admin 22/22、双端构建绿
This commit is contained in:
@@ -239,12 +239,12 @@ describe('ProductFamiliesService', () => {
|
||||
|
||||
await expect(
|
||||
service.putPriceOverrides(fid, [
|
||||
{ sizeId: 'size_S', colorId: 'color_blk', craft: '不存在的工艺', logistics: '包邮', price: 1 },
|
||||
{ sizeId: 'size_S', colorId: 'color_blk', printCount: '单面印花', craft: '不存在的工艺', logistics: '包邮', price: 1 },
|
||||
]),
|
||||
).rejects.toThrow(BadRequestException);
|
||||
|
||||
const result = (await service.putPriceOverrides(fid, [
|
||||
{ sizeId: 'size_S', colorId: 'color_blk', craft: '单面印花', logistics: '包邮', price: 23, note: '促销' },
|
||||
{ sizeId: 'size_S', colorId: 'color_blk', printCount: '单面印花', craft: '烫画', logistics: '包邮', price: 23, note: '促销' },
|
||||
])) as any;
|
||||
expect(result.items).toHaveLength(1);
|
||||
expect(result.items[0].derivedPrice).toBe('25');
|
||||
@@ -256,7 +256,7 @@ describe('ProductFamiliesService', () => {
|
||||
expect(row.manual).toBe(true);
|
||||
|
||||
const restored = (await service.deletePriceOverrides(fid, {
|
||||
cells: [{ sizeId: 'size_S', colorId: 'color_blk', craft: '单面印花', logistics: '包邮' }],
|
||||
cells: [{ sizeId: 'size_S', colorId: 'color_blk', printCount: '单面印花', craft: '烫画', logistics: '包邮' }],
|
||||
})) as any;
|
||||
expect(restored.items).toHaveLength(0);
|
||||
const after2 = await prisma.productFamily.findUniqueOrThrow({ where: { id: fid } });
|
||||
|
||||
Reference in New Issue
Block a user