feat(warehouse): 添加库位排序号修正功能并优化钢卷查询排序

- 在 IWmsActualWarehouseService 中新增 fixSortNoByParentId 方法用于修正库位排序号
- 在 WmsActualWarehouseController 中新增 /fixSortNo/{parentId} 接口
- 实现 WmsActualWarehouseServiceImpl 中的 fixSortNoByParentId 业务逻辑
- 添加正则表达式处理库位编码的排序键解析
- 新增 WmsMaterialCoilMapper 的 selectVoPagePlusOrderBy 查询方法
- 重构 WmsMaterialCoilMapper.xml 中的排序辅助字段查询逻辑
- 修改 WmsMaterialCoilServiceImpl 中的分页查询逻辑以支持排序功能
This commit is contained in:
2026-03-12 17:05:22 +08:00
parent e589bb6496
commit bfba3ce49a
6 changed files with 245 additions and 11 deletions

View File

@@ -224,4 +224,17 @@ public class WmsActualWarehouseController extends BaseController {
return AjaxResult.error("库区释放失败: " + e.getMessage());
}
}
/**
* 修正已生成库位的排序号(交错排序)
*
* @param parentId 父库位ID
*/
@Log(title = "修正库位排序号", businessType = BusinessType.UPDATE)
@PutMapping("/fixSortNo/{parentId}")
public R<Integer> fixSortNo(@PathVariable Long parentId) {
int count = iWmsActualWarehouseService.fixSortNoByParentId(parentId);
return R.ok(count);
}
}

View File

@@ -37,6 +37,11 @@ public interface WmsMaterialCoilMapper extends BaseMapperPlus<WmsMaterialCoilMap
Page<WmsMaterialCoilVo> selectVoPagePlus(Page<Object> build,@Param("ew") QueryWrapper<WmsMaterialCoil> lqw);
/**
* orderBy=true 时使用包含库位排序辅助字段aw_sort_key/aw_layer_key/aw_id_key以及父库位 join
*/
Page<WmsMaterialCoilVo> selectVoPagePlusOrderBy(Page<Object> build, @Param("ew") QueryWrapper<WmsMaterialCoil> lqw);
List<WmsMaterialCoilVo> selectVoListWithDynamicJoin(@Param("ew")QueryWrapper<WmsMaterialCoil> lqw);
List<Map<String, Object>> getDistributionByActualWarehouse(@Param("itemType") String itemType, @Param("itemId") Long itemId);

View File

@@ -84,4 +84,12 @@ public interface IWmsActualWarehouseService {
* - 清空钢卷表中绑定此库区且为现存(data_type=1)、未删除(del_flag=0)的记录的 actual_warehouse_id
*/
void releaseActualWarehouse(Long actualWarehouseId);
/**
* 修正已生成库位的排序号(交错排序)
* @param parentId 父库位ID
* @return 修正的记录数
*/
int fixSortNoByParentId(Long parentId);
}

View File

@@ -24,6 +24,8 @@ import com.klp.domain.WmsMaterialCoil;
import com.klp.mapper.WmsMaterialCoilMapper;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
@@ -799,5 +801,117 @@ public class WmsActualWarehouseServiceImpl implements IWmsActualWarehouseService
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public int fixSortNoByParentId(Long parentId) {
if (parentId == null) {
throw new ServiceException("父库位ID不能为空");
}
WmsActualWarehouse parent = baseMapper.selectById(parentId);
if (parent == null) {
throw new ServiceException("父库位不存在");
}
Long l1SortNo = parent.getSortNo() != null ? parent.getSortNo() : 0L;
int[] counter = {1}; // Global counter for sortNo
if (parent.getActualWarehouseType() != null && parent.getActualWarehouseType() == 1L) {
List<WmsActualWarehouse> l2List = baseMapper.selectList(
new LambdaQueryWrapper<WmsActualWarehouse>()
.eq(WmsActualWarehouse::getParentId, parentId)
.eq(WmsActualWarehouse::getDelFlag, 0)
);
int totalCount = 0;
for (WmsActualWarehouse l2 : l2List) {
Long l2SortNo = l2.getSortNo() != null ? l2.getSortNo() : 0L;
totalCount += fixLevel(l2.getActualWarehouseId(), l1SortNo, l2SortNo, counter);
}
return totalCount;
} else {
Long l2SortNo = 0L;
if (parent.getParentId() != null) {
WmsActualWarehouse l2 = baseMapper.selectById(parent.getParentId());
l2SortNo = l2 != null && l2.getSortNo() != null ? l2.getSortNo() : 0L;
}
return fixLevel(parentId, l1SortNo, l2SortNo, counter);
}
}
private int fixLevel(Long parentId, Long l1SortNo, Long l2SortNo, int[] counter) {
List<WmsActualWarehouse> list = baseMapper.selectList(
new LambdaQueryWrapper<WmsActualWarehouse>()
.eq(WmsActualWarehouse::getParentId, parentId)
.eq(WmsActualWarehouse::getDelFlag, 0)
);
if (list.isEmpty()) return 0;
// 需求调整:此处不再对四级(小库位)进行 sort_no 修正,只修正三级(大库位)即可
boolean isFourthLevel = list.get(0).getActualWarehouseType() != null
&& list.get(0).getActualWarehouseType() == 4L;
if (isFourthLevel) {
return 0;
}
Map<WmsActualWarehouse, int[]> sortKeyMap = new HashMap<>();
Pattern pattern3 = Pattern.compile("(.*?)(\\d+)-(\\d+)-(\\d+)");
for (WmsActualWarehouse w : list) {
String code = w.getActualWarehouseCode();
if (StringUtils.isBlank(code)) continue;
Matcher m3 = pattern3.matcher(code);
if (m3.matches()) {
sortKeyMap.put(w, new int[]{
Integer.parseInt(m3.group(2)),
Integer.parseInt(m3.group(3)),
Integer.parseInt(m3.group(4))
});
}
}
List<WmsActualWarehouse> sorted = sortKeyMap.entrySet().stream()
.sorted((e1, e2) -> {
int[] k1 = e1.getValue();
int[] k2 = e2.getValue();
int c = Integer.compare(k1[0], k2[0]);
if (c != 0) return c;
c = Integer.compare(k1[1], k2[1]);
if (c != 0) return c;
return Integer.compare(k1[2], k2[2]);
})
.map(Map.Entry::getKey)
.collect(Collectors.toList());
List<WmsActualWarehouse> updates = new ArrayList<>();
int totalCount = 0;
for (WmsActualWarehouse w : sorted) {
long currentSortNo = l1SortNo * 100000L + l2SortNo * 10000L + counter[0];
// 仅修正三级排序号;四级交错排序已由钢卷查询排序逻辑处理
totalCount += fixLevel(w.getActualWarehouseId(), l1SortNo, l2SortNo, counter);
WmsActualWarehouse update = new WmsActualWarehouse();
update.setActualWarehouseId(w.getActualWarehouseId());
update.setSortNo(currentSortNo);
updates.add(update);
counter[0]++;
totalCount++;
if (updates.size() >= 500) {
baseMapper.updateBatchById(updates);
updates.clear();
}
}
if (!updates.isEmpty()) {
baseMapper.updateBatchById(updates);
}
return totalCount;
}
}

View File

@@ -305,7 +305,12 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
@Override
public TableDataInfo<WmsMaterialCoilVo> queryPageList(WmsMaterialCoilBo bo, PageQuery pageQuery) {
QueryWrapper<WmsMaterialCoil> qw = buildQueryWrapperPlus(bo);
Page<WmsMaterialCoilVo> result = baseMapper.selectVoPagePlus(pageQuery.build(), qw);
Page<WmsMaterialCoilVo> result;
if (Boolean.TRUE.equals(bo.getOrderBy())) {
result = baseMapper.selectVoPagePlusOrderBy(pageQuery.build(), qw);
} else {
result = baseMapper.selectVoPagePlus(pageQuery.build(), qw);
}
List<WmsMaterialCoilVo> records = result.getRecords();
if (records == null || records.isEmpty()) {

View File

@@ -139,17 +139,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
WHEN mc.item_type = 'product' THEN p.product_code
ELSE NULL
END as itemCode,
-- 库位排序辅助字段(用于全局交错排序,避免在 ORDER BY 中写复杂表达式触发 MP 注入拦截)
COALESCE(CASE WHEN aw.actual_warehouse_type = 4 THEN awp.sort_no ELSE aw.sort_no END, 0) AS aw_sort_key,
CASE WHEN aw.actual_warehouse_type = 4 THEN CAST(SUBSTRING_INDEX(aw.actual_warehouse_code, '-', -1) AS UNSIGNED) ELSE 0 END AS aw_layer_key,
COALESCE(aw.actual_warehouse_id, 0) AS aw_id_key,
-- 异常数量统计
COALESCE(ca.abnormal_count, 0) AS abnormalCount
FROM wms_material_coil mc
LEFT JOIN wms_warehouse w ON mc.warehouse_id = w.warehouse_id
LEFT JOIN wms_warehouse nw ON mc.next_warehouse_id = nw.warehouse_id
LEFT JOIN wms_actual_warehouse aw ON mc.actual_warehouse_id = aw.actual_warehouse_id
LEFT JOIN wms_actual_warehouse awp ON aw.parent_id = awp.actual_warehouse_id
LEFT JOIN sys_user su ON mc.sale_id = su.user_id
LEFT JOIN wms_raw_material rm ON mc.item_type = 'raw_material' AND mc.item_id = rm.raw_material_id
LEFT JOIN wms_product p ON mc.item_type = 'product' AND mc.item_id = p.product_id
@@ -161,6 +156,105 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
) ca ON mc.coil_id = ca.coil_id
${ew.customSqlSegment}
</select>
<!-- orderBy=true 专用包含库位排序辅助字段aw_sort_key/aw_layer_key/aw_id_key以及父库位 join -->
<select id="selectVoPagePlusOrderBy" resultType="com.klp.domain.vo.WmsMaterialCoilVo">
SELECT
mc.coil_id,
mc.parent_coil_id,
mc.export_time,
mc.export_by,
mc.enter_coil_no,
mc.current_coil_no,
mc.supplier_coil_no,
mc.data_type,
mc.material_type,
mc.next_warehouse_id,
mc.qrcode_record_id,
mc.team,
mc.has_merge_split,
mc.parent_coil_nos,
mc.item_type,
mc.item_id,
mc.gross_weight,
mc.net_weight,
mc.status,
mc.remark,
mc.warehouse_id,
mc.actual_warehouse_id,
mc.del_flag,
mc.create_time,
mc.update_time,
mc.create_by,
mc.update_by,
mc.quality_status,
mc.trimming_requirement,
mc.packaging_requirement,
mc.packing_status,
mc.sale_id AS saleId,
mc.length,
mc.actual_length,
mc.actual_width,
mc.coating_type,
mc.temper_grade,
mc.business_purpose,
mc.is_related_to_order,
mc.exclusive_status,
su.nick_name AS saleName,
w.warehouse_name AS warehouseName,
nw.warehouse_name AS nextWarehouseName,
aw.actual_warehouse_name AS actualWarehouseName,
CASE WHEN mc.item_type = 'raw_material' THEN rm.specification
WHEN mc.item_type = 'product' THEN p.specification
ELSE NULL END AS specification,
CASE WHEN mc.item_type = 'raw_material' THEN rm.material
WHEN mc.item_type = 'product' THEN p.material
ELSE NULL END AS material,
CASE WHEN mc.item_type = 'raw_material' THEN rm.manufacturer
WHEN mc.item_type = 'product' THEN p.manufacturer
ELSE NULL END AS manufacturer,
CASE WHEN mc.item_type = 'raw_material' THEN rm.surface_treatment_desc
WHEN mc.item_type = 'product' THEN p.surface_treatment_desc
ELSE NULL END AS surfaceTreatmentDesc,
CASE WHEN mc.item_type = 'raw_material' THEN rm.zinc_layer
WHEN mc.item_type = 'product' THEN p.zinc_layer
ELSE NULL END AS zincLayer,
-- 物品名称和编号(用于兼容)
CASE
WHEN mc.item_type = 'raw_material' THEN rm.raw_material_name
WHEN mc.item_type = 'product' THEN p.product_name
ELSE NULL
END as itemName,
CASE
WHEN mc.item_type = 'raw_material' THEN rm.raw_material_code
WHEN mc.item_type = 'product' THEN p.product_code
ELSE NULL
END as itemCode,
-- 库位排序辅助字段(用于全局交错排序,避免在 ORDER BY 中写复杂表达式触发 MP 注入拦截)
COALESCE(CASE WHEN aw.actual_warehouse_type = 4 THEN awp.sort_no ELSE aw.sort_no END, 0) AS aw_sort_key,
CASE WHEN aw.actual_warehouse_type = 4 THEN CAST(SUBSTRING_INDEX(aw.actual_warehouse_code, '-', -1) AS UNSIGNED) ELSE 0 END AS aw_layer_key,
COALESCE(aw.actual_warehouse_id, 0) AS aw_id_key,
-- 异常数量统计
COALESCE(ca.abnormal_count, 0) AS abnormalCount
FROM wms_material_coil mc
LEFT JOIN wms_warehouse w ON mc.warehouse_id = w.warehouse_id
LEFT JOIN wms_warehouse nw ON mc.next_warehouse_id = nw.warehouse_id
LEFT JOIN wms_actual_warehouse aw ON mc.actual_warehouse_id = aw.actual_warehouse_id
LEFT JOIN wms_actual_warehouse awp ON aw.parent_id = awp.actual_warehouse_id
LEFT JOIN sys_user su ON mc.sale_id = su.user_id
LEFT JOIN wms_raw_material rm ON mc.item_type = 'raw_material' AND mc.item_id = rm.raw_material_id
LEFT JOIN wms_product p ON mc.item_type = 'product' AND mc.item_id = p.product_id
LEFT JOIN (
SELECT coil_id, COUNT(*) AS abnormal_count
FROM wms_coil_abnormal
WHERE del_flag = 0
GROUP BY coil_id
) ca ON mc.coil_id = ca.coil_id
${ew.customSqlSegment}
</select>
<!-- 查询不同类型的钢卷在不同库区的分布情况 -->
<select id="getDistributionByItemType" resultType="java.util.Map">
SELECT
@@ -255,10 +349,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
WHEN mc.item_type = 'product' THEN p.product_code
ELSE NULL
END as itemCode,
-- 库位排序辅助字段(用于全局交错排序,避免在 ORDER BY 中写复杂表达式触发 MP 注入拦截)
COALESCE(CASE WHEN aw.actual_warehouse_type = 4 THEN awp.sort_no ELSE aw.sort_no END, 0) AS aw_sort_key,
CASE WHEN aw.actual_warehouse_type = 4 THEN CAST(SUBSTRING_INDEX(aw.actual_warehouse_code, '-', -1) AS UNSIGNED) ELSE 0 END AS aw_layer_key,
COALESCE(aw.actual_warehouse_id, 0) AS aw_id_key,
-- 异常数量统计
COALESCE(ca.abnormal_count, 0) AS abnormalCount
FROM wms_material_coil mc
@@ -266,7 +356,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
LEFT JOIN wms_product p ON mc.item_type = 'product' AND mc.item_id = p.product_id
LEFT JOIN wms_warehouse w ON mc.warehouse_id = w.warehouse_id
LEFT JOIN wms_actual_warehouse aw ON mc.actual_warehouse_id = aw.actual_warehouse_id
LEFT JOIN wms_actual_warehouse awp ON aw.parent_id = awp.actual_warehouse_id
LEFT JOIN (
SELECT coil_id, COUNT(*) AS abnormal_count
FROM wms_coil_abnormal