feat(wms):上架管理PC上传页默认填充指定上架库位(维他奶仓→2层冷凍A區A01),仅回显不落库
This commit is contained in:
@@ -237,6 +237,12 @@ public interface SystemServiceFeign {
|
||||
@GetMapping("/warehouseApi/getInfo/{warehouseId}")
|
||||
public AjaxResult getWarehouseInfoByWarehouseId(@PathVariable("warehouseId") Long warehouseId);
|
||||
|
||||
/**
|
||||
* 根据warehouseId获取仓库及下库区及库位树(与前端 warehouseApi/getWarehouseChildren 一致,用于PC上架页默认库位回显)
|
||||
*/
|
||||
@GetMapping("/warehouseApi/getWarehouseChildren")
|
||||
public AjaxResult getWarehouseChildren(@RequestParam("warehouseId") Long warehouseId);
|
||||
|
||||
/**
|
||||
* 根据storageSectionId获取对应库区信息
|
||||
*/
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.mhd.system.api.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 仓库联动树节点(Feign侧)
|
||||
* 镜像system端WarehouseLinkagePO/StorageSectionLinkagePO/StorageLocationLinkagePO三级结构:仓库→库区→库位
|
||||
*
|
||||
* @author rcx
|
||||
* @date 2026-08-22
|
||||
*/
|
||||
@Data
|
||||
public class WarehouseLinkageFeignPO implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 仓库id / 库区id(storageSectionId) / 库位id(storageLocationId) */
|
||||
private Long id;
|
||||
|
||||
/** warehouseCode / storageCode / storageLocationCode */
|
||||
private String code;
|
||||
|
||||
/** warehouseName / storageName / storageLocationName */
|
||||
private String name;
|
||||
|
||||
/** 下级节点:仓库下为库区列表,库区下为库位列表,库位无children */
|
||||
private List<WarehouseLinkageFeignPO> children;
|
||||
}
|
||||
+6
@@ -20,6 +20,7 @@ import org.springframework.cloud.openfeign.FallbackFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -184,6 +185,11 @@ public class RemoteSystemFeignFallbackFactory implements FallbackFactory<SystemS
|
||||
return AjaxResult.error("根据仓库ID获取仓库信息失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult getWarehouseChildren(@RequestParam("warehouseId") Long warehouseId) {
|
||||
return AjaxResult.error("根据仓库ID获取仓库及下库区及库位树失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult getStorageSectionInfoByStorageSectionId(@PathVariable("storageSectionId") Long storageSectionId) {
|
||||
return AjaxResult.error("根据库区ID获取库区信息失败");
|
||||
|
||||
+112
@@ -133,6 +133,14 @@ public class StockShelfOrderApplicationService {
|
||||
private static final String API_NAME = "save_qnBill_i";
|
||||
private static final String VERIFY = "ESLuxAmB6VXCgbqP1eFzxTPVRagkQ62BUkfhElrgQ6XmE/g2reHVflY/SiCSU7JD";
|
||||
|
||||
/** 仅这些仓库的上架单在PC上传页默认填充上架库位(按仓库名匹配;需放开其他仓库时在此追加)。
|
||||
* 生产环境:维他奶仓(warehouseId=14);测试环境为 青洲仓(warehouseId=13),需测试时切换 */
|
||||
private static final Set<String> DEFAULT_STORAGE_LOCATION_WAREHOUSE_NAMES = new HashSet<>(Collections.singletonList("维他奶仓"));
|
||||
/** 默认上架库位:指定库区名→库位名(精确匹配,须与基础资料名称完全一致,注意含繁体字)。
|
||||
* 生产环境:維他奶2层冷凍A區 → 2层冷凍A區A01;测试环境为 4楼A区 → 4A-01-01,需测试时切换 */
|
||||
private static final String DEFAULT_SHELF_STORAGE_NAME = "維他奶2层冷凍A區";
|
||||
private static final String DEFAULT_SHELF_STORAGE_LOCATION_NAME = "2层冷凍A區A01";
|
||||
|
||||
|
||||
/**
|
||||
* 分页查询上架单列表
|
||||
@@ -357,6 +365,8 @@ public class StockShelfOrderApplicationService {
|
||||
|
||||
// PC 端(addParentCopyWhenNoChildren==false):单头 total* 仍按明细树递归汇总;明细行净重/毛重/体积/面积<strong>不</strong>做「计划−已上架」覆盖,保持 shelf_material_detail 库表值
|
||||
if (!addParentCopyWhenNoChildren) {
|
||||
// PC上传页:指定仓库(维他奶仓)的待上架明细默认填充指定库位,供前端回显(PDA不填充,实际落库仍以上架提交时选择的库位为准)
|
||||
fillDefaultStorageLocation(stockShelfOrderPO, shelfMaterialDetailPOList);
|
||||
BigDecimal totalNetWeight = BigDecimal.ZERO;
|
||||
BigDecimal totalGrossWeight = BigDecimal.ZERO;
|
||||
BigDecimal totalVolume = BigDecimal.ZERO;
|
||||
@@ -2447,6 +2457,108 @@ public class StockShelfOrderApplicationService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PC上传页:为尚未指定上架库位的明细行默认填充指定仓库的指定库位
|
||||
* (按名称精确匹配 DEFAULT_SHELF_STORAGE_NAME 库区下的 DEFAULT_SHELF_STORAGE_LOCATION_NAME 库位,非取排序第一个)。
|
||||
* 仅回显默认值不落库:实际落库仍以上架提交时选择的库位为准(setStorageLocationInfo 会重新校验补全);
|
||||
* 已上架行的库表库位不覆盖,兼容二次上架。Feign失败或未匹配到目标库位时仅告警降级,不影响页面打开。
|
||||
*/
|
||||
private void fillDefaultStorageLocation(StockShelfOrderPO stockShelfOrderPO, List<ShelfMaterialDetailPO> shelfMaterialDetailPOList) {
|
||||
if (stockShelfOrderPO == null || CollectionUtils.isEmpty(shelfMaterialDetailPOList)) {
|
||||
return;
|
||||
}
|
||||
// 已完成上架的单据不再填充,避免展示从未实际使用的库位
|
||||
if (stockShelfOrderPO.getStatus() != null && stockShelfOrderPO.getStatus() > 2) {
|
||||
return;
|
||||
}
|
||||
// 仅指定仓库生效(按名称匹配,warehouseId跨环境不稳定)
|
||||
if (stockShelfOrderPO.getWarehouseId() == null
|
||||
|| !DEFAULT_STORAGE_LOCATION_WAREHOUSE_NAMES.contains(stockShelfOrderPO.getWarehouseName())) {
|
||||
return;
|
||||
}
|
||||
// 明细树中存在未填库位的行才发起查询
|
||||
if (!hasEmptyStorageLocationRecursively(shelfMaterialDetailPOList)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
AjaxResult warehouseChildrenResult = systemServiceFeign.getWarehouseChildren(stockShelfOrderPO.getWarehouseId());
|
||||
if (warehouseChildrenResult == null || !"200".equals(String.valueOf(warehouseChildrenResult.get("code")))
|
||||
|| warehouseChildrenResult.get("data") == null) {
|
||||
log.warn("获取仓库库位树失败,跳过默认上架库位填充,warehouseId={}", stockShelfOrderPO.getWarehouseId());
|
||||
return;
|
||||
}
|
||||
List<WarehouseLinkageFeignPO> warehouseLinkageList = JSON.parseArray(
|
||||
JSONObject.toJSONString(warehouseChildrenResult.get("data")), WarehouseLinkageFeignPO.class);
|
||||
if (CollectionUtils.isEmpty(warehouseLinkageList)) {
|
||||
return;
|
||||
}
|
||||
WarehouseLinkageFeignPO warehouse = warehouseLinkageList.get(0);
|
||||
if (CollectionUtils.isEmpty(warehouse.getChildren())) {
|
||||
return;
|
||||
}
|
||||
// 精确匹配指定的默认库区/库位(非取排序第一个)
|
||||
WarehouseLinkageFeignPO section = warehouse.getChildren().stream()
|
||||
.filter(sectionNode -> DEFAULT_SHELF_STORAGE_NAME.equals(sectionNode.getName()))
|
||||
.findFirst().orElse(null);
|
||||
if (section == null || CollectionUtils.isEmpty(section.getChildren())) {
|
||||
log.warn("未找到默认上架库区:{},warehouseId={},跳过默认库位填充",
|
||||
DEFAULT_SHELF_STORAGE_NAME, stockShelfOrderPO.getWarehouseId());
|
||||
return;
|
||||
}
|
||||
WarehouseLinkageFeignPO location = section.getChildren().stream()
|
||||
.filter(locationNode -> DEFAULT_SHELF_STORAGE_LOCATION_NAME.equals(locationNode.getName()))
|
||||
.findFirst().orElse(null);
|
||||
if (location == null) {
|
||||
log.warn("未找到默认上架库位:{}(库区:{}),warehouseId={},跳过默认库位填充",
|
||||
DEFAULT_SHELF_STORAGE_LOCATION_NAME, DEFAULT_SHELF_STORAGE_NAME, stockShelfOrderPO.getWarehouseId());
|
||||
return;
|
||||
}
|
||||
fillStorageLocationRecursively(shelfMaterialDetailPOList, warehouse, section, location);
|
||||
log.info("已为上架单填充默认上架库位,shelfOrderId={},shelfOrderNumber={},库位:{}-{}-{}(库位ID:{})",
|
||||
stockShelfOrderPO.getShelfOrderId(), stockShelfOrderPO.getShelfOrderNumber(),
|
||||
warehouse.getName(), section.getName(), location.getName(), location.getId());
|
||||
} catch (Exception e) {
|
||||
log.warn("填充默认上架库位失败,warehouseId={},错误:{}", stockShelfOrderPO.getWarehouseId(), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/** 明细树(含子行)中是否存在未指定库位(storageLocationId为空或0)的行 */
|
||||
private boolean hasEmptyStorageLocationRecursively(List<ShelfMaterialDetailPO> shelfMaterialDetailPOList) {
|
||||
for (ShelfMaterialDetailPO detail : shelfMaterialDetailPOList) {
|
||||
if (detail.getStorageLocationId() == null || detail.getStorageLocationId() == 0) {
|
||||
return true;
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(detail.getChildren())
|
||||
&& hasEmptyStorageLocationRecursively(detail.getChildren())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** 递归为未指定库位(storageLocationId为空或0)的明细行填充仓库/库区/库位信息,已有值不覆盖 */
|
||||
private void fillStorageLocationRecursively(List<ShelfMaterialDetailPO> shelfMaterialDetailPOList,
|
||||
WarehouseLinkageFeignPO warehouse,
|
||||
WarehouseLinkageFeignPO section,
|
||||
WarehouseLinkageFeignPO location) {
|
||||
for (ShelfMaterialDetailPO detail : shelfMaterialDetailPOList) {
|
||||
if (detail.getStorageLocationId() == null || detail.getStorageLocationId() == 0) {
|
||||
detail.setWarehouseId(warehouse.getId());
|
||||
detail.setWarehouseCode(warehouse.getCode());
|
||||
detail.setWarehouseName(warehouse.getName());
|
||||
detail.setStorageSectionId(section.getId());
|
||||
detail.setStorageCode(section.getCode());
|
||||
detail.setStorageName(section.getName());
|
||||
detail.setStorageLocationId(location.getId());
|
||||
detail.setStorageLocationCode(location.getCode());
|
||||
detail.setStorageLocationName(location.getName());
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(detail.getChildren())) {
|
||||
fillStorageLocationRecursively(detail.getChildren(), warehouse, section, location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据批次标签(batchLabels)映射到字段名
|
||||
* @param batchLabel 批次标签
|
||||
|
||||
Reference in New Issue
Block a user