# 生产日结与材料闭环设计

## 背景

真实生产不是一次领料后必须按参考生产数量一次性全部做完。常见场景是：今天领料生产一部分，下班前把已完成成品入成品库，把剩余原材料还回原材料库，第二天再次领料或继续生产。现有逻辑偏向“参考生产数量未做完则生产出库任务未结束”，会让 DAG 看起来像领料一直悬挂，无法表达阶段性生产和阶段性结算。

本设计目标是把生产出库从“一次性完工工单”改造为“可多次日结的生产任务”，用材料去向闭环替代计划数量闭环。

## 核心业务原则

1. 生产出库代表一次领料任务，不代表必须一次性完成全部参考生产数量。
2. 每次生产结束可以做一次“生产日结”，记录本次报工、成品入库、余料归还、废料/报废和差异原因。
3. 任务是否结束，不再只看 `完工数 >= 参考生产数量`，而是看领出的材料是否已经有明确去向。
4. 成品入库、生产余料入库、生产废料入库都要能挂到同一次生产日结下。
5. DAG 要展示“领料任务 -> 多次生产日结 -> 各类入库/报废 -> 任务结清”的真实链路。

## 新增概念

### 生产出库任务

沿用现有生产出库/工单主体，语义调整为“领料任务”。它记录：

- 生产跟踪号
- 产品
- 领用原材料库存批次
- 领用重量
- 参考生产数量
- 当前材料闭环状态

参考生产数量仍保留，但只作为参考值，不再是唯一闭环标准。

### 生产日结单

新增一个业务对象，建议表名为 `pp_production_settlement`，用于记录某个生产出库任务的一次阶段性结算。

建议字段：

- `settlement_no`：日结单号
- `work_order_id`：生产出库任务 ID
- `settlement_date`：结算日期
- `reported_qty`：本次报工数量
- `finished_qty`：本次合格成品数量
- `scrap_qty`：本次报废数量
- `standard_consumed_weight_kg`：标准消耗重量
- `expected_surplus_weight_kg`：标准应归还余料重量
- `actual_surplus_weight_kg`：实际余料归还重量
- `site_carryover_weight_kg`：现场留存重量，用于记录当天不还仓、继续留在生产现场的材料重量
- `scrap_weight_kg`：废料或报废折算重量
- `variance_weight_kg`：差异重量
- `variance_rate`：差异率
- `variance_reason`：偏差原因
- `status`：草稿、已确认、异常确认、已撤销

标准消耗公式：

```text
标准消耗重量 = 本次报工数量 × 产品毛重
```

标准应归还余料：

```text
标准应归还余料 = 结算前未闭环现场余额 - 标准消耗重量 - 废料/报废折算重量 - 现场留存重量
```

偏差率：

```text
偏差率 = abs(实际余料归还重量 - 标准应归还余料) / 标准应归还余料
```

当标准应归还余料为 0 时，使用差异重量是否为 0 判断；如存在差异，要求填写原因。

## 状态规则

生产出库任务建议状态：

- `已领料`：已经完成生产出库，还没有日结。
- `生产中`：已有小程序报工或工序进度，但尚未结算。
- `部分结算`：至少存在一张已确认生产日结单，但材料尚未全部闭环。
- `待结清`：理论上仍有未处理材料、未入库成品或未解释差异。
- `已结清`：领料重量已经通过成品、余料、废料、允许损耗和差异原因完成闭环。
- `异常结清`：偏差超过阈值，用户填写原因后确认结清。

偏差阈值默认使用 10%。超过 10% 时，必须填写偏差原因才能确认日结。

## 材料闭环判断

一个生产出库任务的材料闭环按重量判断：

```text
领料总重量
= 已结算标准消耗重量
+ 已归还余料重量
+ 已入废料/报废重量
+ 允许损耗重量
+ 已解释差异重量
+ 未结清现场余额
```

系统展示时要明确区分：

- 已生产消耗
- 已余料归还
- 已报废/废料入库
- 已解释差异
- 未结清现场余额

只有未结清现场余额为 0，且所有超过阈值的差异都有原因时，任务才能进入已结清或异常结清。

如果用户当天不把剩余材料全部还仓，而是留在现场第二天继续生产，则在生产日结中填写“现场留存重量”。这部分重量不会形成余料入库流水，也不会让任务结清；它会作为下一次生产日结的结算前未闭环现场余额。

## 出入库联动

### 成品入库

成品入库从生产日结单发起或关联生产日结单。每张生产日结单可以对应一张或多张成品入库记录，但推荐前端默认合并为一次成品入库操作。

成品批次要记录：

- 生产出库任务
- 生产日结单
- 原材料库存批次来源
- 入库数量
- 入库重量
- 入库材料成本

### 生产余料入库

生产余料入库必须关联生产日结单和来源库存批次。归还逻辑仍然是回到原库存批次，不新建库存批次。

页面展示：

- 来源库存批次号，多选
- 每个来源库存批次的归还重量
- 标准应归还重量
- 实际归还重量
- 现场留存重量
- 偏差率
- 超过 10% 时填写原因

### 生产废料入库

生产废料入库可以关联生产日结单。用于记录边角料、废料和报废折算进入废料库。

如果废料入库重量来自报废数量折算，系统应显示计算依据；如果用户直接称重录入，则以称重为准。

## DAG 展示设计

DAG 从当前“生产出库后直接挂工序、报工、成品入库”调整为分层展示：

```mermaid
flowchart LR
  A["原材料库存批次"] --> B["生产出库任务"]
  B --> C1["生产日结 2026-06-02"]
  B --> C2["生产日结 2026-06-03"]
  C1 --> D1["成品入库"]
  C1 --> E1["生产余料入库"]
  C1 --> F1["生产废料入库"]
  C2 --> D2["成品入库"]
  C2 --> E2["生产余料入库"]
  C2 --> F2["生产废料入库"]
  B --> G["任务结清状态"]
```

节点层级：

- Level 0：原材料库存批次
- Level 1：生产出库任务
- Level 2：生产日结单
- Level 3：工序报工汇总、成品入库、余料入库、废料入库
- Level 4：销售出库或后续追溯节点

DAG 节点指标：

- 生产出库任务节点：领料重量、参考生产数量、累计日结数量、未结清现场余额、状态。
- 生产日结节点：本次报工、合格品、报废、标准消耗、标准余料、实际余料、偏差率。
- 未结清现场余额节点或指标：展示仍留在现场、尚未还仓或尚未解释去向的材料重量。
- 成品入库节点：入库数量、来源库存批次、材料成本。
- 余料入库节点：归还库存批次、归还重量、偏差说明。
- 废料入库节点：废料重量、来源日结、处理状态。

DAG 视觉规则：

- 未结清任务用黄色状态。
- 偏差超过阈值且未写原因用红色状态。
- 已结清任务用绿色状态。
- 生产日结节点按日期从上到下排列。
- 点击生产出库任务时，高亮所有关联日结和出入库链路。
- 点击某个生产日结时，只高亮该日结对应的成品、余料和废料链路。

## 前端交互

### 生产出库列表

新增或调整列：

- 生产跟踪号
- 产品
- 领料重量
- 参考生产数量
- 累计报工数量
- 累计成品入库
- 累计余料归还
- 未结清现场余额
- 状态

操作：

- 查看 DAG
- 新增生产日结
- 查看日结记录
- 结清任务

### 新增生产日结抽屉

用户选择生产出库任务后，系统自动带出：

- 产品
- 产品毛重
- 领料来源库存批次
- 当前未结清重量
- 小程序报工汇总
- 可入库成品数量

用户填写或确认：

- 本次报工数量
- 本次成品入库数量
- 本次报废数量
- 本次余料归还重量
- 本次现场留存重量
- 本次废料入库重量
- 偏差原因

系统实时计算：

- 标准消耗重量
- 标准应归还重量
- 结算后未结清现场余额
- 实际归还偏差
- 偏差率
- 是否必须填写原因

## 后端接口

建议新增接口：

- `GET /production/work-orders/{id}/settlement-preview`
- `POST /production/work-orders/{id}/settlements`
- `GET /production/work-orders/{id}/settlements`
- `POST /production/settlements/{id}/confirm`
- `POST /production/work-orders/{id}/close`

现有接口调整：

- 成品入库接口支持传入 `settlement_id`。
- 生产余料入库接口支持传入 `settlement_id`。
- 生产废料入库接口支持传入 `settlement_id`。
- DAG 生命周期接口返回生产日结节点和日结关联的入库/报废节点。

## 数据迁移

已有历史生产出库可以不强制补日结单。迁移策略：

- 已完工且已有成品入库的生产出库，DAG 可继续按旧链路展示。
- 新增生产日结功能上线后，新生产出库默认走日结链路。
- 对历史未完成生产出库，可允许用户手工创建一张“历史补录日结单”进行结清。

## 测试要点

后端测试：

- 领料 200kg，报工 200 件，毛重 0.6kg，标准应归还 80kg。
- 偏差不超过 10% 时允许确认日结。
- 偏差超过 10% 且无原因时禁止确认。
- 多次日结累计后，未结清现场余额正确减少。
- 成品入库、余料入库、废料入库均能关联同一日结单。
- 任务结清不再依赖 `完工数 >= 参考生产数量`。

前端测试：

- 生产日结抽屉实时计算标准余料和偏差率。
- 超过 10% 时偏差原因必填。
- DAG 展示生产日结节点和多条出入库链路。
- 点击生产出库任务和点击日结节点的高亮范围不同。

## 非目标

本次设计不引入复杂 APS 排产，不管理员工排班，不强制要求每道工序都每日结算。小程序报工仍作为生产数量和报废数量来源，ERP 负责生产日结和库存闭环。
