diff --git a/src/main/java/com/xujie/modules/qms/entity/vo/TemplateDTO.java b/src/main/java/com/xujie/modules/qms/entity/vo/TemplateDTO.java index df65df4..4d6f55e 100644 --- a/src/main/java/com/xujie/modules/qms/entity/vo/TemplateDTO.java +++ b/src/main/java/com/xujie/modules/qms/entity/vo/TemplateDTO.java @@ -17,4 +17,6 @@ public class TemplateDTO { private BigDecimal aql; private BigDecimal ac; private BigDecimal re; + private BigDecimal defaultSamplingQuantity; + private BigDecimal defaultSamplingProportion; } diff --git a/src/main/java/com/xujie/modules/qms/service/impl/QcServiceImpl.java b/src/main/java/com/xujie/modules/qms/service/impl/QcServiceImpl.java index 0500891..78b9af1 100644 --- a/src/main/java/com/xujie/modules/qms/service/impl/QcServiceImpl.java +++ b/src/main/java/com/xujie/modules/qms/service/impl/QcServiceImpl.java @@ -69,6 +69,7 @@ import java.util.stream.Collectors; @Service @Slf4j public class QcServiceImpl implements QcService { + private static final String TEMPLATE_SUPPLIER_WILDCARD = "*"; //记录日志使用 private static final Logger logger = LoggerFactory.getLogger(HttpClientUtil.class); @@ -5473,29 +5474,32 @@ public class QcServiceImpl implements QcService { return "免检物料,无需生成IQC"; } - List templates = getTemplates(detail); + List templates = deduplicateTemplates(getTemplates(detail)); if (templates == null || templates.isEmpty()) { throw new RuntimeException("未维护此物料的检验模板"); } String inspectionNo = genInspectionNo(detail.getSite()); updateInspectRequestDetail(detail, inspectionNo); - insertMain(detail, partAttr, inspectionNo); + BigDecimal mainSamplingQty = resolveSamplingQty(detail.getQty(), partAttr, templates); + insertMain(detail, partAttr, inspectionNo, mainSamplingQty); + Set insertedItemNoSet = new HashSet<>(); for (TemplateDTO template : templates) { // 查询模板明细 - List items = + List items = deduplicateTemplateItems( getTemplateDetail(template.getTemplateId(), detail.getSite(), partAttr.getBuNo(), - "*"); + TEMPLATE_SUPPLIER_WILDCARD)); if (items == null || items.isEmpty()) { continue; } - insertDetail(detail, partAttr, template, items, inspectionNo); + BigDecimal detailSamplingQty = resolveSamplingQty(detail.getQty(), partAttr, template); + insertDetail(detail, partAttr, template, items, inspectionNo, detailSamplingQty, insertedItemNoSet); } return inspectionNo; @@ -5521,7 +5525,7 @@ public class QcServiceImpl implements QcService { return qcMapper.listByPart( detail.getSite(), detail.getPartNo(), - "*"); + TEMPLATE_SUPPLIER_WILDCARD); } // ================= 查询模板明细 ================= @@ -5532,9 +5536,115 @@ public class QcServiceImpl implements QcService { return qcMapper.listDetail(templateId, site, buNo, supplierNo); } + /** + * 计算检验单主记录抽样数:优先使用模板抽样方案,取第一个可命中的抽样数; + * 若未命中则回退物料属性的默认抽样数/默认抽样比例。 + */ + private BigDecimal resolveSamplingQty(BigDecimal rollQty, + PartAttrDTO partAttr, + List templates) { + if (templates != null && !templates.isEmpty()) { + for (TemplateDTO template : templates) { + BigDecimal samplingQty = resolveSamplingQty(rollQty, partAttr, template); + if (samplingQty != null) { + return samplingQty; + } + } + } + return resolveSamplingQty(rollQty, partAttr, (TemplateDTO) null); + } + + /** + * 去重模板(按 templateId),避免重复模板导致重复插入明细。 + */ + private List deduplicateTemplates(List templates) { + if (templates == null || templates.isEmpty()) { + return templates; + } + Map uniqueMap = new LinkedHashMap<>(); + for (TemplateDTO template : templates) { + if (template == null || StringUtils.isBlank(template.getTemplateId())) { + continue; + } + uniqueMap.putIfAbsent(template.getTemplateId(), template); + } + return new ArrayList<>(uniqueMap.values()); + } + + /** + * 去重模板明细(按 itemNo),避免同一模板重复项目导致主键冲突。 + */ + private List deduplicateTemplateItems(List items) { + if (items == null || items.isEmpty()) { + return items; + } + Map uniqueMap = new LinkedHashMap<>(); + for (TemplateDetailDTO item : items) { + if (item == null || StringUtils.isBlank(item.getItemNo())) { + continue; + } + uniqueMap.putIfAbsent(item.getItemNo(), item); + } + return new ArrayList<>(uniqueMap.values()); + } + + /** + * 计算单个模板的抽样数:抽样方案矩阵 > 默认抽样数 > 默认抽样比例 + */ + private BigDecimal resolveSamplingQty(BigDecimal rollQty, + PartAttrDTO partAttr, + TemplateDTO template) { + BigDecimal samplingQty = null; + + if (rollQty != null + && template != null + && StringUtils.isNotBlank(template.getSamplingProgrammeNo()) + && StringUtils.isNotBlank(template.getSamplingLevelNo()) + && StringUtils.isNotBlank(partAttr.getSite()) + && StringUtils.isNotBlank(partAttr.getBuNo())) { + QcSamplingInspectionProgrammeData searchCriteria = new QcSamplingInspectionProgrammeData(); + searchCriteria.setSite(partAttr.getSite()); + searchCriteria.setBuNo(partAttr.getBuNo()); + searchCriteria.setSamplingProgrammeNo(template.getSamplingProgrammeNo()); + List programmeDataList = qcMapper.searchSamplingProgrammeDetails(searchCriteria); + for (QcSamplingInspectionProgrammeData programmeData : programmeDataList) { + if (template.getSamplingLevelNo().equals(programmeData.getSamplingLevelNo()) + && programmeData.getMinQty() != null + && programmeData.getMaxQty() != null + && rollQty.compareTo(programmeData.getMinQty()) >= 0 + && rollQty.compareTo(programmeData.getMaxQty()) <= 0) { + samplingQty = programmeData.getSamplingQty(); + break; + } + } + } + + if (samplingQty == null + && template != null + && template.getDefaultSamplingQuantity() != null) { + samplingQty = template.getDefaultSamplingQuantity(); + } + + if (samplingQty == null + && template != null + && template.getDefaultSamplingProportion() != null + && rollQty != null) { + samplingQty = template.getDefaultSamplingProportion() + .multiply(rollQty) + .divide(new BigDecimal(100), 3, BigDecimal.ROUND_HALF_UP); + } + + if (samplingQty == null && partAttr.getDefaultSamplingQuantity() != null) { + samplingQty = partAttr.getDefaultSamplingQuantity(); + } + + return samplingQty; + } + private void insertMain(MyInspectionListVO detail, PartAttrDTO partAttr, - String inspectionNo) { + String inspectionNo, + BigDecimal samplingQty) { Map map = new HashMap<>(); @@ -5551,7 +5661,7 @@ public class QcServiceImpl implements QcService { map.put("rollQty", detail.getQty()); - map.put("samplingQty", partAttr.getDefaultSamplingQuantity()); + map.put("samplingQty", samplingQty); map.put("buNo", partAttr.getBuNo()); @@ -5569,9 +5679,19 @@ public class QcServiceImpl implements QcService { PartAttrDTO partAttr, TemplateDTO template, List items, - String inspectionNo) { + String inspectionNo, + BigDecimal samplingQty, + Set insertedItemNoSet) { for (TemplateDetailDTO i : items) { + if (StringUtils.isBlank(i.getItemNo())) { + continue; + } + if (insertedItemNoSet.contains(i.getItemNo())) { + log.warn("createIqc 跳过重复项目: inspectionNo={}, templateId={}, itemNo={}", + inspectionNo, template.getTemplateId(), i.getItemNo()); + continue; + } Map map = new HashMap<>(); @@ -5594,9 +5714,10 @@ public class QcServiceImpl implements QcService { map.put("site", detail.getSite()); map.put("buNo", partAttr.getBuNo()); - map.put("samplingQty", partAttr.getDefaultSamplingQuantity()); + map.put("samplingQty", samplingQty); qcMapper.insertDetail(map); + insertedItemNoSet.add(i.getItemNo()); } } diff --git a/src/main/resources/mapper/inspection/InspectionRequestHeaderMapper.xml b/src/main/resources/mapper/inspection/InspectionRequestHeaderMapper.xml index 5764d1c..ec40e48 100644 --- a/src/main/resources/mapper/inspection/InspectionRequestHeaderMapper.xml +++ b/src/main/resources/mapper/inspection/InspectionRequestHeaderMapper.xml @@ -41,7 +41,8 @@ and h.request_no like '%${query.requestNo}%' and h.supplier_no like '%${query.supplierNo}%' and s.supplier_name like '%${query.supplierName}%' - and h.status_db = #{query.status} + and h.status_db != 'Draft' + and h.status_db = #{query.status} and h.qc_operator like '%${query.qcOperator}%' and h.create_by like '%${query.createBy}%' and h.request_date >= #{query.requestDateStart} diff --git a/src/main/resources/mapper/qms/QcMapper.xml b/src/main/resources/mapper/qms/QcMapper.xml index 7de2230..1188a7a 100644 --- a/src/main/resources/mapper/qms/QcMapper.xml +++ b/src/main/resources/mapper/qms/QcMapper.xml @@ -1986,8 +1986,8 @@ a.default_value, a.min_value, a.max_value, - a.text_value, - a.number_value, + ISNULL(a.text_value, a.default_value) as text_value, + ISNULL(a.number_value, TRY_CONVERT(decimal(18,6), a.default_value)) as number_value, a.value_type_db, a.value_type, case when a.item_result = '' or a.item_result is null then 'Y' else a.item_result end as itemResult, @@ -2597,8 +2597,8 @@ - INSERT INTO qc_iqc_detailed_record (inspection_no, template_id, sampling_level_no, sampling_level_desc, sampling_programme_no, sampling_programme_desc, AQL, AC, RE, item_no, item_desc, object_id, object_desc, default_value, min_value, max_value, value_type_db, value_type, site, sampling_qty, bu_no,order_id) - VALUES(#{inspectionNo}, #{templateId}, #{samplingLevelNo}, #{samplingLevelDesc}, #{samplingProgrammeNo}, #{samplingProgrammeDesc}, #{aql,jdbcType=DECIMAL}, #{ac,jdbcType=DECIMAL}, #{re,jdbcType=DECIMAL}, #{itemNo}, #{itemDesc}, #{objectId}, #{objectDesc}, #{defaultValue}, #{minValue,jdbcType=DECIMAL}, #{maxValue,jdbcType=DECIMAL}, #{valueTypeDb}, #{valueType}, #{site}, #{samplingQty}, #{buNo},#{orderId,jdbcType=INTEGER}) + INSERT INTO qc_iqc_detailed_record (inspection_no, template_id, sampling_level_no, sampling_level_desc, sampling_programme_no, sampling_programme_desc, AQL, AC, RE, item_no, item_desc, object_id, object_desc, default_value, min_value, max_value, value_type_db, value_type, text_value, number_value, site, sampling_qty, bu_no,order_id) + VALUES(#{inspectionNo}, #{templateId}, #{samplingLevelNo}, #{samplingLevelDesc}, #{samplingProgrammeNo}, #{samplingProgrammeDesc}, #{aql,jdbcType=DECIMAL}, #{ac,jdbcType=DECIMAL}, #{re,jdbcType=DECIMAL}, #{itemNo}, #{itemDesc}, #{objectId}, #{objectDesc}, #{defaultValue}, #{minValue,jdbcType=DECIMAL}, #{maxValue,jdbcType=DECIMAL}, #{valueTypeDb}, #{valueType}, #{defaultValue}, TRY_CONVERT(decimal(18,6), #{defaultValue}), #{site}, #{samplingQty}, #{buNo},#{orderId,jdbcType=INTEGER}) @@ -5041,31 +5041,34 @@