package com.klp.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.klp.common.exception.ServiceException; import com.klp.common.utils.StringUtils; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.klp.domain.bo.WmsActualWarehouseBo; import com.klp.domain.bo.WmsActualWarehouseHierarchyBo; import com.klp.domain.bo.WmsActualWarehouseBatchGenerateBo; import com.klp.domain.bo.WmsActualWarehouseSplitBo; import com.klp.domain.vo.WmsActualWarehouseTreeVo; import com.klp.domain.vo.WmsActualWarehouseImportVo; import com.klp.domain.vo.WmsActualWarehouseVo; import com.klp.domain.WmsActualWarehouse; import com.klp.mapper.WmsActualWarehouseMapper; import com.klp.service.IWmsActualWarehouseService; import com.klp.domain.WmsMaterialCoil; import com.klp.mapper.WmsMaterialCoilMapper; import java.util.*; import java.util.stream.Collectors; /** * 实际库区/库位自关联Service业务层处理 * * @author klp * @date 2025-11-24 */ @RequiredArgsConstructor @Service public class WmsActualWarehouseServiceImpl implements IWmsActualWarehouseService { private final WmsActualWarehouseMapper baseMapper; private final WmsMaterialCoilMapper wmsMaterialCoilMapper; /** * 查询实际库区/库位自关联 */ @Override public WmsActualWarehouseVo queryById(Long actualWarehouseId) { return baseMapper.selectVoById(actualWarehouseId); } @Override @Transactional(rollbackFor = Exception.class) public int batchGenerateLocations(WmsActualWarehouseBatchGenerateBo bo) { if (bo == null) { throw new ServiceException("参数不能为空"); } Integer rows = bo.getRowCount(); Integer cols = bo.getColumnCount(); Integer layers = bo.getLayerCount(); String prefix = bo.getPrefix(); Long parentId = bo.getParentId(); if (layers == null) { layers = 2; } if (rows == null || cols == null || rows < 1 || cols < 1) { throw new ServiceException("行/列必须为正整数"); } if (layers < 1) { throw new ServiceException("层必须为正整数"); } if (StringUtils.isBlank(prefix)) { throw new ServiceException("前缀不能为空"); } List codes = new ArrayList<>(rows * cols * layers); for (int l = 1; l <= layers; l++) { int rowsForLayer = (l == 2) ? Math.max(rows - 1, 1) : rows; for (int c = 1; c <= cols; c++) { for (int r = 1; r <= rowsForLayer; r++) { String rStr = r < 10 ? ("0" + r) : String.valueOf(r); String code = prefix + c + '-' + rStr + '-' + l; codes.add(code); } } } // 去重:过滤同父级下已存在的编码 List exists = baseMapper.selectList(Wrappers.lambdaQuery() .eq(WmsActualWarehouse::getParentId, parentId) .in(!codes.isEmpty(), WmsActualWarehouse::getActualWarehouseCode, codes)); Set existCodes = exists.stream().map(WmsActualWarehouse::getActualWarehouseCode).collect(Collectors.toSet()); List toInsert = new ArrayList<>(); for (String code : codes) { if (existCodes.contains(code)) { continue; } WmsActualWarehouse e = new WmsActualWarehouse(); e.setParentId(parentId); e.setActualWarehouseType(3L); e.setActualWarehouseCode(code); e.setActualWarehouseName(code); e.setSortNo(0L); e.setIsEnabled(1); toInsert.add(e); } if (toInsert.isEmpty()) { return 0; } boolean ok = baseMapper.insertBatch(toInsert); if (!ok) { throw new ServiceException("批量生成失败"); } return toInsert.size(); } /** * 查询实际库区/库位自关联列表 */ @Override public List queryList(WmsActualWarehouseBo bo) { LambdaQueryWrapper lqw = buildQueryWrapper(bo); List list = baseMapper.selectVoList(lqw); if (CollUtil.isEmpty(list)) { return list; } // 如果当前查询的是某二级父节点下的三级库位,需要将被拆分的大库位替换为其两个子库位 if (bo.getParentId() != null) { List splitParentIds = list.stream() .filter(v -> Optional.ofNullable(v.getSplitStatus()).orElse(0) == 1) .map(WmsActualWarehouseVo::getActualWarehouseId) .collect(Collectors.toList()); if (CollUtil.isNotEmpty(splitParentIds)) { List children = baseMapper.selectVoList( Wrappers.lambdaQuery() .in(WmsActualWarehouse::getParentId, splitParentIds) .eq(WmsActualWarehouse::getDelFlag, 0) .orderByAsc(WmsActualWarehouse::getActualWarehouseCode, WmsActualWarehouse::getActualWarehouseId) ); Map> childrenMap = children.stream() .collect(Collectors.groupingBy(WmsActualWarehouseVo::getParentId, LinkedHashMap::new, Collectors.toList())); List expanded = new ArrayList<>(list.size() + children.size()); for (WmsActualWarehouseVo v : list) { if (Optional.ofNullable(v.getSplitStatus()).orElse(0) == 1) { List ch = childrenMap.get(v.getActualWarehouseId()); if (CollUtil.isNotEmpty(ch)) { expanded.addAll(ch); continue; } } expanded.add(v); } list = expanded; } } // 仅对被占用的位置(isEnabled=0)补充钢卷信息 List occupiedAwIds = list.stream() .filter(it -> it.getIsEnabled() != null && it.getIsEnabled() == 0) .map(WmsActualWarehouseVo::getActualWarehouseId) .filter(Objects::nonNull) .distinct() .collect(Collectors.toList()); if (CollUtil.isEmpty(occupiedAwIds)) { return list; } // 查询当前在库(del_flag=0, status=0)并且占用这些库位的钢卷,仅选择必要列 List coils = wmsMaterialCoilMapper.selectList( Wrappers.lambdaQuery() .select( WmsMaterialCoil::getActualWarehouseId, WmsMaterialCoil::getCoilId, WmsMaterialCoil::getEnterCoilNo, WmsMaterialCoil::getCurrentCoilNo, WmsMaterialCoil::getSupplierCoilNo ) .in(WmsMaterialCoil::getActualWarehouseId, occupiedAwIds) .eq(WmsMaterialCoil::getDelFlag, 0) .eq(WmsMaterialCoil::getStatus, 0) ); if (CollUtil.isEmpty(coils)) { return list; } // 同一库位若有多条记录,选择最新一条(按更新顺序无字段,这里按主键最大) Map coilByAwId = coils.stream() .collect(Collectors.toMap( WmsMaterialCoil::getActualWarehouseId, c -> c, (a, b) -> a.getCoilId() != null && b.getCoilId() != null && a.getCoilId() > b.getCoilId() ? a : b )); list.forEach(it -> { if (it.getIsEnabled() != null && it.getIsEnabled() == 0) { WmsMaterialCoil c = coilByAwId.get(it.getActualWarehouseId()); if (c != null) { it.setEnterCoilNo(c.getEnterCoilNo()); it.setCurrentCoilNo(c.getCurrentCoilNo()); it.setSupplierCoilNo(c.getSupplierCoilNo()); } } }); return list; } @Override public List queryTree(WmsActualWarehouseBo bo) { if (bo == null) { bo = new WmsActualWarehouseBo(); } LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); wrapper.eq(StringUtils.isNotBlank(bo.getActualWarehouseCode()), WmsActualWarehouse::getActualWarehouseCode, bo.getActualWarehouseCode()); wrapper.like(StringUtils.isNotBlank(bo.getActualWarehouseName()), WmsActualWarehouse::getActualWarehouseName, bo.getActualWarehouseName()); wrapper.eq(bo.getActualWarehouseType() != null, WmsActualWarehouse::getActualWarehouseType, bo.getActualWarehouseType()); wrapper.eq(bo.getIsEnabled() != null, WmsActualWarehouse::getIsEnabled, bo.getIsEnabled()); wrapper.orderByAsc(WmsActualWarehouse::getSortNo, WmsActualWarehouse::getActualWarehouseId); List flatList = baseMapper.selectVoList(wrapper); Map nodeMap = new LinkedHashMap<>(); flatList.forEach(item -> { WmsActualWarehouseTreeVo node = new WmsActualWarehouseTreeVo(); BeanUtil.copyProperties(item, node); nodeMap.put(node.getActualWarehouseId(), node); }); List roots = new ArrayList<>(); nodeMap.values().forEach(node -> { Long parentId = Optional.ofNullable(node.getParentId()).orElse(0L); if (parentId == 0 || !nodeMap.containsKey(parentId)) { roots.add(node); } else { nodeMap.get(parentId).getChildren().add(node); } }); return roots; } @Override public List queryTreeExcludeLevelThree(WmsActualWarehouseBo bo) { if (bo == null) { bo = new WmsActualWarehouseBo(); } // 设置查询条件,排除三级节点(actualWarehouseType=3) LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); wrapper.eq(StringUtils.isNotBlank(bo.getActualWarehouseCode()), WmsActualWarehouse::getActualWarehouseCode, bo.getActualWarehouseCode()); wrapper.like(StringUtils.isNotBlank(bo.getActualWarehouseName()), WmsActualWarehouse::getActualWarehouseName, bo.getActualWarehouseName()); wrapper.eq(bo.getActualWarehouseType() != null, WmsActualWarehouse::getActualWarehouseType, bo.getActualWarehouseType()); wrapper.eq(bo.getIsEnabled() != null, WmsActualWarehouse::getIsEnabled, bo.getIsEnabled()); // 排除三级节点(类型为3的节点) wrapper.ne(WmsActualWarehouse::getActualWarehouseType, 3); // 四级节点也排除 wrapper.ne(WmsActualWarehouse::getActualWarehouseType, 4); wrapper.orderByAsc(WmsActualWarehouse::getSortNo, WmsActualWarehouse::getActualWarehouseId); List flatList = baseMapper.selectVoList(wrapper); Map nodeMap = new LinkedHashMap<>(); flatList.forEach(item -> { WmsActualWarehouseTreeVo node = new WmsActualWarehouseTreeVo(); BeanUtil.copyProperties(item, node); nodeMap.put(node.getActualWarehouseId(), node); }); List roots = new ArrayList<>(); nodeMap.values().forEach(node -> { Long parentId = Optional.ofNullable(node.getParentId()).orElse(0L); if (parentId == 0 || !nodeMap.containsKey(parentId)) { roots.add(node); } else { nodeMap.get(parentId).getChildren().add(node); } }); return roots; } private LambdaQueryWrapper buildQueryWrapper(WmsActualWarehouseBo bo) { Map params = bo.getParams(); LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); lqw.eq(bo.getParentId() != null, WmsActualWarehouse::getParentId, bo.getParentId()); lqw.eq(StringUtils.isNotBlank(bo.getActualWarehouseCode()), WmsActualWarehouse::getActualWarehouseCode, bo.getActualWarehouseCode()); lqw.like(StringUtils.isNotBlank(bo.getActualWarehouseName()), WmsActualWarehouse::getActualWarehouseName, bo.getActualWarehouseName()); lqw.eq(bo.getActualWarehouseType() != null, WmsActualWarehouse::getActualWarehouseType, bo.getActualWarehouseType()); lqw.eq(bo.getSortNo() != null, WmsActualWarehouse::getSortNo, bo.getSortNo()); lqw.eq(bo.getIsEnabled() != null, WmsActualWarehouse::getIsEnabled, bo.getIsEnabled()); return lqw; } /** * 新增实际库区/库位自关联 */ @Override public Boolean insertByBo(WmsActualWarehouseBo bo) { WmsActualWarehouse add = BeanUtil.toBean(bo, WmsActualWarehouse.class); validEntityBeforeSave(add); boolean flag = baseMapper.insert(add) > 0; if (flag) { bo.setActualWarehouseId(add.getActualWarehouseId()); } return flag; } /** * 修改实际库区/库位自关联 */ @Override public Boolean updateByBo(WmsActualWarehouseBo bo) { WmsActualWarehouse update = BeanUtil.toBean(bo, WmsActualWarehouse.class); validEntityBeforeSave(update); return baseMapper.updateById(update) > 0; } @Override @Transactional(rollbackFor = Exception.class) public List createHierarchy(WmsActualWarehouseHierarchyBo bo) { if (bo.getLevels() == null || bo.getLevels().isEmpty()) { throw new ServiceException("层级数据不能为空"); } List sortedLevels = bo.getLevels().stream() .sorted(Comparator.comparing(WmsActualWarehouseHierarchyBo.HierarchyLevel::getLevel)) .collect(Collectors.toList()); Long parentId = 0L; List createdIds = new ArrayList<>(); for (WmsActualWarehouseHierarchyBo.HierarchyLevel level : sortedLevels) { Integer levelValue = level.getLevel(); if (levelValue == null || levelValue < 1 || levelValue > 3) { throw new ServiceException("层级必须在1-3之间"); } if (level.getActualWarehouseId() != null) { WmsActualWarehouse existing = baseMapper.selectById(level.getActualWarehouseId()); if (existing == null) { throw new ServiceException("指定的节点不存在:" + level.getActualWarehouseId()); } if (!Objects.equals(Optional.ofNullable(existing.getParentId()).orElse(0L), parentId)) { throw new ServiceException("节点不属于当前父级,无法复用"); } parentId = existing.getActualWarehouseId(); continue; } if (StringUtils.isBlank(level.getActualWarehouseCode()) || StringUtils.isBlank(level.getActualWarehouseName())) { throw new ServiceException("编码与名称不能为空"); } WmsActualWarehouse duplicate = baseMapper.selectOne(Wrappers.lambdaQuery() .eq(WmsActualWarehouse::getParentId, parentId) .and(wrapper -> wrapper.eq(WmsActualWarehouse::getActualWarehouseCode, level.getActualWarehouseCode()) .or() .eq(WmsActualWarehouse::getActualWarehouseName, level.getActualWarehouseName()))); if (duplicate != null) { parentId = duplicate.getActualWarehouseId(); continue; } WmsActualWarehouse entity = new WmsActualWarehouse(); entity.setParentId(parentId); entity.setActualWarehouseType(levelValue.longValue()); entity.setActualWarehouseCode(level.getActualWarehouseCode()); entity.setActualWarehouseName(level.getActualWarehouseName()); entity.setSortNo(Optional.ofNullable(level.getSortNo()).orElse(0L)); entity.setIsEnabled(Optional.ofNullable(level.getIsEnabled()).orElse(1)); entity.setRemark(level.getRemark()); baseMapper.insert(entity); parentId = entity.getActualWarehouseId(); createdIds.add(parentId); } return createdIds; } @Override @Transactional(rollbackFor = Exception.class) public void importHierarchy(List importList) { if (CollUtil.isEmpty(importList)) { throw new ServiceException("导入数据不能为空"); } for (WmsActualWarehouseImportVo row : importList) { List levels = new ArrayList<>(); appendLevel(levels, 1, row.getLevelOneCode(), row.getLevelOneName(), row.getLevelOneSort()); appendLevel(levels, 2, row.getLevelTwoCode(), row.getLevelTwoName(), row.getLevelTwoSort()); appendLevel(levels, 3, row.getLevelThreeCode(), row.getLevelThreeName(), row.getLevelThreeSort()); if (levels.isEmpty()) { continue; } WmsActualWarehouseHierarchyBo bo = new WmsActualWarehouseHierarchyBo(); bo.setLevels(levels); createHierarchy(bo); } } /** * 保存前的数据校验 */ private void validEntityBeforeSave(WmsActualWarehouse entity) { //TODO 做一些数据校验,如唯一约束 } private void appendLevel(List levels, int level, String code, String name, Long sortNo) { if (StringUtils.isBlank(code) || StringUtils.isBlank(name)) { return; } WmsActualWarehouseHierarchyBo.HierarchyLevel item = new WmsActualWarehouseHierarchyBo.HierarchyLevel(); item.setLevel(level); item.setActualWarehouseCode(code.trim()); item.setActualWarehouseName(name.trim()); item.setSortNo(Optional.ofNullable(sortNo).orElse(0L)); item.setIsEnabled(1); levels.add(item); } /** * 批量删除实际库区/库位自关联 */ @Override public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { if (isValid) { //TODO 做一些业务上的校验,判断是否需要校验 } return baseMapper.deleteBatchIds(ids) > 0; } @Override @Transactional(rollbackFor = Exception.class) public void splitLocations(WmsActualWarehouseSplitBo bo) { if (bo == null) { throw new ServiceException("参数不能为空"); } // 参数验证 String columnFlag = bo.getColumnFlag(); if (StringUtils.isBlank(columnFlag)) { throw new ServiceException("列标识不能为空"); } int splitType = Optional.ofNullable(bo.getSplitType()).orElse(0); List splitIds = Optional.ofNullable(bo.getSplitIds()).orElse(new ArrayList<>()); 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) .orderByAsc(WmsActualWarehouse::getActualWarehouseCode)); if (CollUtil.isEmpty(columnLocations)) { throw new ServiceException("未找到列标识为 " + columnFlag + " 的库位"); } // 分离需要拆分的库位和剩余库位 List splitLocations = new ArrayList<>(); List remainingLocations = new ArrayList<>(); for (WmsActualWarehouse location : columnLocations) { if (splitIds.contains(location.getActualWarehouseId())) { splitLocations.add(location); } else { remainingLocations.add(location); } } // 存储需要插入/更新的子库位 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)); // 查询已逻辑删除的子库位 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); } } // 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); } } // 3. 验证总数 int expectedSplitSub = splitLocations.size() * 2; int expectedRemainingSub = remainingLocations.size() * 1; int expectedTotal = expectedSplitSub + expectedRemainingSub; // 实际总数 = 新增数 + 复用数 int actualTotal = toInsert.size() + toUpdate.size(); if (actualTotal != expectedTotal) { throw new ServiceException(String.format( "子库位数量不匹配,期望%d个,实际新增%d个+复用%d个=%d个", expectedTotal, toInsert.size(), toUpdate.size(), actualTotal)); } // 4. 批量插入新子库位 if (!toInsert.isEmpty()) { boolean insertOk = baseMapper.insertBatch(toInsert); if (!insertOk) { throw new ServiceException("新增子库位失败"); } } // 5. 批量更新复用的子库位(恢复状态) if (!toUpdate.isEmpty()) { for (WmsActualWarehouse child : toUpdate) { baseMapper.updateById(child); } } // 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())) { throw new ServiceException("参数不能为空"); } // 批量查询父库位 List parents = baseMapper.selectList(Wrappers.lambdaQuery() .in(WmsActualWarehouse::getActualWarehouseId, bo.getLocationIds()) .eq(WmsActualWarehouse::getDelFlag, 0)); if (CollUtil.isEmpty(parents)) { return; } // 过滤出已拆分的父库位 List splitParents = parents.stream() .filter(p -> Optional.ofNullable(p.getSplitStatus()).orElse(0) == 1) .collect(Collectors.toList()); if (CollUtil.isEmpty(splitParents)) { return; } // 批量查询所有子库位 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); continue; } // 准备隐藏子库位 for (WmsActualWarehouse child : children) { WmsActualWarehouse childUpdate = new WmsActualWarehouse(); childUpdate.setActualWarehouseId(child.getActualWarehouseId()); childUpdate.setDelFlag(1); // 逻辑删除(隐藏) childrenToHide.add(childUpdate); } // 准备重置父库位状态 WmsActualWarehouse parentUpdate = new WmsActualWarehouse(); parentUpdate.setActualWarehouseId(parent.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); } } } /** * 重置父库位拆分状态(通用方法) */ private void resetParentLocationStatus(WmsActualWarehouse parent) { WmsActualWarehouse upd = new WmsActualWarehouse(); upd.setActualWarehouseId(parent.getActualWarehouseId()); upd.setSplitStatus(0); // 还原为未拆分 upd.setSplitType(0); // 清空拆分类型 baseMapper.updateById(upd); } }