feat(mes/ReverseTraceMapper): 优化混料追溯报表数据查询逻辑

- 简化实际重量计算逻辑,移除复杂的CASE WHEN条件判断
- 新增时间段内所有工步列表查询功能,支持曲线生成需求
- 实现混料步骤数据的完整时间线展示
- 添加设备、材料、配方等相关信息的关联查询
- 优化SQL性能,减少不必要的子查询和条件判断
- 支持按多种条件筛选混料步骤数据
master
zangch@mesnac.com 1 week ago
parent e4c9c2acd7
commit ba10ca4395

@ -0,0 +1,599 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.mes.mapper.ReverseTraceMapper">
<!-- ======================== 1. 行业判定 + 成品锚点定位 ======================== -->
<!--
严格按《密炼.txt》4.1 + 4.2 执行:
1. 先通过 prod_order_info + base_material_info.tire_markings + qc_inspection_main.production_order 判定行业
2. 再按已判定行业去对应成品明细表定位锚点
为什么这里恢复成“两阶段”:
文档要求先基于生产订单和质检主表确定行业,而不是直接根据成品分表是否命中来反推。
这样可以避免“轮胎单据但 _4 未命中时被误判成机加”的口径偏差。
-->
<select id="selectAnchor" resultType="java.util.Map">
WITH industry_judge AS (
SELECT TOP 1
po.product_order_id AS productOrderId,
po.order_code AS orderCode,
po.material_id AS materialId,
CASE
WHEN ISNULL(RTRIM(LTRIM(bmi.tire_markings)), '') &lt;&gt; '' THEN 'TIRE'
ELSE 'JJ'
END AS industryType
FROM prod_order_info po
LEFT JOIN base_material_info bmi
ON bmi.material_id = po.material_id
AND bmi.del_flag = '0'
WHERE EXISTS (
SELECT 1
FROM qc_inspection_main qim
WHERE qim.production_order = po.order_code
AND qim.batch_no = #{batchCode}
AND qim.del_flag = '0'
)
ORDER BY po.create_time DESC
)
SELECT TOP 1
anchor.industryType,
anchor.productOrderId,
anchor.orderCode,
anchor.materialId,
anchor.batchCode,
anchor.finalPlanId,
anchor.finalPlanCode,
anchor.finalPlanDetailId,
anchor.finalPlanDetailCode,
anchor.materialBarcode,
anchor.returnBarcode,
anchor.productionDate
FROM (
<!-- 轮胎行业:从 _4 硫化明细表查找 -->
SELECT TOP 1
ij.industryType AS industryType,
ij.productOrderId AS productOrderId,
ij.orderCode AS orderCode,
ij.materialId AS materialId,
#{batchCode} AS batchCode,
p.plan_id AS finalPlanId,
p.plan_code AS finalPlanCode,
d.plan_detail_id AS finalPlanDetailId,
d.plan_detail_code AS finalPlanDetailCode,
d.material_barcode AS materialBarcode,
d.return_barcode AS returnBarcode,
d.real_end_time AS productionDate
FROM prod_plan_info_4 p
INNER JOIN industry_judge ij
ON ij.productOrderId = p.product_order_id
AND ij.industryType = 'TIRE'
INNER JOIN prod_product_plan_detail_4 d
ON d.plan_id = p.plan_id
AND ISNULL(d.del_flag, '0') = '0'
WHERE (
RTRIM(LTRIM(ISNULL(d.material_barcode, ''))) = RTRIM(LTRIM(#{batchCode}))
OR RTRIM(LTRIM(ISNULL(d.return_barcode, ''))) = RTRIM(LTRIM(#{batchCode}))
)
ORDER BY d.real_end_time DESC, d.create_time DESC
UNION ALL
<!-- 机加行业:从通用明细表查找 -->
SELECT TOP 1
ij.industryType AS industryType,
ij.productOrderId AS productOrderId,
ij.orderCode AS orderCode,
ij.materialId AS materialId,
#{batchCode} AS batchCode,
p.plan_id AS finalPlanId,
p.plan_code AS finalPlanCode,
d.plan_detail_id AS finalPlanDetailId,
d.plan_detail_code AS finalPlanDetailCode,
d.material_barcode AS materialBarcode,
d.return_barcode AS returnBarcode,
d.real_end_time AS productionDate
FROM prod_plan_info p
INNER JOIN industry_judge ij
ON ij.productOrderId = p.product_order_id
AND ij.industryType = 'JJ'
INNER JOIN prod_product_plan_detail d
ON d.plan_id = p.plan_id
AND ISNULL(d.del_flag, '0') = '0'
WHERE (
RTRIM(LTRIM(ISNULL(d.material_barcode, ''))) = RTRIM(LTRIM(#{batchCode}))
OR RTRIM(LTRIM(ISNULL(d.return_barcode, ''))) = RTRIM(LTRIM(#{batchCode}))
)
ORDER BY d.real_end_time DESC, d.create_time DESC
) anchor
ORDER BY anchor.productionDate DESC
</select>
<!-- ======================== 2. 成品信息查询 ======================== -->
<!--
成品状态映射优先级:已出库 > 已入库 > 已质检 > 生产完成
已出库wms_outstock_record 中有该批次码的记录
已入库wms_instock_record 中有该批次码的记录
已质检qc_inspection_main 中有该批次码且 result='0'(合格)的记录
其他:默认生产完成
-->
<select id="selectProductInfo" resultType="org.dromara.mes.domain.vo.ReverseTraceVo$ProductInfo">
<!-- 轮胎行业 -->
<if test="industryType == 'TIRE'">
SELECT TOP 1
#{batchCode} AS batchCode,
bmi.material_code AS productCode,
bmi.material_name AS productName,
bmi.material_spec AS spec,
CONVERT(VARCHAR(19), d.real_end_time, 120) AS productionDate,
CASE
WHEN EXISTS (
SELECT 1 FROM wms_outstock_record wor
WHERE RTRIM(LTRIM(ISNULL(wor.batch_code, ''))) = RTRIM(LTRIM(#{batchCode}))
) THEN N'已出库'
WHEN EXISTS (
SELECT 1 FROM wms_instock_record wir
WHERE RTRIM(LTRIM(ISNULL(wir.batch_code, ''))) = RTRIM(LTRIM(#{batchCode}))
) THEN N'已入库'
WHEN EXISTS (
SELECT 1 FROM qc_inspection_main qim
WHERE qim.batch_no = #{batchCode}
AND qim.del_flag = '0'
AND qim.result = '0'
) THEN N'已质检'
ELSE N'生产完成'
END AS status
FROM prod_plan_info_4 p
INNER JOIN prod_product_plan_detail_4 d
ON d.plan_id = p.plan_id AND ISNULL(d.del_flag, '0') = '0'
LEFT JOIN base_material_info bmi
ON bmi.material_id = p.material_id AND bmi.del_flag = '0'
WHERE RTRIM(LTRIM(ISNULL(d.material_barcode, ''))) = RTRIM(LTRIM(#{batchCode}))
OR RTRIM(LTRIM(ISNULL(d.return_barcode, ''))) = RTRIM(LTRIM(#{batchCode}))
ORDER BY d.real_end_time DESC, d.create_time DESC
</if>
<!-- 机加行业 -->
<if test="industryType != 'TIRE'">
SELECT TOP 1
#{batchCode} AS batchCode,
bmi.material_code AS productCode,
bmi.material_name AS productName,
bmi.material_spec AS spec,
CONVERT(VARCHAR(19), d.real_end_time, 120) AS productionDate,
CASE
WHEN EXISTS (
SELECT 1 FROM wms_outstock_record wor
WHERE RTRIM(LTRIM(ISNULL(wor.batch_code, ''))) = RTRIM(LTRIM(#{batchCode}))
) THEN N'已出库'
WHEN EXISTS (
SELECT 1 FROM wms_instock_record wir
WHERE RTRIM(LTRIM(ISNULL(wir.batch_code, ''))) = RTRIM(LTRIM(#{batchCode}))
) THEN N'已入库'
WHEN EXISTS (
SELECT 1 FROM qc_inspection_main qim
WHERE qim.batch_no = #{batchCode}
AND qim.del_flag = '0'
AND qim.result = '0'
) THEN N'已质检'
ELSE N'生产完成'
END AS status
FROM prod_plan_info p
INNER JOIN prod_product_plan_detail d
ON d.plan_id = p.plan_id AND ISNULL(d.del_flag, '0') = '0'
LEFT JOIN base_material_info bmi
ON bmi.material_id = p.material_id AND bmi.del_flag = '0'
WHERE RTRIM(LTRIM(ISNULL(d.material_barcode, ''))) = RTRIM(LTRIM(#{batchCode}))
OR RTRIM(LTRIM(ISNULL(d.return_barcode, ''))) = RTRIM(LTRIM(#{batchCode}))
ORDER BY d.real_end_time DESC, d.create_time DESC
</if>
</select>
<!-- ======================== 3. 客户信息查询 ======================== -->
<!--
仅当存在出库记录时返回数据。
关联链路wms_outstock_record -> wms_outstock_order -> wms_base_customer
-->
<select id="selectCustomerInfo" resultType="org.dromara.mes.domain.vo.ReverseTraceVo$CustomerData">
SELECT TOP 1
c.customer_code AS customerCode,
c.customer_name AS customerName,
c.contact_person AS contactPerson,
c.contact_phone AS contactPhone,
c.address AS deliveryAddress,
CONVERT(VARCHAR(19), COALESCE(wor.create_time, wso.audit_time), 120) AS outboundTime,
CONVERT(VARCHAR(32), wor.outstock_qty) AS outboundQty,
wso.outstock_code AS invoiceNo
FROM wms_outstock_record wor
INNER JOIN wms_outstock_order wso
ON wso.outstock_id = wor.outstock_id
LEFT JOIN wms_base_customer c
ON c.customer_id = wso.customer_id
WHERE RTRIM(LTRIM(ISNULL(wor.batch_code, ''))) = RTRIM(LTRIM(#{batchCode}))
ORDER BY wor.create_time DESC
</select>
<!-- ======================== 4. 成品质检主信息 ======================== -->
<select id="selectQcInfo" resultType="org.dromara.mes.domain.vo.ReverseTraceVo$QcInfo">
SELECT TOP 1
qim.inspection_id AS inspectionId,
qim.inspection_no AS qcCode,
qim.batch_no AS batchCode,
qim.material_code AS productCode,
qim.material_name AS productName,
CAST(NULL AS VARCHAR(200)) AS spec,
CONVERT(VARCHAR(19), qim.inspection_end_time, 120) AS qcTime,
qit.type_name AS qcType,
qim.inspector AS inspector,
CASE qim.result
WHEN '0' THEN N'合格'
WHEN '1' THEN N'不合格'
ELSE N'未判定'
END AS result
FROM qc_inspection_main qim
LEFT JOIN qc_inspection_type qit
ON qit.type_id = qim.inspection_type AND qit.del_flag = '0'
WHERE qim.batch_no = #{batchCode}
AND qim.del_flag = '0'
ORDER BY qim.inspection_end_time DESC, qim.create_time DESC
</select>
<!-- ======================== 5. 质检明细查询 ======================== -->
<!--
标准值展示逻辑:
- detect_type='1'(计量型): 展示"下限 ~ 上限"
- 其他(计数型/文本型): 展示 spec_inspection 或 spec_name
-->
<select id="selectQcCheckItems" resultType="org.dromara.mes.domain.vo.TraceQcCheckItemVo">
SELECT
qir.item_name AS itemName,
CASE
WHEN qir.detect_type = '1' THEN
CONCAT(
ISNULL(CONVERT(VARCHAR(50), qir.lower_limit), ''),
' ~ ',
ISNULL(CONVERT(VARCHAR(50), qir.upper_limit), '')
)
ELSE
ISNULL(qir.spec_inspection, qir.spec_name)
END AS standard,
CASE
WHEN qir.detect_type = '1' THEN CONVERT(VARCHAR(50), qir.detect_value)
ELSE ISNULL(qir.problem_detail, N'')
END AS actual,
CASE qir.detect_result
WHEN '0' THEN N'合格'
WHEN '1' THEN N'不合格'
ELSE N'未判定'
END AS result
FROM qc_inspection_result qir
WHERE qir.inspection_id = #{inspectionId}
AND qir.del_flag = '0'
ORDER BY qir.create_time ASC
</select>
<!-- ======================== 6. 生产订单信息 ======================== -->
<select id="selectProductionOrder" resultType="org.dromara.mes.domain.vo.ReverseTraceVo$ProductionOrder">
SELECT
po.order_code AS orderCode,
#{batchCode} AS batchCode,
bmi.material_name AS productName,
po.dispatch_type AS dispatchType,
CASE po.dispatch_type
WHEN '1' THEN N'产线'
WHEN '2' THEN N'工艺路线'
WHEN '3' THEN N'工序'
ELSE po.dispatch_type
END AS dispatchTypeName,
<!-- 派工信息:根据派工类型关联不同表获取名称 -->
CASE po.dispatch_type
WHEN '1' THEN (SELECT TOP 1 pli.prod_line_name FROM prod_base_prod_line_info pli WHERE pli.prod_line_id = po.dispatch_id)
WHEN '2' THEN (SELECT TOP 1 rt.route_name FROM prod_base_route rt WHERE rt.route_id = po.dispatch_id)
WHEN '3' THEN (SELECT TOP 1 pi.process_name FROM prod_base_process_info pi WHERE pi.process_id = po.dispatch_id)
ELSE CONVERT(VARCHAR(64), po.dispatch_id)
END AS dispatchInfo,
CONVERT(VARCHAR(32), po.plan_amount) AS planQty,
CONVERT(VARCHAR(32), po.dispatch_amount) AS dispatchedQty,
CONVERT(VARCHAR(32), po.complete_amount) AS completedQty,
CONVERT(VARCHAR(19), po.real_begin_time, 120) AS startTime,
CONVERT(VARCHAR(19), po.real_end_time, 120) AS endTime,
CASE po.order_status
WHEN '2' THEN N'已完成'
WHEN '3' THEN N'已开始'
WHEN '1' THEN N'已发布'
WHEN '4' THEN N'暂停'
ELSE N'待处理'
END AS status
FROM prod_order_info po
LEFT JOIN base_material_info bmi
ON bmi.material_id = po.material_id AND bmi.del_flag = '0'
WHERE po.product_order_id = #{productOrderId}
</select>
<!-- ======================== 7. 生产工单列表 - 轮胎行业 ======================== -->
<!--
为什么使用 UNION ALL 四张表:
轮胎行业按工序分为密炼(_1)、半制品(_2)、成型(_3)、硫化(_4) 四张表。
同一 product_order_id 下可能有多道工序的工单,需要汇总展示。
Service 层已经通过锚点查到了 product_order_id这里直接按订单过滤
可以避免再次按 batchCode 扫描硫化明细表,减少一次无效回表。
-->
<select id="selectWorkOrderListTire" resultType="org.dromara.mes.domain.vo.ReverseTraceVo$WorkOrder">
WITH final_plan AS (
SELECT TOP 1
p4.product_order_id,
p4.plan_id,
p4.plan_code
FROM prod_plan_info_4 p4
WHERE p4.product_order_id = #{productOrderId}
ORDER BY p4.create_time DESC, p4.plan_id DESC
)
SELECT * FROM (
<!-- 密炼 _1 -->
SELECT
p1.process_order AS processSeq,
p1.plan_code AS workOrderCode,
bp.process_code AS processCode,
bp.process_name AS processName,
CONVERT(VARCHAR(64), p1.release_id) AS machineNo,
bm.machine_name AS machineName,
CONVERT(VARCHAR(19), COALESCE(MAX(d1.real_begin_time), p1.real_begin_time), 120) AS startTime,
CONVERT(VARCHAR(19), COALESCE(MAX(d1.real_end_time), p1.real_end_time), 120) AS endTime,
MAX(d1.user_name) AS worker,
CASE COALESCE(MAX(d1.plan_detail_status), p1.plan_status)
WHEN '3' THEN N'已完成'
WHEN '2' THEN N'已开始'
WHEN '1' THEN N'未开始'
ELSE N'待处理'
END AS status,
p1.plan_id AS planId,
'TIRE' AS industryType
FROM final_plan fp
INNER JOIN prod_plan_info_1 p1 ON p1.product_order_id = fp.product_order_id
LEFT JOIN prod_product_plan_detail_1 d1 ON d1.plan_id = p1.plan_id AND ISNULL(d1.del_flag, '0') = '0'
LEFT JOIN prod_base_process_info bp ON bp.process_id = p1.process_id
LEFT JOIN prod_base_machine_info bm ON bm.machine_id = p1.release_id
GROUP BY p1.process_order, p1.plan_code, bp.process_code, bp.process_name,
p1.release_id, bm.machine_name, p1.real_begin_time, p1.real_end_time, p1.plan_status, p1.plan_id
UNION ALL
<!-- 半制品 _2 -->
SELECT
p2.process_order AS processSeq,
p2.plan_code AS workOrderCode,
bp.process_code AS processCode,
bp.process_name AS processName,
CONVERT(VARCHAR(64), p2.release_id) AS machineNo,
bm.machine_name AS machineName,
CONVERT(VARCHAR(19), COALESCE(MAX(d2.real_begin_time), p2.real_begin_time), 120) AS startTime,
CONVERT(VARCHAR(19), COALESCE(MAX(d2.real_end_time), p2.real_end_time), 120) AS endTime,
MAX(d2.user_name) AS worker,
CASE COALESCE(MAX(d2.plan_detail_status), p2.plan_status)
WHEN '3' THEN N'已完成'
WHEN '2' THEN N'已开始'
WHEN '1' THEN N'未开始'
ELSE N'待处理'
END AS status,
p2.plan_id AS planId,
'TIRE' AS industryType
FROM final_plan fp
INNER JOIN prod_plan_info_2 p2 ON p2.product_order_id = fp.product_order_id
LEFT JOIN prod_product_plan_detail_2 d2 ON d2.plan_id = p2.plan_id AND ISNULL(d2.del_flag, '0') = '0'
LEFT JOIN prod_base_process_info bp ON bp.process_id = p2.process_id
LEFT JOIN prod_base_machine_info bm ON bm.machine_id = p2.release_id
GROUP BY p2.process_order, p2.plan_code, bp.process_code, bp.process_name,
p2.release_id, bm.machine_name, p2.real_begin_time, p2.real_end_time, p2.plan_status, p2.plan_id
UNION ALL
<!-- 成型 _3 -->
SELECT
p3.process_order AS processSeq,
p3.plan_code AS workOrderCode,
bp.process_code AS processCode,
bp.process_name AS processName,
CONVERT(VARCHAR(64), p3.release_id) AS machineNo,
bm.machine_name AS machineName,
CONVERT(VARCHAR(19), COALESCE(MAX(d3.real_begin_time), p3.real_begin_time), 120) AS startTime,
CONVERT(VARCHAR(19), COALESCE(MAX(d3.real_end_time), p3.real_end_time), 120) AS endTime,
MAX(d3.user_name) AS worker,
CASE COALESCE(MAX(d3.plan_detail_status), p3.plan_status)
WHEN '3' THEN N'已完成'
WHEN '2' THEN N'已开始'
WHEN '1' THEN N'未开始'
ELSE N'待处理'
END AS status,
p3.plan_id AS planId,
'TIRE' AS industryType
FROM final_plan fp
INNER JOIN prod_plan_info_3 p3 ON p3.product_order_id = fp.product_order_id
LEFT JOIN prod_product_plan_detail_3 d3 ON d3.plan_id = p3.plan_id AND ISNULL(d3.del_flag, '0') = '0'
LEFT JOIN prod_base_process_info bp ON bp.process_id = p3.process_id
LEFT JOIN prod_base_machine_info bm ON bm.machine_id = p3.release_id
GROUP BY p3.process_order, p3.plan_code, bp.process_code, bp.process_name,
p3.release_id, bm.machine_name, p3.real_begin_time, p3.real_end_time, p3.plan_status, p3.plan_id
UNION ALL
<!-- 硫化 _4 -->
SELECT
p4.process_order AS processSeq,
p4.plan_code AS workOrderCode,
bp.process_code AS processCode,
bp.process_name AS processName,
CONVERT(VARCHAR(64), p4.release_id) AS machineNo,
bm.machine_name AS machineName,
CONVERT(VARCHAR(19), COALESCE(MAX(d4.real_begin_time), p4.real_begin_time), 120) AS startTime,
CONVERT(VARCHAR(19), COALESCE(MAX(d4.real_end_time), p4.real_end_time), 120) AS endTime,
MAX(d4.user_name) AS worker,
CASE COALESCE(MAX(d4.plan_detail_status), p4.plan_status)
WHEN '3' THEN N'已完成'
WHEN '2' THEN N'已开始'
WHEN '1' THEN N'未开始'
ELSE N'待处理'
END AS status,
p4.plan_id AS planId,
'TIRE' AS industryType
FROM final_plan fp
INNER JOIN prod_plan_info_4 p4 ON p4.product_order_id = fp.product_order_id
LEFT JOIN prod_product_plan_detail_4 d4 ON d4.plan_id = p4.plan_id AND ISNULL(d4.del_flag, '0') = '0'
LEFT JOIN prod_base_process_info bp ON bp.process_id = p4.process_id
LEFT JOIN prod_base_machine_info bm ON bm.machine_id = p4.release_id
GROUP BY p4.process_order, p4.plan_code, bp.process_code, bp.process_name,
p4.release_id, bm.machine_name, p4.real_begin_time, p4.real_end_time, p4.plan_status, p4.plan_id
) t
ORDER BY t.processSeq ASC, t.planId ASC
</select>
<!-- ======================== 8. 生产工单列表 - 机加行业 ======================== -->
<select id="selectWorkOrderListJj" resultType="org.dromara.mes.domain.vo.ReverseTraceVo$WorkOrder">
SELECT
p.process_order AS processSeq,
p.plan_code AS workOrderCode,
bp.process_code AS processCode,
bp.process_name AS processName,
CONVERT(VARCHAR(64), p.release_id) AS machineNo,
bm.machine_name AS machineName,
CONVERT(VARCHAR(19), COALESCE(d.real_begin_time, p.real_begin_time), 120) AS startTime,
CONVERT(VARCHAR(19), COALESCE(d.real_end_time, p.real_end_time), 120) AS endTime,
d.user_name AS worker,
CASE COALESCE(d.plan_detail_status, p.plan_status)
WHEN '3' THEN N'已完成'
WHEN '2' THEN N'已开始'
WHEN '1' THEN N'未开始'
ELSE N'待处理'
END AS status,
p.plan_id AS planId,
'JJ' AS industryType
FROM prod_plan_info p
INNER JOIN prod_product_plan_detail d
ON d.plan_id = p.plan_id AND ISNULL(d.del_flag, '0') = '0'
LEFT JOIN prod_base_process_info bp ON bp.process_id = p.process_id
LEFT JOIN prod_base_machine_info bm ON bm.machine_id = p.release_id
WHERE RTRIM(LTRIM(ISNULL(d.material_barcode, ''))) = RTRIM(LTRIM(#{batchCode}))
OR RTRIM(LTRIM(ISNULL(d.return_barcode, ''))) = RTRIM(LTRIM(#{batchCode}))
ORDER BY p.process_order ASC, p.create_time ASC
</select>
<!-- ======================== 9. 查询工单产出条码 ======================== -->
<!--
根据行业类型查不同的明细表,获取该工单下的所有产出条码。
产出条码优先取 material_barcode为空则取 return_barcode。
-->
<select id="selectProductionBarcodes" resultType="java.lang.String">
<if test="industryType == 'TIRE'">
<if test="tableSuffix == '_1'">
SELECT COALESCE(NULLIF(RTRIM(LTRIM(d.material_barcode)), ''), RTRIM(LTRIM(d.return_barcode)))
FROM prod_product_plan_detail_1 d
WHERE d.plan_id = #{planId} AND ISNULL(d.del_flag, '0') = '0'
AND (ISNULL(RTRIM(LTRIM(d.material_barcode)), '') != '' OR ISNULL(RTRIM(LTRIM(d.return_barcode)), '') != '')
</if>
<if test="tableSuffix == '_2'">
SELECT COALESCE(NULLIF(RTRIM(LTRIM(d.material_barcode)), ''), RTRIM(LTRIM(d.return_barcode)))
FROM prod_product_plan_detail_2 d
WHERE d.plan_id = #{planId} AND ISNULL(d.del_flag, '0') = '0'
AND (ISNULL(RTRIM(LTRIM(d.material_barcode)), '') != '' OR ISNULL(RTRIM(LTRIM(d.return_barcode)), '') != '')
</if>
<if test="tableSuffix == '_3'">
SELECT COALESCE(NULLIF(RTRIM(LTRIM(d.material_barcode)), ''), RTRIM(LTRIM(d.return_barcode)))
FROM prod_product_plan_detail_3 d
WHERE d.plan_id = #{planId} AND ISNULL(d.del_flag, '0') = '0'
AND (ISNULL(RTRIM(LTRIM(d.material_barcode)), '') != '' OR ISNULL(RTRIM(LTRIM(d.return_barcode)), '') != '')
</if>
<if test="tableSuffix == '_4'">
SELECT COALESCE(NULLIF(RTRIM(LTRIM(d.material_barcode)), ''), RTRIM(LTRIM(d.return_barcode)))
FROM prod_product_plan_detail_4 d
WHERE d.plan_id = #{planId} AND ISNULL(d.del_flag, '0') = '0'
AND (ISNULL(RTRIM(LTRIM(d.material_barcode)), '') != '' OR ISNULL(RTRIM(LTRIM(d.return_barcode)), '') != '')
</if>
</if>
<if test="industryType != 'TIRE'">
SELECT COALESCE(NULLIF(RTRIM(LTRIM(d.material_barcode)), ''), RTRIM(LTRIM(d.return_barcode)))
FROM prod_product_plan_detail d
WHERE d.plan_id = #{planId} AND ISNULL(d.del_flag, '0') = '0'
AND (ISNULL(RTRIM(LTRIM(d.material_barcode)), '') != '' OR ISNULL(RTRIM(LTRIM(d.return_barcode)), '') != '')
</if>
</select>
<!-- ======================== 10. 原材料投料信息查询 ======================== -->
<!--
核心条码链路:
产出条码 -> prod_input_scan_info.production_barcode -> input_barcode -> 关联原材料
三层关联:
1. input_record: 从扫描表获取投入记录
2. qc_latest: 取每条投入批次最新的质检记录ROW_NUMBER 窗口函数)
3. outstock_sum: 按批次 + 物料汇总出库数量,避免分批领料时数量被最后一笔覆盖
为什么使用 CTE
质检记录按 batch_no + material_code 分组取最新,出库记录按批次和物料汇总,
CTE 使复杂聚合逻辑更清晰可读。
-->
<select id="selectMaterialInputs" resultType="org.dromara.mes.domain.vo.TraceMaterialInputVo">
WITH input_record AS (
SELECT
pis.prod_input_scan_info_id,
pis.production_barcode,
pis.input_barcode,
pis.materiel_id,
pis.feeding_time
FROM prod_input_scan_info pis
WHERE RTRIM(LTRIM(ISNULL(pis.production_barcode, ''))) = RTRIM(LTRIM(#{productionBarcode}))
),
qc_latest AS (
SELECT
qim.inspection_id,
qim.inspection_no,
qim.batch_no,
qim.material_code,
qim.supplier_name,
qim.result,
ROW_NUMBER() OVER (
PARTITION BY qim.batch_no, qim.material_code
ORDER BY qim.inspection_end_time DESC, qim.create_time DESC
) AS rn
FROM qc_inspection_main qim
WHERE qim.del_flag = '0'
),
outstock_sum AS (
SELECT
wor.batch_code,
wor.material_id,
SUM(wor.outstock_qty) AS outstock_qty
FROM wms_outstock_record wor
GROUP BY wor.batch_code, wor.material_id
)
SELECT
ir.production_barcode AS productionBarcode,
ir.prod_input_scan_info_id AS inputScanId,
bmi.material_code AS materialCode,
bmi.material_name AS materialName,
ir.input_barcode AS batchCode,
ql.supplier_name AS supplier,
CONVERT(VARCHAR(32), os.outstock_qty) AS qty,
mu.unit_name AS unit,
CONVERT(VARCHAR(19), ir.feeding_time, 120) AS inTime,
ql.inspection_no AS qcCode,
CASE ql.result
WHEN '0' THEN N'合格'
WHEN '1' THEN N'不合格'
ELSE N'未判定'
END AS qcResult,
ql.inspection_id AS inspectionId
FROM input_record ir
LEFT JOIN base_material_info bmi
ON bmi.material_id = ir.materiel_id AND bmi.del_flag = '0'
LEFT JOIN base_measurement_unit_info mu
ON mu.unit_id = bmi.unit_id
LEFT JOIN qc_latest ql
ON ql.batch_no = ir.input_barcode
AND ql.material_code = bmi.material_code
AND ql.rn = 1
LEFT JOIN outstock_sum os
ON os.batch_code = ir.input_barcode
AND os.material_id = ir.materiel_id
ORDER BY ir.feeding_time DESC, ir.prod_input_scan_info_id DESC
</select>
</mapper>
Loading…
Cancel
Save