Files
inkreach-official-website/plans/fix/price-matrix-option-sort-fix.md
T

58 lines
3.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Fix:价格矩阵选项组按词表序输出(印花/工艺/物流按钮顺序稳定)
日期:2026-09-02
类型:Bug 修复(fix
影响面:`apps/api/src/product-families/family-recompute.service.ts` 及其测试、一次性全库重算
## 背景与问题
详情接口 `family.priceMatrix``printCounts / crafts / logistics` 是物化进 JSONB 的字符串数组,H5 按数组原序渲染印花/工艺/物流按钮组(无前端排序)。数组顺序 = 重算时 Set 去重的"首次遇到序",且成员查询 `originGoods``orderBy`,导致:
1. 每个族的按钮顺序不一致(实测 goodId=1 为 `['双面印花','单面印花']``['不包邮','包邮']`,与词表相反);
2. 同一族两次重算顺序理论上可能漂移(Postgres 无顺序保证)。
对比:尺码/颜色按钮组有 `variants.sortOrder`,顺序稳定;本修复把印花/工艺/物流对齐到同样可预期。
## 目标顺序(业务确认)
| 维度 | 展示顺序 |
| --- | --- |
| printCount | 单面印花 → 双面印花 |
| craft | 烫画 → 直喷 → 不打印 |
| logistics | 不包邮 → 包邮 |
无论族内实际出现哪个子集,相对顺序恒定;词表外自由文本(如 CUSTOM 的"海运")沉到最后,相互间保持首次遇到序。
## 数据边界(2026-09-02 全库实测)
- crafts 中出现 `双面印花`×2、logistics 中出现 `海运`×2:来自 3 条 CUSTOM 链接 craftLabel/logisticsLabel 自由文本(含维度填错,属数据清理问题,本修复只保证其沉底,不改数据)。
## 方案
1. `derivePriceMatrix`:聚合(Set 去重)+ 人工覆盖 append 之后,对三个数组做稳定排序:
- 新增 `OPTION_DISPLAY_ORDER` 常量(printCount/craft/logistics 三组词表序,logistics 与 `DIM_VALUES` 顺序相反是业务要求;`DIM_VALUES` 组合生成语义不动);
- 排序键 = 词表下标,未知值 = `canon.length`(沉底),稳定排序保持未知值间首次遇到序。
2. `recomputeFamily` 成员查询加 `orderBy: { id: 'asc' }`,使"遇到序"确定(未知值之间顺序也确定)。
3. 只影响 `autoManaged` 族物化;非自动族人工字段照旧不碰(现有不变量)。
4. 一次性脚本:逐族调用 `recomputeFamily` 全库刷新存量(166 个族)。
## 非目标
- 不改 API 输出结构(仍是 `string[]`),前端零改动;
- 不清理 CUSTOM 维度填错数据(另行处理)。
## 测试计划(TDD
测试文件:`apps/api/src/product-families/family-recompute.service.spec.ts``derivePriceMatrix` 为纯函数,可直接单测)。
1. **打乱输入仍输出词表序**:成员顺序颠倒,crafts 输出仍 `烫画→直喷→不打印`(修复前为遇到序,RED)。
2. **子集保序**:只含 `直喷+烫画` → 输出 `烫画,直喷`;只含 `双面` → 单元素。
3. **未知值沉底**logistics 含 `海运``不包邮,包邮,海运`;未知值相互保持遇到序。
4. **覆盖 append 值参与同一排序**:override 新增取值后数组仍词表序。
5. **重算幂等(含顺序)**:同输入跑两遍输出 deep-equal。
6. 既有用例全绿;全量 jest + tsc 通过。
## 风险与回滚
- 纯物化顺序变化,无 schema/契约变更;回滚 = revert commit + 再跑一次全库重算(旧逻辑会把顺序"洗回"遇到序,仅顺序变化无数据损坏)。