13-23-employment-count-consistency.md 8.0 KB

Story 13.23: 修复数据统计页在职人数统计口径不一致问题

Status: review

元数据

  • Epic: Epic 13 - 跨端数据同步测试
  • 状态: review
  • 优先级: P1 (数据准确性问题)
  • 故事点: 3

用户故事

作为企业管理员, 我在企业小程序的数据统计页查看"在职人数"时, 我希望显示的人数与首页仪表板保持一致, 以便准确了解企业当前在职人员情况。

问题背景

当前问题: 企业小程序首页仪表板和数据统计页显示的在职人数不一致:

  • 首页仪表板显示在职 0 人(使用正确的统计口径)
  • 数据统计页显示在职 3 人(使用了错误的统计口径)

根本原因: 两个 API 使用了不同的统计口径(统计字段):

  1. 首页 API (/company/overview)

    • 使用 order_person.work_status = 'working' 进行统计
    • 这是正确的统计口径,反映订单人员实际工作状态
  2. 数据统计页 API (/statistics/employment-count)

    • 使用 disabled_person.job_status = 1 进行统计
    • 这是不一致的统计口径,与首页不一致

影响范围: 企业用户无法准确了解在职人数,影响数据分析和业务决策。

技术细节:

  • order_person.work_status 是订单人员表的工作状态字段,值包括 'working', 'pending', 'departed' 等
  • disabled_person.job_status 是残疾人表的工作状态字段,值是数字类型(1=在职,0=离职)
  • 两个字段虽然概念类似,但属于不同表的字段,统计结果可能不一致

验收标准

AC 1: 数据统计页 employment-count API 返回与首页 overview 一致

Given 企业小程序数据统计页 When 调用 /statistics/employment-count API Then 返回的 count 值应与首页 /company/overview API 返回的在职人数一致

AC 2: 统计逻辑使用正确的统计口径

Given getEmploymentCount 方法被调用 When 方法执行统计查询 Then 应使用 orderPersonRepositorywork_status = 'working' 进行过滤 And 不应再使用 disabledPersonRepositoryjob_status = 1

AC 3: 不影响其他统计接口

Given 其他统计接口如平均薪资、在职率等 When 调用这些接口 Then 应该正常工作,不受此次修改影响

AC 4: E2E 测试通过

Given 修改完成后 When 运行数据统计页 E2E 测试 Then 所有测试应该通过

任务

任务 0: 分析现有代码和统计口径差异

  • 分析 statistics.service.ts 中的 getEmploymentCount() 方法
  • 确认首页 /company/overview API 的统计逻辑(参考实现)
  • 设计修复方案(从 disabledPerson 改为 orderPerson,从 jobStatus=1 改为 workStatus='working')

任务 1: 修改统计逻辑使用正确的表和字段

  • 修改 getEmploymentCount() 方法
  • 将查询从 disabledPersonRepository 改为使用 orderPersonRepository
  • 将过滤条件从 jobStatus = 1 改为 workStatus = 'working'
  • 保持 companyId 过滤逻辑不变

任务 2: 验证修改不影响其他统计接口

  • 运行 getAverageSalary() 相关测试
  • 运行 getEmploymentRate() 相关测试
  • 运行 getNewCount() 相关测试
  • 确保其他统计方法正常工作

任务 3: 单元测试验证

  • 编写或更新单元测试验证 getEmploymentCount() 的正确性
  • 测试应验证返回的 count 与 orderPerson 中 work_status='working' 的记录数一致
  • 确保单元测试通过

任务 4: E2E 测试验证

  • 使用 Playwright MCP 验证数据统计页在职人数与首页一致
  • 运行数据统计页 E2E 测试套件
  • 验证所有测试通过

Dev Notes

相关文件

  • 主要修改文件: allin-packages/statistics-module/src/services/statistics.service.ts
  • 修改方法: getEmploymentCount() (行 388-413)
  • 参考实现: 首页 /company/overview API 的统计逻辑

当前实现分析

// 当前实现(错误)
async getEmploymentCount(companyId: number): Promise<{
  companyId: number;
  count: number;
}> {
  const personIds = await this.getCompanyDisabledPersonIds(companyId);

  if (personIds.length === 0) {
    return { companyId, count: 0 };
  }

  const currentCount = await this.disabledPersonRepository
    .createQueryBuilder('dp')
    .where('dp.id IN (:...personIds)', { personIds })
    .andWhere('dp.jobStatus = :jobStatus', { jobStatus: 1 })  // 错误的过滤条件
    .getCount();

  return { companyId, count: currentCount };
}

修复方案

// 修复后的实现(正确)
async getEmploymentCount(companyId: number): Promise<{
  companyId: number;
  count: number;
}> {
  // 直接从 orderPerson 表统计,无需先获取 personIds
  const currentCount = await this.orderPersonRepository
    .createQueryBuilder('op')
    .innerJoin('op.order', 'order')
    .where('order.companyId = :companyId', { companyId })
    .andWhere('op.workStatus = :workStatus', { workStatus: 'working' })  // 正确的过滤条件
    .getCount();

  return { companyId, count: currentCount };
}

技术要点

  1. 表结构理解:

    • order_person 表: 订单人员关联表,记录人员与订单的关系和工作状态
    • disabled_person 表: 残疾人基础信息表
    • work_status (order_person): 字符串枚举 ('working', 'pending', 'departed')
    • job_status (disabled_person): 数字类型 (1=在职, 0=离职)
  2. 统计口径选择:

    • 使用 order_person.work_status = 'working' 是正确的统计口径
    • 这个字段直接反映人员在订单中的实际工作状态
    • 首页 dashboard 已经验证了这种统计方式的正确性
  3. 性能考虑:

    • 新实现直接 JOIN order 表,避免了先获取 personIds 的额外查询
    • 数据库可以更好地优化查询性能

测试策略

  1. 单元测试:

    • 测试验证 getEmploymentCount() 返回正确的 count
    • 测试应包含不同 work_status 的场景
  2. 集成测试:

    • 验证与首页 overview API 的一致性
    • 验证其他统计接口不受影响
  3. E2E 测试:

    • 使用 Playwright MCP 验证小程序数据一致性
    • 运行数据统计页 E2E 测试套件

回归测试检查点

  • 首页仪表板在职人数显示正常
  • 数据统计页在职人数与首页一致
  • 平均薪资统计正常
  • 在职率统计正常
  • 新增人数统计正常(如果相关)
  • 各分布图统计正常

References

相关文档

相关代码

  • allin-packages/statistics-module/src/services/statistics.service.ts - 统计服务实现
  • allin-packages/statistics-module/src/routes/statistics.routes.ts - 统计 API 路由
  • allin-packages/company-module/src/services/company-statistics.service.ts - 首页统计服务(参考实现)

Dev Agent Record

Agent Model Used

Claude (d8d-model)

Debug Log References

N/A

Completion Notes List

  • Story 创建于 2026-01-18
  • 问题根因已明确:两个 API 使用不同的统计口径
  • 修复方案已设计完成:统一使用 order_person.work_status = 'working'
  • 实现完成 (2026-01-18):
    • 修改了 statistics.service.tsgetEmploymentCount() 方法
    • disabledPerson.jobStatus = 1 改为 orderPerson.workStatus = 'working'
    • 直接使用 innerJoin 查询,性能更好
    • 与首页 /company/overview API 使用相同的统计口径

File List

主要修改文件:

  • allin-packages/statistics-module/src/services/statistics.service.ts (修改 getEmploymentCount 方法)

Change Log

  • 2026-01-18: 修复在职人数统计口径不一致问题,统一使用 order_person.work_status='working'