| | |
| | | import com.ruoyi.inspect.service.*; |
| | | import com.ruoyi.inspect.util.HackLoopTableRenderPolicy; |
| | | import com.ruoyi.inspect.util.PreserveReportPicturePlaceholderHandler; |
| | | import com.ruoyi.inspect.util.ReportSignaturePictureUtils; |
| | | import com.ruoyi.inspect.vo.InsOrderPlanTaskSwitchVo; |
| | | import com.ruoyi.inspect.vo.InsOrderPlanVO; |
| | | import com.ruoyi.inspect.vo.InsSampleUserVO; |
| | |
| | | import java.nio.file.Paths; |
| | | import java.text.DecimalFormat; |
| | | import java.text.SimpleDateFormat; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.*; |
| | |
| | | // 查询订单Id |
| | | InsOrder order = insOrderMapper.selectFirstSubmit(dto.getId()); |
| | | if (order == null) { |
| | | return BeanUtil.isEmpty(insProducts) ? null : insProducts; |
| | | return BeanUtil.isEmpty(insProducts) ? Collections.emptyList() : insProducts; |
| | | } |
| | | insProducts = mergeDirectTemplateSnapshots(order, dto.getId(), dto.getLaboratory(), insProducts); |
| | | if (BeanUtil.isEmpty(insProducts)) { |
| | | return null; |
| | | return Collections.emptyList(); |
| | | } |
| | | getTemplateThing(order, insProducts, dto.getLaboratory()); |
| | | return insProducts; |
| | |
| | | if (snapshots.isEmpty()) { |
| | | return source; |
| | | } |
| | | InsSample sample = insSampleMapper.selectById(sampleId); |
| | | boolean directTemplateOrder = source.stream() |
| | | .anyMatch(product -> product.getTemplateRowIndex() != null) |
| | | || isDirectTemplateSample(order, sample); |
| | | if (!directTemplateOrder) { |
| | | return source; |
| | | } |
| | | |
| | | Map<Integer, List<InsProduct>> productsByTemplate = source.stream() |
| | | .filter(product -> product.getTemplateId() != null) |
| | | .collect(Collectors.groupingBy(InsProduct::getTemplateId, LinkedHashMap::new, Collectors.toList())); |
| | |
| | | .last("FOR UPDATE")); |
| | | boolean isInspectionReport = Objects.equals(INSPECTION_REPORT, reportType); |
| | | registerInsResults = isInspectionReport && Boolean.TRUE.equals(registerInsResults); |
| | | // 1. 判断是否有重复编号, 有重复编号做提醒 |
| | | // 1. 委托编号全局唯一,提交复核时再次校验,防止并发或历史数据绕过生成校验。 |
| | | Long codeCount = insOrderMapper.selectCount(Wrappers.<InsOrder>lambdaQuery() |
| | | .ne(InsOrder::getState, -1) |
| | | .ne(InsOrder::getIfsInventoryId, order.getIfsInventoryId()) |
| | | .ne(InsOrder::getId, orderId) |
| | | .eq(InsOrder::getEntrustCode, order.getEntrustCode())); |
| | | if (codeCount > 0) { |
| | | throw new ErrorException("当前编号有重复, 请先去修改重复编号"); |
| | | throw new ErrorException("样品/委托单已存在,请确认样品编号"); |
| | | } |
| | | |
| | | // 2. 判断该订单是否是第一次生产(后续报告生成只取第一次提交时间) |
| | |
| | | || report.getExamineTime() != null; |
| | | if (submitted) { |
| | | User writer = getReportSigner(report.getWriteUserId(), "编制人"); |
| | | marks.put("writeUrl", Pictures.ofLocal(imgUrl + "/" + writer.getSignatureUrl()).create()); |
| | | marks.put("writeUrl", ReportSignaturePictureUtils.create(imgUrl, writer.getSignatureUrl())); |
| | | marks.put("writeDateUrl", Pictures.ofStream(DateImageUtil.createDateImage(report.getWriteTime())).create()); |
| | | marks.put("insUrl", Pictures.ofLocal(imgUrl + "/" + writer.getSignatureUrl()).create()); |
| | | marks.put("insUrl", ReportSignaturePictureUtils.create(imgUrl, writer.getSignatureUrl())); |
| | | } |
| | | if (Objects.equals(report.getIsExamine(), 1)) { |
| | | User examiner = getReportSigner(report.getExamineUserId(), "审核人"); |
| | | marks.put("examineUrl", Pictures.ofLocal(imgUrl + "/" + examiner.getSignatureUrl()).create()); |
| | | marks.put("examineUrl", ReportSignaturePictureUtils.create(imgUrl, examiner.getSignatureUrl())); |
| | | marks.put("examineDateUrl", Pictures.ofStream(DateImageUtil.createDateImage(report.getExamineTime())).create()); |
| | | } |
| | | return marks; |
| | |
| | | enterFactoryReport.setLotBatchNo(ifsInventoryQuantity.getUpdateBatchNo()); |
| | | |
| | | // 检测依据 |
| | | Set<String> standardMethod = new HashSet<>(); |
| | | Set<String> standardMethod = new LinkedHashSet<>(); |
| | | StringBuilder standardMethod2 = new StringBuilder(); |
| | | standardMethod.add(baseMapper.getStandardMethodCode(insSample.getStandardMethodListId())); |
| | | String reportStandardMethod = baseMapper.getStandardMethodReportText(insSample.getStandardMethodListId()); |
| | | if (StringUtils.isNotBlank(reportStandardMethod)) { |
| | | standardMethod.add(reportStandardMethod); |
| | | } |
| | | for (String s : standardMethod) { |
| | | standardMethod2.append("、").append(s); |
| | | } |
| | | standardMethod2.replace(0, 1, ""); |
| | | if (standardMethod2.length() > 0) { |
| | | standardMethod2.deleteCharAt(0); |
| | | } |
| | | |
| | | // 样品类型 |
| | | String orderType = iSysDictTypeService.selectLabelByDict(DictDataConstants.CHECK_TYPE, insOrder.getOrderType()); |
| | |
| | | insReport.setReportType(reportType); |
| | | boolean showResult = Objects.equals(reportType, INSPECTION_REPORT); |
| | | List<Map<String, Object>> tables = new ArrayList<>(); |
| | | Set<String> standardMethod = new HashSet<>(); |
| | | Set<String> deviceSet = new HashSet<>(); |
| | | Set<String> standardMethod = new LinkedHashSet<>(); |
| | | Set<String> models = new HashSet<>(); |
| | | // 查询检验项数量 |
| | | AtomicInteger productSize = new AtomicInteger(); |
| | |
| | | /*基础报告(根据绘制的原始记录模版形成)*/ |
| | | samples.forEach(a -> { |
| | | models.add(a.getModel()); |
| | | String standardMethodCode = baseMapper.getStandardMethodCode(a.getStandardMethodListId()); |
| | | if (StrUtil.isNotBlank(a.getSpecialStandardMethod())) { |
| | | standardMethodCode = standardMethodCode + "+" + a.getSpecialStandardMethod(); |
| | | } |
| | | standardMethod.add(standardMethodCode); |
| | | for (InsProduct b : a.getInsProduct()) { |
| | | if (b.getInsProductResult() != null) { |
| | | List<JSONObject> jsonObjects = JSON.parseArray(b.getInsProductResult().getEquipValue(), JSONObject.class); |
| | | for (JSONObject jsonObject : jsonObjects) { |
| | | if (!"".equals(jsonObject.get("v") + "")) { |
| | | List<String> v = StrUtil.split(jsonObject.get("v") + "", ","); |
| | | deviceSet.addAll(v); |
| | | } |
| | | } |
| | | String standardMethodCode = baseMapper.getStandardMethodReportText(a.getStandardMethodListId()); |
| | | if (StrUtil.isNotBlank(standardMethodCode)) { |
| | | if (StrUtil.isNotBlank(a.getSpecialStandardMethod())) { |
| | | standardMethodCode = standardMethodCode + "+" + a.getSpecialStandardMethod(); |
| | | } |
| | | standardMethod.add(standardMethodCode); |
| | | } |
| | | // 直绑模板的检测报告、检验报告都使用新版固定结果行,不再进入旧版检验项表格逻辑。 |
| | | // 直绑模板中的承载记录没有旧检验项字段,进入旧逻辑会在格式化时产生空指针。 |
| | |
| | | } |
| | | |
| | | max = a.getQuantity(); |
| | | // 季度检验需要进厂检验的设备 |
| | | // 查询是否有进厂检验 |
| | | InsOrder order = insOrderMapper.selectOne(Wrappers.<InsOrder>lambdaQuery() |
| | | .eq(InsOrder::getIfsInventoryId, insOrder.getIfsInventoryId()) |
| | | .ne(InsOrder::getState, -1) |
| | | .eq(InsOrder::getOrderType, InsOrderTypeConstants.ENTER_THE_FACTORY) |
| | | .ne(InsOrder::getId, insOrder.getId()) |
| | | .last("limit 1")); |
| | | if (order != null) { |
| | | List<SampleProductDto> sampleProductDtos = insSampleMapper.selectSampleProductListByOrderId(order.getId()); |
| | | for (InsProduct b : sampleProductDtos.get(0).getInsProduct()) { |
| | | if (b.getInsProductResult() != null) { |
| | | List<JSONObject> jsonObjects = JSON.parseArray(b.getInsProductResult().getEquipValue(), JSONObject.class); |
| | | for (JSONObject jsonObject : jsonObjects) { |
| | | if (!"".equals(jsonObject.get("v") + "")) { |
| | | List<String> v = StrUtil.split(jsonObject.get("v") + "", ","); |
| | | deviceSet.addAll(v); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | if (StringUtils.isBlank(insOrder.getSampleView())) { |
| | | insOrder.setSampleView(insOrder.getSample()); |
| | | } |
| | |
| | | tables.forEach(table -> { |
| | | table.put("tableSize", tables.size() + 1); |
| | | }); |
| | | // 新订单按模板选择设备;旧订单没有模板设备关系时回退到订单级设备记录。 |
| | | Set<String> reportDeviceNumbers = insOrderTemplateDeviceMapper |
| | | .selectManagementNumbersByOrderId(orderId).stream() |
| | | .filter(StringUtils::isNotBlank) |
| | | // 报告只展示检验单各模板选择的设备,并按设备ID去重。 |
| | | Set<Integer> reportDeviceIds = insOrderTemplateDeviceMapper |
| | | .selectDeviceIdsByOrderId(orderId).stream() |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toCollection(LinkedHashSet::new)); |
| | | if (reportDeviceNumbers.isEmpty()) { |
| | | reportDeviceNumbers.addAll(insOrderDeviceRecordMapper.selectDeviceNumber(orderId).stream() |
| | | .map(InsOrderDeviceRecordDto::getManagementNumber) |
| | | .filter(StringUtils::isNotBlank) |
| | | .collect(Collectors.toList())); |
| | | } |
| | | reportDeviceNumbers.addAll(deviceSet); |
| | | List<Map<String, String>> deviceList = reportDeviceNumbers.isEmpty() |
| | | ? new ArrayList<>() : insOrderMapper.selectDeviceList(reportDeviceNumbers); |
| | | List<Map<String, String>> deviceList = reportDeviceIds.isEmpty() |
| | | ? new ArrayList<>() : insOrderMapper.selectDeviceListByIds(reportDeviceIds); |
| | | if (CollectionUtils.isNotEmpty(deviceList)) { |
| | | int count = 1; |
| | | for (Map<String, String> stringMap : deviceList) { |
| | |
| | | sendTime = reportInventory.getDeclareDate(); |
| | | } |
| | | |
| | | // 检测日期:首次保存模板值时间-首次提交时间 |
| | | // 检测日期:汇总检验单各模板填写的检测时间,日期相同显示一个,否则显示最早至最晚。 |
| | | LocalDateTime now = LocalDateTime.now(); |
| | | // 提交时间 |
| | | LocalDateTime submitTime = LocalDateTime.now(); |
| | | // 判断是否有提交时间 |
| | | if (insOrder.getFirstSubmitDate() != null) { |
| | | submitTime = insOrder.getFirstSubmitDate(); |
| | | } |
| | | |
| | | LocalDateTime firstInspectDate = insOrder.getFirstInspectDate(); |
| | | // 字段上线前的历史订单沿用原来的下发时间,避免改变既有报告口径。 |
| | | if (firstInspectDate == null) { |
| | | firstInspectDate = insOrder.getSendTime(); |
| | | } |
| | | |
| | | String insTime = firstInspectDate.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")) + "-" |
| | | + submitTime.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")); |
| | | |
| | | String insTimeEn = monthNames[firstInspectDate.getMonthValue() - 1] + " " + firstInspectDate.format(DateTimeFormatter.ofPattern("dd, yyyy")) + "-" |
| | | + monthNames[submitTime.getMonthValue() - 1] + " " + submitTime.format(DateTimeFormatter.ofPattern("dd, yyyy")); |
| | | List<InsOrderStandardTemplate> templateSnapshots = insOrderStandardTemplateService.list( |
| | | Wrappers.<InsOrderStandardTemplate>lambdaQuery() |
| | | .eq(InsOrderStandardTemplate::getInsOrderId, orderId) |
| | | .orderByAsc(InsOrderStandardTemplate::getSort, InsOrderStandardTemplate::getId)); |
| | | List<LocalDate> detectionDates = templateSnapshots.stream() |
| | | .map(InsOrderStandardTemplate::getDetectionTime) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toList()); |
| | | String insTime = formatReportTestDate(detectionDates); |
| | | String insTimeEn = formatReportTestDateEn(detectionDates, monthNames); |
| | | |
| | | // 检验环境:优先汇总各模板填写的温湿度,报告展示全部模板的最小值到最大值。 |
| | | String environment = buildReportEnvironment(orderId, insOrder); |
| | |
| | | batchNo = defaultReportText(reportInventory.getUpdateBatchNo(), reportInventory.getLotBatchNo()); |
| | | } |
| | | // 新聚直绑模板订单:报告信息取委托信息和订单模板快照,不再取能力范围标准方法。 |
| | | List<InsOrderStandardTemplate> templateSnapshots = insOrderStandardTemplateService.list( |
| | | Wrappers.<InsOrderStandardTemplate>lambdaQuery() |
| | | .eq(InsOrderStandardTemplate::getInsOrderId, orderId) |
| | | .orderByAsc(InsOrderStandardTemplate::getSort, InsOrderStandardTemplate::getId)); |
| | | boolean newJuTemplateOrder = !templateSnapshots.isEmpty() && directTemplateOrder; |
| | | if (newJuTemplateOrder) { |
| | | productName = defaultReportText(insOrder.getSampleView(), insOrder.getSample()); |
| | |
| | | productionDate = insOrder.getProductionDate().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")); |
| | | } |
| | | batchNo = defaultReportText(insOrder.getProductionBatch(), "/"); |
| | | standardMethodText = templateSnapshots.stream() |
| | | .map(InsOrderStandardTemplate::getRemark) |
| | | .filter(StringUtils::isNotBlank) |
| | | .distinct() |
| | | .collect(Collectors.joining(";")); |
| | | standardMethodText = defaultReportText( |
| | | baseMapper.getStandardMethodReportTextByCode(insOrder.getSample()), insOrder.getSample()); |
| | | } |
| | | boolean containsOrganicChlorine = detectionResultRows.stream() |
| | | .map(row -> row.get("itemName")) |
| | |
| | | if (CollectionUtils.isEmpty(deviceList)) { |
| | | return "/"; |
| | | } |
| | | Set<String> lines = new LinkedHashSet<>(); |
| | | int sequence = 1; |
| | | Set<String> equipmentItems = new LinkedHashSet<>(); |
| | | for (Map<String, String> device : deviceList) { |
| | | String name = getMapText(device, "deviceName", "device_name"); |
| | | String managementNumber = getMapText(device, "managementNumber", "management_number"); |
| | | String line = sequence++ + ". " + defaultReportText(name, "/"); |
| | | if (StringUtils.isNotBlank(managementNumber)) { |
| | | line += ":" + managementNumber; |
| | | if (StringUtils.isBlank(name) || "/".equals(name.trim())) { |
| | | continue; |
| | | } |
| | | lines.add(line); |
| | | String number = StringUtils.isBlank(managementNumber) || "/".equals(managementNumber.trim()) |
| | | ? "出厂编号" : managementNumber.trim(); |
| | | String item = name.trim() + ":" + number; |
| | | equipmentItems.add(item); |
| | | } |
| | | if (equipmentItems.isEmpty()) { |
| | | return "/"; |
| | | } |
| | | List<String> items = new ArrayList<>(equipmentItems); |
| | | List<String> lines = new ArrayList<>(); |
| | | for (int i = 0; i < items.size(); i++) { |
| | | String punctuation = i == items.size() - 1 ? "。" : ";"; |
| | | lines.add((i + 1) + ". " + items.get(i) + punctuation); |
| | | } |
| | | return String.join("\n", lines); |
| | | } |
| | |
| | | .collect(Collectors.toList()); |
| | | |
| | | String temperature = formatConditionRange(temperatures, order.getTemperature(), "℃"); |
| | | String humidity = formatConditionRange(humidities, order.getHumidity(), "%"); |
| | | String humidity = formatConditionRange(humidities, order.getHumidity(), "%RH"); |
| | | return Stream.of(temperature, humidity) |
| | | .filter(StringUtils::isNotBlank) |
| | | .collect(Collectors.joining(" ")); |
| | |
| | | return StringUtils.isNotBlank(fallback) ? fallback : "/"; |
| | | } |
| | | |
| | | private static String formatReportTestDate(List<LocalDate> detectionDates) { |
| | | if (CollectionUtils.isEmpty(detectionDates)) { |
| | | return "/"; |
| | | } |
| | | LocalDate startDate = Collections.min(detectionDates); |
| | | LocalDate endDate = Collections.max(detectionDates); |
| | | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日"); |
| | | if (startDate.equals(endDate)) { |
| | | return startDate.format(formatter); |
| | | } |
| | | return startDate.format(formatter) + "至" + endDate.format(formatter); |
| | | } |
| | | |
| | | private static String formatReportTestDateEn(List<LocalDate> detectionDates, String[] monthNames) { |
| | | if (CollectionUtils.isEmpty(detectionDates)) { |
| | | return "/"; |
| | | } |
| | | LocalDate startDate = Collections.min(detectionDates); |
| | | LocalDate endDate = Collections.max(detectionDates); |
| | | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd, yyyy"); |
| | | String startText = monthNames[startDate.getMonthValue() - 1] + " " + startDate.format(formatter); |
| | | if (startDate.equals(endDate)) { |
| | | return startText; |
| | | } |
| | | return startText + "-" + monthNames[endDate.getMonthValue() - 1] + " " + endDate.format(formatter); |
| | | } |
| | | |
| | | /** |
| | | * 计算表格列宽度 |
| | | * |