liding
2026-09-01 bf2026a38d4d36371060673d4651b6e05ca90632
feat(device): 1.更新设备导入验证逻辑和检验任务功能
2.报告编制
已修改8个文件
86 ■■■■■ 文件已修改
cnas-device/src/main/java/com/ruoyi/device/service/impl/DeviceServiceImpl.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
inspect-server/src/main/java/com/ruoyi/inspect/controller/InsOrderPlanController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
inspect-server/src/main/java/com/ruoyi/inspect/service/InsOrderPlanService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderPlanServiceImpl.java 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsReportServiceImpl.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
inspect-server/src/main/resources/static/detection-report-template.docx 补丁 | 查看 | 原始文档 | blame | 历史
inspect-server/src/main/resources/static/small-detection-template.docx 补丁 | 查看 | 原始文档 | blame | 历史
inspect-server/src/main/resources/static/small-wg-detection-template.docx 补丁 | 查看 | 原始文档 | blame | 历史
cnas-device/src/main/java/com/ruoyi/device/service/impl/DeviceServiceImpl.java
@@ -547,17 +547,18 @@
            throw new RuntimeException("导入文件没有设备数据");
        }
        Set<String> managementNumbers = new HashSet<>();
        Set<String> fileKeys = new HashSet<>();
        for (int i = 0; i < rows.size(); i++) {
            String managementNumber = required(rows.get(i).getManagementNumber(), i + 2, "管理编号");
            if (!managementNumbers.add(managementNumber)) {
                throw new RuntimeException("第" + (i + 2) + "行:管理编号" + managementNumber + "在文件中重复");
            String deviceName = required(rows.get(i).getDeviceName(), i + 2, "仪器名称");
            String specificationModel = required(rows.get(i).getSpecificationModel(), i + 2, "规格型号");
            if (!fileKeys.add(deviceKey(deviceName, specificationModel, managementNumber))) {
                throw new RuntimeException("第" + (i + 2) + "行:仪器名称+规格型号+管理编号在文件中重复");
            }
        }
        Set<String> existingNumbers = baseMapper.selectList(Wrappers.<Device>lambdaQuery()
                        .in(Device::getManagementNumber, managementNumbers)
                        .select(Device::getManagementNumber))
                .stream().map(Device::getManagementNumber).collect(Collectors.toSet());
        Set<String> existingKeys = baseMapper.selectList(Wrappers.<Device>lambdaQuery()
                        .select(Device::getDeviceName, Device::getSpecificationModel, Device::getManagementNumber))
                .stream().map(d -> deviceKey(d.getDeviceName(), d.getSpecificationModel(), d.getManagementNumber())).collect(Collectors.toSet());
        Map<String, List<SysDept>> departmentMap = sysDeptMapper.selectDeptList(new SysDept()).stream()
                .filter(item -> StringUtils.isNotBlank(item.getDeptName()))
@@ -573,8 +574,10 @@
            int rowNumber = i + 2;
            DeviceImport row = rows.get(i);
            String managementNumber = required(row.getManagementNumber(), rowNumber, "管理编号");
            if (existingNumbers.contains(managementNumber)) {
                throw new RuntimeException("第" + rowNumber + "行:管理编号" + managementNumber + "已存在");
            String deviceName = required(row.getDeviceName(), rowNumber, "仪器名称");
            String specificationModel = required(row.getSpecificationModel(), rowNumber, "规格型号");
            if (existingKeys.contains(deviceKey(deviceName, specificationModel, managementNumber))) {
                throw new RuntimeException("第" + rowNumber + "行:仪器名称“" + deviceName + "”+规格型号“" + specificationModel + "”+管理编号“" + managementNumber + "”已存在");
            }
            String laboratoryName = required(row.getLaboratoryName(), rowNumber, "所属部门");
@@ -584,10 +587,10 @@
            }
            Device device = new Device();
            device.setDeviceName(required(row.getDeviceName(), rowNumber, "仪器名称"));
            device.setSpecificationModel(required(row.getSpecificationModel(), rowNumber, "规格型号"));
            device.setDeviceName(deviceName);
            device.setSpecificationModel(specificationModel);
            device.setManagementNumber(managementNumber);
            device.setActivationDate(parseDate(row.getActivationDate(), rowNumber, "校准有效期", true));
            device.setActivationDate(parseDate(row.getActivationDate()));
            device.setSubordinateDepartmentsId(departments.get(0).getDeptId().intValue());
            device.setDeviceStatus(Integer.valueOf(dictValue(statusMap, row.getDeviceStatus(), rowNumber, "当前状态", true)));
            device.setCalibrationDate(required(row.getCalibrationDate(), rowNumber, "校准周期(月)"));
@@ -596,12 +599,12 @@
            device.setFactoryNo(trim(row.getFactoryNo()));
            device.setAssetCode(trim(row.getAssetCode()));
            device.setOrigin(trim(row.getOrigin()));
            device.setAcquisitionDate(parseDate(row.getAcquisitionDate(), rowNumber, "购置日期", false));
            device.setAcquisitionDate(parseDate(row.getAcquisitionDate()));
            device.setStoragePoint(trim(row.getStoragePoint()));
            device.setTechnicalIndicators(trim(row.getTechnicalIndicators()));
            device.setCalibrationServices(trim(row.getCalibrationServices()));
            device.setLastCalibrationDate(parseDate(row.getLastCalibrationDate(), rowNumber, "最近校准日期", false));
            device.setNextCalibrationDate(parseDate(row.getNextCalibrationDate(), rowNumber, "下次校准日期", false));
            device.setLastCalibrationDate(parseDate(row.getLastCalibrationDate()));
            device.setNextCalibrationDate(parseDate(row.getNextCalibrationDate()));
            device.setLargeCategory(dictValue(typeMap, row.getLargeCategory(), rowNumber, "设备类型", false));
            device.setUnitPrice(parseDecimal(row.getUnitPrice(), rowNumber, "单价(万元)"));
@@ -642,19 +645,16 @@
        return value;
    }
    private LocalDateTime parseDate(String input, int rowNumber, String column, boolean required) {
    private LocalDateTime parseDate(String input) {
        String text = trim(input);
        if (StringUtils.isBlank(text)) {
            if (required) {
                throw new RuntimeException("第" + rowNumber + "行:" + column + "不能为空");
            }
            return null;
        }
        String datePart = text.replace('/', '-').split("\\s+")[0];
        try {
            return LocalDate.parse(text.substring(0, Math.min(text.length(), 10)).replace('/', '-'), DateTimeFormatter.ofPattern("yyyy-M-d"))
                    .atStartOfDay();
            return LocalDate.parse(datePart, DateTimeFormatter.ofPattern("yyyy-M-d")).atStartOfDay();
        } catch (Exception e) {
            throw new RuntimeException("第" + rowNumber + "行:" + column + "格式应为yyyy-MM-dd", e);
            return null;
        }
    }
@@ -678,6 +678,12 @@
        return value;
    }
    private String deviceKey(String deviceName, String specificationModel, String managementNumber) {
        return (deviceName == null ? "" : deviceName.trim()) + "|"
                + (specificationModel == null ? "" : specificationModel.trim()) + "|"
                + (managementNumber == null ? "" : managementNumber.trim());
    }
    private String trim(String value) {
        return value == null ? null : value.trim();
    }
inspect-server/src/main/java/com/ruoyi/inspect/controller/InsOrderPlanController.java
@@ -99,8 +99,8 @@
    @ApiOperation(value = "校验检验任务提交")
    @PostMapping("/checkSubmitPlan")
    public Result<?> checkSubmitPlan(Integer orderId, String laboratory) {
        return Result.success(insOrderPlanService.checkSubmitPlan(orderId, laboratory));
    public Result<?> checkSubmitPlan(Integer orderId, String laboratory, Integer reportType) {
        return Result.success(insOrderPlanService.checkSubmitPlan(orderId, laboratory, reportType));
    }
inspect-server/src/main/java/com/ruoyi/inspect/service/InsOrderPlanService.java
@@ -36,7 +36,7 @@
    List<InsProduct> getInsProduct(InsOrderPlanProductDto insOrderPlanProductDto);
    Map<String,Object> checkSubmitPlan(Integer orderId, String laboratory);
    Map<String,Object> checkSubmitPlan(Integer orderId, String laboratory, Integer reportType);
    IPage<InsOrderFile> getFileList(Page page, InsOrderFile insOrderFile);
inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderPlanServiceImpl.java
@@ -277,9 +277,14 @@
    }
    @Override
    public Map<String,Object> checkSubmitPlan(Integer orderId, String laboratory) {
    public Map<String,Object> checkSubmitPlan(Integer orderId, String laboratory, Integer reportType) {
        Map<String, Object> map = new HashMap<>();
        List<String> collect = new ArrayList<>();
        if (Objects.equals(DETECTION_REPORT, reportType)) {
            map.put("errorMsg", collect);
            map.put("unInsOrderCount", 0L);
            return map;
        }
        List<InsSample> insSamples = insSampleMapper.selectList(Wrappers.<InsSample>lambdaQuery().eq(InsSample::getInsOrderId, orderId).select(InsSample::getId));
        List<Integer> ids = insSamples.stream().map(a -> a.getId()).collect(Collectors.toList());
        List<InsProduct> insProducts = insProductMapper.selectList(Wrappers.<InsProduct>lambdaQuery()
@@ -773,7 +778,17 @@
        if (!Objects.equals(DETECTION_REPORT, reportType) && !Objects.equals(INSPECTION_REPORT, reportType)) {
            throw new ErrorException("请选择报告类型");
        }
        InsOrder order = insOrderMapper.selectById(orderId);
        InsOrder order = insOrderMapper.selectOne(Wrappers.<InsOrder>lambdaQuery()
                .eq(InsOrder::getId, orderId)
                .last("FOR UPDATE"));
        InsReport existingReport = insReportMapper.selectOne(Wrappers.<InsReport>lambdaQuery()
                .eq(InsReport::getInsOrderId, orderId));
        if (existingReport != null && existingReport.getReportType() != null
                && !Objects.equals(existingReport.getReportType(), reportType)) {
            throw new ErrorException("同一检验订单只能使用一种报告类型");
        }
        boolean isInspectionReport = Objects.equals(INSPECTION_REPORT, reportType);
        registerInsResults = isInspectionReport && Boolean.TRUE.equals(registerInsResults);
        // 1. 判断是否有重复编号, 有重复编号做提醒
        Long codeCount = insOrderMapper.selectCount(Wrappers.<InsOrder>lambdaQuery()
                .ne(InsOrder::getState, -1)
@@ -887,7 +902,7 @@
        // 11.成品抽样添加合格状态
        // 判断是否有抽样信息
        if (order.getQuarterItemId() != null) {
        if (isInspectionReport && order.getQuarterItemId() != null) {
            // 判断是否有不合格
            this.addProductSpotCheck(insSamples, order);
        }
@@ -942,7 +957,7 @@
        });
        // 14.ifs移库(原材料需要进行移库操作) --> 最后执行,因为失败无法回滚
        if (ifsInventoryQuantity != null) {
        if (ifsInventoryQuantity != null && isInspectionReport) {
            // 登记检验结果
            // 判断是否有不合格, 有不合格不能移库
            // todo: ifs移库
@@ -956,7 +971,7 @@
            });
        } else {
        } else if (isInspectionReport) {
            // 修改成品状态
            // 判断是否有不合格
            Long unqualifiedCount = insReportService.getUnqualifiedCount(order);
@@ -983,7 +998,7 @@
    private void addAnalysis(List<InsProduct> productList, IfsInventoryQuantity ifsInventoryQuantity, InsOrder order, String sendUserAccount) {
        for (InsProduct insProduct : productList) {
            // 判断是否是数值类型
            if (insProduct.getInspectionValueType().equals("1") && insProduct.getInsResult().equals(1)) {
            if ("1".equals(insProduct.getInspectionValueType()) && Objects.equals(insProduct.getInsResult(), 1)) {
                List<InsProductDeviationWarningDetail> insProductAnalysisDtoList = insProductMapper.selectAnalysis(insProduct, ifsInventoryQuantity.getSupplierName());
                if (CollectionUtils.isEmpty(insProductAnalysisDtoList)) {
inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsReportServiceImpl.java
@@ -814,7 +814,8 @@
        // 判断是否有不合格
        Long unqualifiedCount = getUnqualifiedCount(insOrder);
        if (count.equals(0L) && unqualifiedCount.equals(0L) && one.getIsFinish().equals(0) && one.getIsSource().equals(1) && registerInsResults) {
        if (count.equals(0L) && unqualifiedCount.equals(0L) && one.getIsFinish().equals(0)
                && one.getIsSource().equals(1) && Boolean.TRUE.equals(registerInsResults)) {
            // 原材料移库
            //如果是拆分的订单,则把拆分的所有批次都移库
            if(one.getIsSplitOrder()==1 && !hasExemption){
inspect-server/src/main/resources/static/detection-report-template.docx
Binary files differ
inspect-server/src/main/resources/static/small-detection-template.docx
Binary files differ
inspect-server/src/main/resources/static/small-wg-detection-template.docx
Binary files differ