PDA收货修改批次属性

This commit is contained in:
秦鸿展
2026-03-11 10:52:51 +08:00
parent 51fe38dfde
commit 0242a5416d
5 changed files with 581 additions and 182 deletions
@@ -259,19 +259,16 @@ public class StockReceiptOrderApplicationService {
BigDecimal totalArea = BigDecimal.ZERO;
if (!CollectionUtils.isEmpty(receiptMaterialDetailPOList)) {
for (ReceiptMaterialDetailPO detail : receiptMaterialDetailPOList) {
if (detail.getLevel() == null || detail.getLevel() == 1) {
totalNetWeight = totalNetWeight.add(sumDetailRecursively(detail, ReceiptMaterialDetailPO::getTotalNetWeight));
totalGrossWeight = totalGrossWeight.add(sumDetailRecursively(detail, ReceiptMaterialDetailPO::getTotalGrossWeight));
totalVolume = totalVolume.add(sumDetailRecursively(detail, ReceiptMaterialDetailPO::getTotalVolume));
totalArea = totalArea.add(sumDetailRecursively(detail, ReceiptMaterialDetailPO::getTotalArea));
}
totalNetWeight = totalNetWeight.add(sumDetailRecursively(detail, ReceiptMaterialDetailPO::getTotalNetWeight));
totalGrossWeight = totalGrossWeight.add(sumDetailRecursively(detail, ReceiptMaterialDetailPO::getTotalGrossWeight));
totalVolume = totalVolume.add(sumDetailRecursively(detail, ReceiptMaterialDetailPO::getTotalVolume));
totalArea = totalArea.add(sumDetailRecursively(detail, ReceiptMaterialDetailPO::getTotalArea));
}
}
stockReceiptOrderPO.setTotalNetWeight(totalNetWeight);
stockReceiptOrderPO.setTotalGrossWeight(totalGrossWeight);
stockReceiptOrderPO.setTotalVolume(totalVolume);
stockReceiptOrderPO.setTotalArea(totalArea);
stockReceiptOrderPO.setMaterialDetailList(receiptMaterialDetailPOList);
log.info("返回收货单信息,receiptOrderId={}, materialDetailList大小={}, totalNetWeight={}, totalGrossWeight={}, totalVolume={}, totalArea={}",
stockReceiptOrderPO.getReceiptOrderId(),
@@ -806,11 +803,68 @@ public class StockReceiptOrderApplicationService {
}
/**
* 获取收货单详细信息
* 获取收货单详细信息PDA 端)
* 在 Domain 层结果基础上,补充包装规格填充,与 PC 端 getInfo 一致
*/
public StockReceiptOrderPO getInfoByApp(Long receiptOrderId)
{
return stockReceiptOrderDomainService.getInfoByApp(receiptOrderId);
StockReceiptOrderPO stockReceiptOrderPO = stockReceiptOrderDomainService.getInfoByApp(receiptOrderId);
List<ReceiptMaterialDetailPO> materialDetailList = stockReceiptOrderPO.getMaterialDetailList();
if (!CollectionUtils.isEmpty(materialDetailList)) {
Set<Long> materialBaseInfoIdSet = new HashSet<>();
collectMaterialBaseInfoIdsRecursively(materialDetailList, materialBaseInfoIdSet);
Map<Long, MaterialBaseInfoPO> materialBaseInfoMap = new HashMap<>();
for (Long materialBaseInfoId : materialBaseInfoIdSet) {
try {
MaterialBaseInfoPO materialBaseInfoPO = materialBaseInfoService.getInfo(materialBaseInfoId);
if (materialBaseInfoPO != null) {
materialBaseInfoMap.put(materialBaseInfoId, materialBaseInfoPO);
}
} catch (Exception e) {
log.warn("获取物料基础信息失败,物料基础信息ID:{},错误:{}", materialBaseInfoId, e.getMessage());
}
}
Map<Long, PackDetailFeignPO> packDetailMap = new HashMap<>();
for (Long materialBaseInfoId : materialBaseInfoIdSet) {
MaterialBaseInfoPO materialBaseInfoPO = materialBaseInfoMap.get(materialBaseInfoId);
if (materialBaseInfoPO != null && materialBaseInfoPO.getPackId() != null) {
try {
AjaxResult packDetailResult = systemServiceFeign.getInfoByPackIdAndUnitCode(materialBaseInfoPO.getPackId(), "EA");
if (packDetailResult != null && "200".equals(String.valueOf(packDetailResult.get("code")))
&& packDetailResult.get("data") != null) {
PackDetailFeignPO packDetailFeignPO = JSON.parseObject(
JSONObject.toJSONString(packDetailResult.get("data")),
PackDetailFeignPO.class);
if (packDetailFeignPO != null) {
packDetailMap.put(materialBaseInfoId, packDetailFeignPO);
}
}
} catch (Exception e) {
log.warn("获取包装规格EA单位信息失败,物料基础信息ID:{},包装ID:{},错误:{}",
materialBaseInfoId, materialBaseInfoPO.getPackId(), e.getMessage());
}
}
}
fillMaterialDetailUnitInfoRecursively(materialDetailList, materialBaseInfoMap, packDetailMap);
}
return stockReceiptOrderPO;
}
/**
* 递归收集明细树中所有物料基础信息ID
*/
private void collectMaterialBaseInfoIdsRecursively(List<ReceiptMaterialDetailPO> list, Set<Long> set) {
if (CollectionUtils.isEmpty(list)) {
return;
}
for (ReceiptMaterialDetailPO po : list) {
if (po.getMaterialBaseInfoId() != null) {
set.add(po.getMaterialBaseInfoId());
}
if (!CollectionUtils.isEmpty(po.getChildren())) {
collectMaterialBaseInfoIdsRecursively(po.getChildren(), set);
}
}
}
@@ -887,14 +941,100 @@ public class StockReceiptOrderApplicationService {
* @return Boolean
*/
public Boolean receivingGoodsByApp(StockReceiptOrderDO stockReceiptOrderDO){
// PDA 收货回传时,将第一项作为主项,其余作为其子项
ensureFirstItemAsParent(stockReceiptOrderDO);
List<ReceiptMaterialDetailDO> list = stockReceiptOrderDO.getMaterialDetailList();
// 记录 PDA 传入时第一项是否已有 children
boolean firstItemHadChildrenBefore = !CollectionUtils.isEmpty(list)
&& !CollectionUtils.isEmpty(list.get(0).getChildren());
// PDA 可能以平铺 [主项, 子项] 回传,此时主项无 children,需先转换为父子结构,否则主项 ALREADY_RECEIPT_QUANTITY 无法累加子项数量
if (!CollectionUtils.isEmpty(list) && list.size() > 1) {
ensureFirstItemAsParent(stockReceiptOrderDO);
}
if (firstItemHadChildrenBefore) {
// 主项子项结构:将 children 第一条(parent_copy)赋值给主项并删除
assignFirstChildToParentAndRemove(stockReceiptOrderDO);
}
StockReceiptOrderDO assembleStockReceiptOrderDO = assembleParamByReceipt(stockReceiptOrderDO);
if (CollectionUtils.isEmpty(assembleStockReceiptOrderDO.getMaterialDetailList())) {
throw new ServiceException("无有效收货数据,请确认已填写收货数量(收货数量不能全部为0)");
}
return stockReceiptOrderDomainService.receivingGoods(assembleStockReceiptOrderDO);
}
/**
* 收货时:将 children 中第一条(parent_copy)的值赋给主项(1),并删除第一条;不合并数量,仅赋值替换。
* getInfoByApp 有子项时会将 parent_copy 作为 children 第一条,PDA 可能不传 materialDetailId/uniqueId
* 故用 materialDetailId、uniqueId、materialBaseInfoId 综合判断,避免误合并真实子项导致第一条被覆盖。
*/
private void assignFirstChildToParentAndRemove(StockReceiptOrderDO stockReceiptOrderDO) {
List<ReceiptMaterialDetailDO> list = stockReceiptOrderDO.getMaterialDetailList();
if (CollectionUtils.isEmpty(list)) {
return;
}
for (ReceiptMaterialDetailDO parent : list) {
List<ReceiptMaterialDetailDO> children = parent.getChildren();
if (CollectionUtils.isEmpty(children)) {
continue;
}
ReceiptMaterialDetailDO firstChild = children.get(0);
if (!isParentCopy(parent, firstChild)) {
// 第一条是真实子项,不合并,保留主项和子项各自独立
continue;
}
// 将 parent_copy 的值赋给主项(赋值替换,不合并数量)
BeanUtils.copyProperties(firstChild, parent, "children", "parentUniqueId", "uniqueId", "materialDetailId",
"organizationIdList", "permissionMenuId", "receiptOrderNumberList", "compoundOrQuery");
// 删除 children 中的第一条(parent_copy
List<ReceiptMaterialDetailDO> newChildren = new ArrayList<>();
for (int i = 1; i < children.size(); i++) {
newChildren.add(children.get(i));
}
parent.setChildren(newChildren);
}
}
/**
* 判断第一条子项是否为 parent_copy(主项拷贝,供 PDA 收货编辑用)。
* parent_copy 与主项同 materialDetailId/uniqueId/materialBaseInfoId;真实子项则不同。
* PDA 可能不传 materialDetailId/uniqueId/materialBaseInfoId,需综合判断。
*/
private boolean isParentCopy(ReceiptMaterialDetailDO parent, ReceiptMaterialDetailDO firstChild) {
Long parentId = parent.getMaterialDetailId();
Long firstChildId = firstChild.getMaterialDetailId();
Long parentUniqueId = parent.getUniqueId();
Long firstChildUniqueId = firstChild.getUniqueId();
Long parentBaseInfoId = parent.getMaterialBaseInfoId();
Long firstChildBaseInfoId = firstChild.getMaterialBaseInfoId();
// 1. materialDetailId 相同 → parent_copy
if (parentId != null && parentId.equals(firstChildId)) {
return true;
}
// 2. uniqueId 相同 → parent_copy
if (parentUniqueId != null && parentUniqueId.equals(firstChildUniqueId)) {
return true;
}
// 3. 子项有与主项不同的 materialDetailId → 真实子项
if (firstChildId != null && !firstChildId.equals(parentId)) {
return false;
}
// 4. 子项有与主项不同的 uniqueId → 真实子项
if (firstChildUniqueId != null && !firstChildUniqueId.equals(parentUniqueId)) {
return false;
}
// 5. 子项 materialBaseInfoId 与主项不同 → 真实子项(不同物料)
if (firstChildBaseInfoId != null && parentBaseInfoId != null && !firstChildBaseInfoId.equals(parentBaseInfoId)) {
return false;
}
// 6. PDA 未传 materialDetailId/uniqueId 时:getInfoByApp 的 parent_copy 总是 children 第一条,
// 真实子项通常会有 materialDetailId,故无 id 时视为 parent_copy 并合并
if (firstChildId == null && firstChildUniqueId == null) {
return true;
}
return false;
}
/**
* PDA 收货回传时,将 materialDetailList 的第一项作为主项(level 1),其余项作为其子项(level 2)
* 仅当数据库中第二项为 level 2(真实子项)时才转换,避免将两条平铺明细错误转为父子导致第一条被覆盖
*/
private void ensureFirstItemAsParent(StockReceiptOrderDO stockReceiptOrderDO) {
List<ReceiptMaterialDetailDO> list = stockReceiptOrderDO.getMaterialDetailList();
@@ -919,6 +1059,14 @@ public class StockReceiptOrderApplicationService {
if (firstPO == null || firstPO.getUniqueId() == null) {
return;
}
// 若第二项在数据库中也是 level 1,说明是平铺兄弟关系,不应转为父子,避免第一条被覆盖
ReceiptMaterialDetailDO second = list.get(1);
if (second != null && second.getMaterialDetailId() != null) {
ReceiptMaterialDetailPO secondPO = dbMap.get(second.getMaterialDetailId());
if (secondPO != null && secondPO.getLevel() != null && secondPO.getLevel() == 1) {
return;
}
}
Long parentUniqueId = firstPO.getUniqueId();
List<ReceiptMaterialDetailDO> children = new ArrayList<>();
for (int i = 1; i < list.size(); i++) {
@@ -1087,15 +1235,29 @@ public class StockReceiptOrderApplicationService {
receiptMaterialDetailDOByQuery.setReceiptOrderNumber(stockReceiptOrderPO.getReceiptOrderNumber());
List<ReceiptMaterialDetailPO> receiptMaterialDetailPODbList = receiptMaterialDetailDomainService.queryList(receiptMaterialDetailDOByQuery);
Map<Long, ReceiptMaterialDetailPO> receiptMaterialDetailDbMap = receiptMaterialDetailPODbList.stream().collect(Collectors.toMap(ReceiptMaterialDetailPO::getMaterialDetailId, Function.identity()));
Map<Long, ReceiptMaterialDetailPO> receiptMaterialDetailDbMapByUniqueId = receiptMaterialDetailPODbList.stream()
.filter(po -> po.getUniqueId() != null)
.collect(Collectors.toMap(ReceiptMaterialDetailPO::getUniqueId, Function.identity()));
BigDecimal totalActualQuantity = BigDecimal.ZERO;//收货单当前作业收货数
int totalActualReceiptMaterialQuantity = 0;//收货单收货物料种数
List<ReceiptMaterialDetailDO> returnReceiptMaterialDetailDOList = new ArrayList<>();
for (ReceiptMaterialDetailDO receiptMaterialDetailDO : stockReceiptOrderDO.getMaterialDetailList()){
//设置物料更多属性信息
//设置物料更多属性信息:优先用 materialDetailId 查找,若为空则用 uniqueId 查找(兼容 PDA 只传 uniqueId 的场景)
ReceiptMaterialDetailPO receiptMaterialDetailPO = receiptMaterialDetailDbMap.get(receiptMaterialDetailDO.getMaterialDetailId());
if (receiptMaterialDetailPO == null && receiptMaterialDetailDO.getUniqueId() != null) {
receiptMaterialDetailPO = receiptMaterialDetailDbMapByUniqueId.get(receiptMaterialDetailDO.getUniqueId());
if (receiptMaterialDetailPO != null) {
receiptMaterialDetailDO.setMaterialDetailId(receiptMaterialDetailPO.getMaterialDetailId());
}
}
if (receiptMaterialDetailPO == null){
throw new ServiceException("物料明细不存在");
}
// receiptQuantity 空值保护,PDA 未传时按 0 处理
BigDecimal receiptQuantity = receiptMaterialDetailDO.getReceiptQuantity();
if (receiptQuantity == null) {
receiptQuantity = BigDecimal.ZERO;
}
List<ReceiptMaterialDetailDO> children = receiptMaterialDetailDO.getChildren();
BigDecimal childrenTotalQuantity = BigDecimal.ZERO;
if (!CollectionUtils.isEmpty(children)) {
@@ -1104,43 +1266,70 @@ public class StockReceiptOrderApplicationService {
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
if (receiptMaterialDetailDO.getReceiptQuantity().compareTo(BigDecimal.ZERO) == 0 && childrenTotalQuantity.compareTo(BigDecimal.ZERO) == 0){
//未进行收货直接跳过
continue;
}
BigDecimal actualQuantity = BigDecimal.ZERO;//当前作业收货数
// 主项和子项收货数量均为 0 时仍保留该明细参与流程,避免多条平铺明细被“丢失”(batchReceiptUpdate、syncUpdateInMaterialDetail 等需感知全部明细)
boolean hasReceipt = receiptQuantity.compareTo(BigDecimal.ZERO) > 0 || childrenTotalQuantity.compareTo(BigDecimal.ZERO) > 0;
BigDecimal mainItemActualQuantity = BigDecimal.ZERO;//主项自身当前作业收货数(不包含子项)
BigDecimal orderLevelQuantity = BigDecimal.ZERO;//主项+子项合计,用于收货单级汇总
List<ReceiptMaterialDetailDO> returnReceiptMaterialDetailDOChildList = new ArrayList<>();
if (hasReceipt) {
//判断收否收货 第一次收货创建 更多属性 序列号
if (receiptMaterialDetailPO.getReceiptQuantity().compareTo(BigDecimal.ZERO) == 0){
//收货后 设置该记录不允许被修改
receiptMaterialDetailDO.setAllowModify(2);
//未收过货 统计到当前收货单作业收货数
actualQuantity = receiptMaterialDetailDO.getReceiptQuantity();
//设置物料状态及容器信息
setMaterialMoreDetailInfo(receiptMaterialDetailDO);
}
//判断是否存在子项
List<ReceiptMaterialDetailDO> returnReceiptMaterialDetailDOChildList = new ArrayList<>();
}
// 主项本次收货增量 = 新子项数量 + 已存在子项的本次收货增量(PDA 传子项累计值时:child.receiptQuantity - childDb.alreadyReceiptQuantity
BigDecimal newChildrenTotalQuantity = BigDecimal.ZERO;
BigDecimal existingChildrenIncrement = BigDecimal.ZERO;
List<ReceiptMaterialDetailDO> receiptMaterialDetailDOChildList = receiptMaterialDetailDO.getChildren();
if (!CollectionUtils.isEmpty(receiptMaterialDetailDOChildList)){
for (ReceiptMaterialDetailDO receiptMaterialDetailDOChild : receiptMaterialDetailDOChildList){
ReceiptMaterialDetailPO receiptMaterialDetailPOChildDb = receiptMaterialDetailDbMap.get(receiptMaterialDetailDOChild.getMaterialDetailId());
if (receiptMaterialDetailPOChildDb != null){
continue;
if (receiptMaterialDetailPOChildDb == null && receiptMaterialDetailDOChild.getUniqueId() != null) {
receiptMaterialDetailPOChildDb = receiptMaterialDetailDbMapByUniqueId.get(receiptMaterialDetailDOChild.getUniqueId());
}
BigDecimal childQty = receiptMaterialDetailDOChild.getReceiptQuantity() != null ? receiptMaterialDetailDOChild.getReceiptQuantity() : BigDecimal.ZERO;
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);
}
}
BigDecimal childReceiptQty = receiptMaterialDetailDOChild.getReceiptQuantity() != null ? receiptMaterialDetailDOChild.getReceiptQuantity() : BigDecimal.ZERO;
ReceiptMaterialDetailDO returnReceiptMaterialDetailDOChild = new ReceiptMaterialDetailDO();
BeanUtils.copyProperties(receiptMaterialDetailPO, returnReceiptMaterialDetailDOChild, "materialDetailId","createBy","createByName","createTime",
if (receiptMaterialDetailPOChildDb != null){
// 子项已存在:用 DB 数据 + PDA 收货数据组装,保证不同明细独立收货不被丢失
BeanUtils.copyProperties(receiptMaterialDetailPOChildDb, returnReceiptMaterialDetailDOChild);
BeanUtils.copyProperties(receiptMaterialDetailDOChild, returnReceiptMaterialDetailDOChild, IgnoreNullUtil.getNullPropertyNames(receiptMaterialDetailDOChild));
// PDA 传子项累计值时,更新子项已收数量(取较大值,确保第二次及以后收货时子项已收数正确)
if (childQty.compareTo(childDbAlready) > 0) {
returnReceiptMaterialDetailDOChild.setAlreadyReceiptQuantity(childQty);
}
returnReceiptMaterialDetailDOChild.setAllowModify(2);
returnReceiptMaterialDetailDOChild.setLevel(2);
returnReceiptMaterialDetailDOChild.setParentUniqueId(receiptMaterialDetailPO.getUniqueId());
setMaterialMoreDetailInfo(returnReceiptMaterialDetailDOChild);
} else {
// 子项不存在:新增子项
BeanUtils.copyProperties(receiptMaterialDetailPO, returnReceiptMaterialDetailDOChild, "materialDetailId","createBy","createByName","createTime",
"updateBy","updateByName","updateTime");
BeanUtils.copyProperties(receiptMaterialDetailDOChild, returnReceiptMaterialDetailDOChild, IgnoreNullUtil.getNullPropertyNames(receiptMaterialDetailDOChild));
if (ObjectUtil.isNotNull(returnReceiptMaterialDetailDOChild.getMaterialDetailId()) && returnReceiptMaterialDetailDOChild.getMaterialDetailId() == 0){
returnReceiptMaterialDetailDOChild.setMaterialDetailId(null);
BeanUtils.copyProperties(receiptMaterialDetailDOChild, returnReceiptMaterialDetailDOChild, IgnoreNullUtil.getNullPropertyNames(receiptMaterialDetailDOChild));
if (ObjectUtil.isNotNull(returnReceiptMaterialDetailDOChild.getMaterialDetailId()) && returnReceiptMaterialDetailDOChild.getMaterialDetailId() == 0){
returnReceiptMaterialDetailDOChild.setMaterialDetailId(null);
}
returnReceiptMaterialDetailDOChild.setAllowModify(2);
returnReceiptMaterialDetailDOChild.setUniqueId(idGenerator.snowflakeId(SnowFlakeConstants.wmsId));
returnReceiptMaterialDetailDOChild.setLevel(2);
returnReceiptMaterialDetailDOChild.setParentUniqueId(receiptMaterialDetailPO.getUniqueId());
setMaterialMoreDetailInfo(returnReceiptMaterialDetailDOChild);
}
//收货后 设置该记录不允许被修改
returnReceiptMaterialDetailDOChild.setAllowModify(2);
returnReceiptMaterialDetailDOChild.setUniqueId(idGenerator.snowflakeId(SnowFlakeConstants.wmsId));
returnReceiptMaterialDetailDOChild.setLevel(2);
returnReceiptMaterialDetailDOChild.setParentUniqueId(receiptMaterialDetailPO.getUniqueId());
//设置物料状态及容器信息
setMaterialMoreDetailInfo(returnReceiptMaterialDetailDOChild);
//是否开启了序列号管理
if (receiptMaterialDetailPO.getSerialNumberManage() == 1){
if (CollectionUtils.isEmpty(receiptMaterialDetailDOChild.getMaterialDetailSerialNumberList())){
@@ -1150,19 +1339,33 @@ public class StockReceiptOrderApplicationService {
returnReceiptMaterialDetailDOChild.setMaterialDetailSerialNumberList(receiptMaterialDetailDOChild.getMaterialDetailSerialNumberList());
returnReceiptMaterialDetailDOChild.setMaterialMoreDetailList(receiptMaterialDetailDOChild.getMaterialMoreDetailList());
returnReceiptMaterialDetailDOChildList.add(returnReceiptMaterialDetailDOChild);
actualQuantity = actualQuantity.add(returnReceiptMaterialDetailDOChild.getReceiptQuantity());
orderLevelQuantity = orderLevelQuantity.add(childReceiptQty);
}
}
//收货量 = 已收货数量 + 当前作业数量
receiptMaterialDetailDO.setAlreadyReceiptQuantity(receiptMaterialDetailPO.getAlreadyReceiptQuantity().add(actualQuantity));
//记录本次收货单收货总数
totalActualQuantity = totalActualQuantity.add(actualQuantity);
// 主项本次收货量 = 新子项数量 + 已存在子项增量;若均为 0 则使用主项 receiptQuantity 或子项合计(再次收货时 PDA 传相同值,主项可能为 0)
// 无子项时使用主项 receiptQuantity
BigDecimal childrenTotalIncrement = newChildrenTotalQuantity.add(existingChildrenIncrement);
mainItemActualQuantity = CollectionUtils.isEmpty(receiptMaterialDetailDOChildList)
? receiptQuantity
: (childrenTotalIncrement.compareTo(BigDecimal.ZERO) > 0
? childrenTotalIncrement
: (receiptQuantity.compareTo(BigDecimal.ZERO) > 0 ? receiptQuantity : childrenTotalQuantity));
//主项已收货数量 = 原有 + 主项本次收货增量
receiptMaterialDetailDO.setAlreadyReceiptQuantity(receiptMaterialDetailPO.getAlreadyReceiptQuantity().add(mainItemActualQuantity));
//记录本次收货单收货总数(主项+子项合计,用于收货单级统计)
orderLevelQuantity = mainItemActualQuantity;
totalActualQuantity = totalActualQuantity.add(orderLevelQuantity);
//判断收货数量是否大于计划数量
Integer receiptStatus = judgeReceiptQuantity(receiptMaterialDetailDO.getAlreadyReceiptQuantity(), receiptMaterialDetailPO.getQuantity());
receiptMaterialDetailDO.setReceiptStatus(receiptStatus);
if (receiptStatus > 2){
totalActualReceiptMaterialQuantity += 1;
}
} else {
// 收货为 0 的明细:保持已收货数量和状态不变,仍加入列表以保持明细完整
receiptMaterialDetailDO.setAlreadyReceiptQuantity(receiptMaterialDetailPO.getAlreadyReceiptQuantity());
receiptMaterialDetailDO.setReceiptStatus(receiptMaterialDetailPO.getReceiptStatus() != null ? receiptMaterialDetailPO.getReceiptStatus() : 1);
}
ReceiptMaterialDetailDO returnReceiptMaterialDetailDO = new ReceiptMaterialDetailDO();
BeanUtils.copyProperties(receiptMaterialDetailPO, returnReceiptMaterialDetailDO);
BeanUtils.copyProperties(receiptMaterialDetailDO, returnReceiptMaterialDetailDO, IgnoreNullUtil.getNullPropertyNames(receiptMaterialDetailDO));
@@ -1285,8 +1488,9 @@ public class StockReceiptOrderApplicationService {
receiptMaterialDetailDOChildByCopy.setLevel(2);
receiptMaterialDetailDOChildByCopy.setParentUniqueId(receiptMaterialDetailDO.getUniqueId());
receiptMaterialDetailDOChildByCopy.setInUniqueId(inMaterialDetailDO.getUniqueId());
receiptMaterialDetailDOChildByCopy.setQuantity(receiptMaterialDetailDOChild.getReceiptQuantity());
receiptMaterialDetailDOChildByCopy.setAlreadyReceiptQuantity(receiptMaterialDetailDOChild.getReceiptQuantity());
BigDecimal childQty = receiptMaterialDetailDOChild.getReceiptQuantity() != null ? receiptMaterialDetailDOChild.getReceiptQuantity() : BigDecimal.ZERO;
receiptMaterialDetailDOChildByCopy.setQuantity(childQty);
receiptMaterialDetailDOChildByCopy.setAlreadyReceiptQuantity(childQty);
BeanUtils.copyProperties(receiptMaterialDetailDOChildByCopy, receiptMaterialDetailDOChild);
//是否开启了序列号管理
if (receiptMaterialDetailDO.getSerialNumberManage() == 1){
@@ -1294,7 +1498,7 @@ public class StockReceiptOrderApplicationService {
throw new ServiceException("物料【" + receiptMaterialDetailDO.getMaterialName() + "】开启了序列号管理的序列号不能为空");
}
}
actualQuantity = actualQuantity.add(receiptMaterialDetailDOChild.getReceiptQuantity());
actualQuantity = actualQuantity.add(childQty);
}
}
//已收货数量 = 当前作业数量
@@ -1,6 +1,7 @@
package com.mhd.wms.domain.inventoryStandingReport.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.mhd.common.core.annotation.Excel;
import com.mhd.common.core.web.domain.BaseVOEntity;
@@ -55,6 +56,7 @@ public class InventoryStandingReport extends BaseVOEntity {
@ApiModelProperty("货主编码")
@Excel(name = "货主名称编码")
@TableField(exist = false)
private String shipperCode;
@ApiModelProperty("货主名称")
@@ -113,19 +113,29 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
if (CollectionUtils.isEmpty(materialMoreDetailList)) {
ajaxResult = systemServiceFeign.getBatchDetailListByMaterialBaseInfoId(receiptMaterialDetailPO.getMaterialBaseInfoId());
if (ajaxResult != null && "200".equals(String.valueOf(ajaxResult.get("code")))) {
materialMoreDetailList = JSON.parseArray(JSONObject.toJSONString(ajaxResult.get("data")), MaterialMoreDetailPO.class);
List<BatchDetailFeignPO> batchList = JSON.parseArray(JSONObject.toJSONString(ajaxResult.get("data")), BatchDetailFeignPO.class);
materialMoreDetailList = filterAndConvertToMaterialMoreDetail(batchList);
}
}
// 从入库单明细表中获取InvoiceNo、BatchRefNo、SheetRefNo、BoxPalletNo字段的值
fillAttributeValueFromInMaterialDetail(receiptMaterialDetailPO, materialMoreDetailList);
receiptMaterialDetailPO.setMaterialMoreDetailList(materialMoreDetailList);
});
// 获取查询的层级
// 获取查询的层级level 1 为顶级;level 2 且 parent_unique_id 为 null/0 的为孤儿项;level 2 且 parent_unique_id 在收货明细中无对应父项的也为孤儿(如 PDA 只收子项、父项在 in_material_detail 中),均作为顶级展示
java.util.Set<Long> receiptParentIds = receiptMaterialDetailPOList.stream()
.flatMap(po -> java.util.stream.Stream.of(po.getUniqueId(), po.getInUniqueId()))
.filter(id -> id != null)
.collect(Collectors.toSet());
List<ReceiptMaterialDetailPO> receiptMaterialDetailPOParentList = receiptMaterialDetailPOList
.stream().filter(e -> 1 == e.getLevel()).collect(Collectors.toList());
// 递归查询子集
.stream().filter(e -> e.getLevel() != null && (
1 == e.getLevel()
|| (2 == e.getLevel() && (e.getParentUniqueId() == null || Long.valueOf(0).equals(e.getParentUniqueId())))
|| (2 == e.getLevel() && e.getParentUniqueId() != null && !receiptParentIds.contains(e.getParentUniqueId()))
)).collect(Collectors.toList());
// 递归查询子集:parent_unique_id 可能指向 receipt.unique_idPDA 收货创建的子项)或 in_material_detail.unique_id(从入库单复制),
// 需同时用 unique_id 和 in_unique_id 查找子项
for(ReceiptMaterialDetailPO materialDetailPO :receiptMaterialDetailPOParentList){
List<ReceiptMaterialDetailPO> children = getChildren(materialDetailPO.getUniqueId(), receiptMaterialDetailPOList, 2);
List<ReceiptMaterialDetailPO> children = getChildren(materialDetailPO.getUniqueId(), materialDetailPO.getInUniqueId(), receiptMaterialDetailPOList, 2);
children.forEach(childrenDetailPO -> {
MaterialMoreDetailDO materialMoreDetailDO = new MaterialMoreDetailDO();
materialMoreDetailDO.setMaterialDetailUniqueId(childrenDetailPO.getUniqueId());
@@ -135,7 +145,8 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
if (CollectionUtils.isEmpty(materialMoreDetailList)) {
ajaxResult = systemServiceFeign.getBatchDetailListByMaterialBaseInfoId(childrenDetailPO.getMaterialBaseInfoId());
if (ajaxResult != null && "200".equals(String.valueOf(ajaxResult.get("code")))) {
materialMoreDetailList = JSON.parseArray(JSONObject.toJSONString(ajaxResult.get("data")), MaterialMoreDetailPO.class);
List<BatchDetailFeignPO> batchList = JSON.parseArray(JSONObject.toJSONString(ajaxResult.get("data")), BatchDetailFeignPO.class);
materialMoreDetailList = filterAndConvertToMaterialMoreDetail(batchList);
}
}
// 从入库单明细表中获取InvoiceNo、BatchRefNo、SheetRefNo、BoxPalletNo字段的值
@@ -146,15 +157,70 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
materialDetailPO.setChildren(children);
}
// 兜底:若有 level 2 既不在顶级列表、也不在任何父项的 children 中,则提升为顶级(避免 PDA 收货后 PC 端漏显)
java.util.Set<Long> displayedUniqueIds = new java.util.HashSet<>();
receiptMaterialDetailPOParentList.forEach(p -> collectUniqueIdsRecursively(p, displayedUniqueIds));
for (ReceiptMaterialDetailPO po : receiptMaterialDetailPOList) {
if (po.getLevel() != null && 2 == po.getLevel() && po.getUniqueId() != null && !displayedUniqueIds.contains(po.getUniqueId())) {
receiptMaterialDetailPOParentList.add(po);
}
}
return receiptMaterialDetailPOParentList;
}
private List<ReceiptMaterialDetailPO> getChildren(Long parentUniqueId, List<ReceiptMaterialDetailPO> receiptMaterialDetailPOList, Integer maxLevel){
List<ReceiptMaterialDetailPO> childrenCityList = receiptMaterialDetailPOList.stream().filter(materialDetailPO -> parentUniqueId.equals(materialDetailPO.getParentUniqueId())).collect(Collectors.toList());
private void collectUniqueIdsRecursively(ReceiptMaterialDetailPO po, java.util.Set<Long> set) {
if (po == null || po.getUniqueId() == null) return;
set.add(po.getUniqueId());
if (!CollectionUtils.isEmpty(po.getChildren())) {
po.getChildren().forEach(c -> collectUniqueIdsRecursively(c, set));
}
}
/**
* 过滤 isDisplay=1 的批次属性并转换为 MaterialMoreDetailPO,与 PC 端 getInfo 一致
*/
private List<MaterialMoreDetailPO> filterAndConvertToMaterialMoreDetail(List<BatchDetailFeignPO> batchList) {
List<MaterialMoreDetailPO> result = new ArrayList<>();
if (CollectionUtils.isEmpty(batchList)) {
return result;
}
for (BatchDetailFeignPO po : batchList) {
if (po.getIsDisplay() == null || po.getIsDisplay() != 1) {
continue;
}
MaterialMoreDetailPO mpo = new MaterialMoreDetailPO();
mpo.setBatchId(po.getBatchId());
mpo.setBatchDetailId(po.getBatchDetailId());
mpo.setBatchLabels(po.getBatchLabels());
mpo.setInputControl(po.getInputControl());
mpo.setAttributeFormat(po.getAttributeFormat());
mpo.setAttributeOption(po.getAttributeOption());
result.add(mpo);
}
return result;
}
/**
* 查找子项:parent_unique_id 可能指向 receipt.unique_idPDA 收货)或 in_material_detail.unique_id(从入库单复制)
*/
private List<ReceiptMaterialDetailPO> getChildren(Long parentUniqueId, Long parentInUniqueId,
List<ReceiptMaterialDetailPO> receiptMaterialDetailPOList, Integer maxLevel){
if (parentUniqueId == null && parentInUniqueId == null) {
return new ArrayList<>();
}
final Long pid = parentUniqueId;
final Long inPid = parentInUniqueId;
List<ReceiptMaterialDetailPO> childrenCityList = receiptMaterialDetailPOList.stream()
.filter(materialDetailPO -> {
Long p = materialDetailPO.getParentUniqueId();
if (p == null) return false;
return (pid != null && p.equals(pid)) || (inPid != null && p.equals(inPid));
})
.collect(Collectors.toList());
if (!CollectionUtils.isEmpty(childrenCityList)){
childrenCityList.forEach(childrenCity -> {
if (childrenCity.getLevel() < maxLevel){
childrenCity.setChildren(getChildren(childrenCity.getUniqueId(), receiptMaterialDetailPOList, maxLevel));
if (childrenCity.getLevel() != null && childrenCity.getLevel() < maxLevel){
childrenCity.setChildren(getChildren(childrenCity.getUniqueId(), childrenCity.getInUniqueId(), receiptMaterialDetailPOList, maxLevel));
}
});
}
@@ -244,73 +310,7 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
List<MaterialMoreDetail> materialMoreDetailList = new ArrayList<>();
List<InMaterialDetailSerialNumber> materialDetailSerialNumberList = new ArrayList<>();
for (ReceiptMaterialDetailDO receiptMaterialDetailDO : receiptMaterialDetailDOList){
List<MaterialMoreDetailDO> materialMoreDetailList1 = receiptMaterialDetailDO.getMaterialMoreDetailList();
if (CollectionUtils.isEmpty(materialMoreDetailList1)) {
materialMoreDetailList1 = new ArrayList<>();
}
for (MaterialMoreDetailDO materialMoreDetailDO : materialMoreDetailList1) {
String batchLabels = materialMoreDetailDO.getBatchLabels();
String attributeValue = materialMoreDetailDO.getAttributeValue();
if (attributeValue != null && !attributeValue.isEmpty() && attributeValue != "" && attributeValue.length() > 0 ) {
attributeValue = attributeValue.trim();
switch (batchLabels) {
case "扩展字段4":
receiptMaterialDetailDO.setExtAttr4(attributeValue);
break;
case "扩展字段3":
receiptMaterialDetailDO.setExtAttr3(attributeValue);
break;
case "扩展字段2":
receiptMaterialDetailDO.setExtAttr2(attributeValue);
break;
case "扩展字段1":
receiptMaterialDetailDO.setExtAttr1(attributeValue);
break;
case "箱号/卡板号":
receiptMaterialDetailDO.setBoxPalletNo(attributeValue);
break;
case "Sheet Ref NO's":
receiptMaterialDetailDO.setSheetRefNo(attributeValue);
break;
case "Batch Ref NO's":
receiptMaterialDetailDO.setBatchRefNo(attributeValue);
break;
case "存货日期":
// 判断是否是日期格式再赋值避免报错
try {
if (attributeValue.matches("\\d{4}-\\d{2}-\\d{2}.*")) {
receiptMaterialDetailDO.setInventoryDate(DateUtils.parseDate(attributeValue));
}
} catch (Exception e) {
log.warn("库存日期格式转换失败,物料:{},原始值:{}", receiptMaterialDetailDO.getMaterialName(), attributeValue);
}
//receiptMaterialDetailDO.setInventoryDate(DateUtils.parseDate(attributeValue));
break;
case "过期日期":
// 判断是否是日期格式再赋值避免报错
try {
if (attributeValue.matches("\\d{4}-\\d{2}-\\d{2}.*")) {
receiptMaterialDetailDO.setExpiryDate(DateUtils.parseDate(attributeValue));
}
} catch (Exception e) {
log.warn("库存日期格式转换失败,物料:{},原始值:{}", receiptMaterialDetailDO.getMaterialName(), attributeValue);
}
//receiptMaterialDetailDO.setExpiryDate(DateUtils.parseDate(attributeValue));
break;
case "生产日期":
// 判断是否是日期格式再赋值避免报错
try {
if (attributeValue.matches("\\d{4}-\\d{2}-\\d{2}.*")) {
receiptMaterialDetailDO.setProductionDate(DateUtils.parseDate(attributeValue));
}
} catch (Exception e) {
log.warn("库存日期格式转换失败,物料:{},原始值:{}", receiptMaterialDetailDO.getMaterialName(), attributeValue);
}
//receiptMaterialDetailDO.setProductionDate(DateUtils.parseDate(attributeValue));
break;
}
}
}
extractBatchAttributesToReceiptDetail(receiptMaterialDetailDO);
// 自动生成批次号并校验唯一性(包括子项)
generateAndValidateBatchNumber(receiptMaterialDetailDO, shipperId);
// 当 materialMoreDetailList 为空时(如 PDA 未传),从 receiptMaterialDetailDO 的 batch_number、material_status_code 等字段构建,确保更多属性能保存并回显
@@ -331,6 +331,8 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
List<ReceiptMaterialDetail> receiptMaterialDetailChildList = new ArrayList<>();
if (!CollectionUtils.isEmpty(receiptMaterialDetailDOChildList)){
for (ReceiptMaterialDetailDO receiptMaterialDetailDOChild : receiptMaterialDetailDOChildList){
// 子项也需从批次属性提取净重、毛重、体积、面积等字段
extractBatchAttributesToReceiptDetail(receiptMaterialDetailDOChild);
ReceiptMaterialDetail receiptMaterialDetailChild = new ReceiptMaterialDetail();
BeanUtils.copyProperties(receiptMaterialDetailDOChild, receiptMaterialDetailChild);
receiptMaterialDetailChild.setCreateBy(loginUser.getUserid());
@@ -361,8 +363,21 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
}
//保存物料明细信息
saveOrUpdateBatch(receiptMaterialDetailList);
//批量新增物料信息
//批量新增/更新物料更多属性:先删除该收货单下所有明细的旧批次属性,再插入新值,避免重复插入导致更新失效
if (!CollectionUtils.isEmpty(materialMoreDetailList)){
String receiptOrderNumber = stockReceiptOrderDO.getReceiptOrderNumber();
if (StringUtils.isBlank(receiptOrderNumber) && !CollectionUtils.isEmpty(receiptMaterialDetailDOList)) {
receiptOrderNumber = receiptMaterialDetailDOList.get(0).getReceiptOrderNumber();
}
if (StringUtils.isNotBlank(receiptOrderNumber)) {
java.util.Set<Long> uniqueIds = collectReceiptDetailUniqueIds(receiptMaterialDetailDOList);
if (!uniqueIds.isEmpty()) {
IMaterialMoreDetailService.remove(new QueryWrapper<MaterialMoreDetail>()
.eq("order_number", receiptOrderNumber)
.in("material_detail_unique_id", uniqueIds)
.eq("del_flag", 1));
}
}
IMaterialMoreDetailService.saveBatch(materialMoreDetailList);
}
//批量新增序列号
@@ -603,22 +618,57 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
return;
}
// 根据attributeOption从入库单明细中获取对应的值并填充到attributeValue
// 根据attributeOption或batchLabels从入库单/收货单明细中获取对应的值并填充到attributeValue
for (MaterialMoreDetailPO materialMoreDetail : materialMoreDetailList) {
String attributeOption = materialMoreDetail.getAttributeOption();
String batchLabels = materialMoreDetail.getBatchLabels();
// 如果attributeValue已经有值,跳过
if (materialMoreDetail.getAttributeValue() != null && !materialMoreDetail.getAttributeValue().trim().isEmpty()) {
continue;
}
// 根据attributeOption映射到入库单明细表的字段
if ("InvoiceNo".equalsIgnoreCase(attributeOption)) {
materialMoreDetail.setAttributeValue(inMaterialDetail.getInvoiceNo());
} else if ("BatchRefNo".equalsIgnoreCase(attributeOption)) {
materialMoreDetail.setAttributeValue(inMaterialDetail.getBatchRefNo());
} else if ("SheetRefNo".equalsIgnoreCase(attributeOption)) {
materialMoreDetail.setAttributeValue(inMaterialDetail.getSheetRefNo());
} else if ("BoxPalletNo".equalsIgnoreCase(attributeOption)) {
materialMoreDetail.setAttributeValue(inMaterialDetail.getBoxPalletNo());
// 根据attributeOption映射到入库单明细表的字段(兼容 batchLabels 兜底,如 "Batch Ref NO's"、"Sheet Ref NO's"、"箱号/卡板号"
String refVal = null;
if ("InvoiceNo".equalsIgnoreCase(attributeOption) || "Invoice No".equalsIgnoreCase(batchLabels) || "发票号".equals(batchLabels)) {
refVal = inMaterialDetail.getInvoiceNo();
} else if ("BatchRefNo".equalsIgnoreCase(attributeOption) || "Batch Ref NO's".equalsIgnoreCase(batchLabels) || "批次参考号".equals(batchLabels)) {
refVal = inMaterialDetail.getBatchRefNo();
} else if ("SheetRefNo".equalsIgnoreCase(attributeOption) || "Sheet Ref NO's".equalsIgnoreCase(batchLabels) || "单据参考号".equals(batchLabels)) {
refVal = inMaterialDetail.getSheetRefNo();
} else if ("BoxPalletNo".equalsIgnoreCase(attributeOption) || "Box No./Pallet No.".equalsIgnoreCase(batchLabels) || "箱号/卡板号".equals(batchLabels)) {
refVal = inMaterialDetail.getBoxPalletNo();
}
if (refVal != null) {
materialMoreDetail.setAttributeValue(refVal);
} else if (StringUtils.isNotBlank(batchLabels)) {
// 根据batchLabels填充净重、毛重、体积、面积(优先用收货明细,无则用入库明细)
String val = null;
switch (batchLabels.trim()) {
case "总净重":
case "净重(KG)":
case "净重":
val = receiptMaterialDetailPO.getTotalNetWeight() != null ? receiptMaterialDetailPO.getTotalNetWeight().toString() : (inMaterialDetail.getTotalNetWeight() != null ? inMaterialDetail.getTotalNetWeight().toString() : null);
break;
case "总毛重":
case "毛重(KG)":
case "毛重":
val = receiptMaterialDetailPO.getTotalGrossWeight() != null ? receiptMaterialDetailPO.getTotalGrossWeight().toString() : (inMaterialDetail.getTotalGrossWeight() != null ? inMaterialDetail.getTotalGrossWeight().toString() : null);
break;
case "总体积":
case "体积(CBM)":
case "体积":
val = receiptMaterialDetailPO.getTotalVolume() != null ? receiptMaterialDetailPO.getTotalVolume().toString() : (inMaterialDetail.getTotalVolume() != null ? inMaterialDetail.getTotalVolume().toString() : null);
break;
case "总面积":
case "面积(SQM)":
case "面积":
val = receiptMaterialDetailPO.getTotalArea() != null ? receiptMaterialDetailPO.getTotalArea().toString() : (inMaterialDetail.getTotalArea() != null ? inMaterialDetail.getTotalArea().toString() : null);
break;
default:
break;
}
if (val != null) {
materialMoreDetail.setAttributeValue(val);
}
}
}
}
@@ -710,6 +760,145 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
}
/**
* 从批次属性 materialMoreDetailList 提取值到收货明细字段(扩展字段、净重、毛重、体积、面积等)
*/
private void extractBatchAttributesToReceiptDetail(ReceiptMaterialDetailDO receiptMaterialDetailDO) {
List<MaterialMoreDetailDO> list = receiptMaterialDetailDO.getMaterialMoreDetailList();
if (CollectionUtils.isEmpty(list)) {
return;
}
for (MaterialMoreDetailDO materialMoreDetailDO : list) {
String batchLabels = materialMoreDetailDO.getBatchLabels();
String attributeValue = materialMoreDetailDO.getAttributeValue();
if (StringUtils.isBlank(batchLabels) || StringUtils.isBlank(attributeValue)) {
continue;
}
attributeValue = attributeValue.trim();
switch (batchLabels) {
case "扩展字段4":
receiptMaterialDetailDO.setExtAttr4(attributeValue);
break;
case "扩展字段3":
receiptMaterialDetailDO.setExtAttr3(attributeValue);
break;
case "扩展字段2":
receiptMaterialDetailDO.setExtAttr2(attributeValue);
break;
case "扩展字段1":
receiptMaterialDetailDO.setExtAttr1(attributeValue);
break;
case "箱号/卡板号":
receiptMaterialDetailDO.setBoxPalletNo(attributeValue);
break;
case "Sheet Ref NO's":
receiptMaterialDetailDO.setSheetRefNo(attributeValue);
break;
case "Batch Ref NO's":
receiptMaterialDetailDO.setBatchRefNo(attributeValue);
break;
case "存货日期":
try {
if (attributeValue.matches("\\d{4}-\\d{2}-\\d{2}.*")) {
receiptMaterialDetailDO.setInventoryDate(DateUtils.parseDate(attributeValue));
}
} catch (Exception e) {
log.warn("库存日期格式转换失败,物料:{},原始值:{}", receiptMaterialDetailDO.getMaterialName(), attributeValue);
}
break;
case "过期日期":
try {
if (attributeValue.matches("\\d{4}-\\d{2}-\\d{2}.*")) {
receiptMaterialDetailDO.setExpiryDate(DateUtils.parseDate(attributeValue));
}
} catch (Exception e) {
log.warn("库存日期格式转换失败,物料:{},原始值:{}", receiptMaterialDetailDO.getMaterialName(), attributeValue);
}
break;
case "生产日期":
try {
if (attributeValue.matches("\\d{4}-\\d{2}-\\d{2}.*")) {
receiptMaterialDetailDO.setProductionDate(DateUtils.parseDate(attributeValue));
}
} catch (Exception e) {
log.warn("库存日期格式转换失败,物料:{},原始值:{}", receiptMaterialDetailDO.getMaterialName(), attributeValue);
}
break;
case "总净重":
case "净重(KG)":
case "净重":
setReceiptDetailBigDecimalField(receiptMaterialDetailDO, attributeValue, "totalNetWeight");
break;
case "总毛重":
case "毛重(KG)":
case "毛重":
setReceiptDetailBigDecimalField(receiptMaterialDetailDO, attributeValue, "totalGrossWeight");
break;
case "总体积":
case "体积(CBM)":
case "体积":
setReceiptDetailBigDecimalField(receiptMaterialDetailDO, attributeValue, "totalVolume");
break;
case "总面积":
case "面积(SQM)":
case "面积":
setReceiptDetailBigDecimalField(receiptMaterialDetailDO, attributeValue, "totalArea");
break;
default:
break;
}
}
}
/**
* 递归收集收货明细及其子项的所有 uniqueId(用于删除旧批次属性)
*/
private java.util.Set<Long> collectReceiptDetailUniqueIds(List<ReceiptMaterialDetailDO> list) {
java.util.Set<Long> set = new java.util.HashSet<>();
if (CollectionUtils.isEmpty(list)) {
return set;
}
for (ReceiptMaterialDetailDO d : list) {
if (d.getUniqueId() != null) {
set.add(d.getUniqueId());
}
if (!CollectionUtils.isEmpty(d.getChildren())) {
set.addAll(collectReceiptDetailUniqueIds(d.getChildren()));
}
}
return set;
}
/**
* 从批次属性 attributeValue 解析 BigDecimal 并设置到收货明细对应字段(净重、毛重、体积、面积等)
*/
private void setReceiptDetailBigDecimalField(ReceiptMaterialDetailDO receiptMaterialDetailDO, String attributeValue, String fieldName) {
if (StringUtils.isBlank(attributeValue)) {
return;
}
try {
BigDecimal val = new BigDecimal(attributeValue.trim());
switch (fieldName) {
case "totalNetWeight":
receiptMaterialDetailDO.setTotalNetWeight(val);
break;
case "totalGrossWeight":
receiptMaterialDetailDO.setTotalGrossWeight(val);
break;
case "totalVolume":
receiptMaterialDetailDO.setTotalVolume(val);
break;
case "totalArea":
receiptMaterialDetailDO.setTotalArea(val);
break;
default:
break;
}
} catch (Exception e) {
log.warn("批次属性数值解析失败,物料:{},字段:{},原始值:{}", receiptMaterialDetailDO.getMaterialName(), fieldName, attributeValue);
}
}
/**
* 当 PDA 未传 materialMoreDetailList 时,从 receiptMaterialDetailDO 的 batch_number、batch_ref_no、material_status_code 等字段构建,
* 确保更多属性能保存到 material_more_detail 表并正确回显
@@ -729,6 +918,12 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
if (CollectionUtils.isEmpty(list)) {
return result;
}
// 优先使用 attributeOption(如 BatchRefNo、SheetRefNo),其次 fieldName,最后 batchLabels 兜底映射
Map<String, String> attributeOptionToField = new HashMap<>();
attributeOptionToField.put("InvoiceNo", "invoiceNo");
attributeOptionToField.put("BatchRefNo", "batchRefNo");
attributeOptionToField.put("SheetRefNo", "sheetRefNo");
attributeOptionToField.put("BoxPalletNo", "boxPalletNo");
Map<String, String> labelToField = new HashMap<>();
labelToField.put("Batch Ref NO's", "batchRefNo");
labelToField.put("Batch Ref NO", "batchRefNo");
@@ -745,6 +940,9 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
continue;
}
String fieldName = po.getFieldName();
if (StringUtils.isBlank(fieldName) && StringUtils.isNotBlank(po.getAttributeOption())) {
fieldName = attributeOptionToField.get(po.getAttributeOption().trim());
}
if (StringUtils.isBlank(fieldName) && StringUtils.isNotBlank(po.getBatchLabels())) {
fieldName = labelToField.get(po.getBatchLabels().trim());
}
@@ -215,69 +215,62 @@ public class StockReceiptOrderDomainService {
Map<Long, List<MaterialMoreDetailPO>> materialMoreDetailMap = materialMoreDetailPOList.stream()
.collect(Collectors.groupingBy(MaterialMoreDetailPO::getMaterialDetailUniqueId));
receiptMaterialDetailPOList.forEach(receiptMaterialDetailPO -> {
List<ReceiptMaterialDetailPO> receiptMaterialDetailPOChildrenNowList = new ArrayList<>();
//子集(level 2 的真实子项)
//子集(level 2 的真实子项),PDA 端不添加 parent_copy,与 PC 端一致,避免主项重复展示
List<ReceiptMaterialDetailPO> receiptMaterialDetailPOChildrenList = receiptMaterialDetailPO.getChildren();
if (CollectionUtils.isEmpty(receiptMaterialDetailPOChildrenList)) {
//无 level 2 子项时,不添加父级拷贝,避免 PC 端显示重复
receiptMaterialDetailPO.setChildren(receiptMaterialDetailPOChildrenNowList);
return;
}
//有 level 2 子项时,添加父级拷贝(level 1)供 PDA 收货使用
ReceiptMaterialDetailPO receiptMaterialDetailPOChildrenNow = new ReceiptMaterialDetailPO();
BeanUtils.copyProperties(receiptMaterialDetailPO, receiptMaterialDetailPOChildrenNow, "children");
List<InMaterialDetailSerialNumberPO> materialDetailSerialNumberList = inMaterialDetailSerialNumberMap.get(receiptMaterialDetailPO.getUniqueId());
if (!CollectionUtils.isEmpty(materialDetailSerialNumberList)) {
receiptMaterialDetailPOChildrenNow.setMaterialDetailSerialNumberList(materialDetailSerialNumberList);
if (!CollectionUtils.isEmpty(receiptMaterialDetailPOChildrenList)) {
receiptMaterialDetailPOChildrenList.forEach(receiptMaterialDetailPOChildren -> {
List<InMaterialDetailSerialNumberPO> materialDetailSerialNumberChildrenList = inMaterialDetailSerialNumberMap.get(receiptMaterialDetailPOChildren.getUniqueId());
if (!CollectionUtils.isEmpty(materialDetailSerialNumberChildrenList)) {
receiptMaterialDetailPOChildren.setMaterialDetailSerialNumberList(materialDetailSerialNumberChildrenList);
} else {
receiptMaterialDetailPOChildren.setMaterialDetailSerialNumberList(new ArrayList<>());
}
List<MaterialMoreDetailPO> materialMoreDetailChildrenList = materialMoreDetailMap.get(receiptMaterialDetailPOChildren.getUniqueId());
if (!CollectionUtils.isEmpty(materialMoreDetailChildrenList)) {
receiptMaterialDetailPOChildren.setMaterialMoreDetailList(materialMoreDetailChildrenList);
} else if (CollectionUtils.isEmpty(receiptMaterialDetailPOChildren.getMaterialMoreDetailList())) {
// material_more_detail 表无记录时,queryListChildren 已填充 attributeValue;仅当子项本身无批次属性时才从物料获取
receiptMaterialDetailPOChildren.setMaterialMoreDetailList(getMaterialMoreDetail(receiptMaterialDetailPOChildren));
}
// 否则保留 queryListChildren 已填充的 materialMoreDetailList(含 BatchRefNo、SheetRefNo、BoxPalletNo 等 attributeValue
});
} else {
receiptMaterialDetailPOChildrenNow.setMaterialDetailSerialNumberList(new ArrayList<>());
}
List<MaterialMoreDetailPO> materialMoreDetailList = materialMoreDetailMap.get(receiptMaterialDetailPO.getUniqueId());
if (!CollectionUtils.isEmpty(materialMoreDetailList)) {
receiptMaterialDetailPOChildrenNow.setMaterialMoreDetailList(materialMoreDetailList);
} else {
receiptMaterialDetailPOChildrenNow.setMaterialMoreDetailList(getMaterialMoreDetail(receiptMaterialDetailPO));
}
receiptMaterialDetailPOChildrenNowList.add(receiptMaterialDetailPOChildrenNow);
receiptMaterialDetailPOChildrenList.forEach(receiptMaterialDetailPOChildren -> {
List<InMaterialDetailSerialNumberPO> materialDetailSerialNumberChildrenList = inMaterialDetailSerialNumberMap.get(receiptMaterialDetailPOChildren.getUniqueId());
if (!CollectionUtils.isEmpty(materialDetailSerialNumberChildrenList)) {
receiptMaterialDetailPOChildren.setMaterialDetailSerialNumberList(materialDetailSerialNumberChildrenList);
} else {
receiptMaterialDetailPOChildren.setMaterialDetailSerialNumberList(new ArrayList<>());
// 主项无子项时(点击分批收货前):确保主项也有批次属性,否则 PDA 不显示
if (CollectionUtils.isEmpty(receiptMaterialDetailPO.getMaterialMoreDetailList())) {
receiptMaterialDetailPO.setMaterialMoreDetailList(getMaterialMoreDetail(receiptMaterialDetailPO));
}
List<MaterialMoreDetailPO> materialMoreDetailChildrenList = materialMoreDetailMap.get(receiptMaterialDetailPOChildren.getUniqueId());
if (!CollectionUtils.isEmpty(materialMoreDetailChildrenList)) {
receiptMaterialDetailPOChildren.setMaterialMoreDetailList(materialMoreDetailChildrenList);
} else {
receiptMaterialDetailPOChildren.setMaterialMoreDetailList(getMaterialMoreDetail(receiptMaterialDetailPO));
}
});
receiptMaterialDetailPOChildrenNowList.addAll(receiptMaterialDetailPOChildrenList);
receiptMaterialDetailPO.setChildren(receiptMaterialDetailPOChildrenNowList);
}
receiptMaterialDetailPO.setChildren(receiptMaterialDetailPOChildrenList != null ? receiptMaterialDetailPOChildrenList : new ArrayList<>());
});
stockReceiptOrderPO.setMaterialDetailList(receiptMaterialDetailPOList);
return stockReceiptOrderPO;
}
/**
* @param receiptMaterialDetailPO
* @return List<MaterialMoreDetail>
* @description 获取物料更多属性
* @author ZhouGY
* @date 2024/7/3 13:46
* 根据物料绑定的批次属性动态获取更多属性(按 materialBaseInfoId,不再使用 MaterialGoodsRule.batchId
* @param receiptMaterialDetailPO 收货明细
* @return List<MaterialMoreDetailPO>
*/
public List<MaterialMoreDetailPO> getMaterialMoreDetail(ReceiptMaterialDetailPO receiptMaterialDetailPO) {
MaterialGoodsRule materialGoodsRule = materialGoodsRuleService.getOne(new QueryWrapper<MaterialGoodsRule>().lambda()
.eq(MaterialGoodsRule::getMaterialBaseInfoId, receiptMaterialDetailPO.getMaterialBaseInfoId()));
List<MaterialMoreDetailPO> materialMoreDetailPOList = new ArrayList<>();
if (materialGoodsRule != null) {
AjaxResult ajaxResult = systemServiceFeign.getBatchDetailListByBatchId(materialGoodsRule.getBatchId());
if (!"200".equals(String.valueOf(ajaxResult.get("code")))) {
throw new ServiceException("获取批次信息失败");
Long materialBaseInfoId = receiptMaterialDetailPO != null ? receiptMaterialDetailPO.getMaterialBaseInfoId() : null;
if (materialBaseInfoId == null) {
return materialMoreDetailPOList;
}
try {
AjaxResult ajaxResult = systemServiceFeign.getBatchDetailListByMaterialBaseInfoId(materialBaseInfoId);
if (ajaxResult == null || !"200".equals(String.valueOf(ajaxResult.get("code")))) {
return materialMoreDetailPOList;
}
List<BatchDetailFeignPO> batchDetailFeignPOList = JSON.parseArray(JSONObject.toJSONString(ajaxResult.get("data")), BatchDetailFeignPO.class);
batchDetailFeignPOList.forEach(batchDetailFeignPO -> {
if (CollectionUtils.isEmpty(batchDetailFeignPOList)) {
return materialMoreDetailPOList;
}
// 只保留 isDisplay=1 的批次属性,与 PC 端 getInfo 一致
for (BatchDetailFeignPO batchDetailFeignPO : batchDetailFeignPOList) {
if (batchDetailFeignPO.getIsDisplay() == null || batchDetailFeignPO.getIsDisplay() != 1) {
continue;
}
MaterialMoreDetailPO materialMoreDetailPO = new MaterialMoreDetailPO();
materialMoreDetailPO.setBatchId(batchDetailFeignPO.getBatchId());
materialMoreDetailPO.setBatchDetailId(batchDetailFeignPO.getBatchDetailId());
@@ -286,7 +279,9 @@ public class StockReceiptOrderDomainService {
materialMoreDetailPO.setAttributeFormat(batchDetailFeignPO.getAttributeFormat());
materialMoreDetailPO.setAttributeOption(batchDetailFeignPO.getAttributeOption());
materialMoreDetailPOList.add(materialMoreDetailPO);
});
}
} catch (Exception e) {
log.warn("获取物料批次属性失败,物料基础信息ID:{},错误:{}", materialBaseInfoId, e.getMessage());
}
return materialMoreDetailPOList;
}
@@ -52,7 +52,7 @@ public class StockReceiptOrderAppApi extends BaseController {
@ApiOperation("获取收货单")
@GetMapping(value = "/getInfoByApp")
public AjaxResult getInfoByApp(Long receiptOrderId) {
return AjaxResult.success(stockReceiptOrderApplicationService.getInfo(receiptOrderId));
return AjaxResult.success(stockReceiptOrderApplicationService.getInfoByApp(receiptOrderId));
}
/**