PDA收货详情查询修改
This commit is contained in:
+203
-12
@@ -285,6 +285,8 @@ public class StockReceiptOrderApplicationService {
|
||||
flattenMaterialDetailList(receiptMaterialDetailPOList);
|
||||
// PC 端子项计划数量不展示:递归清空所有子项的 quantity
|
||||
clearChildQuantityRecursively(receiptMaterialDetailPOList);
|
||||
// 计算待收货数量 = 计划数量 - 已收货数量
|
||||
fillPendingReceiptQuantityRecursively(receiptMaterialDetailPOList);
|
||||
stockReceiptOrderPO.setMaterialDetailList(receiptMaterialDetailPOList);
|
||||
log.info("返回收货单信息,receiptOrderId={}, materialDetailList大小={}, totalNetWeight={}, totalGrossWeight={}, totalVolume={}, totalArea={}",
|
||||
stockReceiptOrderPO.getReceiptOrderId(),
|
||||
@@ -451,6 +453,89 @@ public class StockReceiptOrderApplicationService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归计算并填充待收货数量:待收货数量 = 计划数量 - 已收货数量
|
||||
*/
|
||||
private void fillPendingReceiptQuantityRecursively(List<ReceiptMaterialDetailPO> receiptMaterialDetailPOList) {
|
||||
if (CollectionUtils.isEmpty(receiptMaterialDetailPOList)) {
|
||||
return;
|
||||
}
|
||||
for (ReceiptMaterialDetailPO detail : receiptMaterialDetailPOList) {
|
||||
BigDecimal quantity = detail.getQuantity() != null ? detail.getQuantity() : BigDecimal.ZERO;
|
||||
BigDecimal alreadyReceiptQuantity = detail.getAlreadyReceiptQuantity() != null ? detail.getAlreadyReceiptQuantity() : BigDecimal.ZERO;
|
||||
BigDecimal pending = quantity.subtract(alreadyReceiptQuantity);
|
||||
detail.setPendingReceiptQuantity(pending.compareTo(BigDecimal.ZERO) > 0 ? pending : BigDecimal.ZERO);
|
||||
List<ReceiptMaterialDetailPO> children = detail.getChildren();
|
||||
if (!CollectionUtils.isEmpty(children)) {
|
||||
fillPendingReceiptQuantityRecursively(children);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PDA详情展示:按“计划-已收”计算待收字段
|
||||
*/
|
||||
private void fillPendingDisplayFieldsRecursively(List<ReceiptMaterialDetailPO> receiptMaterialDetailPOList) {
|
||||
if (CollectionUtils.isEmpty(receiptMaterialDetailPOList)) {
|
||||
return;
|
||||
}
|
||||
for (ReceiptMaterialDetailPO detail : receiptMaterialDetailPOList) {
|
||||
BigDecimal quantity = detail.getQuantity() != null ? detail.getQuantity() : BigDecimal.ZERO;
|
||||
BigDecimal alreadyReceiptQuantity = detail.getAlreadyReceiptQuantity() != null ? detail.getAlreadyReceiptQuantity() : BigDecimal.ZERO;
|
||||
BigDecimal pendingQuantity = quantity.subtract(alreadyReceiptQuantity);
|
||||
if (pendingQuantity.compareTo(BigDecimal.ZERO) < 0) {
|
||||
pendingQuantity = BigDecimal.ZERO;
|
||||
}
|
||||
detail.setPendingReceiptQuantity(pendingQuantity);
|
||||
// 按需求:收货数量展示为待收数量
|
||||
detail.setReceiptQuantity(pendingQuantity);
|
||||
|
||||
// 计划值 - 已收值;已收值按数量比例折算
|
||||
detail.setTotalGrossWeight(calcPendingMetric(detail.getTotalGrossWeight(), quantity, alreadyReceiptQuantity));
|
||||
detail.setTotalNetWeight(calcPendingMetric(detail.getTotalNetWeight(), quantity, alreadyReceiptQuantity));
|
||||
detail.setTotalVolume(calcPendingMetric(detail.getTotalVolume(), quantity, alreadyReceiptQuantity));
|
||||
detail.setTotalArea(calcPendingMetric(detail.getTotalArea(), quantity, alreadyReceiptQuantity));
|
||||
|
||||
List<ReceiptMaterialDetailPO> children = detail.getChildren();
|
||||
if (!CollectionUtils.isEmpty(children)) {
|
||||
fillPendingDisplayFieldsRecursively(children);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 详情展示:仅回填待收毛重/净重/体积/面积,避免影响数量字段口径
|
||||
*/
|
||||
private void fillPendingMetricsOnlyRecursively(List<ReceiptMaterialDetailPO> receiptMaterialDetailPOList) {
|
||||
if (CollectionUtils.isEmpty(receiptMaterialDetailPOList)) {
|
||||
return;
|
||||
}
|
||||
for (ReceiptMaterialDetailPO detail : receiptMaterialDetailPOList) {
|
||||
BigDecimal quantity = detail.getQuantity() != null ? detail.getQuantity() : BigDecimal.ZERO;
|
||||
BigDecimal alreadyReceiptQuantity = detail.getAlreadyReceiptQuantity() != null ? detail.getAlreadyReceiptQuantity() : BigDecimal.ZERO;
|
||||
detail.setTotalGrossWeight(calcPendingMetric(detail.getTotalGrossWeight(), quantity, alreadyReceiptQuantity));
|
||||
detail.setTotalNetWeight(calcPendingMetric(detail.getTotalNetWeight(), quantity, alreadyReceiptQuantity));
|
||||
detail.setTotalVolume(calcPendingMetric(detail.getTotalVolume(), quantity, alreadyReceiptQuantity));
|
||||
detail.setTotalArea(calcPendingMetric(detail.getTotalArea(), quantity, alreadyReceiptQuantity));
|
||||
if (!CollectionUtils.isEmpty(detail.getChildren())) {
|
||||
fillPendingMetricsOnlyRecursively(detail.getChildren());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private BigDecimal calcPendingMetric(BigDecimal planMetric, BigDecimal quantity, BigDecimal alreadyReceiptQuantity) {
|
||||
if (planMetric == null) {
|
||||
return null;
|
||||
}
|
||||
if (quantity == null || quantity.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return planMetric;
|
||||
}
|
||||
BigDecimal alreadyRatio = (alreadyReceiptQuantity == null ? BigDecimal.ZERO : alreadyReceiptQuantity)
|
||||
.divide(quantity, 8, java.math.RoundingMode.HALF_UP);
|
||||
BigDecimal pendingMetric = planMetric.subtract(planMetric.multiply(alreadyRatio));
|
||||
return pendingMetric.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : pendingMetric;
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归为物料明细设置更多属性
|
||||
@@ -933,11 +1018,22 @@ public class StockReceiptOrderApplicationService {
|
||||
* 获取收货单详细信息(PDA 端)
|
||||
* 在 Domain 层结果基础上,补充包装规格填充,与 PC 端 getInfo 一致
|
||||
*/
|
||||
public StockReceiptOrderPO getInfoByApp(Long receiptOrderId)
|
||||
public StockReceiptOrderPO getInfoByApp(Long receiptOrderId, Integer receiptStatus)
|
||||
{
|
||||
StockReceiptOrderPO stockReceiptOrderPO = stockReceiptOrderDomainService.getInfoByApp(receiptOrderId);
|
||||
if (stockReceiptOrderPO == null) {
|
||||
return null;
|
||||
}
|
||||
List<ReceiptMaterialDetailPO> materialDetailList = stockReceiptOrderPO.getMaterialDetailList();
|
||||
if (!CollectionUtils.isEmpty(materialDetailList)) {
|
||||
// PDA 详情按明细收货状态过滤:1=待收货/收货中(明细状态1、2),3=已收货(明细状态3)
|
||||
if (receiptStatus != null) {
|
||||
materialDetailList = filterMaterialDetailsByReceiptStatus(materialDetailList, receiptStatus);
|
||||
stockReceiptOrderPO.setMaterialDetailList(materialDetailList);
|
||||
}
|
||||
if (CollectionUtils.isEmpty(materialDetailList)) {
|
||||
return stockReceiptOrderPO;
|
||||
}
|
||||
Set<Long> materialBaseInfoIdSet = new HashSet<>();
|
||||
collectMaterialBaseInfoIdsRecursively(materialDetailList, materialBaseInfoIdSet);
|
||||
Map<Long, MaterialBaseInfoPO> materialBaseInfoMap = new HashMap<>();
|
||||
@@ -981,10 +1077,53 @@ public class StockReceiptOrderApplicationService {
|
||||
// PDA 端与 PC 端一致:主行收货数量取第一条子项,已收货数量汇总所有子项
|
||||
flattenMaterialDetailList(materialDetailList);
|
||||
clearChildQuantityRecursively(materialDetailList);
|
||||
// 收货详情:总毛重/净重/体积/面积按“计划-已收”展示
|
||||
fillPendingMetricsOnlyRecursively(materialDetailList);
|
||||
// 仅在 PDA 详情筛选“待收/收货中”时,按待收口径回填展示字段
|
||||
if (receiptStatus != null && receiptStatus == 1) {
|
||||
// 按“计划-已收”回填待收展示字段(数量/毛净重/体积/面积)
|
||||
fillPendingDisplayFieldsRecursively(materialDetailList);
|
||||
} else {
|
||||
// 其他场景保持原始详情口径,仅补充待收数量字段
|
||||
fillPendingReceiptQuantityRecursively(materialDetailList);
|
||||
}
|
||||
}
|
||||
return stockReceiptOrderPO;
|
||||
}
|
||||
|
||||
private List<ReceiptMaterialDetailPO> filterMaterialDetailsByReceiptStatus(List<ReceiptMaterialDetailPO> source, Integer receiptStatus) {
|
||||
if (CollectionUtils.isEmpty(source) || receiptStatus == null) {
|
||||
return source;
|
||||
}
|
||||
List<ReceiptMaterialDetailPO> result = new ArrayList<>();
|
||||
for (ReceiptMaterialDetailPO item : source) {
|
||||
if (item == null) {
|
||||
continue;
|
||||
}
|
||||
// 先递归过滤子项
|
||||
List<ReceiptMaterialDetailPO> filteredChildren = filterMaterialDetailsByReceiptStatus(item.getChildren(), receiptStatus);
|
||||
item.setChildren(filteredChildren == null ? new ArrayList<>() : filteredChildren);
|
||||
// 父项命中或存在命中的子项都保留,保证树结构可展示
|
||||
if (matchReceiptStatus(item.getReceiptStatus(), receiptStatus) || !CollectionUtils.isEmpty(item.getChildren())) {
|
||||
result.add(item);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean matchReceiptStatus(Integer detailStatus, Integer receiptStatus) {
|
||||
if (detailStatus == null || receiptStatus == null) {
|
||||
return false;
|
||||
}
|
||||
if (receiptStatus == 1) {
|
||||
return detailStatus == 1 || detailStatus == 2;
|
||||
}
|
||||
if (receiptStatus == 3) {
|
||||
return detailStatus == 3;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归收集明细树中所有物料基础信息ID
|
||||
*/
|
||||
@@ -1078,6 +1217,8 @@ public class StockReceiptOrderApplicationService {
|
||||
*/
|
||||
public Boolean receivingGoodsByApp(StockReceiptOrderDO stockReceiptOrderDO){
|
||||
List<ReceiptMaterialDetailDO> list = stockReceiptOrderDO.getMaterialDetailList();
|
||||
// 超计划提示:实际收货数量 > 待收数量(计划-已收) 时,先提示确认
|
||||
checkOverPlanReceiptForApp(stockReceiptOrderDO);
|
||||
// 记录 PDA 传入时第一项是否已有 children
|
||||
boolean firstItemHadChildrenBefore = !CollectionUtils.isEmpty(list)
|
||||
&& !CollectionUtils.isEmpty(list.get(0).getChildren());
|
||||
@@ -1097,6 +1238,60 @@ public class StockReceiptOrderApplicationService {
|
||||
return stockReceiptOrderDomainService.receivingGoods(assembleStockReceiptOrderDO);
|
||||
}
|
||||
|
||||
private void checkOverPlanReceiptForApp(StockReceiptOrderDO stockReceiptOrderDO) {
|
||||
if (stockReceiptOrderDO == null || CollectionUtils.isEmpty(stockReceiptOrderDO.getMaterialDetailList())) {
|
||||
return;
|
||||
}
|
||||
StockReceiptOrderPO dbOrder = stockReceiptOrderDomainService.getInfo(stockReceiptOrderDO.getReceiptOrderId());
|
||||
if (dbOrder == null) {
|
||||
return;
|
||||
}
|
||||
ReceiptMaterialDetailDO queryDO = new ReceiptMaterialDetailDO();
|
||||
queryDO.setReceiptOrderNumber(dbOrder.getReceiptOrderNumber());
|
||||
List<ReceiptMaterialDetailPO> dbList = receiptMaterialDetailDomainService.queryList(queryDO);
|
||||
Map<Long, ReceiptMaterialDetailPO> dbById = dbList.stream()
|
||||
.filter(x -> x.getMaterialDetailId() != null)
|
||||
.collect(Collectors.toMap(ReceiptMaterialDetailPO::getMaterialDetailId, Function.identity(), (a, b) -> a));
|
||||
Map<Long, ReceiptMaterialDetailPO> dbByUniqueId = dbList.stream()
|
||||
.filter(x -> x.getUniqueId() != null)
|
||||
.collect(Collectors.toMap(ReceiptMaterialDetailPO::getUniqueId, Function.identity(), (a, b) -> a));
|
||||
for (ReceiptMaterialDetailDO item : stockReceiptOrderDO.getMaterialDetailList()) {
|
||||
validateOverPlanNode(item, dbById, dbByUniqueId);
|
||||
}
|
||||
}
|
||||
|
||||
private void validateOverPlanNode(ReceiptMaterialDetailDO item,
|
||||
Map<Long, ReceiptMaterialDetailPO> dbById,
|
||||
Map<Long, ReceiptMaterialDetailPO> dbByUniqueId) {
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
ReceiptMaterialDetailPO db = null;
|
||||
if (item.getMaterialDetailId() != null) {
|
||||
db = dbById.get(item.getMaterialDetailId());
|
||||
}
|
||||
if (db == null && item.getUniqueId() != null) {
|
||||
db = dbByUniqueId.get(item.getUniqueId());
|
||||
}
|
||||
if (db != null) {
|
||||
BigDecimal plan = db.getQuantity() != null ? db.getQuantity() : BigDecimal.ZERO;
|
||||
BigDecimal already = db.getAlreadyReceiptQuantity() != null ? db.getAlreadyReceiptQuantity() : BigDecimal.ZERO;
|
||||
BigDecimal pending = plan.subtract(already);
|
||||
if (pending.compareTo(BigDecimal.ZERO) < 0) {
|
||||
pending = BigDecimal.ZERO;
|
||||
}
|
||||
BigDecimal current = item.getReceiptQuantity() != null ? item.getReceiptQuantity() : BigDecimal.ZERO;
|
||||
if (current.compareTo(pending) > 0) {
|
||||
throw new ServiceException("当前物料实收数量大于计划收货数量,是否确认收货");
|
||||
}
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(item.getChildren())) {
|
||||
for (ReceiptMaterialDetailDO child : item.getChildren()) {
|
||||
validateOverPlanNode(child, dbById, dbByUniqueId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 收货时:将 children 中第一条的值赋给主项,并删除第一条。
|
||||
* PDA 收两条时只生成 2 条(主项 + 第二条子项),主项展示第一条子项的数据。
|
||||
@@ -1382,7 +1577,8 @@ public class StockReceiptOrderApplicationService {
|
||||
//设置物料状态及容器信息
|
||||
setMaterialMoreDetailInfo(receiptMaterialDetailDO);
|
||||
}
|
||||
// 主项本次收货增量 = 新子项数量 + 已存在子项的本次收货增量(PDA 传子项累计值时:child.receiptQuantity - childDb.alreadyReceiptQuantity)
|
||||
// 主项本次收货增量 = 新子项数量 + 已存在子项的本次收货增量
|
||||
// 统一口径:PDA 上传的 receiptQuantity 视为“本次收货量”,不再按累计值覆盖
|
||||
BigDecimal newChildrenTotalQuantity = BigDecimal.ZERO;
|
||||
BigDecimal existingChildrenIncrement = BigDecimal.ZERO;
|
||||
List<ReceiptMaterialDetailDO> receiptMaterialDetailDOChildList = receiptMaterialDetailDO.getChildren();
|
||||
@@ -1396,14 +1592,11 @@ public class StockReceiptOrderApplicationService {
|
||||
BigDecimal childDbAlready = receiptMaterialDetailPOChildDb != null && receiptMaterialDetailPOChildDb.getAlreadyReceiptQuantity() != null
|
||||
? receiptMaterialDetailPOChildDb.getAlreadyReceiptQuantity() : BigDecimal.ZERO;
|
||||
if (receiptMaterialDetailPOChildDb == null) {
|
||||
// 新子项:累加其收货数量
|
||||
// 新子项:累加其本次收货量
|
||||
newChildrenTotalQuantity = newChildrenTotalQuantity.add(childQty);
|
||||
} else {
|
||||
// 已存在子项:累加本次增量(PDA 传累计值,增量 = 本次值 - DB 已收值)
|
||||
BigDecimal delta = childQty.subtract(childDbAlready);
|
||||
if (delta.compareTo(BigDecimal.ZERO) > 0) {
|
||||
existingChildrenIncrement = existingChildrenIncrement.add(delta);
|
||||
}
|
||||
// 已存在子项:累加其本次收货量
|
||||
existingChildrenIncrement = existingChildrenIncrement.add(childQty);
|
||||
}
|
||||
BigDecimal childReceiptQty = receiptMaterialDetailDOChild.getReceiptQuantity() != null ? receiptMaterialDetailDOChild.getReceiptQuantity() : BigDecimal.ZERO;
|
||||
ReceiptMaterialDetailDO returnReceiptMaterialDetailDOChild = new ReceiptMaterialDetailDO();
|
||||
@@ -1411,10 +1604,8 @@ public class StockReceiptOrderApplicationService {
|
||||
// 子项已存在:用 DB 数据 + PDA 收货数据组装,保证不同明细独立收货不被丢失
|
||||
BeanUtils.copyProperties(receiptMaterialDetailPOChildDb, returnReceiptMaterialDetailDOChild);
|
||||
BeanUtils.copyProperties(receiptMaterialDetailDOChild, returnReceiptMaterialDetailDOChild, IgnoreNullUtil.getNullPropertyNames(receiptMaterialDetailDOChild));
|
||||
// PDA 传子项累计值时,更新子项已收数量(取较大值,确保第二次及以后收货时子项已收数正确)
|
||||
if (childQty.compareTo(childDbAlready) > 0) {
|
||||
returnReceiptMaterialDetailDOChild.setAlreadyReceiptQuantity(childQty);
|
||||
}
|
||||
// 子项统一按“本次收货量”累加
|
||||
returnReceiptMaterialDetailDOChild.setAlreadyReceiptQuantity(childDbAlready.add(childQty));
|
||||
returnReceiptMaterialDetailDOChild.setAllowModify(2);
|
||||
returnReceiptMaterialDetailDOChild.setLevel(2);
|
||||
returnReceiptMaterialDetailDOChild.setParentUniqueId(receiptMaterialDetailPO.getUniqueId());
|
||||
|
||||
+4
@@ -80,6 +80,10 @@ public class ReceiptMaterialDetailPO extends BaseVOEntity {
|
||||
@Excel(name = "已收货数量")
|
||||
private BigDecimal alreadyReceiptQuantity;
|
||||
|
||||
@ApiModelProperty("待收货数量")
|
||||
@Excel(name = "待收货数量")
|
||||
private BigDecimal pendingReceiptQuantity;
|
||||
|
||||
@ApiModelProperty("收货数量")
|
||||
@Excel(name = "收货数量")
|
||||
private BigDecimal receiptQuantity;
|
||||
|
||||
+4
-3
@@ -49,10 +49,11 @@ public class StockReceiptOrderAppApi extends BaseController {
|
||||
/**
|
||||
* 获取收货单详细信息
|
||||
*/
|
||||
@ApiOperation("获取收货单")
|
||||
@ApiOperation("获取收货单详细信息")
|
||||
@GetMapping(value = "/getInfoByApp")
|
||||
public AjaxResult getInfoByApp(Long receiptOrderId) {
|
||||
return AjaxResult.success(stockReceiptOrderApplicationService.getInfoByApp(receiptOrderId));
|
||||
public AjaxResult getInfoByApp(@RequestParam Long receiptOrderId,
|
||||
@RequestParam(required = false) Integer receiptStatus) {
|
||||
return AjaxResult.success(stockReceiptOrderApplicationService.getInfoByApp(receiptOrderId, receiptStatus));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user