| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | private StandardTemplateService standardTemplateService; |
| | | private InsOrderStandardTemplateMapper insOrderStandardTemplateMapper; |
| | | private InsOrderTemplateDeviceMapper insOrderTemplateDeviceMapper; |
| | | private InsSampleReceiptMapper insSampleReceiptMapper; |
| | | private ApplicationEventPublisher applicationEventPublisher; |
| | | |
| | | |
| | | |
| | |
| | | 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); |
| | | } |
| | | |
| | | |
| | |
| | | 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); |
| | | 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); |
| | | } |
| | | } |
| | | |
| | | // 判断订单有没有绑定抽样计划 |
| | | InsOrder order = insOrderMapper.selectById(orderId); |
| | | if (order.getQuarterItemId() != null) { |
| | | // 需要添加下发时间到抽样时间, 取样人员就是检测人 |
| | | SpotCheckQuarterItem spotCheckQuarterItem = spotCheckQuarterItemMapper.selectById(order.getQuarterItemId()); |
| | |
| | | } |
| | | |
| | | 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())); |
| | | } |
| | | |
| | | |
| | |
| | | } |
| | | } |
| | | }); |
| | | // 下单时生成委托编号并校验唯一性;季度检验复用进厂检验编号,留待审核处理。 |
| | | 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())) { |
| | | // 委托人就是报检人, 生产单位就是供应商单位 |
| | |
| | | // 审核检验单 |
| | | 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)){ |
| | |
| | | public int addNewJuInsOrder(InsPlaceOrderDto dto) { |
| | | 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位"); |
| | | } |
| | | // 委托要求字段校验:四组单选必选,分包/快递联动必填 |
| | | 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()) |
| | |
| | | |
| | | 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()); |
| | |
| | | // 新聚订单的环境条件由检验任务填写,避免下单模板或浏览器缓存带入旧值。 |
| | | 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(); |
| | | sample.setInsOrderId(order.getId()); |
| | | sample.setSampleCode(dto.getSampleCode()); |
| | | sample.setSampleCode(sampleCode); |
| | | sample.setFactory(null); |
| | | sample.setLaboratory(standard.getLaboratory()); |
| | | sample.setSampleType(null); |
| | |
| | | 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)); |
| | | // 免审核后由下单生成待接收的样品接收记录,主检验人仍在样品接收页面选择后才创建检验任务 |
| | | 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) { |
| | |
| | | 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); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | * @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()); |
| | | // 委托编号按送样日期独立流水,例如: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(); |
| | | // 判断是否是季度检验, 是季度检验取消原材料季度检验下单 |
| | | if (InsOrderTypeConstants.QUARTERLY_TEST.equals(order.getOrderType())) { |
| | | ifsInventoryQuantityMapper.update(null, Wrappers.<IfsInventoryQuantity>lambdaUpdate() |
| | |
| | | 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())) { |
| | | // 如果只有一个样品就不需要拼接数字 |
| | |
| | | |
| | | 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 |
| | |
| | | insOrder.setState(1); |
| | | |
| | | upInsOrderOfState(insOrder); |
| | | upInsOrder(insOrder.getId(), null, appointed != null ? appointed.toString() : null, SecurityUtils.getUserId().intValue(), "原材料"); |
| | | // 审核通过后仅进入样品接收;由样品接收页面选择主检验人后再创建检验任务。 |
| | | |
| | | return insOrder.getId(); |
| | | } |