Files
klp-oa/ems-cost-allocation-notes.md

226 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

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

# 能源分摊(现有实现)与加入“备件/辅料分摊”的接入方案
## 0. 时间线(用于交接,持续更新)
- **2026-01-20**
- **已改动(代码)**
- `klp-ems/src/main/java/com/klp/ems/domain/vo/CoilTotalCostVo.java`:新增 `auxCost/spareCost` 字段,`totalCost` 注释更新。
- `klp-ems/src/main/java/com/klp/ems/domain/vo/CoilTotalMergedExportVo.java`:新增导出列 `auxCost/spareCost`
- `klp-ems/src/main/resources/mapper/WmsEnergyCoilDailyMapper.xml``selectCoilTotalMerged``selectCoilTotalMergedExport` 已加入 `auxCost/spareCost` 计算与 join并更新 `totalCost` 公式。
- `klp-ems/src/main/java/com/klp/ems/controller/EnergyCostReportController.java`:导出接口已补充 `auxCost/spareCost` 赋值。
- `klp-ui/src/views/ems/cost/cost.vue`:列表新增列展示 `auxCost/spareCost`;顶部卡片展示 `materialSummary`(当前按列表行求和);总成本计算加入备件/辅料。
- **2026-01-26**
- **新增(前端页面)**:按数据库路由方式新增两个独立页面(不在前端代码写路由)。
- `klp-ui/src/views/ems/cost/auxAllocation.vue`:辅料成本分摊页面(按入场卷号汇总),包含“分摊明细”弹窗与导出;并新增“辅料消耗构成(分摊口径)”区域(展示用了哪些辅料、几种、数量与金额)。
- `klp-ui/src/views/ems/cost/spareAllocation.vue`:备件成本分摊页面(按入场卷号汇总),包含“分摊明细”弹窗与导出;并新增“备件消耗构成(分摊口径)”区域(展示用了哪些备件、几种、数量与金额)。
- **路由 component 配置建议(写入数据库)**
- 辅料:`ems/cost/auxAllocation`
- 备件:`ems/cost/spareAllocation`
- **接口复用说明**
- 汇总:两个页面均复用 `GET /ems/energy/report/coilTotal/merged``GET /ems/energy/report/coilTotal/merged/export`,分别取字段 `auxCost` / `spareCost`
- 构成:新增两个接口返回“按物料/备件聚合后的分摊构成”(数量与金额均按日分摊系数切分):
- `GET /ems/energy/report/material/aux/breakdown`
- `GET /ems/energy/report/material/spare/breakdown`
- **口径(构成)**
- 全厂按日聚合消耗(`eqp_*_change``change_type='减少'`,金额取 `ABS(amount)`,数量取 `ABS(change_quantity)`
- 当日卷分摊系数:`coil_minutes_day / total_minutes_day`(分钟基于 `wms_coil_pending_action.create_time ~ complete_time/now`
- 最终按物料/备件汇总:`allocatedQty = Σ_D (day_item_qty * factor_day)``allocatedAmount = Σ_D (day_item_amount * factor_day)`
- **重要说明**
- merged 仍不返回按日池/分钟明细;页面“分摊明细”弹窗仍为汇总占位。
- 构成接口可在不强制 enterCoilNo 的情况下使用:不传 enterCoilNo 时可用于查看全厂消耗构成allocated≈total
- **2026-01-20**
- **口径确认**:备件/辅料分摊池按**全厂**聚合(不按库区/设备/产线拆分)。
- **过滤规则确认**
- `wms_coil_pending_action`:按 `pa.create_time` 落在 `[startDate, endDate]` 过滤。
- `eqp_*_change`:按 `change_time` 落在同一 `[startDate, endDate]` 过滤。
- 仅统计 `change_type = '减少'`(消耗)。
- **金额按天切分规则确认**:采用 **A 方案**(按 `DATE(pa.create_time)` 归属到某一天;不做跨天拆分时长)。消耗金额按天形成日池(例如 3 天形成 3 个日池、5 天形成 5 个日池),再在当日内按钢卷时长占比分摊。
- **跨库可达性确认**EMS/WMS 可以直接查询到 MES 的 `eqp_auxiliary_material_change``eqp_spare_parts_change` 两张变动表(可在 EMS 侧 SQL 直接使用)。
- **已完成**:梳理前端 `klp-ui/src/views/ems/cost/cost.vue` 的查询/展示/接口调用。
- **已完成**:定位后端 `EnergyCostReportController``WmsEnergyCoilDailyMapper.xml`
- **已修正**:早期将能源分摊概括为“库区时间窗”会误导备件/辅料接入;备件/辅料分摊以 `wms_coil_pending_action` 的待操作时间窗为中心(见本时间线确认项)。
- **已确认MES 成本记账规则)**
- 台账表(`eqp_spare_part``eqp_auxiliary_material`)补充 `unit_price/total_amount`
- 入库单价来源:**前端必传**(老接口与前端一并改造)。
- 入库/增加时采用移动加权平均价:`new_unit_price = (old_unit_price*old_qty + in_unit_price*in_qty) / (old_qty+in_qty)`
- 消耗/减少时在变动表写入 `unit_price_snapshot` 并计算 `amount`**有符号**;减少为负:`-unit_price_snapshot * change_quantity`)。
- 分摊侧聚合消耗金额使用 `ABS(amount)`
> 范围:
> - 前端页面:`klp-ui/src/views/ems/cost/cost.vue`
> - 后端接口:`klp-ems/src/main/java/com/klp/ems/controller/EnergyCostReportController.java`
> - 主要 SQL`klp-ems/src/main/resources/mapper/WmsEnergyCoilDailyMapper.xml`
> - MES 表结构:`script/sql/mysql/eqp_auxiliary_material.sql`
## 1. 现有页面做了什么(前端)
页面名称:`CoilTotalCost`(钢卷成本汇总)
### 1.1 查询条件
`queryParams`
- `enterCoilNo`:入场卷号(页面标记 required支持模糊
- `currentCoilNo`:当前卷号(支持模糊)
- `startDate`开始日期yyyy-MM-dd
- `endDate`结束日期yyyy-MM-dd
点击“查询”会同时触发三块数据加载:
- **能源成本汇总 + 明细**EMS
- **囤积成本明细/汇总**WMS
- **能源+囤积 合并汇总**EMS 聚合接口)
### 1.2 页面展示结构
- **顶部 4 个卡片**
- **能源成本**:来自 `energySummary.totalEnergyCost`,并展示耗能、时长
- **本日囤积成本**:来自 `stockSummary.todayCost`,并展示净重/毛重
- **辅料成本**:当前写死 `0.00``暂不计`
- **总成本**`能源 + 囤积 + 辅料(当前为 0)`
- **表格:成本汇总(按入场卷号)**
- 数据源:`mergedRows`
- 列:入场卷号、当前卷号、能源成本、囤积成本(当日)、总成本、净重、毛重
- 操作:查看详情
- **详情弹窗**
- 能源分摊明细(按待操作时间跨度分摊)
- 囤积成本(单行汇总)
### 1.3 前端调用的接口
能源相关(同一模块 `@/api/ems/energyCostReport`
- `fetchCoilTotalEnergySummary(params)`
- 对应后端:`GET /ems/energy/report/coilTotal/summary`
- `fetchCoilTotalEnergyDetail(params)`
- 对应后端:`GET /ems/energy/report/coilTotal/detail`
- `fetchCoilTotalMerged(params)`
- 对应后端:`GET /ems/energy/report/coilTotal/merged`
- `exportCoilTotalMerged(params)`
- 对应后端:`GET /ems/energy/report/coilTotal/merged/export`
囤积成本WMS 模块 `@/api/wms/cost`
- `getStockpileCostList(params)`
## 2. 现有“能源分摊”后端是怎么做的(与备件/辅料接入相关的部分)
核心 Controller`EnergyCostReportController`
- `GET /ems/energy/report/coilTotal/summary`
- `GET /ems/energy/report/coilTotal/detail`
- `GET /ems/energy/report/coilTotal/merged`
- `GET /ems/energy/report/coilTotal/merged/export`
入参对象:`CoilTotalCostBo``enterCoilNo/currentCoilNo/startDate/endDate`
当前实现中,`coilTotal/*` 相关 SQL 主要围绕 `wms_coil_pending_action` 的时间跨度计算(分钟/小时),并将能耗/成本按占比分配到卷。
## 3. 备件/辅料分摊:最新确认的正确口径(可直接实现)
### 3.1 总体思路
- 备件/辅料成本池:按**全厂**聚合。
- 成本池按**日**切分:以 `DATE(change_time)` 形成每日消耗金额池。
- 分摊权重按**日**切分:以 `DATE(pa.create_time)` 形成每日钢卷“待操作时长”池。
- 当天内按“入场卷号的总时长 / 全厂总时长”占比,将当日消耗金额分摊到各入场卷号。
### 3.2 关键定义A 方案:不拆跨天时长)
#### (1) 当日消耗金额池(仅减少)
- `aux_pool_day(D) = SUM(eqp_auxiliary_material_change.amount)`
- `spare_pool_day(D) = SUM(eqp_spare_parts_change.amount)`
过滤:
- `change_type = '减少'`
- `DATE(change_time) = D`
-`change_time``[startDate, endDate]` 范围内(与查询一致)
#### (2) 当日全厂总时长池
- `minutes(pa) = TIMESTAMPDIFF(MINUTE, pa.create_time, COALESCE(pa.complete_time, NOW()))`
- `total_minutes_day(D) = SUM(minutes(pa))`
过滤:
- `pa.create_time``[startDate, endDate]`
- `DATE(pa.create_time) = D`
#### (3) 当日按入场卷号的时长
- `coil_minutes_day(D, enter_coil_no) = SUM(minutes(pa))`
其中 `enter_coil_no` 通过:
- `wms_coil_pending_action.pa.coil_id -> wms_material_coil.coil_id -> wms_material_coil.enter_coil_no`
#### (4) 当日分摊与汇总
- `aux_cost_day = aux_pool_day(D) * coil_minutes_day / total_minutes_day`
- `spare_cost_day = spare_pool_day(D) * coil_minutes_day / total_minutes_day`
最终:
- `auxCost = Σ_D aux_cost_day`
- `spareCost = Σ_D spare_cost_day`
### 3.3 SQL 接入点(在 EMS merged 中 join
建议在 `WmsEnergyCoilDailyMapper.xml`
- `selectCoilTotalMerged`
- `selectCoilTotalMergedExport`
新增 join 结构:
1. 先构造“按入场卷号的每日分钟数”子查询:`coil_day_minutes`
2. 再构造“全厂每日总分钟数”子查询:`total_day_minutes`
3. 再构造“全厂每日消耗金额池(备件/辅料)”子查询:`aux_day_amount` / `spare_day_amount`
4. 通过 `day` 将以上子查询 join 起来,得到 `Σ( day_amount * coil_day_minutes / total_day_minutes )`
5. 最终在 `merged` 的 select 列表中补充:
- `IFNULL(x.aux_cost, 0) AS auxCost`
- `IFNULL(x.spare_cost, 0) AS spareCost`
- `totalCost = energy_cost + stock_cost + aux_cost + spare_cost`
> 注意:实现时需要防止分母为 0`CASE WHEN total_day_minutes > 0 THEN ... ELSE 0 END`。
## 4. 需要改动的后端/前端文件清单(待实现)
### 4.1 EMS 后端klp-ems
- `klp-ems/src/main/java/com/klp/ems/domain/vo/CoilTotalCostVo.java`
- 增加字段:`auxCost``spareCost`(以及 `totalCost` 公式更新)
- `klp-ems/src/main/resources/mapper/WmsEnergyCoilDailyMapper.xml`
- 修改:`selectCoilTotalMerged``selectCoilTotalMergedExport`
- `klp-ems/src/main/java/com/klp/ems/controller/EnergyCostReportController.java`
- 导出映射:`coilTotalMergedExport` 增加导出字段赋值
- `klp-ems/src/main/java/com/klp/ems/domain/vo/CoilTotalMergedExportVo.java`
- 增加列:备件成本、辅料成本(以及总成本)
### 4.2 前端klp-ui
- `klp-ui/src/views/ems/cost/cost.vue`
- 顶部卡片:“辅料成本”从 0 改为接口返回(或新增 summary 聚合)
- 表格增加两列:`auxCost``spareCost`
- 总成本公式更新:能源 + 囤积 + 备件 + 辅料
---
## 5. 当前状态(给新 agent 的交接结论)
- 分摊口径已最终确认并记录:**全厂池 + 按天切分 + A 方案(按 `DATE(pa.create_time)` 归属)**。
- EMS/WMS 可直接查询 MES 的 change 表,允许在 `WmsEnergyCoilDailyMapper.xml` 内直接 join 实现。
- 尚未开始实际代码改造;下一步按第 4 节清单逐项实现,并在每次提交后回写本文件时间线(记录修改了哪些文件/字段/SQL