diff --git a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/external/ExternalIncomingInspectionTaskController.java b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/external/ExternalIncomingInspectionTaskController.java index 9145b66d..5d5957ae 100644 --- a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/external/ExternalIncomingInspectionTaskController.java +++ b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/external/ExternalIncomingInspectionTaskController.java @@ -34,7 +34,7 @@ public class ExternalIncomingInspectionTaskController extends BaseController { */ @PostMapping("incoming-apply") public ApiResult IncomingApply(@Valid @RequestBody List requests) { - incomingInspectionTaskControllerService.IncomingApply(requests); + incomingInspectionTaskControllerService.incomingApply(requests); return ApiResult.success(); } diff --git a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/IncomingInspectionTaskControllerService.java b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/IncomingInspectionTaskControllerService.java index c475a730..da6d38ba 100644 --- a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/IncomingInspectionTaskControllerService.java +++ b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/IncomingInspectionTaskControllerService.java @@ -19,6 +19,8 @@ import org.apache.commons.lang3.tuple.Pair; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.support.TransactionSynchronization; +import org.springframework.transaction.support.TransactionSynchronizationManager; import java.time.LocalDateTime; import java.util.*; @@ -125,7 +127,7 @@ public class IncomingInspectionTaskControllerService { * - 若质检人员设置了转办人,则使用转办人代替 */ @Transactional - public void IncomingApply(List requests) { + public void incomingApply(List requests) { for (ExternalIncomingInspectionApplyQO request : requests) { applySingle(request); } @@ -163,7 +165,6 @@ public class IncomingInspectionTaskControllerService { String inspectorName; User inspectorUser; if (Objects.nonNull(inspector.getChangeUserId())) { - // 转办人是 user.id,需查询对应的 qms_quality_inspector 记录 QmsQualityInspector agentInspector = qualityInspectorService.getById(inspector.getChangeUserId()); if (Objects.nonNull(agentInspector)) { inspectorId = agentInspector.getId(); @@ -218,7 +219,7 @@ public class IncomingInspectionTaskControllerService { Long inspectionStandardId = dictionaryItemService.getIdByCode("InspectionStandardTestingMethod", "Sampling"); VUtil.trueThrowBusinessError(Objects.isNull(inspectionStandardId)).throwMessage("检测方式不存在"); if (Objects.equals(standard.getTestingMethodDictItemId(), inspectionStandardId)) { - Pair aqlType = CalculatedAqlType(task, standard + Pair aqlType = calculatedAqlType(task, standard , dictionaryItemService.getListByDictionaryCode("InspectionStandardSQLType")); incomingInspectionTaskAqlRuleService.save(new QmsIncomingInspectionTaskAqlRule() .setTaskId(task.getId()) @@ -357,7 +358,7 @@ public class IncomingInspectionTaskControllerService { Long inspectionStandardId = dictionaryItemService.getIdByCode("InspectionStandardTestingMethod", "Sampling"); VUtil.trueThrowBusinessError(Objects.isNull(inspectionStandardId)).throwMessage("检测方式不存在"); if (Objects.equals(standard.getTestingMethodDictItemId(), inspectionStandardId)) { - Pair aqlType = CalculatedAqlType(task, standard + Pair aqlType = calculatedAqlType(task, standard , dictionaryItemService.getListByDictionaryCode("InspectionStandardSQLType")); incomingInspectionTaskAqlRuleService.save(new QmsIncomingInspectionTaskAqlRule() .setTaskId(task.getId()) @@ -412,8 +413,8 @@ public class IncomingInspectionTaskControllerService { QmsIncomingInspectionTask newTask = new QmsIncomingInspectionTask() .setRequestNo(task.getRequestNo()) .setTaskNo(taskNo) - .setMaterialId(task.getId()) - .setInspectionStandardId(task.getId()) + .setMaterialId(task.getMaterialId()) + .setInspectionStandardId(task.getInspectionStandardId()) .setTestingMethodDictItemId(testingMethodDictItemId) .setSupplierCode(task.getSupplierCode()) .setSupplierName(task.getSupplierName()) @@ -530,14 +531,17 @@ public class IncomingInspectionTaskControllerService { } private DictionaryItem getAql(Long id, List aqls) { - return aqls.stream().filter(aql -> Objects.equals(aql.getId(), id)).findFirst().get(); + return aqls.stream() + .filter(aql -> Objects.equals(aql.getId(), id)) + .findFirst() + .orElseThrow(() -> new NflgException(STATE.BusinessError,"未找到AQL")); } - private Pair CalculatedAqlType(QmsIncomingInspectionTask task, QmsInspectionStandard standard + private Pair calculatedAqlType(QmsIncomingInspectionTask task, QmsInspectionStandard standard , List aqls) { - DictionaryItem sqlzc = aqls.stream().filter(aql -> StrUtil.equals(aql.getCode(), "正常")).findFirst().get(); - DictionaryItem sqljy = aqls.stream().filter(aql -> StrUtil.equals(aql.getCode(), "加严")).findFirst().get(); - DictionaryItem sqlfw = aqls.stream().filter(aql -> StrUtil.equals(aql.getCode(), "放宽")).findFirst().get(); + DictionaryItem sqlzc = aqls.stream().filter(aql -> StrUtil.equals(aql.getName(), "正常")).findFirst().get(); + DictionaryItem sqljy = aqls.stream().filter(aql -> StrUtil.equals(aql.getName(), "加严")).findFirst().get(); + DictionaryItem sqlfw = aqls.stream().filter(aql -> StrUtil.equals(aql.getName(), "放宽")).findFirst().get(); log.info("【抽样严格性转移规则计算】检验项严格性为:" + getAql(standard.getAqlTypeDictItemId(), aqls).getName()); List statistics = supplierInspectionStatisticsService.lambdaQuery() .eq(QmsSupplierInspectionStatistics::getInspectionStandardId, standard.getId()) @@ -778,7 +782,7 @@ public class IncomingInspectionTaskControllerService { // 校验是否存在已检任务 boolean hasFinished = tasks.stream() - .anyMatch(t -> t.getInspectionStatus() != null && t.getInspectionStatus() == 1); + .anyMatch(t -> Objects.equals(t.getInspectionStatus(),(short)2)); VUtil.trueThrowBusinessError(hasFinished) .throwMessage("已检状态的任务不允许转办"); @@ -1177,7 +1181,18 @@ public class IncomingInspectionTaskControllerService { updateWrapper.update(); if (request.getQualified() && task.getUnqualifiedQty() == 0) { - wmsIncomingInspectionTaskCallbackService.processAsync(task.getId(), (short) 0); + // 异步回调需等当前事务提交后再触发,否则异步线程可能读到未提交的旧状态,导致回调数据错误或漏回调 + Long taskId = task.getId(); + if (TransactionSynchronizationManager.isSynchronizationActive()) { + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { + @Override + public void afterCommit() { + wmsIncomingInspectionTaskCallbackService.processAsync(taskId, (short) 0); + } + }); + } else { + wmsIncomingInspectionTaskCallbackService.processAsync(taskId, (short) 0); + } } else { issueTicketControllerService.initiate(task.getId()); } @@ -1241,10 +1256,33 @@ public class IncomingInspectionTaskControllerService { .collect(Collectors.groupingBy(QmsIncomingInspectionTaskRecordItemData::getItemId)); } - // 5. 组装返回VO + // 5. 批量查询所有样本数据涉及的文件,避免在组装时逐条查询(N+1) + List allImageIds = itemDataMap.values().stream() + .flatMap(List::stream) + .map(QmsIncomingInspectionTaskRecordItemData::getImageIds) + .filter(StrUtil::isNotBlank) + .flatMap(ids -> Arrays.stream(StrUtil.splitToLong(ids, ",")).boxed()) + .distinct() + .toList(); + Map fileMap = Map.of(); + if (!allImageIds.isEmpty()) { + fileMap = fileUploadRecordService.lambdaQuery() + .in(FileUploadRecord::getId, allImageIds) + .list() + .stream() + .collect(Collectors.toMap(FileUploadRecord::getId, + file -> new FileUploadVO() + .setId(file.getId()) + .setFileName(file.getFileName()) + .setUrl(file.getUrl()) + )); + } + + // 6. 组装返回VO Map finalContentMap = contentMap; Map finalStandardItemMap = standardItemMap; Map> finalItemDataMap = itemDataMap; + Map finalFileMap = fileMap; return items.stream().map(item -> { QmsIncomingInspectionTaskRecordItemDetailVO vo = new QmsIncomingInspectionTaskRecordItemDetailVO(); vo.setId(item.getId()); @@ -1287,15 +1325,10 @@ public class IncomingInspectionTaskControllerService { dataVO.setQualified(data.getQualified()); if (StrUtil.isNotBlank(data.getImageIds())) { dataVO.setImages( - fileUploadRecordService.lambdaQuery() - .in(FileUploadRecord::getId, Arrays.stream(StrUtil.splitToLong(data.getImageIds(), ",")).boxed().toList()) - .list() - .stream() - .map(file -> new FileUploadVO() - .setId(file.getId()) - .setFileName(file.getFileName()) - .setUrl(file.getUrl()) - ) + Arrays.stream(StrUtil.splitToLong(data.getImageIds(), ",")) + .boxed() + .map(finalFileMap::get) + .filter(Objects::nonNull) .collect(Collectors.toList()) ); } diff --git a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/WmsIncomingInspectionTaskCallbackService.java b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/WmsIncomingInspectionTaskCallbackService.java index 5e9592cd..b4057c10 100644 --- a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/WmsIncomingInspectionTaskCallbackService.java +++ b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/WmsIncomingInspectionTaskCallbackService.java @@ -101,18 +101,13 @@ public class WmsIncomingInspectionTaskCallbackService { ); } - boolean callbackResult = true; + // 注意:本方法不可被 @Transactional 包裹,否则下面"标记失败"的更新会随异常一起回滚,导致失败状态丢失 try { wmsApiService.post(incomingUrl, qo, "来料检验任务回调WMS"); + updateCallbackResult(taskVO.getId(), true); } catch (Exception e) { - callbackResult = false; + updateCallbackResult(taskVO.getId(), false); throw new NflgException(STATE.BusinessError, "调用WMS接口失败:" + e.getMessage()); - } finally { - incomingInspectionTaskService.lambdaUpdate() - .eq(QmsIncomingInspectionTask::getId, taskVO.getId()) - .ne(QmsIncomingInspectionTask::getCallbackResult, true) - .set(QmsIncomingInspectionTask::getCallbackResult, callbackResult) - .update(); } } @@ -149,7 +144,7 @@ public class WmsIncomingInspectionTaskCallbackService { .toList() ); - boolean callbackResult = true; + // 注意:本方法不可被 @Transactional 包裹,否则下面"标记失败"的更新会随异常一起回滚,导致失败状态丢失 try { // wmsApiService.post(inventoryUrl, qo, "库存检验任务回调WMS"); inventoryService.lambdaUpdate() @@ -160,18 +155,24 @@ public class WmsIncomingInspectionTaskCallbackService { .eq(WmsInventory::getWarehouseNo, taskVO.getWarehouse()) .eq(WmsInventory::getBinLocation, taskVO.getStorageLocation()) .update(); + updateCallbackResult(taskVO.getId(), true); } catch (Exception e) { - callbackResult = false; + updateCallbackResult(taskVO.getId(), false); throw new NflgException(STATE.BusinessError, "调用WMS接口失败:" + e.getMessage()); - } finally { - incomingInspectionTaskService.lambdaUpdate() - .eq(QmsIncomingInspectionTask::getId, taskVO.getId()) - .ne(QmsIncomingInspectionTask::getCallbackResult, true) - .set(QmsIncomingInspectionTask::getCallbackResult, callbackResult) - .update(); } } + /** + * 更新回调结果标记(仅当原结果非成功时才更新,避免覆盖已成功的状态) + */ + private void updateCallbackResult(Long taskId, boolean callbackResult) { + incomingInspectionTaskService.lambdaUpdate() + .eq(QmsIncomingInspectionTask::getId, taskId) + .ne(QmsIncomingInspectionTask::getCallbackResult, true) + .set(QmsIncomingInspectionTask::getCallbackResult, callbackResult) + .update(); + } + /** * WMS系统来料检验任务回调 * @param taskId 来料检验任务ID @@ -189,7 +190,7 @@ public class WmsIncomingInspectionTaskCallbackService { public void process(Long taskId) { QmsIncomingInspectionTaskVO taskVO = incomingInspectionTaskService.getDetail(taskId); VUtil.trueThrowBusinessError(Objects.equals(taskVO.getCallbackResult(), true)).throwMessage("请勿重复回调"); - VUtil.trueThrowBusinessError(taskVO.getInspectionStatus() != 2).throwMessage("来料检验任务状态不允许回调"); + VUtil.trueThrowBusinessError(!Objects.equals(taskVO.getInspectionStatus(),(short)2)).throwMessage("来料检验任务状态不允许回调"); if (taskVO.getInspectionResult()) { process(taskVO, (short) 0); } else { @@ -231,6 +232,7 @@ public class WmsIncomingInspectionTaskCallbackService { private void process(Long taskId, Short processingResult) { QmsIncomingInspectionTaskVO taskVO = incomingInspectionTaskService.getDetail(taskId); VUtil.trueThrowBusinessError(Objects.equals(taskVO.getCallbackResult(), true)).throwMessage("请勿重复回调"); + VUtil.trueThrowBusinessError(!Objects.equals(taskVO.getInspectionStatus(),(short)2)).throwMessage("来料检验任务状态不允许回调"); process(taskVO, processingResult); } }