From 8f5098c98c2e91ee988f3487fa8edafcbe3f1409 Mon Sep 17 00:00:00 2001 From: Joshi <3040996759@qq.com> Date: Sat, 20 Dec 2025 16:31:24 +0800 Subject: [PATCH 1/3] =?UTF-8?q?feat(wms):=20=E4=BC=98=E5=8C=96=E5=BA=93?= =?UTF-8?q?=E4=BD=8D=E6=8B=86=E5=88=86=E4=B8=8E=E5=90=88=E5=B9=B6=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 改进拆分逻辑以支持子库位复活和新建 - 实现更精确的子库位编码生成规则 - 完善合并时对子库位占用状态的检查 - 修复拆分ID去重问题,确保数据一致性 - 调整异常提示信息,提高可读性 --- .../impl/WmsActualWarehouseServiceImpl.java | 465 ++++++++---------- 1 file changed, 208 insertions(+), 257 deletions(-) diff --git a/klp-wms/src/main/java/com/klp/service/impl/WmsActualWarehouseServiceImpl.java b/klp-wms/src/main/java/com/klp/service/impl/WmsActualWarehouseServiceImpl.java index 9de5a724..4312ea4f 100644 --- a/klp-wms/src/main/java/com/klp/service/impl/WmsActualWarehouseServiceImpl.java +++ b/klp-wms/src/main/java/com/klp/service/impl/WmsActualWarehouseServiceImpl.java @@ -434,23 +434,107 @@ public class WmsActualWarehouseServiceImpl implements IWmsActualWarehouseService } int splitType = Optional.ofNullable(bo.getSplitType()).orElse(0); - List splitIds = Optional.ofNullable(bo.getSplitIds()).orElse(new ArrayList<>()); + List Ids = Optional.ofNullable(bo.getSplitIds()).orElse(new ArrayList<>()); + + // 合并所有待拆分的ID + Set splitIds = new HashSet<>(); + splitIds.addAll(Ids); if (splitIds.isEmpty()) { throw new ServiceException("待拆分库位ID列表不能为空"); } - // 根据列标识查询该列的所有三级库位 + // 根据列标识查询该列的所有库位(第一层和第二层) List columnLocations = baseMapper.selectList(Wrappers.lambdaQuery() .like(WmsActualWarehouse::getActualWarehouseCode, columnFlag) .eq(WmsActualWarehouse::getDelFlag, 0) - .eq(WmsActualWarehouse::getActualWarehouseType, 3) + .eq(WmsActualWarehouse::getActualWarehouseType, 3) // 只查询三级库位 .orderByAsc(WmsActualWarehouse::getActualWarehouseCode)); if (CollUtil.isEmpty(columnLocations)) { throw new ServiceException("未找到列标识为 " + columnFlag + " 的库位"); } + // 检查是否已经有子库位存在(包括被删除的) + boolean hasExistingChildren = false; + for (WmsActualWarehouse location : columnLocations) { + List existingChildren = baseMapper.selectList(Wrappers.lambdaQuery() + .eq(WmsActualWarehouse::getParentId, location.getActualWarehouseId()) + .eq(WmsActualWarehouse::getActualWarehouseType, 4)); // 四级子库位 + if (CollUtil.isNotEmpty(existingChildren)) { + hasExistingChildren = true; + break; + } + } + + if (hasExistingChildren) { + // 如果已经有子库位,执行复活逻辑 + reviveExistingSubLocations(columnLocations, splitIds, splitType); + } else { + // 如果没有子库位,执行创建逻辑 + createNewSubLocationsWithOriginalLogic(columnLocations, splitIds, splitType, columnFlag); + } + + // 更新该列所有被拆分库位的状态 + for (WmsActualWarehouse location : columnLocations) { + WmsActualWarehouse upd = new WmsActualWarehouse(); + upd.setActualWarehouseId(location.getActualWarehouseId()); + upd.setSplitStatus(1); + upd.setSplitType(splitType); + baseMapper.updateById(upd); + } + } + + /** + * 复活已存在的子库位 + */ + private void reviveExistingSubLocations(List columnLocations, Set splitIds, Integer splitType) { + for (WmsActualWarehouse location : columnLocations) { + boolean isSplitLocation = splitIds.contains(location.getActualWarehouseId()); + + // 查询该库位下所有子库位(包括已删除的) + List allChildren = baseMapper.selectList(Wrappers.lambdaQuery() + .eq(WmsActualWarehouse::getParentId, location.getActualWarehouseId()) + .eq(WmsActualWarehouse::getActualWarehouseType, 4) // 四级子库位 + .orderByAsc(WmsActualWarehouse::getActualWarehouseId)); + + if (CollUtil.isNotEmpty(allChildren)) { + // 根据是否为拆分库位决定需要复活的子库位数量 + int requiredCount = isSplitLocation ? 2 : 1; + + // 复活前N个子库位 + for (int i = 0; i < Math.min(requiredCount, allChildren.size()); i++) { + WmsActualWarehouse child = allChildren.get(i); + if (child.getDelFlag() == 1) { // 只处理已删除的子库位 + WmsActualWarehouse childUpdate = new WmsActualWarehouse(); + childUpdate.setActualWarehouseId(child.getActualWarehouseId()); + childUpdate.setDelFlag(0); + childUpdate.setSplitStatus(1); + childUpdate.setSplitType(splitType); + baseMapper.updateById(childUpdate); + } + } + + // 如果子库位数量超过需要的数量,隐藏多余的 + if (allChildren.size() > requiredCount) { + for (int i = requiredCount; i < allChildren.size(); i++) { + WmsActualWarehouse child = allChildren.get(i); + if (child.getDelFlag() == 0) { // 只处理未删除的子库位 + WmsActualWarehouse childUpdate = new WmsActualWarehouse(); + childUpdate.setActualWarehouseId(child.getActualWarehouseId()); + childUpdate.setDelFlag(1); + baseMapper.updateById(childUpdate); + } + } + } + } + } + } + + /** + * 使用逻辑创建新的子库位 + */ + private void createNewSubLocationsWithOriginalLogic(List columnLocations, Set splitIds, Integer splitType, String columnFlag) { // 分离需要拆分的库位和剩余库位 List splitLocations = new ArrayList<>(); List remainingLocations = new ArrayList<>(); @@ -463,306 +547,173 @@ public class WmsActualWarehouseServiceImpl implements IWmsActualWarehouseService } } - // 存储需要插入/更新的子库位 + // 第一步:先创建所有子库位(不设置编码) List toInsert = new ArrayList<>(); - List toUpdate = new ArrayList<>(); // 1. 处理需要拆分的库位(每个拆分为2个子库位) for (WmsActualWarehouse location : splitLocations) { - // 先查询该父库位下是否存在已逻辑删除的子库位(合并后保留的) - List existingChildren = baseMapper.selectList(Wrappers.lambdaQuery() - .eq(WmsActualWarehouse::getParentId, location.getActualWarehouseId()) - .eq(WmsActualWarehouse::getActualWarehouseType, 4) - .eq(WmsActualWarehouse::getDelFlag, 1)); // 查询已逻辑删除的子库位 + // 生成第一个子库位 + WmsActualWarehouse subLocation1 = new WmsActualWarehouse(); + subLocation1.setParentId(location.getActualWarehouseId()); + subLocation1.setActualWarehouseType(4L); // 四级节点 + subLocation1.setSortNo(Optional.ofNullable(location.getSortNo()).orElse(0L)); + subLocation1.setIsEnabled(1); + subLocation1.setSplitStatus(1); + subLocation1.setSplitType(splitType); + toInsert.add(subLocation1); - if (CollUtil.isNotEmpty(existingChildren) && existingChildren.size() == 2) { - // 复用原有子库位:恢复启用状态,更新拆分类型 - for (WmsActualWarehouse child : existingChildren) { - child.setDelFlag(0); // 恢复未删除 - child.setSplitStatus(1); - child.setSplitType(splitType); - toUpdate.add(child); - } - } else { - // 无原有子库位,新建2个子库位(暂不设置编码) - WmsActualWarehouse sub1 = createSubLocation(location, splitType); - WmsActualWarehouse sub2 = createSubLocation(location, splitType); - toInsert.add(sub1); - toInsert.add(sub2); - } + // 生成第二个子库位 + WmsActualWarehouse subLocation2 = new WmsActualWarehouse(); + subLocation2.setParentId(location.getActualWarehouseId()); + subLocation2.setActualWarehouseType(4L); // 四级节点 + subLocation2.setSortNo(Optional.ofNullable(location.getSortNo()).orElse(0L)); + subLocation2.setIsEnabled(1); + subLocation2.setSplitStatus(1); + subLocation2.setSplitType(splitType); + toInsert.add(subLocation2); } - // 2. 处理剩余库位(每个拆分为1个子库位) + // 2. 处理剩余库位(每个拆分为1个子库位,保持原层级) for (WmsActualWarehouse remainingLocation : remainingLocations) { - // 先查询是否存在已逻辑删除的子库位 - List existingChildren = baseMapper.selectList(Wrappers.lambdaQuery() - .eq(WmsActualWarehouse::getParentId, remainingLocation.getActualWarehouseId()) - .eq(WmsActualWarehouse::getActualWarehouseType, 4) - .eq(WmsActualWarehouse::getDelFlag, 1)); - - if (CollUtil.isNotEmpty(existingChildren)) { - // 复用原有子库位 - WmsActualWarehouse child = existingChildren.get(0); - child.setDelFlag(0); - child.setIsEnabled(1); - child.setSplitStatus(1); - child.setSplitType(splitType); - toUpdate.add(child); - } else { - // 新建子库位 - WmsActualWarehouse sub = createSubLocation(remainingLocation, splitType); - toInsert.add(sub); - } + // 生成剩余库位的子库位 + WmsActualWarehouse remainingSubLocation = new WmsActualWarehouse(); + remainingSubLocation.setParentId(remainingLocation.getActualWarehouseId()); + remainingSubLocation.setActualWarehouseType(4L); // 四级节点 + remainingSubLocation.setSortNo(Optional.ofNullable(remainingLocation.getSortNo()).orElse(0L)); + remainingSubLocation.setIsEnabled(1); + remainingSubLocation.setSplitStatus(1); + remainingSubLocation.setSplitType(splitType); + toInsert.add(remainingSubLocation); } // 3. 验证总数 - int expectedSplitSub = splitLocations.size() * 2; - int expectedRemainingSub = remainingLocations.size() * 1; - int expectedTotal = expectedSplitSub + expectedRemainingSub; - // 实际总数 = 新增数 + 复用数 - int actualTotal = toInsert.size() + toUpdate.size(); + int expectedSplitSubLocations = splitLocations.size() * 2; + int expectedRemainingSubLocations = remainingLocations.size() * 1; + int expectedTotalSubLocations = expectedSplitSubLocations + expectedRemainingSubLocations; + int actualTotalSubLocations = toInsert.size(); - if (actualTotal != expectedTotal) { + if (actualTotalSubLocations != expectedTotalSubLocations) { throw new ServiceException(String.format( - "子库位数量不匹配,期望%d个,实际新增%d个+复用%d个=%d个", - expectedTotal, toInsert.size(), toUpdate.size(), actualTotal)); + "子库位生成数量不匹配,期望%d个(拆分库位:%d个→%d个,剩余库位:%d个→%d个),实际生成%d个", + expectedTotalSubLocations, + splitLocations.size(), expectedSplitSubLocations, + remainingLocations.size(), expectedRemainingSubLocations, + actualTotalSubLocations + )); } - // 4. 批量插入新子库位 + // 4. 批量插入子库位(先插入获取ID) if (!toInsert.isEmpty()) { - boolean insertOk = baseMapper.insertBatch(toInsert); - if (!insertOk) { + boolean ok = baseMapper.insertBatch(toInsert); + if (!ok) { throw new ServiceException("新增子库位失败"); } } - // 5. 批量更新复用的子库位(恢复状态) + // 第二步:重新生成编码 + String prefix = columnFlag; + List toUpdate = new ArrayList<>(); + + // 1. 先把所有子库位按父库位排序 + List sortedSubLocations = new ArrayList<>(toInsert); + sortedSubLocations.sort((a, b) -> { + // 按父库位在原列中的顺序排序 + Long parentA = a.getParentId(); + Long parentB = b.getParentId(); + int indexA = columnLocations.stream().map(WmsActualWarehouse::getActualWarehouseId).collect(Collectors.toList()).indexOf(parentA); + int indexB = columnLocations.stream().map(WmsActualWarehouse::getActualWarehouseId).collect(Collectors.toList()).indexOf(parentB); + return Integer.compare(indexA, indexB); + }); + + // 2. 遍历排序后的子库位,每2个为一组生成编码(序号递增,后缀固定1、2) + for (int i = 0; i < sortedSubLocations.size(); i++) { + WmsActualWarehouse sub = sortedSubLocations.get(i); + int sequenceNum = (i / 2) + 1; // 每2个子库位对应一个序号(0→1,1→1,2→2,3→2...) + int layer = (i % 2) + 1; // 每组内固定1、2后缀(0→1,1→2,2→1,3→2...) + + // 生成编码:前缀-两位序号-层级(如F2B1-X01-1、F2B1-X01-2、F2B1-X02-1...) + String newCode = String.format("%s-X%02d-%d", prefix, sequenceNum, layer); + sub.setActualWarehouseCode(newCode); + sub.setActualWarehouseName(newCode); + toUpdate.add(sub); + } + + // 3. 批量更新编码 if (!toUpdate.isEmpty()) { - for (WmsActualWarehouse child : toUpdate) { - baseMapper.updateById(child); + for (WmsActualWarehouse item : toUpdate) { + baseMapper.updateById(item); } } - - // 6. 统一生成/更新子库位编码(包含新增和复用的) - List allSubLocations = new ArrayList<>(); - allSubLocations.addAll(toInsert); - allSubLocations.addAll(toUpdate); - - if (!allSubLocations.isEmpty()) { - // 按父库位在columnLocations中的顺序排序 - Map parentOrderMap = new HashMap<>(); - for (int i = 0; i < columnLocations.size(); i++) { - parentOrderMap.put(columnLocations.get(i).getActualWarehouseId(), i); - } - - allSubLocations.sort((a, b) -> { - int orderA = parentOrderMap.getOrDefault(a.getParentId(), Integer.MAX_VALUE); - int orderB = parentOrderMap.getOrDefault(b.getParentId(), Integer.MAX_VALUE); - if (orderA != orderB) { - return Integer.compare(orderA, orderB); - } - // 同一父库位下,按层级排序(假设层级1在前,层级2在后) - return Long.compare(a.getActualWarehouseId(), b.getActualWarehouseId()); - }); - - // 生成规范编码 - String prefix = columnFlag; - List codeToUpdate = new ArrayList<>(); - - int sequenceNum = 1; - for (int i = 0; i < allSubLocations.size(); i++) { - WmsActualWarehouse sub = allSubLocations.get(i); - - // 判断是第一层还是第二层 - // 如果是拆分库位的子库位,按顺序分配层级 - // 如果是剩余库位的子库位,保持原层级 - Long parentId = sub.getParentId(); - boolean isFromSplitLocation = splitLocations.stream() - .anyMatch(loc -> loc.getActualWarehouseId().equals(parentId)); - - int layer; - if (isFromSplitLocation) { - // 拆分库位:第一个子库位是层级1,第二个是层级2 - final int currentIndex = i; // 创建一个有效的final变量 - long sameParentCount = allSubLocations.stream() - .filter(s -> s.getParentId().equals(parentId)) - .filter(s -> allSubLocations.indexOf(s) <= currentIndex) - .count(); - layer = (int) ((sameParentCount - 1) % 2) + 1; - } else { - // 剩余库位:保持原层级 - WmsActualWarehouse parent = columnLocations.stream() - .filter(loc -> loc.getActualWarehouseId().equals(parentId)) - .findFirst().orElse(null); - if (parent != null) { - String[] parts = parent.getActualWarehouseCode().split("-"); - layer = parts.length >= 3 ? Integer.parseInt(parts[2]) : 1; - } else { - layer = 1; - } - } - - String newCode = String.format("%s-X%02d-%d", prefix, sequenceNum, layer); - sub.setActualWarehouseCode(newCode); - sub.setActualWarehouseName(newCode); - codeToUpdate.add(sub); - - // 如果是拆分库位的第二个子库位,或者是剩余库位的子库位,序号递增 - if (!isFromSplitLocation || layer == 2) { - sequenceNum++; - } - } - - // 批量更新编码 - for (WmsActualWarehouse sub : codeToUpdate) { - baseMapper.updateById(sub); - } - } - - // 7. 批量更新父库位拆分状态 - List parentUpdates = new ArrayList<>(); - for (WmsActualWarehouse location : columnLocations) { - WmsActualWarehouse upd = new WmsActualWarehouse(); - upd.setActualWarehouseId(location.getActualWarehouseId()); - upd.setSplitStatus(1); - upd.setSplitType(splitType); - parentUpdates.add(upd); - } - - for (WmsActualWarehouse upd : parentUpdates) { - baseMapper.updateById(upd); - } - } - - /** - * 创建子库位基础对象(通用方法) - */ - private WmsActualWarehouse createSubLocation(WmsActualWarehouse parent, int splitType) { - WmsActualWarehouse sub = new WmsActualWarehouse(); - sub.setParentId(parent.getActualWarehouseId()); - sub.setActualWarehouseType(4L); - sub.setSortNo(Optional.ofNullable(parent.getSortNo()).orElse(0L)); - sub.setIsEnabled(1); - sub.setSplitStatus(1); - sub.setSplitType(splitType); - sub.setDelFlag(0); - return sub; } @Override @Transactional(rollbackFor = Exception.class) public void mergeLocations(WmsActualWarehouseSplitBo bo) { - if (bo == null || CollUtil.isEmpty(bo.getLocationIds())) { + if (bo == null) { throw new ServiceException("参数不能为空"); } - // 批量查询父库位 - List parents = baseMapper.selectList(Wrappers.lambdaQuery() - .in(WmsActualWarehouse::getActualWarehouseId, bo.getLocationIds()) - .eq(WmsActualWarehouse::getDelFlag, 0)); - - if (CollUtil.isEmpty(parents)) { - return; + // 获取列标识 + String columnFlag = bo.getColumnFlag(); + if (StringUtils.isBlank(columnFlag)) { + throw new ServiceException("列标识不能为空"); } - // 过滤出已拆分的父库位 - List splitParents = parents.stream() - .filter(p -> Optional.ofNullable(p.getSplitStatus()).orElse(0) == 1) - .collect(Collectors.toList()); + // 根据列标识查询该列的所有三级库位 + List columnLocations = baseMapper.selectList(Wrappers.lambdaQuery() + .like(WmsActualWarehouse::getActualWarehouseCode, columnFlag) + .eq(WmsActualWarehouse::getDelFlag, 0) + .eq(WmsActualWarehouse::getActualWarehouseType, 3) // 只查询三级库位 + .orderByAsc(WmsActualWarehouse::getActualWarehouseCode)); - if (CollUtil.isEmpty(splitParents)) { - return; + if (CollUtil.isEmpty(columnLocations)) { + throw new ServiceException("未找到列标识为 " + columnFlag + " 的库位"); } - // 批量查询所有子库位 - List splitParentIds = splitParents.stream() - .map(WmsActualWarehouse::getActualWarehouseId) - .collect(Collectors.toList()); - - List allChildren = baseMapper.selectList(Wrappers.lambdaQuery() - .in(WmsActualWarehouse::getParentId, splitParentIds) - .eq(WmsActualWarehouse::getActualWarehouseType, 4) - .eq(WmsActualWarehouse::getDelFlag, 0)); - - // 按父ID分组子库位 - Map> childrenByParent = allChildren.stream() - .collect(Collectors.groupingBy(WmsActualWarehouse::getParentId)); - - // 检查是否有被占用的子库位 - List occupiedChildren = allChildren.stream() - .filter(c -> !Objects.equals(c.getIsEnabled(), 1)) - .collect(Collectors.toList()); - - if (!occupiedChildren.isEmpty()) { - // 找到被占用子库位的父库位名称 - Set occupiedParentIds = occupiedChildren.stream() - .map(WmsActualWarehouse::getParentId) - .collect(Collectors.toSet()); - - List occupiedParentCodes = splitParents.stream() - .filter(p -> occupiedParentIds.contains(p.getActualWarehouseId())) - .map(WmsActualWarehouse::getActualWarehouseCode) - .collect(Collectors.toList()); - - throw new ServiceException("以下库位的小库位被占用,不能合并:" + String.join(", ", occupiedParentCodes)); - } - - // 准备批量更新操作 - List childrenToHide = new ArrayList<>(); - List parentsToReset = new ArrayList<>(); - - for (WmsActualWarehouse parent : splitParents) { - List children = childrenByParent.get(parent.getActualWarehouseId()); - - if (CollUtil.isEmpty(children)) { - // 无子库位,直接重置父库位状态 - WmsActualWarehouse parentUpdate = new WmsActualWarehouse(); - parentUpdate.setActualWarehouseId(parent.getActualWarehouseId()); - parentUpdate.setSplitStatus(0); - parentUpdate.setSplitType(0); - parentsToReset.add(parentUpdate); + // 合并操作:隐藏子库位 + for (WmsActualWarehouse location : columnLocations) { + Integer currentSplitStatus = Optional.ofNullable(location.getSplitStatus()).orElse(0); + if (currentSplitStatus != 1) { + // 未拆分的库位无需合并 continue; } - // 准备隐藏子库位 - for (WmsActualWarehouse child : children) { - WmsActualWarehouse childUpdate = new WmsActualWarehouse(); - childUpdate.setActualWarehouseId(child.getActualWarehouseId()); - childUpdate.setDelFlag(1); // 逻辑删除(隐藏) - childrenToHide.add(childUpdate); + // 查询该库位下所有子库位(包括已删除的) + List allChildren = baseMapper.selectList(Wrappers.lambdaQuery() + .eq(WmsActualWarehouse::getParentId, location.getActualWarehouseId()) + .eq(WmsActualWarehouse::getActualWarehouseType, 4)); // 四级子库位 + + if (CollUtil.isNotEmpty(allChildren)) { + // 检查子库位是否被占用(只检查未删除的子库位) + List activeChildren = allChildren.stream() + .filter(c -> c.getDelFlag() == 0) + .collect(Collectors.toList()); + + boolean anyOccupied = activeChildren.stream() + .anyMatch(c -> !Objects.equals(c.getIsEnabled(), 1)); + if (anyOccupied) { + throw new ServiceException("子库位被占用,不能合并:" + location.getActualWarehouseCode()); + } + + // 隐藏所有子库位(设置delFlag=1) + for (WmsActualWarehouse child : allChildren) { + if (child.getDelFlag() == 0) { // 只处理未删除的子库位 + WmsActualWarehouse childUpdate = new WmsActualWarehouse(); + childUpdate.setActualWarehouseId(child.getActualWarehouseId()); + childUpdate.setDelFlag(2); + baseMapper.updateById(childUpdate); + } + } } - // 准备重置父库位状态 + // 更新父库位状态为未拆分 WmsActualWarehouse parentUpdate = new WmsActualWarehouse(); - parentUpdate.setActualWarehouseId(parent.getActualWarehouseId()); + parentUpdate.setActualWarehouseId(location.getActualWarehouseId()); parentUpdate.setSplitStatus(0); parentUpdate.setSplitType(0); - parentsToReset.add(parentUpdate); - } - - // 批量执行更新操作 - if (!childrenToHide.isEmpty()) { - for (WmsActualWarehouse child : childrenToHide) { - baseMapper.updateById(child); - } - } - - if (!parentsToReset.isEmpty()) { - for (WmsActualWarehouse parent : parentsToReset) { - baseMapper.updateById(parent); - } + baseMapper.updateById(parentUpdate); } } - /** - * 重置父库位拆分状态(通用方法) - */ - private void resetParentLocationStatus(WmsActualWarehouse parent) { - WmsActualWarehouse upd = new WmsActualWarehouse(); - upd.setActualWarehouseId(parent.getActualWarehouseId()); - upd.setSplitStatus(0); // 还原为未拆分 - upd.setSplitType(0); // 清空拆分类型 - baseMapper.updateById(upd); - } } From dacd1cb8fddef0fea0ce3c2b2570d2c7996910cb Mon Sep 17 00:00:00 2001 From: Joshi <3040996759@qq.com> Date: Sat, 20 Dec 2025 16:44:19 +0800 Subject: [PATCH 2/3] =?UTF-8?q?refactor(wms):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=BA=93=E4=BD=8D=E6=8B=86=E5=88=86=E4=B8=8E=E5=90=88=E5=B9=B6?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 批量查询子库位以减少数据库访问次数 - 使用批量更新替代循环单条更新提高性能 - 优化复活子库位逻辑,支持批量操作 - 合并库位时增加占用状态检查 - 提取需要合并的库位进行针对性处理 - 子库位隐藏状态从1改为2以区分删除状态 --- .../impl/WmsActualWarehouseServiceImpl.java | 176 +++++++++++------- 1 file changed, 106 insertions(+), 70 deletions(-) diff --git a/klp-wms/src/main/java/com/klp/service/impl/WmsActualWarehouseServiceImpl.java b/klp-wms/src/main/java/com/klp/service/impl/WmsActualWarehouseServiceImpl.java index 4312ea4f..3c9e5b9c 100644 --- a/klp-wms/src/main/java/com/klp/service/impl/WmsActualWarehouseServiceImpl.java +++ b/klp-wms/src/main/java/com/klp/service/impl/WmsActualWarehouseServiceImpl.java @@ -455,80 +455,92 @@ public class WmsActualWarehouseServiceImpl implements IWmsActualWarehouseService throw new ServiceException("未找到列标识为 " + columnFlag + " 的库位"); } - // 检查是否已经有子库位存在(包括被删除的) - boolean hasExistingChildren = false; - for (WmsActualWarehouse location : columnLocations) { - List existingChildren = baseMapper.selectList(Wrappers.lambdaQuery() - .eq(WmsActualWarehouse::getParentId, location.getActualWarehouseId()) - .eq(WmsActualWarehouse::getActualWarehouseType, 4)); // 四级子库位 - if (CollUtil.isNotEmpty(existingChildren)) { - hasExistingChildren = true; - break; - } - } + // 批量查询所有子库位(一次性查询,避免循环查询) + List parentIds = columnLocations.stream() + .map(WmsActualWarehouse::getActualWarehouseId) + .collect(Collectors.toList()); + + List allChildren = baseMapper.selectList(Wrappers.lambdaQuery() + .in(WmsActualWarehouse::getParentId, parentIds) + .eq(WmsActualWarehouse::getActualWarehouseType, 4)); // 四级子库位 + + boolean hasExistingChildren = CollUtil.isNotEmpty(allChildren); if (hasExistingChildren) { // 如果已经有子库位,执行复活逻辑 - reviveExistingSubLocations(columnLocations, splitIds, splitType); + reviveExistingSubLocations(columnLocations, splitIds, splitType, allChildren); } else { // 如果没有子库位,执行创建逻辑 createNewSubLocationsWithOriginalLogic(columnLocations, splitIds, splitType, columnFlag); } - // 更新该列所有被拆分库位的状态 + // 批量更新该列所有被拆分库位的状态 + List toUpdate = new ArrayList<>(); for (WmsActualWarehouse location : columnLocations) { WmsActualWarehouse upd = new WmsActualWarehouse(); upd.setActualWarehouseId(location.getActualWarehouseId()); upd.setSplitStatus(1); upd.setSplitType(splitType); - baseMapper.updateById(upd); + toUpdate.add(upd); + } + if (!toUpdate.isEmpty()) { + baseMapper.updateBatchById(toUpdate); } } /** - * 复活已存在的子库位 + * 复活已存在的子库位(优化版:批量操作) */ - private void reviveExistingSubLocations(List columnLocations, Set splitIds, Integer splitType) { + private void reviveExistingSubLocations(List columnLocations, Set splitIds, Integer splitType, List allChildren) { + // 按父ID分组子库位 + Map> childrenByParent = allChildren.stream() + .sorted(Comparator.comparing(WmsActualWarehouse::getActualWarehouseId)) + .collect(Collectors.groupingBy(WmsActualWarehouse::getParentId, LinkedHashMap::new, Collectors.toList())); + + List toUpdate = new ArrayList<>(); + for (WmsActualWarehouse location : columnLocations) { boolean isSplitLocation = splitIds.contains(location.getActualWarehouseId()); + List children = childrenByParent.get(location.getActualWarehouseId()); + + if (CollUtil.isEmpty(children)) { + continue; + } - // 查询该库位下所有子库位(包括已删除的) - List allChildren = baseMapper.selectList(Wrappers.lambdaQuery() - .eq(WmsActualWarehouse::getParentId, location.getActualWarehouseId()) - .eq(WmsActualWarehouse::getActualWarehouseType, 4) // 四级子库位 - .orderByAsc(WmsActualWarehouse::getActualWarehouseId)); + // 根据是否为拆分库位决定需要复活的子库位数量 + int requiredCount = isSplitLocation ? 2 : 1; - if (CollUtil.isNotEmpty(allChildren)) { - // 根据是否为拆分库位决定需要复活的子库位数量 - int requiredCount = isSplitLocation ? 2 : 1; + // 复活前N个子库位 + for (int i = 0; i < Math.min(requiredCount, children.size()); i++) { + WmsActualWarehouse child = children.get(i); + if (child.getDelFlag() == 1) { // 只处理已删除的子库位 + WmsActualWarehouse childUpdate = new WmsActualWarehouse(); + childUpdate.setActualWarehouseId(child.getActualWarehouseId()); + childUpdate.setDelFlag(0); + childUpdate.setSplitStatus(1); + childUpdate.setSplitType(splitType); + toUpdate.add(childUpdate); + } + } - // 复活前N个子库位 - for (int i = 0; i < Math.min(requiredCount, allChildren.size()); i++) { - WmsActualWarehouse child = allChildren.get(i); - if (child.getDelFlag() == 1) { // 只处理已删除的子库位 + // 如果子库位数量超过需要的数量,隐藏多余的 + if (children.size() > requiredCount) { + for (int i = requiredCount; i < children.size(); i++) { + WmsActualWarehouse child = children.get(i); + if (child.getDelFlag() == 0) { // 只处理未删除的子库位 WmsActualWarehouse childUpdate = new WmsActualWarehouse(); childUpdate.setActualWarehouseId(child.getActualWarehouseId()); - childUpdate.setDelFlag(0); - childUpdate.setSplitStatus(1); - childUpdate.setSplitType(splitType); - baseMapper.updateById(childUpdate); - } - } - - // 如果子库位数量超过需要的数量,隐藏多余的 - if (allChildren.size() > requiredCount) { - for (int i = requiredCount; i < allChildren.size(); i++) { - WmsActualWarehouse child = allChildren.get(i); - if (child.getDelFlag() == 0) { // 只处理未删除的子库位 - WmsActualWarehouse childUpdate = new WmsActualWarehouse(); - childUpdate.setActualWarehouseId(child.getActualWarehouseId()); - childUpdate.setDelFlag(1); - baseMapper.updateById(childUpdate); - } + childUpdate.setDelFlag(1); + toUpdate.add(childUpdate); } } } } + + // 批量更新 + if (!toUpdate.isEmpty()) { + baseMapper.updateBatchById(toUpdate); + } } /** @@ -640,9 +652,7 @@ public class WmsActualWarehouseServiceImpl implements IWmsActualWarehouseService // 3. 批量更新编码 if (!toUpdate.isEmpty()) { - for (WmsActualWarehouse item : toUpdate) { - baseMapper.updateById(item); - } + baseMapper.updateBatchById(toUpdate); } } @@ -670,38 +680,56 @@ public class WmsActualWarehouseServiceImpl implements IWmsActualWarehouseService throw new ServiceException("未找到列标识为 " + columnFlag + " 的库位"); } - // 合并操作:隐藏子库位 - for (WmsActualWarehouse location : columnLocations) { - Integer currentSplitStatus = Optional.ofNullable(location.getSplitStatus()).orElse(0); - if (currentSplitStatus != 1) { - // 未拆分的库位无需合并 - continue; - } + // 过滤出需要合并的库位(splitStatus=1) + List locationsToMerge = columnLocations.stream() + .filter(loc -> Optional.ofNullable(loc.getSplitStatus()).orElse(0) == 1) + .collect(Collectors.toList()); - // 查询该库位下所有子库位(包括已删除的) - List allChildren = baseMapper.selectList(Wrappers.lambdaQuery() - .eq(WmsActualWarehouse::getParentId, location.getActualWarehouseId()) - .eq(WmsActualWarehouse::getActualWarehouseType, 4)); // 四级子库位 + if (CollUtil.isEmpty(locationsToMerge)) { + return; // 没有需要合并的库位 + } - if (CollUtil.isNotEmpty(allChildren)) { - // 检查子库位是否被占用(只检查未删除的子库位) - List activeChildren = allChildren.stream() + // 批量查询所有子库位 + List parentIds = locationsToMerge.stream() + .map(WmsActualWarehouse::getActualWarehouseId) + .collect(Collectors.toList()); + + List allChildren = baseMapper.selectList(Wrappers.lambdaQuery() + .in(WmsActualWarehouse::getParentId, parentIds) + .eq(WmsActualWarehouse::getActualWarehouseType, 4)); // 四级子库位 + + // 按父ID分组子库位 + Map> childrenByParent = allChildren.stream() + .collect(Collectors.groupingBy(WmsActualWarehouse::getParentId)); + + // 检查是否有子库位被占用 + for (WmsActualWarehouse location : locationsToMerge) { + List children = childrenByParent.get(location.getActualWarehouseId()); + if (CollUtil.isNotEmpty(children)) { + boolean anyOccupied = children.stream() .filter(c -> c.getDelFlag() == 0) - .collect(Collectors.toList()); - - boolean anyOccupied = activeChildren.stream() .anyMatch(c -> !Objects.equals(c.getIsEnabled(), 1)); if (anyOccupied) { throw new ServiceException("子库位被占用,不能合并:" + location.getActualWarehouseCode()); } + } + } - // 隐藏所有子库位(设置delFlag=1) - for (WmsActualWarehouse child : allChildren) { - if (child.getDelFlag() == 0) { // 只处理未删除的子库位 + // 批量更新子库位和父库位 + List childrenToUpdate = new ArrayList<>(); + List parentsToUpdate = new ArrayList<>(); + + for (WmsActualWarehouse location : locationsToMerge) { + List children = childrenByParent.get(location.getActualWarehouseId()); + + // 隐藏所有子库位 + if (CollUtil.isNotEmpty(children)) { + for (WmsActualWarehouse child : children) { + if (child.getDelFlag() == 0) { WmsActualWarehouse childUpdate = new WmsActualWarehouse(); childUpdate.setActualWarehouseId(child.getActualWarehouseId()); childUpdate.setDelFlag(2); - baseMapper.updateById(childUpdate); + childrenToUpdate.add(childUpdate); } } } @@ -711,7 +739,15 @@ public class WmsActualWarehouseServiceImpl implements IWmsActualWarehouseService parentUpdate.setActualWarehouseId(location.getActualWarehouseId()); parentUpdate.setSplitStatus(0); parentUpdate.setSplitType(0); - baseMapper.updateById(parentUpdate); + parentsToUpdate.add(parentUpdate); + } + + // 批量更新 + if (!childrenToUpdate.isEmpty()) { + baseMapper.updateBatchById(childrenToUpdate); + } + if (!parentsToUpdate.isEmpty()) { + baseMapper.updateBatchById(parentsToUpdate); } } From 185ffb996351443273a38c4715f86b10cd071d86 Mon Sep 17 00:00:00 2001 From: Joshi <3040996759@qq.com> Date: Mon, 22 Dec 2025 09:36:31 +0800 Subject: [PATCH 3/3] =?UTF-8?q?feat(wms):=20=E5=A2=9E=E5=8A=A0=E5=BA=93?= =?UTF-8?q?=E4=BD=8D=E6=8B=86=E5=88=86=E5=89=8D=E7=9A=84=E5=8D=A0=E7=94=A8?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在拆分逻辑中增加对父库位占用状态的批量校验 - 若父库位被占用则抛出明确提示异常 - 优化库位拆分与合并时的子库位查询逻辑 - 统一处理拆分与合并操作中的空子库位判断 - 调整代码结构,增强可读性与维护性 --- .../impl/WmsActualWarehouseServiceImpl.java | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/klp-wms/src/main/java/com/klp/service/impl/WmsActualWarehouseServiceImpl.java b/klp-wms/src/main/java/com/klp/service/impl/WmsActualWarehouseServiceImpl.java index 3c9e5b9c..192b7c59 100644 --- a/klp-wms/src/main/java/com/klp/service/impl/WmsActualWarehouseServiceImpl.java +++ b/klp-wms/src/main/java/com/klp/service/impl/WmsActualWarehouseServiceImpl.java @@ -455,15 +455,34 @@ public class WmsActualWarehouseServiceImpl implements IWmsActualWarehouseService throw new ServiceException("未找到列标识为 " + columnFlag + " 的库位"); } + // 1. 筛选出待拆分的父库位(只校验需要拆分的库位,非拆分库位不限制) + List toSplitParents = columnLocations.stream() + .filter(loc -> splitIds.contains(loc.getActualWarehouseId())) + .collect(Collectors.toList()); + + // 2. 批量校验占用状态 + List occupiedCodes = new ArrayList<>(); + for (WmsActualWarehouse parent : toSplitParents) { + // 锁定状态=0 → 被占用 + boolean isOccupied = parent.getIsEnabled() != null && parent.getIsEnabled() == 0; + if (isOccupied) { + occupiedCodes.add(parent.getActualWarehouseCode()); + } + } + + // 3. 存在被占用的父库位,抛出异常提示 + if (!occupiedCodes.isEmpty()) { + throw new ServiceException("以下父库位被占用,无法拆分:" + String.join(",", occupiedCodes)); + } // 批量查询所有子库位(一次性查询,避免循环查询) List parentIds = columnLocations.stream() .map(WmsActualWarehouse::getActualWarehouseId) .collect(Collectors.toList()); - + List allChildren = baseMapper.selectList(Wrappers.lambdaQuery() .in(WmsActualWarehouse::getParentId, parentIds) .eq(WmsActualWarehouse::getActualWarehouseType, 4)); // 四级子库位 - + boolean hasExistingChildren = CollUtil.isNotEmpty(allChildren); if (hasExistingChildren) { @@ -498,11 +517,11 @@ public class WmsActualWarehouseServiceImpl implements IWmsActualWarehouseService .collect(Collectors.groupingBy(WmsActualWarehouse::getParentId, LinkedHashMap::new, Collectors.toList())); List toUpdate = new ArrayList<>(); - + for (WmsActualWarehouse location : columnLocations) { boolean isSplitLocation = splitIds.contains(location.getActualWarehouseId()); List children = childrenByParent.get(location.getActualWarehouseId()); - + if (CollUtil.isEmpty(children)) { continue; } @@ -536,7 +555,7 @@ public class WmsActualWarehouseServiceImpl implements IWmsActualWarehouseService } } } - + // 批量更新 if (!toUpdate.isEmpty()) { baseMapper.updateBatchById(toUpdate); @@ -693,7 +712,7 @@ public class WmsActualWarehouseServiceImpl implements IWmsActualWarehouseService List parentIds = locationsToMerge.stream() .map(WmsActualWarehouse::getActualWarehouseId) .collect(Collectors.toList()); - + List allChildren = baseMapper.selectList(Wrappers.lambdaQuery() .in(WmsActualWarehouse::getParentId, parentIds) .eq(WmsActualWarehouse::getActualWarehouseType, 4)); // 四级子库位 @@ -721,7 +740,7 @@ public class WmsActualWarehouseServiceImpl implements IWmsActualWarehouseService for (WmsActualWarehouse location : locationsToMerge) { List children = childrenByParent.get(location.getActualWarehouseId()); - + // 隐藏所有子库位 if (CollUtil.isNotEmpty(children)) { for (WmsActualWarehouse child : children) {