liding
2026-10-24 f8c024b1c1de318a4de485e048d1044cd6dcaa53
inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderServiceImpl.java
@@ -55,6 +55,7 @@
import com.ruoyi.inspect.vo.TemplateConditionVo;
import com.ruoyi.system.mapper.UserMapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationEventPublisher;
@@ -80,6 +81,7 @@
 * @description 针对表【ins_order(检验下单)】的数据库操作Service实现
 * @createDate 2024-03-12 16:17:55
 */
@Slf4j
@Service
@AllArgsConstructor
public class InsOrderServiceImpl extends ServiceImpl<InsOrderMapper, InsOrder>
@@ -844,6 +846,7 @@
            snapshot.setTemplateId(template.getId());
            snapshot.setName(template.getName());
            snapshot.setNumber(template.getNumber());
            snapshot.setStandardRequirement(template.getStandardRequirement());
            snapshot.setRemark(template.getRemark());
            snapshot.setThing(template.getThing());
            snapshot.setSort(selection.getSort());
@@ -1067,7 +1070,11 @@
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> getInsOrderAndSample(Integer id, String laboratory) {
        Map<String, Object> map = new HashMap<>();
        initializeTemplateDevicesOnFirstOpen(id);
        try {
            initializeTemplateDevicesOnFirstOpen(id, laboratory);
        } catch (RuntimeException e) {
            log.warn("检验任务默认设备同步失败,orderId={}", id, e);
        }
//        InsOrder insOrder = insOrderMapper.selectById(id);
        IfsOrderVO ifsOrderVO = insOrderMapper.selectOrderInfoById(id);
        Map<Integer, List<Integer>> templateDeviceIds = insOrderTemplateDeviceMapper.selectList(
@@ -1085,6 +1092,7 @@
                                .select(InsOrderStandardTemplate::getTemplateId,
                                        InsOrderStandardTemplate::getTemperature,
                                        InsOrderStandardTemplate::getDetectionTime,
                                        InsOrderStandardTemplate::getDetectionEndTime,
                                        InsOrderStandardTemplate::getDetectionPlace,
                                        InsOrderStandardTemplate::getInsResult)
                                .orderByAsc(InsOrderStandardTemplate::getSort,
@@ -1094,6 +1102,8 @@
                    condition.setTemplateId(snapshot.getTemplateId());
                    condition.setTemperature(snapshot.getTemperature());
                    condition.setDetectionTime(snapshot.getDetectionTime());
                    condition.setDetectionEndTime(snapshot.getDetectionEndTime() == null
                            ? snapshot.getDetectionTime() : snapshot.getDetectionEndTime());
                    condition.setDetectionPlace(snapshot.getDetectionPlace());
                    condition.setInsResult(snapshot.getInsResult());
                    condition.setDeviceIds(templateDeviceIds.getOrDefault(
@@ -1110,18 +1120,34 @@
        return map;
    }
    /** 首次打开检验任务时,将仍为空的模板设备从对应标准补入订单。 */
    private void initializeTemplateDevicesOnFirstOpen(Integer orderId) {
    /**
     * 打开检验任务时,把尚未被人工改动过的模板设备同步为标准库当前绑定的设备;
     * 检验员手动增删过的模板以人工为准,不再自动填充。
     */
    private void initializeTemplateDevicesOnFirstOpen(Integer orderId, String laboratory) {
        InsOrder order = insOrderMapper.selectById(orderId);
        if (order == null || !DIRECT_TEMPLATE_LABORATORY.equals(order.getLaboratory())
                || !Objects.equals(order.getTypeSource(), -1)
        if (order == null || !Objects.equals(order.getTypeSource(), -1)
                || !Objects.equals(order.getState(), 1)
                || "QUALITY_MONITOR".equals(order.getTaskSource())) {
            return;
        }
        if (StringUtils.isNotBlank(laboratory)) {
            InsOrderState orderState = insOrderStateService.getOne(Wrappers.<InsOrderState>lambdaQuery()
                    .eq(InsOrderState::getInsOrderId, orderId)
                    .eq(InsOrderState::getLaboratory, laboratory)
                    .last("limit 1"));
            // 仅待检、在检阶段同步;进入复核等后续状态后以保存下来的设备为准。
            if (orderState != null && orderState.getInsState() != null
                    && orderState.getInsState() != 0 && orderState.getInsState() != 1) {
                return;
            }
        }
        List<InsOrderStandardTemplate> snapshots = insOrderStandardTemplateMapper.selectList(
                Wrappers.<InsOrderStandardTemplate>lambdaQuery()
                        .eq(InsOrderStandardTemplate::getInsOrderId, orderId)
                        .select(InsOrderStandardTemplate::getId,
                                InsOrderStandardTemplate::getTemplateId,
                                InsOrderStandardTemplate::getDeviceDefaultsInitialized)
                        .orderByAsc(InsOrderStandardTemplate::getSort, InsOrderStandardTemplate::getId)
                        .last("FOR UPDATE"));
        if (snapshots.isEmpty() || snapshots.stream().allMatch(
@@ -1129,41 +1155,57 @@
            return;
        }
        Set<Integer> existingTemplateIds = insOrderTemplateDeviceMapper.selectList(
                Wrappers.<InsOrderTemplateDevice>lambdaQuery()
                        .eq(InsOrderTemplateDevice::getInsOrderId, orderId))
                .stream().map(InsOrderTemplateDevice::getTemplateId)
                .filter(Objects::nonNull).collect(Collectors.toSet());
        boolean inspectionStarted = order.getFirstInspectDate() != null
                || (order.getInsState() != null && order.getInsState() > 0)
                || snapshots.stream().anyMatch(snapshot -> StringUtils.isNotBlank(snapshot.getRecordValues())
                        || snapshot.getDetectionTime() != null || snapshot.getTemperature() != null
                        || snapshot.getDetectionPlace() != null);
        Map<Integer, List<Integer>> defaults = inspectionStarted ? Collections.emptyMap()
                : findStandardDeviceDefaults(order, snapshots);
        Map<Integer, List<InsOrderTemplateDevice>> existingDevices = insOrderTemplateDeviceMapper.selectList(
                        Wrappers.<InsOrderTemplateDevice>lambdaQuery()
                                .eq(InsOrderTemplateDevice::getInsOrderId, orderId)
                                .orderByAsc(InsOrderTemplateDevice::getSort, InsOrderTemplateDevice::getId))
                .stream().filter(relation -> relation.getTemplateId() != null)
                .collect(Collectors.groupingBy(InsOrderTemplateDevice::getTemplateId));
        Map<Integer, List<Integer>> defaults = findStandardDeviceDefaults(order, snapshots);
        for (InsOrderStandardTemplate snapshot : snapshots) {
            // 检验员手动选择或清空过的模板以人工为准,不再套用标准库默认值。
            if (Objects.equals(snapshot.getDeviceDefaultsInitialized(), 1)) {
                continue;
            }
            Integer templateId = snapshot.getTemplateId();
            if (!inspectionStarted && !existingTemplateIds.contains(templateId)
                    && defaults.containsKey(templateId)) {
                List<Integer> deviceIds = defaults.get(templateId);
                for (int index = 0; index < deviceIds.size(); index++) {
                    InsOrderTemplateDevice relation = new InsOrderTemplateDevice();
                    relation.setInsOrderId(orderId);
                    relation.setTemplateId(templateId);
                    relation.setDeviceId(deviceIds.get(index));
                    relation.setSort(index);
                    insOrderTemplateDeviceMapper.insert(relation);
                }
            if (templateId == null) {
                continue;
            }
            // 无法唯一确定来源时也只尝试这一次,避免以后标准库调整时意外改动订单。
            insOrderStandardTemplateMapper.update(null,
                    Wrappers.<InsOrderStandardTemplate>lambdaUpdate()
                            .eq(InsOrderStandardTemplate::getId, snapshot.getId())
                            .set(InsOrderStandardTemplate::getDeviceDefaultsInitialized, 1));
            List<InsOrderTemplateDevice> currentDevices = existingDevices.getOrDefault(
                    templateId, Collections.emptyList());
            // 旧数据没有初始化标记,已有设备视为人工选择,标记后不再自动覆盖。
            if (snapshot.getDeviceDefaultsInitialized() == null && !currentDevices.isEmpty()) {
                insOrderStandardTemplateMapper.update(null,
                        Wrappers.<InsOrderStandardTemplate>lambdaUpdate()
                                .eq(InsOrderStandardTemplate::getId, snapshot.getId())
                                .set(InsOrderStandardTemplate::getDeviceDefaultsInitialized, 1));
                continue;
            }
            if (!defaults.containsKey(templateId)) {
                continue;
            }
            List<Integer> standardDeviceIds = defaults.get(templateId).stream()
                    .filter(Objects::nonNull).distinct().collect(Collectors.toList());
            List<Integer> currentDeviceIds = currentDevices.stream()
                    .map(InsOrderTemplateDevice::getDeviceId)
                    .filter(Objects::nonNull).distinct().collect(Collectors.toList());
            if (currentDeviceIds.equals(standardDeviceIds)) {
                continue;
            }
            // 未初始化过的模板完全对齐标准库绑定:绑定几个就显示几个。
            insOrderTemplateDeviceMapper.delete(
                    Wrappers.<InsOrderTemplateDevice>lambdaQuery()
                            .eq(InsOrderTemplateDevice::getInsOrderId, orderId)
                            .eq(InsOrderTemplateDevice::getTemplateId, templateId));
            for (int index = 0; index < standardDeviceIds.size(); index++) {
                InsOrderTemplateDevice relation = new InsOrderTemplateDevice();
                relation.setInsOrderId(orderId);
                relation.setTemplateId(templateId);
                relation.setDeviceId(standardDeviceIds.get(index));
                relation.setSort(index);
                insOrderTemplateDeviceMapper.insert(relation);
            }
        }
    }
@@ -1184,23 +1226,29 @@
                        .isNotNull(StandardTree::getSample)
                        .isNull(StandardTree::getSampleType)
                        .isNull(StandardTree::getModel));
                List<StandardTree> matches = candidates.stream()
                        .filter(tree -> StringUtils.isNotBlank(tree.getSample()))
                        .filter(tree -> {
                            Set<Integer> boundIds = standardTreeService.selectTemplateBindings(tree.getId()).stream()
                                    .map(StandardTreeTemplateBindingVo::getTemplateId).collect(Collectors.toSet());
                            return boundIds.containsAll(templateIds);
                        }).collect(Collectors.toList());
                if (matches.size() == 1) {
                    standardTreeId = matches.get(0).getId();
                } else {
                    List<StandardTree> exact = matches.stream().filter(tree ->
                            standardTreeService.selectTemplateBindings(tree.getId()).stream()
                                    .map(StandardTreeTemplateBindingVo::getTemplateId)
                                    .collect(Collectors.toSet()).equals(templateIds))
                            .collect(Collectors.toList());
                    if (exact.size() == 1) {
                        standardTreeId = exact.get(0).getId();
                if (candidates.size() == 1) {
                    // 同一标准编号、同一实验室只有一个二级节点时直接认定,
                    // 避免标准库调整过模板后旧订单匹配不上。
                    standardTreeId = candidates.get(0).getId();
                } else if (!candidates.isEmpty()) {
                    List<StandardTree> matches = candidates.stream()
                            .filter(tree -> StringUtils.isNotBlank(tree.getSample()))
                            .filter(tree -> {
                                Set<Integer> boundIds = standardTreeService.selectTemplateBindings(tree.getId()).stream()
                                        .map(StandardTreeTemplateBindingVo::getTemplateId).collect(Collectors.toSet());
                                return boundIds.containsAll(templateIds);
                            }).collect(Collectors.toList());
                    if (matches.size() == 1) {
                        standardTreeId = matches.get(0).getId();
                    } else if (!matches.isEmpty()) {
                        List<StandardTree> exact = matches.stream().filter(tree ->
                                standardTreeService.selectTemplateBindings(tree.getId()).stream()
                                        .map(StandardTreeTemplateBindingVo::getTemplateId)
                                        .collect(Collectors.toSet()).equals(templateIds))
                                .collect(Collectors.toList());
                        if (exact.size() == 1) {
                            standardTreeId = exact.get(0).getId();
                        }
                    }
                }
            }