From 534cc438066871470e367a86293556daea286692 Mon Sep 17 00:00:00 2001 From: "zangch@mesnac.com" Date: Sun, 22 Feb 2026 22:35:54 +0800 Subject: [PATCH] =?UTF-8?q?feat(mes):=20=E6=96=B0=E5=A2=9E=E6=B7=B7?= =?UTF-8?q?=E7=82=BC=E8=BF=BD=E6=BA=AF=E6=8A=A5=E8=A1=A8=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 MixTraceListVo 中新增实际重量、检验结果、累计车次、计划明细状态字段 - 在 MixTraceSummaryVo 中新增检验结果和配方时间字段 - 在 MixTraceUsageVo 中新增配方ID、计划明细ID、重量ID等相关字段 - 修改数据库查询逻辑,添加默认值处理和条件筛选功能 - 新增车次范围查询条件支持 - 完善物料追溯匹配逻辑,增加多层级匹配优先级 - 优化料罐类型显示逻辑,支持字典翻译和回退机制 - 添加租户ID过滤支持,增强数据隔离能力 - 完善动作类型和状态的分类逻辑,支持自动识别卸料和称量操作 --- .../dromara/mes/domain/vo/MixTraceListVo.java | 16 ++ .../mes/domain/vo/MixTraceSummaryVo.java | 3 + .../mes/domain/vo/MixTraceUsageVo.java | 13 +- .../impl/ProdMixTraceReportServiceImpl.java | 1 + .../mapper/mes/ProdMixTraceReportMapper.xml | 269 +++++++++++++++--- 5 files changed, 266 insertions(+), 36 deletions(-) diff --git a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/MixTraceListVo.java b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/MixTraceListVo.java index 9f8e8a86..285b6d77 100644 --- a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/MixTraceListVo.java +++ b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/MixTraceListVo.java @@ -144,10 +144,26 @@ public class MixTraceListVo implements Serializable { @ExcelProperty(value = "完成数") private BigDecimal completeAmount; + /** 实际重量/实量 */ + @ExcelProperty(value = "实量") + private BigDecimal realWeight; + + /** 检验结果 */ + @ExcelProperty(value = "检验结果") + private String testResult; + /** 车次 */ @ExcelProperty(value = "密炼车次") private Long trainNumber; + /** 累计车次 */ + @ExcelProperty(value = "累计车次") + private Long totalTrainNo; + + /** 计划明细状态 */ + @ExcelProperty(value = "生产状态") + private String planDetailStatus; + /** 实际开始时间 */ @ExcelProperty(value = "开始生产时间") private Date realBeginTime; diff --git a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/MixTraceSummaryVo.java b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/MixTraceSummaryVo.java index 8c0de9a0..a1c66b62 100644 --- a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/MixTraceSummaryVo.java +++ b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/MixTraceSummaryVo.java @@ -49,6 +49,9 @@ public class MixTraceSummaryVo implements Serializable { private BigDecimal dischargeEnergy; private String mixingStatus; + private String testResult; + private Long recipeTime; + private Long mixingTime; private Long consumeTime; private Long intervalTime; diff --git a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/MixTraceUsageVo.java b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/MixTraceUsageVo.java index e90c1413..5965ef65 100644 --- a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/MixTraceUsageVo.java +++ b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/MixTraceUsageVo.java @@ -16,8 +16,18 @@ public class MixTraceUsageVo implements Serializable { private static final long serialVersionUID = 1L; private Long usageId; + private Long recipeId; + private Long planDetailId; + private Long weightId; private Long weightSeq; + private Integer traceWeightSeq; + private Long traceWeightId; + private String traceActCode; + private Long traceRowCount; + private String jarTypeName; private String categoryName; + private Long wareNum; + private String weighNum; private String materialName; private BigDecimal setWeight; @@ -30,5 +40,6 @@ public class MixTraceUsageVo implements Serializable { private String actCode; private String actName; + private String actionType; + private String actionStatus; } - diff --git a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/service/impl/ProdMixTraceReportServiceImpl.java b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/service/impl/ProdMixTraceReportServiceImpl.java index 614fb6db..963db48d 100644 --- a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/service/impl/ProdMixTraceReportServiceImpl.java +++ b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/service/impl/ProdMixTraceReportServiceImpl.java @@ -67,6 +67,7 @@ public class ProdMixTraceReportServiceImpl implements IProdMixTraceReportService // 入口参数统一规范后,再注入 recipeId,避免前端同名空值覆盖 Map detailParams = safeParams(params); detailParams.put("recipeId", recipeId); + detailParams.put("tenantId", TenantHelper.getTenantId()); // 先查主信息,主信息不存在时不继续查询子表,避免无意义 IO MixTraceListVo recipeInfo = mixTraceReportMapper.selectTraceRecipeInfo(detailParams); diff --git a/ruoyi-modules/hwmom-mes/src/main/resources/mapper/mes/ProdMixTraceReportMapper.xml b/ruoyi-modules/hwmom-mes/src/main/resources/mapper/mes/ProdMixTraceReportMapper.xml index d4d3b72b..4504ff3f 100644 --- a/ruoyi-modules/hwmom-mes/src/main/resources/mapper/mes/ProdMixTraceReportMapper.xml +++ b/ruoyi-modules/hwmom-mes/src/main/resources/mapper/mes/ProdMixTraceReportMapper.xml @@ -7,9 +7,9 @@ WITH router_master_data AS ( SELECT - MAX(CASE WHEN REPLACE(sm.query_param, ' ', '') LIKE '%"router":"act"%' THEN sm.master_data_id END) AS act_master_data_id, - MAX(CASE WHEN REPLACE(sm.query_param, ' ', '') LIKE '%"router":"term"%' THEN sm.master_data_id END) AS term_master_data_id, - MAX(CASE WHEN REPLACE(sm.query_param, ' ', '') LIKE '%"router":"jar"%' THEN sm.master_data_id END) AS jar_master_data_id + COALESCE(MAX(CASE WHEN REPLACE(sm.query_param, ' ', '') LIKE '%"router":"act"%' THEN sm.master_data_id END), 10009) AS act_master_data_id, + COALESCE(MAX(CASE WHEN REPLACE(sm.query_param, ' ', '') LIKE '%"router":"term"%' THEN sm.master_data_id END), 10010) AS term_master_data_id, + COALESCE(MAX(CASE WHEN REPLACE(sm.query_param, ' ', '') LIKE '%"router":"jar"%' THEN sm.master_data_id END), 10011) AS jar_master_data_id FROM sys_master_data sm WHERE sm.del_flag = '0' AND sm.active_flag = '1' @@ -84,6 +84,12 @@ OR LTRIM(RTRIM(COALESCE(ppd.material_barcode, ''))) = LTRIM(RTRIM(#{map.productionBarcode})) ) + + AND ppd.train_number >= #{map.trainNumberStart} + + + AND ppd.train_number <= #{map.trainNumberEnd} + ORDER BY CASE WHEN #{map.planDetailId} IS NOT NULL @@ -140,17 +146,31 @@ tp.classTeamName AS classTeamName, tp.planAmount AS planAmount, COALESCE(tp.detailCompleteAmount, tp.planCompleteAmount) AS completeAmount, + COALESCE(tp.detailCompleteAmount, tp.planCompleteAmount) AS realWeight, + CAST(NULL AS VARCHAR(64)) AS testResult, tp.trainNumber AS trainNumber, + train_stat.totalTrainNo AS totalTrainNo, + tp.planDetailStatus AS planDetailStatus, COALESCE(tp.detailRealBeginTime, tp.planRealBeginTime) AS realBeginTime, COALESCE(tp.detailRealEndTime, tp.planRealEndTime) AS realEndTime FROM prod_recipe_info ri LEFT JOIN prod_base_machine_info bm ON bm.machine_id = ri.machine_id LEFT JOIN base_material_info bmi ON bmi.material_id = ri.material_id + OUTER APPLY ( + SELECT CAST(COUNT(1) AS BIGINT) AS totalTrainNo + FROM prod_product_plan_detail_1 d + WHERE tp.planId IS NOT NULL + AND d.plan_id = tp.planId + AND ISNULL(d.del_flag, '0') = '0' + ) train_stat WHERE ri.del_flag = '0' AND ri.recipe_code LIKE CONCAT('%', #{map.recipeCode}, '%') + + AND ri.recipe_id = #{map.recipeId} + AND ri.machine_id = #{map.machineId} @@ -190,6 +210,8 @@ or (map.planDetailId != null and map.planDetailId != '') or (map.planDetailCode != null and map.planDetailCode != '') or (map.productionBarcode != null and map.productionBarcode != '') + or (map.trainNumberStart != null and map.trainNumberStart != '') + or (map.trainNumberEnd != null and map.trainNumberEnd != '') or (map.shiftId != null and map.shiftId != '') or (map.classTeamId != null and map.classTeamId != '') or (map.shiftName != null and map.shiftName != '') @@ -296,6 +318,8 @@ mix_last.dischargePower AS dischargePower, mix_last.dischargeEnergy AS dischargeEnergy, tp.planDetailStatus AS mixingStatus, + CAST(NULL AS VARCHAR(64)) AS testResult, + ri.done_time AS recipeTime, mix_sum.totalMixingTime AS mixingTime, CASE WHEN tp.detailRealBeginTime IS NOT NULL AND tp.detailRealEndTime IS NOT NULL @@ -388,9 +412,12 @@ w.father_code AS fatherCode, w.unit_id AS unitId, w.child_code AS childCode, + bmi.material_name AS materialName, w.if_use_bat AS ifUseBat, w.max_rate AS maxRate FROM prod_recipe_weight w + LEFT JOIN base_material_info bmi ON bmi.material_id = w.child_code + AND bmi.tenant_id = w.tenant_id CROSS JOIN router_master_data rmd OUTER APPLY ( SELECT TOP 1 d.data_detail_name @@ -411,8 +438,23 @@ SELECT w.weight_id AS usageId, + w.recipe_id AS recipeId, + trace_used.tracePlanDetailId AS planDetailId, + w.weight_id AS weightId, w.weight_seq AS weightSeq, - RTRIM(LTRIM(COALESCE(w.weight_type, ''))) AS categoryName, + trace_used.traceWeightSeq AS traceWeightSeq, + trace_used.traceWeightId AS traceWeightId, + trace_used.traceActCode AS traceActCode, + trace_used.traceRowCount AS traceRowCount, + -- 类别展示三层兜底:jar主数据名称 -> 机台罐型编码 -> 配方weight_type + jar_detail.jarTypeName AS jarTypeName, + COALESCE( + NULLIF(RTRIM(LTRIM(COALESCE(jar_detail.jarTypeName, ''))), ''), + NULLIF(RTRIM(LTRIM(COALESCE(CONVERT(VARCHAR(64), jar_ref.tankTypeCode), ''))), ''), + RTRIM(LTRIM(COALESCE(w.weight_type, ''))) + ) AS categoryName, + jar_ref.wareNum AS wareNum, + jar_ref.weighNum AS weighNum, COALESCE(cm.material_name, fm.material_name, act_detail.data_detail_name, RTRIM(LTRIM(COALESCE(w.act_code, '')))) AS materialName, w.set_weight AS setWeight, trace_used.actualWeight AS actualWeight, @@ -431,11 +473,58 @@ CASE WHEN act_detail.data_detail_name IS NULL OR LTRIM(RTRIM(act_detail.data_detail_name)) = '' THEN RTRIM(LTRIM(COALESCE(w.act_code, ''))) ELSE RTRIM(LTRIM(act_detail.data_detail_name)) - END AS actName + END AS actName, + -- 动作类型严格二值:卸料/称量(ELSE 必须回落称量) + CASE + WHEN CHARINDEX(N'卸', COALESCE(act_detail.data_detail_name, '')) > 0 THEN N'卸料' + WHEN RTRIM(LTRIM(COALESCE(w.act_code, ''))) IN ('11', '12') THEN N'卸料' + ELSE N'称量' + END AS actionType, + -- 称量状态优先级:卸料强制覆盖 -> 自动/手动 -> '-' + CASE + WHEN CHARINDEX(N'卸', COALESCE(act_detail.data_detail_name, '')) > 0 + OR RTRIM(LTRIM(COALESCE(w.act_code, ''))) IN ('11', '12') THEN N'卸料' + WHEN RTRIM(LTRIM(COALESCE(w.if_use_bat, ''))) = '1' THEN N'自动' + WHEN RTRIM(LTRIM(COALESCE(w.if_use_bat, ''))) = '0' THEN N'手动' + ELSE '-' + END AS actionStatus FROM prod_recipe_weight w CROSS JOIN router_master_data rmd + LEFT JOIN prod_recipe_info ri ON ri.recipe_id = w.recipe_id AND ISNULL(ri.del_flag, '0') = '0' LEFT JOIN base_material_info cm ON cm.material_id = w.child_code LEFT JOIN base_material_info fm ON fm.material_id = w.father_code + -- 机台+物料映射料罐,子料优先,再按料仓优先级与仓位号稳定选择 + OUTER APPLY ( + SELECT TOP 1 + td.ware_num AS wareNum, + td.weigh_num AS weighNum, + tt.tank_type AS tankTypeCode + FROM prod_machine_tank_detail td + LEFT JOIN prod_machine_tank_type tt + ON tt.tank_type_id = td.tank_type_id + AND ISNULL(tt.del_flag, '0') = '0' + WHERE ISNULL(td.del_flag, '0') = '0' + AND RTRIM(LTRIM(CONVERT(VARCHAR(64), td.machine_id))) = RTRIM(LTRIM(CONVERT(VARCHAR(64), ri.machine_id))) + AND td.material_id IN (w.child_code, w.father_code) + + AND td.tenant_id = #{map.tenantId} + + ORDER BY + CASE WHEN td.material_id = w.child_code THEN 0 ELSE 1 END, + ISNULL(td.mater_priority, 999999), + td.ware_num + ) jar_ref + -- jar 主数据字典翻译:优先用罐型编码,缺失时回退 weight_type + OUTER APPLY ( + SELECT TOP 1 d.data_detail_name AS jarTypeName + FROM sys_master_data_detail d + WHERE d.del_flag = '0' + AND d.active_flag = '1' + AND d.master_data_id = rmd.jar_master_data_id + AND RTRIM(LTRIM(COALESCE(d.data_detail_code, ''))) = + RTRIM(LTRIM(COALESCE(CONVERT(VARCHAR(64), jar_ref.tankTypeCode), CONVERT(VARCHAR(64), w.weight_type), ''))) + ORDER BY d.master_data_detail_id DESC + ) jar_detail OUTER APPLY ( SELECT TOP 1 d.data_detail_name FROM sys_master_data_detail d @@ -447,40 +536,150 @@ ) act_detail OUTER APPLY ( - SELECT - CASE - WHEN ISNULL(SUM(CASE WHEN t.materiel_id = w.child_code THEN 1 ELSE 0 END), 0) = 0 - AND ISNULL(SUM(CASE - WHEN w.father_code IS NOT NULL - AND w.father_code <> w.child_code - AND t.materiel_id = w.father_code THEN 1 - ELSE 0 - END), 0) = 0 - THEN NULL - ELSE - ISNULL(SUM(CASE WHEN t.materiel_id = w.child_code THEN ISNULL(t.used_amount, 0) ELSE 0 END), 0) - + ISNULL(SUM(CASE - WHEN w.father_code IS NOT NULL - AND w.father_code <> w.child_code - AND t.materiel_id = w.father_code - THEN ISNULL(t.used_amount, 0) - ELSE 0 - END), 0) - END AS actualWeight - FROM prod_trace_cur_info t - WHERE t.production_barcode = #{map.productionBarcode} - AND ( - t.materiel_id = w.child_code - OR ( - w.father_code IS NOT NULL - AND w.father_code <> w.child_code - AND t.materiel_id = w.father_code + SELECT TOP 1 + matched.actualWeight, + matched.tracePlanDetailId, + matched.traceRecipeId, + matched.traceWeightSeq, + matched.traceWeightId, + matched.traceActCode, + matched.traceRowCount + FROM ( + SELECT + CAST(1 AS INT) AS matchPriority, + CAST(SUM(ISNULL(t.used_amount, 0)) AS DECIMAL(18, 4)) AS actualWeight, + MAX(t.plan_detail_id) AS tracePlanDetailId, + MAX(t.recipe_id) AS traceRecipeId, + MAX(t.weight_seq) AS traceWeightSeq, + MAX(t.weight_id) AS traceWeightId, + MAX(RTRIM(LTRIM(COALESCE(t.act_code, '')))) AS traceActCode, + CAST(COUNT(1) AS BIGINT) AS traceRowCount + FROM prod_trace_cur_info t + WHERE t.production_barcode = #{map.productionBarcode} + + AND t.tenant_id = #{map.tenantId} + + + AND t.plan_detail_id = #{map.planDetailId} + + + AND t.recipe_id = #{map.recipeId} + + AND t.weight_id = w.weight_id + AND ( + t.materiel_id = w.child_code + OR ( + w.father_code IS NOT NULL + AND w.father_code <> w.child_code + AND t.materiel_id = w.father_code + ) ) - ) + HAVING COUNT(1) > 0 + + UNION ALL + + SELECT + CAST(2 AS INT) AS matchPriority, + CAST(SUM(ISNULL(t.used_amount, 0)) AS DECIMAL(18, 4)) AS actualWeight, + MAX(t.plan_detail_id) AS tracePlanDetailId, + MAX(t.recipe_id) AS traceRecipeId, + MAX(t.weight_seq) AS traceWeightSeq, + MAX(t.weight_id) AS traceWeightId, + MAX(RTRIM(LTRIM(COALESCE(t.act_code, '')))) AS traceActCode, + CAST(COUNT(1) AS BIGINT) AS traceRowCount + FROM prod_trace_cur_info t + WHERE t.production_barcode = #{map.productionBarcode} + + AND t.tenant_id = #{map.tenantId} + + + AND t.plan_detail_id = #{map.planDetailId} + + + AND t.recipe_id = #{map.recipeId} + + AND t.weight_id IS NULL + AND t.weight_seq = w.weight_seq + AND ( + RTRIM(LTRIM(COALESCE(t.act_code, ''))) = RTRIM(LTRIM(COALESCE(w.act_code, ''))) + OR RTRIM(LTRIM(COALESCE(t.act_code, ''))) = '' + ) + AND ( + t.materiel_id = w.child_code + OR ( + w.father_code IS NOT NULL + AND w.father_code <> w.child_code + AND t.materiel_id = w.father_code + ) + ) + HAVING COUNT(1) > 0 + + UNION ALL + + SELECT + CAST(9 AS INT) AS matchPriority, + CAST( + CASE + WHEN ISNULL(SUM(CASE WHEN t.materiel_id = w.child_code THEN 1 ELSE 0 END), 0) = 0 + AND ISNULL(SUM(CASE + WHEN w.father_code IS NOT NULL + AND w.father_code <> w.child_code + AND t.materiel_id = w.father_code THEN 1 + ELSE 0 + END), 0) = 0 + THEN NULL + ELSE + ISNULL(SUM(CASE WHEN t.materiel_id = w.child_code THEN ISNULL(t.used_amount, 0) ELSE 0 END), 0) + + ISNULL(SUM(CASE + WHEN w.father_code IS NOT NULL + AND w.father_code <> w.child_code + AND t.materiel_id = w.father_code + THEN ISNULL(t.used_amount, 0) + ELSE 0 + END), 0) + END + AS DECIMAL(18, 4)) AS actualWeight, + MAX(t.plan_detail_id) AS tracePlanDetailId, + MAX(t.recipe_id) AS traceRecipeId, + MAX(t.weight_seq) AS traceWeightSeq, + MAX(t.weight_id) AS traceWeightId, + MAX(RTRIM(LTRIM(COALESCE(t.act_code, '')))) AS traceActCode, + CAST(COUNT(1) AS BIGINT) AS traceRowCount + FROM prod_trace_cur_info t + WHERE t.production_barcode = #{map.productionBarcode} + + AND t.tenant_id = #{map.tenantId} + + + AND (t.plan_detail_id = #{map.planDetailId} OR t.plan_detail_id IS NULL) + + + AND (t.recipe_id = #{map.recipeId} OR t.recipe_id IS NULL) + + AND ( + t.materiel_id = w.child_code + OR ( + w.father_code IS NOT NULL + AND w.father_code <> w.child_code + AND t.materiel_id = w.father_code + ) + ) + HAVING COUNT(1) > 0 + ) matched + ORDER BY matched.matchPriority ASC ) trace_used - OUTER APPLY (SELECT CAST(NULL AS DECIMAL(18, 4)) AS actualWeight) trace_used + OUTER APPLY ( + SELECT + CAST(NULL AS DECIMAL(18, 4)) AS actualWeight, + CAST(NULL AS BIGINT) AS tracePlanDetailId, + CAST(NULL AS BIGINT) AS traceRecipeId, + CAST(NULL AS INT) AS traceWeightSeq, + CAST(NULL AS BIGINT) AS traceWeightId, + CAST(NULL AS VARCHAR(32)) AS traceActCode, + CAST(NULL AS BIGINT) AS traceRowCount + ) trace_used WHERE w.del_flag = '0' AND w.recipe_id = #{map.recipeId}