diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/service/processor/BatchProcessor.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/service/processor/BatchProcessor.java index f45cb15..9e82c09 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/service/processor/BatchProcessor.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/service/processor/BatchProcessor.java @@ -116,8 +116,7 @@ public class BatchProcessor { * 批量处理分配操作 */ @Transactional(rollbackFor = Exception.class) - public void batchAllocate(Map inventoryUpdateMap, Map pickDetailUpdateMap, List createToTask) { - + public boolean batchAllocate(Map inventoryUpdateMap, Map pickDetailUpdateMap, List createToTask) { List updateToInventory = new ArrayList<>(inventoryUpdateMap.values()); List updateToPickDetail = new ArrayList<>(pickDetailUpdateMap.values()); if (CollectionUtils.isNotEmpty(updateToInventory)) { @@ -128,7 +127,9 @@ public class BatchProcessor { } if (CollectionUtils.isNotEmpty(createToTask)) { batchUtil.saveBatchTask(createToTask); + return true; } + return false; } /** diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/inventory/controller/InventoryController.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/inventory/controller/InventoryController.java index 58fd69c..2e0f786 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/inventory/controller/InventoryController.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/inventory/controller/InventoryController.java @@ -154,9 +154,9 @@ public class InventoryController extends JeecgController processedCache = new ConcurrentHashMap<>(); - - // 缓存最大大小,防止内存溢出 - private static final int MAX_CACHE_SIZE = 1000; - @Override public void execute(JobExecutionContext jobExecutionContext) { //1.获取未拣货完成的出库明细 @@ -176,7 +167,10 @@ public class AllocatePickDetailJob implements Job { // 检查是否需要分配 if (shouldAllocatePickDetail(executingTaskKeys, currentKey)) { - allocatePickDetail(detail); + boolean allocated = allocatePickDetail(detail); + if (allocated) { + return true; + } } } return false; // 未分配任何明细 @@ -221,7 +215,10 @@ public class AllocatePickDetailJob implements Job { if (isAlreadyAssigned(detail.getStatus())) { continue; } - allocatePickDetail(detail); + boolean allocated = allocatePickDetail(detail); + if (allocated) { + return; + } } } @@ -235,45 +232,13 @@ public class AllocatePickDetailJob implements Job { return PickStatusEnum.ASSIGNED.getValue().equals(status); } - private void allocatePickDetail(PickDetail pickDetail) { - // 分配单个出库明细 - List resultMsg; + private boolean allocatePickDetail(PickDetail pickDetail) { try { - // 每次只分配一个出库单明细 - resultMsg = pickService.allocatePickDetail(pickDetail); - if (CollectionUtils.isNotEmpty(resultMsg)) { - // 生成缓存键 - String cacheKey = generateCacheKey(resultMsg); - - // 检查是否已经处理过相同的内容 - if (!processedCache.containsKey(cacheKey)) { - // 新内容,记录日志 - baseCommonService.addLog("出库明细分配:" + "\n" + cacheKey, CommonConstant.LOG_TYPE_2, CommonConstant.OPERATE_TYPE_1); - - // 添加到缓存 - processedCache.put(cacheKey, true); - - // 控制缓存大小 - if (processedCache.size() > MAX_CACHE_SIZE) { - processedCache.clear(); - } - } - } + return pickService.allocatePickDetail(pickDetail); } catch (Exception e) { - resultMsg = List.of(e.getMessage()); - log.error("分配出库明细失败,ID: {}, 错误: {}", pickDetail.getId(), resultMsg); + log.error("分配出库明细失败,ID: {}, 错误: {}", pickDetail.getId(), e.getMessage()); + return false; } } - - /** - * 生成缓存键 - 基于分配结果生成唯一标识 - */ - private String generateCacheKey(List resultMsg) { - // 对结果进行排序后拼接,确保相同内容生成相同键 - return resultMsg.stream() - .filter(Objects::nonNull) - .sorted() - .collect(Collectors.joining("\n")); - } } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/entity/Asn.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/entity/Asn.java index ab0797c..2ab58fb 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/entity/Asn.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/receive/entity/Asn.java @@ -52,10 +52,10 @@ public class Asn implements Serializable { @Schema(description = "系统单号") private java.lang.String orderNo; /** - * 外部单号 + * 赛意单号 */ - @Excel(name = "外部单号", width = 15) - @Schema(description = "外部单号") + @Excel(name = "赛意单号", width = 15) + @Schema(description = "赛意单号") private java.lang.String thirdOrderNo; /** * 任务号 diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/IPickService.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/IPickService.java index 04d9c84..8f3f0f4 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/IPickService.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/IPickService.java @@ -59,7 +59,7 @@ public interface IPickService extends IService { * * @param pickDetail 出库单明细 */ - List allocatePickDetail(PickDetail pickDetail); + boolean allocatePickDetail(PickDetail pickDetail); /** * 取消分配 diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/impl/PickServiceImpl.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/impl/PickServiceImpl.java index c9302b3..c439e61 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/impl/PickServiceImpl.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/impl/PickServiceImpl.java @@ -155,7 +155,7 @@ public class PickServiceImpl extends ServiceImpl implements IP } @Override - public List allocatePickDetail(PickDetail pickDetail) { + public boolean allocatePickDetail(PickDetail pickDetail) { return allocateProcessor.allocatePickDetail(pickDetail); } diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/processor/AllocateProcessor.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/processor/AllocateProcessor.java index 91fa0cd..fc1e7c2 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/processor/AllocateProcessor.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/shipping/service/processor/AllocateProcessor.java @@ -31,11 +31,14 @@ import org.cpte.modules.shipping.vo.InventoryScore; import org.cpte.modules.shipping.vo.ItemGroupKey; import org.cpte.modules.utils.BigDecimalUtil; import org.cpte.modules.utils.RedisDistributedLockUtil; +import org.jeecg.common.constant.CommonConstant; +import org.jeecg.modules.base.service.BaseCommonService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; /** @@ -81,6 +84,9 @@ public class AllocateProcessor { @Autowired private IInventoryLogService inventoryLogService; + @Autowired + private BaseCommonService baseCommonService; + @Autowired private ScanTrayProcessor scanTrayProcessor; @@ -93,6 +99,12 @@ public class AllocateProcessor { @Autowired private RedisDistributedLockUtil redissonLock; + // 使用 ConcurrentHashMap 缓存已处理的结果 + private static final Map processedCache = new ConcurrentHashMap<>(); + + // 缓存最大大小,防止内存溢出 + private static final int MAX_CACHE_SIZE = 1000; + /** * 分配出库单 @@ -108,7 +120,7 @@ public class AllocateProcessor { AllocationData data = prepareAllocationData(pickIds); //2.验证库存 - if (!validateInventory(data, errorMsgSet)) { + if (validateInventory(data, errorMsgSet)) { return new ArrayList<>(errorMsgSet); } @@ -139,7 +151,7 @@ public class AllocateProcessor { * @param pickDetail 出库单明细 * @return 错误信息 */ - public List allocatePickDetail(PickDetail pickDetail) { + public boolean allocatePickDetail(PickDetail pickDetail) { // 错误信息去重(LinkedHashSet保证顺序和唯一) Set errorMsgSet = new LinkedHashSet<>(); @@ -147,8 +159,8 @@ public class AllocateProcessor { AllocationData data = prepareAllocationDetailData(pickDetail); //2.验证库存 - if (!validateInventory(data, errorMsgSet)) { - return new ArrayList<>(errorMsgSet); + if (validateInventory(data, errorMsgSet)) { + return false; } //3.创建数据结构 @@ -164,12 +176,12 @@ public class AllocateProcessor { moveTask(createToTask, movePoints); //6.批量操作 - batchProcessor.batchAllocate(inventoryUpdateMap, pickDetailUpdateMap, createToTask); + boolean result = batchProcessor.batchAllocate(inventoryUpdateMap, pickDetailUpdateMap, createToTask); //7.刷新出库单 refreshData(data); - return new ArrayList<>(errorMsgSet); + return result; } @@ -212,8 +224,8 @@ public class AllocateProcessor { List itemKeyIds = list.stream().map(Inventory::getItemKeyId).distinct().toList(); List iks = itemKeyMapper.selectByIds(itemKeyIds); if (CollectionUtils.isNotEmpty(itemKeys)) { - for (ItemKey ik : iks){ - if(!itemKeys.contains(ik)){ + for (ItemKey ik : iks) { + if (!itemKeys.contains(ik)) { itemKeys.add(ik); } } @@ -223,7 +235,7 @@ public class AllocateProcessor { } } } - if(CollectionUtils.isNotEmpty(itemKeys)){ + if (CollectionUtils.isNotEmpty(itemKeys)) { //根据物料属性分组 Map itemGroupKey = itemKeys.stream() .collect(Collectors.toMap( @@ -306,8 +318,8 @@ public class AllocateProcessor { List itemKeyIds = list.stream().map(Inventory::getItemKeyId).distinct().toList(); List iks = itemKeyMapper.selectByIds(itemKeyIds); if (CollectionUtils.isNotEmpty(itemKeys)) { - for (ItemKey ik : iks){ - if(!itemKeys.contains(ik)){ + for (ItemKey ik : iks) { + if (!itemKeys.contains(ik)) { itemKeys.add(ik); } } @@ -316,7 +328,7 @@ public class AllocateProcessor { } } } - if(CollectionUtils.isNotEmpty(itemKeys)){ + if (CollectionUtils.isNotEmpty(itemKeys)) { //根据物料属性分组 Map itemGroupKey = itemKeys.stream() .collect(Collectors.toMap( @@ -373,9 +385,11 @@ public class AllocateProcessor { if (CollectionUtils.isEmpty(inventories)) { String itemCodes = data.getItemMap().values().stream().map(Item::getItemCode).collect(Collectors.joining(",")); errorMsgSet.add("【" + itemCodes + "】物料库存不足"); - return false; + String cacheKey = generateCacheKey(errorMsgSet); + logAndCacheResult(cacheKey); + return true; } - return true; + return false; } /** @@ -465,6 +479,9 @@ public class AllocateProcessor { ); ItemKey itemKey = data.getItemGroupMap().get(groupKey); + if (itemKey == null) { + return new ArrayList<>(); + } return data.getInventoryMap().get(itemKey.getId()); } @@ -482,6 +499,8 @@ public class AllocateProcessor { errorMsgSet.add(String.format("物料【%s】无匹配库存(物料ID:%s,批次:%s,库存状态:%s,仓库:%s)", item.getItemCode(), item.getId(), pickDetail.getPropC1(), pickDetail.getPropC3(), pick.getWhCode())); + String cacheKey = generateCacheKey(errorMsgSet); + logAndCacheResult(cacheKey); } /** @@ -516,7 +535,7 @@ public class AllocateProcessor { Stock stock = stockService.getById(pickDetail.getStockId()); String message = String.format("任务号【%s】,容器【%s】无库存", pick.getNo(), stock.getStockCode()); errorMsgSet.add(message); - return; + logAndCacheResult(message); } //未分配数量 @@ -877,6 +896,7 @@ public class AllocateProcessor { unallocateQty ); errorMsgSet.add(failInfo); + logAndCacheResult(failInfo); } /** @@ -992,4 +1012,35 @@ public class AllocateProcessor { pickDetailService.refreshPick(entry.getValue(), pickDetailMapper.selectByMainId(entry.getKey())); } } + + + /** + * 记录日志并缓存处理结果 + * + * @param cacheKey 缓存键 + */ + private void logAndCacheResult(String cacheKey) { + // 检查是否已经处理过相同的内容 + if (!processedCache.containsKey(cacheKey)) { + // 新内容,记录日志 + // 注意:这里需要注入baseCommonService + baseCommonService.addLog("出库明细分配:" + "\n" + cacheKey, CommonConstant.LOG_TYPE_2, CommonConstant.OPERATE_TYPE_1); + + // 添加到缓存 + processedCache.put(cacheKey, true); + + // 控制缓存大小 + if (processedCache.size() > MAX_CACHE_SIZE) { + processedCache.clear(); + } + } + } + + private String generateCacheKey(Collection resultMsg) { + // 对结果进行排序后拼接,确保相同内容生成相同键 + return resultMsg.stream() + .filter(Objects::nonNull) + .sorted() + .collect(Collectors.joining("\n")); + } }