diff --git a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/external/MaterialController.java b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/external/MaterialController.java index 45d206e8..b8c82fef 100644 --- a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/external/MaterialController.java +++ b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/external/MaterialController.java @@ -16,6 +16,7 @@ import org.checkerframework.common.reflection.qual.GetClass; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import java.util.LinkedHashMap; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -81,10 +82,19 @@ public class MaterialController extends BaseController { public ApiResult> getMaterialInspectionCycle() { return ApiResult.success( qcMaterialService.lambdaQuery() - .select(QmsQcMaterial::getMaterialNo, QmsQcMaterial::getInspectionCycle1, QmsQcMaterial::getInspectionCycle2, QmsQcMaterial::getInspectionCycle3) + .select(QmsQcMaterial::getId, QmsQcMaterial::getMaterialNo, QmsQcMaterial::getInspectionCycle1, QmsQcMaterial::getInspectionCycle2, QmsQcMaterial::getInspectionCycle3) + .orderByDesc(QmsQcMaterial::getId) .list() .stream() - .map(qcMaterial -> new MaterialInspectionCycleVO(qcMaterial.getMaterialNo(), qcMaterial.getInspectionCycle1(), qcMaterial.getInspectionCycle2(), qcMaterial.getInspectionCycle3())) + .filter(qcMaterial -> qcMaterial.getMaterialNo() != null) + .collect(Collectors.toMap( + QmsQcMaterial::getMaterialNo, + qcMaterial -> new MaterialInspectionCycleVO(qcMaterial.getMaterialNo(), qcMaterial.getInspectionCycle1(), qcMaterial.getInspectionCycle2(), qcMaterial.getInspectionCycle3()), + (first, ignored) -> first, + LinkedHashMap::new + )) + .values() + .stream() .toList() ); } diff --git a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/schedule/InventoryExpirationInspectionScheduledTask.java b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/schedule/InventoryExpirationInspectionScheduledTask.java index 6f502eb6..662d672c 100644 --- a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/schedule/InventoryExpirationInspectionScheduledTask.java +++ b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/schedule/InventoryExpirationInspectionScheduledTask.java @@ -2,8 +2,11 @@ package com.nflg.wms.admin.schedule; import com.nflg.wms.admin.service.QmsService; import com.nflg.wms.common.pojo.qo.InventoryDetectionApplyQO; +import com.nflg.wms.common.pojo.vo.MaterialInspectionCycleVO; +import com.nflg.wms.repository.entity.QmsIncomingInspectionTask; import com.nflg.wms.repository.entity.QmsQcMaterial; import com.nflg.wms.repository.entity.WmsInventory; +import com.nflg.wms.repository.service.IQmsIncomingInspectionTaskService; import com.nflg.wms.repository.service.IQmsQcMaterialService; import com.nflg.wms.repository.service.IWmsInventoryService; import jakarta.annotation.Resource; @@ -14,11 +17,11 @@ import org.springframework.stereotype.Component; import java.math.BigDecimal; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; -import java.util.function.Function; import java.util.stream.Collectors; /** @@ -28,12 +31,18 @@ import java.util.stream.Collectors; @Component public class InventoryExpirationInspectionScheduledTask { + private static final Short INSPECTION_STATUS_FINISHED = 2; + private static final Short INVENTORY_DETECTION_STATUS_CHECKING = 1; + @Resource private IWmsInventoryService inventoryService; @Resource private IQmsQcMaterialService qcMaterialService; + @Resource + private IQmsIncomingInspectionTaskService incomingInspectionTaskService; + @Resource private QmsService qmsService; @@ -46,7 +55,6 @@ public class InventoryExpirationInspectionScheduledTask { List inventories = inventoryService.lambdaQuery() .gt(WmsInventory::getNum, BigDecimal.ZERO) .isNotNull(WmsInventory::getCreateTime) - .eq(WmsInventory::getDetectionStatus, (short) 0) .list(); if (inventories.isEmpty()) { log.info("库存物料过期检测任务执行完成:无待检查库存"); @@ -62,25 +70,57 @@ public class InventoryExpirationInspectionScheduledTask { return; } - Map materialMap = qcMaterialService.lambdaQuery() + Map cycleMap = qmsService.getMaterialInspectionCycle().stream() + .filter(cycle -> Objects.nonNull(cycle.getMaterialNo())) + .collect(Collectors.toMap(MaterialInspectionCycleVO::getMaterialNo, cycle -> cycle, (first, ignored) -> first)); + + Map> materialIdMap = qcMaterialService.lambdaQuery() + .select(QmsQcMaterial::getId, QmsQcMaterial::getMaterialNo) .in(QmsQcMaterial::getMaterialNo, materialNos) - .orderByDesc(QmsQcMaterial::getId) .list() .stream() - .collect(Collectors.toMap(QmsQcMaterial::getMaterialNo, Function.identity(), (first, ignored) -> first)); + .filter(material -> Objects.nonNull(material.getId()) && Objects.nonNull(material.getMaterialNo())) + .collect(Collectors.groupingBy(QmsQcMaterial::getMaterialNo, Collectors.mapping(QmsQcMaterial::getId, Collectors.toList()))); int applied = 0; int skipped = 0; int failed = 0; + Set appliedKeys = new HashSet<>(); for (WmsInventory inventory : inventories) { - QmsQcMaterial material = materialMap.get(inventory.getMaterialNo()); - if (Objects.isNull(material) || Objects.isNull(material.getValidityPeriod())) { + String inspectionKey = buildInspectionKey(inventory); + if (appliedKeys.contains(inspectionKey) + || Objects.equals(inventory.getDetectionStatus(), INVENTORY_DETECTION_STATUS_CHECKING)) { skipped++; continue; } - LocalDateTime expiredTime = inventory.getCreateTime().plusMonths(material.getValidityPeriod()); - if (!expiredTime.isBefore(now)) { + MaterialInspectionCycleVO cycle = cycleMap.get(inventory.getMaterialNo()); + List materialIds = materialIdMap.get(inventory.getMaterialNo()); + if (Objects.isNull(cycle) || Objects.isNull(materialIds) || materialIds.isEmpty()) { + skipped++; + continue; + } + + List historyTasks = getInventoryInspectionTasks(inventory, materialIds); + if (hasUnfinishedTask(historyTasks)) { + skipped++; + continue; + } + + long finishedCount = historyTasks.stream() + .filter(this::isFinishedTask) + .count(); + Integer cycleMonths = getCycleMonths(cycle, finishedCount); + if (Objects.isNull(cycleMonths) || cycleMonths <= 0) { + skipped++; + continue; + } + + LocalDateTime baseTime = getLastFinishedTime(historyTasks); + if (Objects.isNull(baseTime)) { + baseTime = inventory.getCreateTime(); + } + if (!baseTime.plusMonths(cycleMonths).isBefore(now)) { skipped++; continue; } @@ -91,6 +131,7 @@ public class InventoryExpirationInspectionScheduledTask { request.setStorageDays(Math.max(1, (int) ChronoUnit.DAYS.between(inventory.getCreateTime(), now))); try { qmsService.pushInventoryInspection(request); + appliedKeys.add(inspectionKey); applied++; } catch (Exception ex) { failed++; @@ -100,4 +141,50 @@ public class InventoryExpirationInspectionScheduledTask { log.info("库存物料过期检测任务执行完成:检查库存数={},发起检测数={},跳过数={},失败数={}", inventories.size(), applied, skipped, failed); } + + private List getInventoryInspectionTasks(WmsInventory inventory, List materialIds) { + return incomingInspectionTaskService.lambdaQuery() + .in(QmsIncomingInspectionTask::getMaterialId, materialIds) + .eq(QmsIncomingInspectionTask::getInspectionType, 1) + .eq(QmsIncomingInspectionTask::getDataType, 1) + .eq(QmsIncomingInspectionTask::getFactory, inventory.getFactoryNo()) + .eq(QmsIncomingInspectionTask::getWarehouse, inventory.getWarehouseNo()) + .eq(QmsIncomingInspectionTask::getStorageLocation, inventory.getBinLocation()) + .list(); + } + + private boolean hasUnfinishedTask(List historyTasks) { + return historyTasks.stream().anyMatch(task -> !isFinishedTask(task)); + } + + private boolean isFinishedTask(QmsIncomingInspectionTask task) { + return Objects.equals(task.getInspectionStatus(), INSPECTION_STATUS_FINISHED); + } + + private Integer getCycleMonths(MaterialInspectionCycleVO cycle, long finishedCount) { + if (finishedCount <= 0) { + return cycle.getInspectionCycle1(); + } + if (finishedCount == 1) { + return cycle.getInspectionCycle2(); + } + return cycle.getInspectionCycle3(); + } + + private LocalDateTime getLastFinishedTime(List historyTasks) { + return historyTasks.stream() + .filter(this::isFinishedTask) + .map(QmsIncomingInspectionTask::getInspectionFinishTime) + .filter(Objects::nonNull) + .max(LocalDateTime::compareTo) + .orElse(null); + } + + private String buildInspectionKey(WmsInventory inventory) { + return String.join("|", + String.valueOf(inventory.getMaterialNo()), + String.valueOf(inventory.getFactoryNo()), + String.valueOf(inventory.getWarehouseNo()), + String.valueOf(inventory.getBinLocation())); + } } diff --git a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/service/QmsService.java b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/service/QmsService.java index df030248..31b64c8d 100644 --- a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/service/QmsService.java +++ b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/service/QmsService.java @@ -5,6 +5,7 @@ import cn.hutool.json.JSONUtil; import com.nflg.wms.common.pojo.ApiResult; import com.nflg.wms.common.pojo.qo.*; import com.nflg.wms.common.pojo.vo.ExemptMaterialCheckVO; +import com.nflg.wms.common.pojo.vo.MaterialInspectionCycleVO; import com.nflg.wms.common.util.VUtil; import com.nflg.wms.repository.entity.WmsInProduceOrderItem; import com.nflg.wms.repository.entity.WmsInventory; @@ -68,6 +69,9 @@ public class QmsService { @Value("${qms.iqc.inventory.apply.url}") private String iqcInventoryApplyUrl; + @Value("${qms.material.inspectionCycle.url:/external/material/getMaterialInspectionCycle}") + private String materialInspectionCycleUrl; + @Value("${qms.pdi.apply.url}") private String pdiApplyUrl; @@ -148,6 +152,26 @@ public class QmsService { return !Objects.equals(response.getBody().getResult(), false); } + public List getMaterialInspectionCycle() { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + HttpEntity requestEntity = new HttpEntity<>(headers); + + ResponseEntity>> response = restTemplate.exchange( + qmsHost + materialInspectionCycleUrl, + HttpMethod.GET, + requestEntity, + new ParameterizedTypeReference>>() { + } + ); + + ApiResult> body = response.getBody(); + log.info("获取物料质检周期结果:{},{}", response.getStatusCode().value(), JSONUtil.toJsonStr(body)); + VUtil.trueThrowBusinessError(Objects.isNull(body) || body.getCode() != 200) + .throwMessage("获取物料质检周期失败:" + (Objects.isNull(body) ? "无响应内容" : body.getMessage())); + return Objects.isNull(body.getResult()) ? List.of() : body.getResult(); + } + public void pushInventoryInspection(InventoryDetectionApplyQO request) { WmsInventory inventory = inventoryService.getById(request.getInventoryId()); VUtil.trueThrowBusinessError(Objects.isNull(inventory)).throwMessage("未找到对应库存");