From fbd4ecb70baf2e671876ca809a81f6e6fe7342ee Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期日, 20 九月 2026 19:52:50 +0800
Subject: [PATCH] feat(inspect): 新增检测标准方法报告文本功能并优化报告生成 - 委托编号生成逻辑调整为下单时生成并校验唯一性,避免审核时重复 - 新增标准模板价格字段及对应的数据模型和数据库映射 - 订单费用详情查询逻辑重构为基于模板价格计算方式 - 新增标准模板与设备绑定关系的数据结构和管理功能 - 委托编号唯一性校验逻辑增强

---
 inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderServiceImpl.java |  154 +++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 124 insertions(+), 30 deletions(-)

diff --git a/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderServiceImpl.java b/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderServiceImpl.java
index c62c2ce..5be630d 100644
--- a/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderServiceImpl.java
+++ b/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderServiceImpl.java
@@ -84,6 +84,8 @@
 public class InsOrderServiceImpl extends ServiceImpl<InsOrderMapper, InsOrder>
         implements InsOrderService {
 
+    private static final String DIRECT_TEMPLATE_LABORATORY = "鏂拌仛";
+
     private InsOrderMapper insOrderMapper;
     private InsSampleService insSampleService;
     private InsSampleMapper insSampleMapper;
@@ -137,36 +139,52 @@
         insOrderMapper.updateById(insOrder);
         List<InsSample> insSamples = insSampleMapper.selectList(Wrappers.<InsSample>lambdaQuery().eq(InsSample::getInsOrderId, orderId));
         List<Integer> ids = insSamples.stream().map(InsSample::getId).collect(Collectors.toList());
-        List<InsProduct> insProducts = insProductMapper.selectList(Wrappers.<InsProduct>lambdaQuery()
-                .in(InsProduct::getInsSampleId, ids)
-                .eq(InsProduct::getState, 1)
-                .select(InsProduct::getSonLaboratory).groupBy(InsProduct::getSonLaboratory));
+        List<InsProduct> insProducts = ids.isEmpty()
+                ? Collections.emptyList()
+                : insProductMapper.selectList(Wrappers.<InsProduct>lambdaQuery()
+                        .in(InsProduct::getInsSampleId, ids)
+                        .eq(InsProduct::getState, 1)
+                        .select(InsProduct::getSonLaboratory).groupBy(InsProduct::getSonLaboratory));
+
+        InsOrder order = insOrderMapper.selectById(orderId);
+        boolean directTemplateOrder = isDirectTemplateOrder(order, insSamples);
+        Set<String> taskLaboratories = directTemplateOrder
+                ? Collections.singleton(DIRECT_TEMPLATE_LABORATORY)
+                : insProducts.stream()
+                        .map(InsProduct::getSonLaboratory)
+                        .filter(StringUtils::isNotBlank)
+                        .collect(Collectors.toCollection(LinkedHashSet::new));
+        if (!directTemplateOrder && taskLaboratories.size() != insProducts.size()) {
+            throw new ErrorException("璇ユ楠屽崟鏈夋湭缁存姢瀹為獙瀹ょ殑妫�楠岄」鐩�");
+        }
 
         // 鎵归噺娣诲姞妫�楠屼换鍔$姸鎬佽〃
-        List<InsOrderState> insOrderStateList = insProducts.stream().map(insProduct -> {
+        List<InsOrderState> insOrderStateList = taskLaboratories.stream()
+                .filter(laboratory -> insOrderStateService.count(Wrappers.<InsOrderState>lambdaQuery()
+                        .eq(InsOrderState::getInsOrderId, orderId)
+                        .eq(InsOrderState::getLaboratory, laboratory)) == 0)
+                .map(laboratory -> {
             InsOrderState insOrderState = new InsOrderState();
             insOrderState.setInsOrderId(orderId);
-            try {
-                insOrderState.setLaboratory(insProduct.getSonLaboratory());
-            } catch (NullPointerException e) {
-                throw new ErrorException("璇ユ楠屽崟鏈夋湭缁存姢瀹為獙瀹ょ殑妫�楠岄」鐩�");
-            }
+            insOrderState.setLaboratory(laboratory);
             insOrderState.setInsState(0);
             return insOrderState;
         }).collect(Collectors.toList());
-        insOrderStateService.saveBatch(insOrderStateList);
+        if (!insOrderStateList.isEmpty()) {
+            insOrderStateService.saveBatch(insOrderStateList);
+        }
 
         if (userId != null) {
             InsSampleUser insSampleUser = new InsSampleUser();
             insSampleUser.setState(0);
             insSampleUser.setUserId(userId);
             insSampleUser.setInsSampleId(orderId);
-            insSampleUser.setSonLaboratory(sonLaboratory);
+            insSampleUser.setSonLaboratory(directTemplateOrder
+                    ? DIRECT_TEMPLATE_LABORATORY : sonLaboratory);
             insSampleUserMapper.insert(insSampleUser);
         }
 
         // 鍒ゆ柇璁㈠崟鏈夋病鏈夌粦瀹氭娊鏍疯鍒�
-        InsOrder order = insOrderMapper.selectById(orderId);
         if (order.getQuarterItemId() != null) {
            // 闇�瑕佹坊鍔犱笅鍙戞椂闂村埌鎶芥牱鏃堕棿, 鍙栨牱浜哄憳灏辨槸妫�娴嬩汉
             SpotCheckQuarterItem spotCheckQuarterItem = spotCheckQuarterItemMapper.selectById(order.getQuarterItemId());
@@ -177,6 +195,22 @@
         }
 
         return 1;
+    }
+
+    private boolean isDirectTemplateOrder(InsOrder order, List<InsSample> samples) {
+        if (order == null || CollectionUtils.isEmpty(samples)) {
+            return false;
+        }
+        Long snapshotCount = insOrderStandardTemplateMapper.selectCount(
+                Wrappers.<InsOrderStandardTemplate>lambdaQuery()
+                        .eq(InsOrderStandardTemplate::getInsOrderId, order.getId()));
+        return snapshotCount > 0 && samples.stream().anyMatch(sample ->
+                sample.getStandardMethodListId() == null
+                        && StringUtils.isBlank(sample.getFactory())
+                        && StringUtils.isBlank(sample.getSampleType())
+                        && StringUtils.isBlank(sample.getModel())
+                        && StringUtils.isBlank(order.getFactory())
+                        && StringUtils.isBlank(order.getSampleType()));
     }
 
 
@@ -330,6 +364,15 @@
                 }
             }
         });
+        // 涓嬪崟鏃剁敓鎴愬鎵樼紪鍙峰苟鏍¢獙鍞竴鎬э紱瀛e害妫�楠屽鐢ㄨ繘鍘傛楠岀紪鍙凤紝鐣欏緟瀹℃牳澶勭悊銆�
+        if (!InsOrderTypeConstants.QUARTERLY_TEST.equals(insOrder.getOrderType())) {
+            String entrustCode = buildEntrustCode(insOrder, Collections.emptyList());
+            assertEntrustCodeUnique(entrustCode, insOrder.getId());
+            insOrder.setEntrustCode(entrustCode);
+            insOrderMapper.update(null, Wrappers.<InsOrder>lambdaUpdate()
+                    .eq(InsOrder::getId, insOrder.getId())
+                    .set(InsOrder::getEntrustCode, entrustCode));
+        }
         //鍘熸潗鏂欎笅鍗曟垨澶栬喘鎴愬搧涓嬪崟
         if (Objects.nonNull(insOrder.getTypeSource())&&Objects.nonNull(insOrder.getIfsInventoryId())) {
             // 濮旀墭浜哄氨鏄姤妫�浜�, 鐢熶骇鍗曚綅灏辨槸渚涘簲鍟嗗崟浣�
@@ -430,6 +473,10 @@
         if (dto == null || dto.getInsOrder() == null || dto.getStandardTreeId() == null) {
             throw new ErrorException("涓嬪崟淇℃伅鎴栨爣鍑嗕笉鑳戒负绌�");
         }
+        String sampleCode = StringUtils.trim(dto.getSampleCode());
+        if (StringUtils.isBlank(sampleCode) || sampleCode.length() < 2) {
+            throw new ErrorException("鏍峰搧缂栧彿涓嶈兘涓虹┖涓斾笉鑳藉皯浜�2浣�");
+        }
         StandardTree standard = standardTreeService.getById(dto.getStandardTreeId());
         if (standard == null || StringUtils.isBlank(standard.getSample())
                 || standard.getSampleType() != null || standard.getModel() != null) {
@@ -506,7 +553,7 @@
 
         InsSample sample = new InsSample();
         sample.setInsOrderId(order.getId());
-        sample.setSampleCode(dto.getSampleCode());
+        sample.setSampleCode(sampleCode);
         sample.setFactory(null);
         sample.setLaboratory(standard.getLaboratory());
         sample.setSampleType(null);
@@ -530,16 +577,24 @@
             product.setModel(null);
             product.setTemplateId(item.getTemplateId());
             product.setTemplateRowIndex(item.getTemplateRowIndex());
-            product.setSonLaboratory("鏂拌仛");
+            product.setSonLaboratory(DIRECT_TEMPLATE_LABORATORY);
             product.setState(1);
             product.setSort(productSort++);
             insProductMapper.insert(product);
         }
-        saveTemplateSnapshots(order.getId(), selections);
+        saveTemplateSnapshots(order.getId(), selections, bindingMap);
+
+        // 涓嬪崟鏃剁敓鎴愬鎵樼紪鍙峰苟鏍¢獙鍞竴鎬э紝閲嶅鍒欐彁绀猴紝閬垮厤鐣欏埌瀹℃牳鎵嶆姤閿欍��
+        String entrustCode = buildEntrustCode(order, Collections.singletonList(sample));
+        assertEntrustCodeUnique(entrustCode, order.getId());
+        insOrderMapper.update(null, Wrappers.<InsOrder>lambdaUpdate()
+                .eq(InsOrder::getId, order.getId())
+                .set(InsOrder::getEntrustCode, entrustCode));
         return order.getId();
     }
 
-    private void saveTemplateSnapshots(Integer orderId, List<OrderTemplateSelectionDto> selections) {
+    private void saveTemplateSnapshots(Integer orderId, List<OrderTemplateSelectionDto> selections,
+                                       Map<Integer, StandardTreeTemplateBindingVo> bindingMap) {
         for (OrderTemplateSelectionDto selection : selections) {
             StandardTemplate template = standardTemplateService.getById(selection.getTemplateId());
             if (template == null) {
@@ -554,6 +609,18 @@
             snapshot.setThing(template.getThing());
             snapshot.setSort(selection.getSort());
             insOrderStandardTemplateMapper.insert(snapshot);
+
+            StandardTreeTemplateBindingVo binding = bindingMap.get(selection.getTemplateId());
+            List<Integer> deviceIds = binding == null || binding.getDeviceIds() == null
+                    ? Collections.emptyList() : binding.getDeviceIds();
+            for (int index = 0; index < deviceIds.size(); index++) {
+                InsOrderTemplateDevice relation = new InsOrderTemplateDevice();
+                relation.setInsOrderId(orderId);
+                relation.setTemplateId(selection.getTemplateId());
+                relation.setDeviceId(deviceIds.get(index));
+                relation.setSort(index);
+                insOrderTemplateDeviceMapper.insert(relation);
+            }
         }
     }
 
@@ -637,17 +704,12 @@
     public int upInsOrderOfState(InsOrder insOrder) {
         insOrder.setExamineTime(LocalDateTime.now());
         if (insOrder.getState() == 1) {
-            //瀹℃牳閫氳繃鎵嶄細鐢熸垚濮旀墭缂栧彿
+            //濮旀墭缂栧彿宸插湪涓嬪崟鏃剁敓鎴愬苟鏍¢獙鍞竴鎬э紝瀹℃牳鏃跺鐢紱鍘嗗彶/瀛e害妫�楠岃鍗曞厹搴曠敓鎴愩��
             InsOrder order = this.getById(insOrder.getId());
-            // 濮旀墭缂栧彿鎸夐�佹牱鏃ユ湡鐙珛娴佹按锛屼緥濡傦細LMSY-20260909-01銆�
-            // 鍘嗗彶/澶栭儴璁㈠崟鏈~鍐欓�佹牱鏃ユ湡鏃跺洖閫�鍒板綋澶╋紝閬垮厤褰卞搷鍘熸湁娴佺▼銆�
-            LocalDate entrustDate = order.getSampleDate() == null ? LocalDate.now() : order.getSampleDate();
-            String entrustCodePrefix = "LMSY-"
-                    + entrustDate.format(DateTimeFormatter.BASIC_ISO_DATE)
-                    + "-";
-            String no = numberGenerator.generateNumberWithPrefix(2,
-                    entrustCodePrefix,
-                    InsOrder::getEntrustCode);
+            List<InsSample> insSamples = insSampleMapper.selectList(Wrappers.<InsSample>lambdaQuery()
+                    .eq(InsSample::getInsOrderId, insOrder.getId())
+                    .orderByAsc(InsSample::getId));
+            String no = order.getEntrustCode();
             // 鍒ゆ柇鏄惁鏄搴︽楠�, 鏄搴︽楠屽彇娑堝師鏉愭枡瀛e害妫�楠屼笅鍗�
             if (InsOrderTypeConstants.QUARTERLY_TEST.equals(order.getOrderType())) {
                 ifsInventoryQuantityMapper.update(null,  Wrappers.<IfsInventoryQuantity>lambdaUpdate()
@@ -663,11 +725,12 @@
                   no = order1.getEntrustCode();
                 }
             }
+            if (StringUtils.isBlank(no)) {
+                no = buildEntrustCode(order, insSamples);
+            }
+            assertEntrustCodeUnique(no, order.getId());
 
             int count = 1;
-            // 鏌ヨ鏍峰搧琛�
-            List<InsSample> insSamples = insSampleMapper.selectList(Wrappers.<InsSample>lambdaQuery()
-                    .eq(InsSample::getInsOrderId, insOrder.getId()));
             for (InsSample insSample : insSamples) {
                 if (StringUtils.isBlank(insSample.getSampleCode())) {
                     // 濡傛灉鍙湁涓�涓牱鍝佸氨涓嶉渶瑕佹嫾鎺ユ暟瀛�
@@ -686,6 +749,37 @@
         return insOrderMapper.updateById(insOrder);
     }
 
+    /**
+     * 濮旀墭缂栧彿鍏ㄥ眬鍞竴锛岀敓鎴愮紪鍙峰拰鍚庣画鎻愪氦鍓嶅潎闇�鎺掗櫎褰撳墠璁㈠崟鍚庢牎楠屻��
+     */
+    private void assertEntrustCodeUnique(String entrustCode, Integer currentOrderId) {
+        Long count = insOrderMapper.selectCount(Wrappers.<InsOrder>lambdaQuery()
+                .eq(InsOrder::getEntrustCode, entrustCode)
+                .ne(currentOrderId != null, InsOrder::getId, currentOrderId));
+        if (count > 0) {
+            throw new ErrorException("鏍峰搧/濮旀墭鍗曞凡瀛樺湪锛岃纭鏍峰搧缂栧彿");
+        }
+    }
+
+    /**
+     * 鐢熸垚濮旀墭缂栧彿锛氭柊鑱氱洿缁戞ā鏉胯鍗曟湯涓や綅鍙栨牱鍝佺紪鍙锋湯涓や綅锛屽叾浣欐寜閫佹牱鏃ユ湡鐢熸垚搴忓彿銆�
+     */
+    private String buildEntrustCode(InsOrder order, List<InsSample> insSamples) {
+        LocalDate entrustDate = order.getSampleDate() == null ? LocalDate.now() : order.getSampleDate();
+        String entrustCodePrefix = "LMSY-"
+                + entrustDate.format(DateTimeFormatter.BASIC_ISO_DATE)
+                + "-";
+        if (isDirectTemplateOrder(order, insSamples)) {
+            String sampleCode = insSamples.get(0).getSampleCode();
+            if (StringUtils.isBlank(sampleCode) || sampleCode.trim().length() < 2) {
+                throw new ErrorException("鏍峰搧缂栧彿涓嶈兘涓虹┖涓斾笉鑳藉皯浜�2浣�");
+            }
+            sampleCode = sampleCode.trim();
+            return entrustCodePrefix + sampleCode.substring(sampleCode.length() - 2);
+        }
+        return numberGenerator.generateNumberWithPrefix(2, entrustCodePrefix, InsOrder::getEntrustCode);
+    }
+
     @Override
     public Map<String, Object> getInsOrderAndSample(Integer id, String laboratory) {
         Map<String, Object> map = new HashMap<>();

--
Gitblit v1.9.3