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

11 KiB
Raw Blame History

能源分摊(现有实现)与加入“备件/辅料分摊”的接入方案

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.xmlselectCoilTotalMergedselectCoilTotalMergedExport 已加入 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/mergedGET /ems/energy/report/coilTotal/merged/export,分别取字段 auxCost / spareCost
      • 构成:新增两个接口返回“按物料/备件聚合后的分摊构成”(数量与金额均按日分摊系数切分):
        • GET /ems/energy/report/material/aux/breakdown
        • GET /ems/energy/report/material/spare/breakdown
    • 口径(构成)
      • 全厂按日聚合消耗(eqp_*_changechange_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_changeeqp_spare_parts_change 两张变动表(可在 EMS 侧 SQL 直接使用)。
    • 已完成:梳理前端 klp-ui/src/views/ems/cost/cost.vue 的查询/展示/接口调用。
    • 已完成:定位后端 EnergyCostReportControllerWmsEnergyCoilDailyMapper.xml
    • 已修正:早期将能源分摊概括为“库区时间窗”会误导备件/辅料接入;备件/辅料分摊以 wms_coil_pending_action 的待操作时间窗为中心(见本时间线确认项)。
    • 已确认MES 成本记账规则)
      • 台账表(eqp_spare_parteqp_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
  • 主要 SQLklp-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. 现有“能源分摊”后端是怎么做的(与备件/辅料接入相关的部分)

核心 ControllerEnergyCostReportController

  • 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

入参对象:CoilTotalCostBoenterCoilNo/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

注意:实现时需要防止分母为 0CASE 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

    • 增加字段:auxCostspareCost(以及 totalCost 公式更新)
  • klp-ems/src/main/resources/mapper/WmsEnergyCoilDailyMapper.xml

    • 修改:selectCoilTotalMergedselectCoilTotalMergedExport
  • 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 聚合)
    • 表格增加两列:auxCostspareCost
    • 总成本公式更新:能源 + 囤积 + 备件 + 辅料

5. 当前状态(给新 agent 的交接结论)

  • 分摊口径已最终确认并记录:全厂池 + 按天切分 + A 方案(按 DATE(pa.create_time) 归属)
  • EMS/WMS 可直接查询 MES 的 change 表,允许在 WmsEnergyCoilDailyMapper.xml 内直接 join 实现。
  • 尚未开始实际代码改造;下一步按第 4 节清单逐项实现,并在每次提交后回写本文件时间线(记录修改了哪些文件/字段/SQL