Ver Fonte

docs(story): 补充订单管理模块故事的经验教训

基于故事007.004和007.007的经验教训,补充到故事007.005中:
1. 详细分类经验教训(数据库类型、测试、路由API、模块集成、开发流程)
2. 添加关键经验教训总结(16条具体经验)
3. 提供实施建议和代码示例
4. 更新故事文档说明

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
yourname há 1 mês atrás
pai
commit
acedc8dc9d

+ 136 - 9
docs/stories/007.005.transplant-order-management-module.story.md

@@ -194,14 +194,57 @@ Ready for Development
 ## Dev Notes
 
 ### 从之前故事吸取的经验教训:
-1. **实体主键命名**:确保所有实体使用`id`作为主键字段名,而不是`orderId`、`opId`等特定名称
-2. **workspace配置**:在根目录`pnpm-workspace.yaml`中添加新包路径`'allin-packages/order-module'`
-3. **测试依赖**:集成测试需要配置测试数据库,参考salary-module的`tests/integration/setup.ts`
-4. **类型检查问题**:使用`pnpm typecheck`检查类型错误,特别注意枚举导入和循环依赖
-5. **API兼容性**:保持与原始NestJS API相同的请求/响应格式
-6. **文件实体集成**:正确配置与`@d8d/file-module`的关联关系,参考disabled-photo.entity.ts
-7. **枚举使用**:通过`@d8d/allin-enums`包导入OrderStatus和WorkStatus枚举
-8. **区域包集成经验**:参考salary-module与geo-areas的集成方式处理外部依赖
+
+#### 从故事007.004(残疾人管理模块)吸取的经验教训:
+1. **PostgreSQL类型兼容问题**:需要处理tinyint → smallint,datetime → timestamp的类型转换
+2. **Schema验证错误**:实体字段与schema定义不匹配(createTime/updateTime → uploadTime/remarkTime/visitTime)
+3. **测试数据问题**:缺少subBankName、operatorId等必填字段
+4. **错误处理**:DELETE端点返回404而不是200,GET聚合端点返回404而不是500
+5. **文件模块集成**:银行卡实体使用fileId字段而不是cardPhotoUrl
+6. **实体主键命名**:确保所有实体使用`id`作为主键字段名,而不是`orderId`、`opId`等特定名称
+7. **文件实体集成**:正确配置与`@d8d/file-module`的关联关系,参考disabled-photo.entity.ts
+
+#### 从故事007.007(薪资管理模块)吸取的经验教训:
+1. **唯一性约束冲突**:测试数据创建了相同(provinceId, cityId)组合的记录,需要修改测试数据
+2. **Schema验证问题**:allowance、insurance、housingFund字段"expected number, received string",需要改为z.coerce.number()
+3. **路由冲突**:CRUD路由可能与自定义路由冲突,需要暂时注释掉CRUD路由聚合
+4. **调试信息**:在路由中添加console.debug便于问题排查
+5. **decimal字段处理**:需要正确处理字符串格式的decimal字段
+6. **测试期望值**:按区域过滤测试期望值需要调整
+7. **workspace配置**:在根目录`pnpm-workspace.yaml`中添加新包路径`'allin-packages/order-module'`
+8. **测试依赖**:集成测试需要配置测试数据库,参考salary-module的`tests/integration/setup.ts`
+9. **类型检查问题**:使用`pnpm typecheck`检查类型错误,特别注意枚举导入和循环依赖
+10. **API兼容性**:保持与原始NestJS API相同的请求/响应格式
+11. **枚举使用**:通过`@d8d/allin-enums`包导入OrderStatus和WorkStatus枚举
+12. **区域包集成经验**:参考salary-module与geo-areas的集成方式处理外部依赖
+
+### 关键经验教训总结(基于007.004和007.007):
+
+#### 数据库和类型相关:
+1. **PostgreSQL类型兼容**:注意tinyint → smallint,datetime → timestamp的类型转换
+2. **Decimal字段处理**:数据库返回的decimal字段可能是字符串格式,需要使用z.coerce.number()处理
+3. **Schema一致性**:确保实体字段名与Schema定义完全匹配,特别注意时间字段命名
+
+#### 测试相关:
+4. **测试数据完整性**:确保测试数据包含所有必填字段(如subBankName、operatorId等)
+5. **唯一性约束**:测试数据避免创建违反唯一性约束的记录
+6. **测试期望值**:根据实际数据调整测试断言期望值
+7. **调试信息**:在路由中添加console.debug便于问题排查
+
+#### 路由和API相关:
+8. **路由冲突**:CRUD路由可能与自定义路由冲突,需要合理设计路由结构
+9. **错误响应**:确保DELETE返回200(成功)而不是404,GET聚合端点正确处理404场景
+10. **API兼容性**:保持与原始NestJS API相同的请求/响应格式
+
+#### 模块集成相关:
+11. **文件模块集成**:正确使用fileId字段而不是URL字段,建立与File实体的关联
+12. **循环依赖处理**:使用ID引用代替直接实体引用,避免模块间循环依赖
+13. **枚举集成**:通过@d8d/allin-enums包导入共享枚举
+
+#### 开发流程相关:
+14. **workspace配置**:及时在pnpm-workspace.yaml中添加新包路径
+15. **类型检查**:使用pnpm typecheck检查类型错误,特别注意枚举导入
+16. **测试依赖**:集成测试需要正确配置测试数据库和实体
 
 ### 技术细节:
 1. **OrderStatus和WorkStatus枚举集成**:
@@ -321,6 +364,89 @@ Ready for Development
 - [ ] 代码符合项目代码规范
 - [ ] 文档完整(README、API文档)
 
+## 实施建议(基于007.004和007.007经验)
+
+### 1. 数据库类型处理
+```typescript
+// 处理PostgreSQL类型兼容
+@Column({
+  name: 'order_status',
+  type: 'enum',
+  enum: OrderStatus,
+  default: OrderStatus.DRAFT
+})
+orderStatus!: OrderStatus;
+
+// 处理decimal字段
+@Column({
+  name: 'total_amount',
+  type: 'decimal',
+  precision: 10,
+  scale: 2
+})
+totalAmount!: number; // Schema中使用z.coerce.number()
+```
+
+### 2. Schema验证设计
+```typescript
+// 使用z.coerce.number()处理数据库返回的字符串
+const CreateOrderSchema = z.object({
+  totalAmount: z.coerce.number().min(0),
+  // 确保字段名与实体完全一致
+  createTime: z.string().datetime().optional(),
+  updateTime: z.string().datetime().optional(),
+});
+```
+
+### 3. 测试数据准备
+```typescript
+// 确保测试数据包含所有必填字段
+const testOrderData = {
+  orderName: '测试订单',
+  platformId: 1,
+  orderStatus: OrderStatus.DRAFT,
+  workStatus: WorkStatus.NOT_WORKING,
+  totalAmount: 1000.00,
+  // 不要遗漏任何必填字段
+};
+```
+
+### 4. 路由设计避免冲突
+```typescript
+// 合理设计路由结构,避免CRUD路由与自定义路由冲突
+const orderRoutes = new Hono()
+  .basePath('/orders')
+  .route('/', customRoutes)  // 自定义路由
+  .route('/', crudRoutes);   // CRUD路由(设置为readOnly: true)
+```
+
+### 5. 错误处理规范
+```typescript
+// DELETE成功返回200,GET聚合端点正确处理404
+app.delete('/:id', async (c) => {
+  const result = await service.delete(id);
+  return c.json({ success: true }, 200); // 不是404
+});
+
+app.get('/aggregated/:id', async (c) => {
+  const data = await service.findAggregated(id);
+  if (!data) {
+    return c.json({ error: 'Not found' }, 404); // 正确处理404
+  }
+  return c.json(data);
+});
+```
+
+### 6. 调试信息添加
+```typescript
+// 在关键路由中添加console.debug便于问题排查
+app.post('/create', async (c) => {
+  const body = await c.req.json();
+  console.debug('创建订单请求:', body);
+  // ...处理逻辑
+});
+```
+
 ## Dev Agent Record
 *将在开发完成后填写*
 
@@ -328,4 +454,5 @@ Ready for Development
 
 *故事创建时间:2025-12-02*
 *创建者:Bob (Scrum Master)*
-*更新说明:重新创建故事,吸取之前移植故事的经验教训,在任务中标注迁移文件的路径和参考对照文件的路径*
+*更新说明:重新创建故事,吸取之前移植故事的经验教训,在任务中标注迁移文件的路径和参考对照文件的路径*
+*经验教训更新:2025-12-02,基于故事007.004和007.007的经验教训补充*