|
|
@@ -0,0 +1,155 @@
|
|
|
+# Story 006.009: 父子商品名称关联查询优化
|
|
|
+
|
|
|
+## Status
|
|
|
+Draft
|
|
|
+
|
|
|
+## Story
|
|
|
+**As a** user viewing shopping cart or orders,
|
|
|
+**I want** to see consistent and accurate parent goods names through entity relations rather than redundant spuName field,
|
|
|
+**so that** data consistency is maintained when parent goods names are updated and I always see the correct product information.
|
|
|
+
|
|
|
+## Acceptance Criteria
|
|
|
+1. 商品详情API返回的`parent`对象包含完整的父商品基本信息(id、name等)
|
|
|
+2. 前端组件能正确通过`goods.parent?.name`获取父商品名称
|
|
|
+3. 保持向后兼容:现有依赖`spuName`的代码继续正常工作
|
|
|
+4. 父子商品名称显示正确,无数据不一致问题
|
|
|
+5. 所有测试通过,无回归问题
|
|
|
+
|
|
|
+## Tasks / Subtasks
|
|
|
+- [ ] Task 1: 完善商品详情API,确保`parent`对象包含完整父商品信息 (AC: 1, 4)
|
|
|
+ - [ ] 修改`GoodsServiceMt.getById`方法,确保关联查询包含父商品的基本字段(至少id、name)
|
|
|
+ - [ ] 验证API返回的`parent`对象结构符合预期
|
|
|
+ - [ ] 添加单元测试验证关联查询功能
|
|
|
+- [ ] Task 2: 更新商品Schema,将`parent`字段类型从`z.any()`改为具体的父商品Schema (AC: 1, 2)
|
|
|
+ - [ ] 创建精简版父商品Schema(`ParentGoodsSchema`)包含id、name等必要字段
|
|
|
+ - [ ] 更新所有商品Schema(public/admin/user)中的`parent`字段类型
|
|
|
+ - [ ] 确保Schema更新不影响现有数据验证
|
|
|
+- [ ] Task 3: 前端适配,优先使用`goods.parent?.name`获取父商品名称 (AC: 2, 3)
|
|
|
+ - [ ] 创建商品名称格式化工具函数`formatGoodsName`,优先使用`parent.name`,后备使用`spuName`
|
|
|
+ - [ ] 更新`GoodsParentChildPanel`组件使用新的名称获取方式
|
|
|
+ - [ ] 更新`GoodsManagement`组件使用新的名称获取方式
|
|
|
+ - [ ] 验证向后兼容性:现有依赖`spuName`的代码继续工作
|
|
|
+- [ ] Task 4: 逐步迁移,减少对`spuName`字段的直接依赖 (AC: 3, 4)
|
|
|
+ - [ ] 识别并记录所有直接使用`spuName`字段的组件和函数
|
|
|
+ - [ ] 制定迁移计划,逐步更新关键组件
|
|
|
+ - [ ] 确保API继续返回`spuName`字段以保持向后兼容
|
|
|
+- [ ] Task 5: 测试验证和回归测试 (AC: 5)
|
|
|
+ - [ ] 添加关联查询的单元测试和集成测试
|
|
|
+ - [ ] 验证数据一致性:父商品名称更新后,子商品关联查询显示新名称
|
|
|
+ - [ ] 运行现有测试套件,确保无回归问题
|
|
|
+ - [ ] 添加前端组件测试,验证名称显示逻辑
|
|
|
+
|
|
|
+## Dev Notes
|
|
|
+
|
|
|
+### 先前故事洞察
|
|
|
+- 故事8(购物车页面规格切换功能)已完成,实现了购物车中规格切换功能
|
|
|
+- 购物车上下文(CartContext)已支持父子商品,包含parentGoodsId字段
|
|
|
+- 商品详情API已支持父子商品关系,但`parent`对象可能不完整
|
|
|
+- 多租户兼容性已在前序故事中确保,父子商品在同一租户下
|
|
|
+
|
|
|
+### 数据模型
|
|
|
+- **商品实体**:包含`spuId`(父商品ID)、`spuName`(父商品名称冗余字段)、`parent`(关联父商品对象)字段
|
|
|
+- **父子关系**:`spuId=0`表示父商品或单规格商品,`spuId>0`表示子商品
|
|
|
+- **关联关系**:子商品通过`spuId`关联到父商品,TypeORM配置了`@ManyToOne`关系
|
|
|
+- **Schema定义**:商品Schema位于`packages/goods-module-mt/src/schemas/`目录下
|
|
|
+- **冗余字段策略**:当前使用`spuName`冗余存储父商品名称以优化查询性能,但存在数据一致性问题
|
|
|
+
|
|
|
+[Source: 史诗006文档第303-336行]
|
|
|
+
|
|
|
+### API规范
|
|
|
+- **商品详情API**:`GET /api/v1/goods/:id`,应返回完整的父子商品信息
|
|
|
+- **返回结构**:父商品应包含`children`列表,子商品应包含`parent`对象
|
|
|
+- **关联查询**:通过TypeORM的`relations`配置加载关联实体
|
|
|
+- **多租户过滤**:所有查询必须包含`tenantId`过滤,确保数据隔离
|
|
|
+- **向后兼容**:API继续返回`spuName`字段,前端逐步减少使用
|
|
|
+
|
|
|
+[Source: 史诗006文档第80-94行]
|
|
|
+
|
|
|
+### 组件规范
|
|
|
+- **商品管理UI组件**:位于`packages/goods-management-ui-mt/src/components/`
|
|
|
+ - `GoodsParentChildPanel.tsx`:父子商品管理面板
|
|
|
+ - `GoodsManagement.tsx`:商品管理主组件
|
|
|
+- **小程序工具函数**:计划创建`mini/src/utils/formatGoodsName.ts`统一处理商品名称格式化
|
|
|
+- **前端适配策略**:优先使用`goods.parent?.name`,后备使用`goods.spuName`
|
|
|
+
|
|
|
+[Source: 史诗006文档第329-336行]
|
|
|
+
|
|
|
+### 文件位置
|
|
|
+- **后端商品模块**:`packages/goods-module-mt/src/`
|
|
|
+ - Schemas: `packages/goods-module-mt/src/schemas/*.schema.mt.ts`
|
|
|
+ - Services: `packages/goods-module-mt/src/services/goods.service.mt.ts`
|
|
|
+- **前端管理界面**:`packages/goods-management-ui-mt/src/components/`
|
|
|
+ - `GoodsParentChildPanel.tsx`
|
|
|
+ - `GoodsManagement.tsx`
|
|
|
+- **小程序工具**:`mini/src/utils/formatGoodsName.ts`(待创建)
|
|
|
+- **测试文件**:与源码并列的`tests/`目录,遵循项目测试结构标准
|
|
|
+
|
|
|
+[Source: 架构文档source-tree.md第253-284行,第369-383行]
|
|
|
+
|
|
|
+### 测试要求
|
|
|
+- **测试框架**:使用Vitest进行单元测试,hono/testing进行API测试
|
|
|
+- **测试位置**:`tests`文件夹与源码并列(例如`packages/goods-module-mt/tests/`)
|
|
|
+- **测试类型**:单元测试、集成测试
|
|
|
+- **覆盖率目标**:核心业务逻辑 > 80%
|
|
|
+- **测试策略**:
|
|
|
+ - 验证关联查询正确加载父商品信息
|
|
|
+ - 验证Schema类型定义正确性
|
|
|
+ - 验证前端组件名称显示逻辑
|
|
|
+ - 验证向后兼容性
|
|
|
+- **RPC客户端Mock**:在测试中正确mock客户端管理器的get()方法调用链
|
|
|
+
|
|
|
+[Source: 架构文档coding-standards.md第16-34行]
|
|
|
+
|
|
|
+### 技术约束
|
|
|
+- **多租户支持**:所有操作必须包含tenantId过滤,父子商品在同一租户下
|
|
|
+- **性能考虑**:关联查询需确保性能,避免N+1查询问题
|
|
|
+- **向后兼容**:现有API契约不能破坏,`spuName`字段继续返回
|
|
|
+- **TypeORM关系配置**:确保`parent`关联关系正确配置,支持懒加载或急加载
|
|
|
+- **Zod Schema验证**:更新Schema类型定义,保持严格的运行时验证
|
|
|
+
|
|
|
+### 项目结构注意事项
|
|
|
+- 文件路径与项目结构指南一致,无需调整
|
|
|
+- 商品模块采用多租户包架构(`-mt`后缀),位于`packages/goods-module-mt/`
|
|
|
+- 管理界面采用多租户管理界面包,位于`packages/goods-management-ui-mt/`
|
|
|
+- 小程序项目位于`mini/`目录,工具函数应放在`mini/src/utils/`
|
|
|
+
|
|
|
+## Testing
|
|
|
+
|
|
|
+### 测试标准
|
|
|
+- **测试文件位置**:与源码并列的`tests/`目录(例如`packages/goods-module-mt/tests/unit/services/goods.service.mt.test.ts`)
|
|
|
+- **测试框架**:Vitest用于单元测试,hono/testing用于API端点测试
|
|
|
+- **测试模式**:遵循现有测试模式,使用测试数据工厂创建测试数据
|
|
|
+- **覆盖率要求**:核心业务逻辑(服务层、Schema验证)> 80%
|
|
|
+- **集成测试**:验证API端点返回正确的父子商品关系数据
|
|
|
+- **前端组件测试**:使用Testing Library验证组件渲染和交互逻辑
|
|
|
+
|
|
|
+### 故事特定测试要求
|
|
|
+1. **关联查询测试**:验证`GoodsServiceMt.getById`方法正确返回包含完整父商品信息的`parent`对象
|
|
|
+2. **Schema验证测试**:验证更新后的商品Schema正确处理`parent`字段类型
|
|
|
+3. **向后兼容测试**:验证现有依赖`spuName`的代码继续正常工作
|
|
|
+4. **数据一致性测试**:模拟父商品名称更新,验证子商品关联查询显示新名称
|
|
|
+5. **前端组件测试**:验证`GoodsParentChildPanel`和`GoodsManagement`组件正确使用`parent.name`显示父商品名称
|
|
|
+6. **工具函数测试**:验证`formatGoodsName`工具函数正确优先使用`parent.name`,后备使用`spuName`
|
|
|
+
|
|
|
+## Change Log
|
|
|
+| Date | Version | Description | Author |
|
|
|
+|------|---------|-------------|--------|
|
|
|
+| 2025-12-14 | 1.0 | 初始故事草稿创建 | Bob (Scrum Master) |
|
|
|
+
|
|
|
+## Dev Agent Record
|
|
|
+*This section is populated by the development agent during implementation*
|
|
|
+
|
|
|
+### Agent Model Used
|
|
|
+*To be populated by dev agent*
|
|
|
+
|
|
|
+### Debug Log References
|
|
|
+*To be populated by dev agent*
|
|
|
+
|
|
|
+### Completion Notes List
|
|
|
+*To be populated by dev agent*
|
|
|
+
|
|
|
+### File List
|
|
|
+*To be populated by dev agent*
|
|
|
+
|
|
|
+## QA Results
|
|
|
+*Results from QA Agent QA review of the completed story implementation*
|