PDA上架调整修改

This commit is contained in:
秦鸿展
2026-03-31 09:03:12 +08:00
parent 888a646c3e
commit 71f86798e5
7 changed files with 641 additions and 4 deletions
@@ -20,6 +20,9 @@ import com.mhd.system.api.domain.cache.AssociationWarehouseCacheDO;
import com.mhd.system.api.domain.cache.SystemServiceCacheUtil;
import com.mhd.system.api.model.LoginUser;
import com.mhd.wms.domain.inventoryAdjustmentRecord.entity.InventoryAdjustmentRecord;
import com.mhd.wms.domain.receiptMaterialDetail.repository.po.ReceiptMaterialDetailPO;
import com.mhd.wms.domain.receiptMaterialDetail.repository.todo.ReceiptMaterialDetailDO;
import com.mhd.wms.domain.receiptMaterialDetail.service.ReceiptMaterialDetailDomainService;
import com.mhd.wms.domain.materialBarCode.repository.facade.IMaterialBarCodeService;
import com.mhd.wms.domain.materialBarCode.repository.po.MaterialBarCodePO;
import com.mhd.wms.domain.materialBaseInfo.entity.MaterialBaseInfo;
@@ -36,6 +39,9 @@ import com.mhd.wms.domain.materialInventory.repository.mapper.MaterialInventoryM
import com.mhd.wms.domain.materialInventory.repository.po.MaterialInventoryPO;
import com.mhd.system.api.domain.BatchDetailFeignPO;
import com.mhd.wms.domain.materialMoreDetail.repository.po.MaterialMoreDetailPO;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailPO;
import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailDO;
import com.mhd.wms.domain.inMaterialDetail.service.InMaterialDetailDomainService;
import com.mhd.wms.domain.shelfMaterialDetail.repository.po.ShelfMaterialDetailPO;
import com.mhd.wms.domain.shelfMaterialDetail.repository.todo.ShelfMaterialDetailDO;
import com.mhd.wms.domain.shelfMaterialDetail.service.ShelfMaterialDetailDomainService;
@@ -75,6 +81,10 @@ public class StockShelfOrderApplicationService {
@Autowired
private ShelfMaterialDetailDomainService shelfMaterialDetailDomainService;
@Autowired
private InMaterialDetailDomainService inMaterialDetailDomainService;
@Autowired
private ReceiptMaterialDetailDomainService receiptMaterialDetailDomainService;
@Autowired
private UserServiceFeign userServiceFeign;
@Autowired
private SystemServiceFeign systemServiceFeign;
@@ -320,6 +330,374 @@ public class StockShelfOrderApplicationService {
return stockShelfOrderPO;
}
/**
* PDA 获取上架单详情:可按明细 shelvesStatus 做 tab 筛选(PC 不走该接口)
*
* @param shelfStatus 1=待上架(仅1/2)3=已上架(3/4/5)null 返回全部明细
*/
public StockShelfOrderPO getInfo(Long shelfOrderId, boolean addParentCopyWhenNoChildren, Integer shelfStatus) {
StockShelfOrderPO stockShelfOrderPO = getInfo(shelfOrderId, addParentCopyWhenNoChildren);
if (stockShelfOrderPO == null) {
return stockShelfOrderPO;
}
// 只在 PDA 场景下生效(addParentCopyWhenNoChildren==true
if (!addParentCopyWhenNoChildren) {
return stockShelfOrderPO;
}
List<ShelfMaterialDetailPO> materialDetailList = stockShelfOrderPO.getMaterialDetailList();
if (CollectionUtils.isEmpty(materialDetailList)) {
return stockShelfOrderPO;
}
if (shelfStatus != null) {
materialDetailList = filterShelfMaterialDetailsByShelfStatus(materialDetailList, shelfStatus);
}
// 已上架完成(3/4/5):主项无子项时注入的 parent_copy 与主项为同一明细,子行可能仍带「本次提交」的 shelves_quantity=0
// 导致「上架数量」误显示为 0;与主项对齐累计已上架数量后再做展示计算
alignParentCopyShelfQuantityWithParentForTerminal(materialDetailList);
// PDA 待上架数量 = 计划数量 - 已上架数量,仅接口计算(不落库)
fillPendingShelvesQuantityRecursively(materialDetailList);
// PDA 展示:shelvesQuantity 显示为累计已上架数量(与 receipt 口径一致);已上架完成行不再用本次提交量
syncShelvesQuantityCumulativeDisplayRecursively(materialDetailList);
// PDA 展示:净重/毛重/体积/面积
// - 待上架/上架中:展示 pending = 计划 - 已上架
// - 已上架(3/4/5):展示累计已上架(不计算 pending)
Map<Long, WeightMetrics> planWeightMetrics = loadReceiptPlanWeightMetrics(stockShelfOrderPO.getReceiptOrderNumber());
overwriteTotalWithPendingForPdaWeightDisplayRecursively(materialDetailList, planWeightMetrics);
syncMaterialMoreDetailWeightValuesRecursively(materialDetailList);
stockShelfOrderPO.setMaterialDetailList(materialDetailList);
return stockShelfOrderPO;
}
private List<ShelfMaterialDetailPO> filterShelfMaterialDetailsByShelfStatus(List<ShelfMaterialDetailPO> source, Integer shelfStatus) {
if (CollectionUtils.isEmpty(source) || shelfStatus == null) {
return source;
}
List<ShelfMaterialDetailPO> result = new ArrayList<>();
for (ShelfMaterialDetailPO item : source) {
if (item == null) {
continue;
}
List<ShelfMaterialDetailPO> filteredChildren = filterShelfMaterialDetailsByShelfStatus(item.getChildren(), shelfStatus);
item.setChildren(filteredChildren == null ? new ArrayList<>() : filteredChildren);
if (matchShelfDetailStatusFilter(item.getShelvesStatus(), shelfStatus) || !CollectionUtils.isEmpty(item.getChildren())) {
result.add(item);
}
}
return result;
}
private boolean matchShelfDetailStatusFilter(Integer detailShelvesStatus, Integer requestShelfStatus) {
if (detailShelvesStatus == null || requestShelfStatus == null) {
return false;
}
if (requestShelfStatus == 1) {
return detailShelvesStatus == 1 || detailShelvesStatus == 2;
}
if (requestShelfStatus == 3) {
return detailShelvesStatus == 3 || detailShelvesStatus == 4 || detailShelvesStatus == 5;
}
return true;
}
/**
* PDA 待上架数量递归计算:待上架数量 = max(0, 计划数量 - 已上架数量)
*/
private void fillPendingShelvesQuantityRecursively(List<ShelfMaterialDetailPO> list) {
if (CollectionUtils.isEmpty(list)) {
return;
}
for (ShelfMaterialDetailPO d : list) {
if (d == null) {
continue;
}
BigDecimal plan = d.getQuantity() != null ? d.getQuantity() : BigDecimal.ZERO;
BigDecimal already = d.getAlreadyShelvesQuantity() != null ? d.getAlreadyShelvesQuantity() : BigDecimal.ZERO;
BigDecimal pending = plan.subtract(already);
if (pending.compareTo(BigDecimal.ZERO) <= 0) {
pending = BigDecimal.ZERO;
}
d.setPendingShelvesQuantity(pending);
fillPendingShelvesQuantityRecursively(d.getChildren());
}
}
/**
* PDA:已上架完成时,将 parent_copy 子行的累计已上架数量与主项对齐(仅接口展示,不落库)。
* 否则详情页从 children 读数时「上架数量」仍为 0。
*/
private void alignParentCopyShelfQuantityWithParentForTerminal(List<ShelfMaterialDetailPO> list) {
if (CollectionUtils.isEmpty(list)) {
return;
}
for (ShelfMaterialDetailPO parent : list) {
if (parent == null) {
continue;
}
List<ShelfMaterialDetailPO> children = parent.getChildren();
if (!CollectionUtils.isEmpty(children)) {
ShelfMaterialDetailPO first = children.get(0);
if (first != null
&& isShelfParentCopyPo(parent, first)
&& isShelfTerminalShelvesStatus(parent.getShelvesStatus())) {
BigDecimal pAlready = parent.getAlreadyShelvesQuantity() != null
? parent.getAlreadyShelvesQuantity()
: BigDecimal.ZERO;
first.setAlreadyShelvesQuantity(pAlready);
first.setShelvesStatus(parent.getShelvesStatus());
}
alignParentCopyShelfQuantityWithParentForTerminal(children);
}
}
}
/**
* 判断子项是否为 getInfo 时注入的 parent_copy(与主项同 materialDetailId 或 uniqueId
*/
private static boolean isShelfParentCopyPo(ShelfMaterialDetailPO parent, ShelfMaterialDetailPO child) {
if (parent == null || child == null) {
return false;
}
Long parentId = parent.getMaterialDetailId();
Long childId = child.getMaterialDetailId();
Long parentUid = parent.getUniqueId();
Long childUid = child.getUniqueId();
if (parentId != null && parentId.equals(childId)) {
return true;
}
if (parentUid != null && parentUid.equals(childUid)) {
return true;
}
if (childId != null && parentId != null && !childId.equals(parentId)) {
return false;
}
if (childUid != null && parentUid != null && !childUid.equals(parentUid)) {
return false;
}
return childId == null && childUid == null;
}
/**
* PDA 展示把 shelvesQuantity 改为累计已上架数量(alreadyShelvesQuantity
* - 不落库:仅影响接口返回
* - 让前端“上架数量”展示字段与累计字段一致
* - 已上架完成(3/4/5):不再使用 DB 中「本次提交」的 shelves_quantity 语义,统一为已上架数量
*/
private void syncShelvesQuantityCumulativeDisplayRecursively(List<ShelfMaterialDetailPO> list) {
if (CollectionUtils.isEmpty(list)) {
return;
}
for (ShelfMaterialDetailPO d : list) {
if (d == null) {
continue;
}
BigDecimal already = d.getAlreadyShelvesQuantity() != null ? d.getAlreadyShelvesQuantity() : BigDecimal.ZERO;
d.setShelvesQuantity(already);
syncShelvesQuantityCumulativeDisplayRecursively(d.getChildren());
}
}
private static boolean isShelfTerminalShelvesStatus(Integer shelvesStatus) {
return shelvesStatus != null && (shelvesStatus == 3 || shelvesStatus == 4 || shelvesStatus == 5);
}
private static class WeightMetrics {
private BigDecimal netWeight;
private BigDecimal grossWeight;
private BigDecimal volume;
private BigDecimal area;
private WeightMetrics(BigDecimal netWeight, BigDecimal grossWeight, BigDecimal volume, BigDecimal area) {
this.netWeight = netWeight;
this.grossWeight = grossWeight;
this.volume = volume;
this.area = area;
}
}
/**
* 从收货单明细加载 PDA“计划净重/毛重/体积/面积”(用于 plan - already
* key
* - receipt_material_detail.unique_id
* - receipt_material_detail.in_unique_id(兼容部分场景只传 inUniqueId
*/
private Map<Long, WeightMetrics> loadReceiptPlanWeightMetrics(String receiptOrderNumber) {
Map<Long, WeightMetrics> result = new HashMap<>();
if (StringUtils.isBlank(receiptOrderNumber)) {
return result;
}
ReceiptMaterialDetailDO query = new ReceiptMaterialDetailDO();
query.setReceiptOrderNumber(receiptOrderNumber);
List<ReceiptMaterialDetailPO> list = receiptMaterialDetailDomainService.queryList(query);
if (CollectionUtils.isEmpty(list)) {
return result;
}
for (ReceiptMaterialDetailPO p : list) {
if (p == null || p.getUniqueId() == null) {
continue;
}
WeightMetrics metrics = new WeightMetrics(
p.getTotalNetWeight(),
p.getTotalGrossWeight(),
p.getTotalVolume(),
p.getTotalArea()
);
// key1:收货明细 unique_id
result.put(p.getUniqueId(), metrics);
// key2:兼容:有些上架明细可能只带 inUniqueId
if (p.getInUniqueId() != null) {
result.put(p.getInUniqueId(), metrics);
}
}
return result;
}
private void overwriteTotalWithPendingForPdaWeightDisplayRecursively(
List<ShelfMaterialDetailPO> list,
Map<Long, WeightMetrics> planWeightMetrics
) {
if (CollectionUtils.isEmpty(list)) {
return;
}
for (ShelfMaterialDetailPO d : list) {
if (d == null) {
continue;
}
// 已上架:不覆盖,展示累计已上架实绩(与 DB 同口径)
if (isShelfTerminalShelvesStatus(d.getShelvesStatus())) {
// 参考收货:已完成行不参与「计划−待收」,total* 直接展示累计 already
if (d.getAlreadyShelvesNetWeight() != null) {
d.setTotalNetWeight(d.getAlreadyShelvesNetWeight());
}
if (d.getAlreadyShelvesGrossWeight() != null) {
d.setTotalGrossWeight(d.getAlreadyShelvesGrossWeight());
}
if (d.getAlreadyShelvesVolume() != null) {
d.setTotalVolume(d.getAlreadyShelvesVolume());
}
if (d.getAlreadyShelvesArea() != null) {
d.setTotalArea(d.getAlreadyShelvesArea());
}
overwriteTotalWithPendingForPdaWeightDisplayRecursively(d.getChildren(), planWeightMetrics);
continue;
}
Long planKey = d.getReceiptUniqueId() != null ? d.getReceiptUniqueId() : d.getInUniqueId();
WeightMetrics plan = planWeightMetrics != null && planKey != null ? planWeightMetrics.get(planKey) : null;
BigDecimal planNet = plan != null ? plan.netWeight : null;
BigDecimal planGross = plan != null ? plan.grossWeight : null;
BigDecimal planVol = plan != null ? plan.volume : null;
BigDecimal planArea = plan != null ? plan.area : null;
BigDecimal alreadyNet = d.getAlreadyShelvesNetWeight() != null ? d.getAlreadyShelvesNetWeight() : BigDecimal.ZERO;
BigDecimal alreadyGross = d.getAlreadyShelvesGrossWeight() != null ? d.getAlreadyShelvesGrossWeight() : BigDecimal.ZERO;
BigDecimal alreadyVol = d.getAlreadyShelvesVolume() != null ? d.getAlreadyShelvesVolume() : BigDecimal.ZERO;
BigDecimal alreadyArea = d.getAlreadyShelvesArea() != null ? d.getAlreadyShelvesArea() : BigDecimal.ZERO;
// 参考收货:只对「有计划值」的字段覆盖 total*,否则保留原 total*
if (planNet == null && planGross == null && planVol == null && planArea == null) {
overwriteTotalWithPendingForPdaWeightDisplayRecursively(d.getChildren(), planWeightMetrics);
continue;
}
// 兜底:待上架(1/2) 且已上架数量为 0 时,
// DB 里的 total_* 可能被初始化为“计划值”,此时不应把它当作 already。
// 按“数量为准”把 already 权重当 0,使 pending 展示为计划值。
BigDecimal alreadyShelvesQty = d.getAlreadyShelvesQuantity() != null ? d.getAlreadyShelvesQuantity() : BigDecimal.ZERO;
boolean hasAlreadyQty = alreadyShelvesQty.compareTo(BigDecimal.ZERO) > 0;
if (!hasAlreadyQty) {
alreadyNet = BigDecimal.ZERO;
alreadyGross = BigDecimal.ZERO;
alreadyVol = BigDecimal.ZERO;
alreadyArea = BigDecimal.ZERO;
}
if (planNet != null) {
d.setTotalNetWeight(calcPendingMetric(planNet, alreadyNet));
}
if (planGross != null) {
d.setTotalGrossWeight(calcPendingMetric(planGross, alreadyGross));
}
if (planVol != null) {
d.setTotalVolume(calcPendingMetric(planVol, alreadyVol));
}
if (planArea != null) {
d.setTotalArea(calcPendingMetric(planArea, alreadyArea));
}
overwriteTotalWithPendingForPdaWeightDisplayRecursively(d.getChildren(), planWeightMetrics);
}
}
private static BigDecimal calcPendingMetric(BigDecimal plan, BigDecimal already) {
if (plan == null) {
return null;
}
BigDecimal pending = plan.subtract(already != null ? already : BigDecimal.ZERO);
if (pending.compareTo(BigDecimal.ZERO) <= 0) {
return BigDecimal.ZERO;
}
return normalizeDecimalForApi(pending);
}
private static BigDecimal normalizeDecimalForApi(BigDecimal v) {
if (v == null) {
return null;
}
if (v.compareTo(BigDecimal.ZERO) == 0) {
return BigDecimal.ZERO;
}
BigDecimal stripped = v.stripTrailingZeros();
return new BigDecimal(stripped.toPlainString());
}
private void syncMaterialMoreDetailWeightValuesRecursively(List<ShelfMaterialDetailPO> list) {
if (CollectionUtils.isEmpty(list)) {
return;
}
for (ShelfMaterialDetailPO d : list) {
if (d == null) {
continue;
}
if (!CollectionUtils.isEmpty(d.getMaterialMoreDetailList())) {
String netStr = d.getTotalNetWeight() != null ? d.getTotalNetWeight().toPlainString() : null;
String grossStr = d.getTotalGrossWeight() != null ? d.getTotalGrossWeight().toPlainString() : null;
String volStr = d.getTotalVolume() != null ? d.getTotalVolume().toPlainString() : null;
String areaStr = d.getTotalArea() != null ? d.getTotalArea().toPlainString() : null;
for (MaterialMoreDetailPO m : d.getMaterialMoreDetailList()) {
if (m == null || StringUtils.isBlank(m.getBatchLabels())) {
continue;
}
String labels = m.getBatchLabels().trim();
switch (labels) {
case "总净重":
case "净重(KG)":
case "净重":
m.setAttributeValue(netStr);
break;
case "总毛重":
case "毛重(KG)":
case "毛重":
m.setAttributeValue(grossStr);
break;
case "总体积":
case "体积(CBM)":
case "体积":
m.setAttributeValue(volStr);
break;
case "总面积":
case "面积(SQM)":
case "面积":
m.setAttributeValue(areaStr);
break;
default:
break;
}
}
}
syncMaterialMoreDetailWeightValuesRecursively(d.getChildren());
}
}
/**
* 获取上架单详细信息
*/
@@ -363,6 +741,8 @@ public class StockShelfOrderApplicationService {
* @return Boolean
*/
public Boolean upShelfByApp(StockShelfOrderDO stockReceiptOrderDO){
// 标记 PDA:权重/数量都按“累计”语义处理(与收货保持一致)
stockReceiptOrderDO.setFromApp(Boolean.TRUE);
List<ShelfMaterialDetailDO> shelfMaterialDetailDOList = stockReceiptOrderDO.getMaterialDetailList();
boolean firstItemHadChildrenBefore = !CollectionUtils.isEmpty(shelfMaterialDetailDOList)
&& !CollectionUtils.isEmpty(shelfMaterialDetailDOList.get(0).getChildren());
@@ -599,6 +979,11 @@ public class StockShelfOrderApplicationService {
if (stockShelfOrderPO.getStatus() > 2) {
throw new ServiceException("上架单已完成上架");
}
// PDAtotalNetWeight/totalGrossWeight/totalVolume/totalArea 按“增量”回传,需要累加到 DB 的 total*(不超过计划)
boolean fromApp = Boolean.TRUE.equals(stockShelfOrderDO.getFromApp());
Map<Long, WeightMetrics> planWeightMetrics = fromApp
? loadReceiptPlanWeightMetrics(stockShelfOrderPO.getReceiptOrderNumber())
: new HashMap<>();
StockShelfOrderDO returnStockShelfOrderDO = new StockShelfOrderDO();
BeanUtils.copyProperties(stockShelfOrderDO, returnStockShelfOrderDO);
returnStockShelfOrderDO.setShelfOrderId(stockShelfOrderPO.getShelfOrderId());
@@ -649,6 +1034,11 @@ public class StockShelfOrderApplicationService {
continue;
}
BigDecimal actualQuantity = BigDecimal.ZERO;//当前作业上架数
// PDA 权重/体积/面积:记录“本次增量”
BigDecimal netIncrement = BigDecimal.ZERO;
BigDecimal grossIncrement = BigDecimal.ZERO;
BigDecimal volIncrement = BigDecimal.ZERO;
BigDecimal areaIncrement = BigDecimal.ZERO;
//判断收否上架 第一次收货创建 更多属性 序列号
if (shelfMaterialDetailPO.getShelvesQuantity().compareTo(BigDecimal.ZERO) == 0){
//设置上架信息
@@ -663,7 +1053,23 @@ public class StockShelfOrderApplicationService {
//判断是否存在子项
List<ShelfMaterialDetailDO> returnShelfMaterialDetailDOChildList = new ArrayList<>();
List<ShelfMaterialDetailDO> shelfMaterialDetailDOChildList = shelfMaterialDetailDO.getChildren();
if (!CollectionUtils.isEmpty(shelfMaterialDetailDOChildList)){
// 叶子节点在第二次上架时,DB 里的 shelves_quantity 可能不为 0
// 旧逻辑只依赖 children 来计算 actualQuantity,导致 actualQuantity=0
// 从而 alreadyShelvesQuantity 不累计(覆盖问题的根因)。
// 当没有子项时,actualQuantity 应直接等于本次上架数量 shelvesQuantity。
if (CollectionUtils.isEmpty(shelfMaterialDetailDOChildList)) {
actualQuantity = shelvesQuantity;
if (fromApp) {
// 若本次未上架数量(shelvesQuantity=0),则不允许用 PDA 提交的重量更新累计值
// 否则会出现:数量仍为 0,但 total_* 已经被累加到计划值 => pending 全 0
if (shelvesQuantity.compareTo(BigDecimal.ZERO) > 0) {
netIncrement = shelfMaterialDetailDO.getTotalNetWeight() != null ? shelfMaterialDetailDO.getTotalNetWeight() : BigDecimal.ZERO;
grossIncrement = shelfMaterialDetailDO.getTotalGrossWeight() != null ? shelfMaterialDetailDO.getTotalGrossWeight() : BigDecimal.ZERO;
volIncrement = shelfMaterialDetailDO.getTotalVolume() != null ? shelfMaterialDetailDO.getTotalVolume() : BigDecimal.ZERO;
areaIncrement = shelfMaterialDetailDO.getTotalArea() != null ? shelfMaterialDetailDO.getTotalArea() : BigDecimal.ZERO;
}
}
} else {
for (ShelfMaterialDetailDO shelfMaterialDetailDOChild : shelfMaterialDetailDOChildList){
ShelfMaterialDetailPO shelfMaterialDetailPOChildDb = shelfMaterialDetailDbMap.get(shelfMaterialDetailDOChild.getMaterialDetailId());
if (shelfMaterialDetailPOChildDb == null && shelfMaterialDetailDOChild.getUniqueId() != null) {
@@ -673,12 +1079,100 @@ public class StockShelfOrderApplicationService {
}
}
BigDecimal childShelvesQty = shelfMaterialDetailDOChild.getShelvesQuantity() != null ? shelfMaterialDetailDOChild.getShelvesQuantity() : BigDecimal.ZERO;
if (fromApp) {
// 子项未上架数量时,不累加重量增量
BigDecimal childNetInc = childShelvesQty.compareTo(BigDecimal.ZERO) > 0
? (shelfMaterialDetailDOChild.getTotalNetWeight() != null ? shelfMaterialDetailDOChild.getTotalNetWeight() : BigDecimal.ZERO)
: BigDecimal.ZERO;
BigDecimal childGrossInc = childShelvesQty.compareTo(BigDecimal.ZERO) > 0
? (shelfMaterialDetailDOChild.getTotalGrossWeight() != null ? shelfMaterialDetailDOChild.getTotalGrossWeight() : BigDecimal.ZERO)
: BigDecimal.ZERO;
BigDecimal childVolInc = childShelvesQty.compareTo(BigDecimal.ZERO) > 0
? (shelfMaterialDetailDOChild.getTotalVolume() != null ? shelfMaterialDetailDOChild.getTotalVolume() : BigDecimal.ZERO)
: BigDecimal.ZERO;
BigDecimal childAreaInc = childShelvesQty.compareTo(BigDecimal.ZERO) > 0
? (shelfMaterialDetailDOChild.getTotalArea() != null ? shelfMaterialDetailDOChild.getTotalArea() : BigDecimal.ZERO)
: BigDecimal.ZERO;
// 汇总父项“本次增量”
netIncrement = netIncrement.add(childNetInc);
grossIncrement = grossIncrement.add(childGrossInc);
volIncrement = volIncrement.add(childVolInc);
areaIncrement = areaIncrement.add(childAreaInc);
}
if (shelfMaterialDetailPOChildDb != null){
// 子项已存在:累加上架数量,并加入返回列表供 batchShelfUpdate 更新(与收货一致,避免重复提交/漏更新)
actualQuantity = actualQuantity.add(childShelvesQty);
ShelfMaterialDetailDO returnShelfMaterialDetailDOChild = new ShelfMaterialDetailDO();
BeanUtils.copyProperties(shelfMaterialDetailPOChildDb, returnShelfMaterialDetailDOChild);
BeanUtils.copyProperties(shelfMaterialDetailDOChild, returnShelfMaterialDetailDOChild, IgnoreNullUtil.getNullPropertyNames(shelfMaterialDetailDOChild));
if (fromApp) {
// 子项已存在:total* 回传的是“本次增量”,需要累加到已有 already(并不超过计划)
// oldAlready:优先用 DB 的累计值 total_*。
// 但如果 DB 历史脏数据导致 already_shelves_quantity=0 时 total_* 也被初始化成“计划值”,
// 那么这些 total_* 不应再当作 already 基数参与累加(否则会被 min(plan, ...) 直接卡死为 plan)。
BigDecimal childOldAlreadyQty = shelfMaterialDetailPOChildDb.getAlreadyShelvesQuantity() != null
? shelfMaterialDetailPOChildDb.getAlreadyShelvesQuantity()
: BigDecimal.ZERO;
boolean childHasAlreadyQty = childOldAlreadyQty.compareTo(BigDecimal.ZERO) > 0;
BigDecimal childOldAlreadyNet = childHasAlreadyQty && shelfMaterialDetailPOChildDb.getTotalNetWeight() != null
? shelfMaterialDetailPOChildDb.getTotalNetWeight()
: BigDecimal.ZERO;
BigDecimal childOldAlreadyGross = childHasAlreadyQty && shelfMaterialDetailPOChildDb.getTotalGrossWeight() != null
? shelfMaterialDetailPOChildDb.getTotalGrossWeight()
: BigDecimal.ZERO;
BigDecimal childOldAlreadyVol = childHasAlreadyQty && shelfMaterialDetailPOChildDb.getTotalVolume() != null
? shelfMaterialDetailPOChildDb.getTotalVolume()
: BigDecimal.ZERO;
BigDecimal childOldAlreadyArea = childHasAlreadyQty && shelfMaterialDetailPOChildDb.getTotalArea() != null
? shelfMaterialDetailPOChildDb.getTotalArea()
: BigDecimal.ZERO;
WeightMetrics childPlan = shelfMaterialDetailPOChildDb.getInUniqueId() != null
? planWeightMetrics.get(shelfMaterialDetailPOChildDb.getReceiptUniqueId() != null
? shelfMaterialDetailPOChildDb.getReceiptUniqueId()
: shelfMaterialDetailPOChildDb.getInUniqueId())
: null;
// 子项未上架数量时,不累加重量增量(保持 DB already 不变)
BigDecimal childNetInc = childShelvesQty.compareTo(BigDecimal.ZERO) > 0
? (shelfMaterialDetailDOChild.getTotalNetWeight() != null ? shelfMaterialDetailDOChild.getTotalNetWeight() : BigDecimal.ZERO)
: BigDecimal.ZERO;
BigDecimal childGrossInc = childShelvesQty.compareTo(BigDecimal.ZERO) > 0
? (shelfMaterialDetailDOChild.getTotalGrossWeight() != null ? shelfMaterialDetailDOChild.getTotalGrossWeight() : BigDecimal.ZERO)
: BigDecimal.ZERO;
BigDecimal childVolInc = childShelvesQty.compareTo(BigDecimal.ZERO) > 0
? (shelfMaterialDetailDOChild.getTotalVolume() != null ? shelfMaterialDetailDOChild.getTotalVolume() : BigDecimal.ZERO)
: BigDecimal.ZERO;
BigDecimal childAreaInc = childShelvesQty.compareTo(BigDecimal.ZERO) > 0
? (shelfMaterialDetailDOChild.getTotalArea() != null ? shelfMaterialDetailDOChild.getTotalArea() : BigDecimal.ZERO)
: BigDecimal.ZERO;
BigDecimal childNewAlreadyNet = childOldAlreadyNet.add(childNetInc);
BigDecimal childNewAlreadyGross = childOldAlreadyGross.add(childGrossInc);
BigDecimal childNewAlreadyVol = childOldAlreadyVol.add(childVolInc);
BigDecimal childNewAlreadyArea = childOldAlreadyArea.add(childAreaInc);
if (childPlan != null) {
if (childPlan.netWeight != null && childNewAlreadyNet.compareTo(childPlan.netWeight) > 0) {
childNewAlreadyNet = childPlan.netWeight;
}
if (childPlan.grossWeight != null && childNewAlreadyGross.compareTo(childPlan.grossWeight) > 0) {
childNewAlreadyGross = childPlan.grossWeight;
}
if (childPlan.volume != null && childNewAlreadyVol.compareTo(childPlan.volume) > 0) {
childNewAlreadyVol = childPlan.volume;
}
if (childPlan.area != null && childNewAlreadyArea.compareTo(childPlan.area) > 0) {
childNewAlreadyArea = childPlan.area;
}
}
returnShelfMaterialDetailDOChild.setTotalNetWeight(childNewAlreadyNet);
returnShelfMaterialDetailDOChild.setTotalGrossWeight(childNewAlreadyGross);
returnShelfMaterialDetailDOChild.setTotalVolume(childNewAlreadyVol);
returnShelfMaterialDetailDOChild.setTotalArea(childNewAlreadyArea);
}
setStorageLocationInfo(returnShelfMaterialDetailDOChild);
returnShelfMaterialDetailDOChild.setAllowModify(2);
returnShelfMaterialDetailDOChild.setLevel(2);
@@ -691,6 +1185,47 @@ public class StockShelfOrderApplicationService {
BeanUtils.copyProperties(shelfMaterialDetailPO, returnShelfMaterialDetailDOChild, "materialDetailId","createBy","createByName","createTime",
"updateBy","updateByName","updateTime");
BeanUtils.copyProperties(shelfMaterialDetailDOChild, returnShelfMaterialDetailDOChild, IgnoreNullUtil.getNullPropertyNames(shelfMaterialDetailDOChild));
if (fromApp) {
// 子项不存在:new already = 0 + 本次增量(并不超过计划)
WeightMetrics childPlan = shelfMaterialDetailDOChild.getInUniqueId() != null
? planWeightMetrics.get(shelfMaterialDetailDOChild.getReceiptUniqueId() != null
? shelfMaterialDetailDOChild.getReceiptUniqueId()
: shelfMaterialDetailDOChild.getInUniqueId())
: null;
// 子项未上架数量时,不允许用 PDA 提交的 total_* 更新累计重量
BigDecimal childNewAlreadyNet = childShelvesQty.compareTo(BigDecimal.ZERO) > 0
? (shelfMaterialDetailDOChild.getTotalNetWeight() != null ? shelfMaterialDetailDOChild.getTotalNetWeight() : BigDecimal.ZERO)
: BigDecimal.ZERO;
BigDecimal childNewAlreadyGross = childShelvesQty.compareTo(BigDecimal.ZERO) > 0
? (shelfMaterialDetailDOChild.getTotalGrossWeight() != null ? shelfMaterialDetailDOChild.getTotalGrossWeight() : BigDecimal.ZERO)
: BigDecimal.ZERO;
BigDecimal childNewAlreadyVol = childShelvesQty.compareTo(BigDecimal.ZERO) > 0
? (shelfMaterialDetailDOChild.getTotalVolume() != null ? shelfMaterialDetailDOChild.getTotalVolume() : BigDecimal.ZERO)
: BigDecimal.ZERO;
BigDecimal childNewAlreadyArea = childShelvesQty.compareTo(BigDecimal.ZERO) > 0
? (shelfMaterialDetailDOChild.getTotalArea() != null ? shelfMaterialDetailDOChild.getTotalArea() : BigDecimal.ZERO)
: BigDecimal.ZERO;
if (childPlan != null) {
if (childPlan.netWeight != null && childNewAlreadyNet.compareTo(childPlan.netWeight) > 0) {
childNewAlreadyNet = childPlan.netWeight;
}
if (childPlan.grossWeight != null && childNewAlreadyGross.compareTo(childPlan.grossWeight) > 0) {
childNewAlreadyGross = childPlan.grossWeight;
}
if (childPlan.volume != null && childNewAlreadyVol.compareTo(childPlan.volume) > 0) {
childNewAlreadyVol = childPlan.volume;
}
if (childPlan.area != null && childNewAlreadyArea.compareTo(childPlan.area) > 0) {
childNewAlreadyArea = childPlan.area;
}
}
returnShelfMaterialDetailDOChild.setTotalNetWeight(childNewAlreadyNet);
returnShelfMaterialDetailDOChild.setTotalGrossWeight(childNewAlreadyGross);
returnShelfMaterialDetailDOChild.setTotalVolume(childNewAlreadyVol);
returnShelfMaterialDetailDOChild.setTotalArea(childNewAlreadyArea);
}
setStorageLocationInfo(shelfMaterialDetailDOChild);
returnShelfMaterialDetailDOChild.setAllowModify(2);
returnShelfMaterialDetailDOChild.setMaterialDetailSerialNumberList(shelfMaterialDetailDOChild.getMaterialDetailSerialNumberList());
@@ -710,6 +1245,58 @@ public class StockShelfOrderApplicationService {
}
//现在已上架数量=之前已上架数量+现在作业数量
shelfMaterialDetailDO.setAlreadyShelvesQuantity(shelfMaterialDetailPO.getAlreadyShelvesQuantity().add(actualQuantity));
if (fromApp) {
// 父项:total* 回传的是“本次增量”,需要累加到已有 already(并不超过计划)
// oldAlready:优先用 DB 的累计值 total_*。
// 但如果 DB 历史脏数据导致 already_shelves_quantity=0 时 total_* 也被初始化成“计划值”,
// 那么这些 total_* 不应再当作 already 基数参与累加(否则会被 min(plan, ...) 直接卡死为 plan)。
BigDecimal oldAlreadyQty = shelfMaterialDetailPO.getAlreadyShelvesQuantity() != null
? shelfMaterialDetailPO.getAlreadyShelvesQuantity()
: BigDecimal.ZERO;
boolean hasAlreadyQty = oldAlreadyQty.compareTo(BigDecimal.ZERO) > 0;
BigDecimal oldAlreadyNet = hasAlreadyQty && shelfMaterialDetailPO.getTotalNetWeight() != null
? shelfMaterialDetailPO.getTotalNetWeight()
: BigDecimal.ZERO;
BigDecimal oldAlreadyGross = hasAlreadyQty && shelfMaterialDetailPO.getTotalGrossWeight() != null
? shelfMaterialDetailPO.getTotalGrossWeight()
: BigDecimal.ZERO;
BigDecimal oldAlreadyVol = hasAlreadyQty && shelfMaterialDetailPO.getTotalVolume() != null
? shelfMaterialDetailPO.getTotalVolume()
: BigDecimal.ZERO;
BigDecimal oldAlreadyArea = hasAlreadyQty && shelfMaterialDetailPO.getTotalArea() != null
? shelfMaterialDetailPO.getTotalArea()
: BigDecimal.ZERO;
BigDecimal newAlreadyNet = oldAlreadyNet.add(netIncrement);
BigDecimal newAlreadyGross = oldAlreadyGross.add(grossIncrement);
BigDecimal newAlreadyVol = oldAlreadyVol.add(volIncrement);
BigDecimal newAlreadyArea = oldAlreadyArea.add(areaIncrement);
WeightMetrics plan = shelfMaterialDetailPO.getInUniqueId() != null
? planWeightMetrics.get(shelfMaterialDetailPO.getReceiptUniqueId() != null
? shelfMaterialDetailPO.getReceiptUniqueId()
: shelfMaterialDetailPO.getInUniqueId())
: null;
if (plan != null) {
if (plan.netWeight != null && newAlreadyNet.compareTo(plan.netWeight) > 0) {
newAlreadyNet = plan.netWeight;
}
if (plan.grossWeight != null && newAlreadyGross.compareTo(plan.grossWeight) > 0) {
newAlreadyGross = plan.grossWeight;
}
if (plan.volume != null && newAlreadyVol.compareTo(plan.volume) > 0) {
newAlreadyVol = plan.volume;
}
if (plan.area != null && newAlreadyArea.compareTo(plan.area) > 0) {
newAlreadyArea = plan.area;
}
}
shelfMaterialDetailDO.setTotalNetWeight(newAlreadyNet);
shelfMaterialDetailDO.setTotalGrossWeight(newAlreadyGross);
shelfMaterialDetailDO.setTotalVolume(newAlreadyVol);
shelfMaterialDetailDO.setTotalArea(newAlreadyArea);
}
//记录本次上架单上架总数
totalActualQuantity = totalActualQuantity.add(actualQuantity);
//判断上架数量是否大于计划数量
@@ -314,14 +314,26 @@ public class ShelfMaterialDetail extends BaseVOEntity {
@Excel(name = "总净重(KG)")
private BigDecimal totalNetWeight;
@ApiModelProperty("累计已上架净重(KG),与 totalNetWeight 同口径累加本次净重")
@TableField("total_net_weight")
private BigDecimal alreadyShelvesNetWeight;
@ApiModelProperty("总毛重(KG)")
@Excel(name = "总毛重(KG)")
private BigDecimal totalGrossWeight;
@ApiModelProperty("累计已上架毛重(KG),与 totalGrossWeight 同口径累加本次毛重")
@TableField("total_gross_weight")
private BigDecimal alreadyShelvesGrossWeight;
@ApiModelProperty("总体积(CBM)")
@Excel(name = "总体积(CBM)")
private BigDecimal totalVolume;
@ApiModelProperty("累计已上架体积(CBM),与 totalVolume 同口径累加本次体积")
@TableField("total_volume")
private BigDecimal alreadyShelvesVolume;
@ApiModelProperty("总面积(SQM)")
@Excel(name = "总面积(SQM)")
private BigDecimal totalArea;
@@ -333,4 +345,8 @@ public class ShelfMaterialDetail extends BaseVOEntity {
@ApiModelProperty("LOT编号")
@Excel(name = "LOT编号")
private String lotNumber;
@ApiModelProperty("累计已上架面积(SQM),与 totalArea 同口径累加本次面积")
@TableField("total_area")
private BigDecimal alreadyShelvesArea;
}
@@ -290,6 +290,7 @@ public class ShelfMaterialDetailImpl extends ServiceImpl<ShelfMaterialDetailMapp
throw new ServiceException("物料明细不能为空");
}
LoginUser loginUser = SecurityUtils.getLoginUser();
boolean fromApp = Boolean.TRUE.equals(stockShelfOrderDO.getFromApp());
//批量新增或修改物料信息
List<ShelfMaterialDetail> shelfMaterialDetailList = new ArrayList<>();
// 批量新增序列号
@@ -326,11 +327,21 @@ public class ShelfMaterialDetailImpl extends ServiceImpl<ShelfMaterialDetailMapp
totalActualQuantity = totalActualQuantity.add(childActualQuantity);
}
}
if (shelfMaterialDetailDO.getShelvesStatus() == 2){//部分上架 第二次上架 这次上架数量覆盖掉已上架数量
// 不要覆盖累计已上架数量:alreadyShelvesQuantity 应由上层 assembleParamByShelf 累计计算
// 仅当 alreadyShelvesQuantity 为空时,才回退到 shelvesQuantity(兼容旧/缺字段场景)
if (shelfMaterialDetailDO.getAlreadyShelvesQuantity() == null) {
shelfMaterialDetailDO.setAlreadyShelvesQuantity(shelfMaterialDetailDO.getShelvesQuantity());
}
ShelfMaterialDetail shelfMaterialDetail = new ShelfMaterialDetail();
BeanUtils.copyProperties(shelfMaterialDetailDO, shelfMaterialDetail);
// PDA:明细表 shelves_quantity 也要跟累计 already_shelves_quantity 同步
// PC:保持旧语义(shelves_quantity=本次上架数量)
if (fromApp) {
BigDecimal already = shelfMaterialDetailDO.getAlreadyShelvesQuantity();
if (already != null) {
shelfMaterialDetail.setShelvesQuantity(already);
}
}
shelfMaterialDetail.setUpdateBy(loginUser.getUserid());
shelfMaterialDetail.setUpdateByName(loginUser.getUsername());
shelfMaterialDetail.setUpdateTime(new Date());
@@ -77,6 +77,10 @@ public class ShelfMaterialDetailPO extends BaseVOEntity {
@Excel(name = "已上架数量")
private BigDecimal alreadyShelvesQuantity;
@ApiModelProperty("待上架数量")
@Excel(name = "待上架数量")
private BigDecimal pendingShelvesQuantity;
@ApiModelProperty("上架数量")
@Excel(name = "上架数量")
private BigDecimal shelvesQuantity;
@@ -317,18 +321,30 @@ public class ShelfMaterialDetailPO extends BaseVOEntity {
@Excel(name = "总净重(KG)")
private BigDecimal totalNetWeight;
@ApiModelProperty("累计已上架净重(KG),与 totalNetWeight 同口径累加本次净重")
private BigDecimal alreadyShelvesNetWeight;
@ApiModelProperty("总毛重(KG)")
@Excel(name = "总毛重(KG)")
private BigDecimal totalGrossWeight;
@ApiModelProperty("累计已上架毛重(KG),与 totalGrossWeight 同口径累加本次毛重")
private BigDecimal alreadyShelvesGrossWeight;
@ApiModelProperty("总体积(CBM)")
@Excel(name = "总体积(CBM)")
private BigDecimal totalVolume;
@ApiModelProperty("累计已上架体积(CBM),与 totalVolume 同口径累加本次体积")
private BigDecimal alreadyShelvesVolume;
@ApiModelProperty("总面积(SQM)")
@Excel(name = "总面积(SQM)")
private BigDecimal totalArea;
@ApiModelProperty("累计已上架面积(SQM),与 totalArea 同口径累加本次面积")
private BigDecimal alreadyShelvesArea;
@ApiModelProperty("入库单号")
@Excel(name = "入库单号")
private String inOrderNumber;
@@ -51,9 +51,11 @@ public class StockShelfOrderAppApi extends BaseController {
*/
@ApiOperation("获取上架单")
@GetMapping(value = "/getInfo")
public AjaxResult getInfo(Long shelfOrderId)
public AjaxResult getInfo(Long shelfOrderId,
@RequestParam(required = false) Integer shelfStatus)
{
return AjaxResult.success(stockShelfOrderApplicationService.getInfo(shelfOrderId, true));
// 仅 PDA 支持根据明细 shelvesStatus 做筛选:1 待上架(仅1/2)3 已上架(3/4/5)
return AjaxResult.success(stockShelfOrderApplicationService.getInfo(shelfOrderId, true, shelfStatus));
}
@@ -9,6 +9,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="organizationId" column="organization_id" />
<result property="organizationName" column="organization_name" />
<result property="topOrganizationId" column="top_organization_id" />
<result property="uniqueId" column="unique_id" />
<result property="materialBaseInfoId" column="material_base_info_id" />
<result property="materialCode" column="material_code" />
<result property="materialName" column="material_name" />
@@ -62,11 +62,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="extAttr3" column="ext_attr_3" />
<result property="extAttr4" column="ext_attr_4" />
<result property="totalNetWeight" column="total_net_weight" />
<result property="alreadyShelvesNetWeight" column="total_net_weight" />
<result property="totalGrossWeight" column="total_gross_weight" />
<result property="alreadyShelvesGrossWeight" column="total_gross_weight" />
<result property="totalVolume" column="total_volume" />
<result property="alreadyShelvesVolume" column="total_volume" />
<result property="totalArea" column="total_area" />
<result property="inOrderNumber" column="in_order_number" />
<result property="lotNumber" column="lot_number" />
<result property="alreadyShelvesArea" column="total_area" />
</resultMap>