JhHardwareWRS/docs/superpowers/specs/2026-07-25-report-time-allocation-design.md

351 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 报工跨日期工时归属拆分设计
## 背景
现有报工记录使用 `report_date` 作为单一报工日期。这个字段被报工记录、管理员审核、经理看板、导出、对账小账本、设备/模具使用统计等模块复用。
当员工夜里或凌晨跨日期工作时,单一 `report_date` 无法准确表达工时归属。例如:
- `00:10` 上班,`11:00` 下班
- `00:10-06:00` 是前一天夜班尾段
- `06:00-08:00` 是作息空白区间,但按新规则应算加班
- `08:00-11:00` 是当天白班
如果整条报工强行归前一天或当天,都会造成一部分工时、数量、工资统计不合理。
## 目标
实现一条原始报工记录可以按工时归属拆分到多个日期。
核心原则:
- 原始报工记录仍然只保留一条,不拆成多条审核记录。
- 管理员审核、作废、更改、水印、员工记录仍围绕原始报工记录。
- 经理看板、导出、对账小账本、设备/模具统计、概览等统计类模块按拆分后的归属明细汇总。
- 跨日期时,成品数量、不良数量、报废数量、换料次数、参考工资等涉及统计的字段按有效工时比例拆分。
- 作息空白区间统一算加班,但不直接改变原始 `report_date`
## 非目标
- 不把一条原始报工拆成多条 `ProductionReport`
- 不开放管理员手工编辑 `report_date`
- 不批量回改历史记录的原始 `report_date`
- 不改变员工扫码上班、换模具、下班提交的主流程。
## 术语
- 原始报工:员工提交或系统自动提交后形成的一条 `ProductionReport`
- 工序明细:一条报工下的产品工序明细。
- 归属明细:按日期和班种拆出来的统计明细。
- 有效工时:扣除符合规则的吃饭时间后,用于统计、工资和数量分摊的工时。
- 空白区间:不属于白班、夜班、原加班区间的作息时间,例如默认 `06:00-08:00`、`17:20-18:00`。
## 推荐方案
采用“一条原始报工 + 多条归属明细”的方案。
### 原始记录
`ProductionReport` 继续保存员工真实提交的完整记录:
- 考勤点
- 员工
- 上班时间
- 下班时间
- 报工明细
- 审核状态
- 作废状态
- 更改状态
- 原始 `report_date`
原始 `report_date` 仍用于报工记录卡片的基础展示,但统计类模块不再只依赖它。
### 归属明细
新增一张后端表,例如 `production_report_allocations`
建议字段:
- `id`
- `report_id`
- `report_item_id`
- `attendance_point_name`
- `employee_phone`
- `allocation_date`
- `day_minutes`
- `overtime_minutes`
- `night_minutes`
- `effective_minutes`
- `good_qty`
- `defect_qty`
- `scrap_qty`
- `changeover_count`
- `reference_wage`
- `created_at`
- `updated_at`
如果后续设备/模具统计需要直接按设备或模具拆分,可以再补:
- `device_no`
- `mold_name`
- `product_name`
- `process_name`
- `stamping_method`
第一版建议保留到 `report_item_id` 级别,设备/模具统计可以根据现有工序明细和设备段关联计算,避免一次性改表过重。
## 拆分规则
### 班种区间
按报工所属考勤点的作息配置计算:
- 白班:`day_start` 到 `day_end`
- 原加班:`overtime_start` 到 `overtime_end`
- 夜班:`night_start` 到 `night_end`
- 午饭、晚饭:继续使用当前吃饭扣除规则
夜班跨天时,例如 `20:00-06:00`,按当前系统已有跨天区间逻辑处理。
### 空白区间
一天中不属于白班、原加班、夜班的时间,统一计入加班。
默认作息下:
- `06:00-08:00` 算加班
- `17:20-18:00` 算加班
空白区间只影响工时分布,不单独改变原始 `report_date`
### 日期归属
归属明细按时间片所在的自然日期和夜班归属拆分。
默认作息 `20:00-06:00` 下:
- `20:00-24:00` 夜班归属当天
- `00:00-06:00` 夜班归属前一天
- `06:00` 之后的空白加班、白班、加班归属当天
例子:`2026-07-25 00:10` 到 `2026-07-25 11:00`
- `2026-07-24`:夜班 `350` 分钟
- `2026-07-25`:加班 `120` 分钟,白班 `180` 分钟
### 数量和金额分摊
每个工序明细先计算总有效分钟,再按日期归属比例拆分。
公式:
```text
归属比例 = 某归属日有效分钟 / 当前工序明细总有效分钟
归属数量 = 原始数量 * 归属比例
归属工资 = 原始参考工资 * 归属比例
```
适用字段:
- 成品数量
- 不良数量
- 报废数量
- 换料次数
- 参考工资
### 小数处理
后端内部保留两位小数。
导出和页面展示可以使用两位小数,避免比例拆分后出现不合理的整数强行取整。
如果未来现场要求成品必须整数,可以另开一个“整数分摊余数归属规则”,本次不引入。
## 数据流
### 员工提交报工
1. 员工扫码、填写报工并提交。
2. 后端创建一条 `ProductionReport` 和对应 `ProductionReportItem`
3. 后端计算原始记录指标。
4. 后端生成或刷新归属明细。
5. 返回原始报工卡片。
### 系统自动提交
1. 自动提交服务创建原始报工。
2. 原始结束时间为系统自动提交时间。
3. 后端计算原始记录指标。
4. 后端生成或刷新归属明细。
### 管理员审核或更改
管理员调整以下内容时,需要重算归属明细:
- 上班时间
- 下班时间
- 换模具时间
- 产品工序
- 设备
- 成品数量
- 不良数量
- 报废数量
- 换料次数
- 工序单价
- 作废/撤销作废
保存流程:
1. 校验管理员权限和编辑窗口。
2. 保存原始记录修改。
3. 重算原始记录指标。
4. 删除旧归属明细。
5. 生成新归属明细。
6. 设置更改水印。
作废记录不参与统计。作废时可以保留归属明细,但统计查询必须过滤;也可以删除归属明细。第一版建议保留并在统计查询中过滤,方便撤销作废后立即恢复统计。
## 模块影响
### 员工报工记录
仍显示一条原始记录。
可在明细里补充展示工时归属,例如:
```text
工时归属2026-07-24 夜班 5小时50分2026-07-25 加班 2小时、白班 3小时
```
第一版只在管理员和经理侧展示归属摘要,员工侧报工记录保留现状。
### 管理员审核页
仍按原始记录审核。
管理员改时间或数量后,页面返回重算后的原始指标和归属摘要。
审核页可以展示归属摘要,帮助管理员知道这条记录会被拆到哪些日期。
### 经理报工看板
看板按归属明细汇总,不再只按 `ProductionReport.report_date` 汇总。
筛选日期查的是 `allocation_date`
同人、同考勤点、同项目、同产品、同工序、同冲压方式的聚合,应基于归属明细汇总。
### 经理看板导出
第一张明细 sheet 按归属明细导出。
建议保留两个日期字段:
- 原始报工日期
- 统计归属日期
这样经理既能追溯原始记录,也能看到工资和工时实际归属。
参考工资、工序单价、工种、备注等现有导出字段继续保留。
工资汇总 sheet 按归属明细汇总。
### 对账小账本
已报工成品数量使用归属明细统计。
最后一道工序判断仍按产品清单数字工序大小确定。
月份归属改为 `allocation_date` 所在月份。
### 设备/模具使用统计
默认统计审核通过且未作废记录。
时间筛选按归属明细日期。
普通设备/模具:
- 时长按归属明细有效分钟汇总
- 报工次数按原始报工 ID 去重
建议第一版:
- 时长按归属明细汇总
- 报工次数按原始报工 ID 去重
清洗设备:
- 清洗数量按归属明细数量汇总
- 报工次数按原始报工 ID 去重
### 概览
涉及今日、历史待审核、已通过等指标时:
- 审核状态类数量仍按原始报工记录。
- 工时、数量、工资类指标按归属明细。
## 错误处理
- 如果归属明细生成失败,原始报工保存应回滚,避免原始记录和统计数据不一致。
- 如果旧数据没有归属明细,统计查询应提供兼容兜底:用原始记录实时计算或用迁移脚本补齐。
- 如果有效分钟为 `0`,数量和工资不做比例拆分,统一归到原始 `report_date`,同时记录日志,避免除零。
- 如果作息配置缺失,使用当前默认作息。
## 历史数据处理
历史原始 `report_date` 不批量回改。
但为了让统计类模块切换到新口径,建议提供一次性迁移脚本:
1. 扫描审核通过且未作废的历史报工。
2. 根据记录当时的上下班时间、工序明细、考勤点作息生成归属明细。
3. 不修改原始 `report_date`
4. 迁移后输出处理数量、跳过数量、异常记录 ID。
如果担心历史作息被后续修改导致还原不准,第一版接受使用当前考勤点作息生成历史归属明细。后续如要严格追溯,需要在报工时快照作息配置。
## 测试用例
核心用例:
- `2026-07-25 00:10``2026-07-25 11:00`
- `2026-07-24` 夜班 `350` 分钟
- `2026-07-25` 加班 `120` 分钟,白班 `180` 分钟
- `2026-07-25 05:59``2026-07-25 11:00`
- `2026-07-24` 夜班 `1` 分钟
- `2026-07-25` 加班 `120` 分钟,白班 `180` 分钟
- `2026-07-24 20:00``2026-07-25 06:30`
- `2026-07-24` 夜班 `600` 分钟
- `2026-07-25` 加班 `30` 分钟
- `2026-07-25 06:00``2026-07-25 08:00`
- `2026-07-25` 加班 `120` 分钟
- `2026-07-25 17:20``2026-07-25 18:00`
- `2026-07-25` 加班 `40` 分钟
- 覆盖吃饭扣除和 5 分钟缓冲规则。
- 覆盖管理员修改上下班时间后归属明细重算。
- 覆盖管理员修改换模具时间后归属明细重算。
- 覆盖作废记录从统计中排除。
- 覆盖撤销作废后统计恢复。
## 实施顺序建议
1. 后端新增归属计算服务和单元测试。
2. 新增归属明细表和迁移脚本。
3. 报工提交、自动提交、管理员审核保存后写入归属明细。
4. 经理看板和导出切换到归属明细。
5. 对账小账本、设备/模具统计、概览按风险顺序切换。
6. 前端增加归属摘要展示。
7. 跑迁移脚本补齐历史归属明细。
## 已固定技术口径
当前方案已按以下业务口径固定:
- 涉及拆分的字段都按工时比例拆。
- 空白作息区间算加班。
- 空白作息区间不影响原始 `report_date`
- 原始报工记录不拆。
- 报工次数统计按原始报工 ID 去重,不因一条报工拆到多个日期而重复计数。