diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockShelfOrder/StockShelfOrderApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockShelfOrder/StockShelfOrderApplicationService.java index 470b71f21..a8e42c4c3 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockShelfOrder/StockShelfOrderApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockShelfOrder/StockShelfOrderApplicationService.java @@ -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 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 planWeightMetrics = loadReceiptPlanWeightMetrics(stockShelfOrderPO.getReceiptOrderNumber()); + overwriteTotalWithPendingForPdaWeightDisplayRecursively(materialDetailList, planWeightMetrics); + syncMaterialMoreDetailWeightValuesRecursively(materialDetailList); + stockShelfOrderPO.setMaterialDetailList(materialDetailList); + return stockShelfOrderPO; + } + + private List filterShelfMaterialDetailsByShelfStatus(List source, Integer shelfStatus) { + if (CollectionUtils.isEmpty(source) || shelfStatus == null) { + return source; + } + List result = new ArrayList<>(); + for (ShelfMaterialDetailPO item : source) { + if (item == null) { + continue; + } + List 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 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 list) { + if (CollectionUtils.isEmpty(list)) { + return; + } + for (ShelfMaterialDetailPO parent : list) { + if (parent == null) { + continue; + } + List 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 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 loadReceiptPlanWeightMetrics(String receiptOrderNumber) { + Map result = new HashMap<>(); + if (StringUtils.isBlank(receiptOrderNumber)) { + return result; + } + ReceiptMaterialDetailDO query = new ReceiptMaterialDetailDO(); + query.setReceiptOrderNumber(receiptOrderNumber); + List 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 list, + Map 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 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 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("上架单已完成上架"); } + // PDA:totalNetWeight/totalGrossWeight/totalVolume/totalArea 按“增量”回传,需要累加到 DB 的 total*(不超过计划) + boolean fromApp = Boolean.TRUE.equals(stockShelfOrderDO.getFromApp()); + Map 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 returnShelfMaterialDetailDOChildList = new ArrayList<>(); List 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); //判断上架数量是否大于计划数量 diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/shelfMaterialDetail/entity/ShelfMaterialDetail.java b/mhd_wms/src/main/java/com/mhd/wms/domain/shelfMaterialDetail/entity/ShelfMaterialDetail.java index a7f246974..edc640bc7 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/shelfMaterialDetail/entity/ShelfMaterialDetail.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/shelfMaterialDetail/entity/ShelfMaterialDetail.java @@ -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; } \ No newline at end of file diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/shelfMaterialDetail/repository/persistence/ShelfMaterialDetailImpl.java b/mhd_wms/src/main/java/com/mhd/wms/domain/shelfMaterialDetail/repository/persistence/ShelfMaterialDetailImpl.java index fda1e7127..15a19c181 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/shelfMaterialDetail/repository/persistence/ShelfMaterialDetailImpl.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/shelfMaterialDetail/repository/persistence/ShelfMaterialDetailImpl.java @@ -290,6 +290,7 @@ public class ShelfMaterialDetailImpl extends ServiceImpl shelfMaterialDetailList = new ArrayList<>(); // 批量新增序列号 @@ -326,11 +327,21 @@ public class ShelfMaterialDetailImpl extends ServiceImpl + diff --git a/mhd_wms/src/main/resources/mapper/shelfMaterialDetail/ShelfMaterialDetailMapper.xml b/mhd_wms/src/main/resources/mapper/shelfMaterialDetail/ShelfMaterialDetailMapper.xml index c4226ae08..1d1259c61 100644 --- a/mhd_wms/src/main/resources/mapper/shelfMaterialDetail/ShelfMaterialDetailMapper.xml +++ b/mhd_wms/src/main/resources/mapper/shelfMaterialDetail/ShelfMaterialDetailMapper.xml @@ -62,11 +62,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + + +