云
16 小时以前 ce85503abbd0924f8d999e6a86eeb46498b85665
docs(mes): 新增MES生产报工与入库设计方案文档

- 添加报工质检标识取值调整前端联调方案文档
- 添加一道工序多产出联产品设计与改造方案文档
- 添加产品入库库存记账时点调整前端联调方案文档
- 添加生产报工自动扣料与质检流转修改方案文档
已添加6个文件
858 ■■■■■ 文件已修改
docs/feedback_qc_flag_source.md 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/process_multi_output_design.md 251 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/product_receipt_stock_timing.md 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/production_feedback_qc_fix_plan.md 270 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/qc_source_link_frontend_integration.md 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/task_reporter_assignment.md 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/feedback_qc_flag_source.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,68 @@
# æŠ¥å·¥è´¨æ£€æ ‡è¯†å–值调整 - å‰ç«¯è”调方案
## æ¶‰åŠé¡µé¢
- ç”Ÿäº§è®¢å•(工单工序列表、工序编辑)
- MES ç”Ÿäº§ä»»åŠ¡ï¼ˆä»»åŠ¡åˆ—è¡¨ã€ä»»åŠ¡è¯¦æƒ…ã€å¾…æŠ¥å·¥å°è´¦ï¼‰
- MES ç”Ÿäº§æŠ¥å·¥ï¼ˆæ–°å¢ž/修改、审批)
- ç”Ÿäº§å·¥ä½œå°ï¼ˆä»»åŠ¡åˆ—è¡¨ã€æŠ¥å·¥é¡µç­¾ï¼‰
## ä¸šåŠ¡èƒŒæ™¯
工单创建时可以在「工序」页签单独勾选本工单每道工序是否质检,该配置保存在工单工序快照 `mes_pro_work_order_process`。
此前报工审批、任务列表、工作台判断「是否需要质检」时读取的是工艺路线模板 `mes_pro_route_process`,导致工单上勾选「质检」但工艺路线该工序为「否」时,报工审批走的是免检分支:产出直接按合格入库,不生成待检任务,任务报完工后不会进入质检。
调整后统一为:**一律以工单工序快照的「质检」标识为准**,仅在工单未维护对应工序时回退工艺路线模板。
## è®°è´¦/流程规则
| åœºæ™¯ | è§„则 |
|------|------|
| å·¥å•工序勾选质检 | æŠ¥å·¥å®¡æ‰¹åŽç”Ÿæˆã€Œå¾…检验」产出,进入待检任务,质检完成后才入库 |
| å·¥å•工序未勾选质检 | æŠ¥å·¥å®¡æ‰¹åŽæŒ‰åˆæ ¼/不合格数量直接完成入库 |
| å·¥å•未维护该工序 | å›žé€€è¯»å–工艺路线工序的质检标识 |
| å€’冲标识 | ä¸Žè´¨æ£€æ ‡è¯†ä¸€è‡´ï¼šå·¥å•工序快照优先,工艺路线兜底 |
## API
接口路径、请求参数、响应结构均无变化,仅 `checkFlag` å­—段的取值来源调整。
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| GET | /mes/pro/task/get | ä»»åŠ¡è¯¦æƒ…ï¼Œ`checkFlag` æ”¹ä¸ºå–工单工序快照 |
| GET | /mes/pro/task/page | ä»»åŠ¡åˆ†é¡µï¼ŒåŒä¸Š |
| GET | /mes/pro/task/pending-feedback-page | å¾…报工台账,同上 |
| GET | /mes/pro/feedback/get | æŠ¥å·¥è¯¦æƒ…,`checkFlag` æ”¹ä¸ºå–工单工序快照 |
| GET | /mes/pro/feedback/page | æŠ¥å·¥åˆ†é¡µï¼ŒåŒä¸Š |
| PUT | /mes/pro/feedback/update | æ ¡éªŒå£å¾„改为工单工序快照(需检工序只校验报工数量) |
| POST | /mes/pro/feedback/approve | å®¡æ‰¹æŒ‰å·¥å•工序快照决定是否进入质检 |
## å­—段展示规则
| å­—段 | å±•示位置 | å˜åŒ–说明 |
|------|----------|----------|
| checkFlag | ç”Ÿäº§ä»»åŠ¡åˆ—è¡¨ã€ä»»åŠ¡é€‰æ‹©å¼¹çª— | å–工单工序快照,表示该任务产出是否需要质检 |
| checkFlag | æŠ¥å·¥è¡¨å•数量区域 | ä¸º true æ—¶åªå¡«æŠ¥å·¥æ•°é‡ï¼Œä¸º false æ—¶å¡«åˆæ ¼/不合格数量 |
| backflushFlag | ä»»åŠ¡åˆ—è¡¨ | å–工单工序快照,表示该工序是否倒冲扣料 |
## å¤šäº§å‡ºç‰©æ–™çš„æ£€éªŒè§„则
同一道工序可能同时产出多个物料(主产出 + è”产出,来源为工单工序快照 `outputItemId`),需要检验时:
| åœºæ™¯ | è§„则 |
|------|------|
| æŠ¥å·¥å®¡æ‰¹ | æ¯ä¸ªäº§å‡ºç‰©æ–™å„生成一条「待检验」产出行,产出单保持未完成,报工状态为待检验 |
| å¾…检任务 | æ¯æ¡äº§å‡ºè¡Œå‘ˆçŽ°ä¸ºä¸€æ¡å¾…æ£€è®°å½•ï¼Œç‰©æ–™å–äº§å‡ºè¡Œç‰©æ–™ï¼Œå·¥åºå–æŠ¥å·¥å•å·¥åº |
| åˆ›å»ºè¿‡ç¨‹æ£€éªŒå• | æ£€éªŒç‰©æ–™æŒ‰æ¥æºäº§å‡ºè¡Œç¡®å®šï¼ˆä¸å†å–任务物料),工序取报工单工序 |
| å®ŒæˆæŸå¼ æ£€éªŒå• | åªæ‹†åˆ†è¯¥æ£€éªŒå•对应的产出行(生成合格/不合格明细) |
| å®ŒæˆæŠ¥å·¥ | åŒä¸€æŠ¥å·¥çš„æ‰€æœ‰äº§å‡ºè¡Œéƒ½æ£€éªŒå®ŒæˆåŽï¼Œäº§å‡ºå•才完成入库,报工/任务进度才回写 |
| æ•°é‡å£å¾„ | æŠ¥å·¥å•与任务的合格/不合格/废品数量只统计主产出物料,联产出物料单独检验、单独入库 |
| æ£€éªŒæ¨¡æ¿ | æ¯ä¸ªäº§å‡ºç‰©æ–™éƒ½å¿…须单独配置启用的过程检验模板(IPQC),否则审批或建单会提示缺失 |
## æ³¨æ„äº‹é¡¹
- å·¥å•工序勾选「质检」时,该工序的每个产出物料都必须已配置启用的过程检验模板(IPQC),否则审批会提示「未配置启用的过程检验模板」。
- å‰ç«¯å¦‚自行调用 `/mes/pro/route-process/get-by-route-and-process` æŽ¨å¯¼ `checkFlag`,应改为优先使用任务或报工接口返回的 `checkFlag`,避免与后端审批口径不一致。
- è¿‡ç¨‹æ£€éªŒå•的物料由后端按来源产出行确定,前端无需传 `itemId`;传了也不会改变检验物料。
- åŽ†å²ä»»åŠ¡ RW2611070009 å·²æŒ‰ `scripts/feedback-qc-rollback-20261107/01_rollback_rw2611070009.sql` å’Œ `03_rollback_per_material_ipqc.sql` å›žé€€æŠ¥å·¥å•、任务进度、产出/自动入库单及过程检验单,可重新报工验证质检流程。
docs/process_multi_output_design.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,251 @@
# ä¸€é“工序多产出(联产品)设计与改造方案
> çŠ¶æ€ï¼šå¾…ç¡®è®¤ï¼Œç¡®è®¤åŽå†å®žæ–½
> æ—¥æœŸï¼š2026-11-07
## 1. èƒŒæ™¯
一键排产预览时,工单 `WO_202611070001` åœ¨å·¥åºã€Œé“èŠ¯å è£…ã€è¢«æ‹¦æˆªï¼š
```
工序铁芯叠装对应多个产出,请手工排产确认各产出数量
```
来源:`MesProBatchScheduleService.java:252-260`。当前排产模型是「一道工序 = ä¸€ä¸ªä»»åŠ¡ = ä¸€ä¸ªäº§å‡ºç‰©æ–™ã€ï¼Œæ£€æµ‹åˆ°å·¥åºäº§å‡ºå¤šäºŽä¸€ä¸ªæ—¶ç›´æŽ¥æŠ›é”™ã€‚
但工艺路线本身允许一道工序配置多个产出(`mes_pro_route_process_output`),工单工序快照也保存了多个产出(`mes_pro_work_order_process.output_item_id`,逗号分隔)。下游的任务、报工、生产产出单又都是单物料模型,因此多产出目前处于「能配、不能排、不能正确流转」的状态。
同时排查发现几个关联问题:
| ä½ç½® | çŽ°çŠ¶é—®é¢˜ |
|------|----------|
| `MesProBatchScheduleService` | å¤šäº§å‡ºç›´æŽ¥æ‹’绝,无法批量排产 |
| `schedule-form.vue:128` | æŽ’产时把 `outputItemId`(逗号串)直接当 `itemId` ä¼ ç»™ä»»åŠ¡ï¼Œå¤šäº§å‡ºæ—¶ä¼šä¼ éžæ³•å€¼ |
| `MesProTaskServiceImpl.resolveTaskItemId` | å–第一个产出,顺序不确定 |
| `MesWmProductProduceServiceImpl` | ä¸€ä¸ªæŠ¥å·¥åªç”Ÿæˆä¸€ä¸ªç‰©æ–™çš„产出行 |
| `MesProWorkOrderBomController.buildWorkOrderItems` | äº§å‡ºâ†’工序投料映射只取 CSV ç¬¬ä¸€ä¸ªäº§å‡º |
| `mes_pro_route_process_output` | å­˜é‡å­˜åœ¨é‡å¤è¡Œï¼ˆroute_process 126/127/128/129 å…± 4 ç»„) |
## 2. ä¸šåŠ¡å®šä¹‰ï¼ˆå·²ç¡®è®¤ï¼‰
1. **同一次加工同时产出多个物料**(联产品/副产品),不是同一工序分别生产。
2. å„产出数量由**工艺路线工序产出配置中的固定配比**决定,以主产出为基准 `1`:
   - ä¸»äº§å‡ºï¼šæ¯åŠ å·¥ 1 ä¸ªä¸»äº§å‡ºï¼›
   - å…¶å®ƒäº§å‡ºï¼šæ¯åŠ å·¥ 1 ä¸ªä¸»äº§å‡ºé™„带的数量(如 `2` è¡¨ç¤º 1 ä¸ªä¸»äº§å‡ºåŒæ—¶äº§å‡º 2 ä¸ªå•位)。
3. æŽ’产、报工、工单进度、报工扣料都以**主产出数量**为准;其它产出按配比自动换算。
4. ä¸€ä¸ªå·¥åºä»ç„¶**只生成一个生产任务、只报一次工**,产出单按产出物料拆成多行。
## 3. æ€»ä½“方案
```
工艺路线工序
  â””── äº§å‡ºé…ç½®ï¼ˆitemId, é…æ¯” quantity, ä¸»äº§å‡º mainFlag)
          â”‚
          â–¼
工单工序快照(output_item_id é€—号串,主产出排第一位)
          â”‚
          â–¼
生产任务(一条,itemId = ä¸»äº§å‡ºï¼Œquantity = ä¸»äº§å‡ºæ•°é‡ï¼‰
          â”‚
          â–¼
报工(一次,feedback.itemId = ä¸»äº§å‡ºï¼‰
          â”‚
          â–¼
生产产出单(一个单头,每个产出一行 line + ä¸€æ¡ detail)
          â”‚
          â–¼
产品入库单(一个单头,每行一个产出)
```
核心原则:**不新增任务维度、不改报工模型**,只在产出单生成时按配比展开多行。这样排产工时、报工扣料、工单已生产数量的计算都不受影响。
## 4. æ•°æ®æ¨¡åž‹
### 4.1 `mes_pro_route_process_output` å¢žåŠ å­—æ®µ
```sql
ALTER TABLE mes_pro_route_process_output
    ADD COLUMN quantity DECIMAL(18,6) NOT NULL DEFAULT 1.000000 COMMENT '配比:每1个主产出的附带数量,主产出固定为1' AFTER item_id;
ALTER TABLE mes_pro_route_process_output
    ADD COLUMN main_flag TINYINT NOT NULL DEFAULT 0 COMMENT '是否主产出:1是 0否' AFTER quantity;
```
说明:
- ä¸»äº§å‡ºçš„ `quantity` å›ºå®šä¸º 1,由服务端强制;其它产出必须 > 0。
- åŒä¸€é“工序(同一归属产品分组内)最多一个 `main_flag = 1`;服务层校验,不做数据库唯一索引(`product_id` å…è®¸ä¸º NULL,唯一索引无法约束)。
- å·¥åºäº§å‡ºå€™é€‰é›†ä»æŒ‰ `product_id IS NULL OR product_id = å½“前产品` è¿‡æ»¤ï¼›è‹¥è¿‡æ»¤åŽæ²¡æœ‰ä¸»äº§å‡ºï¼Œè¿è¡Œæ—¶å›žé€€å–排序第一条。
### 4.2 å·¥å•工序快照
`mes_pro_work_order_process.output_item_id` ç»§ç»­ä½¿ç”¨é€—号串,**只调整顺序:主产出排第一位**,其余按 sort æŽ’序。
原因:现有任务创建、BOM å±•开、前端展示都有取「第一个」的兜底逻辑,保持第一位是主产出可以最小化改动。
配比不快照到工单,生成产出单时按 `(routeId, processId, productId, itemId)` å›žæŸ¥è·¯çº¿é…ç½®ï¼›æŸ¥ä¸åˆ°æ—¶é»˜è®¤ 1。
> è¾¹ç•Œï¼šè·¯çº¿å¯ç”¨åŽä¸å…è®¸ç¼–辑;停用→修改→再启用时,历史工单的配比会跟随路线变化。如需冻结,后续可增加工单工序产出快照表,本方案暂不引入。
### 4.3 å­˜é‡æ•°æ®æ¸…理
```sql
-- 1) åˆ é™¤é‡å¤äº§å‡ºå½’属行,保留每组最小 id
DELETE o1 FROM mes_pro_route_process_output o1
JOIN mes_pro_route_process_output o2
  ON o1.route_process_id = o2.route_process_id
 AND o1.item_id = o2.item_id
 AND (o1.product_id = o2.product_id OR (o1.product_id IS NULL AND o2.product_id IS NULL))
 AND o1.id > o2.id;
-- 2) æ¯é“工序回填一个主产出(排序最小、同序取 id æœ€å°ï¼‰
UPDATE mes_pro_route_process_output o
JOIN (
    SELECT route_process_id, MIN(id) AS keep_id
    FROM (
        SELECT route_process_id, id,
               ROW_NUMBER() OVER (PARTITION BY route_process_id
                                  ORDER BY sort IS NULL, sort, id) AS rn
        FROM mes_pro_route_process_output
    ) t
    WHERE rn = 1
    GROUP BY route_process_id
) m ON m.keep_id = o.id
SET o.main_flag = 1;
```
> æ³¨ï¼šå¦‚果某道工序按不同归属产品配置了不同产出,主产出按全局取一条;运行时若当前产品过滤后不含该行,回退取排序第一条。
## 5. åŽç«¯æ”¹é€ æ¸…单
| æ–‡ä»¶ | æ”¹åЍ |
|------|------|
| `MesProRouteProcessOutputDO` | å¢žåŠ  `quantity`、`mainFlag` å­—段 |
| `MesProRouteProcessSaveReqVO.OutputItem` | å¢žåŠ  `quantity`、`mainFlag`;保存时校验主产出唯一、配比 > 0 |
| `MesProRouteProcessOutputVO` / `RespVO` | å“åº”增加 `quantity`、`mainFlag` |
| `MesProRouteProcessServiceImpl` | ä¿å­˜é…æ¯”/主产出;`resolveOutputItemId` æŒ‰ã€Œä¸»äº§å‡ºä¼˜å…ˆ + sort」拼接;`getOutputItemIdsByRouteProcessId` è¿”回顺序主产出优先;新增 `getProcessOutputs(routeProcessId, productId)` è¿”回 `itemId + ratio + mainFlag` |
| `MesProWorkOrderProcessServiceImpl.getProcessListByProductId` | å·²èµ° `getRouteProcessListByProductId`,保证 CSV ä¸»äº§å‡ºåœ¨é¦–位 |
| `MesProBatchScheduleService` | åˆ é™¤ã€Œå¤šä¸ªäº§å‡ºã€æŠ›é”™ï¼›ä»»åŠ¡ç‰©æ–™å–ä¸»äº§å‡ºï¼›é¢„è§ˆå¢žåŠ  warning「工序 X å« N ä¸ªè”产出,按主产出排产」 |
| `MesProTaskServiceImpl.resolveTaskItemId` | å–主产出(依赖上面的排序保证取第一个即主产出) |
| `MesWmProductProduceServiceImpl.generateProductProduce` | æŒ‰äº§å‡ºåˆ—表生成多行:每行 `itemId` = äº§å‡ºç‰©æ–™ï¼Œ`quantity` = æŠ¥å·¥æ•°é‡ Ã— é…æ¯”;批次按各自物料生成 |
| `MesWmProductProduceServiceImpl.splitPendingAndFinishProduce` | IPQC å®Œæˆæ—¶ï¼Œé™¤æºè¡Œå¤–按同一合格率拆分同产出单内其它待检行 |
| `MesProWorkOrderBomController.buildWorkOrderItems` | äº§å‡ºâ†’工序投料映射覆盖全部产出;联产出按「轮次 = max(需求量 / æ¯è½®äº§å‡ºé‡)」只展开一次,避免重复计算 |
| `MesProFeedbackServiceImpl` | ä¸å˜ï¼ˆæŠ¥å·¥ç‰©æ–™ä»ä¸ºä¸»äº§å‡ºï¼‰ï¼›å¦‚需在报工单展示联产出,仅做只读展示 |
| `MesWmItemConsumeServiceImpl` | ä¸å˜ï¼ˆä¸€æ¬¡æŠ¥å·¥æŒ‰å·¥åº BOM Ã— æŠ¥å·¥æ•°é‡æ‰£ä¸€æ¬¡æ–™ï¼Œå¤©ç„¶æ­£ç¡®ï¼‰ |
| `MesWmProductReceiptServiceImpl` | ä¸å˜ï¼ˆäº§å‡ºå•多行 â†’ å…¥åº“单多行,现有逻辑已支持) |
| `ErrorCodeConstants` | æ–°å¢žï¼š`PRO_ROUTE_PROCESS_OUTPUT_MAIN_REQUIRED`(1_040_501_104)、`PRO_ROUTE_PROCESS_OUTPUT_RATIO_INVALID`(_105)、`PRO_ROUTE_PROCESS_OUTPUT_MAIN_DUPLICATE`(_106) |
## 6. æ ¸å¿ƒç®—法
### 6.1 æ•°é‡æ¢ç®—
```
主产出:qty_main = feedbackQuantity
其它产出 i:qty_i = feedbackQuantity Ã— ratio_i
```
- é…æ¯”允许小数(如 0.5 kg / 1 ä¸ªï¼‰ï¼Œä¿ç•™ 6 ä½ã€‚
- ä¸åšå¼ºåˆ¶å–整;如需按物料计量单位取整,后续在产出生成处补充。
### 6.2 æ‰¹é‡æŽ’产
1. å·¥åºç›®æ ‡æ•°é‡ `targetQuantity` ä»æŒ‰æ”¶çŽ‡å€’æŽ¨ï¼ˆä¸»äº§å‡ºå£å¾„ï¼‰ã€‚
2. è§£æžè¯¥å·¥åºä¸»äº§å‡ºç‰©æ–™ï¼šä¼˜å…ˆå– `main_flag = 1` ä¸”归属当前产品的产出;没有则取排序第一条。
3. ä»»åŠ¡æ•°é‡ = `targetQuantity - å·²æŽ’任务数量`,任务物料 = ä¸»äº§å‡ºã€‚
4. ä¸å†å› ä¸ºå­˜åœ¨å…¶å®ƒäº§å‡ºè€ŒæŠ¥é”™ï¼›å…¶å®ƒäº§å‡ºä¸ç”Ÿæˆä»»åŠ¡ã€‚
5. é¢„览结果对多产出工序追加一条非阻断 warning æç¤ºã€‚
### 6.3 æŠ¥å·¥ â†’ äº§å‡ºå•
`generateProductProduce` å†…:
1. è§£æžäº§å‡ºåˆ—表:工单工序快照的 `output_item_id`(顺序即主产出优先)∩ è·¯çº¿é…æ¯”配置;缺失配比按 1。
2. æ— æ£€éªŒï¼šæ¯ä¸ªäº§å‡ºæŒ‰ã€Œåˆæ ¼æ•° / ä¸åˆæ ¼æ•°ã€å„生成一行(沿用现有拆分规则),数量各自乘配比。
3. éœ€è¦æ£€éªŒï¼šæ¯ä¸ªäº§å‡ºç”Ÿæˆä¸€æ¡ã€Œå¾…检验」行,等待 IPQC。
4. æ‰¹æ¬¡å·æŒ‰å„产出物料分别生成(沿用 `getOrGenerateBatchCode`)。
5. æ˜Žç»†è¡Œçš„仓库沿用 `resolveOutputTarget(workOrderId, processId, itemId, feedbackId)`:
   - å·¥å•工序配置了仓库 â†’ æ‰€æœ‰äº§å‡ºè¡Œéƒ½ç”¨è¯¥ä»“库;
   - å¦åˆ™æŒ‰äº§å‡ºç‰©æ–™æŸ¥è·¯çº¿äº§å“ä»“库;
   - æœ«é“工序仍要求实际仓库,中间工序仍可落虚拟线边库。
### 6.4 IPQC
- æ£€éªŒä»ä»¥ä¸»äº§å‡ºå¾…检行为源行(IPQC å•与报工单一一对应)。
- æ£€éªŒå®Œæˆæ—¶ï¼ŒæŒ‰ä¸»äº§å‡ºè¡Œçš„ `合格数 / å¾…检数量` å¾—到合格率 `r`,对同产出单内其它待检行执行:
  - `合格_i = è¡Œæ•°é‡ Ã— r`(保留 6 ä½ï¼‰ï¼›
  - `不合格_i = è¡Œæ•°é‡ - åˆæ ¼_i`。
- è¡Œæ•°é‡ä¸º 0 çš„产出不生成产出单行。
### 6.5 ç‰©æ–™éœ€æ±‚展开
`buildWorkOrderItems` è°ƒæ•´ï¼š
1. æ¯ä¸ªäº§å‡ºç‰©æ–™éƒ½å»ºç«‹ã€Œäº§å‡º â†’ æœ¬å·¥åºæŠ•料配方」映射(不再只取第一个)。
2. é€å±‚展开时,对属于同一工序的多个产出先按轮次归并:
   ```
   runs = max(各产出需求量 / è¯¥äº§å‡ºæ¯è½®äº§å‡ºé‡)
   æ¯è½®äº§å‡ºé‡ï¼šä¸»äº§å‡º = 1,其它产出 = ratio
   ```
   ç”¨ `runs` å±•开一次该工序投料,避免同工序产出分别展开导致物料重复。
3. åªæœ‰ä¸€ä¸ªäº§å‡ºçš„工序保持现有逻辑不变。
## 7. å‰ç«¯æ”¹é€ æ¸…单
| é¡µé¢ / æ–‡ä»¶ | æ”¹åЍ |
|-------------|------|
| `pro/route/components/output-attribution.vue` | æ¯è¡Œå¢žåŠ ã€Œé…æ¯”ã€InputNumber(默认 1、最小 0.000001)、「主产出」Radio;切换主产出时自动把上一行主产出取消 |
| `pro/route/data.ts` å·¥åºåˆ—表 | ã€Œæœ¬å·¥åºäº§å‡ºã€åˆ—展示 `名称 Ã— é…æ¯”`,主产出加标记 |
| å·¥å•创建/编辑 â†’ å·¥åºä¸Žäº§å‡º | å±•示联产出及配比(只读) |
| `pro/task/modules/schedule-form.vue` | ä¿®å¤ `item-id` ä¼ å…¥ï¼šå–工单工序输出的第一个 id(主产出),不要直接传逗号串 |
| æŽ’产预览弹窗 | å¤šäº§å‡ºå·¥åºæ˜¾ç¤ºæç¤ºæ–‡æ¡ˆï¼ˆéžé˜»æ–­ï¼‰ |
| ç”Ÿäº§äº§å‡ºå• / äº§å“å…¥åº“单 | çŽ°æœ‰åˆ—è¡¨æŒ‰è¡Œå±•ç¤ºï¼Œæ— éœ€æ–°é¡µé¢ï¼›ç¡®è®¤å¤šè¡Œæ­£å¸¸æ˜¾ç¤ºï¼Œæ¥æºåˆ—ä»æŒ‰äº§å‡ºå•å±•ç¤º |
## 8. å…¼å®¹æ€§ä¸Žè¾¹ç•Œ
| åœºæ™¯ | å¤„理 |
|------|------|
| å­˜é‡å·¥å•缺少主产出标记 | è¿è¡Œæ—¶å–排序第一条作为主产出 |
| å­˜é‡å·¥å•å¿«ç…§ CSV é¡ºåºä¸Žè·¯çº¿ä¸ä¸€è‡´ | ä»¥å¿«ç…§ CSV ç¬¬ä¸€æ¡ä¸ºä¸»äº§å‡ºï¼Œé…æ¯”按物料回查路线 |
| å‰¯äº§å‡ºåœ¨è·¯çº¿äº§å“ä¸Šæ²¡æœ‰ä»“库配置 | ä¼˜å…ˆç”¨å·¥å•工序仓库;中间工序回退虚拟线边库;末道工序仍要求实际仓库(与现有校验一致) |
| æŠ¥å·¥åªæŠ¥ä¸»äº§å‡ºæ•°é‡ | å‰¯äº§å‡ºæ•°é‡ç”±é…æ¯”推导,不允许单独修改(避免与主产出脱节) |
| å·¥åºåªæœ‰ä¸€ä¸ªäº§å‡º | å…¨éƒ¨é€»è¾‘退化为现有行为 |
| åŒä¸€å·¥åºå·²æœ‰åŽ†å²ä»»åŠ¡ï¼ˆå¤šä»»åŠ¡ï¼‰ | ä¸è‡ªåŠ¨åˆå¹¶ï¼›æ–°æŽ’äº§ä»æŒ‰ã€Œå·²æœ‰ä»»åŠ¡æ•°é‡åˆè®¡ã€è®¡ç®—å‰©ä½™é‡ |
| äº§å‡ºå½’属重复行 | ç”±è¿ç§»è„šæœ¬æ¸…ç†ï¼›æœåŠ¡å±‚ä¿å­˜æ—¶æŒ‰ `productId + itemId` åŽ»é‡ï¼ˆå·²æœ‰é€»è¾‘ï¼‰ |
## 9. è¿ç§»è„šæœ¬
目录:`scripts/process-multi-output-20261107/`
- `01_ddl.sql`:加 `quantity`、`main_flag` åˆ—
- `02_cleanup.sql`:清理重复产出行 + å›žå¡«ä¸»äº§å‡º
脚本不包含 `tenant_id`(本项目不使用多租户)。
## 10. éªŒæ”¶æ¸…单
1. å·¥è‰ºè·¯çº¿ã€Œé“èŠ¯å è£…ã€é…ç½® 2 ä¸ªäº§å‡ºï¼Œå…¶ä¸­ 1 ä¸ªä¸»äº§å‡ºã€é…æ¯”分别为 1 / 2,保存成功;配置两个主产出时被拦截。
2. æ–°å»ºå·¥å•并生成工序,快照 `output_item_id` ä¸»äº§å‡ºåœ¨ç¬¬ä¸€ä½ã€‚
3. ä¸€é”®æŽ’产预览通过,生成 1 ä¸ªä»»åŠ¡ï¼Œç‰©æ–™ä¸ºä¸»äº§å‡ºï¼Œæ•°é‡ = å·¥å•数量。
4. æŠ¥å·¥ 100,产出单生成 2 è¡Œï¼šä¸»äº§å‡º 100、副产出 200(配比 2)。
5. äº§å“å…¥åº“单生成 2 è¡Œï¼Œæ•°é‡å’Œä»“库正确。
6. å¼€å¯ IPQC:检验主产出合格 90/100,产出单两行按 90% æ‹†åˆ†ï¼ˆ90/10、180/20)。
7. å·¥å•已生产数量只增加 100,不重复累加。
8. æŠ¥å·¥è‡ªåŠ¨æ‰£æ–™ï¼šæŒ‰å·¥åº BOM Ã— 100 æ‰£ä¸€æ¬¡ï¼Œä¸å› å¤šäº§å‡ºé‡å¤æ‰£æ–™ã€‚
9. ç‰©æ–™éœ€æ±‚展开不重复计算该工序投料。
10. å­˜é‡å•产出工序功能回归正常。
## 11. å®žæ–½é¡ºåº
1. DDL + DO/VO + è·¯çº¿ä¿å­˜/读取(含主产出、配比、排序)
2. æ•°æ®æ¸…理脚本 + å­˜é‡å›žå¡«
3. æŽ’产解锁(`MesProBatchScheduleService`、前端 schedule-form ä¿®å¤ï¼‰
4. æŠ¥å·¥äº§å‡ºå•多行 + IPQC æ‹†åˆ†
5. å…¥åº“回归
6. ç‰©æ–™éœ€æ±‚展开联产出归并
7. å‰ç«¯äº§å‡ºé…ç½®ã€åˆ—表展示、提示
## 12. å¾…确认
1. è”产出的质检是否全部跟随主产出合格率(本方案默认跟随)。
2. æŠ¥å·¥ç•Œé¢æ˜¯å¦éœ€è¦å±•示联产出明细(本方案默认只展示主产出,产出单里体现)。
3. é…æ¯”是否允许按工单覆盖(本方案默认只在工艺路线维护,工单只读)。
docs/product_receipt_stock_timing.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,49 @@
# äº§å“å…¥åº“库存记账时点调整 - å‰ç«¯è”调方案
## æ¶‰åŠé¡µé¢
- äº§å“å…¥åº“(列表、提交、执行上架、执行入库)
- åº“存事务流水
- åº“存台账 / ç‰©æ–™åº“å­˜
## ä¸šåŠ¡èƒŒæ™¯
此前报工审批生成产出单后,产出单完成时就把成品直接记入实际仓库库存,导致「产品入库单还未提交、未执行上架、未执行入库」时,库存事务流水里已经出现产品产出入库记录、库存数量也已增加。
调整后统一为:**产品入库单执行入库时才登记实际仓库库存**,与采购入库的执行入库口径一致。
## è®°è´¦è§„则
| åœºæ™¯ | è®°è´¦æ—¶ç‚¹ | è¯´æ˜Ž |
|------|----------|------|
| ä¸­é—´å·¥åºäº§å‡ºåˆ°è™šæ‹Ÿçº¿è¾¹åº“ | æŠ¥å·¥å®¡æ‰¹ç”Ÿæˆäº§å‡ºå•并完成时 | è½¦é—´åœ¨åˆ¶åº“存,下道工序倒冲领用依赖该库存,保持立即记账 |
| äº§å‡ºåˆ°å®žé™…仓库(成品/半成品) | äº§å“å…¥åº“单「执行入库」时 | äº‹åŠ¡ç±»åž‹ `产品产出` ä¸å†äº§ç”Ÿå®žé™…仓库入库;改为 `生产入库` å…¥åº“事务 |
| è‡ªåŠ¨ç”Ÿæˆçš„äº§å“å…¥åº“å•ï¼ˆAUTO-PR-*) | æ‰§è¡Œå…¥åº“æ—¶ | ä»…登记实际仓库入库 |
| æ‰‹å·¥åˆ›å»ºçš„产品入库单 | æ‰§è¡Œå…¥åº“æ—¶ | ä¿æŒã€Œè™šæ‹Ÿçº¿è¾¹åº“出库 + å®žé™…仓库入库」 |
## API
接口路径、请求参数、响应结构均无变化。
## å­—段展示规则
| å­—段 | å±•示位置 | å˜åŒ–说明 |
|------|----------|----------|
| åº“存事务流水 | åº“存事务流水页面 | äº§å‡ºåˆ°å®žé™…仓库的记录,业务类型由「产品产出」变为「生产入库」,且时间点变为执行入库时间 |
| åº“存数量 | åº“存台账、物料库存 | æˆå“/半成品库存在执行入库后才增加 |
| äº§å“å…¥åº“单明细仓库 | äº§å“å…¥åº“详情 | ä»ä¸ºé¢„填的目标仓库,执行入库时按明细最终仓库记账 |
## ä¸šåŠ¡è§„åˆ™è¯´æ˜Ž
| åœºæ™¯ | è§„则 |
|------|------|
| äº§å“å…¥åº“单为草稿 / å¾…上架 / å¾…执行入库 | å®žé™…仓库库存不变,不产生库存事务流水 |
| æ‰§è¡Œå…¥åº“ | æŒ‰ä¸Šæž¶æ˜Žç»†çš„实际仓库、库位、库区登记入库事务,并增加库存 |
| è‡ªåŠ¨å…¥åº“å•å­˜åœ¨æ˜Žç»†æŒ‡å‘è™šæ‹Ÿçº¿è¾¹åº“ | è·³è¿‡è®°è´¦ï¼ˆäº§å‡ºå•完成时已记账),避免重复 |
| äº§å‡ºåˆ°è™šæ‹Ÿçº¿è¾¹åº“(中间工序) | ä»ç«‹å³è®°è´¦ï¼Œå¦åˆ™ä¸‹é“工序倒冲会报「库存不足」 |
## æ³¨æ„äº‹é¡¹
- åŽ†å²æœªå®Œæˆçš„è‡ªåŠ¨å…¥åº“å• AUTO-PR-37 å·²æŒ‰ `scripts/product-receipt-stock-timing-20261107/01_cleanup_early_transactions.sql` å†²é”€æå‰è®°è´¦çš„库存与事务,后续执行入库会正常入账。
- AUTO-PR-36 ç¼ºå°‘上架明细无法执行入库,其提前记账的库存暂未冲销;如需补齐明细后入库,须先按脚本注释冲销对应事务,否则会重复记账。
- å·²å®Œæˆçš„入库单不受影响,不重复记账。
docs/production_feedback_qc_fix_plan.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,270 @@
# ç”Ÿäº§æŠ¥å·¥è‡ªåŠ¨æ‰£æ–™ / è´¨æ£€æµè½¬ / äº§å‡ºå…¥åº“ ä¿®æ”¹æ–¹æ¡ˆ
> èŒƒå›´ï¼šMES ç”Ÿäº§æŠ¥å·¥ï¼ˆfeedback)审批 â†’ å€’冲扣料 â†’ è¿‡ç¨‹æ£€éªŒï¼ˆIPQC)→ äº§å‡ºå…¥åº“
> çŠ¶æ€ï¼šå¾…è¯„å®¡
> æ¶‰åŠæ¨¡å—:`yudao-module-mes`(pro / qc / wm)
## ä¸€ã€èƒŒæ™¯
当前报工链路已实现自动化,但在以下环节存在数据正确性与流程闭环问题:
- è‡ªåŠ¨æ‰£æ–™ï¼ˆå€’å†²ï¼‰ç¼ºå°‘å¯ç”¨é‡æ ¡éªŒï¼Œä¸”ä¸åˆæ ¼å“/中间工序的账务口径不清晰
- è´¨æ£€å®Œæˆå›žè°ƒæ²¡æœ‰å›žå†™ä»»åŠ¡ã€å·¥å•ã€MPS æ•°é‡
- è¿‡ç¨‹æ£€éªŒæ•°é‡æ²¡æœ‰ä¸Šé™æ ¡éªŒï¼Œä¸”不合格品按正常品入账
- äº§å‡ºå…¥åº“在末道工序未配置产出仓库时,成品滞留虚拟线边库
- ã€Œæ²¡æœ‰è´¨æ£€æ–¹æ¡ˆã€æ—¶ï¼ŒæŠ¥å·¥è¿›å…¥å¾…检后无法创建过程检验单,永久卡在待检状态
本文档汇总问题、根因与修改方案,供评审后实施。
## äºŒã€çŽ°çŠ¶é“¾è·¯
### 2.1 æ— è´¨æ£€ï¼ˆå·¥åº checkFlag = 0)
```
报工审批 approveFeedback
  â””─ å€’冲工序? â”€â”€ æ˜¯ â†’ ç”Ÿæˆæ¶ˆè€—单 + æ‰£çº¿è¾¹åº“ + ç”Ÿæˆå€’冲领料凭证
  â””─ ç”Ÿæˆäº§å‡ºå•(按合格/不合格拆行 + æ˜Žç»†ï¼‰
  â””─ finishProductProduce
       â”œâ”€ ä¸ºã€Œæ‰€æœ‰è¡Œã€åˆ›å»º IN åº“存事务(含不合格行)
       â”œâ”€ æ›´æ–°äº§å‡ºå•为已完成
       â””─ è‹¥ä¸ºæœ«é“工序 â†’ ç”Ÿæˆäº§å“å…¥åº“单(仅合格行,状态=草稿)
报工完成
```
### 2.2 æœ‰è´¨æ£€ï¼ˆå·¥åº checkFlag = 1)
```
报工审批 approveFeedback
  â””─ å€’冲扣料(同上,扣料发生在质检之前)
  â””─ ç”Ÿæˆäº§å‡ºå•:只建一条「待检验」行,不建明细
  â””─ æŠ¥å·¥çŠ¶æ€ â†’ å¾…检验
待检任务页(quality_status = å¾…检验 çš„产出行)
  â””─ åˆ›å»ºè¿‡ç¨‹æ£€éªŒå•(需物料已配置 IPQC æ£€éªŒæ¨¡æ¿ï¼‰
  â””─ å®Œæˆæ£€éªŒ finishIpqc
       â”œâ”€ æŒ‰åˆæ ¼/不合格拆待检行、生成明细
       â”œâ”€ finishProductProduce(入库,末道生成入库单)
       â”œâ”€ å›žå†™æŠ¥å·¥åˆæ ¼/不合格/废品数量,状态 â†’ å·²å®Œæˆ
       â””─ ä¸åˆæ ¼è‡ªåŠ¨ç”Ÿæˆ NCR
```
## ä¸‰ã€é—®é¢˜æ±‡æ€»
| ç¼–号 | ä¼˜å…ˆçº§ | æ¨¡å— | é—®é¢˜æ‘˜è¦ |
|---|---|---|---|
| Q1 | P0 | è´¨æ£€å›žå†™ | è´¨æ£€å®Œæˆå›žè°ƒæœªæ›´æ–°ä»»åŠ¡/工单/MPS æ•°é‡ |
| Q2 | P0 | æŠ¥å·¥ | å…³é”®å·¥åºæ•°é‡æ›´æ–°æ—¶ç‚¹æ—©äºŽäº§å‡ºå•生成,合格/不合格恒为 0 |
| Q3 | P1 | æŠ¥å·¥ | æœ«é“工序若非关键工序,工单/MPS å·²ç”Ÿäº§æ•°é‡æ°¸ä¸ç´¯åŠ  |
| Q4 | P1 | æŠ¥å·¥ | è·¯çº¿å·¥åºæŸ¥ä¸åˆ°æ—¶ï¼Œé™é»˜é™çº§ä¸ºã€Œä¸è´¨æ£€ã€ä¸æ‰£æ–™ã€ |
| Q5 | P0 | è¿‡ç¨‹æ£€éªŒ | è´¨æ£€æ•°é‡æ— ä¸€è‡´æ€§/上限校验,可超量入库 |
| Q6 | P0 | è¿‡ç¨‹æ£€éªŒ/入库 | ä¸åˆæ ¼å“ä¹ŸæŒ‰æ­£å¸¸å“åˆ›å»ºå…¥åº“事务,混入可用库存 |
| Q7 | P1 | è¿‡ç¨‹æ£€éªŒ | å…¨éƒ¨ä¸åˆæ ¼æˆ–合格数为 0 æ—¶äº§ç”Ÿ 0 æ•°é‡è„æ•°æ® |
| Q8 | P1 | è¿‡ç¨‹æ£€éªŒ | åŒä¸€å¾…检行可重复创建多张检验单 |
| Q9 | P2 | è¿‡ç¨‹æ£€éªŒ | æ‰‹å·¥/导入创建的检验单靠 taskId å…œåº•回写,可能串单或失败 |
| Q10 | P1 | è¿‡ç¨‹æ£€éªŒ | æ— æ£€éªŒæ¨¡æ¿æ—¶åˆ›å»ºæŠ¥é”™ä¸æ˜Žç¡®ï¼›æŠ¥å·¥å¡åœ¨å¾…检 |
| P1 | P0 | äº§å‡ºå…¥åº“ | æœ«é“工序未配置产出仓时,成品滞留虚拟线边库 |
| P2 | P1 | äº§å‡ºå…¥åº“ | è‡ªåŠ¨å…¥åº“å•åªå»ºè¡Œä¸å»ºæ˜Žç»†ï¼Œæ‰§è¡Œå…¥åº“å¿…ç„¶å¤±è´¥ |
| P3 | P2 | äº§å‡ºå…¥åº“ | å¾…检期间产品完全不入账(账外) |
| D1 | P1 | è‡ªåŠ¨æ‰£æ–™ | å€’冲扣料无可用量校验,线边库可被扣成负数 |
| D2 | P2 | è‡ªåŠ¨æ‰£æ–™ | åŒä¸€å·¥åº BOM å‡ºçŽ°åŒä¸€ç‰©æ–™å¤šè¡Œæ—¶ï¼Œé‡å¤å ç”¨åŒä¸€æ‰¹æ¬¡ |
## å››ã€ä¿®æ”¹æ–¹æ¡ˆ
### Q1 è´¨æ£€å®Œæˆå›žè°ƒè¡¥å›žå†™ä»»åŠ¡/工单/MPS
- ä½ç½®ï¼š`MesProFeedbackServiceImpl.java:632-658`
- çŽ°è±¡ï¼šæ–¹æ³•æ³¨é‡Šå†™ç€ã€Œ4. æ›´æ–°ä»»åŠ¡/工单的已生产数量」,但只对内存对象 `set` äº†ä¸¤ä¸ªå­—段,没有调用 `updateTaskAndWorkOrderByFeedback`。结果质检工序的合格/不合格数不进任务;末道工序为质检工序时,工单 `quantity_produced` ä¸Ž MPS `quantity_produced` ä¸ç´¯åŠ ï¼ŒMPS/销售订单的「生产完成」判定永远不满足。
- æ–¹æ¡ˆï¼š
  1. ç¬¬ 5 æ­¥ä¹‹å‰é‡æ–°è¯»å–报工单最新数据(状态已改为已完成,且数量已回写)。
  2. è°ƒç”¨ä¸Žç›´æŽ¥å…¥åº“分支统一的进度更新方法 `updateTaskAndWorkOrderByFeedback(feedback)`。
  3. åˆ é™¤ç¬¬ 655 è¡Œæ— æ•ˆçš„ `feedback.setQualifiedQuantity(...)` è°ƒç”¨ã€‚
- å½±å“ï¼šä»»åŠ¡ã€å·¥å•ã€MPS、销售订单生产完成事件的数量口径修正。
### Q2 ä¿®æ­£å…³é”®å·¥åºæ•°é‡æ›´æ–°æ—¶ç‚¹
- ä½ç½®ï¼š`MesProFeedbackServiceImpl.java:330-360`
- çŽ°è±¡ï¼š`keyFlag=true` æ—¶å…ˆè°ƒç”¨ `updateTaskAndWorkOrderByFeedback`,而该方法是按 `feedbackId` èšåˆäº§å‡ºå•行计算合格/不合格数;此时产出单尚未生成,聚合结果恒为 0。
- æ–¹æ¡ˆï¼ˆäºŒé€‰ä¸€ï¼ŒæŽ¨èæ–¹æ¡ˆ A):
  - **A(统一收口)**:把「任务/工单/MPS è¿›åº¦æ›´æ–°ã€ä»Ž `approveFeedback` ä¸­ç§»é™¤ï¼Œç»Ÿä¸€æ”¾åˆ°äº§å‡ºå•生成/完成之后执行;无质检在 `finishProductProduce` ä¹‹åŽè°ƒç”¨ï¼Œæœ‰è´¨æ£€åœ¨ `updateProFeedbackWhenIpqcFinish` ä¸­è°ƒç”¨ã€‚`approveFeedback` åªè´Ÿè´£æ‰£æ–™ã€ç”Ÿæˆäº§å‡ºå•和状态流转。
  - **B(分层更新)**:`approveFeedback` åªç´¯åŠ  `producedQuantity`(不依赖产出单),合格/不合格数在产出单完成后单独累加。
- å½±å“ï¼šå…³é”®å·¥åºçš„任务合格数、不合格数恢复正确。
### Q3 æœ«é“工序工单/MPS æ›´æ–°ä¸Ž keyFlag è§£è€¦
- ä½ç½®ï¼š`MesProFeedbackServiceImpl.java:338-347`
- çŽ°è±¡ï¼šå·¥å• `quantity_produced` å’Œ MPS `quantity_produced` çš„累加被放在 `keyFlag=true` åˆ†æ”¯å†…,且内部再判断是否末道工序。若末道工序未配置「关键工序」,工单产出永远为 0。
- æ–¹æ¡ˆï¼šå°†ã€Œæ˜¯å¦æœ«é“工序」判断独立出来;只要本次报工工序是末道工序,无论 `keyFlag` ä¸Žå¦éƒ½æ›´æ–°å·¥å•/MPS。`keyFlag` åªå½±å“æ˜¯å¦éœ€è¦é‡å¤ç´¯åŠ ä¸­é—´å·¥åºäº§å‡ºï¼ˆæŒ‰çŽ°æœ‰ä¸šåŠ¡æ„å›¾ä¿ç•™ï¼‰ã€‚
- éœ€ç¡®è®¤ï¼šä¸­é—´å·¥åºæ˜¯å¦è®¡å…¥å·¥å•产出。若不计入,则仅末道工序累加;若计入,则所有工序都累加,二者只保留一种口径。
### Q4 è·¯çº¿å·¥åºç¼ºå¤±ä¸å†é™é»˜é™çº§
- ä½ç½®ï¼š`MesProFeedbackServiceImpl.java:300-314`
- çŽ°è±¡ï¼š`getRouteProcessByRouteIdAndProcessId` è¿”回 null æ—¶ï¼Œ`keyFlag`、`checkFlag`、`backflushFlag` å…¨éƒ¨æŒ‰ false å¤„理,既不扣料也不进质检,且没有任何提示。
- æ–¹æ¡ˆï¼š
  1. æŸ¥è¯¢ä¸åˆ°è·¯çº¿å·¥åºæ—¶æŠ›å‡ºä¸šåŠ¡å¼‚å¸¸ï¼ˆæç¤ºã€ŒæŠ¥å·¥å·¥åºæœªåœ¨å·¥è‰ºè·¯çº¿ä¸­æ‰¾åˆ°ï¼Œè¯·æ£€æŸ¥å·¥å•å·¥è‰ºè·¯çº¿é…ç½®ã€ï¼‰ã€‚
  2. è‹¥ä¸šåŠ¡å…è®¸åŽ†å²æ•°æ®å­˜åœ¨ï¼Œåˆ™è‡³å°‘è®°å½• error æ—¥å¿—并在接口返回中提示,禁止静默。
- å½±å“ï¼šé¿å…å› é…ç½®ç¼ºå¤±å¯¼è‡´ææ–™ä¸æ‰£ã€è´¨æ£€è·³è¿‡å´æ— äººå‘现。
### Q5 è¿‡ç¨‹æ£€éªŒæ•°é‡ä¸€è‡´æ€§æ ¡éªŒ
- ä½ç½®ï¼š`MesQcIpqcServiceImpl.java:225-244`;`MesWmProductProduceServiceImpl.java:270-325`
- çŽ°è±¡ï¼šå®Œæˆæ£€éªŒåªæ ¡éªŒã€Œæ£€æµ‹ç»“è®ºéžç©º + è‡³å°‘一条检测项」,不校验:
  - `检测数量 = åˆæ ¼æ•°é‡ + ä¸åˆæ ¼æ•°é‡`
  - `检测数量 â‰¤ å¾…检产出行数量`
- åŽæžœï¼šå¯å¡«å‡ºè¶…过报工数量的合格数,拆行后按填报数生成入库明细,造成超量入库。
- æ–¹æ¡ˆï¼š`finishIpqc` åœ¨æ›´æ–°çŠ¶æ€å‰å¢žåŠ æ ¡éªŒï¼š
  1. åˆæ ¼æ•°ã€ä¸åˆæ ¼æ•°ä¸å¾—为负。
  2. åˆæ ¼æ•° + ä¸åˆæ ¼æ•° = æ£€æµ‹æ•°é‡ã€‚
  3. è‹¥æ¥æºä¸ºæŠ¥å·¥äº§å‡ºè¡Œï¼Œæ£€æµ‹æ•°é‡ä¸å¾—大于该待检行的数量。
  4. æ ¡éªŒå¤±è´¥è¿”回明确错误码(新增 `QC_IPQC_QUANTITY_MISMATCH`、`QC_IPQC_QUANTITY_EXCEEDS_SOURCE`)。
- åŒæ­¥ï¼š`MesWmProductProduceServiceImpl#splitPendingAndFinishProduce` å¢žåŠ å…œåº•æ ¡éªŒï¼Œé˜²æ­¢ç»•è¿‡ IPQC ç›´æŽ¥è°ƒç”¨ã€‚
### Q6 ä¸åˆæ ¼å“ä¸å¾—按正常品入账
- ä½ç½®ï¼š`MesWmProductProduceServiceImpl.java:96、110-134`;`MesWmProductReceiptServiceImpl.java:106-112`
- çŽ°è±¡ï¼š`finishProductProduce` å¯¹ä¸Šæ‰€æœ‰äº§å‡ºå•行创建 IN äº‹åŠ¡ï¼ˆå« `FAIL` è¡Œï¼‰ï¼Œä»“库为正常产出仓/线边库;而产品入库单只对 `PASS` è¡Œç”Ÿæˆã€‚结果不合格品有库存、无单据,与合格品混放,可被后续领用或发货。NCR åªå»ºå•,不做库存隔离。
- æ–¹æ¡ˆï¼ˆéœ€ä¸šåŠ¡ç¡®è®¤ï¼ŒäºŒé€‰ä¸€ï¼‰ï¼š
  - **A(推荐)不合格品入不良品仓**:`resolveOutputTarget` å¢žåŠ æŒ‰è´¨é‡çŠ¶æ€é€‰æ‹©ä»“åº“ï¼›`FAIL` è¡Œé»˜è®¤å…¥ä¸è‰¯å“ä»“(可配置),`PASS` è¡Œå…¥æ­£å¸¸äº§å‡ºä»“。
  - **B ä¸åˆæ ¼å“ä¸å…¥è´¦**:只对 `PASS` è¡Œåˆ›å»º IN äº‹åŠ¡ï¼Œ`FAIL` è¡Œä»…保留产出记录,由 NCR åŽç»­å¤„置(返工/报废)时再走库存事务。
- æ— è®ºå“ªç§ï¼Œéƒ½è¦æ±‚「库存事务行」与「入库单行」口径一致。
### Q7 å…¨éƒ¨ä¸åˆæ ¼/零数量不再产生脏数据
- ä½ç½®ï¼š`MesWmProductProduceServiceImpl.java:282-321`
- çŽ°è±¡ï¼šåˆæ ¼æ•°ä¸º 0 æ—¶ï¼Œå¾…检行仍被改成 `PASS`、数量 0,并生成 0 æ•°é‡æ˜Žç»†å’Œ 0 æ•°é‡å…¥åº“事务。
- æ–¹æ¡ˆï¼š
  1. åˆæ ¼æ•°ä¸º 0 ä¸”不合格数 > 0 æ—¶ï¼Œå¾…检行直接标记为 `FAIL`,不生成合格明细。
  2. æ•°é‡ä¸º 0 çš„行不创建明细、不创建库存事务。
  3. è‹¥åˆæ ¼æ•°ä¸Žä¸åˆæ ¼æ•°å‡ä¸º 0,完成检验直接报错。
### Q8 é˜²æ­¢åŒä¸€å¾…检行重复建检验单
- ä½ç½®ï¼šäº§å‡ºè¡Œ DO;`MesQcIpqcServiceImpl.java:368-371`
- çŽ°è±¡ï¼šäº§å‡ºè¡Œæ²¡æœ‰å’Œ IPQC çš„关联字段,创建时只校验 `PENDING`。第一张检验单完成前可重复创建多张;第二张完成时因产出单已完成抛异常回滚,留下无法完成的检验单。
- æ–¹æ¡ˆï¼š
  1. `mes_wm_product_produce_line` å¢žåŠ  `ipqc_id`(BIGINT,可空)。
  2. `createIpqc` æ ¡éªŒäº§å‡ºè¡Œ `ipqc_id` ä¸ºç©ºï¼›åˆ›å»ºæˆåŠŸåŽå›žå†™ `ipqc_id`。
  3. å¾…检任务 SQL å¢žåŠ  `ppl.ipqc_id IS NULL` è¿‡æ»¤ã€‚
  4. åˆ é™¤æ£€éªŒå•时清除 `ipqc_id`(仅草稿状态允许删除)。
- æ•°æ®åº“变更见第六节。
### Q9 æ‰‹å·¥/导入创建的检验单回写可靠性
- ä½ç½®ï¼š`MesQcIpqcServiceImpl.java:279-297`
- çŽ°è±¡ï¼šæ²¡æœ‰æ¥æºå•æ®æ—¶ï¼ŒæŒ‰ `taskId` æ‰¾ç¬¬ä¸€å¼ ã€Œå¾…检验」报工兜底。同一任务多张待检会串单;`sourceLineId` ä¸ºç©ºæ—¶æ‹†åˆ†ç›´æŽ¥æŠ›å¼‚常。
- æ–¹æ¡ˆï¼š
  1. æ¥æºä¸ºæŠ¥å·¥æ—¶å¼ºåˆ¶è¦æ±‚ `sourceDocId` + `sourceLineId`(前端只允许从待检任务页发起)。
  2. ç§»é™¤æŒ‰ `taskId` çŒœæµ‹å›žå†™çš„逻辑,改为无法定位来源时明确报错或跳过并记录 warning。
  3. å¯¼å…¥åˆ›å»ºçš„æ£€éªŒå•不允许关联来源,完成后不推进报工(保持现状但打日志)。
### Q10 æ— æ£€éªŒæ¨¡æ¿æ—¶çš„æç¤ºä¸ŽçŠ¶æ€å¤„ç†
- ä½ç½®ï¼š`MesQcIpqcServiceImpl.java:140-143`;`MesQcTemplateItemServiceImpl.java:118-141`
- çŽ°è±¡ï¼šç‰©æ–™æœªé…ç½® IPQC æ¨¡æ¿æ—¶åˆ›å»ºæ£€éªŒå•抛 `QC_NO_TEMPLATE`,现场难以定位;报工已进入待检,若无法创建检验单会永久卡住。
- æ–¹æ¡ˆï¼š
  1. æŠ¥é”™æ–‡æ¡ˆæ˜Žç¡®ä¸ºã€Œç‰©æ–™ã€xxx】未配置 IPQC æ£€éªŒæ–¹æ¡ˆï¼Œè¯·å…ˆåœ¨è´¨æ£€æ¨¡æ¿ä¸­ä¸ºè¯¥ç‰©æ–™å¯ç”¨è¿‡ç¨‹æ£€éªŒã€ã€‚
  2. å¾…检任务列表增加「是否可检验」提示(依据模板匹配结果),避免用户盲目点创建。
  3. æŠ¥å·¥å®¡æ‰¹æ—¶è‹¥å·¥åº `checkFlag=1`,增加一次模板存在性预检,缺失时在审批前直接提示(避免报工进入待检后才失败)。
- éœ€ç¡®è®¤ï¼šæ˜¯å¦å…è®¸ã€Œæ— æ¨¡æ¿ä½†æœ‰å·¥åºæ£€éªŒæ ‡è¯†ã€çš„æŠ¥å·¥ç›´æŽ¥æ”¾è¡Œå¹¶è®°ä¸ºå…æ£€ã€‚
### P1 æœ«é“工序产出仓兜底策略
- ä½ç½®ï¼š`MesWmProductProduceServiceImpl.java:327-354`;`MesWmProductReceiptServiceImpl.java:269-273`
- çŽ°è±¡ï¼šæœ«é“å·¥åºæœªé…ç½®äº§å‡ºä»“æ—¶å›žé€€è™šæ‹Ÿçº¿è¾¹åº“ï¼›äº§å‡ºäº‹åŠ¡è®°å…¥çº¿è¾¹åº“ï¼Œè‡ªåŠ¨å…¥åº“å•åˆå›  `produceId != null` è·³è¿‡è½¬ç§»äº‹åŠ¡ï¼Œæˆå“æ°¸è¿œç•™åœ¨çº¿è¾¹åº“ï¼Œä¸ä¼šè¿›å…¥æˆå“ä»“ã€‚
- æ–¹æ¡ˆï¼ˆæŽ¨è A):
  - **A å¼ºåˆ¶é…ç½®**:末道工序必须配置报工仓库(工单工序或工艺路线产品),`resolveOutputTarget` åœ¨æœ«é“工序不允许回退虚拟线边库,缺失时审批报错。
  - **B è‡ªåŠ¨è½¬ç§»**:自动入库单完成时,若明细仓库为虚拟线边库,补做「线边库 OUT + å®žé™…仓 IN」;需要入库单能确定目标成品仓。
- åŒæ—¶æ˜Žç¡®ï¼šä¸­é—´å·¥åºäº§å‡ºæ˜¯å¦å…è®¸è¿›å®žé™…仓。若允许,应同步生成对应的半成品入库单,避免「有库存无单据」。
### P2 è‡ªåŠ¨å…¥åº“å•è¡¥é½æ˜Žç»†
- ä½ç½®ï¼š`MesWmProductReceiptServiceImpl.java:160-168`;`finishProductReceipt` æ˜Žç»†éžç©ºæ ¡éªŒ `:264-267`
- çŽ°è±¡ï¼šè‡ªåŠ¨ç”Ÿæˆçš„äº§å“å…¥åº“å•åªæœ‰è¡Œã€æ²¡æœ‰æ˜Žç»†ï¼Œæ‰§è¡Œå…¥åº“ä¼šå› ã€Œæ— æ˜Žç»†ã€å¤±è´¥ï¼Œå¿…é¡»äººå·¥è¡¥ã€‚
- æ–¹æ¡ˆï¼š`generateProductReceipt` ç”Ÿæˆè¡Œçš„同时,按产出单明细生成入库明细(仓库、库位、库区、批次、数量均可从 `mes_wm_product_produce_detail` å¸¦å‡ºï¼‰ã€‚若采用 P1-A(产出直接入成品仓),则入库单仅作业务凭证,需在页面上明确标识「自动单据,无需执行入库」,或改为由产出单直接生成已完成入库单。
### P3 å¾…检期间产品不入账(设计权衡)
- ä½ç½®ï¼š`MesWmProductProduceServiceImpl.java:190-195`
- çŽ°è±¡ï¼š`checkFlag=true` æ—¶ä¸ç”Ÿæˆä»»ä½•库存事务,产品在待检期间处于账外状态。
- æ–¹æ¡ˆï¼šå¦‚需严格库存管理,可在审批时先将待检数量入「待检仓」,质检完成后做「待检仓 â†’ åˆæ ¼ä»“ / ä¸è‰¯å“ä»“」转移;若接受当前口径,则在文档与报表中说明待检产品不计库存。
### D1 å€’冲扣料可用量校验
- ä½ç½®ï¼š`MesWmItemConsumeServiceImpl.java:126-159、192`
- çŽ°è±¡ï¼šçº¿è¾¹åº“æ— åº“å­˜æˆ–ä¸è¶³æ—¶ä»ç”Ÿæˆæ— æ‰¹æ¬¡æ˜Žç»†ï¼Œä¸”åº“å­˜äº‹åŠ¡ `checkFlag=false` å…è®¸è´Ÿåº“存,扣成负数无提示。
- æ–¹æ¡ˆï¼š
  1. ä¸¥æ ¼æ¨¡å¼ï¼šå€’冲前校验线边库可用量,不足时报错并提示「请先执行生产领料」。
  2. å®½æ¾æ¨¡å¼ï¼ˆè‹¥ä¸šåŠ¡å…è®¸è´Ÿåº“å­˜ï¼‰ï¼šä¿ç•™æ‰£å‡ï¼Œä½†è¿”å›ž/记录预警,并在报工审批结果中提示可用量不足。
- éœ€ç¡®è®¤ï¼šçº¿è¾¹åº“是否允许负库存。建议默认严格模式。
### D2 åŒä¸€ç‰©æ–™å¤šè¡Œé‡å¤å ç”¨æ‰¹æ¬¡
- ä½ç½®ï¼š`MesWmItemConsumeServiceImpl.java:126-159`
- çŽ°è±¡ï¼šæ¯æ¡æ¶ˆè€—è¡Œç‹¬ç«‹æŸ¥è¯¢åº“å­˜å¿«ç…§åš FIFO,同一工序 BOM è‹¥å‡ºçŽ°åŒä¸€ç‰©æ–™å¤šè¡Œï¼Œä¼šé‡å¤å ç”¨åŒä¸€æ‰¹æ¬¡ã€‚
- æ–¹æ¡ˆï¼š
  1. æœåŠ¡ç«¯æ ¡éªŒåŒä¸€å·¥åº BOM ç‰©æ–™ä¸å¯é‡å¤ï¼ˆä¿å­˜æ—¶æŠ¥é”™ï¼‰ã€‚
  2. æ¶ˆè€—生成时按 `itemId` åˆå¹¶åŽå†åˆ†é…æ‰¹æ¬¡ã€‚
  3. æˆ–者在内存中维护「已分配量」,每条行的可用量 = åº“存数量 - å·²åˆ†é…é‡ã€‚
## äº”、需要确认的业务决策
| ç¼–号 | å†³ç­–点 | å¤‡é€‰ |
|---|---|---|
| 1 | ä¸åˆæ ¼å“åº“存去向 | å…¥ä¸è‰¯å“ä»“ / ä¸å…¥è´¦ç”± NCR å¤„ç½® / å†»ç»“ |
| 2 | å·¥å•已生产数量口径 | åªç´¯è®¡æœ«é“工序 / ç´¯è®¡æ‰€æœ‰å·¥åº |
| 3 | æœ«é“工序产出仓 | å¼ºåˆ¶é…ç½® / è‡ªåŠ¨ä»Žçº¿è¾¹åº“è½¬ç§»åˆ°æˆå“ä»“ |
| 4 | ä¸­é—´å·¥åºäº§å‡º | åªå…¥çº¿è¾¹åº“ / å…è®¸å…¥å®žé™…仓并生成半成品入库单 |
| 5 | çº¿è¾¹åº“负库存 | ç¦æ­¢ / å…è®¸å¹¶é¢„è­¦ |
| 6 | å¾…检期间库存 | ä¸å…¥è´¦ï¼ˆçŽ°çŠ¶ï¼‰/ å…¥å¾…检仓 |
| 7 | æ— æ£€éªŒæ¨¡æ¿ä½†å·¥åºè¦æ±‚检验 | æŠ¥å·¥å®¡æ‰¹æ—¶æŠ¥é”™ / å…è®¸å…æ£€æ”¾è¡Œ |
## å…­ã€æ•°æ®åº“变更
```sql
-- Q8:产出行关联过程检验单,防止重复建单
ALTER TABLE mes_wm_product_produce_line
    ADD COLUMN ipqc_id BIGINT NULL COMMENT '过程检验单ID' AFTER quality_status;
CREATE INDEX idx_ppl_ipqc_id ON mes_wm_product_produce_line (ipqc_id);
```
> è‹¥ Q6 é€‰æ‹©ã€Œä¸åˆæ ¼å“å…¥ä¸è‰¯å“ä»“」,需补充不良品仓的配置项(建议复用仓库类型字段或新增字典),不新增业务表字段前先确认现有仓库模型。
## ä¸ƒã€å®žæ–½é¡ºåº
1. **第一批(数据正确性,P0)**
   - Q1 è´¨æ£€å›žè°ƒè¡¥å†™ä»»åŠ¡/工单/MPS
   - Q2 è°ƒæ•´æ•°é‡æ›´æ–°æ—¶ç‚¹
   - Q5 è´¨æ£€æ•°é‡æ ¡éªŒ
   - Q6 ä¸åˆæ ¼å“å…¥è´¦å£å¾„
2. **第二批(流程闭环,P1)**
   - Q3 æœ«é“工序与 keyFlag è§£è€¦
   - Q4 è·¯çº¿å·¥åºç¼ºå¤±æŠ¥é”™
   - Q7 é›¶æ•°é‡è„æ•°æ®
   - Q8 é‡å¤å»ºå•(含 DDL)
   - Q10 æ¨¡æ¿ç¼ºå¤±æç¤º
   - P1 æœ«é“产出仓策略
   - P2 è‡ªåŠ¨å…¥åº“æ˜Žç»†
3. **第三批(健壮性,P2)**
   - Q9 æ¥æºå•据强校验
   - D1 å¯ç”¨é‡æ ¡éªŒ
   - D2 BOM é‡å¤ç‰©æ–™
   - P3 å¾…检仓(可选)
## å…«ã€æµ‹è¯•验证清单
- [ ] éžå€’冲工序报工:不扣料、直接入库、末道生成入库单
- [ ] å€’冲工序报工:消耗单数量 = å•位用料 Ã— æŠ¥å·¥æ•°é‡ï¼ŒFIFO æ‰¹æ¬¡æ­£ç¡®ï¼Œåº“存扣减正确
- [ ] å€’冲工序线边库不足:按确认的模式报错或预警
- [ ] æ— éœ€æ£€éªŒ + æœ«é“工序:产出事务与入库单一致
- [ ] éœ€æ£€éªŒï¼šæŠ¥å·¥è¿›å…¥å¾…检,待检页出现产出行
- [ ] æ—  IPQC æ¨¡æ¿ï¼šåˆ›å»ºæ£€éªŒå•给出明确提示
- [ ] IPQC å…¨éƒ¨åˆæ ¼ï¼šæŠ¥å·¥å®Œæˆã€äº§å‡ºå…¥åº“、任务/工单/MPS æ•°é‡æ­£ç¡®
- [ ] IPQC éƒ¨åˆ†ä¸åˆæ ¼ï¼šåˆæ ¼å“å…¥æ­£å¸¸ä»“、不合格品按确认口径处理,NCR ç”Ÿæˆ
- [ ] IPQC å…¨éƒ¨ä¸åˆæ ¼ï¼šä¸äº§ç”Ÿ 0 æ•°é‡æ˜Žç»†ä¸Žäº‹åŠ¡ï¼Œä»»åŠ¡/工单数量正确
- [ ] IPQC æ•°é‡è¶…过待检数量:被拦截
- [ ] åŒä¸€å¾…检行重复建单:第二张被拦截
- [ ] å…³é”®å·¥åº + è´¨æ£€ï¼šåˆæ ¼/不合格数量进入任务
- [ ] æœ«é“工序非关键:工单/MPS äº§å‡ºç´¯åŠ 
- [ ] æœ«é“工序未配置产出仓:按确认策略报错或转移
- [ ] è‡ªåŠ¨å…¥åº“å•ï¼šæ˜Žç»†é½å…¨ï¼Œå¯å®Œæˆå…¥åº“ï¼ˆæˆ–æ˜Žç¡®ä¸ºå…æ‰§è¡Œå‡­è¯ï¼‰
- [ ] å®¡æ‰¹é‡å¤æäº¤ï¼šæ‰£æ–™ã€äº§å‡ºå•、入库单均不重复
docs/qc_source_link_frontend_integration.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,121 @@
# è´¨æ£€å•关联生产报工/销售出库 - å‰ç«¯è”调方案
## æ¶‰åŠé¡µé¢
- è´¨é‡ç®¡ç† â†’ è¿‡ç¨‹æ£€éªŒï¼ˆIPQC)列表、详情
- è´¨é‡ç®¡ç† â†’ å‡ºè´§æ£€éªŒï¼ˆOQC)列表、详情
- ç”Ÿäº§ç®¡ç† â†’ ç”Ÿäº§æŠ¥å·¥ï¼ˆåªè¯»å‚考:报工单号、状态、盘号)
- ä»“储管理 â†’ é”€å”®å‡ºåº“单(只读参考:出库单号、明细盘号、质量状态)
## ä¸šåŠ¡æµç¨‹ä¸Žæ•°æ®å¸¦å…¥
### è¿‡ç¨‹æ£€éªŒï¼ˆIPQC)关联生产报工
1. è´¨æ£€å·¥åºæŠ¥å·¥å®¡æ‰¹é€šè¿‡åŽï¼ŒæŠ¥å·¥å•转为「待检验(3)」,同时生成质量状态为「待检验(0)」的产出行,产出行盘号来自生产工单。
2. è´¨æ£€å‘˜ç‹¬ç«‹æ–°å»ºæˆ–导入 IPQC å•,填写检测数量、合格数量、不合格数量并上传检验附件,完成后由后端按数量自动判定:不合格数量为 0 â†’ æ ¡éªŒé€šè¿‡ï¼ˆ1),否则校验不通过(2)。
3. åœ¨å·²å®Œæˆä¸”未关联来源的 IPQC è¯¦æƒ…页点击「关联生产报工」,前端调用候选接口。后端自动使用本单的「物料 + ç›˜å·ã€ç­›é€‰ï¼Œåªè¿”回物料、盘号、数量与当前质检单完全一致,且仍处于待检验状态的报工产出行。
4. ç”¨æˆ·é€‰ä¸­ä¸€æ¡å€™é€‰åŽæäº¤å…³è”。后端校验通过后回写:报工单状态 â†’ å·²å®Œæˆï¼ˆ4)、按合格/不合格数量拆分产出行并完成产出入库、回写任务质量数量、检查工单是否完工。
5. å…³è”成功后,质检单详情应显示来源单据类型、来源单据编号、来源行 ID,并隐藏「关联生产报工」按钮。
### å‡ºè´§æ£€éªŒï¼ˆOQC)关联销售出库
1. é”€å”®å‡ºåº“单提交时,勾选「需要出货检验」的明细质量状态置为「待检验(0)」,出库单状态进入「待检测(1)」。提交动作不再自动创建 OQC å•。
2. è´¨æ£€å‘˜ç‹¬ç«‹æ–°å»ºæˆ–导入 OQC å•,填写检测数量、合格数量、不合格数量并上传检验附件,完成后同样按数量自动判定 1/2。
3. åœ¨å·²å®Œæˆä¸”未关联来源的 OQC è¯¦æƒ…页点击「关联销售出库」,前端调用候选接口。后端自动使用本单的「物料 + ç›˜å·ã€ç­›é€‰ï¼Œåªè¿”回出库单状态为「待检测」、明细勾选了出货检验、尚未关联质检单,且物料、盘号、数量与当前质检单完全一致的明细。
4. ç”¨æˆ·é€‰ä¸­ä¸€æ¡å€™é€‰åŽæäº¤å…³è”。后端回写出库明细的质检单 ID ä¸Žè´¨é‡çŠ¶æ€ï¼ˆåˆæ ¼ â†’ PASS,不合格 â†’ FAIL)。
5. å½“该出库单所有需检验明细都变为合格后,出库单自动从「待检测(1)」流转到「待拣货(2)」。存在不合格明细时保持「待检测」,等待后续处置,不会自动取消整张出库单。
## API
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| GET | /mes/qc/source-link/feedback-candidates | æŸ¥è¯¢ IPQC å¯å…³è”的生产报工产出行候选 |
| POST | /mes/qc/source-link/feedback | å°† IPQC å…³è”到指定报工产出行 |
| GET | /mes/qc/source-link/sales-candidates | æŸ¥è¯¢ OQC å¯å…³è”的销售出库明细候选 |
| POST | /mes/qc/source-link/sales | å°† OQC å…³è”到指定销售出库明细 |
权限码:
| æŽ¥å£ | æƒé™ç  |
|------|--------|
| feedback-candidates、feedback | mes:qc-ipqc:update |
| sales-candidates、sales | mes:qc-oqc:update |
**请求参数(候选查询):**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| qcId | Long | æ˜¯ | å½“前质检单 ID(IPQC æˆ– OQC) |
**请求参数(提交关联):**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| qcId | Long | æ˜¯ | å½“前质检单 ID |
| lineId | Long | æ˜¯ | å€™é€‰æŽ¥å£è¿”回的 lineId(报工产出行 ID æˆ–销售出库明细 ID) |
**候选响应字段:**
| å­—段 | ç±»åž‹ | è¯´æ˜Ž |
|------|------|------|
| lineId | Long | å¾…检明细 ID,提交关联时回传 |
| documentId | Long | æ¥æºå•据 ID:报工单 ID æˆ–销售出库单 ID |
| documentCode | String | æ¥æºå•据编号:报工单号或出库单号 |
| reelNo | String | ç›˜å· |
| quantity | BigDecimal | å¾…检数量 |
**候选响应示例:**
```json
{
  "code": 0,
  "data": [
    {
      "lineId": 123,
      "documentId": 456,
      "documentCode": "BG20261104001",
      "reelNo": "PAN-001",
      "quantity": 200
    }
  ]
}
```
**关联成功响应:** `{ "code": 0, "data": true }`
## å­—段展示规则
| å­—段 | å±•示位置 | è¯´æ˜Ž |
|------|----------|------|
| sourceDocCode | è´¨æ£€å•详情 | å·²å…³è”时展示来源单据编号,未关联时显示空 |
| sourceDocType | è´¨æ£€å•详情 | åŽç«¯è¿”回 304=生产报工,119=销售出库 |
| sourceLineId | è´¨æ£€å•详情 | å·²å…³è”时非空,用于判断是否隐藏关联按钮 |
| reelNo | è´¨æ£€å•列表、详情 | å·²å®Œæˆè´¨æ£€å•必须非空才能发起关联 |
| documentCode | å€™é€‰å¼¹çª— | æŠ¥å·¥å•号或销售出库单号 |
| reelNo | å€™é€‰å¼¹çª— | ç›˜å·ï¼Œç”¨äºŽäººå·¥å¤æ ¸ |
| quantity | å€™é€‰å¼¹çª— | å¾…检数量,应与质检单检测数量一致 |
## ä¸šåŠ¡è§„åˆ™
| åœºæ™¯ | è§„则 |
|------|------|
| IPQC å…³è”前置条件 | è´¨æ£€å•状态必须为已完成(4),且 sourceDocType、sourceDocId、sourceLineId å‡ä¸ºç©ºï¼Œç›˜å·éžç©º |
| IPQC å€™é€‰æ¡ä»¶ | äº§å‡ºè¡Œè´¨é‡çŠ¶æ€ä¸ºå¾…æ£€éªŒï¼ˆ0)、关联报工单状态为待检验(3)、物料一致、生产工单一致;质检单指定了生产任务时任务也必须一致;盘号一致;报工产出行数量等于质检单检测数量 |
| IPQC å…³è”写回 | æŠ¥å·¥å•转已完成(4),按合格/不合格数量拆分产出行并完成产出入库,回写任务质量数量与工单进度 |
| OQC å…³è”前置条件 | è´¨æ£€å•状态必须为已完成(4),且 sourceDocType、sourceDocId、sourceLineId å‡ä¸ºç©ºï¼Œç›˜å·éžç©º |
| OQC å€™é€‰æ¡ä»¶ | å‡ºåº“单状态为待检测(1)、明细勾选需要出货检验、明细尚未关联质检单、物料一致、客户一致(质检单填写客户时)、盘号一致、明细数量等于质检单检测数量 |
| OQC å…³è”写回 | å‡ºåº“明细写入质检单 ID ä¸Žè´¨é‡çŠ¶æ€ï¼›å…¨éƒ¨éœ€æ£€æ˜Žç»†åˆæ ¼åŽå‡ºåº“å•è½¬å¾…æ‹£è´§ï¼ˆ2) |
| ä¸€å¯¹ä¸€çº¦æŸ | ä¸€æ¡å¾…检明细只能被一张质检单关联;一张质检单只能关联一条来源明细 |
| ç›˜å·æ¥æº | IPQC å–生产工单盘号;OQC å–销售订单明细盘号;两处均不做模糊匹配,仅去除首尾空格后比较 |
| æ•°é‡çº¦æŸ | è´¨æ£€å•检测数量必须大于 0 ä¸”与待检明细数量完全相等 |
## æ³¨æ„äº‹é¡¹
- å…³è”操作不可重复:质检单已关联来源后,详情页应隐藏关联入口;重复提交会被后端拒绝并提示已关联来源单据编号。
- å€™é€‰åˆ—表为空不代表接口异常:多为盘号、数量或单据状态不满足;前端应提示用户核对盘号与检测数量,并刷新重试。
- åŽç«¯é”™è¯¯æç¤ºä¼šæŒ‰ã€Œå•据状态 / ç‰©æ–™ / å·¥å• / ä»»åŠ¡ / ç›˜å· / æ•°é‡ / å·²å…³è”」给出具体维度与双方实际值,前端应直接展示后端 message,不要替换为统一的“操作失败”。
- å®Œæˆè´¨æ£€å•时后端会校验:合格数量与不合格数量之和必须大于 0 ä¸”等于检测数量,并且必须已上传至少一份检验附件;未满足时不允许完成。
- è´¨æ£€ç»“论由数量自动计算,前端完成弹窗无需再让用户选择判定结果;提交的判定值会被后端覆盖。
- æ–°å»ºè´¨æ£€å•不再依赖质检方案:后端会忽略 templateId,也不会自动生成检验指标行;前端表单无需再强校验质检方案。
- é”€å”®å‡ºåº“单提交后不再自动创建 OQC,原“提交即生成检验单”的提示文案和后续跳转需同步调整。
- å…³è”成功后需刷新质检单详情与来源单据列表,避免继续展示旧的状态与关联信息。
docs/task_reporter_assignment.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,99 @@
# ç”Ÿäº§ä»»åŠ¡æŠ¥å·¥äººé™åˆ¶ - å‰ç«¯è”调方案
## æ¶‰åŠé¡µé¢
- MES ç”Ÿäº§ä»»åŠ¡ï¼ˆæ–°å¢ž/编辑弹窗)
- ç”Ÿäº§å·¥ä½œå°ï¼ˆä»»åŠ¡åˆ—è¡¨ã€å·¥ä½œç«™é€‰æ‹©å¼¹çª—ï¼‰
- MES ç”Ÿäº§æŠ¥å·¥ï¼ˆæ–°å¢ž/修改/提交、快捷报工、批量报工、导入)
## ä¸šåŠ¡æµç¨‹ä¸Žæ•°æ®å¸¦å…¥
1. ç”Ÿäº§ä»»åŠ¡æ–°å¢ž/编辑时选择「报工人」(可多选),保存后写入任务表。
2. å·¥ä½œå°æŒ‰å½“前登录人过滤待报工任务:只显示报工人包含当前登录人的任务。
3. æŠ¥å·¥æ—¶åŽç«¯å†æ¬¡æ ¡éªŒï¼šä»…任务的报工人可以创建、修改、提交报工单。
4. æ–°å»ºä»»åŠ¡æœªæŒ‡å®šæŠ¥å·¥äººæ—¶ï¼Œè‡ªåŠ¨å–è¯¥å·¥ä½œç«™é…ç½®äººå‘˜ï¼ˆå²—ä½ä¸‹å¯ç”¨ç”¨æˆ·ï¼‰ä½œä¸ºæŠ¥å·¥äººï¼›ä¸€é”®æŽ’äº§ç­‰è‡ªåŠ¨ç”Ÿæˆä»»åŠ¡åŒæ ·é€‚ç”¨ã€‚
5. ä»»åŠ¡æ²¡æœ‰æŠ¥å·¥äººï¼ˆå·¥ä½œç«™æœªé…ç½®äººå‘˜ï¼‰æ—¶ï¼Œä»»ä½•äººåœ¨å·¥ä½œå°éƒ½çœ‹ä¸åˆ°ã€ä¹Ÿæ— æ³•æŠ¥å·¥ã€‚
## API
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| POST | /mes/pro/task/create | åˆ›å»ºä»»åŠ¡ï¼Œæ–°å¢ž `assigneeUserIds` |
| PUT | /mes/pro/task/update | æ›´æ–°ä»»åŠ¡ï¼Œæ–°å¢ž `assigneeUserIds` |
| GET | /mes/pro/task/get | ä»»åŠ¡è¯¦æƒ…ï¼Œå“åº”æ–°å¢ž `assigneeUserIds`、`assigneeUserNames` |
| GET | /mes/pro/task/page | ä»»åŠ¡åˆ†é¡µï¼Œå“åº”æ–°å¢ž `assigneeUserIds`、`assigneeUserNames` |
| GET | /mes/pro/task/pending-feedback-page | å¾…报工台账,新增 `onlyMine` å‚æ•° |
| GET | /mes/pro/task/pending-count-by-workstation | æŒ‰å·¥ä½œç«™ç»Ÿè®¡å¾…报工数,新增 `onlyMine` å‚æ•° |
**任务保存请求参数新增:**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| assigneeUserIds | Long[] | å¦ | æŠ¥å·¥äººç”¨æˆ·ç¼–号列表;新增时不传或传空表示不限制;更新时传 null è¡¨ç¤ºä¸ä¿®æ”¹ï¼Œä¼ ç©ºæ•°ç»„表示清空限制 |
**任务响应字段新增:**
| å­—段 | ç±»åž‹ | è¯´æ˜Ž |
|------|------|------|
| assigneeUserIds | Long[] | æŠ¥å·¥äººç”¨æˆ·ç¼–号列表,空数组表示不限制 |
| assigneeUserNames | String | æŠ¥å·¥äººå§“名,多个用顿号“、”分隔 |
**待报工台账请求参数新增:**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| onlyMine | Boolean | å¦ | ä¸º true æ—¶ä»…返回当前登录人可报工的任务(含未配置报工人的任务) |
**请求示例:**
```
GET /mes/pro/task/pending-feedback-page?workstationId=10&pageNo=1&pageSize=200&onlyMine=true
GET /mes/pro/task/pending-count-by-workstation?onlyMine=true
```
**响应示例:**
```json
{
  "code": 0,
  "data": {
    "list": [
      {
        "id": 1001,
        "code": "PT202611070001",
        "assigneeUserIds": [1024, 1025],
        "assigneeUserNames": "张三、李四"
      }
    ],
    "total": 1
  }
}
```
## å­—段展示规则
| å­—段 | å±•示位置 | è¯´æ˜Ž |
|------|----------|------|
| assigneeUserIds | ä»»åŠ¡æ–°å¢ž/编辑弹窗 | å¤šé€‰ä¸‹æ‹‰ï¼Œé€‰é¡¹æ¥æºä¸ºå·¥ä½œç«™äººå‘˜ï¼›ç¼–辑时回显 |
| assigneeUserNames | ä»»åŠ¡åˆ—è¡¨ï¼ˆå¯é€‰ï¼‰ | é€—号/顿号分隔的姓名串,纯展示 |
## ä¸šåŠ¡è§„åˆ™è¯´æ˜Ž
| åœºæ™¯ | è§„则 |
|------|------|
| ä»»åŠ¡æœªé…ç½®æŠ¥å·¥äºº | æ— äººå¯æŠ¥å·¥ï¼Œä¸åœ¨ä»»ä½•人的工作台显示 |
| ä»»åŠ¡å·²é…ç½®æŠ¥å·¥äºº | ä»…列表内人员可以创建、修改、提交报工单 |
| æ–°å»ºä»»åŠ¡æœªæŒ‡å®šæŠ¥å·¥äºº | è‡ªåŠ¨å–å·¥ä½œç«™é…ç½®äººå‘˜ä½œä¸ºæŠ¥å·¥äºº |
| æ‰¹é‡ä¸€é”®æŽ’产 | åˆ›å»ºä»»åŠ¡æ—¶è‡ªåŠ¨å¸¦å·¥ä½œç«™é…ç½®äººå‘˜ä½œä¸ºæŠ¥å·¥äºº |
| å·¥ä½œå°ä»»åŠ¡åˆ—è¡¨ | è°ƒç”¨ `pending-feedback-page` æ—¶ä¼  `onlyMine=true`,仅显示报工人含自己的任务 |
| å·¥ä½œå°å·¥ä½œç«™å¡ç‰‡ | è°ƒç”¨ `pending-count-by-workstation` æ—¶ä¼  `onlyMine=true`,任务数口径与列表一致 |
| ç®¡ç†ç«¯ä»»åŠ¡å°è´¦ | ä¸ä¼  `onlyMine`,查看全部任务 |
| æŠ¥å·¥å¯¼å…¥ | å¤ç”¨åˆ›å»º/修改校验,导入人需为任务报工人 |
## æ³¨æ„äº‹é¡¹
- æ–°å¢žé”™è¯¯ç  `1_040_506_018`:「您不是该生产任务的报工人,无法报工」,前端可直接展示后端 message。
- `assigneeUserIds` æ›´æ–°è¯­ä¹‰ï¼š`null` ä¸ä¿®æ”¹ï¼Œç©ºæ•°ç»„清空报工人(清空后该任务无人可报工),非空数组覆盖。
- ä»»åŠ¡è¡¨éœ€å…ˆæ‰§è¡Œè¿ç§»è„šæœ¬ `scripts/task-reporter-20261107/01_ddl.sql` å¢žåŠ  `assignee_user_ids` åˆ—。
- åŽ†å²ä»»åŠ¡å·²é€šè¿‡ `scripts/task-reporter-20261107/02_backfill.sql` æŒ‰å·¥ä½œç«™äººå‘˜å›žå¡«æŠ¥å·¥äººï¼›å·¥ä½œç«™æœªé…ç½®äººå‘˜ï¼ˆå²—位)的任务仍为空,这些任务在补齐报工人前不会出现在工作台。
- å·¥ä½œç«™äººå‘˜å–自「工作站-岗位」配置(`mes_md_workstation_worker`)下所有启用用户。