|
|
@@ -0,0 +1,245 @@
|
|
|
+# 故事 012.004:订单统计与数据统计API
|
|
|
+
|
|
|
+## 状态
|
|
|
+Draft
|
|
|
+
|
|
|
+## 故事
|
|
|
+**作为**企业用户,
|
|
|
+**我希望**查看订单统计数据和整体数据可视化统计,
|
|
|
+**以便**更好地管理企业订单和了解人才数据分布,减少人工统计时间,提升管理决策准确性。
|
|
|
+
|
|
|
+**史诗上下文**:此故事是史诗012(用人方小程序API补充与数据库扩展)的第4个核心故事,为企业用户提供订单管理和数据可视化统计功能,支持用人方小程序的完整管理能力。
|
|
|
+
|
|
|
+## 验收标准
|
|
|
+从史诗文件复制的验收标准编号列表
|
|
|
+
|
|
|
+1. [ ] 订单打卡数据统计接口返回正确的打卡视频数量
|
|
|
+2. [ ] 订单视频统计接口按类型分类返回统计结果
|
|
|
+3. [ ] 企业维度订单查询接口支持按企业ID过滤,返回完整订单信息
|
|
|
+4. [ ] 所有数据统计接口返回正确的统计结果
|
|
|
+5. [ ] 年龄统计基于`birth_date`字段准确计算
|
|
|
+6. [ ] 统计查询性能良好,大数据量下响应时间可接受
|
|
|
+7. [ ] 所有接口通过单元测试和集成测试
|
|
|
+
|
|
|
+## 任务 / 子任务
|
|
|
+将故事分解为实施所需的具体任务和子任务。
|
|
|
+在相关处引用适用的验收标准编号。
|
|
|
+
|
|
|
+- [ ] 任务1:订单统计API实现(order-module扩展)(AC:1,2,3)
|
|
|
+ - [ ] 在`allin-packages/order-module/src/routes/order-custom.routes.ts`中添加订单统计路由:
|
|
|
+ - [ ] 打卡数据统计接口:`GET /order/checkin-statistics`(企业维度,基于`order_person_asset`表的`checkin_video`类型统计)
|
|
|
+ - [ ] 视频分类统计接口:`GET /order/video-statistics`(企业维度,支持按`asset_type`视频类型过滤)
|
|
|
+ - [ ] 企业维度订单查询接口:`GET /order/company-orders`(支持企业ID过滤、分页、排序)
|
|
|
+ - [ ] 在`allin-packages/order-module/src/services/order.service.ts`中添加统计服务方法:
|
|
|
+ - [ ] `getCheckinStatistics(companyId: number): Promise<number>` - 统计打卡视频数量
|
|
|
+ - [ ] `getVideoStatistics(companyId: number, assetType?: string): Promise<VideoStats>` - 视频分类统计
|
|
|
+ - [ ] `getCompanyOrders(companyId: number, filters: OrderFilters): Promise<OrderList>` - 企业维度订单查询
|
|
|
+ - [ ] 在`allin-packages/order-module/src/schemas/order.schema.ts`中添加对应的Zod Schema验证:
|
|
|
+ - [ ] `CheckinStatisticsResponseSchema` - 打卡统计响应schema
|
|
|
+ - [ ] `VideoStatisticsResponseSchema` - 视频统计响应schema
|
|
|
+ - [ ] `CompanyOrdersQuerySchema` - 企业订单查询参数schema
|
|
|
+ - [ ] 添加企业数据隔离逻辑:所有统计查询必须包含`company_id`条件(通过`employment_order.company_id`关联过滤)
|
|
|
+ - [ ] 更新`allin-packages/order-module/src/routes/index.ts`导出新的路由
|
|
|
+
|
|
|
+- [ ] 任务2:数据统计API实现(创建独立的statistics-module)(AC:4,5)
|
|
|
+ - [ ] 创建`allin-packages/statistics-module/`目录结构,遵循后端模块包标准:
|
|
|
+ - [ ] `package.json` - 包配置(名称:`@d8d/allin-statistics-module`,依赖:`@d8d/allin-disability-module`、`@d8d/allin-order-module`、`@d8d/shared-types`、`@d8d/shared-utils`、`@d8d/shared-crud`等)
|
|
|
+ - [ ] `tsconfig.json` - TypeScript配置(参考现有模块配置)
|
|
|
+ - [ ] `vitest.config.ts` - 测试配置(参考现有模块配置)
|
|
|
+ - [ ] `src/` - 源代码目录
|
|
|
+ - [ ] 创建`src/routes/statistics.routes.ts`路由文件,实现6个统计接口:
|
|
|
+ - [ ] 残疾类型分布:`GET /statistics/disability-type-distribution`
|
|
|
+ - [ ] 性别分布:`GET /statistics/gender-distribution`
|
|
|
+ - [ ] 年龄分布:`GET /statistics/age-distribution`(基于`birth_date`字段计算年龄分组:18-25、26-35、36-45、46+)
|
|
|
+ - [ ] 户籍分布:`GET /statistics/household-distribution`
|
|
|
+ - [ ] 在职状态分布:`GET /statistics/job-status-distribution`
|
|
|
+ - [ ] 薪资分布:`GET /statistics/salary-distribution`
|
|
|
+ - [ ] 创建`src/services/statistics.service.ts`服务文件,实现统计业务逻辑:
|
|
|
+ - [ ] 依赖注入:注入`DisabledPersonRepository`、`OrderPersonRepository`等实体仓库
|
|
|
+ - [ ] 实现6个统计查询方法,使用TypeORM QueryBuilder进行复杂统计查询
|
|
|
+ - [ ] 实现企业数据隔离:所有统计查询必须通过`company_id`关联过滤(`employment_order`→`order_person`→`disabled_person`关联链)
|
|
|
+ - [ ] 创建`src/schemas/statistics.schema.ts`Schema文件,定义Zod验证:
|
|
|
+ - [ ] 6个统计接口的请求参数和响应Schema
|
|
|
+ - [ ] 年龄分组计算逻辑Schema
|
|
|
+ - [ ] 企业ID验证Schema
|
|
|
+ - [ ] 创建`src/index.ts`包入口文件,导出路由、服务、schema
|
|
|
+ - [ ] 创建`tests/integration/statistics.integration.test.ts`集成测试文件:
|
|
|
+ - [ ] 测试6个统计接口的正确性
|
|
|
+ - [ ] 测试企业数据隔离(不同企业用户只能看到自己企业的统计)
|
|
|
+ - [ ] 测试空数据、边缘情况处理
|
|
|
+
|
|
|
+- [ ] 任务3:性能优化与数据库索引(AC:6)
|
|
|
+ - [ ] 分析统计查询性能瓶颈,添加针对性的数据库索引(如`order_person_asset.asset_type`、`disabled_person.disability_type`等统计字段索引)
|
|
|
+ - [ ] 优化复杂统计查询,使用CTE(Common Table Expressions)或窗口函数提高查询效率
|
|
|
+ - [ ] 考虑大数据量下的分页策略和查询缓存机制
|
|
|
+ - [ ] 评估并实现物化视图(如需要),用于高频统计查询的结果缓存
|
|
|
+
|
|
|
+- [ ] 任务4:测试实现(AC:7)
|
|
|
+ - [ ] **order-module扩展测试**:
|
|
|
+ - [ ] 在`allin-packages/order-module/tests/integration/order.integration.test.ts`中添加订单统计接口的集成测试
|
|
|
+ - [ ] 测试打卡数据统计的正确性(mock `order_person_asset`表数据)
|
|
|
+ - [ ] 测试视频分类统计按类型过滤功能
|
|
|
+ - [ ] 测试企业维度订单查询的分页和过滤功能
|
|
|
+ - [ ] 测试企业数据隔离:不同企业用户只能访问自己企业的数据
|
|
|
+ - [ ] **statistics-module测试**:
|
|
|
+ - [ ] 在`allin-packages/statistics-module/tests/integration/statistics.integration.test.ts`中实现6个统计接口的完整集成测试
|
|
|
+ - [ ] 测试每个统计接口的数据准确性(与数据库实际数据对比)
|
|
|
+ - [ ] 测试年龄分组计算逻辑(基于`birth_date`字段)
|
|
|
+ - [ ] 测试企业数据隔离:验证统计结果只包含当前企业关联的人才数据
|
|
|
+ - [ ] 测试边缘情况:空数据统计、部分字段缺失(如`birth_date`为空)的优雅处理
|
|
|
+ - [ ] **性能测试**:
|
|
|
+ - [ ] 建立统计查询性能基准,测试大数据量(1000+记录)下的响应时间
|
|
|
+ - [ ] 验证数据库索引优化效果
|
|
|
+ - [ ] 测试复杂统计查询(如年龄分组、薪资分布)的查询性能
|
|
|
+
|
|
|
+## 开发笔记
|
|
|
+仅填充从docs文件夹中的实际工件提取的相关信息,与此故事相关:
|
|
|
+
|
|
|
+### 先前故事洞察
|
|
|
+基于故事012.001-012.003和012.008的已完成实施:
|
|
|
+1. **故事012.001**:数据库schema扩展已完成,为数据统计提供基础字段(`birth_date`、扩展的`asset_type`枚举)
|
|
|
+2. **故事012.002**:企业用户认证API已实现,提供企业用户认证中间件`enterpriseAuthMiddleware`
|
|
|
+3. **故事012.003**:企业统计与人才扩展API已实现,提供相关聚合查询模式参考
|
|
|
+ - **职责划分**:故事012.003专注于**企业特定统计**(企业概览统计、企业维度人才统计)和**个人维度查询**(工作历史、薪资历史、征信信息、视频关联)
|
|
|
+ - **与本故事关系**:故事012.004专注于**跨实体通用数据统计**(残疾类型、性别、年龄、户籍、在职状态、薪资分布),两者职责互补不重叠
|
|
|
+4. **故事012.008**:路由路径规范修复已完成,确保API路径前缀`/api/v1/yongren`在server包统一注册
|
|
|
+
|
|
|
+### 数据模型
|
|
|
+基于现有实体定义和故事012.001的数据库schema扩展:
|
|
|
+
|
|
|
+**OrderPersonAsset实体**(allin-packages/order-module/src/entities/order-person-asset.entity.ts):
|
|
|
+- 用于打卡视频统计(`asset_type` = `checkin_video`)
|
|
|
+- 用于视频类型分类统计(`asset_type`枚举值:`salary_video`、`tax_video`、`checkin_video`、`work_video`)
|
|
|
+- 关联关系:通过`order_person_id`关联`order_person`表,进而关联`employment_order`表
|
|
|
+
|
|
|
+**EmploymentOrder实体**(allin-packages/order-module/src/entities/order.entity.ts):
|
|
|
+- 用于企业维度订单查询,包含企业ID(`company_id`)关联
|
|
|
+- 订单状态字段用于过滤和统计
|
|
|
+
|
|
|
+**DisabledPerson实体**(allin-packages/disability-module/src/entities/disabled-person.entity.ts):
|
|
|
+- 用于数据统计:`disability_type`、`gender`、`household_province`、`household_city`、`job_status`
|
|
|
+- 新增`birth_date`字段用于准确年龄计算(故事012.001添加)
|
|
|
+
|
|
|
+**OrderPerson实体**(allin-packages/order-module/src/entities/order-person.entity.ts):
|
|
|
+- `salary_detail`字段用于薪资分布统计
|
|
|
+
|
|
|
+### API规范
|
|
|
+**API路径约定**:
|
|
|
+所有新增API必须遵循`/api/v1/yongren`前缀约定,路由在模块包内不应包含此前缀,前缀在server包注册时统一添加。
|
|
|
+
|
|
|
+**订单统计API接口设计**(order-module扩展):
|
|
|
+1. 打卡数据统计:`GET /order/checkin-statistics`(企业维度)
|
|
|
+2. 视频分类统计:`GET /order/video-statistics`(企业维度,支持按类型过滤)
|
|
|
+3. 企业维度订单查询:`GET /order/company-orders`(支持企业ID过滤、分页、排序)
|
|
|
+
|
|
|
+**数据统计API接口设计**(**决策:创建独立的statistics-module**,专注于跨实体通用数据统计,与故事012.003的企业统计互补):
|
|
|
+
|
|
|
+**模块职责范围**:
|
|
|
+- **statistics-module**:跨实体通用数据统计,包括人才数据分布、薪资分布等跨企业维度的统计分析
|
|
|
+- **与012.003的职责划分**:
|
|
|
+ - 故事012.003:企业特定统计(企业概览、企业维度人才统计)和个人维度查询(工作历史、薪资历史、征信信息、视频关联)
|
|
|
+ - 故事012.004:跨实体通用数据统计(残疾类型、性别、年龄、户籍、在职状态、薪资分布)
|
|
|
+- **设计原则**:统计功能跨多个实体(disabled_person、order_person等)且可能被其他模块复用,遵循单一职责原则
|
|
|
+
|
|
|
+**具体接口列表**:
|
|
|
+1. 残疾类型分布:`GET /statistics/disability-type-distribution`
|
|
|
+2. 性别分布:`GET /statistics/gender-distribution`
|
|
|
+3. 年龄分布:`GET /statistics/age-distribution`(基于`birth_date`字段)
|
|
|
+4. 户籍分布:`GET /statistics/household-distribution`
|
|
|
+5. 在职状态分布:`GET /statistics/job-status-distribution`
|
|
|
+6. 薪资分布:`GET /statistics/salary-distribution`
|
|
|
+
|
|
|
+**认证要求**:
|
|
|
+- 所有接口需要企业用户权限验证
|
|
|
+- 使用故事012.002实现的`enterpriseAuthMiddleware`中间件
|
|
|
+- 企业用户只能访问自己关联的企业数据(通过`company_id`验证)
|
|
|
+
|
|
|
+**企业数据隔离实现细节**:
|
|
|
+- 在服务层实现企业数据过滤:所有查询必须包含`company_id`条件(从认证用户的`company_id`字段获取)
|
|
|
+- 对于订单统计:通过`employment_order.company_id`过滤
|
|
|
+- 对于数据统计:统计范围限定在企业关联的人才数据(通过`employment_order`→`order_person`→`disabled_person`关联链)
|
|
|
+- API层面验证:中间件验证用户`company_id`不为空,服务层验证查询结果的企业ID与用户企业ID匹配
|
|
|
+
|
|
|
+### 组件规范
|
|
|
+不适用(后端API故事)。
|
|
|
+
|
|
|
+### 文件位置
|
|
|
+基于项目结构和后端模块包规范:
|
|
|
+
|
|
|
+**订单模块位置**:
|
|
|
+- `allin-packages/order-module/src/routes/` - 路由文件位置
|
|
|
+- `allin-packages/order-module/src/services/` - 服务层文件位置
|
|
|
+- `allin-packages/order-module/src/schemas/` - Schema验证文件位置
|
|
|
+- `allin-packages/order-module/tests/integration/` - 集成测试位置
|
|
|
+
|
|
|
+**统计模块位置**(**决策:创建独立的statistics-module**):
|
|
|
+- `allin-packages/statistics-module/` - 新模块根目录
|
|
|
+- `allin-packages/statistics-module/package.json` - 包配置(依赖:`@d8d/allin-disability-module`、`@d8d/allin-order-module`、`@d8d/shared-types`、`@d8d/shared-utils`、`@d8d/shared-crud`等)
|
|
|
+- `allin-packages/statistics-module/src/routes/statistics.routes.ts` - 路由文件
|
|
|
+- `allin-packages/statistics-module/src/services/statistics.service.ts` - 服务层文件
|
|
|
+- `allin-packages/statistics-module/src/schemas/statistics.schema.ts` - Schema验证文件
|
|
|
+- `allin-packages/statistics-module/tests/integration/statistics.integration.test.ts` - 集成测试文件
|
|
|
+
|
|
|
+**残疾人模块位置**(用于数据统计):
|
|
|
+- `allin-packages/disability-module/src/entities/` - 实体定义
|
|
|
+- `allin-packages/disability-module/src/repositories/` - 数据访问层
|
|
|
+
|
|
|
+### 技术约束
|
|
|
+- **API路径规范**:模块包内路由不应包含`/api/v1/yongren`前缀,前缀在server包统一注册 [来源:docs/prd/epic-012-api-supplement-for-employer-mini-program.md#故事012-08]
|
|
|
+- **企业数据隔离**:企业用户只能访问自己关联的企业数据,通过`company_id`验证
|
|
|
+- **性能要求**:统计查询需要优化,大数据量下响应时间应可接受
|
|
|
+- **数据库兼容性**:使用PostgreSQL 17,TypeORM 0.3.25 [来源:docs/architecture/tech-stack.md]
|
|
|
+- **数据完整性假设**:假设数据库已包含必要的业务数据且字段完整(如`birth_date`字段已添加且部分记录有值,`asset_type`枚举已扩展),统计查询应考虑空数据情况的优雅处理
|
|
|
+
|
|
|
+### 项目结构说明
|
|
|
+- Monorepo结构,`allin-packages/`用于业务模块
|
|
|
+- 每个模块遵循后端模块包标准
|
|
|
+- 模块间通过依赖注入和TypeORM关联关系进行数据访问
|
|
|
+
|
|
|
+### 测试
|
|
|
+列出开发者需要遵循的相关测试标准:
|
|
|
+
|
|
|
+#### 测试文件位置
|
|
|
+- 单元测试:`allin-packages/{模块名称}/tests/unit/**/*.test.ts`
|
|
|
+- 集成测试:`allin-packages/{模块名称}/tests/integration/**/*.test.ts`
|
|
|
+
|
|
|
+#### 测试标准
|
|
|
+- 测试框架:Vitest
|
|
|
+- 数据库测试:使用测试数据库和事务回滚
|
|
|
+- 覆盖率要求:单元测试 ≥ 80%,集成测试 ≥ 60%
|
|
|
+
|
|
|
+#### 测试框架和模式
|
|
|
+- **单元测试**:测试服务层逻辑、数据统计计算逻辑
|
|
|
+- **集成测试**:测试API端点、数据库查询、企业数据隔离
|
|
|
+- **性能测试**:验证统计查询响应时间
|
|
|
+- **安全测试**:验证企业数据隔离,防止跨企业数据访问
|
|
|
+
|
|
|
+#### 此故事的特定测试要求
|
|
|
+1. **企业数据隔离测试**:验证企业用户只能访问自己企业的数据
|
|
|
+2. **统计准确性测试**:验证各种数据统计结果与数据库实际数据一致
|
|
|
+3. **年龄计算测试**:基于`birth_date`字段准确计算年龄分组
|
|
|
+4. **性能基准测试**:建立统计查询性能基准,确保响应时间可接受
|
|
|
+5. **边缘情况测试**:测试空数据统计、无效企业ID处理、部分字段缺失(如`birth_date`为空)时的优雅处理
|
|
|
+
|
|
|
+## 变更日志
|
|
|
+跟踪对此故事文档所做的更改
|
|
|
+
|
|
|
+| 日期 | 版本 | 描述 | 作者 |
|
|
|
+|------|------|------|------|
|
|
|
+| 2025-12-17 | 1.0 | 初始故事创建 | Bob(Scrum Master) |
|
|
|
+| 2025-12-17 | 1.1 | 根据检查清单反馈更新:添加史诗上下文、修正引用格式、明确统计模块决策、添加企业数据隔离实现细节、完善性能优化策略和边缘情况测试 | Bob(Scrum Master) |
|
|
|
+| 2025-12-17 | 1.2 | 架构决策更新:采用方案A,明确statistics-module职责范围仅限跨实体通用统计,与故事012.003的企业统计功能职责划分清晰 | Bob(Scrum Master) |
|
|
|
+
|
|
|
+## 开发代理记录
|
|
|
+此部分由开发代理在实施过程中填充
|
|
|
+
|
|
|
+### 使用的代理模型
|
|
|
+
|
|
|
+### 调试日志引用
|
|
|
+
|
|
|
+### 完成笔记列表
|
|
|
+
|
|
|
+### 文件列表
|
|
|
+
|
|
|
+## QA结果
|
|
|
+来自QA代理对已完成故事实施的QA审查结果
|