PDA收货修改内容

This commit is contained in:
秦鸿展
2026-04-14 15:06:50 +08:00
parent bce84d0b4c
commit aa0be69556
6 changed files with 438 additions and 6 deletions
@@ -26,6 +26,16 @@ public interface IReceiptMaterialDetailService extends IService<ReceiptMaterialD
*/
public List<ReceiptMaterialDetailPO> queryListChildren(ReceiptMaterialDetailDO receiptMaterialDetailDO);
/**
* PDA:按收货单号 + 父明细主键查询该计划行下所有 level=2 子行(分批收货履历),含批次属性合并。
* 若 {@code parentMaterialDetailId} 对应库中为子行,会先解析为其所属计划父行再查子集。
* 若未拆出任何子行但主计划行上已有实收,则返回一条与主行一致的快照,便于「已收货列表」展示。
*
* @param receiptOrderNumber 收货单号
* @param parentMaterialDetailId 父卡片对应 receipt_material_detail.material_detail_id
*/
List<ReceiptMaterialDetailPO> queryLevel2ChildrenByParentMaterialDetailId(String receiptOrderNumber, Long parentMaterialDetailId);
/**
* 新增物料明细
*/
@@ -50,6 +50,7 @@ import lombok.extern.slf4j.Slf4j;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@@ -146,6 +147,85 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
return receiptMaterialDetailPOParentList;
}
@Override
public List<ReceiptMaterialDetailPO> queryLevel2ChildrenByParentMaterialDetailId(String receiptOrderNumber,
Long parentMaterialDetailId) {
List<ReceiptMaterialDetailPO> empty = new ArrayList<>();
if (receiptOrderNumber == null || parentMaterialDetailId == null) {
return empty;
}
ReceiptMaterialDetailDO q = new ReceiptMaterialDetailDO();
q.setReceiptOrderNumber(receiptOrderNumber);
List<ReceiptMaterialDetailPO> all = receiptMaterialDetailMapper.queryList(q);
if (CollectionUtils.isEmpty(all)) {
return empty;
}
ReceiptMaterialDetailPO anchor = all.stream()
.filter(p -> parentMaterialDetailId.equals(p.getMaterialDetailId()))
.findFirst()
.orElse(null);
if (anchor == null) {
return empty;
}
ReceiptMaterialDetailPO parent = anchor;
if (anchor.getLevel() != null && anchor.getLevel() == 2 && anchor.getParentUniqueId() != null) {
Long puid = anchor.getParentUniqueId();
ReceiptMaterialDetailPO plan = all.stream()
.filter(row -> puid.equals(row.getUniqueId()) || puid.equals(row.getInUniqueId()))
.findFirst()
.orElse(null);
if (plan != null) {
parent = plan;
}
}
Long pid = parent.getUniqueId();
Long inPid = parent.getInUniqueId();
if (pid == null && inPid == null) {
return empty;
}
final Long fpid = pid;
final Long finPid = inPid;
List<ReceiptMaterialDetailPO> children = all.stream()
.filter(m -> m.getLevel() != null && m.getLevel() == 2)
.filter(m -> {
Long p = m.getParentUniqueId();
if (p == null) {
return false;
}
return (fpid != null && p.equals(fpid)) || (finPid != null && p.equals(finPid));
})
.sorted(Comparator.comparing(ReceiptMaterialDetailPO::getCreateTime, Comparator.nullsLast(Comparator.naturalOrder()))
.thenComparing(ReceiptMaterialDetailPO::getMaterialDetailId, Comparator.nullsLast(Comparator.naturalOrder())))
.collect(Collectors.toList());
children.forEach(ch -> {
List<MaterialMoreDetailPO> materialMoreDetailList = buildMaterialMoreDetailListByMaterialBinding(ch);
fillAttributeValueFromInMaterialDetail(ch, materialMoreDetailList);
ch.setMaterialMoreDetailList(materialMoreDetailList);
});
// 首笔只落主计划行、后续批次才 INSERT 子行时:主行上仍有累计实收,列表需在子行之外再带一条「主行首笔」快照(否则只剩子行 500,看不到主行 200)
if (!children.isEmpty() && parent.getLevel() != null && parent.getLevel() == 1
&& parent.getAlreadyReceiptQuantity() != null
&& parent.getAlreadyReceiptQuantity().compareTo(BigDecimal.ZERO) > 0) {
ReceiptMaterialDetailPO mainSnap = new ReceiptMaterialDetailPO();
BeanUtils.copyProperties(parent, mainSnap);
List<MaterialMoreDetailPO> mainMore = buildMaterialMoreDetailListByMaterialBinding(mainSnap);
fillAttributeValueFromInMaterialDetail(mainSnap, mainMore);
mainSnap.setMaterialMoreDetailList(mainMore);
children.add(0, mainSnap);
}
// 未拆 level=2 子行、实收全部记在主计划行时:仍返回一条与主行一致的快照,供 PDA「已收货列表」展示
if (children.isEmpty() && parent.getAlreadyReceiptQuantity() != null
&& parent.getAlreadyReceiptQuantity().compareTo(BigDecimal.ZERO) > 0) {
ReceiptMaterialDetailPO mainSnap = new ReceiptMaterialDetailPO();
BeanUtils.copyProperties(parent, mainSnap);
List<MaterialMoreDetailPO> materialMoreDetailList = buildMaterialMoreDetailListByMaterialBinding(mainSnap);
fillAttributeValueFromInMaterialDetail(mainSnap, materialMoreDetailList);
mainSnap.setMaterialMoreDetailList(materialMoreDetailList);
children.add(mainSnap);
}
return children;
}
private void collectUniqueIdsRecursively(ReceiptMaterialDetailPO po, java.util.Set<Long> set) {
if (po == null || po.getUniqueId() == null) return;
set.add(po.getUniqueId());
@@ -171,6 +171,12 @@ public class StockReceiptOrderDO extends StockInOrderBaseDO {
@ApiModelProperty("是否来自PDA收货:true-PDA收货完成,false-PC收货完成(用于上架单是否下发:PDA=是,PC=否)")
private Boolean fromPda;
/**
* PDA 已执行 assignFirstChildToParentAndRemove(首条子项已合并到主项),禁止再将主项本次量拆成新子行,避免与子项重复。
*/
@ApiModelProperty(hidden = true)
private Boolean pdaSkipInjectBatchChildLine;
/**
* PC 收货确认:以页面提交数据为全量实绩覆盖落库(由 Application 层根据入口设置,非前端传入)
*/
@@ -256,6 +256,34 @@ public class StockReceiptOrderDomainService {
return stockReceiptOrderPO;
}
/**
* PDA:指定计划行(卡片)下所有 level=2 分批收货子行(库表真实子行,不含 parent_copy),附带序列号。
*
* @param receiptOrderId 收货单主键
* @param parentMaterialDetailId 卡片对应 receipt_material_detail.material_detail_id(可误传为某子行 id,将解析到其父计划行)
*/
public List<ReceiptMaterialDetailPO> listLevel2ChildrenByParentForApp(Long receiptOrderId, Long parentMaterialDetailId) {
StockReceiptOrderPO order = stockReceiptOrderService.getInfo(receiptOrderId);
if (order == null) {
throw new ServiceException("收货单不存在");
}
List<ReceiptMaterialDetailPO> children = receiptMaterialDetailService.queryLevel2ChildrenByParentMaterialDetailId(
order.getReceiptOrderNumber(), parentMaterialDetailId);
if (CollectionUtils.isEmpty(children)) {
return new ArrayList<>();
}
InMaterialDetailSerialNumberDO snDo = new InMaterialDetailSerialNumberDO();
snDo.setOrderNumber(order.getReceiptOrderNumber());
List<InMaterialDetailSerialNumberPO> snList = inMaterialDetailSerialNumberService.queryList(snDo);
Map<Long, List<InMaterialDetailSerialNumberPO>> snMap = snList.stream()
.collect(Collectors.groupingBy(InMaterialDetailSerialNumberPO::getMaterialDetailUniqueId));
for (ReceiptMaterialDetailPO ch : children) {
List<InMaterialDetailSerialNumberPO> sns = ch.getUniqueId() != null ? snMap.get(ch.getUniqueId()) : null;
ch.setMaterialDetailSerialNumberList(!CollectionUtils.isEmpty(sns) ? sns : new ArrayList<>());
}
return children;
}
/**
* 根据物料绑定的批次属性动态获取更多属性(按 materialBaseInfoId,不再使用 MaterialGoodsRule.batchId
* @param receiptMaterialDetailPO 收货明细