You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

699 lines
36 KiB
XML

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?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》的“质检单 -> 生产订单 -> 分表”口径定位。
真实库中存在两类偏差:
1. 成品质检条码落在 barcode 而不是 batch_no
2. 生产订单未完全回填到 prod_order_info。
因此这里保留原始订单判定链路,同时增加“按成品分表直接回溯”的兜底逻辑,
确保真实演示数据可以稳定命中而不误判行业。
-->
<select id="selectAnchor" resultType="java.util.Map">
WITH qc_match AS (
SELECT TOP 1
qim.production_order AS productionOrder,
qim.tenant_id AS tenant_id
FROM qc_inspection_main qim
WHERE (
RTRIM(LTRIM(ISNULL(qim.batch_no, ''))) = RTRIM(LTRIM(#{batchCode}))
OR RTRIM(LTRIM(ISNULL(qim.barcode, ''))) = RTRIM(LTRIM(#{batchCode}))
)
AND qim.del_flag = '0'
ORDER BY qim.inspection_end_time DESC, qim.create_time DESC
),
industry_judge AS (
SELECT TOP 1
po.product_order_id AS productOrderId,
po.order_code AS orderCode,
po.material_id AS materialId,
po.tenant_id AS tenant_id,
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'
INNER JOIN qc_match qm
ON qm.productionOrder = po.order_code
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
1 AS matchPriority,
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
1 AS matchPriority,
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
UNION ALL
<!-- 轮胎行业兜底:直接按成品条码命中硫化分表,兼容真实库未完整回填订单的情况 -->
SELECT TOP 1
2 AS matchPriority,
'TIRE' AS industryType,
p.product_order_id AS productOrderId,
po.order_code AS orderCode,
COALESCE(po.material_id, p.material_id) 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 prod_product_plan_detail_4 d
ON d.plan_id = p.plan_id
AND ISNULL(d.del_flag, '0') = '0'
LEFT JOIN prod_order_info po
ON po.product_order_id = p.product_order_id
LEFT JOIN base_material_info bmi
ON bmi.material_id = COALESCE(po.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}))
)
AND ISNULL(RTRIM(LTRIM(bmi.tire_markings)), '') &lt;&gt; ''
ORDER BY d.real_end_time DESC, d.create_time DESC
UNION ALL
<!-- 机加行业兜底:直接按成品条码命中通用分表 -->
SELECT TOP 1
2 AS matchPriority,
'JJ' AS industryType,
p.product_order_id AS productOrderId,
po.order_code AS orderCode,
COALESCE(po.material_id, p.material_id) 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 prod_product_plan_detail d
ON d.plan_id = p.plan_id
AND ISNULL(d.del_flag, '0') = '0'
LEFT JOIN prod_order_info po
ON po.product_order_id = p.product_order_id
LEFT JOIN base_material_info bmi
ON bmi.material_id = COALESCE(po.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}))
)
AND ISNULL(RTRIM(LTRIM(bmi.tire_markings)), '') = ''
ORDER BY d.real_end_time DESC, d.create_time DESC
) anchor
ORDER BY anchor.matchPriority ASC, 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 (
RTRIM(LTRIM(ISNULL(qim.batch_no, ''))) = RTRIM(LTRIM(#{batchCode}))
OR RTRIM(LTRIM(ISNULL(qim.barcode, ''))) = RTRIM(LTRIM(#{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 (
RTRIM(LTRIM(ISNULL(qim.batch_no, ''))) = RTRIM(LTRIM(#{batchCode}))
OR RTRIM(LTRIM(ISNULL(qim.barcode, ''))) = RTRIM(LTRIM(#{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,
COALESCE(wso.outstock_code, wor.outstock_code) AS invoiceNo
FROM wms_outstock_record wor
LEFT JOIN wms_outstock_order wso
ON wso.outstock_id = wor.outstock_id
LEFT JOIN wms_base_customer c
ON c.customer_id = COALESCE(wso.customer_id, wor.customer_id)
WHERE RTRIM(LTRIM(ISNULL(wor.batch_code, ''))) = RTRIM(LTRIM(#{batchCode}))
ORDER BY COALESCE(wor.create_time, wso.audit_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,
COALESCE(
NULLIF(RTRIM(LTRIM(qim.batch_no)), ''),
NULLIF(RTRIM(LTRIM(qim.barcode)), ''),
#{batchCode}
) 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 (
RTRIM(LTRIM(ISNULL(qim.batch_no, ''))) = RTRIM(LTRIM(#{batchCode}))
OR RTRIM(LTRIM(ISNULL(qim.barcode, ''))) = RTRIM(LTRIM(#{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,
p4.tenant_id AS tenant_id
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,
pis.tenant_id
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,
COALESCE(
NULLIF(RTRIM(LTRIM(qim.batch_no)), ''),
NULLIF(RTRIM(LTRIM(qim.barcode)), '')
) AS traceBatch,
qim.material_code,
qim.supplier_name,
qim.result,
qim.tenant_id,
ROW_NUMBER() OVER (
PARTITION BY COALESCE(
NULLIF(RTRIM(LTRIM(qim.batch_no)), ''),
NULLIF(RTRIM(LTRIM(qim.barcode)), '')
), 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,
wor.tenant_id,
SUM(wor.outstock_qty) AS outstock_qty
FROM wms_outstock_record wor
GROUP BY wor.batch_code, wor.material_id, wor.tenant_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,
COALESCE(mu.unit_name, bmi.material_unit) 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
-- 这里优先按物料主数据真实字段 material_unit_id 关联,避免旧口径 unit_id 在当前库中不存在导致 SQL 失败
ON mu.unit_id = bmi.material_unit_id
LEFT JOIN qc_latest ql
ON ql.traceBatch = RTRIM(LTRIM(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>