3 天以前 93327134ed36b2b514ce12af9a5f6b0e773718ad
docs(bi): 添加决策模块重构设计文档与BPM审批流程部署脚本

- 新增决策模块前端联调方案文档,包含API变更说明和KPI编码清单
- 新增决策模块重构设计方案文档,涵盖业务目标、现状分析和数据摸底
- 新增BPM审批流程手工部署脚本,包含6个仓储域审批流程定义
- 补充M6菜单权限配置,增加SN码更新和设备入库单相关权限点
已添加19个文件
2005 ■■■■■ 文件已修改
docs/decision_module_frontend.md 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/decision_module_redesign.md 385 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/hrm_requirements_roadmap.md 187 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/hrm_training_and_expire_remind_integration.md 175 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/machinery_equipment_material_inbound.md 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/sql/bpm_mes_wm_approval_flows.sql 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/sql/equipment_material_stock_link.sql 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/sql/equipment_receipt.sql 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/sql/sn_item_chain.sql 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/sql/stock_taking_plan_auto_generate.sql 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/sql/stock_taking_result_approval.sql 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/wm_barcode_scan_render_integration.md 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/wm_batch_code_requirements.md 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/wm_equipment_receipt_integration.md 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/wm_frontend_upgrade_progress.md 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/wm_sn_item_chain_integration.md 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/wm_stock_taking_plan_auto_generate_integration.md 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/wm_stock_taking_result_approval_integration.md 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/wm_stock_trace_gap_analysis.md 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/decision_module_frontend.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,163 @@
# å†³ç­–模块重构 - å‰ç«¯è”调方案
> ç‰ˆæœ¬ï¼šv1.0 ï½œ æ—¥æœŸï¼š2026-09-09 ï½œ åŽç«¯æ¨¡å—:yudao-module-bi(决策支持)
> è¯¦ç»†è®¾è®¡è§ [decision_module_redesign.md](./decision_module_redesign.md)
## æ¶‰åŠé¡µé¢
- å†³ç­–总览大屏(`/bi/decision-overview`)
- é‡‡è´­é”€å”®å¤§å±ï¼ˆ`/bi/purchase-sales`)
- ä»“库大屏(`/bi/warehouse`)
- ç”Ÿäº§è®¾å¤‡å¤§å±ï¼ˆ`/bi/production-equipment`)
- è´¨é‡å¤§å±ï¼ˆ`/bi/quality`)
- èƒ½è€—监控大屏(`/bi/energy`,新增)
- è¥é”€å®¢æˆ·å¤§å±ï¼ˆ`/bi/sales-customer`,新增)
- å†³ç­– BI å¤§å± / å›¾è¡¨é…ç½®ç®¡ç†é¡µ / æ•°æ®æºé…ç½®ç®¡ç†é¡µï¼ˆæ—¢æœ‰ï¼‰
## API å˜æ›´è¯´æ˜Ž
本次为新增接口,不改动既有接口签名。
### 1. KPI åŽ†å²å¿«ç…§è¶‹åŠ¿ï¼ˆè¶‹åŠ¿ç ”åˆ¤ï¼‰
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| GET | `/bi/decision/kpi/trend/{kpiCode}` | æŒ‡å®š KPI çš„历史快照序列(折线图数据源) |
**请求参数(Query):**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| kpiCode | String | æ˜¯ | KPI ç¼–码(见下方 KPI æ¸…单) |
| beginTime | String | å¦ | å¼€å§‹æ—¶é—´ `yyyy-MM-dd HH:mm:ss`,默认近 30 å¤© |
| endTime | String | å¦ | ç»“束时间,默认当前 |
| periodType | String | å¦ | ç»Ÿè®¡å‘¨æœŸ hour/day/week/month,默认 hour |
**响应字段:**
```json
{
  "code": 0,
  "data": {
    "kpiCode": "device_operation_rate",
    "kpiName": "开机率",
    "category": "device_operation",
    "unit": "%",
    "periodType": "hour",
    "points": [
      {"time": "2026-09-09T02:00:00", "value": 100.0000},
      {"time": "2026-09-09T03:00:00", "value": 100.0000}
    ]
  }
}
```
> å¿«ç…§ç”±å®šæ—¶ä»»åŠ¡æ¯å°æ—¶èšåˆå†™å…¥ï¼ŒKPI å®šä¹‰åŽéœ€ç­‰å¾…下一整点聚合出数;无快照时 `points` ä¸ºç©ºæ•°ç»„。
### 2. KPI çŽ¯æ¯”ç ”åˆ¤
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| GET | `/bi/decision/kpi/compare/{kpiCode}` | å½“前快照值较上一周期的变化率及近 24 æœŸç»Ÿè®¡ |
**响应字段:**
| å­—段 | ç±»åž‹ | è¯´æ˜Ž |
|------|------|------|
| currentValue / currentTime | Decimal / String | æœ€è¿‘一期快照值与时间 |
| previousValue / previousTime | Decimal / String | ä¸Šä¸€æœŸå¿«ç…§å€¼ |
| changeRate | Decimal | çŽ¯æ¯”å˜åŒ–çŽ‡ï¼ˆ%),上期不存在或为 0 æ—¶ä¸º null |
| avgValue / maxValue / minValue | Decimal | è¿‘ 24 æœŸå‡å€¼/最大/最小 |
| periodCount | int | å®žé™…快照条数 |
### 3. é¢„测生成(扩展模型参数)
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| POST | `/bi/decision/forecast/generate` | ç”Ÿæˆé¢„测,新增 `model` å‚æ•° |
**新增 Query å‚数:**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| forecastCode | String | æ˜¯ | é¢„测编码(沿用) |
| model | String | å¦ | æ¨¡åž‹ï¼šSMA/WMA/LR/SEASONAL/YOY,缺省 SMA |
| window | int | å¦ | ç§»åŠ¨å¹³å‡çª—å£ï¼Œé»˜è®¤ 12 |
| period | int | å¦ | å­£èŠ‚å‘¨æœŸï¼Œé»˜è®¤ 7 |
### 4. åŸºäºŽ KPI åŽ†å²ç”Ÿæˆé¢„æµ‹
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| POST | `/bi/decision/forecast/generate-from-kpi` | ç”¨ KPI å¿«ç…§åŽ†å²æŒ‰æ¨¡åž‹æ»šåŠ¨é¢„æµ‹æœªæ¥ N æœŸ |
**请求参数(Query):**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| kpiCode | String | æ˜¯ | ç”¨å“ªä¸ª KPI çš„历史快照预测 |
| model | String | å¦ | SMA/WMA/LR/SEASONAL/YOY,缺省 SMA |
| window | int | å¦ | é»˜è®¤ 12 |
| period | int | å¦ | é»˜è®¤ 7 |
| periods | int | å¦ | é¢„测期数,默认 30,上限 90 |
| intervalMinutes | int | å¦ | é¢„测点间隔分钟,默认 360 |
**响应:** ç”Ÿæˆçš„预测记录数(int)
**注意:** åŽ†å²å¿«ç…§ä¸è¶³æ—¶è¿”å›ž `BI_FORECAST_NO_HISTORY` é”™è¯¯ç ï¼ˆcode éž 0),前端需提示"暂无历史数据,无法预测"。
### 5. æ—¢æœ‰æŽ¥å£ï¼ˆæ— å˜æ›´ï¼‰
- `POST /bi/dashboard/{dashboardCode}/data` â€” å¤§å±æ•°æ®ï¼ˆæ²¿ç”¨æ—¢æœ‰ `bi_dashboard_frontend.md` è”调约定)
- `GET /bi/decision/forecast/list`、`POST /bi/decision/forecast/history`、`POST /bi/decision/forecast/generate-work-order`、`GET /bi/decision/alert/page` ç­‰
## KPI ç¼–码清单(前端展示用)
| åŸŸ | KPI ç¼–码 | åç§° | å•位 |
|----|----------|------|------|
| energy | energy_telemetry_devices | é¥æµ‹åœ¨é‡‡è®¾å¤‡æ•° | å° |
| energy | energy_telemetry_points | åœ¨é‡‡æµ‹ç‚¹æ€»æ•° | ä¸ª |
| energy | energy_anomaly_rate | é¥æµ‹å¼‚常率 | % |
| energy | energy_power_load | å®žæ—¶åŠŸçŽ‡è´Ÿè· | kW |
| energy | energy_power_consumption | å‘¨æœŸç”¨ç”µé‡ | kWh |
| device_operation | device_total / device_running | è®¾å¤‡æ€»æ•° / è¿è¡Œè®¾å¤‡æ•° | å° |
| device_operation | device_operation_rate | å¼€æœºçއ | % |
| device_operation | device_avg_efficiency | å¹³å‡ç”Ÿäº§æ•ˆçއ | ä»¶/时 |
| device_operation | device_need_repair | å¾…维修工单数 | å• |
| production | prod_work_order_total / prod_work_order_finish | å·¥å•总数 / ç´¯è®¡äº§é‡ | å• / ä»¶ |
| production | prod_plan_achieve_rate / prod_feedback_qualified | è®¡åˆ’达成率 / æŠ¥å·¥åˆæ ¼çއ | % |
| production | prod_daily_output | ä»Šæ—¥äº§é‡ | ä»¶ |
| quality | quality_iqc_pass_rate / quality_ipqc_pass_rate / quality_oqc_pass_rate | æ¥æ–™/过程/出货合格率 | % |
| quality | quality_ncr_count | ä¸åˆæ ¼å“æŠ¥å‘Šæ•° | å• |
| procurement | pur_request_amount / pur_order_amount / pur_order_pending_in | é‡‡è´­ç”³è¯·/订单金额、待入库量 | å…ƒ / ä»¶ |
| procurement | stock_amount_value / stock_low_alert | åº“存货值 / ä½Žåº“存物料数 | å…ƒ / ä¸ª |
| procurement | cost_payment_amount | åº”付款近30天 | å…ƒ |
| sales | sale_order_amount / crm_contract_amount / crm_receivable_amount | é”€å”®è®¢å•/合同/回款金额 | å…ƒ |
| sales | crm_customer_count / srm_avg_score | å®¢æˆ·æ•° / ä¾›åº”商评分 | ä¸ª / åˆ† |
| safety | safety_andon_count / safety_andon_unhandled | å®‰ç¯æŠ¥è­¦æ•° / æœªå¤„置数 | æ¬¡ / ä¸ª |
## æ–°å¢žå¤§å± code ä¸Žæ•°æ®å¸¦å…¥è¯´æ˜Ž
| dashboardCode | åç§° | æ•°æ®å¸¦å…¥ / åˆ·æ–° |
|---------------|------|------------------|
| decision_overview | å†³ç­–总览 | number/gauge å¡ç‰‡ 5 åˆ†é’Ÿåˆ·æ–°ï¼Œè¶‹åŠ¿æŠ˜çº¿ 10 åˆ†é’Ÿåˆ·æ–° |
| energy | èƒ½è€—监控 | å®žæ—¶å¡ç‰‡ 5 åˆ†é’Ÿåˆ·æ–°ï¼›æ— åŠŸçŽ‡/电量测点时"功率负荷"显示 0 |
| sales_customer | è¥é”€å®¢æˆ· | æŒ‡æ ‡å¡ç‰‡ 10 åˆ†é’Ÿåˆ·æ–° |
> å¤§å±ç»Ÿä¸€èµ° `POST /bi/dashboard/{code}/data`,`position` ç”¨ 12 åˆ—栅格(`{x,y,w,h}`),图表类型 number/gauge/line/bar æ¸²æŸ“约定与既有 `bi_dashboard_frontend.md` ä¸€è‡´ã€‚
## ä¸šåŠ¡è§„åˆ™è¯´æ˜Ž
| åœºæ™¯ | è§„则 |
|------|------|
| KPI é¦–次配置 | å¿«ç…§ä»Žä¸‹ä¸€ä¸ªæ•´ç‚¹å¼€å§‹èšåˆï¼Œè¶‹åŠ¿æŽ¥å£æš‚ç©º |
| ä¸šåŠ¡è¡¨æ— æ•°æ® | KPI è¿”回 0 æˆ–空,不视为异常;设备/遥测当前即有真实数据 |
| èƒ½è€—无功率测点 | åŠŸçŽ‡è´Ÿè·/用电量返回 0,属正常占位;补充功率类测点后自动出值 |
| é¢„测无历史 | è¿”回 `BI_FORECAST_NO_HISTORY`,前端提示无历史数据 |
| é¢„警去重 | åŒä¸€ KPI å·²æœ‰æœªå¤„理预警时不重复生成,人工处理后恢复 |
## æ³¨æ„äº‹é¡¹
- æŒ‡æ ‡å¡/仪表盘面板建议对"分类"做 tab åˆ†ç»„(能耗/设备/生产/质量/采购/营销/安全),共用同一套卡片组件。
- é¢„警中心页面(既有)已支持未处理计数与确认/处理操作,可直接复用本次 KPI ä½“系产出的 `bi_alert_record`。
- æƒé™ç‚¹æ²¿ç”¨æ—¢æœ‰ï¼š`bi:decision:kpi:query/update`、`bi:decision:alert:query/confirm/handle`,新接口不新增权限,无需改菜单。
docs/decision_module_redesign.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,385 @@
# å†³ç­–模块重构设计方案
> ç‰ˆæœ¬ï¼šv1.0 ï½œ æ—¥æœŸï¼š2026-09-09 ï½œ æ¨¡å—:yudao-module-bi å†³ç­–支持(decision)
> å¯¹é½ç›®æ ‡ï¼šæ•°æ®çœ‹æ¿ä¸Žå¤šç»´åº¦æŠ¥è¡¨ã€å®žæ—¶ KPI ç›‘控与异常预警、历史数据驱动的负荷预测与决策研判
---
## ä¸€ã€èƒŒæ™¯ä¸Žç›®æ ‡
现有 `yudao-module-bi` å†³ç­–支持子模块已具备代码骨架(KPI / é¢„è­¦ / é¢„测 / çœ‹æ¿å››ä¸ªåŸŸï¼‰ï¼Œä½†**配置数据全部为空**(`bi_kpi_definition`、`bi_dashboard`、`bi_chart_config`、`bi_alert_rule`、`bi_forecast_data` å‡ä¸º 0 æ¡ï¼‰ï¼Œå°šæœªä¸Žç³»ç»Ÿä¸šåŠ¡æ•°æ®æ‰“é€šã€‚
本次重构围绕三大业务目标:
| # | ç›®æ ‡ | è½åœ°å½¢æ€ |
|---|------|----------|
| 1 | æ•´åˆç”¨ç”µè¥é”€ã€ç”Ÿäº§è¿ç»´ã€ç‰©èµ„采购、库存、能耗等核心数据 | é…ç½®å¼å¯è§†åŒ–看板(大屏)+ å¤šç»´åº¦æŠ¥è¡¨ |
| 2 | å®žæ—¶ç›‘控供电量、设备运行、生产效率、质量、成本、安全等核心 KPI,异常自动预警 | KPI æŒ‡æ ‡åº“ + å¿«ç…§èšåˆ + é¢„警规则中心 |
| 3 | åŸºäºŽåŽ†å²æ•°æ®å¼€å±•è´Ÿè·é¢„æµ‹ã€éœ€æ±‚åˆ†æžã€è¶‹åŠ¿ç ”åˆ¤ | Java ç»Ÿè®¡é¢„测引擎,支撑电网调度、运维计划、采购策略、客户经营决策 |
---
## äºŒã€çŽ°çŠ¶åˆ†æžä¸Žæ•°æ®æ‘¸åº•
### 2.1 çŽ°æœ‰å†³ç­–æ¨¡å—éª¨æž¶ï¼ˆä»£ç å·²å°±ç»ªï¼‰
| åŸŸ | è¡¨ | æœåŠ¡ | æŽ§åˆ¶å™¨ | å¤‡æ³¨ |
|----|----|------|--------|------|
| KPI æŒ‡æ ‡å®šä¹‰ | `bi_kpi_definition` | BiKpiDefinitionService | DecisionKpiDefinitionController | SQL é…ç½®å¼ï¼Œ`query_sql` å®žæ—¶æ‰§è¡Œ |
| KPI èšåˆå±•示 | â€” | BiDecisionKpiService | DecisionKpiController | overview/detail/category/refresh |
| é¢„警规则 | `bi_alert_rule` | BiAlertRuleService | DecisionAlertRuleController | é˜ˆå€¼ + æ¯”较符 + é€šçŸ¥æ–¹å¼ |
| é¢„警记录 | `bi_alert_record` | BiAlertRecordService | DecisionAlertController | åˆ†é¡µ/未处理数/确认/处理 |
| è´Ÿè·é¢„测 | `bi_forecast_data` | BiForecastService | DecisionForecastController | çŽ°ä¸º SMA ç®€å•移动平均占位,支持联动生成工单 |
| ä»ªè¡¨ç›˜ | `bi_dashboard` | DashboardService | DashboardController | æŒ‰ `{code}/data` è¿”回图表数据 |
| å›¾è¡¨é…ç½® | `bi_chart_config` | BiChartConfigService | BiChartConfigController | SQL + chartType + position + chartOptions |
| æ•°æ®æºé…ç½® | `bi_data_source_config` | BiDataSourceConfigService | BiDataSourceConfigController | å¤šæ•°æ®æºé¢„ç•™ |
### 2.2 é¢„警定时任务(已存在)
`AlertEvaluationTask` æ¯ 5 åˆ†é’Ÿï¼ˆå¯é… `bi.alert.evaluation.interval`)扫描启用预警规则 â†’ æ‰§è¡Œ KPI SQL â†’ ä¸Žé˜ˆå€¼æ¯”较 â†’ ç”Ÿæˆé¢„警记录,并对同一 KPI æœªå¤„理预警去重。
### 2.3 ä¸šåŠ¡æ•°æ®æ‘¸åº•ï¼ˆmom-xgdl åº“ 2026-09-09)
| æ•°æ®åŸŸ | è¡¨ | çŽ°çŠ¶ | è¯´æ˜Ž |
|--------|----|------|------|
| è®¾å¤‡ | `mes_dv_machinery` | 1 å°ï¼ˆç”Ÿäº§æœºï¼Œstatus=1,效率100) | status:0-停 / 1-运行 |
| é¥æµ‹ | `mes_dv_telemetry` | 296 æ¡ï¼ˆ4 å°è®¾å¤‡ï¼‰ | å·¥è‰ºå‚数(温度/匝数等),含 `whether_anomaly` å¼‚常标志、`telemetry_data_time`、`shift_name` |
| ç”Ÿäº§ | `mes_pro_work_order / task / feedback` | 0 | å·¥å•/任务/报工 |
| è´¨é‡ | `mes_qc_iqc/ipqc/oqc/ncr` | 0 | æ¥æ–™/过程/出货/不合格品 |
| åº“å­˜ | `mes_wm_material_stock/transaction` | 1+1 | åº“存余额 + æµæ°´ |
| å®‰ç¯ | `mes_pro_andon_record` | 0 | çŽ°åœºå¼‚å¸¸å‘¼å«ï¼ˆå®‰å…¨ç›‘æŽ§å…¥å£ï¼‰ |
| é‡‡è´­ | `erp_purchase_request/order` | 0 | é‡‡è´­ç”³è¯·/订单 |
| é”€å”® | `erp_sale_order` | 0 | é”€å”®è®¢å• |
| è´¢åŠ¡ | `erp_finance_receipt/payment` | 0 | æ”¶æ¬¾/付款 |
| å®¢æˆ· | `crm_customer/contract/receivable` | 0 | å®¢æˆ·/合同/回款 |
> **结论**:当前处于开发/试运行初期,业务数据未铺开。KPI æŒ‡æ ‡ã€é¢„警规则、看板图表一律按**真实表结构 + çœŸå®žå­—段**配置,数据积累后自动出值;设备运行与遥测异常指标当前即有真实数据支撑。
### 2.4 å…³é”®æ•°æ®ç¼ºå£
| ç¼ºå£ | çŽ°çŠ¶ | æœ¬æ¬¡ç­–ç•¥ |
|------|------|----------|
| èƒ½è€—/供电量数据 | æ— ç‹¬ç«‹ç”¨ç”µé‡è®°å½•表;`mes_dv_telemetry` ä¸ºå·¥è‰ºå‚数遥测,无功率/电量参数 | **从遥测参数聚合**:按 `param_name` åŒ¹é… åŠŸçŽ‡/电量/电流 ç±»å‚数聚合;无匹配参数时 KPI è¿”回 0 å ä½å¹¶ä¿ç•™æŽ¥å£ |
| å®‰å…¨æ•°æ® | æ— äº‹æ•…/隐患台账,仅 `mes_pro_andon_record` å®‰ç¯è®°å½• | å®‰å…¨ KPI åŸºäºŽå®‰ç¯è®°å½•(数量/未处置数),隐患台账留待后续 |
| KPI åŽ†å² | æ— åŽ†å²å€¼å­˜å‚¨ï¼Œæ— æ³•åšè¶‹åŠ¿/同比环比/预测 | **新增 `bi_kpi_value_history` å¿«ç…§è¡¨ + å®šæ—¶èšåˆä»»åŠ¡** |
---
## ä¸‰ã€æ€»ä½“架构设计
```
┌────────────────────────────────────────────────────────────────┐
│                        ç®¡ç†å±‚(大屏/报表)                       â”‚
│  bi_dashboard {code}/data  â†’  é…ç½®å¼å¤§å±ï¼ˆé‡‡è´­é”€å”®/仓库/生产设备  â”‚
│  /质量/能耗/营销 + å†³ç­–总览)                                    â”‚
│  å¤šç»´åº¦æŠ¥è¡¨ï¼šæŒ‰ æ—¶é—´ / è½¦é—´ / è®¾å¤‡ç±»åž‹ / ç‰©æ–™åˆ†ç±» / å®¢æˆ· / ä¾›åº”商   â”‚
│  äº¤å‰åˆ†æžï¼ˆæ–°å¢ž /bi/decision/report æ±‡æ€»æŽ¥å£ï¼‰                    â”‚
├────────────────────────────────────────────────────────────────┤
│                       ç›‘控层(KPI + é¢„警)                       â”‚
│  bi_kpi_definition(SQL æŒ‡æ ‡åº“)                                 â”‚
│    â”œâ”€â”€ å®žæ—¶å±‚:BiDecisionKpiService æŒ‰éœ€å®žæ—¶æ‰§è¡Œ SQL              â”‚
│    â”œâ”€â”€ å¿«ç…§å±‚:(新增)KpiSnapshotTask å®šæ—¶å†™å…¥ bi_kpi_value_history│
│    â””── é¢„警层:AlertEvaluationTask è¯„ä¼° bi_alert_rule â†’ bi_alert_record│
├────────────────────────────────────────────────────────────────┤
│                       å†³ç­–层(预测/研判)                         â”‚
│  BiForecastEngine(统计预测引擎:SMA/WMA/线性回归/同比环比/季节指数)│
│    â”œâ”€â”€ åŸºäºŽ bi_kpi_value_history çš„ KPI è¶‹åŠ¿é¢„æµ‹ï¼ˆè´Ÿè·/产量/采购/回款)│
│    â””── è”动:预测结果 â†’ ç”Ÿæˆç”Ÿäº§å·¥å•(复用 generate-work-order)   â”‚
└────────────────────────────────────────────────────────────────┘
```
### 3.1 åˆ†å±‚职责
| å±‚ | è¾“å…¥ | å¤„理 | è¾“出 |
|----|------|------|------|
| æ•°æ®æŽ¥å…¥ | å„业务表(mes/erp/crm/srm)+ é¥æµ‹ | è·¨æ¨¡å— SQL(单库 JdbcTemplate) | KPI å½“前值 |
| ç›‘控 | KPI æŒ‡æ ‡åº“ | å®žæ—¶æŸ¥è¯¢ + å®šæ—¶å¿«ç…§ + é˜ˆå€¼è¯„ä¼° | overview / å¿«ç…§åŽ†å² / é¢„警记录 |
| å†³ç­– | å¿«ç…§åŽ†å² | ç»Ÿè®¡é¢„测引擎 | é¢„测序列 + ç½®ä¿¡åŒºé—´ + å·¥å•联动 |
| å±•示 | çœ‹æ¿/图表配置 | é…ç½®é©±åŠ¨ç»„è£… | å¤§å± / æŠ¥è¡¨ |
### 3.2 å®žæ—¶æ€§è®¾è®¡
| å±‚级 | æœºåˆ¶ | å‘¨æœŸ |
|------|------|------|
| KPI å®žæ—¶æŸ¥è¯¢ | å‰ç«¯æŒ‰ `refreshInterval` è°ƒ `overview/{kpiCode}` | æŒ‰éœ€ |
| KPI å¿«ç…§ | æ–°å¢ž `KpiSnapshotTask` èšåˆè‡³ `bi_kpi_value_history` | é»˜è®¤ 1 å°æ—¶ï¼ˆå¯é… `bi.kpi.snapshot.interval`) |
| é¢„警评估 | çŽ°æœ‰ `AlertEvaluationTask` | é»˜è®¤ 5 åˆ†é’Ÿï¼ˆå¯é… `bi.alert.evaluation.interval`) |
| é¥æµ‹å¼‚常 | ç›´æŽ¥èšåˆ `mes_dv_telemetry.whether_anomaly` | éšå¿«ç…§ |
---
## å››ã€KPI æŒ‡æ ‡ä½“系设计
统一编码规则:`{域简称}_{指标英文}`,共 7 ç±»ï¼ˆcategory æ‰©å±•原注释枚举)。
### 4.1 åŸŸåˆ’分与指标清单
#### A. ä¾›ç”µç”µé‡ / èƒ½è€—域(category = `energy`)
| code | åç§° | å•位 | æ•°æ®æ¥æº SQL é€»è¾‘ |
|------|------|------|--------------------|
| energy_telemetry_devices | é¥æµ‹åœ¨é‡‡è®¾å¤‡æ•° | å° | `COUNT(DISTINCT tb_device_id)` from mes_dv_telemetry(近24h) |
| energy_telemetry_points | åœ¨é‡‡æµ‹ç‚¹æ€»æ•° | ä¸ª | `COUNT(*)` from mes_dv_telemetry(近24h) |
| energy_anomaly_rate | é¥æµ‹å¼‚常率 | % | `SUM(whether_anomaly)/COUNT(*)` è¿‘24h |
| energy_power_load | å®žæ—¶åŠŸçŽ‡è´Ÿè· | kW | `SUM(timely_value)` where param_name like '%功率%'(无参数返回0占位) |
| energy_power_consumption | å‘¨æœŸç”¨ç”µé‡ | kWh | èšåˆç”µåº¦ç±»å‚数差值(预留模型,本期占位) |
#### B. è®¾å¤‡è¿è¡ŒåŸŸï¼ˆcategory = `device_operation`)
| code | åç§° | å•位 | SQL é€»è¾‘ |
|------|------|------|----------|
| device_total | è®¾å¤‡æ€»æ•° | å° | `COUNT(*)` from mes_dv_machinery |
| device_running | è¿è¡Œè®¾å¤‡æ•° | å° | `COUNT(*) where status=1` |
| device_operation_rate | å¼€æœºçއ | % | è¿è¡Œ / æ€»æ•° |
| device_avg_efficiency | å¹³å‡ç”Ÿäº§æ•ˆçއ | ä»¶/时 | `AVG(production_efficiency)` |
| device_need_repair | å¾…维修工单 | ä¸ª | `COUNT(*) where status<终态` from mes_dv_repair |
| device_overdue_mainten | åˆ°æœŸæœªä¿å…»è®¾å¤‡ | å° | `last_mainten_time < è®¡åˆ’周期`(预留,返回0) |
#### C. ç”Ÿäº§æ•ˆçŽ‡åŸŸï¼ˆcategory = `production`)
| code | åç§° | å•位 | SQL é€»è¾‘ |
|------|------|------|----------|
| prod_work_order_total | å·¥å•总数 | å• | `COUNT(*)` from mes_pro_work_order(近30天) |
| prod_work_order_finish | å®Œå·¥å·¥å•æ•° | å• | `status=已完工` |
| prod_plan_achieve_rate | å·¥å•计划达成率 | % | å®Œå·¥é‡ä¹‹å’Œ / è®¡åˆ’量之和 |
| prod_feedback_qualified | æŠ¥å·¥åˆæ ¼çއ | % | SUM(qualified)/SUM(feedback) from mes_pro_feedback |
| prod_daily_output | æ—¥äº§é‡ | ä»¶ | SUM(feedback_quantity) å½“æ—¥ |
| prod_task_duration | å·¥å•平均工期 | å¤© | AVG(duration) from mes_pro_task |
#### D. è´¨é‡åŸŸï¼ˆcategory = `quality`)
| code | åç§° | å•位 | SQL é€»è¾‘ |
|------|------|------|----------|
| quality_iqc_pass_rate | æ¥æ–™æ£€éªŒåˆæ ¼çއ | % | SUM(qualified)/SUM(check) from mes_qc_iqc |
| quality_ipqc_pass_rate | è¿‡ç¨‹æ£€éªŒåˆæ ¼çއ | % | from mes_qc_ipqc |
| quality_oqc_pass_rate | å‡ºè´§æ£€éªŒåˆæ ¼çއ | % | from mes_qc_oqc |
| quality_ncr_count | ä¸åˆæ ¼å“æŠ¥å‘Šæ•° | å• | `COUNT(*)` from mes_qc_ncr |
#### E. ç‰©èµ„采购 / æˆæœ¬åŸŸï¼ˆcategory = `procurement`)
| code | åç§° | å•位 | SQL é€»è¾‘ |
|------|------|------|----------|
| pur_request_amount | é‡‡è´­ç”³è¯·é‡‘额(近30天) | å…ƒ | `SUM(total_price)` from erp_purchase_request |
| pur_order_amount | é‡‡è´­è®¢å•金额(近30天) | å…ƒ | `SUM(total_price)` from erp_purchase_order |
| pur_order_pending_in | å¾…入库采购量 | ä»¶ | `SUM(total_count-in_count)` from erp_purchase_order |
| stock_amount_value | åº“存货值 | å…ƒ | `SUM(stock.quantity*item.cost_price)` from mes_wm_material_stock join mdm_item |
| stock_low_alert | åº“存低于安全库存物料数 | ä¸ª | `quantity < item.safety_stock` |
| cost_payment_amount | åº”付款(近30天) | å…ƒ | `SUM(payment_price)` from erp_finance_payment |
#### F. ç”¨ç”µè¥é”€ / å®¢æˆ·ç»è¥åŸŸï¼ˆcategory = `sales`)
| code | åç§° | å•位 | SQL é€»è¾‘ |
|------|------|------|----------|
| sale_order_amount | é”€å”®è®¢å•金额(近30天) | å…ƒ | `SUM(total_price)` from erp_sale_order |
| crm_contract_amount | åˆåŒç­¾è®¢é‡‘额 | å…ƒ | `SUM(total_price)` from crm_contract(审核通过) |
| crm_receivable_amount | å®žé™…回款金额 | å…ƒ | `SUM(price)` from crm_receivable |
| crm_customer_count | å®¢æˆ·æ€»æ•° | ä¸ª | `COUNT(*)` from crm_customer |
| crm_receivable_overdue | é€¾æœŸæœªå›žæ¬¾é‡‘额 | å…ƒ | ä½£é‡‘计划 `receivable_plan` è¶… return_time æœªå›ž |
| srm_avg_score | ä¾›åº”商平均综合评分 | åˆ† | `AVG(composite_score)` from srm_supplier_evaluation |
#### G. å®‰å…¨åŸŸï¼ˆcategory = `safety`)
| code | åç§° | å•位 | SQL é€»è¾‘ |
|------|------|------|----------|
| safety_andon_count | å®‰ç¯æŠ¥è­¦æ•°ï¼ˆè¿‘30天) | æ¬¡ | `COUNT(*)` from mes_pro_andon_record |
| safety_andon_unhandled | æœªå¤„置安灯数 | ä¸ª | `COUNT(*) where status=未处置` |
### 4.2 ç»´åº¦è®¾è®¡
| ç»´åº¦ | æ¥æº | ç”¨é€” |
|------|------|------|
| æ—¶é—´ | æ—¥ / å‘¨ / æœˆ / å¹´ | å…¨éƒ¨æŒ‡æ ‡è¶‹åŠ¿ |
| è½¦é—´ | `mes_dv_machinery.workshop_id`、`mes_pro_work_order` | è®¾å¤‡/生产 |
| è®¾å¤‡ç±»åž‹ | `mes_dv_machinery_type` | è®¾å¤‡/能耗 |
| ç‰©æ–™åˆ†ç±» | `mdm_item` åˆ†ç±» | é‡‡è´­/库存 |
| å®¢æˆ· | `crm_customer` | è¥é”€/回款 |
| ä¾›åº”商 | `srm_supplier` / `erp_supplier` | é‡‡è´­/成本 |
---
## äº”、KPI åŽ†å²å¿«ç…§ä¸Žèšåˆï¼ˆæœ¬æ¬¡æ–°å¢žï¼‰
### 5.1 æ–°å¢žè¡¨ `bi_kpi_value_history`
| å­—段 | ç±»åž‹ | è¯´æ˜Ž |
|------|------|------|
| id | bigint | ä¸»é”® |
| kpi_id | bigint | å…³è” bi_kpi_definition.id |
| kpi_code | varchar(64) | KPI ç¼–码(冗余) |
| kpi_name | varchar(128) | KPI åç§°ï¼ˆå†—余) |
| category | varchar(32) | åˆ†ç±» |
| kpi_value | decimal(18,4) | å¿«ç…§å€¼ |
| snapshot_time | datetime | å¿«ç…§æ—¶é—´ç‚¹ï¼ˆæ•´ç‚¹ï¼‰ |
| period_type | varchar(16) | ç»Ÿè®¡å‘¨æœŸï¼šhour/day/week/month |
| dimension_value | varchar(64) | ä¸šåŠ¡ç»´åº¦å€¼ï¼ˆé¢„ç•™ï¼Œé»˜è®¤ all) |
| remark | varchar(255) | å¤‡æ³¨ |
| å®¡è®¡å­—段 | â€” | creator/create_time/updater/update_time/deleted |
索引:`idx_kpi_time(kpi_code, snapshot_time)`,`idx_category_time(category, snapshot_time)`。
### 5.2 æ–°å¢žèšåˆä»»åŠ¡ `KpiSnapshotTask`
- å®šæ—¶ï¼ˆé»˜è®¤æ¯å°æ—¶ `0 0 * * * *`,可配 `bi.kpi.snapshot.cron`)扫描 `status=1` çš„ KPI å®šä¹‰
- æ‰§è¡Œæ¯æ¡ `query_sql` å–当前值,写入 `bi_kpi_value_history`
- åŒå KPI åŒä¸€æ•´ç‚¹åŽ»é‡ï¼ˆè¦†ç›–å¼æ›´æ–°æˆ–è·³è¿‡åŽ»é‡ï¼Œå–æœ€æ–°ï¼‰
- å¤±è´¥ SQL è®°æ—¥å¿—降级,不中断整体
### 5.3 æ–°å¢žæŸ¥è¯¢æŽ¥å£ï¼ˆè¶‹åŠ¿ç ”åˆ¤ï¼‰
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| GET | `/bi/decision/kpi/trend/{kpiCode}?beginTime=&endTime=&periodType=` | KPI åŽ†å²å¿«ç…§è¶‹åŠ¿ï¼ˆä¾›æŠ¥è¡¨/大屏折线) |
| GET | `/bi/decision/kpi/compare/{kpiCode}` | åŒæ¯”环比(较上月/去年同期),基于快照 |
---
## å…­ã€é¢„警规则体系
### 6.1 è§„则配置(本次落库示例)
| KPI | è§„则 | çº§åˆ« | é˜ˆå€¼ | æ¯”较符 |
|-----|------|------|------|--------|
| energy_anomaly_rate | é¥æµ‹å¼‚常率过高 | è­¦å‘Š | 5 (%) | >= |
| device_operation_rate | å¼€æœºçŽ‡è¿‡ä½Ž | ä¸¥é‡ | 60 (%) | < |
| device_avg_efficiency | è®¾å¤‡æ•ˆçŽ‡è¿‡ä½Ž | è­¦å‘Š | 80 (ä»¶/时) | < |
| quality_oqc_pass_rate | å‡ºè´§æ£€éªŒåˆæ ¼çŽ‡è¿‡ä½Ž | ä¸¥é‡ | 95 (%) | < |
| stock_low_alert | åº“存低于安全库存物料数超限 | ä¸¥é‡ | 10 (个) | > |
| safety_andon_unhandled | æœªå¤„置安灯持续累积 | ç´§æ€¥ | 1 (个) | > |
| crm_receivable_overdue | é€¾æœŸå›žæ¬¾é‡‘额过大 | ä¸¥é‡ | 500000 (元) | > |
> é˜ˆå€¼ä»…为初始建议值,上线后按实际水平调整。`notificationType` ç»Ÿä¸€é…ç½®ä¸º `system`(站内信/待办集成,后续扩展 message/email)。
### 6.2 é¢„警生命周期
```
规则启用 â†’ å®šæ—¶è¯„估(5min)→ å‘½ä¸­é˜ˆå€¼ â†’ ç”Ÿæˆ bi_alert_record(status=0)
→ å‰ç«¯"预警中心"展示 + æœªå¤„理计数 â†’ ç¡®è®¤(confirm) / å¤„理(handle) â†’ å…³é—­
```
去重策略:同一 KPI å­˜åœ¨æœªå¤„理预警时不再重复生成(现有逻辑)。
---
## ä¸ƒã€èƒ½è€—/供电量聚合方案(从遥测参数聚合)
### 7.1 å¤„理原则
- ä»¥ `mes_dv_telemetry` ä¸ºå”¯ä¸€å®žæ—¶èƒ½è€—来源,按 `param_name` ç‰¹å¾åŒ¹é…èƒ½åŠ›å‚æ•°ï¼š
  - åŠŸçŽ‡ç±»ï¼š`param_name LIKE '%功率%'` â†’ `energy_power_load`(实时功率,kW)
  - ç”µé‡ç±»ï¼š`param_name LIKE '%电量%' OR '%用电%' OR '%电度%'` â†’ ç”µé‡é‡‡é›†ï¼ˆé¢„留)
  - ç”µæµ/电压类:`%电流%`、`%电压%` â†’ ç”µèƒ½è´¨é‡è¾…助指标
- å½“前测点无能力参数时,相关 KPI è¿”回 0 / æ— æ•°æ®å ä½ï¼Œ**不伪造数据**,待测点补充后自动出值。
### 7.2 èƒ½è€—聚合模型(本次落地)
| æŒ‡æ ‡ | èšåˆå£å¾„ |
|------|----------|
| å®žæ—¶åŠŸçŽ‡è´Ÿè· | å½“前批次 `timely_value` æ±‚和,按设备 |
| ç­æ¬¡èƒ½è€—ä¼°ç®— | æŒ‰ `shift_name` åˆ†ç»„ `AVG(timely_value)` Ã— è¿è¡Œæ—¶é•¿ï¼ˆé¢„留) |
| æ—¥ç”¨ç”µé‡ | ç”µåº¦ç±»å‚æ•° `max_value-min_value` è·¨æ—¥å›žå·®ï¼ˆé¢„留模型,表结构就绪) |
---
## å…«ã€Java ç»Ÿè®¡é¢„测引擎设计
### 8.1 æ¨¡åž‹åº“(本次落地)
| æ¨¡åž‹ | ç®—法 | é€‚用场景 | å®žçް |
|------|------|----------|------|
| SMA | ç®€å•移动平均(窗口 12) | å¹³ç¨³åºåˆ— | çŽ°æœ‰é€»è¾‘ä¿ç•™ |
| WMA | åŠ æƒç§»åŠ¨å¹³å‡ï¼ˆè¿‘æœŸæƒé‡é€’å¢žï¼‰ | æœ‰è½»å¾®è¶‹åŠ¿ | æ–°å¢ž |
| LR | ä¸€å…ƒçº¿æ€§å›žå½’(最小二乘) | çº¿æ€§è¶‹åŠ¿ï¼ˆäº§é‡/采购/回款) | æ–°å¢ž |
| SEASONAL | å­£èŠ‚æŒ‡æ•°ï¼ˆæŒ‰å‘¨æœŸå½’ä¸€åŒ–ï¼‰ | å‘¨æœŸæ€§è´Ÿè· | æ–°å¢ž |
| YOY/QOQ | åŒæ¯”/环比外推 | è¥é”€ç±»å¿«é€Ÿé¢„ä¼° | æ–°å¢ž |
### 8.2 å¼•擎结构
```
BiForecastEngine(新增,纯 Java å·¥å…·ç±»ï¼‰
  â”œâ”€ sma(List<BigDecimal>, window)
  â”œâ”€ wma(List<BigDecimal>, window)
  â”œâ”€ linearRegression(List<BigDecimal>) â†’ slope/intercept/预测下N期
  â”œâ”€ seasonalIndex(List<BigDecimal>, period) â†’ å­£èЂ因子 + åŽ»å­£èŠ‚é¢„æµ‹
  â””─ forecastByModel(code, modelType, data, periods) â†’ ç»Ÿä¸€å‡ºå£
```
### 8.3 æŽ¥å£æ‰©å±•(BiForecastService + Controller)
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| GET | `/bi/decision/kpi/trend/{kpiCode}?beginTime=&endTime=&periodType=` | KPI åŽ†å²å¿«ç…§è¶‹åŠ¿å–æ•°ï¼ˆå–‚ç»™å¼•æ“Žï¼‰ |
| POST | `/bi/decision/forecast/generate` æ‰©å±•参数 `model=SMA\|WMA\|LR\|SEASONAL` + `periods=` | æŒ‰æ¨¡åž‹ç”Ÿæˆé¢„测,落 `bi_forecast_data` |
| POST | `/bi/decision/forecast/generate-from-kpi?kpiCode=&model=&periods=` | ä»Ž KPI å¿«ç…§åŽ†å²ç”Ÿæˆé¢„æµ‹ï¼ˆè´Ÿè·/产量/采购/回款) |
| POST | `/bi/decision/forecast/generate-work-order` | é¢„测联动创建生产工单(现有,延续) |
预测结果字段沿用 `bi_forecast_data`:forecast_value / lowerBound / upperBound / confidenceLevel(95%) / modelVersion(如 `v2.0-lr`)。
### 8.4 å†³ç­–支撑场景映射
| å†³ç­–场景 | é¢„测对象 | æ•°æ®æº | è¾“出 |
|----------|----------|--------|------|
| ç”µç½‘调度/产能排程 | æ—¥äº§é‡ã€å·¥å•负荷 | prod_daily_output å¿«ç…§ | æœªæ¥ 7/30 å¤©äº§é‡é¢„测 |
| è¿ç»´è®¡åˆ’ | è®¾å¤‡æ•ˆçŽ‡ã€å¼‚å¸¸çŽ‡ | device_avg_efficiency、energy_anomaly_rate | å¼‚常趋势预警 |
| é‡‡è´­ç­–ç•¥ | é‡‡è´­é‡‘额、库存周转 | pur_order_amount、stock_low_alert | ä¸‹æœˆé‡‡è´­é‡é¢„测 |
| å®¢æˆ·ç»è¥ | å›žæ¬¾ã€åˆåŒ | crm_receivable_amount | ä¸‹æœˆå›žæ¬¾é¢„测 |
---
## ä¹ã€çœ‹æ¿ä¸Žå¤šç»´åº¦æŠ¥è¡¨æ–¹æ¡ˆ
### 9.1 çœ‹æ¿å¸ƒå±€ï¼ˆbi_dashboard + bi_chart_config è½åº“)
| code | åç§° | è¦†ç›–图表(chart_config) |
|------|------|--------------------------|
| decision_overview | å†³ç­–总览大屏 | æ ¸å¿ƒ KPI å¡ç‰‡ï¼ˆnumber)+ å„域趋势折线 |
| purchase_sales | é‡‡è´­é”€å”®å¤§å± | é‡‡è´­é‡‘额趋势/销售订单趋势/来票额/回款(沿用既有 code) |
| warehouse | ä»“库大屏 | åº“存货值/低库存/出入库流水/库位分布 |
| production_equipment | ç”Ÿäº§è®¾å¤‡å¤§å± | è®¾å¤‡å¼€æœºçއ/效率/工单达成率/产量趋势/遥测异常 |
| quality | è´¨é‡å¤§å± | å„检验合格率/NCR æ•°é‡ |
| energy | èƒ½è€—监控大屏(新增) | å®žæ—¶åŠŸçŽ‡è´Ÿè·/在采测点/异常率/班次能耗 |
| sales_customer | è¥é”€å®¢æˆ·å¤§å±ï¼ˆæ–°å¢žï¼‰ | åˆåŒç­¾å®š/回款/逾期/客户数/供应商评分 |
### 9.2 å¤šç»´åº¦æŠ¥è¡¨ï¼ˆæ–°å¢ž `/bi/decision/report`)
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| POST | `/bi/decision/report/cross` | äº¤å‰è¡¨ï¼šæ—¶é—´ Ã— è½¦é—´/客户/供应商/物料分类 Ã— æŒ‡æ ‡å€¼ |
| GET | `/bi/decision/report/topn?category=&dimension=&limit=` | TOP N æŽ’行(客户回款 TOP、不良 TOP、缺料 TOP) |
响应统一为 `{ columns, rows }` ç»“构,前端渲染普通表格/透视图。
---
## åã€æ•°æ®åº“变更清单
| æ“ä½œ | å¯¹è±¡ | è¯´æ˜Ž |
|------|------|------|
| æ–°å»ºè¡¨ | `bi_kpi_value_history` | KPI åŽ†å²å¿«ç…§ |
| åˆå§‹åŒ–数据 | `bi_kpi_definition` | çº¦ 26 æ¡ KPI(上表全部 code) |
| åˆå§‹åŒ–数据 | `bi_alert_rule` | çº¦ 7 æ¡é¢„警规则 |
| åˆå§‹åŒ–数据 | `bi_dashboard` | 7 ä¸ªçœ‹æ¿ |
| åˆå§‹åŒ–数据 | `bi_chart_config` | å„看板图表(约 30 å¼ ï¼‰ |
| ä¸æ”¹è¡¨ | `bi_forecast_data` | çŽ°æœ‰ç»“æž„å¤Ÿç”¨ï¼Œä»…æ‰©å±• modelVersion ä½¿ç”¨ |
> ä¸šåŠ¡è¡¨é›¶æ”¹åŠ¨ï¼šKPI ä½“系只读各业务表,不加任何冗余字段。符合《文件上传规则》《SQL è„šæœ¬è§„èŒƒã€‹ï¼ˆæ—  tenant_id)等既有约束。
---
## åä¸€ã€å®žæ–½æ­¥éª¤
| æ­¥éª¤ | å†…容 | äº¤ä»˜ |
|------|------|------|
| 1 | æ–°å¢ž `bi_kpi_value_history` è¡¨ + DO + Mapper | è¡¨ç»“构、代码 |
| 2 | æ–°å¢ž `KpiSnapshotTask` å¿«ç…§èšåˆä»»åŠ¡ | å®šæ—¶ä»»åŠ¡ |
| 3 | `BiDecisionKpiService` å¢žåŠ  trend / compare æŽ¥å£ | Controller + Service |
| 4 | BiForecastEngine ç»Ÿè®¡é¢„测引擎 + BiForecastService æ‰©å±• | é¢„测能力 |
| 5 | KPI æŒ‡æ ‡åº“ / é¢„警规则 / çœ‹æ¿å›¾è¡¨ SQL è„šæœ¬è½åº“ | åˆå§‹åŒ–脚本 |
| 6 | ç¼–译检查(mvn compile)+ æ•°æ®åº“回读验证 | éªŒè¯æŠ¥å‘Š |
## åäºŒã€é£Žé™©ä¸Žæ³¨æ„äº‹é¡¹
- ä¸šåŠ¡è¡¨å½“å‰ä¸ºç©ºï¼ŒKPI å‡ºå€¼ä¾èµ–数据积累;本次保证"结构正确 + SQL å¯æ‰§è¡Œ",数据到位自动出值。
- é¥æµ‹æ— åŠŸçŽ‡/电量参数时,能耗 KPI è¿”回 0 å ä½ï¼Œæµ‹ç‚¹è¡¥å……后自动生效,**不伪造数据**。
- KPI `query_sql` ä¸ºç®¡ç†å‘˜å¯é…ç½®é¡¹ï¼Œå±žç³»ç»Ÿè¾¹ç•Œå†…可信配置;运行时经 JdbcTemplate å‚数化执行,无注入风险。
- å¿«ç…§é‡ä¼°ç®—:26 KPI Ã— æ¯å°æ—¶ = çº¦ 624 è¡Œ/天,年数据量 ~23 ä¸‡è¡Œï¼Œè§„模可控。
- é¢„警阈值初值需上线后校准。
docs/hrm_requirements_roadmap.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,187 @@
# ç”µåŠ›è¡Œä¸šäººåŠ›èµ„æºç³»ç»Ÿéœ€æ±‚æ¢³ç†ä¸Žå®žæ–½è·¯çº¿å›¾
> çŠ¶æ€ï¼šéœ€æ±‚æ•´ç†ç¨¿ï¼Œä¾›ç¡®è®¤ï¼Œå°šæœªè¿›å…¥ç¼–ç ã€‚
> ç›®æ ‡åº“:`mom-xgdl`(后端 local profile æ•°æ®æºï¼‰ã€‚关联文档:[培训+到期提醒联调方案](hrm_training_and_expire_remind_integration.md)。
---
## ä¸€ã€éœ€æ±‚总览
电力行业人力资源系统共三段需求,覆盖「人事档案 â†’ è€ƒå‹¤ â†’ è–ªé…¬ â†’ ç»©æ•ˆã€å…¨æµç¨‹ï¼Œä»¥åŠé¢å‘班组/值守岗位的排班与工时,再叠加培训证书合规管理。
| ç¼–号 | éœ€æ±‚原文要点 | æ¨¡å—归属 | å½“前进度 |
|------|--------------|----------|----------|
| éœ€æ±‚â‘  | ç»Ÿç­¹ç®¡ç†å…¨å‘˜äººäº‹æ¡£æ¡ˆã€åŠ³åŠ¨åˆåŒã€è€ƒå‹¤æ‰“å¡ã€è–ªé…¬æ ¸ç®—ã€ç»©æ•ˆè€ƒæ ¸å…¨æµç¨‹ä¸šåŠ¡ | HRM | å¾…实施(本文档梳理方案) |
| éœ€æ±‚â‘¡ | é’ˆå¯¹è¿ç»´ç­ç»„、检修班组、值守岗位实现智能排班、工时统计,工时数据同步对接成本核算模块 | MES æŽ’班/工时 + HRM å·¥æ—¶ | å¾…实施(含与成本模块的对接口径) |
| éœ€æ±‚â‘¢ | ç®¡ç†å®‰å…¨åŸ¹è®­ã€æŠ€èƒ½åŸ¹è®­ã€ç‰¹ç§ä½œä¸šè¯ä¹¦ã€ä»Žä¸šèµ„质,到期自动提醒,满足电力行业合规管理 | HRM åŸ¹è®­ + è¯ä¹¦/合同提醒 | **已实施完成**(见第六节) |
**已确认的总体口径(会话决策)**
- ä¸‰æ®µéœ€æ±‚分阶段推进,先统一梳理、按阶段编码,最后统一回归测试(用户口径「统一改完在测试」)。
- ç›®æ ‡æ•°æ®åº“为 `mom-xgdl`,所有菜单/字典/配置/表均写入该库。
- æˆæœ¬æ ¸ç®—模块**当前不存在**,需求②的工时对接采取「先固化工时汇总表 + å¯¹å¤–提供 Api」,成本模块后续另建(本轮不建成本表)。
---
## äºŒã€çŽ°çŠ¶ç›˜ç‚¹ï¼ˆå·²å…·å¤‡çš„èƒ½åŠ›ï¼‰
| ä¸šåŠ¡åŸŸ | å·²æœ‰å®žä½“/接口 | è¯´æ˜Ž |
|--------|---------------|------|
| äººäº‹æ¡£æ¡ˆ | `hrm_employee`(基本信息/部门/岗位/学历/入职/员工状态/基本工资/薪酬结构ID ç­‰ï¼‰ï¼›`hrm_employee_education`、`_emergency_contact`、`_work_history` | æœ‰æ–°å¢ž/分页/详情/离职交接接口;**入职/审批不联动回写** |
| åŠ³åŠ¨åˆåŒ | `hrm_employee_contract`,已有动态到期状态 + `REMIND_DAYS=30` + `/expiring-count` | æœ‰åˆ°æœŸæé†’计数,无站内信(需求③已补) |
| è¯·å‡/离职/调动审批 | `hrm_leave_application`、`hrm_resignation_application`、`hrm_transfer_application` + BPM | é€šè¿‡ BPM å®¡æ‰¹æµï¼›**审批通过后不反写员工主档** |
| äº¤æŽ¥ | `hrm_user_handover` + `HrmUserHandoverApi.expandUserIds()` | ç¦»èŒæ•°æ®äº¤æŽ¥ï¼Œå„模块查询统一扩展 userId(详见交接规则) |
| è€ƒå‹¤ | `hrm_attendance_record`(打卡/clock-in/clock-out)、`_rule`、`_holiday`、`_exception`、`_summary`(汇总/generate);`HrmAttendanceSummaryDO` | **加班时长链断裂:打卡/异常均未产出 overtime å­—段** |
| è–ªé…¬ | æ¡£æ¡ˆ`hrm_employee_salary`、社保`hrm_employee_social_security`/`hrm_social_security_config`/`_scheme`、个税`hrm_tax_rate_config`、请假类型`hrm_leave_type_config`、核算`hrm_salary_calculation`、发放`hrm_salary_payment`(+明细) | **核算只算固定项;加班写死 0、工作日写死 22;缺薪酬结构/员工薪酬档案后台 CRUD** |
| ç»©æ•ˆ | `hrm_performance_appraise` + `_item` + `_result`(+`_item`) | è€ƒæ ¸æ–¹æ¡ˆå¯¹è±¡å­˜åœ¨ï¼›**"指定班组"维度无落地载体** |
| åŸ¹è®­/证书 | éœ€æ±‚③新增 `hrm_training`/`hrm_training_participant`;`hrm_certificate`(四类资质+到期字段) | è§ç¬¬å…­èŠ‚ |
| æŽ’班(需求②) | MES `mes_cal_plan(_shift/_team)`、`mes_cal_team(_member/_shift)`、`mes_cal_holiday` | æŽ’班套件齐全,**但未落到"人×日"** |
| å·¥æ—¶(需求②) | MES `mes_pro_task`(duration äººæ—¥)、`MesProTaskApi.getTeamWorkHourSummary`(按班组聚合,1 äººæ—¥=8 äººæ—¶) | HRM å·²å¯è·¨æ¨¡å—è°ƒ MES å·¥æ—¶ï¼›**无汇总表,实时统计** |
| æˆæœ¬ | ERP ä»… `erp_finance_receipt`/`erp_finance_payment` | **无成本模块** |
---
## ä¸‰ã€éœ€æ±‚①「全流程业务」差距分析与建议
### 3.1 äººå‘˜æ¡£æ¡ˆä¸ŽåŠ³åŠ¨åˆåŒé—­çŽ¯
需求:全员人事档案 + åŠ³åŠ¨åˆåŒå…¨æµç¨‹ï¼ˆç­¾è®¢/ç»­ç­¾/到期)。
**现状缺口**
1. `hrm_employee` **缺「用工性质」「所属班组」字段**(运维班/检修班/值守岗等组织维度无法表达)。电力场景班组是核心组织单元,需求②排班、绩效指定班组都依赖它。
2. **审批通过后不反写主档**:离职审批通过 â†’ å‘˜å·¥ `employeeStatus`/`leaveDate` æœªè‡ªåŠ¨æ›´æ–°ï¼ˆéœ€æ‰‹åŠ¨æ”¹ï¼‰ï¼›è°ƒåŠ¨å®¡æ‰¹é€šè¿‡ â†’ `deptId/postId` æœªè”动。目前离职交接靠 `hrm_user_handover`,但员工状态字段仍靠手工。
3. **无「转正」业务**:`hrm_employee.regularDate` å­—段存在但无触发点;试用→在职的状态流转无流程。
4. åŠ³åŠ¨åˆåŒåˆ°æœŸï¼šå·²æœ‰åˆ°æœŸè®¡æ•° + éœ€æ±‚③站内信提醒,**续签动作**是否要走审批、新合同号如何衔接待定。
**建议**
- å‘˜å·¥ä¸»æ¡£è¡¥ `employmentType`(用工性质:正式/劳务/外包/实习等,字典) ä¸Ž `teamId`/`teamName`(所属班组) â€”— ç­ç»„引用 MES `mes_cal_team` æˆ– HRM ç‹¬ç«‹ç­ç»„表,需与需求②统一口径。
- ç¦»èŒ/调动审批结果**回写主档**(新增 BPM å®¡æ‰¹å®Œæˆç›‘听,更新 employeeStatus/leaveDate/deptId/postId)。
- æ–°å¢ž**转正**动作(入职满试用期 â†’ æ­£å¼ï¼Œå†™ regularDate,改状态)。是否接 BPM å®¡æ‰¹å¾…定。
- åŠ³åŠ¨åˆåŒå¢ž/续签保留现到期提醒链路。
### 3.2 è€ƒå‹¤æ‰“卡
需求:考勤打卡全流程(规则/打卡/汇总),为薪酬提供加班/缺勤。
**现状缺口**
1. `hrm_attendance_record` æ‰“卡(clock-in/clock-out)存在,但**加班时长从未被计算**:无 overtime å†™å…¥ç‚¹ã€‚
2. æœ‰ `_exception`(异常/补卡)、`_rule`、`_holiday`、`_summary`(generate æ±‡æ€»),但汇总字段与薪酬核算字段**未打通**。
**建议**
- æ‰“通"打卡/规则/节假日 â†’ æ¯æ—¥è€ƒå‹¤(含应出勤、实出勤、**加班时长 overtimeHours**、迟到早退) â†’ æœˆåº¦æ±‡æ€»"。
- æ˜Žç¡®åŠ ç­å£å¾„ï¼ˆè¶…å‡ºè§„åˆ™å·¥æ—¶éƒ¨åˆ† / æ³•定节假上班等),加班源数据由考勤产出,供薪酬消费。
### 3.3 è–ªé…¬æ ¸ç®—
需求:薪酬核算全流程。
**现状缺口(核心断链)**
- `HrmSalaryCalculationServiceImpl` æ ¸ç®—**只取档案固定项**:
  - `overtimePay = BigDecimal.ZERO`、`overtimeHours = BigDecimal.ZERO`(**从不读考勤加班**);
  - `workDays = 22` **写死**(不从考勤/日历得出当月应出勤);
  - è¯·å‡æ‰£æ¬¾åªè¯»"已审批通过的请假记录"(`hrm_leave_application`),**不读考勤缺勤**,`leaveHours` ç›¸å…³å£å¾„待核。
- **绩效结果未参与核算**:performanceSalary ä»Žå‘˜å·¥æ¡£æ¡ˆå–固定值,**不读绩效结果表**。
- **无薪酬结构/员工薪酬档案的后台 CRUD**:`HrmSalaryStructureDO`、`HrmEmployeeSalaryDO` ä»…被核算代码引用,`controller/admin/salary` ä¸‹åªæœ‰ç¤¾ä¿/核算/发放/配置/税率/请假类型,缺 `HrmSalaryStructureController`、`HrmEmployeeSalaryController` â†’ å‰ç«¯æ— æ³•维护"薪酬结构=固定+绩效+补贴+加班"与员工个人薪酬档案。
**建议**
- æ ¸ç®—输入补齐三条链路:①考勤(加班时长/缺勤天数) â†’ åŠ ç­è´¹/扣款;②绩效结果 â†’ ç»©æ•ˆå·¥èµ„;③请假/缺勤 â†’ æ‰£æ¬¾ã€‚三者乘以当人薪酬档案单价。
- è¡¥å»ºè–ªé…¬ç»“æž„ + å‘˜å·¥è–ªé…¬æ¡£æ¡ˆåŽå° CRUD + èœå•权限。
- å»ºç«‹ã€Œè–ªé…¬ç»“构项 Ã— ç³»æ•°ã€ï¼ŒåŠ ç­è´¹ = åŠ ç­æ—¶é•¿ Ã— æ—¶è–ª(由基本工资/应出勤折算),先与用户确认计价口径。
### 3.4 ç»©æ•ˆè€ƒæ ¸
需求:绩效考核全流程。
**现状缺口**
- è€ƒæ ¸å®žä½“(`appraise`/`item`/`result`)已具备,但**"2-指定班组"的 scopeType æ— è½åœ°è½½ä½“**(班组维度未建),指定人的结果与薪酬/培训联动弱。
- è€ƒæ ¸ç»“果如何进入薪酬(绩效工资)链路(见 3.3)需打通。
**建议**
- ç»©æ•ˆå¯¹è±¡è½åº“到"员工(或班组)",班组维度复用需求①补的班组载体。
- ç¡®è®¤ç»©æ•ˆç»“æžœ â†’ è–ªé…¬æ ¸ç®—的取值规则(结果等级/分数 Ã— ç»©æ•ˆå·¥èµ„档)。
### 3.5 éœ€æ±‚①建议实施子项小结
| å­é¡¹ | æ¶‰åŠ | è¯´æ˜Ž |
|------|------|------|
| A. å‘˜å·¥ä¸»æ¡£æ‰©å±• | `hrm_employee` + å­—å…¸ | åŠ  ç”¨å·¥æ€§è´¨ / æ‰€å±žç­ç»„(与②统一口径) |
| B. å®¡æ‰¹ç»“果回写 + è½¬æ­£ | HRM service + BPM ç›‘听 | ç¦»èŒ/调动反写主档;转正动作 |
| C. è€ƒå‹¤åŠ ç­æ‰“é€š | è€ƒå‹¤ç›¸å…³ service/mapper | åŠ ç­æ—¶é•¿äº§å‡ºå£å¾„ |
| D. è–ªé…¬æ ¸ç®—接考勤/绩效 | `HrmSalaryCalculationServiceImpl` | åŠ ç­è´¹ã€åº”å‡ºå‹¤ã€ç»©æ•ˆå·¥èµ„ã€æ‰£æ¬¾ |
| E. è–ªé…¬ç»“构与档案 CRUD | æ–°å¢ž 2 Controller + èœå• | åŽå°å¯ç»´æŠ¤è–ªé…¬æ¨¡åž‹ä¸Žä¸ªäººæ¡£æ¡ˆ |
| F. ç»©æ•ˆç­ç»„落地 + ç»“果入薪酬 | ç»©æ•ˆå¯¹è±¡æ‰©å±• | ä¸Ž A/D è”动 |
---
## å››ã€éœ€æ±‚②「排班 + å·¥æ—¶ + æˆæœ¬å¯¹æŽ¥ã€å·®è·åˆ†æžä¸Žå»ºè®®
需求:对运维班组、检修班组、值守岗位**智能排班**、**工时统计**,工时数据**同步对接成本核算模块**。
### 4.1 æŽ’班
**现状缺口**
- MES `mes_cal_*` æŽ’班套件齐全:`cal_plan`(排班计划) â†’ `cal_plan_shift`(班次)、`cal_plan_team`(参与班组)、`cal_team_member`(班组成员,`userId`↔系统用户)、`cal_team_shift`(班组×班次×日期)、`cal_holiday`(节假日)。
- **可推演到"员工×日"的排班,但未落成明细**:值守岗位逐人逐日的班次安排(白/夜/休)没有物化结果。
- **无"智能"能力**:需明确智能是指(a)自动按规则生成排班表(合规:连续工时/休息间隔/班次均衡),还是(b)仅固化排班看板供查询。
**建议**
- åœ¨ `mes_cal_team_shift` ä¹‹ä¸Š**固化"员工级排班明细"**(`mes_cal_schedule_detail`:员工×日期×班次),作为工时/值守合规的基准。
- "智能"按规则引擎最小化实现:先按班组班次模板生成 + äººå·¥å¾®è°ƒ + åˆè§„校验,后续再谈自动优化。
- å€¼å®ˆ(24h)岗位的排班口径(三班倒/白夜休等)需用户确认班次库。
### 4.2 å·¥æ—¶ç»Ÿè®¡ä¸Žæˆæœ¬å¯¹æŽ¥
**现状缺口**
- æŠ¥å·¥å·¥æ—¶ï¼šMES `mes_pro_task` æ—¶é•¿ duration(人日,1=8h),`MesProTaskApi.getTeamWorkHourSummary` å·²æŒ‰ç­ç»„聚合,**HRM å·²è·¨æ¨¡å—调用**(实时统计,无汇总表)。
- **无成本模块**(ERP ä»…收付款)。需求原文"对接成本核算",若坚持实时算成本,会牵出 ERP æˆæœ¬åŸŸçš„物料/人工/制造费用三要素,范围过大。
**建议(沿用已确认口径:先固化,不建成本)**
- æ–°å¢ž**月度工时汇总表**(员工×班组×工时口径:排班工时/实际工时/加班工时,源自 MES æŽ’班明细 + æŠ¥å·¥ï¼‰ï¼Œå¹¶å¯¹**对外提供 `Api`** ä¾›åŽç»­æˆæœ¬æ¨¡å—消费。
- äººå·¥æˆæœ¬å£å¾„:工时 Ã— å‘˜å·¥æ—¶è–ª(薪酬档案) å¯ä½œ**软成本预览**,但不落 ERP æˆæœ¬æ€»è´¦ï¼ˆå¾…用户确认是否本轮要做)。
---
## äº”、需求③(已完成)交付说明
需求③已实施完成并通过编译、种子落库 `mom-xgdl`:
- **培训管理**:`hrm_training` + `hrm_training_participant`(草稿/待开展/已完成/已取消;编号 PX è‡ªåŠ¨ç”Ÿæˆï¼›å‚è®­äººæ‰¹é‡æ·»åŠ /成绩/是否合格;`/hrm/training/*` ä¸Ž `/hrm/training-participant/*` å…¨å¥—接口)。
- **证书/合同到期提醒**:每日 `infra_job`(`hrmExpiryRemindJob` 08:00) + è¯ä¹¦/合同列表懒触发兜底;Redis æ—¥é”+60 å¤©åŽ»é‡ï¼›æŒ‰å‘˜å·¥ `userId` å‘站内信;提醒天数 `infra_config`(默认 30)可调。
- **联动发证**:培训完成时对 `is_pass=1` ä¸”未发证的参训人生成 `hrm_certificate`(安全→类型4、技能→类型3,证书有效期=完成日+`cert_validity_months`),回写 `certificate_id` é˜²é‡ã€‚
- **证书筛选**:证书分页新增 `expiryType`(1 å³å°†åˆ°æœŸ/2 å·²è¿‡æœŸ)。
- è”调方案文档已出([hrm_training_and_expire_remind_integration.md](hrm_training_and_expire_remind_integration.md))。
> é—留:运行时端到端验证待用户环境就绪后执行(当前 `mom-xgdl` æ— å‘˜å·¥æµ‹è¯•数据)。
---
## å…­ã€æ€»ä½“实施路线图(建议阶段)
> ä¾èµ–关系:班组口径(需求①A) â†’ æŽ’班明细(需求②) å‰ç½®æ‰“通后,绩效指定班组/工时汇总才不返工。
| é˜¶æ®µ | å†…容 | å‰ç½® | äº§å‡º |
|------|------|------|------|
| **P0 å·²äº¤ä»˜** | éœ€æ±‚â‘¢ åŸ¹è®­ + åˆ°æœŸæé†’ | æ—  | å·²è½åœ° + è”调文档 |
| **P1 ç»„织口径** | éœ€æ±‚â‘ A å‘˜å·¥ä¸»æ¡£æ‰©å±•(用工性质/班组) + éœ€æ±‚②班组口径统一 | P0 | å­—å…¸/字段/班组载体 |
| **P2 äººå‘˜é—­çޝ** | éœ€æ±‚â‘ B å®¡æ‰¹å›žå†™/转正 + åŠ³åŠ¨åˆåŒç»­ç­¾å£å¾„ | P1 | BPM ç›‘听 + è½¬æ­£åŠ¨ä½œ |
| **P3 è€ƒå‹¤â†’薪酬** | éœ€æ±‚â‘ C è€ƒå‹¤åŠ ç­ + D è–ªé…¬æ ¸ç®—接考勤/绩效 + E è–ªé…¬ç»“æž„/档案 CRUD | P1 | è€ƒå‹¤/薪酬链路闭环 |
| **P4 ç»©æ•ˆ** | éœ€æ±‚â‘ F ç»©æ•ˆç­ç»„落地 + ç»“果入薪酬 | P1/P3 | ç»©æ•ˆâ†’薪酬取值 |
| **P5 æŽ’班+工时** | éœ€æ±‚â‘¡ å‘˜å·¥çº§æŽ’班明细 + æœˆåº¦å·¥æ—¶æ±‡æ€»è¡¨ + å¯¹å¤– Api | P1(班组) | æŽ’班看板基准 + å·¥æ—¶ Api |
| **P6 æˆæœ¬(另规划)** | ERP æˆæœ¬åŸŸ(人工/物料/制造) æ¶ˆè´¹å·¥æ—¶ Api | P5 | éœ€æ±‚â‘¡"对接成本"落点 |
> æ¯é˜¶æ®µéµå¾ªæœ¬ä»“库规则:接口变更出 `docs/` å‰ç«¯è”调方案;SQL ç§å­å«èœå•/字典/权限并落 `mom-xgdl`;跨模块改动做编译检查。**成本模块是否本轮就建、智能排班到何种程度,见下节待确认。**
---
## ä¸ƒã€å¾…确认的开放决策
1. **班组载体归属**:员工所属班组引用 MES `mes_cal_team`(字段关联 `teamId`),还是 HRM ç‹¬ç«‹ç­ç»„表?→ å½±å“ P1/P2/P5 ä¸‰å¤„。
2. **用工性质字典**:取值集合(正式/劳务/外包/实习/退休返聘/其他?)。
3. **转正流程**:转正是手动动作还是走 BPM å®¡æ‰¹ï¼ˆè¯•用期到自动提醒 + å®¡æ‰¹åŽè½¬æ­£ï¼‰ï¼Ÿ
4. **薪酬加班/扣款计价口径**:加班费 = åŠ ç­æ—¶é•¿ Ã— æ—¶è–ªï¼Ÿæ—¶è–ª = åŸºæœ¬å·¥èµ„ Ã· å½“月应出勤天数?缺勤扣款口径同源?绩效工资 = ç»©æ•ˆç»“果分数/等级 Ã— å›ºå®šç»©æ•ˆæ¡£ï¼Ÿ
5. **绩效考核范围**:本轮考核"指定班组"是否需要完整班组成员逐一评,还是考核到班组再分摊?
6. **需求②"智能"程度**:自动排班仅做规则模板 + äººå·¥å¾®è°ƒ + åˆè§„校验,还是需要自动排班算法?
7. **成本模块范围**:确认本轮不建 ERP æˆæœ¬åŸŸï¼Œåªå›ºåŒ–月度工时汇总表 + å¯¹å¤– Api(软成本预览),成本核算另行规划 â€”— æ˜¯å¦è®¤å¯ï¼Ÿ
---
*本文档为需求梳理稿,待上述决策确认后按阶段实施;未经确认不进入编码。*
docs/hrm_training_and_expire_remind_integration.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,175 @@
# HRM åŸ¹è®­ç®¡ç† + è¯ä¹¦/合同到期提醒 - å‰ç«¯è”调方案
## æ¶‰åŠé¡µé¢
| é¡µé¢ | å˜æ›´ç±»åž‹ | è¯´æ˜Ž |
|------|----------|------|
| äººåŠ›èµ„æº - è¯ä¹¦èµ„è´¨ | æ”¹é€  | åˆ—表筛选新增"到期类型",列表页打开触发证书到期提醒 |
| äººåŠ›èµ„æº - å‘˜å·¥åˆåŒ | æ”¹é€  | åˆ—表页打开触发合同到期提醒(无页面结构改动) |
| äººåŠ›èµ„æº - åŸ¹è®­ç®¡ç†ï¼ˆæ–°å¢žèœå•) | æ–°å¢ž | åŸ¹è®­æ´»åЍ + å‚训人员 + å®Œæˆå‘证 |
| ç³»ç»Ÿæ¶ˆæ¯ï¼ˆç«™å†…信) | å±•示 | åˆ°æœŸæé†’站内信由后端主动发送,前端无需调用接口 |
## åˆ°æœŸæé†’行为说明
- è¯ä¹¦èµ„质、劳动合同到期前 N å¤©ï¼ˆé»˜è®¤ 30,可在「系统配置」中改 `hrm.certificate.remind-days` / `hrm.contract.remind-days`),向该员工绑定的系统账号发送站内信。
- è§¦å‘时机双保险:
  1. æ¯æ—¥å®šæ—¶ä»»åŠ¡ï¼ˆhandlerName=`hrmExpiryRemindJob`,每日 08:00,可在定时任务管理中调整/启停);
  2. æ‡’触发:打开"证书资质"或"员工合同"列表时后端顺带补扫一次(best-effort,失败不影响列表)。
- åŽ»é‡è§„åˆ™ï¼šåŒä¸€è¯ä¹¦/合同在到期日前后 60 å¤©å†…只提醒一次;同一员工离职后不提醒(仅向在岗/试用且有系统账号的员工发送)。
站内信文案(变量由后端带入,前端仅展示):
| æ¨¡æ¿ | å†…容示例 |
|------|----------|
| è¯ä¹¦åˆ°æœŸæé†’ | {employeeName},您的证书资质【{certTypeName}】{certName} å°†äºŽ {expireDate} åˆ°æœŸï¼Œè¯·åŠæ—¶åŠžç†å¤å®¡/换证。 |
| åŠ³åŠ¨åˆåŒåˆ°æœŸæé†’ | {employeeName},您的劳动合同(编号:{contractNo})将于 {endDate} åˆ°æœŸï¼Œè¯·åŠæ—¶è”系人事办理续签或离职手续。 |
## API
### ä¸€ã€è¯ä¹¦èµ„质(改造)
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| GET | /hrm/certificate/page | åˆ†é¡µæŸ¥è¯¢ï¼Œæ–°å¢ž `expiryType` è¿‡æ»¤å‚æ•° |
**请求参数(新增):**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| expiryType | Integer | å¦ | 1=即将到期(30 å¤©å†…),2=已过期;不传则不过滤 |
### äºŒã€åŸ¹è®­æ´»åŠ¨ï¼ˆæ–°å¢žï¼Œèœå•æƒé™ hrm:training:*)
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| POST | /hrm/training/create | åˆ›å»ºåŸ¹è®­ï¼ˆåˆå§‹çŠ¶æ€=草稿) |
| PUT | /hrm/training/update | æ›´æ–°åŸ¹è®­ï¼ˆä»…草稿/待开展可改,编号不可改) |
| DELETE | /hrm/training/delete | æ‰¹é‡åˆ é™¤åŸ¹è®­ï¼ˆids æ•°ç»„,已完成/已取消不可删,级联删参训人) |
| GET | /hrm/training/get?id= | åŸ¹è®­è¯¦æƒ…(含参训人员列表) |
| GET | /hrm/training/page | åŸ¹è®­åˆ†é¡µï¼ˆå«å‚训人数、状态/类型名称) |
| POST | /hrm/training/start?id= | å¼€å§‹åŸ¹è®­ï¼ˆè‰ç¨¿ â†’ å¾…开展) |
| POST | /hrm/training/complete?id= | å®ŒæˆåŸ¹è®­ï¼ˆâ†’ å·²å®Œæˆï¼Œè§¦å‘联动发证) |
| POST | /hrm/training/cancel?id= | å–消培训(草稿/待开展 â†’ å·²å–消) |
**创建/更新请求参数(HrmTrainingSaveReqVO):**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| id | Long | æ›´æ–°å¿…å¡« | åŸ¹è®­æ´»åŠ¨ç¼–å· |
| name | String | æ˜¯ | åŸ¹è®­åç§° |
| trainingType | Integer | æ˜¯ | åŸ¹è®­ç±»åž‹ï¼š1=安全培训,2=技能培训,3=管理培训,4=其他 |
| trainer | String | å¦ | è®²å¸ˆ |
| location | String | å¦ | åŸ¹è®­åœ°ç‚¹ |
| hours | BigDecimal | å¦ | åŸ¹è®­å­¦æ—¶ |
| startDate | LocalDate | å¦ | å¼€å§‹æ—¥æœŸ |
| endDate | LocalDate | å¦ | ç»“束日期 |
| issueCertificate | Boolean | å¦ | æ˜¯å¦è‡ªåŠ¨å‘è¯ï¼ˆ0=否,1=是;仅安全/技能培训可置 1) |
| certValidityMonths | Integer | issue=1 æ—¶å¿…å¡« | è¯ä¹¦æœ‰æ•ˆæœŸï¼ˆæœˆï¼‰ |
| remark | String | å¦ | å¤‡æ³¨ |
**分页查询参数(HrmTrainingPageReqVO):**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| trainingNo | String | å¦ | åŸ¹è®­ç¼–号(精确) |
| name | String | å¦ | åŸ¹è®­åç§°ï¼ˆæ¨¡ç³Šï¼‰ |
| trainingType | Integer | å¦ | åŸ¹è®­ç±»åž‹ |
| status | Integer | å¦ | çŠ¶æ€ï¼š0=草稿,10=待开展,20=已完成,30=已取消 |
**详情/列表响应(HrmTrainingRespVO):**
| å­—段 | ç±»åž‹ | è¯´æ˜Ž |
|------|------|------|
| id / trainingNo / name | | ä¸»é”®ã€ç¼–号(PX å‰ç¼€è‡ªåŠ¨ç”Ÿæˆï¼Œåªè¯»ï¼‰ã€åç§° |
| trainingType / trainingTypeName | | ç±»åž‹ + å±•示名(安全培训/技能培训/管理培训/其他) |
| trainer / location / hours | | è®²å¸ˆ/地点/学时 |
| startDate / endDate | | èµ·æ­¢æ—¥æœŸ |
| issueCertificate / certValidityMonths | | æ˜¯å¦è‡ªåŠ¨å‘è¯ / è¯ä¹¦æœ‰æ•ˆæœŸæœˆ |
| status / statusName | | çŠ¶æ€ + å±•示名(草稿/待开展/已完成/已取消) |
| participantCount | Integer | å‚训人数(分页列表返回) |
| participants | Array | å‚训人员列表(详情接口返回,结构见下) |
| remark / createTime | | å¤‡æ³¨ / åˆ›å»ºæ—¶é—´ |
### ä¸‰ã€åŸ¹è®­å‚训人员(新增,挂培训管理权限)
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| POST | /hrm/training-participant/add | æ‰¹é‡æ·»åŠ å‚è®­å‘˜å·¥ï¼ˆè‡ªåŠ¨è·³è¿‡å·²åœ¨åå•ä¸­çš„å‘˜å·¥ï¼‰ |
| PUT | /hrm/training-participant/update | æ›´æ–°å•条参训记录(参加/成绩/是否合格) |
| DELETE | /hrm/training-participant/delete | æ‰¹é‡åˆ é™¤å‚训记录(ids æ•°ç»„) |
| GET | /hrm/training-participant/list?trainingId= | æŸæ¬¡åŸ¹è®­çš„参训人员列表(含员工工号/姓名) |
**add è¯·æ±‚参数:**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| trainingId | Long | æ˜¯ | åŸ¹è®­æ´»åŠ¨ç¼–å· |
| employeeIds | Array | æ˜¯ | å‚训员工编号集合 |
**update è¯·æ±‚参数:**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| id | Long | æ˜¯ | å‚训记录编号 |
| attended | Boolean | å¦ | æ˜¯å¦å®žé™…参加 |
| score | BigDecimal | å¦ | è€ƒæ ¸æˆç»© |
| isPass | Boolean | å¦ | æ˜¯å¦åˆæ ¼ |
| remark | String | å¦ | å¤‡æ³¨ |
**list å“åº”字段(HrmTrainingParticipantRespVO):**
| å­—段 | ç±»åž‹ | è¯´æ˜Ž |
|------|------|------|
| id / trainingId / employeeId | | ä¸»é”® / åŸ¹è®­ç¼–号 / å‘˜å·¥ç¼–号 |
| employeeNo / employeeName | | å‘˜å·¥å·¥å· / å§“名(后端按 employeeId å›žå¡«ï¼‰ |
| attended | Boolean | æ˜¯å¦å®žé™…参加 |
| score | BigDecimal | è€ƒæ ¸æˆç»© |
| isPass | Boolean | æ˜¯å¦åˆæ ¼ |
| certificateId | Long | è”动生成的证书编号(空=尚未发证,只读) |
| remark / createTime | | å¤‡æ³¨ / åˆ›å»ºæ—¶é—´ |
## å‰ç«¯ä¿®æ”¹ç‚¹ï¼ˆé¡µé¢è¡Œä¸ºè¯´æ˜Žï¼Œä¸å«ä»£ç ï¼‰
### 1. åŸ¹è®­ç®¡ç†åˆ—表页(新增)
- é¡¶éƒ¨ç­›é€‰ï¼šåŸ¹è®­ç¼–号、培训名称、培训类型(下拉)、状态(下拉),调用培训分页接口。
- åˆ—表列:培训编号、名称、类型、讲师、起止日期、参训人数、状态、操作。
- æ–°å¢ž/编辑弹窗:表单字段同创建请求参数;"是否自动发证"勾选且培训类型为安全/技能时展示"证书有效期(月)"必填输入。
- æ“ä½œæŒ‰é’®ï¼ˆæŒ‰å½“前状态显隐):
  - è‰ç¨¿ï¼šå¼€å§‹ã€ç¼–辑、删除;
  - å¾…开展:完成、取消、编辑、删除;
  - å·²å®Œæˆ/已取消:仅查看,不允许编辑/删除/操作参与人。
- "参训人员"弹窗从详情接口获得 participants,按培训完成与否决定是否允许增删改参与人记录。
### 2. å‚训人员操作
- "添加参训员工"使用现有员工选择器,选中后取员工 id åˆ—表,调用 add æŽ¥å£ï¼›æŽ¥å£è¿”回实际新增数(已存在的自动跳过)。
- å‚训记录行可录"是否参加 / è€ƒæ ¸æˆç»© / æ˜¯å¦åˆæ ¼",提交走 update;delete ä¼  ids。
- å‘˜å·¥å·¥å·/姓名由后端回填,前端不要在本地拼装。
### 3. è¯ä¹¦èµ„质列表(改造)
- åˆ—表筛选区新增"到期类型"下拉(全部/即将到期/已过期),值映射 expiryType 1/2。
- åˆ—表打开即会触发到期提醒发送,无需额外 UI。
## ä¸šåŠ¡è§„åˆ™è¯´æ˜Ž
| åœºæ™¯ | è§„则 |
|------|------|
| çŠ¶æ€æµè½¬ | create→草稿(0);start→待开展(10);complete→已完成(20);cancel→已取消(30) |
| å®ŒæˆåŸ¹è®­ | çŠ¶æ€ä¸ºè‰ç¨¿/待开展才可完成,否则报错 |
| è”动发证 | issueCertificate=1 æ—¶ï¼ŒåŸ¹è®­å®Œæˆè‡ªåЍ坹"合格(isPass=1)且未发证(certificateId ä¸ºç©º)"的参训人生成证书 |
| è¯ä¹¦ç±»åž‹æ˜ å°„ | å®‰å…¨åŸ¹è®­(1)→证书类型4 å®‰å…¨åŸ¹è®­åˆæ ¼è¯ï¼›æŠ€èƒ½åŸ¹è®­(2)→证书类型3 æŠ€èƒ½ç­‰çº§è¯ä¹¦ï¼›ç®¡ç†/其他不支持自动发证 |
| è¯ä¹¦æœ‰æ•ˆæœŸ | å‘证日期=完成当天;到期日期=完成当天 + certValidityMonths ä¸ªæœˆ |
| å¹‚ç­‰ | é‡å¤ç‚¹"完成"不会重复发证(参训人回写 certificateId é˜²é‡ï¼‰ |
| ä¸å¯ç¼–辑边界 | å·²å®Œæˆ/已取消的培训:不可编辑、删除,不可添加/更新/删除参训人 |
| å‚训人唯一 | åŒä¸€åŸ¹è®­ä¸‹åŒä¸€å‘˜å·¥åªå…è®¸ä¸€æ¡è®°å½•,重复添加自动跳过 |
| ç¼–号生成 | trainingNo ä»¥ PX å¼€å¤´ + æ—¥æœŸ + è‡ªå¢žï¼Œç”±åŽç«¯ç”Ÿæˆï¼Œå‰ç«¯åªè¯»å±•示 |
| åˆ°æœŸæé†’发送对象 | ä»…该员工绑定系统账号且在职/试用;离职不提醒 |
## æ³¨æ„äº‹é¡¹
- åŸ¹è®­ç›¸å…³ 4 ä¸ªæŒ‰é’®æƒé™ï¼ˆquery/create/update/delete)与证书资质一致已授权给租户管理员等角色;如某些账号看不到"培训管理"菜单,需在"系统管理→角色管理"里勾选该菜单权限。
- ç«™å†…信在登录用户的"系统消息"内查看;收件人是培训外的员工本人(证书/合同归属员工),不是 HR æ“ä½œäººã€‚
- `certificateId` ä¸ºåªè¯»å›žæ˜¾ï¼Œå‰ç«¯ä¸å¯æäº¤ã€‚
- è‹¥ä¿®æ”¹äº†åˆ°æœŸæé†’天数配置,请在"系统配置"保存,下次提醒扫描即按新值生效。
docs/machinery_equipment_material_inbound.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,83 @@
# è®¾å¤‡å°è´¦åˆ›å»ºè‡ªåŠ¨å»ºç‰©æ–™å¹¶å…¥è®¾å¤‡ä»“ - å‰ç«¯è”调方案
## æ¶‰åŠé¡µé¢
- MES è®¾å¤‡ç®¡ç† â†’ è®¾å¤‡å°è´¦ï¼šæ–°å¢ž/编辑表单、列表
- MES è®¾å¤‡ç®¡ç† â†’ è®¾å¤‡å°è´¦ï¼šExcel å¯¼å…¥
- MDM ä¸»æ•°æ® â†’ ç‰©æ–™ï¼ˆå¯åœ¨â€œè®¾å¤‡â€åˆ†ç±»ä¸‹çœ‹åˆ°è‡ªåŠ¨ç”Ÿæˆçš„è®¾å¤‡ç‰©æ–™ï¼‰
- MES ä»“储 â†’ åº“存查询 / åº“存流水查询(查看设备仓数量与流水)
## ä¸šåŠ¡æµç¨‹ä¸Žæ•°æ®å¸¦å…¥
1. æ–°å¢žè®¾å¤‡ï¼ˆå•条/Excel å¯¼å…¥ï¼‰â†’ åŽç«¯åœ¨åŒä¸€äº‹åŠ¡å†…è‡ªåŠ¨å®Œæˆï¼š
   - åˆ›å»º MDM ç‰©æ–™ï¼ˆç±»åž‹=设备、分类=设备、单位=台、编码=设备编码、名称=设备名称、规格=设备规格型号)
   - åŒæ­¥åˆ›å»º MES ç‰©æ–™ï¼ˆç¼–码/名称/规格与 MDM å¯¹é½ï¼Œä¸¤å¥—物料 id ç›¸ç­‰ï¼‰
   - è½è®¾å¤‡å°è´¦å¹¶å›žå†™ `itemId`(设备详情/列表可查)
   - ç”Ÿæˆä¸€æ¡åº“存流水并入设备仓(SYS-EQUIPMENT / SYS-EQUIP-LOC-01 / SYS-EQUIP-BIN-01),库存数量 +1
2. ç¼–辑设备(单条/Excel æ›´æ–°ï¼‰â†’ åªæ”¹è®¾å¤‡å°è´¦ï¼Œä¸é‡å¤å»ºç‰©æ–™ã€ä¸é‡å¤å…¥åº“,`itemId` ä¿æŒä¸å˜
3. åˆ é™¤è®¾å¤‡ â†’ å·²ç”Ÿæˆç‰©æ–™å¹¶å…¥è®¾å¤‡ä»“的设备禁止删除(需先通过库存调整处理库存)
## API
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| POST | /mes/dv-machinery/create | æ–°å¢žè®¾å¤‡ï¼ˆè‡ªåŠ¨å»ºç‰©æ–™å¹¶å…¥åº“ï¼‰ |
| PUT | /mes/dv-machinery/update | ç¼–辑设备(不重复建物料/入库) |
| DELETE | /mes/dv-machinery/delete?id= | åˆ é™¤è®¾å¤‡ï¼ˆå·²å…¥è®¾å¤‡ä»“则拦截) |
| POST | /mes/dv-machinery/import | Excel å¯¼å…¥ï¼ˆåˆ›å»ºè¡ŒåŒæ ·å»ºç‰©æ–™å¹¶å…¥åº“) |
| GET | /mes/dv-machinery/page | è®¾å¤‡åˆ†é¡µåˆ—表 |
| GET | /mes/dv-machinery/get?id= | è®¾å¤‡è¯¦æƒ… |
**请求参数:**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| code | String | æ˜¯ | è®¾å¤‡ç¼–码(将作为对应物料的物料编码) |
| name | String | æ˜¯ | è®¾å¤‡åç§°ï¼ˆå°†ä½œä¸ºå¯¹åº”物料的物料名称) |
| specification | String | å¦ | è§„格型号(同步到物料规格) |
| machineryTypeId | Long | æ˜¯ | è®¾å¤‡ç±»åž‹ |
| workshopId | Long | æ˜¯ | æ‰€å±žè½¦é—´ |
| status | Integer | æ˜¯ | è®¾å¤‡çŠ¶æ€ |
新增/导入时前端**无需传 `itemId`**(系统自动生成并回写)。
**响应字段新增(`get` / `page` / `simple-list` è¿”回的 RespVO ä¸­ï¼‰ï¼š**
| å­—段 | ç±»åž‹ | è¯´æ˜Ž |
|------|------|------|
| itemId | Long | è¯¥è®¾å¤‡å¯¹åº”的物料编号(=MDM ç‰©æ–™ id,同时等于 MES ç‰©æ–™ id) |
**关于创建响应:** `POST /create` è¿”回体 `data` ä»ä¸º `Long`(新建设备 id),不直接携带 `itemId`。前端保存成功后若需立即展示对应物料编号,可再调用 `GET /get?id=<新id>` å– `data.itemId`;`/page`、`/simple-list` åˆ—表行也会返回该字段。
**详情响应示例:**
```json
{
  "code": 0,
  "data": { "id": 1024, "code": "EQ-001", "itemId": 100001 }
}
```
## å­—段展示规则
| å­—段 | å±•示位置 | è¯´æ˜Ž |
|------|----------|------|
| å¯¹åº”物料编号(itemId) | è®¾å¤‡åˆ—表、详情 | åŽç«¯è‡ªåŠ¨ç”Ÿæˆï¼›å¯ç”¨äºŽè·³è½¬ MDM ç‰©æ–™è¯¦æƒ…或按物料查库存 |
| è®¾å¤‡ä»“库存 | åº“存查询页(仓库=设备仓) | æ–°å»ºè®¾å¤‡è‡ªåŠ¨å…¥è®¾å¤‡ä»“ï¼Œæ•°é‡ä¸º 1 |
## ä¸šåŠ¡è§„åˆ™è¯´æ˜Ž
| åœºæ™¯ | è§„则 |
|------|------|
| æ–°å¢žè®¾å¤‡ | åŒä¸€äº‹åŠ¡ï¼šå»º MDM ç‰©æ–™ â†’ åŒæ­¥ MES ç‰©æ–™ â†’ è½å°è´¦ â†’ å…¥è®¾å¤‡ä»“(+1)。任一步失败整体回滚,不留脏数据 |
| ç¼–辑设备 | ä¸é‡å»ºç‰©æ–™ã€ä¸å…¥åº“ï¼›`itemId` åªè¯»ä¸å›žä¼  |
| åˆ é™¤è®¾å¤‡ | `itemId` éžç©ºçš„设备禁止删除(防止库存流水失去业务主体),需先做库存调整 |
| Excel å¯¼å…¥ | åˆ›å»ºè¡Œä¸Žå•条新增走同一套“建物料 + å…¥è®¾å¤‡ä»“”逻辑;编码冲突行报错不落库 |
| ç¼ºä¸»æ•°æ® | è‹¥â€œè®¾å¤‡â€åˆ†ç±»/“台”单位或设备仓未初始化,新增/导入报“主数据未初始化”,提示联系管理员 |
## æ³¨æ„äº‹é¡¹
- è®¾å¤‡ç¼–码即物料编码,请保持设备编码在物料维度也唯一(系统对物料编码做唯一校验,冲突会导致新增失败)。
- åˆ—表/详情接口返回的 `itemId` å¯åœ¨â€œåº“å­˜/流水”查询中作为筛选条件查看该设备在设备仓的库存与流水。
- è‹¥éœ€åœ¨ MDM ç‰©æ–™é¡µæŒ‰åˆ†ç±»ç­›é€‰æŸ¥çœ‹è®¾å¤‡ç‰©æ–™ï¼Œé€‰ä¸­â€œè®¾å¤‡â€åˆ†ç±»å³å¯ã€‚
- æ•°æ®åº“需先执行初始化脚本 `docs/sql/equipment_material_stock_link.sql`(新增 `mes_dv_machinery.item_id`、“设备”分类/类型、“台”单位),否则新建设备会提示主数据未初始化。
docs/sql/bpm_mes_wm_approval_flows.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,140 @@
-- =====================================================================
-- MES ä»“储域 BPM å®¡æ‰¹æµç¨‹æ‰‹å·¥éƒ¨ç½²è„šæœ¬
-- ç›®æ ‡åº“:mom-xgdl(local profile)
--
-- éƒ¨ç½² 6 ä¸ªä¸“用流程,流程定义 KEY_ ä¸Žå„业务监听器 getProcessDefinitionKey() å®Œå…¨ä¸€è‡´ï¼š
--   åˆ†ç±»/KEY_                æµç¨‹å                ç›‘听器
--   misc_receipt_approve     æ‚项入库审批流程       MesWmMiscReceiptStatusListener
--   misc_issue_approve       æ‚项出库审批流程       MesWmMiscIssueStatusListener
--   return_vendor_approve    ä¾›åº”商退货审批流程     MesWmReturnVendorStatusListener
--   item_receipt_approve     é‡‡è´­å…¥åº“审批流程       MesWmItemReceiptStatusListener
--   stock_taking_result_approve  ç›˜ç‚¹ç»“果审批流程   MesWmStockTakingTaskResultStatusListener
--   equipment_receipt_approve    è®¾å¤‡å…¥åº“审批流程   MesWmEquipmentReceiptStatusListener
--
-- BPMN æ¨¡æ¿ï¼šcrm-invoice-audit(candidateStrategy=36 å‘起人提交自动通过)复制并替换 key/名称。
-- çº¦æŸéµå®ˆ bpm-manual-deployment è®°å¿†ï¼š
--   model_type=10;ENGINE_VERSION_ ç•™ NULL(不写空串);META_INFO_ å« sort;deployment=32位无横线ID。
-- =====================================================================
SET NAMES utf8mb4;
-- 1. ACT_RE_DEPLOYMENT -------------------------------------------------
INSERT INTO `mom-xgdl`.`ACT_RE_DEPLOYMENT` (ID_, NAME_, CATEGORY_, KEY_, TENANT_ID_, DEPLOY_TIME_, ENGINE_VERSION_)
VALUES
('10000000000000000000000000000001', '杂项入库审批流程',   'misc_receipt_approve',        '', '', NOW(), NULL),
('10000000000000000000000000000002', '杂项出库审批流程',   'misc_issue_approve',          '', '', NOW(), NULL),
('10000000000000000000000000000003', '供应商退货审批流程', 'return_vendor_approve',       '', '', NOW(), NULL),
('10000000000000000000000000000004', '采购入库审批流程',   'item_receipt_approve',        '', '', NOW(), NULL),
('10000000000000000000000000000005', '盘点结果审批流程',   'stock_taking_result_approve', '', '', NOW(), NULL),
('10000000000000000000000000000006', '设备入库审批流程',   'equipment_receipt_approve',   '', '', NOW(), NULL);
-- 2. ACT_GE_BYTEARRAY(BPMN XML:从 crm-invoice-audit æ¨¡æ¿å¤åˆ¶å¹¶æ›¿æ¢ key/名称)----
INSERT INTO `mom-xgdl`.`ACT_GE_BYTEARRAY` (ID_, REV_, NAME_, DEPLOYMENT_ID_, BYTES_, GENERATED_)
SELECT
  '30000000000000000000000000000001', 1, 'misc_receipt_approve.bpmn',        '10000000000000000000000000000001',
  CAST(REPLACE(REPLACE(CONVERT(BYTES_ USING utf8mb4), 'crm-invoice-audit', 'misc_receipt_approve'),        '开票审批流程', '杂项入库审批流程') AS BINARY), 0
FROM `mom-xgdl`.`ACT_GE_BYTEARRAY` WHERE ID_ = 'c101d3e1-0001-11f2-8a27-00155dad6485'
UNION ALL
SELECT
  '30000000000000000000000000000002', 1, 'misc_issue_approve.bpmn',          '10000000000000000000000000000002',
  CAST(REPLACE(REPLACE(CONVERT(BYTES_ USING utf8mb4), 'crm-invoice-audit', 'misc_issue_approve'),          '开票审批流程', '杂项出库审批流程') AS BINARY), 0
FROM `mom-xgdl`.`ACT_GE_BYTEARRAY` WHERE ID_ = 'c101d3e1-0001-11f2-8a27-00155dad6485'
UNION ALL
SELECT
  '30000000000000000000000000000003', 1, 'return_vendor_approve.bpmn',       '10000000000000000000000000000003',
  CAST(REPLACE(REPLACE(CONVERT(BYTES_ USING utf8mb4), 'crm-invoice-audit', 'return_vendor_approve'),       '开票审批流程', '供应商退货审批流程') AS BINARY), 0
FROM `mom-xgdl`.`ACT_GE_BYTEARRAY` WHERE ID_ = 'c101d3e1-0001-11f2-8a27-00155dad6485'
UNION ALL
SELECT
  '30000000000000000000000000000004', 1, 'item_receipt_approve.bpmn',        '10000000000000000000000000000004',
  CAST(REPLACE(REPLACE(CONVERT(BYTES_ USING utf8mb4), 'crm-invoice-audit', 'item_receipt_approve'),        '开票审批流程', '采购入库审批流程') AS BINARY), 0
FROM `mom-xgdl`.`ACT_GE_BYTEARRAY` WHERE ID_ = 'c101d3e1-0001-11f2-8a27-00155dad6485'
UNION ALL
SELECT
  '30000000000000000000000000000005', 1, 'stock_taking_result_approve.bpmn', '10000000000000000000000000000005',
  CAST(REPLACE(REPLACE(CONVERT(BYTES_ USING utf8mb4), 'crm-invoice-audit', 'stock_taking_result_approve'), '开票审批流程', '盘点结果审批流程') AS BINARY), 0
FROM `mom-xgdl`.`ACT_GE_BYTEARRAY` WHERE ID_ = 'c101d3e1-0001-11f2-8a27-00155dad6485'
UNION ALL
SELECT
  '30000000000000000000000000000006', 1, 'equipment_receipt_approve.bpmn',   '10000000000000000000000000000006',
  CAST(REPLACE(REPLACE(CONVERT(BYTES_ USING utf8mb4), 'crm-invoice-audit', 'equipment_receipt_approve'),   '开票审批流程', '设备入库审批流程') AS BINARY), 0
FROM `mom-xgdl`.`ACT_GE_BYTEARRAY` WHERE ID_ = 'c101d3e1-0001-11f2-8a27-00155dad6485';
-- 3. ACT_RE_PROCDEF(ENGINE_VERSION_ å¿…é¡» NULL,不写空串)----------------
INSERT INTO `mom-xgdl`.`ACT_RE_PROCDEF` (ID_, REV_, CATEGORY_, NAME_, KEY_, VERSION_, DEPLOYMENT_ID_, RESOURCE_NAME_, DGRM_RESOURCE_NAME_, DESCRIPTION_, HAS_START_FORM_KEY_, HAS_GRAPHICAL_NOTATION_, SUSPENSION_STATE_, TENANT_ID_, ENGINE_VERSION_, DERIVED_FROM_, DERIVED_FROM_ROOT_, DERIVED_VERSION_)
VALUES
('misc_receipt_approve:1:10000000000000000000000000000001', 1, 'misc_receipt_approve',        '杂项入库审批流程',   'misc_receipt_approve',        1, '10000000000000000000000000000001', 'misc_receipt_approve.bpmn',        '', '', 0, 0, 1, '', NULL, '', '', 0),
('misc_issue_approve:1:10000000000000000000000000000002', 1, 'misc_issue_approve',          '杂项出库审批流程',   'misc_issue_approve',          1, '10000000000000000000000000000002', 'misc_issue_approve.bpmn',          '', '', 0, 0, 1, '', NULL, '', '', 0),
('return_vendor_approve:1:10000000000000000000000000000003', 1, 'return_vendor_approve',     '供应商退货审批流程', 'return_vendor_approve',       1, '10000000000000000000000000000003', 'return_vendor_approve.bpmn',       '', '', 0, 0, 1, '', NULL, '', '', 0),
('item_receipt_approve:1:10000000000000000000000000000004', 1, 'item_receipt_approve',       '采购入库审批流程',   'item_receipt_approve',        1, '10000000000000000000000000000004', 'item_receipt_approve.bpmn',        '', '', 0, 0, 1, '', NULL, '', '', 0),
('stock_taking_result_approve:1:10000000000000000000000000000005', 1, 'stock_taking_result_approve', '盘点结果审批流程', 'stock_taking_result_approve', 1, '10000000000000000000000000000005', 'stock_taking_result_approve.bpmn', '', '', 0, 0, 1, '', NULL, '', '', 0),
('equipment_receipt_approve:1:10000000000000000000000000000006', 1, 'equipment_receipt_approve', '设备入库审批流程', 'equipment_receipt_approve',  1, '10000000000000000000000000000006', 'equipment_receipt_approve.bpmn',  '', '', 0, 0, 1, '', NULL, '', '', 0);
-- 4. ACT_RE_MODEL(META_INFO_ å« sort;EDITOR_SOURCE_VALUE_ID_ å¯¹é½ BPMN bytearray)----
INSERT INTO `mom-xgdl`.`ACT_RE_MODEL` (ID_, REV_, NAME_, KEY_, CATEGORY_, CREATE_TIME_, LAST_UPDATE_TIME_, VERSION_, META_INFO_, DEPLOYMENT_ID_, EDITOR_SOURCE_VALUE_ID_, EDITOR_SOURCE_EXTRA_VALUE_ID_, TENANT_ID_)
VALUES
('20000000000000000000000000000001', 1, '杂项入库审批流程',   'misc_receipt_approve',        'misc_receipt_approve',        NOW(), NOW(), 1,
 '{"allowCancelRunningProcess":true,"allowWithdrawTask":false,"autoApprovalType":0,"description":"","formCustomCreatePath":"","formCustomViewPath":"","formId":1,"formType":10,"icon":null,"managerUserIds":[1],"printTemplateSetting":{"enable":false,"template":""},"processAfterTriggerSetting":null,"processBeforeTriggerSetting":null,"processIdRule":{"enable":false,"infix":"","length":5,"postfix":"","prefix":""},"sort":1785465606001,"startDeptIds":[],"startUserIds":[],"summarySetting":{"enable":false,"summary":[]},"taskAfterTriggerSetting":null,"taskBeforeTriggerSetting":null,"titleSetting":{"enable":false,"title":""},"type":10,"visible":true}',
 '10000000000000000000000000000001', '30000000000000000000000000000001', NULL, ''),
('20000000000000000000000000000002', 1, '杂项出库审批流程',   'misc_issue_approve',          'misc_issue_approve',          NOW(), NOW(), 1,
 '{"allowCancelRunningProcess":true,"allowWithdrawTask":false,"autoApprovalType":0,"description":"","formCustomCreatePath":"","formCustomViewPath":"","formId":1,"formType":10,"icon":null,"managerUserIds":[1],"printTemplateSetting":{"enable":false,"template":""},"processAfterTriggerSetting":null,"processBeforeTriggerSetting":null,"processIdRule":{"enable":false,"infix":"","length":5,"postfix":"","prefix":""},"sort":1785465606002,"startDeptIds":[],"startUserIds":[],"summarySetting":{"enable":false,"summary":[]},"taskAfterTriggerSetting":null,"taskBeforeTriggerSetting":null,"titleSetting":{"enable":false,"title":""},"type":10,"visible":true}',
 '10000000000000000000000000000002', '30000000000000000000000000000002', NULL, ''),
('20000000000000000000000000000003', 1, '供应商退货审批流程', 'return_vendor_approve',       'return_vendor_approve',       NOW(), NOW(), 1,
 '{"allowCancelRunningProcess":true,"allowWithdrawTask":false,"autoApprovalType":0,"description":"","formCustomCreatePath":"","formCustomViewPath":"","formId":1,"formType":10,"icon":null,"managerUserIds":[1],"printTemplateSetting":{"enable":false,"template":""},"processAfterTriggerSetting":null,"processBeforeTriggerSetting":null,"processIdRule":{"enable":false,"infix":"","length":5,"postfix":"","prefix":""},"sort":1785465606003,"startDeptIds":[],"startUserIds":[],"summarySetting":{"enable":false,"summary":[]},"taskAfterTriggerSetting":null,"taskBeforeTriggerSetting":null,"titleSetting":{"enable":false,"title":""},"type":10,"visible":true}',
 '10000000000000000000000000000003', '30000000000000000000000000000003', NULL, ''),
('20000000000000000000000000000004', 1, '采购入库审批流程',   'item_receipt_approve',        'item_receipt_approve',        NOW(), NOW(), 1,
 '{"allowCancelRunningProcess":true,"allowWithdrawTask":false,"autoApprovalType":0,"description":"","formCustomCreatePath":"","formCustomViewPath":"","formId":1,"formType":10,"icon":null,"managerUserIds":[1],"printTemplateSetting":{"enable":false,"template":""},"processAfterTriggerSetting":null,"processBeforeTriggerSetting":null,"processIdRule":{"enable":false,"infix":"","length":5,"postfix":"","prefix":""},"sort":1785465606004,"startDeptIds":[],"startUserIds":[],"summarySetting":{"enable":false,"summary":[]},"taskAfterTriggerSetting":null,"taskBeforeTriggerSetting":null,"titleSetting":{"enable":false,"title":""},"type":10,"visible":true}',
 '10000000000000000000000000000004', '30000000000000000000000000000004', NULL, ''),
('20000000000000000000000000000005', 1, '盘点结果审批流程',   'stock_taking_result_approve', 'stock_taking_result_approve', NOW(), NOW(), 1,
 '{"allowCancelRunningProcess":true,"allowWithdrawTask":false,"autoApprovalType":0,"description":"","formCustomCreatePath":"","formCustomViewPath":"","formId":1,"formType":10,"icon":null,"managerUserIds":[1],"printTemplateSetting":{"enable":false,"template":""},"processAfterTriggerSetting":null,"processBeforeTriggerSetting":null,"processIdRule":{"enable":false,"infix":"","length":5,"postfix":"","prefix":""},"sort":1785465606005,"startDeptIds":[],"startUserIds":[],"summarySetting":{"enable":false,"summary":[]},"taskAfterTriggerSetting":null,"taskBeforeTriggerSetting":null,"titleSetting":{"enable":false,"title":""},"type":10,"visible":true}',
 '10000000000000000000000000000005', '30000000000000000000000000000005', NULL, ''),
('20000000000000000000000000000006', 1, '设备入库审批流程',   'equipment_receipt_approve',   'equipment_receipt_approve',   NOW(), NOW(), 1,
 '{"allowCancelRunningProcess":true,"allowWithdrawTask":false,"autoApprovalType":0,"description":"","formCustomCreatePath":"","formCustomViewPath":"","formId":1,"formType":10,"icon":null,"managerUserIds":[1],"printTemplateSetting":{"enable":false,"template":""},"processAfterTriggerSetting":null,"processBeforeTriggerSetting":null,"processIdRule":{"enable":false,"infix":"","length":5,"postfix":"","prefix":""},"sort":1785465606006,"startDeptIds":[],"startUserIds":[],"summarySetting":{"enable":false,"summary":[]},"taskAfterTriggerSetting":null,"taskBeforeTriggerSetting":null,"titleSetting":{"enable":false,"title":""},"type":10,"visible":true}',
 '10000000000000000000000000000006', '30000000000000000000000000000006', NULL, '');
-- 5. bpm_process_definition_info(model_type=10,deleted=0)---------------
INSERT INTO `mom-xgdl`.`bpm_process_definition_info`
(process_definition_id, model_id, model_type, category, icon, description, form_type, form_id, form_conf, form_fields, simple_model, visible, sort, start_user_ids, start_dept_ids, manager_user_ids, allow_cancel_running_process, allow_withdraw_task, deleted, creator, create_time, updater, update_time)
VALUES
('misc_receipt_approve:1:10000000000000000000000000000001', '20000000000000000000000000000001', 10, 'misc_receipt_approve', NULL, NULL, 10, 1,
 '{"form":{"layout":"horizontal","labelAlign":"right","size":"middle","colon":false,"labelCol":{"style":{"width":"125px"}},"wrapperCol":{"span":24},"labelWidth":"100px"},"resetBtn":{"show":false,"innerText":"重置"},"submitBtn":{"show":true,"innerText":"提交"}}',
 '[]', NULL, 1, 1785465606001, NULL, NULL, '1', 1, 1, 0, '1', NOW(), '1', NOW()),
('misc_issue_approve:1:10000000000000000000000000000002', '20000000000000000000000000000002', 10, 'misc_issue_approve', NULL, NULL, 10, 1,
 '{"form":{"layout":"horizontal","labelAlign":"right","size":"middle","colon":false,"labelCol":{"style":{"width":"125px"}},"wrapperCol":{"span":24},"labelWidth":"100px"},"resetBtn":{"show":false,"innerText":"重置"},"submitBtn":{"show":true,"innerText":"提交"}}',
 '[]', NULL, 1, 1785465606002, NULL, NULL, '1', 1, 1, 0, '1', NOW(), '1', NOW()),
('return_vendor_approve:1:10000000000000000000000000000003', '20000000000000000000000000000003', 10, 'return_vendor_approve', NULL, NULL, 10, 1,
 '{"form":{"layout":"horizontal","labelAlign":"right","size":"middle","colon":false,"labelCol":{"style":{"width":"125px"}},"wrapperCol":{"span":24},"labelWidth":"100px"},"resetBtn":{"show":false,"innerText":"重置"},"submitBtn":{"show":true,"innerText":"提交"}}',
 '[]', NULL, 1, 1785465606003, NULL, NULL, '1', 1, 1, 0, '1', NOW(), '1', NOW()),
('item_receipt_approve:1:10000000000000000000000000000004', '20000000000000000000000000000004', 10, 'item_receipt_approve', NULL, NULL, 10, 1,
 '{"form":{"layout":"horizontal","labelAlign":"right","size":"middle","colon":false,"labelCol":{"style":{"width":"125px"}},"wrapperCol":{"span":24},"labelWidth":"100px"},"resetBtn":{"show":false,"innerText":"重置"},"submitBtn":{"show":true,"innerText":"提交"}}',
 '[]', NULL, 1, 1785465606004, NULL, NULL, '1', 1, 1, 0, '1', NOW(), '1', NOW()),
('stock_taking_result_approve:1:10000000000000000000000000000005', '20000000000000000000000000000005', 10, 'stock_taking_result_approve', NULL, NULL, 10, 1,
 '{"form":{"layout":"horizontal","labelAlign":"right","size":"middle","colon":false,"labelCol":{"style":{"width":"125px"}},"wrapperCol":{"span":24},"labelWidth":"100px"},"resetBtn":{"show":false,"innerText":"重置"},"submitBtn":{"show":true,"innerText":"提交"}}',
 '[]', NULL, 1, 1785465606005, NULL, NULL, '1', 1, 1, 0, '1', NOW(), '1', NOW()),
('equipment_receipt_approve:1:10000000000000000000000000000006', '20000000000000000000000000000006', 10, 'equipment_receipt_approve', NULL, NULL, 10, 1,
 '{"form":{"layout":"horizontal","labelAlign":"right","size":"middle","colon":false,"labelCol":{"style":{"width":"125px"}},"wrapperCol":{"span":24},"labelWidth":"100px"},"resetBtn":{"show":false,"innerText":"重置"},"submitBtn":{"show":true,"innerText":"提交"}}',
 '[]', NULL, 1, 1785465606006, NULL, NULL, '1', 1, 1, 0, '1', NOW(), '1', NOW());
-- =====================================================================
-- é™„录:M6 èœå•/权限补充(已在 mom-xgdl æ‰§è¡Œï¼‰
-- é‡å¤æ‰§è¡Œä¼šä¸»é”®å†²çªï¼Œæ³¨æ„å¹‚等。
-- =====================================================================
-- SN ç è¡¥"更新"按钮(出入库/详情接口依赖 mes:wm-sn:update)
INSERT INTO `mom-xgdl`.`system_menu`
(id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
VALUES
(1065725, 'SN ç æ›´æ–°', 'mes:wm-sn:update', 3, 3, 5897, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0');
-- è®¾å¤‡å…¥åº“单菜单(仓储物流 5780 ä¸‹ï¼Œç»„ä»¶ wls/equipmentreceipt/index)
INSERT INTO `mom-xgdl`.`system_menu`
(id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
VALUES
(1065726, '设备入库', '', 2, 20, 5780, 'equipment-receipt', 'fa-solid:box-open', 'wls/equipmentreceipt/index', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'),
(1065727, '设备入库查询', 'mes:wm:equipment-receipt:query', 3, 1, 1065726, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'),
(1065728, '设备入库创建', 'mes:wm:equipment-receipt:create', 3, 2, 1065726, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'),
(1065729, '设备入库更新', 'mes:wm:equipment-receipt:update', 3, 3, 1065726, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'),
(1065730, '设备入库删除', 'mes:wm:equipment-receipt:delete', 3, 4, 1065726, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'),
(1065731, '设备入库提交', 'mes:wm:equipment-receipt:submit', 3, 5, 1065726, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'),
(1065732, '设备入库执行', 'mes:wm:equipment-receipt:finish', 3, 6, 1065726, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'),
(1065733, '设备入库取消', 'mes:wm:equipment-receipt:cancel', 3, 7, 1065726, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0');
docs/sql/equipment_material_stock_link.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,48 @@
-- =====================================================================
-- è®¾å¤‡å°è´¦è”动设备仓:设备物料主数据初始化脚本(MySQL)
-- ç›®æ ‡åº“:mom-xgdl(本地 dev åº“)。其它库执行前请核对主键 id æ˜¯å¦å†²çªã€‚
--
-- èƒŒæ™¯ï¼š
--   1) MES è®¾å¤‡åˆ›å»ºæ—¶è‡ªåŠ¨ç”Ÿæˆå¯¹åº”ç‰©æ–™ï¼Œè¿›å…¥è®¾å¤‡ä»“åº“å­˜ï¼Œå…³è”é“¾ä¸ºï¼š
--      mes_dv_machinery.item_id -> mdm_item.id(= mes_md_item.id å¯¹é½ï¼‰
--   2) è®¾å¤‡ç‰©æ–™å¤ç”¨äº† MDM/MES ä¸¤å¥—主数据,本脚本补齐:
--      - åˆ†ç±»/类型:“设备”(mes_md_item_type ä¸Ž mdm_item_category ä½¿ç”¨åŒä¸€ id å¯¹é½ï¼‰
--      - è®¡é‡å•位:“台”(mes_md_unit_measure ä¸Ž mdm_unit_measure)
--      - è®¾å¤‡ä»“/库区/库位:SYS-EQUIPMENT / SYS-EQUIP-LOC-01 / SYS-EQUIP-BIN-01
--        ï¼ˆå¦‚目标库缺失需另行初始化;代码仅在缺失时给出“主数据未初始化”提示)
--
-- çº¦æŸï¼šè„šæœ¬ä¸å« tenant_id;ADD COLUMN å‰åšå­˜åœ¨æ€§æ£€æŸ¥ï¼ˆMySQL ä¸æ”¯æŒ IF NOT EXISTS)。
-- =====================================================================
-- 1. mes_dv_machinery å¢žåŠ  item_id(设备对应物料编号)
SET @col_exists = (SELECT COUNT(*) FROM information_schema.columns
                   WHERE table_schema = 'mom-xgdl' AND table_name = 'mes_dv_machinery' AND column_name = 'item_id');
SET @ddl = IF(@col_exists = 0,
              'ALTER TABLE `mes_dv_machinery` ADD COLUMN `item_id` BIGINT NULL COMMENT ''对应物料编号(mdm_item.id)'' AFTER `workstation_id`',
              'SELECT 1');
PREPARE s FROM @ddl;
EXECUTE s;
DEALLOCATE PREPARE s;
-- 2. MES ç‰©æ–™ç±»åž‹ï¼šâ€œè®¾å¤‡â€ï¼ˆcode=EQUIPMENT,作为设备物料的分类/类型)
INSERT INTO `mes_md_item_type` (`id`, `code`, `name`, `parent_id`, `item_or_product`, `sort`, `status`)
SELECT 100, 'EQUIPMENT', '设备', 0, 'ITEM', 1, 0 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `mes_md_item_type` WHERE `code` = 'EQUIPMENT' AND `deleted` = 0);
-- 3. MDM ç‰©æ–™åˆ†ç±»ï¼šâ€œè®¾å¤‡â€ï¼ˆid ä¸Ž MES ç±»åž‹ id=100 å¯¹é½ï¼Œä»£ç æ®æ­¤è§£æž MDM categoryId)
INSERT INTO `mdm_item_category` (`id`, `parent_id`, `code`, `name`, `item_type`, `item_or_product`, `sort`, `status`)
SELECT 100, 0, 'EQUIPMENT', '设备', 4, 'ITEM', 1, 0 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `mdm_item_category` WHERE `code` = 'EQUIPMENT' AND `deleted` = 0);
-- 4. MES è®¡é‡å•位:“台”(code=TAI)
INSERT INTO `mes_md_unit_measure` (`id`, `code`, `name`, `primary_flag`, `primary_id`, `change_rate`, `status`)
SELECT 100, 'TAI', '台', 1, NULL, 1, 0 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `mes_md_unit_measure` WHERE `code` = 'TAI' AND `deleted` = 0);
-- 5. MDM è®¡é‡å•位:“台”(code=TAI)
INSERT INTO `mdm_unit_measure` (`id`, `code`, `name`, `primary_flag`, `primary_id`, `change_rate`, `status`)
SELECT 100, 'TAI', '台', 1, NULL, 1, 0 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `mdm_unit_measure` WHERE `code` = 'TAI' AND `deleted` = 0);
-- è¯´æ˜Žï¼šè‹¥ç›®æ ‡åº“中 id=100 ä¸Žå·²æœ‰è®°å½•冲突,可将上面 4 å¤„ id è°ƒæ•´ä¸ºåŒä¸€ç©ºé—² id,
--       å¹¶ä¿è¯ mes_md_item_type ä¸Ž mdm_item_category çš„“设备”行 id ç›¸ç­‰ï¼ˆä»£ç æ®æ­¤å– MDM categoryId)。
docs/sql/equipment_receipt.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,43 @@
-- =============================================
-- M5:独立设备入库单
-- 1. mes_wm_equipment_receipt(主表)
-- 2. mes_wm_equipment_receipt_line(行表:从设备台账选择,固定设备仓入库)
-- ç›®æ ‡åº“:mom-xgdl(local profile)
-- =============================================
CREATE TABLE IF NOT EXISTS `mes_wm_equipment_receipt` (
    `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
    `code` varchar(64) NOT NULL COMMENT '单据编码',
    `name` varchar(255) DEFAULT NULL COMMENT '单据名称',
    `receipt_date` datetime DEFAULT NULL COMMENT '入库日期',
    `source` varchar(255) DEFAULT NULL COMMENT '入库来源',
    `status` tinyint NOT NULL DEFAULT '0' COMMENT '状态',
    `process_instance_id` varchar(64) DEFAULT NULL COMMENT 'BPM æµç¨‹å®žä¾‹ç¼–号',
    `remark` varchar(500) DEFAULT NULL COMMENT '备注',
    `creator` varchar(64) DEFAULT '' COMMENT '创建者',
    `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `updater` varchar(64) DEFAULT '' COMMENT '更新者',
    `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
    PRIMARY KEY (`id`),
    KEY `idx_code` (`code`),
    KEY `idx_status` (`status`)
) ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='设备入库单';
CREATE TABLE IF NOT EXISTS `mes_wm_equipment_receipt_line` (
    `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
    `receipt_id` bigint NOT NULL COMMENT '入库单编号',
    `machinery_id` bigint NOT NULL COMMENT '设备台账编号',
    `item_id` bigint DEFAULT NULL COMMENT '设备物料编号(mdm_item.id)',
    `quantity` decimal(24,6) NOT NULL DEFAULT '1.000000' COMMENT '入库数量',
    `remark` varchar(500) DEFAULT NULL COMMENT '备注',
    `creator` varchar(64) DEFAULT '' COMMENT '创建者',
    `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `updater` varchar(64) DEFAULT '' COMMENT '更新者',
    `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
    PRIMARY KEY (`id`),
    KEY `idx_receipt_id` (`receipt_id`),
    KEY `idx_machinery_id` (`machinery_id`),
    KEY `idx_item_id` (`item_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='设备入库单行';
docs/sql/sn_item_chain.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,46 @@
-- =============================================
-- M4:SN å•品库存轻量闭环
-- 1. mes_wm_sn å¢žåŠ åœ¨åº“åº“ä½ç»´åº¦åˆ—ï¼ˆstatus/batch_id/remark è¡¨ä¸­å·²å­˜åœ¨ï¼‰
-- 2. mes_wm_transaction å¢žåŠ  sn_code åˆ—
-- ç›®æ ‡åº“:mom-xgdl(local profile)
-- =============================================
-- 1. mes_wm_sn.warehouse_id(在库仓库 ID)
SET @exists = (SELECT COUNT(*) FROM information_schema.columns
               WHERE table_schema = DATABASE() AND table_name = 'mes_wm_sn' AND column_name = 'warehouse_id');
SET @sql = IF(@exists = 0,
              'ALTER TABLE mes_wm_sn ADD COLUMN warehouse_id BIGINT NULL COMMENT ''在库仓库 ID'' AFTER batch_id',
              'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- 2. mes_wm_sn.location_id(在库库区 ID)
SET @exists = (SELECT COUNT(*) FROM information_schema.columns
               WHERE table_schema = DATABASE() AND table_name = 'mes_wm_sn' AND column_name = 'location_id');
SET @sql = IF(@exists = 0,
              'ALTER TABLE mes_wm_sn ADD COLUMN location_id BIGINT NULL COMMENT ''在库库区 ID'' AFTER warehouse_id',
              'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- 3. mes_wm_sn.area_id(在库库位 ID)
SET @exists = (SELECT COUNT(*) FROM information_schema.columns
               WHERE table_schema = DATABASE() AND table_name = 'mes_wm_sn' AND column_name = 'area_id');
SET @sql = IF(@exists = 0,
              'ALTER TABLE mes_wm_sn ADD COLUMN area_id BIGINT NULL COMMENT ''在库库位 ID'' AFTER location_id',
              'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- 4. mes_wm_transaction.sn_code(SN ç ï¼‰
SET @exists = (SELECT COUNT(*) FROM information_schema.columns
               WHERE table_schema = DATABASE() AND table_name = 'mes_wm_transaction' AND column_name = 'sn_code');
SET @sql = IF(@exists = 0,
              'ALTER TABLE mes_wm_transaction ADD COLUMN sn_code VARCHAR(100) NULL COMMENT ''SN ç '' AFTER batch_code',
              'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
docs/sql/stock_taking_plan_auto_generate.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,35 @@
-- =============================================
-- M2:定期盘点自动调度
-- mes_wm_stock_taking_plan å¢žåŠ å®šæœŸè‡ªåŠ¨ç”Ÿæˆç›¸å…³åˆ—
-- ç›®æ ‡åº“:mom-xgdl(local profile)
-- =============================================
-- 1. mes_wm_stock_taking_plan.auto_generate(是否定期自动生成盘点任务)
SET @exists = (SELECT COUNT(*) FROM information_schema.columns
               WHERE table_schema = DATABASE() AND table_name = 'mes_wm_stock_taking_plan' AND column_name = 'auto_generate');
SET @sql = IF(@exists = 0,
              'ALTER TABLE mes_wm_stock_taking_plan ADD COLUMN auto_generate TINYINT(1) NULL DEFAULT b''0'' COMMENT ''是否定期自动生成盘点任务'' AFTER frozen',
              'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- 2. mes_wm_stock_taking_plan.generate_cron(自动生成周期 cron è¡¨è¾¾å¼ï¼‰
SET @exists = (SELECT COUNT(*) FROM information_schema.columns
               WHERE table_schema = DATABASE() AND table_name = 'mes_wm_stock_taking_plan' AND column_name = 'generate_cron');
SET @sql = IF(@exists = 0,
              'ALTER TABLE mes_wm_stock_taking_plan ADD COLUMN generate_cron VARCHAR(64) NULL COMMENT ''自动生成周期 cron è¡¨è¾¾å¼ï¼ˆauto_generate=1 æ—¶å¿…填)'' AFTER auto_generate',
              'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- 3. mes_wm_stock_taking_plan.last_generate_time(上次自动生成时间)
SET @exists = (SELECT COUNT(*) FROM information_schema.columns
               WHERE table_schema = DATABASE() AND table_name = 'mes_wm_stock_taking_plan' AND column_name = 'last_generate_time');
SET @sql = IF(@exists = 0,
              'ALTER TABLE mes_wm_stock_taking_plan ADD COLUMN last_generate_time DATETIME NULL COMMENT ''上次自动生成时间'' AFTER generate_cron',
              'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
docs/sql/stock_taking_result_approval.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
-- =============================================
-- M1:盘点结果审批 BPM
-- mes_wm_stock_taking_task å¢žåŠ  process_instance_id åˆ—
-- ç”¨äºŽå›žå†™"盘点结果已提交 BPM å®¡æ‰¹"的流程实例编号
-- ç›®æ ‡åº“:mom-xgdl(local profile)
-- =============================================
-- 1. mes_wm_stock_taking_task.process_instance_id
SET @exists = (SELECT COUNT(*) FROM information_schema.columns
               WHERE table_schema = DATABASE() AND table_name = 'mes_wm_stock_taking_task' AND column_name = 'process_instance_id');
SET @sql = IF(@exists = 0,
              'ALTER TABLE mes_wm_stock_taking_task ADD COLUMN process_instance_id VARCHAR(64) NULL COMMENT ''BPM æµç¨‹å®žä¾‹ç¼–号(非空表示盘点结果已提交审批)'' AFTER status',
              'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
docs/wm_barcode_scan_render_integration.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,68 @@
# æ¡ç ç»„合 / æœåŠ¡ç«¯æˆå›¾ / æ‰«ç è§£æž - å‰ç«¯è”调方案
## æ¶‰åŠé¡µé¢
- æ¡ç é…ç½®ç®¡ç†é¡µï¼ˆ`contentFormat` ç¼–辑)
- æ ‡ç­¾æ‰“印 / æ¡ç å±•示页(服务端成图预览)
- æ‰«ç ï¼ˆPDA / æ‰‹æœºæ‰«ç æžªï¼‰è§¦å‘业务解析入口
## ä¸šåŠ¡æµç¨‹ä¸Žæ•°æ®å¸¦å…¥
1. æ¡ç é…ç½® -> å†…容生成:配置 `contentFormat` æ”¯æŒç»„合占位符 `{BUSINESSCODE}`(业务编码)、`{BUSINESSNAME}`(业务名称)。前端传 `bizType`、`bizCode`、`bizName` è°ƒç”ŸæˆæŽ¥å£ï¼ŒåŽç«¯æŒ‰é…ç½®æ¨¡æ¿æ›¿æ¢å ä½ç¬¦ã€æ¸…空未知占位符,返回最终条码内容。
2. æœåŠ¡ç«¯æˆå›¾ï¼šå‰ç«¯æŠŠæ¡ç å†…å®¹ + æ ¼å¼ï¼ˆ1 QRCode / 2 EAN-13 / 3 Code39 / 4 UPC-A / é»˜è®¤ Code128)+ å®½é«˜ä¼ ç»™ `POST /render`,后端用 zxing ç”Ÿæˆå›¾ç‰‡ï¼Œè¿”回 Base64 data-URL ä¾› `<img>` ç›´æŽ¥é¢„览(不持久化落库)。
3. æ‰«ç è§£æžï¼šå‰ç«¯æŠŠæ‰«åˆ°çš„内容传给 `POST /parse`,后端先精确匹配条码表,再按启用配置的 `contentFormat` åå‘正则匹配,返回命中的 `bizType` / `bizCode` / `bizName`,前端据此跳转对应业务单据。
## API
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| GET | /mes/wm/barcode/generate-content?bizType=&bizCode=&bizName= | æŒ‰é…ç½®ç”Ÿæˆæ¡ç å†…容 |
| POST | /mes/wm/barcode/render | æœåŠ¡ç«¯æˆå›¾ï¼ˆè¿”å›ž Base64 å›¾ç‰‡ï¼‰ |
| POST | /mes/wm/barcode/parse | æ‰«ç è§£æžï¼ˆè¿”回业务字段) |
**请求参数(render):**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| content | String | æ˜¯ | æ¡ç å†…容(可由 generate-content è¿”回) |
| format | Integer | å¦ | æ¡ç æ ¼å¼ï¼š1 QRCode / 2 EAN-13 / 3 Code39 / 4 UPC-A / é»˜è®¤ Code128 |
| width | Integer | å¦ | å›¾ç‰‡å®½åº¦ï¼ˆé»˜è®¤ 200) |
| height | Integer | å¦ | å›¾ç‰‡é«˜åº¦ï¼ˆé»˜è®¤ 200) |
**响应(render):** `{ "code": 200, "data": "data:image/png;base64,..." }`
**请求参数(parse):**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| content | String | æ˜¯ | æ‰«æå¾—到的条码内容 |
**响应字段(parse):**
| å­—段 | ç±»åž‹ | è¯´æ˜Ž |
|------|------|------|
| bizType | Integer | å‘½ä¸­çš„业务类型 |
| bizCode | String | å‘½ä¸­çš„业务编码 |
| bizName | String | å‘½ä¸­çš„业务名称 |
## å­—段展示规则
| å­—段 | å±•示位置 | è¯´æ˜Ž |
|------|----------|------|
| contentFormat | æ¡ç é…ç½®ç¼–辑页 | æ”¯æŒ `{BUSINESSCODE}`、`{BUSINESSNAME}` ç»„合 |
| æ¡ç å›¾ç‰‡ | æ ‡ç­¾ / åˆ—表 | `render` è¿”回 Base64 ç›´æŽ¥ `<img src>` |
| è§£æžç»“æžœ | æ‰«ç ç»“果页 | å‘½ä¸­åŽå±•示业务编码并跳转 |
## ä¸šåŠ¡è§„åˆ™è¯´æ˜Ž
| åœºæ™¯ | è§„则 |
|------|------|
| ç”Ÿæˆå†…容 | ä»…替换配置中存在的占位符;未配置的未知占位符会被清空 |
| æœåŠ¡ç«¯æˆå›¾ | åªåšå³æ—¶é¢„览,不落库;正式附件仍走 system å­˜å‚¨é™„件机制 |
| è§£æž | ä¼˜å…ˆç²¾ç¡®åŒ¹é…æ¡ç è¡¨ï¼›æœªå‘½ä¸­å†æŒ‰å¯ç”¨é…ç½® `contentFormat` åå‘匹配;均未命中返回空 |
| æ ¼å¼æ”¯æŒ | äºŒç»´ç ä¸Žä¸€ç»´ç ï¼ˆEAN-13 / Code39 / UPC-A / Code128) |
## æ³¨æ„äº‹é¡¹
- æ¡ç å›¾ç‰‡ä¸º Base64 data-URL,适合即时预览;如需持久存储按「文件上传规则」走 `/system/storage-*`。
- `generate-content` éœ€è¦å­˜åœ¨å¯¹åº”的启用条码配置,否则返回原样或空。
docs/wm_batch_code_requirements.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,152 @@
# ä»“储(WM)批量补码需求说明
> æœ¬æ–‡æ¡£æ•´ç†çš„æ˜¯ **2026-09-08 ç¡®è®¤çš„æœ¬è½®æ‰¹é‡è¡¥ç éœ€æ±‚包**(M1~M5),用于后续开发基线。
> å‰ç½®èƒ½åŠ›ï¼ˆä¸åœ¨æœ¬æ–‡èŒƒå›´ï¼Œå·²å®Œæˆï¼‰ï¼šæ‚é¡¹å…¥åº“/出库/供应商退货三单据 BPM å®¡æ‰¹é—­çŽ¯ã€è®¾å¤‡å°è´¦è”åŠ¨è®¾å¤‡ä»“è‡ªåŠ¨å…¥åº“ã€ç›˜ç‚¹å·®å¼‚è‡ªåŠ¨æ ¸é”€æŽ¥çº¿ã€MDM ç‰©æ–™ä¸»æ•°æ®ï¼ˆå«â€œè®¾å¤‡â€ç‰©æ–™ç±»åž‹/分类/单位)。
## 1. èƒŒæ™¯ä¸Žç›®æ ‡
当前 WM ä»“储已具备单据、库存流水、盘点、设备仓自动入库等能力,但存在以下缺口,本轮一并补齐:
| ç¼ºå£ | çŽ°çŠ¶ | ç›®æ ‡ |
|------|------|------|
| ç›˜ç‚¹æ— å¤æ ¸å…³å£ | å½•å…¥/导入实盘后由“完成盘点”直接核销台账 | ç›˜ç‚¹ç»“果先走 BPM å®¡æ‰¹ï¼Œé€šè¿‡æ‰è§£å†»å¹¶æ ¸é”€ |
| ç›˜ç‚¹é äººå·¥é€æœŸå»ºä»»åŠ¡ | æ¯æ¬¡éœ€æ‰‹å·¥åˆ›å»ºä»»åŠ¡ | æ–¹æ¡ˆé…ç½®å‘¨æœŸï¼ŒåŽå°å®šæ—¶è‡ªåŠ¨ç”Ÿæˆä»»åŠ¡ |
| æ¡ç èƒ½åЛ弱 | ä»…支持单一业务编码占位符、无成图/扫码 | ç»„合字段、服务端成图、扫码解析 |
| SN æ— é—­çޝ | ä»…有 SN ä¸»æ¡£ï¼Œæ— åœ¨åº“/去向 | ç™»è®°/核销 SN、单件在库/去向查询(轻量闭环) |
| è®¾å¤‡å…¥åº“无单据 | ä»…“台账创建即自动入设备仓” | ç‹¬ç«‹è®¾å¤‡å…¥åº“单,走创建、审批、完成入库、查询 |
**全局约束**:仅后端;不修改前端项目;接口变更只出联调文档;库存创建/数量更新/流水一律经库存事务服务,不直写库存表;BPM åˆ†ç±»ä¸Žæµç¨‹å®šä¹‰æ‰‹å·¥éƒ¨ç½²ï¼›æ–°å¢žè¡¨ä¸è½ tenant_id;`ADD COLUMN` æŒ‰å­˜åœ¨æ€§æ£€æŸ¥æ‰§è¡Œã€‚
## 2. èŒƒå›´ç•Œå®š
- **做**:M1 ç›˜ç‚¹ç»“果审批 BPM;M2 å®šæœŸç›˜ç‚¹è‡ªåŠ¨è°ƒåº¦ï¼›M3 æ¡ç ç»„合/成图/扫码;M4 SN è½»é‡é—­çŽ¯ï¼›M5 ç‹¬ç«‹è®¾å¤‡å…¥åº“单。
- **不做**:盘点“冲销/反核销”;历史已完成任务补核销;库存单据行重构为 SN æ˜Žç»†ï¼›å‰ç«¯ä»£ç ã€‚
## 3. M1 ç›˜ç‚¹ç»“果审批 BPM
### 3.1 ä¸šåŠ¡åœºæ™¯
盘点中录入/导入实盘后,由负责人将盘点结果提交 BPM å®¡æ‰¹ï¼›å®¡æ‰¹é€šè¿‡åŽç³»ç»Ÿè§£å†»åº“存并自动核销盘盈/盘亏差异更新台账;审批不通过则允许修改实盘后重新提交。
### 3.2 çŠ¶æ€æœºï¼ˆå¤ç”¨çŽ°æžšä¸¾ï¼Œä¸æ–°å¢žâ€œå·²å®¡æ‰¹â€æ€ï¼‰
```
草稿 PREPARE â”€â”€å¼€å§‹ç›˜ç‚¹â”€â”€â–¶ ç›˜ç‚¹ä¸­ APPROVING â”€â”€æäº¤ç»“果审批(建BPM)──▶ ç›˜ç‚¹ä¸­ APPROVING
                                                                  â”‚(processInstanceId éžç©º=审批中)
盘点中 â”€â”€å®¡æ‰¹é€šè¿‡â”€â”€â–¶ å·²å®Œæˆ FINISHED(解冻 + è‡ªåŠ¨æ ¸é”€å·®å¼‚ï¼ŒåŒäº‹åŠ¡ï¼‰
盘点中 â”€â”€å®¡æ‰¹é©³å›žâ”€â”€â–¶ ç›˜ç‚¹ä¸­ APPROVING(清 processInstanceId,可改实盘后重提)
盘点中 â”€â”€å®¡æ‰¹å–消──▶ å·²å–消 CANCELED(解冻)
草稿/盘点中 â”€â”€å–消──▶ å·²å–消 CANCELED(解冻)
```
### 3.3 ä¸šåŠ¡è§„åˆ™
- **开始盘点**(草稿→盘点中):仅草稿;盘点行非空;开启冻结则冻结盘点行库存。
- **录入/导入实盘**:仅盘点中允许(人工录入、Excel å¯¼å…¥ç»Ÿä¸€å£å¾„)。
- **提交结果审批** å‰ç½®æ ¡éªŒï¼šçŠ¶æ€=盘点中;已有 â‰¥1 æ¡ç›˜ç‚¹ç»“果;未提交过(`processInstanceId` ä¸ºç©ºï¼Œé˜²é‡å¤æäº¤ï¼‰ã€‚
- **审批通过**(同一事务、失败整体回滚回盘点中):置已完成 â†’ è‹¥å†»ç»“则先解冻 â†’ é€æ¡ç›˜ç‚¹ç»“果核销:差异 = å®žç›˜ âˆ’ è´¦é¢ï¼›>0 ç›˜ç›ˆä½œå…¥åº“、<0 ç›˜äºä½œå‡ºåº“(数量为负)、=0 è·³è¿‡ï¼›ä»¥ç›˜ç‚¹ç»“果回填的库存定位精确核销;生成库存流水 `bizType`=盘点。
- åŽŸâ€œå®Œæˆç›˜ç‚¹â€å…¬å¼€åŠ¨ä½œç§»é™¤ï¼Œæ ¸é”€æ”¹ç”±å®¡æ‰¹é€šè¿‡äº‹ä»¶é©±åŠ¨ã€‚
- é©³å›žä¸æ”¹ä»»åŠ¡çŠ¶æ€ï¼ˆä¿æŒç›˜ç‚¹ä¸­ï¼‰ï¼Œä»…æ¸…æµç¨‹å®žä¾‹æ ‡è®°ï¼Œå…è®¸ä¿®æ”¹å®žç›˜åŽé‡æã€‚
### 3.4 æ•°æ®ä¸ŽæŽ¥å£
- `mes_wm_stock_taking_task` å¢žåŠ  `process_instance_id`;任务查询/详情响应返回该字段(前端据此区分“审批中”与“可提交审批”)。
- æŽ¥å£ï¼š`提交盘点结果审批`(单据 id + æµç¨‹å®šä¹‰ key)、`可审批流程定义列表`(分类编码 `stock_taking_result_approve`)。
- BPM ç›‘听:解析业务主键=任务 id,校验任务存在且盘点中,按审批结果更新(通过/驳回/取消)。
## 4. M2 å®šæœŸç›˜ç‚¹è‡ªåŠ¨è°ƒåº¦
### 4.1 ä¸šåŠ¡åœºæ™¯
盘点方案可开启“定期自动生成”:系统按方案配置的周期(cron)自动创建盘点任务,到点即用,无需人工逐期建单。
### 4.2 ä¸šåŠ¡è§„åˆ™
- æ–¹æ¡ˆå­—段:是否自动生成(`auto_generate`)、生成周期 cron(`generate_cron`,Quartz 6 æ®µï¼‰ã€ä¸Šæ¬¡ç”Ÿæˆæ—¶é—´ï¼ˆ`last_generate_time`)。
- å¼€å¯è‡ªåŠ¨ç”Ÿæˆæ—¶å¿…é¡»é…ç½®åˆæ³• cron;未开启则忽略 cron。
- ä»… **启用状态 + å¼€å¯è‡ªåŠ¨ç”Ÿæˆ + å·²é…ç½® cron** çš„æ–¹æ¡ˆå‚与扫描。
- åŽå°å®šæ—¶ä»»åŠ¡å‘¨æœŸè§¦å‘ï¼ˆinfra åŽå°é…ç½® cron,handler=方案生成 Job çš„ Bean åï¼Œå»ºè®®æ¯åˆ†é’Ÿä¸€æ¬¡ï¼‰ï¼šæŒ‰å„方案“上次生成时间 + cron”判断是否到期,到期才生成。
- **防重复**:生成任务成功后同事务回写上次生成时间;首次扫描仅记录基线时间、不立即生成(从下一周期开始)。
- è‡ªåŠ¨ç”Ÿæˆçš„ä»»åŠ¡ï¼šæ²¿ç”¨æ–¹æ¡ˆçš„ç±»åž‹/盲盘/冻结/动态盘点时间段;名称取方案名;盘点人取系统默认用户;任务编码走“盘点任务编码”自动规则;创建后即按方案生成盘点明细行(草稿态)。
- å•个方案生成失败不影响其它方案。
### 4.3 æ•°æ®ä¸ŽæŽ¥å£
- `mes_wm_stock_taking_plan` å¢žåŠ  `auto_generate` / `generate_cron` / `last_generate_time`;方案新增/修改与查询响应携带。
- æä¾›â€œç”±æ–¹æ¡ˆæŒ‰å‘¨æœŸç”Ÿæˆä»»åŠ¡â€çš„æœåŠ¡æ–¹æ³•ï¼Œä¾› Job è°ƒç”¨ï¼›Job æœ¬èº«ä¸åšåº“å­˜/单据业务。
## 5. M3 æ¡ç  / æ ‡ç­¾ / æ‰«ç å¢žå¼º
### 5.1 ä¸šåŠ¡åœºæ™¯
把仓储条码从“单一业务编码”升级为可组合、可成图、可扫码反查,支撑标签打印与 PDA æ‰«ç ã€‚
### 5.2 éœ€æ±‚点
1. **条码内容组合字段**:条码内容模板支持多个占位符自由组合(如业务编码 + ç‰©æ–™ç¼–码 + æ‰¹æ¬¡ + åº“位 + SN ç­‰ï¼‰ï¼Œé…ç½®åˆ°æ¡ç é…ç½®é¡¹ï¼Œç”Ÿæˆæ—¶æŒ‰æ¨¡æ¿æ¸²æŸ“真实内容。
2. **服务端成图 / æ‰“印**:MES æ¨¡å—引入二维码/条码生成库(zxing)在服务端成图;提供打印/预览能力。图片若需留存一律走附件中间表;仅即时预览可用 Base64,不落业务表图片列。
3. **扫码解析**:新增服务端接口,对扫码内容做结构化解析:识别业务编码与其它键值,反查并返回对应业务对象(单据 / ç‰©æ–™ / æ‰¹æ¬¡ / SN / åº“位等),供扫码枪与移动端跳转、核验。
### 5.3 éªŒæ”¶è¦ç‚¹
- ç»„合模板渲染内容正确(含中文/大小写)。
- ç”Ÿæˆå›¾åƒå¯è¢«æ‰«ç è¿˜åŽŸï¼Œä¸”è¿˜åŽŸç»“æžœä¸Žæ¸²æŸ“å†…å®¹ä¸€è‡´ã€‚
- è§£æžæŽ¥å£å¯¹æœªè¯†åˆ«å†…容给出明确错误而非静默。
## 6. M4 SN å•品库存轻量闭环
### 6.1 ä¸šåŠ¡åœºæ™¯
对开启序列号管理的物料,要求能登记每件 SN çš„出入、查看单件当前在库与去向,并支持盘点按 SN æ ¸å¯¹ã€‚**单据行不重构为 SN æ˜Žç»†**(保持行级数量管理,SN ä½œä¸ºç™»è®°/核销记录闭环)。
### 6.2 éœ€æ±‚点
1. **SN åœ¨åº“状态与位置**:`mes_wm_sn` è¡¥é½åœ¨åº“状态、所在库位等字段(DO ä¸Žè¡¨å­—段对齐)。
2. **流水带 SN**:库存事务/流水表增加 `snCode` åˆ—,记录该笔出入对应的序列号。
3. **入库登记 SN**:按 SN ç®¡ç†ç‰©æ–™çš„入库事务登记 SN(置为在库、记录库位)。
4. **出库核销 SN**:出库时核销指定在库 SN(置为出库/非在库),与库存事务同记录。
5. **单件在库/去向查询**:按 SN æŸ¥å½“前在库位置、最近去向流水。
6. **盘点按 SN æ ¸å¯¹**:按 SN ç®¡ç†ç‰©æ–™çš„盘点支持 SN ç²’度核对(在盘点维度内校验实物 SN ä¸Žåœ¨åº“ SN)。
7. **序列号管理标记贯通**:物料“是否序列号管理(isSerialManaged)”需在 MDM API(物料响应/创建 DTO)中贯通,供 MES å„模块判断。
### 6.3 ä¸šåŠ¡è§„åˆ™
- ä»…“按 SN ç®¡ç†â€çš„物料登记/核销 SN。
- åŒä¸€ SN åœ¨åº“唯一;出库核销的 SN å¿…须处于在库状态。
## 7. M5 ç‹¬ç«‹è®¾å¤‡å…¥åº“单
### 7.1 ä¸šåŠ¡åœºæ™¯
“设备台账创建即自动入设备仓”解决设备建档联动;“设备入库单”则作为可追溯、可审批的入库凭证,用于设备由外部进入/正式入仓的业务,按单留痕。
### 7.2 å•据结构
- **主表**:单据编码(自动生成,新增“设备入库单编码”规则)、名称、入库日期、来源/备注、状态、BPM æµç¨‹å®žä¾‹ç¼–号等。
- **明细行**:设备(台账)→ è‡ªåŠ¨å¸¦å…¥è®¾å¤‡ç‰©æ–™(itemId);仓库/库区/库位固定设备仓三元组;数量默认 1;同单可多台;备注。
### 7.3 æµç¨‹ä¸ŽçŠ¶æ€ï¼ˆæ²¿ç”¨æ‚é¡¹å…¥åº“æ¨¡æ¿ï¼‰
```
草稿 PREPARE â”€â”€æäº¤å®¡æ‰¹(建BPM,回写流程编号)──▶ å®¡æ‰¹ä¸­ APPROVING
审批通过 â†’ å·²å®¡æ‰¹ APPROVED â”€â”€å®Œæˆå…¥åº“──▶ å·²å®Œæˆ FINISHED
驳回 â†’ è‰ç¨¿ PREPARE(可改重提)
审批/草稿取消 â†’ å·²å–消 CANCELED
```
- å®¡æ‰¹é€šè¿‡è¿›å…¥â€œå¯æ‰§è¡Œå…¥åº“”,库存动作仅在“完成入库”执行(逐明细行设备仓 IN +1,更新台账与流水,业务类型独立)。
### 7.4 ä¸šåŠ¡è§„åˆ™
- æ˜Žç»†ä»…可选已关联物料(有 `itemId`)的设备台账。
- åº“位必须属于设备仓体系。
- è®¾å¤‡ç¼–码/物料已有则不允许重复建档(沿用台账约束)。
- â€œå®Œæˆå…¥åº“”仅已审批状态可执行,且仅执行一次;库存与流水统一走库存事务服务,不直写库存表。
- ç‹¬ç«‹ BPM æµç¨‹åˆ†ç±»ä¸Žç‹¬ç«‹åº“存流水业务类型(用于设备入库单据与设备台账自动入库区分)。
## 8. è·¨å•元依赖与实施顺序
```
M1 ç›˜ç‚¹ç»“果审批 BPM(改既有盘点任务,含 DB åˆ—/错误码/监听器/端点替换)
  â””─▶ M2 å®šæœŸç›˜ç‚¹è°ƒåº¦ï¼ˆM1 ä»»åŠ¡åˆ›å»º/状态机是其下游产物)
M3 æ¡ç æˆå›¾/扫码/组合字段(MES ä¾èµ–引入 zxing)
M4 SN è½»é‡é—­çŽ¯ï¼ˆå« MDM-API å­—段贯通)
M5 è®¾å¤‡å…¥åº“单(可复用杂项入库单据骨架)
M6 æ”¶å°¾ï¼šå…¨é‡ç¼–译、docs è”调文档、统一端到端冒烟(含 DB è„šæœ¬æ‰§è¡Œã€BPM åˆ†ç±»ä¸Žæµç¨‹å®šä¹‰æ‰‹å·¥éƒ¨ç½²ï¼‰
```
## 9. å¾…澄清/决策项(实现前需确认)
- M5 ç‹¬ç«‹è®¾å¤‡å…¥åº“单是否需要与设备台账的“自动入库”叠加(即设备既随台账自动入库,又可单独走入库单),或自动入库收敛为仅随入库单执行。
## é™„:实施状态追踪(供续作基线)
| å•å…ƒ | çŠ¶æ€ | å¤‡æ³¨ |
|------|------|------|
| M1 ç›˜ç‚¹ç»“果审批 BPM | ä»£ç å®Œæˆï¼Œç¼–译通过 | é”™è¯¯ç /DO/RespVO/Mapper/接口与实现/监听器/端点替换已落地;DB è„šæœ¬å·²å†™å¾…æ‰§è¡Œ |
| M2 å®šæœŸç›˜ç‚¹è°ƒåº¦ | éƒ¨åˆ†å®Œæˆï¼Œæœªç¼–译 | æ–¹æ¡ˆå­—段/校验/查询与 Service å·²æ”¹ï¼›ä»»åŠ¡ä¾§â€œæŒ‰æ–¹æ¡ˆç”Ÿæˆä»»åŠ¡â€ã€Job、DB è„šæœ¬æœªåš |
| M3 æ¡ç ç»„合/成图/扫码 | æœªå¼€å§‹ | å¾… zxing å¼•入、模板渲染、解析接口 |
| M4 SN è½»é‡é—­çޝ | æœªå¼€å§‹ | å¾…表字段/登记核销/查询/API è´¯é€š |
| M5 è®¾å¤‡å…¥åº“单 | æœªå¼€å§‹ | å¾…新单据全栈与 BPM |
| M6 æ”¶å°¾ | æœªå¼€å§‹ | å…¨é‡ç¼–译 + docs + å†’烟 + DB/流程部署 |
docs/wm_equipment_receipt_integration.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,92 @@
# è®¾å¤‡å…¥åº“单 - å‰ç«¯è”调方案
## æ¶‰åŠé¡µé¢
- è®¾å¤‡å…¥åº“单列表(页面路径与路由待前端补充)
- è®¾å¤‡å…¥åº“单详情 / ç¼–辑(主单信息 + æ˜Žç»†è¡Œï¼‰
## ä¸šåŠ¡æµç¨‹ä¸Žæ•°æ®å¸¦å…¥
1. è®¾å¤‡å°è´¦ -> è®¾å¤‡å…¥åº“单明细行:从「设备台账」页选择设备后,`machineryId`、`itemId`(设备物料编号)自动带入并传入 `POST /mes/wm/equipment-receipt-line/create`;物料编码/名称/规格/单位由后端按 `itemId` å®žæ—¶æ‹¼æŽ¥è¿”回。
2. è®¾å¤‡å…¥åº“单创建 -> ç¼–号:`code` åœ¨å‰ç«¯ç¼–辑页可调用自动编码规则(`WM_EQUIP_RECEIPT_CODE`)生成,传给 `POST /mes/wm/equipment-receipt/create`。
3. å®¡æ‰¹æµç¨‹ï¼šä¸»ç®¡å•提交审批后,走 BPM,审批通过后由「执行入库」把明细行按固定「设备仓三元组」(`SYS-EQUIPMENT` / `SYS-EQUIP-LOC-01` / `SYS-EQUIP-BIN-01`)入设备仓、数量默认 1。
## API
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| POST | /mes/wm/equipment-receipt/create | åˆ›å»ºè®¾å¤‡å…¥åº“单(草稿) |
| PUT | /mes/wm/equipment-receipt/update | ä¿®æ”¹è®¾å¤‡å…¥åº“单(仅草稿) |
| DELETE | /mes/wm/equipment-receipt/delete | åˆ é™¤è®¾å¤‡å…¥åº“单(仅草稿,级联删行) |
| GET | /mes/wm/equipment-receipt/get?id= | èŽ·å¾—è®¾å¤‡å…¥åº“å•è¯¦æƒ… |
| GET | /mes/wm/equipment-receipt/page | è®¾å¤‡å…¥åº“单分页 |
| PUT | /mes/wm/equipment-receipt/submit-approval?id=&processDefinitionKey= | æäº¤ BPM å®¡æ‰¹ï¼ˆè‰ç¨¿â†’审批中) |
| GET | /mes/wm/equipment-receipt/approval-process-list | èŽ·å¾—è®¾å¤‡å…¥åº“å¯é€‰æµç¨‹å®šä¹‰åˆ—è¡¨ |
| PUT | /mes/wm/equipment-receipt/finish?id= | æ‰§è¡Œå…¥åº“(已审批→已完成,逐行入设备仓) |
| PUT | /mes/wm/equipment-receipt/cancel?id= | å–消设备入库单 |
| POST | /mes/wm/equipment-receipt-line/create | æ–°å¢žæ˜Žç»†è¡Œ |
| PUT | /mes/wm/equipment-receipt-line/update | ä¿®æ”¹æ˜Žç»†è¡Œ |
| DELETE | /mes/wm/equipment-receipt-line/delete?id= | åˆ é™¤æ˜Žç»†è¡Œ |
| GET | /mes/wm/equipment-receipt-line/get?id= | èŽ·å¾—æ˜Žç»†è¡Œ |
| GET | /mes/wm/equipment-receipt-line/list-by-receipt-id?receiptId= | æŒ‰ä¸»å•获得明细行列表 |
| GET | /mes/wm/equipment-receipt-line/page | æ˜Žç»†è¡Œåˆ†é¡µ |
**请求参数(create/update):**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| code | String | æ˜¯ | å•据编码(可自动编码生成) |
| name | String | å¦ | å•据名称 |
| receiptDate | datetime | æ˜¯ | å…¥åº“日期 |
| source | String | å¦ | å…¥åº“来源 |
| remark | String | å¦ | å¤‡æ³¨ |
**请求参数(明细行 create/update):**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| receiptId | Long | æ˜¯ | å…¥åº“单编号 |
| machineryId | Long | æ˜¯ | è®¾å¤‡å°è´¦ç¼–号 |
| itemId | Long | æ˜¯ | è®¾å¤‡ç‰©æ–™ç¼–号(从设备台账带入) |
| quantity | decimal | æ˜¯ | å…¥åº“数量(默认 1,可同单多台) |
| remark | String | å¦ | å¤‡æ³¨ |
**响应字段新增(主单):**
| å­—段 | ç±»åž‹ | è¯´æ˜Ž |
|------|------|------|
| processInstanceId | String | BPM æµç¨‹å®žä¾‹ç¼–号,非空表示已提交审批 |
**响应字段(明细行):**
| å­—段 | ç±»åž‹ | è¯´æ˜Ž |
|------|------|------|
| machineryId / machineryCode / machineryName | Long/String | è®¾å¤‡å°è´¦ä¿¡æ¯ |
| itemId / itemCode / itemName / specification / unitMeasureName | Long/String | ç‰©æ–™åŠå•位信息 |
## å­—段展示规则
| å­—段 | å±•示位置 | è¯´æ˜Ž |
|------|----------|------|
| å•据编码/名称/入库日期/来源 | åˆ—表、详情 | ä¸»å•基础信息 |
| çŠ¶æ€ | åˆ—表、详情 | 0 è‰ç¨¿ / 2 å®¡æ‰¹ä¸­ / 3 å·²å®¡æ‰¹ / 4 å·²å®Œæˆ / 5 å·²å–消 |
| processInstanceId | è¯¦æƒ… | æœ‰å€¼æ—¶å‰ç«¯å±•示「查看审批流程实例」入口 |
| æ˜Žç»†è¡Œè¡¨æ ¼ | è¯¦æƒ…、编辑 | å±•示设备、物料、数量、单位 |
## ä¸šåŠ¡è§„åˆ™è¯´æ˜Ž
| åœºæ™¯ | è§„则 |
|------|------|
| æ˜Žç»†è¡Œæ–°å¢ž | å¿…须选择已关联物料(itemId éžç©ºï¼‰çš„设备,否则报「所选设备未关联物料」 |
| æ•°é‡ | å¿…é¡» > 0,默认 1 |
| ç¼–辑 | ä»…草稿状态下可增删改主单与明细行 |
| æäº¤å®¡æ‰¹ | è‡³å°‘有一条明细行;提交后进入审批中,不可再编辑 |
| å®¡æ‰¹ç»“æžœ | é€šè¿‡â†’已审批;驳回→回草稿可改重提;取消→已取消 |
| æ‰§è¡Œå…¥åº“ | ä»…已审批可执行;逐行为每台设备在设备仓 +1 åº“存并写库存流水;完成后不可重复执行 |
| åº“存生效 | å®¡æ‰¹é€šè¿‡ä¸ç«‹å³æ‰£åº“存,仅「执行入库」才入设备仓 |
## æ³¨æ„äº‹é¡¹
- æ˜Žç»†è¡Œæœ«ç«¯å›ºå®šå…¥ã€Œè®¾å¤‡ä»“三元组」,前端无需提交仓库/库区/库位字段。
- åº“存数量变化通过既有库存/库存流水查询接口查看,本单据不复制库存数据。
- BPM æµç¨‹å®šä¹‰éœ€åœ¨åŽå°ä»¥åˆ†ç±» `equipment_receipt_approve` æ‰‹å·¥éƒ¨ç½²åŽï¼Œ`approval-process-list` æ‰ä¼šè¿”回可用流程。
docs/wm_frontend_upgrade_progress.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,60 @@
# MES ä»“储功能 - å‰ç«¯æ”¹é€ è¿›åº¦è®°å½•
> æœ¬æ–‡è®°å½•"继续修改前后端"批量补码的前端实施进度(2026-09-08),作为跨天交接依据。
> åŽç«¯ M1~M5 ä»£ç å·²å…¨éƒ¨å®Œæˆå¹¶ç¼–译通过;BPM æµç¨‹ä¸Žèœå•权限已 DB éƒ¨ç½²ã€‚
> æœ¬æ–‡ä»¶ä»…记录**前端(mom-pro2-before)**改动与待办。
## å·²å®Œæˆï¼ˆ2026-09-08)
### 1. é€šç”¨ BPM æµç¨‹é€‰æ‹©å¼¹çª—组件(新建)
- `mom-pro2-before/src/views/wls/components/process-select-modal.vue`
- ç”± mes/pd/project çš„ process-select-modal æ³›åŒ–而来;提交函数通过 `modalApi.getData({ id, processList, submitFn })` ä¼ å…¥ï¼Œä¸‰å•据与后续 M1/M5 å‡å¯å¤ç”¨ã€‚
### 2. é˜¶æ®µ1 ä¸‰å•据 BPM æäº¤å‡çº§ï¼ˆæ‚项入库/杂项出库/供应商退货)
**API å±‚(均新增 processInstanceId å­—段):**
| æ–‡ä»¶ | æ”¹åЍ |
|------|------|
| `src/api/mes/wm/miscreceipt/index.ts` | `getMiscReceiptApproveProcessList()`、`submitMiscReceiptApproval(id, key)`、接口加 `processInstanceId` |
| `src/api/mes/wm/miscissue/index.ts` | `getMiscIssueApproveProcessList()`、`submitMiscIssueApproval(id, key)`、接口加 `processInstanceId` |
| `src/api/mes/wm/returnvendor/index.ts` | `getReturnVendorApproveProcessList()`、`submitReturnVendorApproval(id, key)`、接口加 `processInstanceId` |
> æ—§çš„æ— å‚ `submitMiscReceipt(id)` ç­‰å·²åˆ é™¤ï¼ˆåŽç«¯ submit æŽ¥å£çŽ°åœ¨è¦æ±‚ `processDefinitionKey` å‚数)。
**页面层(三个单据模式一致):**
- `index.vue`:新增 `useRouter` + ProcessSelectModal æŒ‚载;行操作增加
  - â€œæäº¤å®¡æ‰¹â€ï¼ˆPREPARE çŠ¶æ€ï¼Œå…ˆæŸ¥æµç¨‹åˆ—è¡¨å†å¼¹çª—é€‰æ‹©ï¼‰
  - â€œæŸ¥çœ‹å®¡æ‰¹â€ï¼ˆAPPROVING çŠ¶æ€ï¼Œ`router.push` åˆ° `BpmProcessInstanceDetail`)
- `modules/form.vue`:移除表单内“提交”按钮及 `handleSubmit`(提交改由列表行操作触发,规避二次点提交的旧逻辑)
- æƒé™å­—符串按 DB èœå•:
  - æ‚项入库用冒号权限 `mes:wm:misc-receipt:submit` / `:query`
  - æ‚项出库、供应商退货用短横线权限,复用 `mes:wm-misc-issue:update` / `mes:wm-return-vendor:update`(无独立 submit æŒ‰é’®èœå•)
**枚举补齐:**
- `src/packages/constants/src/biz-mes-enum.ts`:`MesWmMiscReceiptStatusEnum`、`MesWmMiscIssueStatusEnum` å¢žåŠ  `APPROVING`(=2)。
**数据库字典(已执行到 mom-xgdl):**
- `mes_wm_misc_receipt_status`、`mes_wm_misc_issue_status` è¡¥ value=2 â€œå®¡æ‰¹ä¸­â€ï¼ˆ`system_dict_data` id 1065512 / 1065513),原值为 3/4/5 çš„æŽ’序自动顺延。
## æ˜Žæ—¥å¾…办(未开始)
| # | ä»»åŠ¡ | ä¸»è¦å†…容 |
|---|------|----------|
| M1 | ç›˜ç‚¹ä»»åС页 BPM å‡çº§ï¼ˆç»“果审批) | ç§»é™¤â€œæ‰§è¡Œç›˜ç‚¹(finish)”按钮与 execute è¡¨å•类型;`提交`按钮文案改“开始盘点”;新增“提交结果审批”(submit-approval) + â€œæŸ¥çœ‹å®¡æ‰¹â€ï¼›API åŠ  `submitStockTakingApproval`/`getStockTakingApproveProcessList`/`processInstanceId` |
| M2 | ç›˜ç‚¹æ–¹æ¡ˆè°ƒåº¦å­—段 | è¡¨å•加 `autoGenerate` Switch + `generateCron` Input(依赖 autoGenerate,helpMessage æç¤ºèµ° infra å®šæ—¶ä»»åŠ¡ï¼‰ï¼›API åŠ ä¸‰ä¸ªå­—æ®µ |
| M3 | æ¡ç æ‰«ç è§£æž + æˆå›¾é¢„览 | barcode é¡µå·¥å…·æ åŠ â€œæ‰«ç è§£æžâ€ï¼›API åŠ  `renderBarcodeImage`(POST) / `parseBarcodeContent`(POST);新建 scan-modal |
| M4 | SN åœ¨åº“单件/出入库/详情 | index.vue åŠ  Tabs(分组/在库单件);新增 in-stock / out-stock / sn-detail å¼¹çª—ï¼›API åŠ  `registerSnInStock`/`outboundSn`/`getSnDetail`/`getSnInStockPage`;加 `MesWmSnStatusEnum` |
| M5 | è®¾å¤‡å…¥åº“单页面(新页面) | æ–°å»º `wls/equipmentreceipt/index.vue` + data.ts + modules/{form,line-list,line-form}.vue;API å±‚新建 equipmentreceipt/index.ts + line.ts;加 `MesWmEquipmentReceiptStatusEnum` + `MesAutoCodeRuleCode.WM_EQUIPMENT_RECEIPT_CODE`;行用 DvMachinerySelect,finish å›ºå®šè®¾å¤‡ä»“三元组 |
| æ”¶å°¾ | typecheck / build | `pnpm typecheck` ä¿®å¤ç±»åž‹é”™è¯¯ï¼›å¿…要时 `pnpm build` |
## æ˜Žæ—¥å¼€å§‹å‰éœ€çŸ¥
1. **M5 å‰ç½®ç¼ºå£**:`src/api/mes/dv/machinery/index.ts` çš„ `Machinery` ç±»åž‹æ²¡æœ‰ `itemId` å­—段(后端 RespVO å·²æœ‰ï¼‰ï¼ŒM5 è¡Œè¡¨å•依赖 DvMachinerySelect çš„ change äº‹ä»¶æºå¸¦ itemId è‡ªåŠ¨å¸¦å…¥â€”â€”éœ€å…ˆç»™å‰ç«¯ç±»åž‹è¡¥ `itemId?: number`。
2. **权限格式**:equipment-receipt èœå•用冒号权限 `mes:wm:equipment-receipt:query/create/update/delete/submit/finish/cancel`;M1 stock-taking-task çš„ submit-approval/cancel å¤ç”¨ `mes:wm-stock-taking-task:update`;M3 barcode å¤ç”¨ `mes:wm-barcode:query`。
3. **已部署 BPM æµç¨‹ key**:`misc_receipt_approve` / `misc_issue_approve` / `return_vendor_approve` / `item_receipt_approve` / `stock_taking_result_approve` / `equipment_receipt_approve`。
4. **后端重启**:48080 éœ€é‡å¯åŠ è½½æ–°ä»£ç åŽæ‰å¯ç«¯åˆ°ç«¯å†’çƒŸï¼ˆç”¨æˆ· dev è¿›ç¨‹ï¼Œé‡å¯æ—¶æœºç”±ç”¨æˆ·å†³å®šï¼‰ã€‚
docs/wm_sn_item_chain_integration.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,84 @@
# SN å•品库存链(轻量闭环)- å‰ç«¯è”调方案
## æ¶‰åŠé¡µé¢
- SN ç åˆ—表 / å•件在库查询页
- SN å•件详情页(在库 / åŽ»å‘ï¼‰
- ä»“库入库、出库(登记 SN)操作页
- ç‰©æ–™ä¸»æ•°æ®ï¼ˆSN å¼€å…³é…ç½®ï¼‰
## ä¸šåŠ¡æµç¨‹ä¸Žæ•°æ®å¸¦å…¥
1. ç‰©æ–™ä¸»æ•°æ® -> SN å¼€å…³ï¼šç‰©æ–™è‹¥å¯ç”¨ã€Œåºåˆ—号管理」(`isSerialManaged`),才允许该物料登记 SN å…¥åº“/出库。
2. å…¥åº“登记 SN:用户扫码/手工录入 `code`,选择物料、仓库/库区/库位,调用 `POST /mes/wm/sn/in-stock`;后端先建 IN åº“存事务再更新 SN ä¸ºã€Œåœ¨åº“」并落库位。`snCode` å†™å…¥åº“存流水(`mes_wm_transaction.sn_code`)。
3. å‡ºåº“核销 SN:录入 SN ç ä¸Žç‰©æ–™ï¼Œè°ƒç”¨ `POST /mes/wm/sn/out-stock`;后端以 SN è®°å½•的库存位置建 OUT äº‹åŠ¡ï¼Œå¹¶æŠŠ SN ç½®ã€Œå·²å‡ºåº“」、清空库位。
4. å•件查询:按 `code` è°ƒ `GET /mes/wm/sn/detail`,返回 SN åœ¨åº“状态、当前位置,以及最近一笔库存流水的类型/数量/业务单据/时间,用于核对去向。
## API
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| POST | /mes/wm/sn/in-stock | SN ç™»è®°å…¥åº“ |
| POST | /mes/wm/sn/out-stock | SN å‡ºåº“核销 |
| GET | /mes/wm/sn/detail?code= | SN å•件详情(在库状态 + æœ€è¿‘流水去向) |
| GET | /mes/wm/sn/in-stock-page | å•件在库分页查询(按状态/库位/物料/批次过滤) |
**请求参数(in-stock):**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| code | String | æ˜¯ | SN ç  |
| itemId | Long | æ˜¯ | ç‰©æ–™ç¼–号(须启用序列号管理) |
| warehouseId | Long | æ˜¯ | ä»“库 |
| locationId | Long | æ˜¯ | åº“区 |
| areaId | Long | æ˜¯ | åº“位 |
| batchCode | String | å¦ | æ‰¹æ¬¡å· |
| remark | String | å¦ | å¤‡æ³¨ |
**请求参数(out-stock):**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| code | String | æ˜¯ | SN ç  |
| itemId | Long | æ˜¯ | ç‰©æ–™ç¼–号 |
| remark | String | å¦ | å¤‡æ³¨ |
**响应字段(detail):**
| å­—段 | ç±»åž‹ | è¯´æ˜Ž |
|------|------|------|
| code / status | String/Integer | SN ç ã€çŠ¶æ€ï¼ˆ1 åœ¨åº“ / 2 å·²å‡ºåº“) |
| warehouseId/locationId/areaId | Long | åœ¨åº“位置(已出库为空) |
| lastTransactionType / TypeName | Integer/String | æœ€è¿‘一笔流水方向(1 å…¥åº“ / 2 å‡ºåº“) |
| lastQuantity / lastBizType / lastBizCode / lastTime | decimal/Integer/String/datetime | æœ€è¿‘流水数量、业务类型、业务单据编码、时间 |
**响应字段新增(物料相关 VO:MdmItemRespDTO / MdmItemSaveReqVO ç­‰ï¼‰ï¼š**
| å­—段 | ç±»åž‹ | è¯´æ˜Ž |
|------|------|------|
| isSerialManaged | Boolean | æ˜¯å¦åºåˆ—号管理开关(create/read/update å‡æ”¯æŒï¼‰ |
## å­—段展示规则
| å­—段 | å±•示位置 | è¯´æ˜Ž |
|------|----------|------|
| SN ç  / ç‰©æ–™ / æ‰¹æ¬¡ | åˆ—表、详情 | å•件标识 |
| åœ¨åº“状态 | åˆ—表、详情 | åœ¨åº“ / å·²å‡ºåº“ |
| åœ¨åº“库位 | åˆ—表、详情 | ä»“库/库区/库位 |
| æœ€è¿‘去向 | è¯¦æƒ… | æœ€è¿‘流水对应的业务单据码 + æ—¶é—´ |
## ä¸šåŠ¡è§„åˆ™è¯´æ˜Ž
| åœºæ™¯ | è§„则 |
|------|------|
| æœªå¯ç”¨åºåˆ—号 | ç‰©æ–™æœªå¼€ `isSerialManaged` æ—¶ç™»è®° SN æŠ¥é”™ |
| é‡å¤å…¥åº“ | å·²ã€Œåœ¨åº“」的 SN å†æ¬¡å…¥åº“报错,须先出库 |
| å‡ºåº“前提 | ä»…「在库」且位置非空可出库;SN ä¸Žç‰©æ–™ä¸åŒ¹é… / ä½ç½®ä¸ç¬¦ä¼šæŠ¥é”™ |
| å‡ºå…¥åº“流转 | in-stock å»º IN äº‹åŠ¡ã€out-stock å»º OUT äº‹åŠ¡ï¼Œå‡èµ°åº“å­˜æµæ°´å¹¶æ›´æ–°åº“å­˜å°è´¦ |
| å•†å“ SN æº¯æº | é€šè¿‡ `mes_wm_transaction.sn_code` å…³è”流水,可按 SN è¿½æº¯åŽ†å²è¿›å‡º |
## æ³¨æ„äº‹é¡¹
- SN ç™»è®°/核销是「轻量」能力:单据行不拆成 SN æ˜Žç»†ï¼ŒSN ç‹¬ç«‹ç®¡ç†åœ¨ `mes_wm_sn`。
- å‡ºåº“位置取自 SN è®°å½•的库存位置,前端无需重复提交库位。
- ç‰©æ–™ `isSerialManaged` å¼€å…³åœ¨ MDM ç‰©æ–™ä¸»æ•°æ®ç»´æŠ¤ï¼ŒMES è¯»å–同一 `mdm_item` æ•°æ®ã€‚
docs/wm_stock_taking_plan_auto_generate_integration.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,63 @@
# å®šæœŸç›˜ç‚¹è‡ªåŠ¨è°ƒåº¦ - å‰ç«¯è”调方案
## æ¶‰åŠé¡µé¢
- ç›˜ç‚¹æ–¹æ¡ˆåˆ—表页(`wls/stocktaking/plan`)
- ç›˜ç‚¹æ–¹æ¡ˆç¼–辑表单(`wls/stocktaking/plan` æ–°å»º/编辑弹窗)
## ä¸šåŠ¡æµç¨‹ä¸Žæ•°æ®å¸¦å…¥
1. ç›˜ç‚¹æ–¹æ¡ˆå¼€å¯ã€Œå®šæœŸè‡ªåŠ¨ç”Ÿæˆã€å¹¶é…ç½®ç”Ÿæˆå‘¨æœŸ cron åŽï¼ŒåŽå°å®šæ—¶ä»»åŠ¡ï¼ˆæ¯å‘¨æœŸæ‰«æã€é»˜è®¤æ¯åˆ†é’Ÿä¸€æ¬¡ï¼‰æŒ‰å„æ–¹æ¡ˆã€Œä¸Šæ¬¡ç”Ÿæˆæ—¶é—´ + cron」判断是否到期。
2. åˆ°æœŸåˆ™ç³»ç»Ÿè‡ªåŠ¨æŒ‰æ–¹æ¡ˆåˆ›å»ºç›˜ç‚¹ä»»åŠ¡ï¼ˆè‰ç¨¿æ€ï¼Œåç§°å–æ–¹æ¡ˆåï¼Œæ²¿æ–¹æ¡ˆçš„ç±»åž‹/盲盘/冻结/动态盘点时间段),并立即按方案生成盘点明细行。
3. æ–¹æ¡ˆé¦–次开启后系统会记录基线时间,从下一个周期起开始生成,不会开启当天立即生成。
## API
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| POST | /mes/wm/stocktaking-plan/create | åˆ›å»ºç›˜ç‚¹æ–¹æ¡ˆ |
| PUT | /mes/wm/stocktaking-plan/update | ä¿®æ”¹ç›˜ç‚¹æ–¹æ¡ˆ |
| GET | /mes/wm/stocktaking-plan/get | èŽ·å¾—ç›˜ç‚¹æ–¹æ¡ˆè¯¦æƒ… |
| GET | /mes/wm/stocktaking-plan/page | èŽ·å¾—ç›˜ç‚¹æ–¹æ¡ˆåˆ†é¡µ |
**请求参数新增(创建/修改 ReqVO):**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| autoGenerate | Boolean | å¦ | æ˜¯å¦å®šæœŸè‡ªåŠ¨ç”Ÿæˆç›˜ç‚¹ä»»åŠ¡ï¼ˆé»˜è®¤ false) |
| generateCron | String | autoGenerate=true æ—¶å¿…å¡« | è‡ªåŠ¨ç”Ÿæˆå‘¨æœŸ cron è¡¨è¾¾å¼ï¼ˆQuartz 6 æ®µï¼‰ï¼Œå¦‚ `0 0 8 * * ?` è¡¨ç¤ºæ¯å¤© 8 ç‚¹ |
**响应字段新增(详情/分页 RespVO):**
| å­—段 | ç±»åž‹ | è¯´æ˜Ž |
|------|------|------|
| autoGenerate | Boolean | æ˜¯å¦å®šæœŸè‡ªåŠ¨ç”Ÿæˆç›˜ç‚¹ä»»åŠ¡ |
| generateCron | String | è‡ªåŠ¨ç”Ÿæˆå‘¨æœŸ cron è¡¨è¾¾å¼ |
| lastGenerateTime | LocalDateTime | ä¸Šæ¬¡è‡ªåŠ¨ç”Ÿæˆæ—¶é—´ï¼ˆåŽç«¯å›žå†™ï¼Œä»…å±•ç¤ºï¼‰ |
## å­—段展示规则
| å­—段 | å±•示位置 | è¯´æ˜Ž |
|------|----------|------|
| autoGenerate | åˆ—表、表单 | å¼€å…³/复选框 |
| generateCron | è¡¨å• | autoGenerate å¼€å¯æ—¶å¿…填并显示;不合法时后端报错「生成周期 cron è¡¨è¾¾å¼ä¸åˆæ³•」 |
| lastGenerateTime | åˆ—表、详情 | åªè¯»å±•示,前端不可编辑 |
## ä¸šåŠ¡è§„åˆ™è¯´æ˜Ž
| åœºæ™¯ | è§„则 |
|------|------|
| å¼€å¯è‡ªåŠ¨ç”Ÿæˆ | autoGenerate=true æ—¶ generateCron å¿…填(否则报错「开启定期自动生成时必须配置生成周期 cron」) |
| æœªå¼€å¯ | autoGenerate=false æ—¶å¿½ç•¥ generateCron |
| cron æ ¡éªŒ | ä½¿ç”¨ Quartz 6 æ®µ cron,不合法给「生成周期 cron è¡¨è¾¾å¼ä¸åˆæ³•」错误 |
| ç”ŸæˆèŒƒå›´ | ä»…「启用状态 + å¼€å¯è‡ªåŠ¨ç”Ÿæˆ + å·²é…ç½® cron」的方案参与扫描 |
| é˜²é‡å¤ | ç”Ÿæˆä»»åŠ¡æˆåŠŸåŽåŒäº‹åŠ¡å›žå†™ä¸Šæ¬¡ç”Ÿæˆæ—¶é—´ï¼Œé¿å…åŒå‘¨æœŸé‡å¤ç”Ÿæˆ |
| é¦–次启用 | é¦–次扫描仅记录基线时间不生成,从下一周期开始 |
| éƒ¨åˆ†å¤±è´¥ | å•个方案生成失败不影响其它方案 |
| ä»»åŠ¡æŸ¥çœ‹ | è‡ªåŠ¨ç”Ÿæˆçš„ä»»åŠ¡å¯åœ¨ç›˜ç‚¹ä»»åŠ¡åˆ—è¡¨æŸ¥çœ‹ï¼Œæ¥æºæ–¹æ¡ˆç¼–ç /名称自动带入 |
## æ³¨æ„äº‹é¡¹
- è‡ªåŠ¨ç”Ÿæˆæ˜¯åŽå°å®šæ—¶ä»»åŠ¡è¡Œä¸ºï¼Œå‰ç«¯æ— éœ€è§¦å‘ï¼›è”è°ƒæ—¶éªŒè¯æ–¹æ¡ˆå­—æ®µä¿å­˜/回显正确即可。
- è‹¥éœ€éªŒè¯ç”Ÿæˆæ•ˆæžœï¼Œå¯å°† cron é…ç½®ä¸ºçŸ­å‘¨æœŸï¼ˆå¦‚每分钟 `0 */1 * * * ?`),保存启用后在盘点任务列表观察自动出现草稿任务。
- åŽç»­è‹¥åœ¨ WMS(mom-pro2-before)盘点方案表单中增加以上两个字段,仅需随方案保存与回显;无新增页面。
docs/wm_stock_taking_result_approval_integration.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,62 @@
# ç›˜ç‚¹ç»“果审批 BPM - å‰ç«¯è”调方案
## æ¶‰åŠé¡µé¢
- ç›˜ç‚¹ä»»åŠ¡åˆ—è¡¨é¡µï¼ˆ`wls/stocktaking/task`)
- ç›˜ç‚¹ä»»åŠ¡è¯¦æƒ…/实盘录入页(`wls/stocktaking/task` è¯¦æƒ…、`result-form` å½•入实盘)
## ä¸šåŠ¡æµç¨‹ä¸Žæ•°æ®å¸¦å…¥
1. åˆ›å»ºç›˜ç‚¹ä»»åŠ¡ï¼ˆè‰ç¨¿ï¼‰â†’ã€Œå¼€å§‹ç›˜ç‚¹ã€ï¼šä»»åŠ¡è¿›å…¥ç›˜ç‚¹ä¸­ï¼Œå¯å½•å…¥/导入实盘。
2. å½•完实盘 â†’「提交结果审批」:调用提交审批接口(需选流程定义),任务进入审批中(带流程实例编号)。
3. å®¡æ‰¹é€šè¿‡ â†’ ç³»ç»Ÿè‡ªåŠ¨è§£å†»å¹¶æ ¸é”€ç›˜ç›ˆ/盘亏差异,任务变为已完成。
4. å®¡æ‰¹é©³å›ž â†’ ä»»åŠ¡ä»ä¸ºç›˜ç‚¹ä¸­ï¼ˆæ¸…é™¤æµç¨‹å®žä¾‹ç¼–å·ï¼‰ï¼Œå¯ä¿®æ”¹å®žç›˜åŽé‡æ–°æäº¤ã€‚
5. å®¡æ‰¹å–消 / å–消任务 â†’ ä»»åŠ¡å˜ä¸ºå·²å–æ¶ˆï¼Œå†»ç»“åº“å­˜è§£å†»ã€‚
## API
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| GET | /mes/wm/stocktaking-task/approval-process-list | èŽ·å¾—ç›˜ç‚¹ç»“æžœå¯ç”¨çš„å®¡æ‰¹æµç¨‹å®šä¹‰åˆ—è¡¨ |
| PUT | /mes/wm/stocktaking-task/submit-approval | æäº¤ç›˜ç‚¹ç»“果审批 |
| PUT | /mes/wm/stocktaking-task/cancel | å–消盘点任务 |
> æ³¨æ„ï¼šåŽŸã€Œå®Œæˆç›˜ç‚¹ã€æŽ¥å£ `/mes/wm/stocktaking-task/finish` å·²ç§»é™¤ï¼Œæ ¸é”€æ”¹ç”±å®¡æ‰¹é€šè¿‡äº‹ä»¶é©±åŠ¨ï¼Œä¸å†æä¾›å®Œæˆç›˜ç‚¹æŒ‰é’®ã€‚
**提交审批请求参数:**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| id | Long | æ˜¯ | ç›˜ç‚¹ä»»åŠ¡ç¼–å· |
| processDefinitionKey | String | æ˜¯ | æµç¨‹å®šä¹‰ Key(从审批流程定义列表选择) |
**审批流程定义列表响应:** `{ "code": 0, "data": [{ "key": "stock_taking_result_approve", "name": "xxx", ... }] }`,取其中的 `key` ä½œä¸ºæäº¤å®¡æ‰¹å‚数。
**响应字段新增(任务列表/详情 RespVO):**
| å­—段 | ç±»åž‹ | è¯´æ˜Ž |
|------|------|------|
| processInstanceId | String | BPM æµç¨‹å®žä¾‹ç¼–号;非空表示已提交审批,可点击查看审批进度 |
## å­—段展示规则
| å­—段 | å±•示位置 | è¯´æ˜Ž |
|------|----------|------|
| processInstanceId | åˆ—表、详情 | éžç©ºæ—¶æ˜¾ç¤ºã€Œå®¡æ‰¹ä¸­/查看审批」入口,为空时显示「可提交审批」 |
## ä¸šåŠ¡è§„åˆ™è¯´æ˜Ž
| åœºæ™¯ | è§„则 |
|------|------|
| æäº¤å‰ç½®æ ¡éªŒ | ä»…盘点中任务可提交;需已有 >=1 æ¡ç›˜ç‚¹ç»“果;未提交过(processInstanceId ä¸ºç©ºï¼‰é˜²é‡å¤æäº¤ |
| å®¡æ‰¹é€šè¿‡ | ç½®å·²å®Œæˆ + è§£å†» + è‡ªåŠ¨æ ¸é”€å·®å¼‚ï¼ˆåŒä¸€äº‹åŠ¡ï¼Œå¤±è´¥æ•´ä½“å›žæ»šä»ä¸ºç›˜ç‚¹ä¸­ï¼‰ |
| å®¡æ‰¹é©³å›ž | ä»»åŠ¡ä¿æŒç›˜ç‚¹ä¸­ï¼Œæ¸… processInstanceId,允许修改实盘后重提 |
| å®¡æ‰¹å–消 | ä»»åŠ¡å˜å·²å–æ¶ˆï¼Œè§£å†» |
| å¼€å§‹ç›˜ç‚¹å‰ç½® | ä»…草稿可开始;盘点行非空;开启冻结则冻结对应库存 |
| å®Œæˆè·¯çº¿ | å®ŒæˆåŽæ— ã€Œå®Œæˆç›˜ç‚¹ã€æ“ä½œï¼Œæ ¸é”€è‡ªåŠ¨æ‰§è¡Œï¼Œæ— éœ€å‰ç«¯å¹²é¢„ |
## æ³¨æ„äº‹é¡¹
- ä»»åŠ¡åˆ—è¡¨æŒ‰é’®æ€å»ºè®®æŒ‰ `status` + `processInstanceId` ç»„合判断:盘点中且 processInstanceId ä¸ºç©ºæ‰æ˜¾ç¤ºã€Œæäº¤ç»“果审批」。
- æäº¤åŽè¯¦æƒ…/列表响应中 processInstanceId å·²æœ‰å€¼ï¼Œå¯æ®æ­¤åŠ è½½å®¡æ‰¹è¿›åº¦è¯¦æƒ…ã€‚
- æŒ‰é’®æƒé™å¤ç”¨ï¼šæäº¤å®¡æ‰¹ä½¿ç”¨ `mes:wm-stock-taking-task:update`,审批流程列表使用 `mes:wm-stock-taking-task:query`。
docs/wm_stock_trace_gap_analysis.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,103 @@
# MES ä»“储物资「条码/二维码 Â· æ ‡ç­¾æ‰“印 Â· ç›˜ç‚¹ Â· æ‰¹æ¬¡ä¸Žå•品追溯」差距分析与实施建议
> ä¾æ®ï¼š`yudao-module-mes` çŽ°æœ‰ä»£ç ç›˜ç‚¹ï¼ˆ2026-09-08),对照三项需求逐条核对"已有/缺失"。结论均可溯源到对应 Controller / Service / DO / è¡¨ã€‚
## 1. æ€»ä½“结论
`mes_wm_*` ä¸€æ•´å¥—地基已经铺得很宽:**库存台账+流水、批次、条码、SN、盘点 plan/task/line/result、批次追溯**都建好了。真正的差距大多是"**最后一公里没接线**",其次才是"需新增模型"。缺表/重造的场景很少,多数是"逻辑已写但无调用点、字段已留但无人维护、模型已建但未进库存链"。
三需求命中最重要的三处:
1. **盘点盘盈盘亏自动核销"未接线"**(`processStockTakingDifference` æ— ä»»ä½•调用方,finish åªç½®çŠ¶æ€ï¼‰â€”â€”æœ€ç¡®å®šã€ä»£ä»·æœ€å°çš„ç¼ºå£ã€‚
2. **标签打印 / æ‰«ç  / æ¡ç ç»„合字段**整体缺失(只有条码字符串与 config é‡Œçš„æ¨¡æ¿åå­—段)。
3. **SN åªåš"号池",未进库存/单据链**,`isSerialManaged` ç©ºè½¬ â†’ "按单件 SN ç²¾å‡†è¿½æº¯"目前是断的。
---
## 2. çŽ°çŠ¶èƒ½åŠ›é€ŸæŸ¥
| èƒ½åŠ› | ä¸»è¡¨ | å…³é”®æŽ¥å£ï¼ˆController è·¯å¾„) | çŠ¶æ€ |
|------|------|------------------------------|------|
| åº“存台账/多条件查询/冻结 | `mes_wm_material_stock` | `/mes/wm/material-stock/page/get/update-frozen` | âœ… åœ¨ç”¨ï¼Œæ”¯æŒç‰©æ–™/批次/仓库/库区库位/供应商筛选 |
| åº“存调整(自定义入/出) | åŒä¸Š + æµæ°´ | `/mes/wm/material-stock/adjust-in/adjust-out` | âœ… èµ° transaction,自动更新台账 |
| ç§»åº“/调拨 | åŒä¸Š + `mes_wm_transfer(_line/_detail)` | `/mes/wm/material-stock/move`、`/mes/wm/transfer/*` | âœ… |
| åº“存流水 | `mes_wm_transaction` | `/mes/wm/transaction/page`(可按 bizType/bizCode/item/batch ç­›ï¼‰ | âœ… å« bizId/bizCode/bizLineId/relatedTransactionId,具备反向串联基础 |
| å¯ç”¨é‡ available | å†…存计算字段 | é¡µé¢çŽ°ç®— `qty - frozen - reserved` | âš ï¸ å±•示层现算;reserved ä»…生产领料/销售出库两单占库(`MesWmStockReserveService`) |
| åœ¨é€” inTransit | `mes_wm_material_stock.in_transit_quantity` | æ—  | âŒ æ— ä»»ä½•写入/冲销方,空转字段 |
| ç›˜ç‚¹è®¡åˆ’/任务/行/结果 | `mes_wm_stock_taking_plan(_param)/task(_line/_result)` | `/mes/wm/stock-taking-plan/*`、`/mes/wm/stock-taking-task/*` | âœ… ä¸»æµç¨‹åœ¨ç”¨ï¼›è¡Œæ”¯æŒ Excel å¯¼å…¥è‡ªåŠ¨åˆ¤ç›ˆäºï¼ˆ`importStockTakingQuantity`) |
| ç›˜ç‚¹ç›˜ç›ˆ/盘亏核销 | ç» transaction æ›´æ–°å°è´¦ | `processStockTakingDifference`(Service) | âš ï¸ **半成品**:逻辑存在(`WM_STOCK_TAKING`=107 ç”Ÿæˆ IN/OUT æµæ°´ï¼‰ï¼Œä½†æ— è°ƒç”¨ç‚¹ |
| ç›˜ç‚¹å®¡æ‰¹ | â€” | task åªæœ‰ submit/finish/cancel | âš ï¸ æ‰‹å·¥ä¸¤æ®µå¼ï¼ˆPREPARE→APPROVING→FINISHED),**未接 BPM** |
| æ‰¹æ¬¡ | `mes_wm_batch`(原料+成品统一) | `/mes/wm/batch/get/page` | âœ… å”¯ä¸€ç¼–码/自动编码/批次条码;库存按 batch ç»´åº¦ï¼Œå…¥åº“强校验 batch |
| æ‰¹æ¬¡è¿½æº¯ | æ‰¹æ¬¡Ã—流水×报工 | `/mes/wm/batch/forward-list` `/backward-list` `/purchase-sources` `/sales-targets` `/process-trace` `/get-by-sn` | âœ… å·²é—­çŽ¯ï¼Œå‘å‰/向后/来源/去向/工序/SN åæŸ¥ |
| SN å·æ±  | `mes_wm_sn` | `/mes/wm/sn/*`(`generateSnCodes`) | âš ï¸ åªç”Ÿæˆ"号码池",单据/库存/流水**均无 SN ç»´åº¦** |
| æ¡ç ç”Ÿæˆ | `mes_wm_barcode(_config)` | å„业务对象创建时 `autoGenerateBarcode` | âœ… 18 ç±» biztype,受 config.autoGenerateFlag æŽ§åˆ¶ |
| æ¡ç å†…容 | config.contentFormat | `{BUSINESSCODE}` å•占位 | âš ï¸ æ— "物料+批次+编号+库位"组合字段 |
| æ ‡ç­¾æ‰“印/成图 | config.defaultTemplate(仅字符串) | æ—  | âŒ æ— æ‰“印/渲染/成图接口 |
| æ‰«ç æœåŠ¡ç«¯ | â€” | æ—  | âŒ æ”¶å‘è´§/领料/盘点均无 scan æ ¡éªŒ |
| è®¾å¤‡â†’物料→库存 | `mes_dv_machinery.item_id` | åˆ›å»ºè®¾å¤‡è‡ªåŠ¨å»ºæ–™å¹¶å…¥è®¾å¤‡ä»“ | âœ…(阶段2,`docs/machinery_equipment_material_inbound.md`) |
---
## 3. é€æ¡éœ€æ±‚差距与建议落点
### 3.1 éœ€æ±‚3:物资二维码/标签打印,绑定批次、编号、库位,配合资产与物资追溯
| å­éœ€æ±‚ | çŽ°çŠ¶ | å·®è· | å»ºè®®åŽç«¯è½ç‚¹ |
|--------|------|------|--------------|
| äºŒç»´ç /标签打印 | åªå­˜æ¡ç å­—符串,config æœ‰ `defaultTemplate` å­—段 | **无成图、无模板渲染、无打印接口** | æ–°å¢ž"标签打印"能力:① æ¡ç /二维码图片生成(BarcodeFormatEnum å·²æœ‰ QR/CODE39/EAN13/UPC-A æžšä¸¾ï¼‰ï¼›â‘¡ æ‰“印模板(按 bizType å–字段组合 â†’ æ¸²æŸ“文本/图片);③ æ‰“印接口(单条/批量,可入打印队列)。参考文件:`MesWmBarcodeServiceImpl`、`MesWmBarcodeConfigDO.contentFormat` |
| ç»‘定"批次+编号+库位" | content ä»… `{BUSINESSCODE}` | æ¡ç ä¸å†…嵌组合字段,无法一码携带业务结构 | æ‰©å±•编码规则:config æ”¯æŒå¤šå ä½ç¬¦ç»„合(如 `{CODE}+{BATCH}+{LOCATION}+{SN}`);或保留"码→(bizType,bizId)→对象"反查,配合打印模板字段展示实现"标签带全信息" |
| èµ„产与物资追溯 | è®¾å¤‡â†’物料→设备仓已做(阶段2);批次追溯对原料/成品已闭环 | è¿½æº¯åˆ°æ‰¹æ¬¡ç²’度;**单品 SN è¿½æº¯æ–­**;库存调整/盘点核销/移库是否纳入批次链需核对 | è‹¥éœ€"资产/物资统一追溯视图":以 `mes_wm_transaction` ä¸ºä¸»é“¾è¡¥ç»Ÿä¸€è¿½æº¯æŸ¥è¯¢ï¼ˆå…¥åº“→库存→出库/领用),覆盖盘点核销(107)、移库等 bizType;单品级见 3.3 SN |
### 3.2 éœ€æ±‚4:实时库存查询、定期盘点、盘点数据导入、自动核算盘盈盘亏、更新库存台账
| å­éœ€æ±‚ | çŽ°çŠ¶ | å·®è· | å»ºè®®åŽç«¯è½ç‚¹ |
|--------|------|------|--------------|
| å®žæ—¶åº“存查询 | å°è´¦åˆ†é¡µ + available çŽ°ç®— | available ä¸ºé¡µé¢è®¡ç®—ï¼›reserved ä»…覆盖领料/销售出库;**在途字段空转** | è‹¥éœ€"可用量统一口径/在途",补:`inTransitQuantity` çš„写入与冲销(调拨在途)、reserved è¦†ç›–面决策 |
| å®šæœŸç›˜ç‚¹ | plan åª"圈定一次范围"(按仓库/库区/库位/物料/批次参数) | æœªå‘现**按周期自动生成任务/提醒**的调度 | ç›˜ç‚¹æ–¹æ¡ˆåŠ å‘¨æœŸ(每日/每周/月 + ä¸‹æ¬¡ç›˜ç‚¹æ—¥),由定时任务到期生成 task å¹¶é€šçŸ¥ï¼ˆå¯æ”¾ `MesWmStockTakingPlanService`) |
| ç›˜ç‚¹æ•°æ®å¯¼å…¥ | è¡Œ Excel å¯¼å…¥ï¼ˆç‰©æ–™ç¼–码+批次+实盘数)自动判盈亏 | âœ… å·²å…·å¤‡ | å¯é€‰ï¼šè¡¥æ‰«ç å½•入(见 3.3) |
| **自动核算盘盈盘亏、更新库存台账** | `processStockTakingDifference` å·²å®žçŽ°ï¼šæŒ‰ç»“æžœå·®é¢ç”Ÿæˆ `MesBizTypeConstants.WM_STOCK_TAKING`(107) çš„ IN/OUT æµæ°´å¹¶ç» `createTransaction` æ›´æ–°åº“å­˜ | **方法无任何调用方**;`finishStockTakingTask`(ServiceImpl:146) åªç½® FINISHED+解冻 | **首选接线方案**:完成盘点时自动核销(finish å†…调用)或新增"核销"端点;补幂等(仅允许核销一次)、可查询核销流水、并发防护。涉及文件:`MesWmStockTakingTaskServiceImpl`(:234 æ–¹æ³•体/接口),Controller è¡¥å…¥å£+权限 |
| ç›˜ç‚¹å®¡æ‰¹ | task:submit ç½® APPROVING+可选冻结,finish è¦æ±‚ APPROVING | æ‰‹å·¥ä¸¤æ®µå¼ï¼Œæ—  BPM | è‹¥è¦ä¸Žå…¶ä½™ä»“储单据一致走真实 BPM:参照 `MesWmItemReceiptStatusListener`/阶段1 ä¸‰å•据模式接入;否则保持现状即可,文档注明口径 |
### 3.3 éœ€æ±‚5:全品类条码/二维码管理,串联出入库/领用/盘点,批次与单品精准追溯
| å­éœ€æ±‚ | çŽ°çŠ¶ | å·®è· | å»ºè®®åŽç«¯è½ç‚¹ |
|--------|------|------|--------------|
| å…¨å“ç±»å¯ç”¨æ¡ç  | æŒ‰ bizType çš„ config.autoGenerateFlag è‡ªåŠ¨ç”Ÿæˆï¼›ç‰©æ–™/批次/SN/库位等已覆盖 | STOCK/供应商/客户类无生成入口;**非强制**,未生成则无码可扫 | æ˜Žç¡®"启用范围",对需全品类强制的主数据(物料/批次/库位/SN)做启动校验与补码 |
| ä¸²è”出入库/领用/盘点 | å„单据已建(收料/杂项/领料 productissue/退料 returnissue/盘点) | **服务端无扫码入口**:收货/发料/领料/盘点点行不能"扫条码/SN/批次定位并校验" | æä¾›ç»Ÿä¸€"扫码解析"接口:按 content æˆ– (bizType,bizId) æˆ– SN/批次号解析出物料/批次/库位,供各单据行快速带入并校验(与物料、批次启用、库位匹配);盘点行录入复用 |
| æ‰¹æ¬¡ä¸Žå•品精准追溯 | æ‰¹æ¬¡è¿½æº¯å·²é—­çޝ | **单品(SN)未进库存链**:`mes_wm_sn` ä»…号池,`mes_wm_material_stock`/`mes_wm_transaction` å‡æ—  sn ç»´åº¦ï¼Œ`isSerialManaged` æ— æ¶ˆè´¹æ–¹ | SN å•品链路(改动较大):库存/流水/单据行支持 SN;启用 `isSerialManaged` ç‰©æ–™çš„入库生成/绑定 SN、出库核销 SN;提供"SN åœ¨åº“位置/历史去向"查询;盘点支持按 SN å•件核对 |
---
## 4. æŒ‰"就绪度"归类缺口(建议实施时按此切里程碑)
### 4.1 åŠæˆå“ï¼šé€»è¾‘已有,只差接线(改动小、风险低)
- **盘点差异自动核销**:`MesWmStockTakingTaskServiceImpl#processStockTakingDifference` å·²èƒ½ç”Ÿæˆç›˜ç›ˆ/盘亏流水并更新台账,接上完成盘点即触发/独立端点 + å¹‚等即可闭环需求4"自动核算盘盈盘亏、更新库存台账"。
### 4.2 æ¨¡åž‹å·²æœ‰ï¼Œéœ€è¡¥èƒ½åŠ›ï¼ˆä¸­æ”¹ï¼‰
- **标签打印与成图**:利用已有 BarcodeFormatEnum/条码表,补图片生成、模板渲染、打印接口。
- **条码内容组合字段 / ä¸€ç å¤šä¿¡æ¯**:扩展 contentFormat å¤šå ä½ç¬¦ï¼ˆç‰©æ–™/批次/库位/编号/SN)。
- **服务端扫码**:统一"解析条码/SN/批次"接口,供收发货、领料、盘点行复用。
- **盘点 BPM(可选)** ä¸Ž **定期盘点调度(可选)**。
- **在途/可用量口径**(若业务要求在途)。
- **追溯链补齐**:把盘点核销(107)、移库等 bizType çº³å…¥æ‰¹æ¬¡/流水追溯(核对现 forward/backward æ˜¯å¦å·²å«ï¼‰ã€‚
### 4.3 éœ€æ–°å¢žæ¨¡åž‹ / è¾ƒé‡æž„(大改,按需立项)
- **SN å•品库存链**:库存、流水、单据行增加 SN ç»´åº¦ + å‡ºå…¥åº“核销 + å•件追溯查询 + ç›˜ç‚¹å•件核对。
- **资产属性**:若"资产"不止设备台账,需在物料侧补资产编号/归属/启用日期/报废等属性,与设备台账合并视图。
- **销售发运级追溯**(如要求按出库单 SN/批次追溯去向明细)。
---
## 5. å»ºè®®å®žæ–½é¡ºåº
| ä¼˜å…ˆçº§ | äº‹é¡¹ | ç†ç”±/依据 | ä¸»è¦æ¶‰åŠ |
|--------|------|-----------|----------|
| P0 | ç›˜ç‚¹å®Œæˆè‡ªåŠ¨æ ¸é”€ç›˜ç›ˆç›˜äº | é€»è¾‘现成(差异核销已编码),收益直接,代价最小;直接命中需求4核心 | `MesWmStockTakingTaskServiceImpl`(+Controller/幂等/流水查询) |
| P0 | æ ‡ç­¾æ‰“印(成图+模板+打印) | éœ€æ±‚3硬性项;当前完全缺失 | æ¡ç æœåŠ¡+config+打印接口;BarcodeFormatEnum å¤ç”¨ |
| P1 | æœåŠ¡ç«¯æ‰«ç  + ç›˜ç‚¹æ‰«ç å½•å…¥ | éœ€æ±‚5"串联出入库/领用/盘点"关键 | ç»Ÿä¸€æ‰«ç è§£æžæŽ¥å£ï¼Œå•据行接入 |
| P1 | æ¡ç å†…容组合字段 / ä¸€ç æºå¸¦æ‰¹æ¬¡Â·åº“位·编号·SN | é…åˆæ‰“印与追溯 | contentFormat å¤šå ä½ç¬¦ |
| P1 | SN å•品库存链 | éœ€æ±‚3/5"单品精准追溯" | åº“å­˜/流水/单据 SN ç»´åº¦ + æ ¸é”€ + å•件追溯 |
| P2 | ç›˜ç‚¹æŽ¥ BPM、定期盘点调度 | ä¸Žé˜¶æ®µ1口径一致化、需求4"定期" | å‚照阶段1三单据模式;调度 job |
| P2 | åœ¨é€”/可用量口径、资产属性、销售发运追溯 | ä¾ä¸šåŠ¡éœ€è¦å†å®š | â€” |
> å»ºè®®å…ˆåš P0 ä¸¤é¡¹å½¢æˆ"闭环样板",再按 4.2/4.3 æŽ¨è¿›ï¼›æ¯é¡¹æŒ‰è·¨æ¨¡å—/库表变更在完成后执行 `mvn compile -pl yudao-module-mes -am -q`,涉及 MDM/BPM å†å…¨é‡ç¼–译。数据库脚本遵循 sql-syntax/sql-script è§„范(无 tenant_id、ADD COLUMN å…ˆæŸ¥å­˜åœ¨ï¼‰ã€‚