|
|
@@ -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的经验教训补充*
|