liding
11 小时以前 51786b723d0a91d11476776d9ce50af7994dc4bd
inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderServiceImpl.java
@@ -57,6 +57,7 @@
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
@@ -107,6 +108,8 @@
    private StandardTemplateService standardTemplateService;
    private InsOrderStandardTemplateMapper insOrderStandardTemplateMapper;
    private InsOrderTemplateDeviceMapper insOrderTemplateDeviceMapper;
    private InsSampleReceiptMapper insSampleReceiptMapper;
    private ApplicationEventPublisher applicationEventPublisher;
@@ -120,7 +123,10 @@
            isOrderAll = "1";
            sampleOrderDto.setState(null);
        }
        return insOrderMapper.selectInsOrderPage(page, QueryWrappers.queryWrappers(sampleOrderDto), laboratory, isOrderAll);
        // 检验中:新聚下单免审核即受理,需样品接收提交后(ins_sample_receipt.status=1)才展示
        String receiptSubmitted = sampleOrderDto.getState() != null && sampleOrderDto.getState() == 1 ? "1" : null;
        return insOrderMapper.selectInsOrderPage(page, QueryWrappers.queryWrappers(sampleOrderDto), laboratory,
                isOrderAll, receiptSubmitted);
    }
@@ -175,13 +181,17 @@
        }
        if (userId != null) {
            InsSampleUser insSampleUser = new InsSampleUser();
            insSampleUser.setState(0);
            insSampleUser.setUserId(userId);
            insSampleUser.setInsSampleId(orderId);
            insSampleUser.setSonLaboratory(directTemplateOrder
                    ? DIRECT_TEMPLATE_LABORATORY : sonLaboratory);
            insSampleUserMapper.insert(insSampleUser);
            Set<String> assignedLaboratories = StringUtils.isBlank(sonLaboratory)
                    ? taskLaboratories
                    : Collections.singleton(sonLaboratory);
            for (String laboratory : assignedLaboratories) {
                InsSampleUser insSampleUser = new InsSampleUser();
                insSampleUser.setState(0);
                insSampleUser.setUserId(userId);
                insSampleUser.setInsSampleId(orderId);
                insSampleUser.setSonLaboratory(laboratory);
                insSampleUserMapper.insert(insSampleUser);
            }
        }
        // 判断订单有没有绑定抽样计划
@@ -364,6 +374,15 @@
                }
            }
        });
        // 下单时生成委托编号并校验唯一性;季度检验复用进厂检验编号,留待审核处理。
        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())) {
            // 委托人就是报检人, 生产单位就是供应商单位
@@ -403,9 +422,7 @@
            // 审核检验单
            upInsOrderOfState(insOrder);
            // 分配检验人
            String sonLaboratory = insOrder.getTypeSource().equals(1)?"原材料":"成品实验室";
            upInsOrder(insOrder.getId(), null, appointed != null ? appointed.toString() : null, SecurityUtils.getUserId().intValue(), sonLaboratory);
            // 审核通过后仅进入样品接收;由样品接收页面选择主检验人后再创建检验任务。
            //是否为原材料下单
            if(insOrder.getTypeSource().equals(1)){
@@ -468,6 +485,24 @@
        if (StringUtils.isBlank(sampleCode) || sampleCode.length() < 2) {
            throw new ErrorException("样品编号不能为空且不能少于2位");
        }
        // 委托要求字段校验:四组单选必选,分包/快递联动必填
        InsOrder reqOrder = dto.getInsOrder();
        if (reqOrder.getSubcontractType() == null || reqOrder.getSampleDisposal() == null
                || reqOrder.getResultEvaluation() == null || reqOrder.getReportDelivery() == null) {
            throw new ErrorException("请选择分包内容、样品处置、对结果评价和报告交付方式");
        }
        if (Integer.valueOf(1).equals(reqOrder.getSubcontractType())
                && StringUtils.isBlank(reqOrder.getSubcontractCompany())) {
            throw new ErrorException("分包内容为有时,分包单位信息不能为空");
        }
        if (Integer.valueOf(2).equals(reqOrder.getReportDelivery())) {
            if (StringUtils.isBlank(reqOrder.getReportAddress())) {
                throw new ErrorException("报告交付方式为快递时,报告寄送地址不能为空");
            }
            if (StringUtils.isBlank(reqOrder.getReportReceiver())) {
                throw new ErrorException("报告交付方式为快递时,收件人及电话不能为空");
            }
        }
        StandardTree standard = standardTreeService.getById(dto.getStandardTreeId());
        if (standard == null || StringUtils.isBlank(standard.getSample())
                || standard.getSampleType() != null || standard.getModel() != null) {
@@ -528,7 +563,9 @@
        InsOrder order = dto.getInsOrder();
        order.setId(null);
        order.setState(0);
        // 新聚下单免审核:直接受理,下单即流转到样品接收
        order.setState(1);
        order.setExamineTime(LocalDateTime.now());
        order.setIsExemption(0);
        order.setFactory(null);
        order.setLaboratory(standard.getLaboratory());
@@ -540,6 +577,14 @@
        // 新聚订单的环境条件由检验任务填写,避免下单模板或浏览器缓存带入旧值。
        order.setTemperature(null);
        order.setHumidity(null);
        // 未命中联动条件时清空对应文本字段,避免模板快照或浏览器缓存带入旧值。
        if (!Integer.valueOf(1).equals(order.getSubcontractType())) {
            order.setSubcontractCompany(null);
        }
        if (!Integer.valueOf(2).equals(order.getReportDelivery())) {
            order.setReportAddress(null);
            order.setReportReceiver(null);
        }
        insOrderMapper.insert(order);
        InsSample sample = new InsSample();
@@ -573,11 +618,23 @@
            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));
        // 免审核后由下单生成待接收的样品接收记录,主检验人仍在样品接收页面选择后才创建检验任务
        insSampleReceiptMapper.insertIgnore(order.getId(), sample.getId());
        // 同事务内发布下单事件,由 cnas-process 自动生成检验委托单;监听器异常会连带下单回滚
        applicationEventPublisher.publishEvent(new com.ruoyi.inspect.event.NewJuOrderPlacedEvent(order.getId()));
        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) {
@@ -592,6 +649,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);
            }
        }
    }
@@ -672,33 +741,16 @@
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int upInsOrderOfState(InsOrder insOrder) {
        insOrder.setExamineTime(LocalDateTime.now());
        if (insOrder.getState() == 1) {
            //审核通过才会生成委托编号
            //委托编号已在下单时生成并校验唯一性,审核时复用;历史/季度检验订单兜底生成。
            InsOrder order = this.getById(insOrder.getId());
            List<InsSample> insSamples = insSampleMapper.selectList(Wrappers.<InsSample>lambdaQuery()
                    .eq(InsSample::getInsOrderId, insOrder.getId())
                    .orderByAsc(InsSample::getId));
            // 委托编号按送样日期生成;新聚单样品订单的末两位取样品编号末两位。
            // 历史/外部订单未填写送样日期时回退到当天,避免影响原有流程。
            LocalDate entrustDate = order.getSampleDate() == null ? LocalDate.now() : order.getSampleDate();
            String entrustCodePrefix = "LMSY-"
                    + entrustDate.format(DateTimeFormatter.BASIC_ISO_DATE)
                    + "-";
            String no;
            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();
                no = entrustCodePrefix + sampleCode.substring(sampleCode.length() - 2);
            } else {
                no = numberGenerator.generateNumberWithPrefix(2,
                        entrustCodePrefix,
                        InsOrder::getEntrustCode);
            }
            String no = order.getEntrustCode();
            // 判断是否是季度检验, 是季度检验取消原材料季度检验下单
            if (InsOrderTypeConstants.QUARTERLY_TEST.equals(order.getOrderType())) {
                ifsInventoryQuantityMapper.update(null,  Wrappers.<IfsInventoryQuantity>lambdaUpdate()
@@ -714,6 +766,10 @@
                  no = order1.getEntrustCode();
                }
            }
            if (StringUtils.isBlank(no)) {
                no = buildEntrustCode(order, insSamples);
            }
            assertEntrustCodeUnique(no, order.getId());
            int count = 1;
            for (InsSample insSample : insSamples) {
@@ -731,7 +787,48 @@
            insOrder.setEntrustCode(no);
        }
        return insOrderMapper.updateById(insOrder);
        int updated = insOrderMapper.updateById(insOrder);
        if (updated > 0 && Integer.valueOf(1).equals(insOrder.getState())) {
            List<InsSample> samples = insSampleMapper.selectList(Wrappers.<InsSample>lambdaQuery()
                    .eq(InsSample::getInsOrderId, insOrder.getId())
                    .orderByAsc(InsSample::getId));
            if (samples.size() != 1) {
                throw new ErrorException("委托单必须且只能包含一个样品,不能进入样品接收流程");
            }
            insSampleReceiptMapper.insertIgnore(insOrder.getId(), samples.get(0).getId());
        }
        return updated;
    }
    /**
     * 委托编号全局唯一,生成编号和后续提交前均需排除当前订单后校验。
     */
    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
@@ -1058,7 +1155,7 @@
        insOrder.setState(1);
        upInsOrderOfState(insOrder);
        upInsOrder(insOrder.getId(), null, appointed != null ? appointed.toString() : null, SecurityUtils.getUserId().intValue(), "原材料");
        // 审核通过后仅进入样品接收;由样品接收页面选择主检验人后再创建检验任务。
        return insOrder.getId();
    }