diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockReceiptOrder/StockReceiptOrderApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockReceiptOrder/StockReceiptOrderApplicationService.java index 1cc9ccce4..e3b07e8e7 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockReceiptOrder/StockReceiptOrderApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockReceiptOrder/StockReceiptOrderApplicationService.java @@ -1663,8 +1663,9 @@ public class StockReceiptOrderApplicationService { } /** - * 本次收货的毛/净重、体积、面积增量:优先 receipt*;否则 total*。 + * 本次收货的毛/净重、体积、面积增量:优先 receipt*(界面本次填写);否则 total*。 * total* 与 PC 回显对齐后可能为「累计实绩」:若 total > 本单收货前累计则增量=差;相等则 0;小于累计则视为「本次增量」原值。 + *

主项/子项数量各自独立:主行 {@code receiptQuantity}、子行 {@code receiptQuantity} 即用户填写的件数,不做计划比例分摊。

*/ private static BigDecimal pickThisReceiptMetricIncrement(BigDecimal receiptField, BigDecimal totalField, BigDecimal dbAlreadyBeforeThisReceipt) { @@ -1747,14 +1748,49 @@ public class StockReceiptOrderApplicationService { .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); } + // 未传 receiptQuantity 但传了称重/体积(常见于 PC 子行):仍视为有收货,否则会走「无收货」分支不写主项累计 + BigDecimal dbParentNetForGate = receiptMaterialDetailPO.getAlreadyReceiptNetWeight() != null + ? receiptMaterialDetailPO.getAlreadyReceiptNetWeight() : BigDecimal.ZERO; + BigDecimal dbParentGrossForGate = receiptMaterialDetailPO.getAlreadyReceiptGrossWeight() != null + ? receiptMaterialDetailPO.getAlreadyReceiptGrossWeight() : BigDecimal.ZERO; + boolean hasReceiptByMetrics = pickThisReceiptMetricIncrement( + receiptMaterialDetailDO.getReceiptNetWeight(), + receiptMaterialDetailDO.getTotalNetWeight(), + dbParentNetForGate).compareTo(BigDecimal.ZERO) > 0 + || pickThisReceiptMetricIncrement( + receiptMaterialDetailDO.getReceiptGrossWeight(), + receiptMaterialDetailDO.getTotalGrossWeight(), + dbParentGrossForGate).compareTo(BigDecimal.ZERO) > 0; + if (!hasReceiptByMetrics && !CollectionUtils.isEmpty(children)) { + for (ReceiptMaterialDetailDO c : children) { + if (c == null) { + continue; + } + ReceiptMaterialDetailPO cdb = receiptMaterialDetailDbMap.get(c.getMaterialDetailId()); + if (cdb == null && c.getUniqueId() != null) { + cdb = receiptMaterialDetailDbMapByUniqueId.get(c.getUniqueId()); + } + BigDecimal cDbNet = cdb != null && cdb.getAlreadyReceiptNetWeight() != null + ? cdb.getAlreadyReceiptNetWeight() : BigDecimal.ZERO; + BigDecimal cDbGross = cdb != null && cdb.getAlreadyReceiptGrossWeight() != null + ? cdb.getAlreadyReceiptGrossWeight() : BigDecimal.ZERO; + if (pickThisReceiptMetricIncrement(c.getReceiptNetWeight(), c.getTotalNetWeight(), cDbNet).compareTo(BigDecimal.ZERO) > 0 + || pickThisReceiptMetricIncrement(c.getReceiptGrossWeight(), c.getTotalGrossWeight(), cDbGross).compareTo(BigDecimal.ZERO) > 0) { + hasReceiptByMetrics = true; + break; + } + } + } // 主项和子项收货数量均为 0 时仍保留该明细参与流程,避免多条平铺明细被“丢失”(batchReceiptUpdate、syncUpdateInMaterialDetail 等需感知全部明细) - boolean hasReceipt = receiptQuantity.compareTo(BigDecimal.ZERO) > 0 || childrenTotalQuantity.compareTo(BigDecimal.ZERO) > 0; - BigDecimal mainItemActualQuantity = BigDecimal.ZERO;//主项自身当前作业收货数(不包含子项) - BigDecimal orderLevelQuantity = BigDecimal.ZERO;//主项+子项合计,用于收货单级汇总 + boolean hasReceipt = receiptQuantity.compareTo(BigDecimal.ZERO) > 0 || childrenTotalQuantity.compareTo(BigDecimal.ZERO) > 0 + || hasReceiptByMetrics; + BigDecimal mainItemActualQuantity = BigDecimal.ZERO;//主项自身当前作业收货数(不含子项合计) List returnReceiptMaterialDetailDOChildList = new ArrayList<>(); if (hasReceipt) { //判断收否收货 第一次收货创建 更多属性 序列号 - if (receiptMaterialDetailPO.getReceiptQuantity().compareTo(BigDecimal.ZERO) == 0){ + BigDecimal poReceiptQty = receiptMaterialDetailPO.getReceiptQuantity() != null + ? receiptMaterialDetailPO.getReceiptQuantity() : BigDecimal.ZERO; + if (poReceiptQty.compareTo(BigDecimal.ZERO) == 0){ //收货后 设置该记录不允许被修改 receiptMaterialDetailDO.setAllowModify(2); //设置物料状态及容器信息 @@ -1764,14 +1800,6 @@ public class StockReceiptOrderApplicationService { // 统一口径:PDA 上传的 receiptQuantity 视为“本次收货量”,不再按累计值覆盖 BigDecimal newChildrenTotalQuantity = BigDecimal.ZERO; BigDecimal existingChildrenIncrement = BigDecimal.ZERO; - BigDecimal newChildrenGrossTotal = BigDecimal.ZERO; - BigDecimal existingChildrenGrossIncrement = BigDecimal.ZERO; - BigDecimal newChildrenNetTotal = BigDecimal.ZERO; - BigDecimal existingChildrenNetIncrement = BigDecimal.ZERO; - BigDecimal newChildrenVolTotal = BigDecimal.ZERO; - BigDecimal existingChildrenVolIncrement = BigDecimal.ZERO; - BigDecimal newChildrenAreaTotal = BigDecimal.ZERO; - BigDecimal existingChildrenAreaIncrement = BigDecimal.ZERO; List receiptMaterialDetailDOChildList = receiptMaterialDetailDO.getChildren(); if (!CollectionUtils.isEmpty(receiptMaterialDetailDOChildList)){ for (ReceiptMaterialDetailDO receiptMaterialDetailDOChild : receiptMaterialDetailDOChildList){ @@ -1794,22 +1822,20 @@ public class StockReceiptOrderApplicationService { BigDecimal childNet = pickThisReceiptMetricIncrement(receiptMaterialDetailDOChild.getReceiptNetWeight(), receiptMaterialDetailDOChild.getTotalNetWeight(), childDbAlreadyNet); BigDecimal childVol = pickThisReceiptMetricIncrement(receiptMaterialDetailDOChild.getReceiptVolume(), receiptMaterialDetailDOChild.getTotalVolume(), childDbAlreadyVol); BigDecimal childArea = pickThisReceiptMetricIncrement(receiptMaterialDetailDOChild.getReceiptArea(), receiptMaterialDetailDOChild.getTotalArea(), childDbAlreadyArea); + // PC 端子行常只回填 totalNetWeight/totalGrossWeight,不回传 receiptQuantity;用本次称重增量兜底为件数(与千克等重量计量物料一致) + if (childQty.compareTo(BigDecimal.ZERO) == 0 && childNet.compareTo(BigDecimal.ZERO) > 0) { + childQty = childNet; + } + if (childQty.compareTo(BigDecimal.ZERO) == 0 && childGross.compareTo(BigDecimal.ZERO) > 0) { + childQty = childGross; + } if (receiptMaterialDetailPOChildDb == null) { - // 新子项:累加其本次收货量 + // 新子项:累加其本次收货量(毛净重体面积仅落子行,不再汇总到主行) newChildrenTotalQuantity = newChildrenTotalQuantity.add(childQty); - newChildrenGrossTotal = newChildrenGrossTotal.add(childGross); - newChildrenNetTotal = newChildrenNetTotal.add(childNet); - newChildrenVolTotal = newChildrenVolTotal.add(childVol); - newChildrenAreaTotal = newChildrenAreaTotal.add(childArea); } else { // 已存在子项:累加其本次收货量 existingChildrenIncrement = existingChildrenIncrement.add(childQty); - existingChildrenGrossIncrement = existingChildrenGrossIncrement.add(childGross); - existingChildrenNetIncrement = existingChildrenNetIncrement.add(childNet); - existingChildrenVolIncrement = existingChildrenVolIncrement.add(childVol); - existingChildrenAreaIncrement = existingChildrenAreaIncrement.add(childArea); } - BigDecimal childReceiptQty = receiptMaterialDetailDOChild.getReceiptQuantity() != null ? receiptMaterialDetailDOChild.getReceiptQuantity() : BigDecimal.ZERO; ReceiptMaterialDetailDO returnReceiptMaterialDetailDOChild = new ReceiptMaterialDetailDO(); if (receiptMaterialDetailPOChildDb != null){ // 子项已存在:用 DB 数据 + PDA 收货数据组装,保证不同明细独立收货不被丢失 @@ -1842,6 +1868,9 @@ public class StockReceiptOrderApplicationService { returnReceiptMaterialDetailDOChild.setAlreadyReceiptNetWeight(childNet); returnReceiptMaterialDetailDOChild.setAlreadyReceiptVolume(childVol); returnReceiptMaterialDetailDOChild.setAlreadyReceiptArea(childArea); + // 与已存在子项分支一致:累计收货数量必须显式赋值。仅从父项 copy 会得到父项已收或 0; + // batchReceiptUpdate 内 alignPersistedReceiptQuantityToCumulative 用 alreadyReceiptQuantity 写入 receipt_quantity。 + returnReceiptMaterialDetailDOChild.setAlreadyReceiptQuantity(childQty); } // PC 端读 total*:与累计实绩一致(与 already_receipt_* 同步) returnReceiptMaterialDetailDOChild.setTotalNetWeight(returnReceiptMaterialDetailDOChild.getAlreadyReceiptNetWeight()); @@ -1856,16 +1885,17 @@ public class StockReceiptOrderApplicationService { } returnReceiptMaterialDetailDOChild.setMaterialDetailSerialNumberList(receiptMaterialDetailDOChild.getMaterialDetailSerialNumberList()); returnReceiptMaterialDetailDOChild.setMaterialMoreDetailList(receiptMaterialDetailDOChild.getMaterialMoreDetailList()); + if (returnReceiptMaterialDetailDOChild.getAlreadyReceiptQuantity() != null) { + returnReceiptMaterialDetailDOChild.setReceiptQuantity(returnReceiptMaterialDetailDOChild.getAlreadyReceiptQuantity()); + } + // 子项不展示/不落库计划数量(与主项计划区分),避免与主行 1100 重复 + returnReceiptMaterialDetailDOChild.setQuantity(null); returnReceiptMaterialDetailDOChildList.add(returnReceiptMaterialDetailDOChild); - orderLevelQuantity = orderLevelQuantity.add(childReceiptQty); } } - // 主项本次收货增量 = 主项 receiptQuantity(含 assignFirstChildToParentAndRemove 合并的第一条子项)+ 其余子项合计 - // 无子项时使用主项 receiptQuantity + // 主行本次收货量 = 仅主行填写的 receiptQuantity;子项各行单独一行落库,不累加到主行 RECEIPT/ALREADY_RECEIPT BigDecimal childrenTotalIncrement = newChildrenTotalQuantity.add(existingChildrenIncrement); - mainItemActualQuantity = CollectionUtils.isEmpty(receiptMaterialDetailDOChildList) - ? receiptQuantity - : receiptQuantity.add(childrenTotalIncrement); + mainItemActualQuantity = receiptQuantity; BigDecimal dbParentBeforeGross = receiptMaterialDetailPO.getAlreadyReceiptGrossWeight() != null ? receiptMaterialDetailPO.getAlreadyReceiptGrossWeight() : BigDecimal.ZERO; BigDecimal dbParentBeforeNet = receiptMaterialDetailPO.getAlreadyReceiptNetWeight() != null ? receiptMaterialDetailPO.getAlreadyReceiptNetWeight() : BigDecimal.ZERO; BigDecimal dbParentBeforeVol = receiptMaterialDetailPO.getAlreadyReceiptVolume() != null ? receiptMaterialDetailPO.getAlreadyReceiptVolume() : BigDecimal.ZERO; @@ -1874,24 +1904,15 @@ public class StockReceiptOrderApplicationService { BigDecimal parentReceiptNet = pickThisReceiptMetricIncrement(receiptMaterialDetailDO.getReceiptNetWeight(), receiptMaterialDetailDO.getTotalNetWeight(), dbParentBeforeNet); BigDecimal parentReceiptVol = pickThisReceiptMetricIncrement(receiptMaterialDetailDO.getReceiptVolume(), receiptMaterialDetailDO.getTotalVolume(), dbParentBeforeVol); BigDecimal parentReceiptArea = pickThisReceiptMetricIncrement(receiptMaterialDetailDO.getReceiptArea(), receiptMaterialDetailDO.getTotalArea(), dbParentBeforeArea); - BigDecimal childrenGrossIncrement = newChildrenGrossTotal.add(existingChildrenGrossIncrement); - BigDecimal childrenNetIncrement = newChildrenNetTotal.add(existingChildrenNetIncrement); - BigDecimal childrenVolIncrement = newChildrenVolTotal.add(existingChildrenVolIncrement); - BigDecimal childrenAreaIncrement = newChildrenAreaTotal.add(existingChildrenAreaIncrement); - BigDecimal mainGrossIncrement = CollectionUtils.isEmpty(receiptMaterialDetailDOChildList) - ? parentReceiptGross - : parentReceiptGross.add(childrenGrossIncrement); - BigDecimal mainNetIncrement = CollectionUtils.isEmpty(receiptMaterialDetailDOChildList) - ? parentReceiptNet - : parentReceiptNet.add(childrenNetIncrement); - BigDecimal mainVolIncrement = CollectionUtils.isEmpty(receiptMaterialDetailDOChildList) - ? parentReceiptVol - : parentReceiptVol.add(childrenVolIncrement); - BigDecimal mainAreaIncrement = CollectionUtils.isEmpty(receiptMaterialDetailDOChildList) - ? parentReceiptArea - : parentReceiptArea.add(childrenAreaIncrement); - //主项已收货数量 = 原有 + 主项本次收货增量 - receiptMaterialDetailDO.setAlreadyReceiptQuantity(receiptMaterialDetailPO.getAlreadyReceiptQuantity().add(mainItemActualQuantity)); + // 主行 already_* 只累计主行本行毛净重体面积;子行各自落子行记录,避免主行重复叠加子行导致与数量口径不一致 + BigDecimal mainGrossIncrement = parentReceiptGross; + BigDecimal mainNetIncrement = parentReceiptNet; + BigDecimal mainVolIncrement = parentReceiptVol; + BigDecimal mainAreaIncrement = parentReceiptArea; + //主项已收货数量 = 原有 + 主项本次收货增量(PO 字段可能为 null,须兜底否则落库 already/receipt_quantity 为空) + BigDecimal dbParentAlreadyQty = receiptMaterialDetailPO.getAlreadyReceiptQuantity() != null + ? receiptMaterialDetailPO.getAlreadyReceiptQuantity() : BigDecimal.ZERO; + receiptMaterialDetailDO.setAlreadyReceiptQuantity(dbParentAlreadyQty.add(mainItemActualQuantity)); BigDecimal dbParentAlreadyGross = receiptMaterialDetailPO.getAlreadyReceiptGrossWeight() != null ? receiptMaterialDetailPO.getAlreadyReceiptGrossWeight() : BigDecimal.ZERO; receiptMaterialDetailDO.setAlreadyReceiptGrossWeight(dbParentAlreadyGross.add(mainGrossIncrement)); BigDecimal dbParentAlreadyNet = receiptMaterialDetailPO.getAlreadyReceiptNetWeight() != null ? receiptMaterialDetailPO.getAlreadyReceiptNetWeight() : BigDecimal.ZERO; @@ -1905,18 +1926,32 @@ public class StockReceiptOrderApplicationService { receiptMaterialDetailDO.setTotalGrossWeight(receiptMaterialDetailDO.getAlreadyReceiptGrossWeight()); receiptMaterialDetailDO.setTotalVolume(receiptMaterialDetailDO.getAlreadyReceiptVolume()); receiptMaterialDetailDO.setTotalArea(receiptMaterialDetailDO.getAlreadyReceiptArea()); - //记录本次收货单收货总数(主项+子项合计,用于收货单级统计) - orderLevelQuantity = mainItemActualQuantity; + // 收货单级本次实收:主行 + 所有子行(与 stock_receipt_order.actualQuantity 一致) + BigDecimal orderLevelQuantity = mainItemActualQuantity.add(childrenTotalIncrement); totalActualQuantity = totalActualQuantity.add(orderLevelQuantity); - //判断收货数量是否大于计划数量 - Integer receiptStatus = judgeReceiptQuantity(receiptMaterialDetailDO.getAlreadyReceiptQuantity(), receiptMaterialDetailPO.getQuantity()); + // 主行收货状态:按「主行+子行」合计与计划数量比较(子行无单独计划数量) + BigDecimal groupReceived = receiptMaterialDetailDO.getAlreadyReceiptQuantity() != null + ? receiptMaterialDetailDO.getAlreadyReceiptQuantity() : BigDecimal.ZERO; + if (!CollectionUtils.isEmpty(returnReceiptMaterialDetailDOChildList)) { + for (ReceiptMaterialDetailDO ch : returnReceiptMaterialDetailDOChildList) { + BigDecimal ca = ch.getAlreadyReceiptQuantity() != null ? ch.getAlreadyReceiptQuantity() : BigDecimal.ZERO; + groupReceived = groupReceived.add(ca); + } + } + Integer receiptStatus = judgeReceiptQuantity(groupReceived, receiptMaterialDetailPO.getQuantity()); receiptMaterialDetailDO.setReceiptStatus(receiptStatus); + if (!CollectionUtils.isEmpty(returnReceiptMaterialDetailDOChildList)) { + for (ReceiptMaterialDetailDO ch : returnReceiptMaterialDetailDOChildList) { + ch.setReceiptStatus(receiptStatus); + } + } if (receiptStatus > 2){ totalActualReceiptMaterialQuantity += 1; } } else { // 收货为 0 的明细:保持已收货数量和状态不变,仍加入列表以保持明细完整 - receiptMaterialDetailDO.setAlreadyReceiptQuantity(receiptMaterialDetailPO.getAlreadyReceiptQuantity()); + receiptMaterialDetailDO.setAlreadyReceiptQuantity(receiptMaterialDetailPO.getAlreadyReceiptQuantity() != null + ? receiptMaterialDetailPO.getAlreadyReceiptQuantity() : BigDecimal.ZERO); receiptMaterialDetailDO.setAlreadyReceiptGrossWeight(receiptMaterialDetailPO.getAlreadyReceiptGrossWeight()); receiptMaterialDetailDO.setAlreadyReceiptNetWeight(receiptMaterialDetailPO.getAlreadyReceiptNetWeight()); receiptMaterialDetailDO.setAlreadyReceiptVolume(receiptMaterialDetailPO.getAlreadyReceiptVolume()); @@ -1930,6 +1965,10 @@ public class StockReceiptOrderApplicationService { returnReceiptMaterialDetailDO.setTotalGrossWeight(receiptMaterialDetailDO.getTotalGrossWeight()); returnReceiptMaterialDetailDO.setTotalVolume(receiptMaterialDetailDO.getTotalVolume()); returnReceiptMaterialDetailDO.setTotalArea(receiptMaterialDetailDO.getTotalArea()); + BigDecimal parentRetAlreadyQty = receiptMaterialDetailDO.getAlreadyReceiptQuantity() != null + ? receiptMaterialDetailDO.getAlreadyReceiptQuantity() : BigDecimal.ZERO; + returnReceiptMaterialDetailDO.setAlreadyReceiptQuantity(parentRetAlreadyQty); + returnReceiptMaterialDetailDO.setReceiptQuantity(parentRetAlreadyQty); if (receiptMaterialDetailPO.getReceiptStatus() == 1){ //一级列表 首次收货 //是否开启了序列号管理 diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/stockReceiptOrder/service/StockReceiptOrderDomainService.java b/mhd_wms/src/main/java/com/mhd/wms/domain/stockReceiptOrder/service/StockReceiptOrderDomainService.java index e66c27f13..fb68d7b01 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/stockReceiptOrder/service/StockReceiptOrderDomainService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/stockReceiptOrder/service/StockReceiptOrderDomainService.java @@ -724,6 +724,8 @@ public class StockReceiptOrderDomainService { /** * 收货单完成时:按累计已收与计划数量比较,更新明细 receipt_status(3 正常收完 / 4 少收 / 5 超收) + *

PC 主子行拆分收货时:计划数量只在主行(level=1),子行 quantity 常为 0;须按「主行已收 + 其下子行已收」与主行计划比较, + * 主、子行使用同一状态,避免主行判少收、子行判超收。

*/ private void updateReceiptMaterialDetailReceiptStatusWhenOrderCompleted(StockReceiptOrderPO stockReceiptOrderPO, LoginUser loginUser, String userRealName) { @@ -738,15 +740,68 @@ public class StockReceiptOrderDomainService { if (CollectionUtils.isEmpty(details)) { return; } + Map> childrenByParentUniqueId = new HashMap<>(); for (ReceiptMaterialDetail d : details) { - d.setReceiptStatus(resolveReceiptDetailStatusOnOrderComplete(d.getAlreadyReceiptQuantity(), d.getQuantity())); - d.setUpdateBy(loginUser.getUserid()); - d.setUpdateByName(userRealName); - d.setUpdateTime(updateTime); + if (isReceiptDetailChildRow(d) && d.getParentUniqueId() != null) { + childrenByParentUniqueId.computeIfAbsent(d.getParentUniqueId(), k -> new ArrayList<>()).add(d); + } + } + Set parentUniqueIdsInOrder = details.stream() + .filter(d -> !isReceiptDetailChildRow(d)) + .map(ReceiptMaterialDetail::getUniqueId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + for (ReceiptMaterialDetail parent : details) { + if (isReceiptDetailChildRow(parent)) { + continue; + } + Integer status; + List children = parent.getUniqueId() == null ? null + : childrenByParentUniqueId.get(parent.getUniqueId()); + if (!CollectionUtils.isEmpty(children)) { + BigDecimal groupReceived = nz(parent.getAlreadyReceiptQuantity()); + for (ReceiptMaterialDetail ch : children) { + groupReceived = groupReceived.add(nz(ch.getAlreadyReceiptQuantity())); + } + status = resolveReceiptDetailStatusOnOrderComplete(groupReceived, parent.getQuantity()); + } else { + status = resolveReceiptDetailStatusOnOrderComplete(parent.getAlreadyReceiptQuantity(), parent.getQuantity()); + } + parent.setReceiptStatus(status); + parent.setUpdateBy(loginUser.getUserid()); + parent.setUpdateByName(userRealName); + parent.setUpdateTime(updateTime); + if (!CollectionUtils.isEmpty(children)) { + for (ReceiptMaterialDetail ch : children) { + ch.setReceiptStatus(status); + ch.setUpdateBy(loginUser.getUserid()); + ch.setUpdateByName(userRealName); + ch.setUpdateTime(updateTime); + } + } + } + // 子行的 parent_unique_id 在本单明细中找不到对应主行时:无法按组合计,仍按单行口径更新 + for (ReceiptMaterialDetail d : details) { + if (isReceiptDetailChildRow(d) && d.getParentUniqueId() != null + && !parentUniqueIdsInOrder.contains(d.getParentUniqueId())) { + d.setReceiptStatus(resolveReceiptDetailStatusOnOrderComplete(d.getAlreadyReceiptQuantity(), d.getQuantity())); + d.setUpdateBy(loginUser.getUserid()); + d.setUpdateByName(userRealName); + d.setUpdateTime(updateTime); + } } receiptMaterialDetailService.updateBatchById(details); } + private static boolean isReceiptDetailChildRow(ReceiptMaterialDetail d) { + return d.getLevel() != null && d.getLevel() == 2 + && d.getParentUniqueId() != null && d.getParentUniqueId() != 0L; + } + + private static BigDecimal nz(BigDecimal v) { + return v != null ? v : BigDecimal.ZERO; + } + /** 3=已收足 4=少收 5=超收 */ private static Integer resolveReceiptDetailStatusOnOrderComplete(BigDecimal alreadyReceiptQuantity, BigDecimal quantity) { BigDecimal already = alreadyReceiptQuantity != null ? alreadyReceiptQuantity : BigDecimal.ZERO; diff --git a/mhd_wms/src/main/java/com/mhd/wms/interfaces/assember/stockReceiptOrder/StockReceiptOrderAssembler.java b/mhd_wms/src/main/java/com/mhd/wms/interfaces/assember/stockReceiptOrder/StockReceiptOrderAssembler.java index c97f85378..1a65ae878 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/interfaces/assember/stockReceiptOrder/StockReceiptOrderAssembler.java +++ b/mhd_wms/src/main/java/com/mhd/wms/interfaces/assember/stockReceiptOrder/StockReceiptOrderAssembler.java @@ -1,12 +1,19 @@ package com.mhd.wms.interfaces.assember.stockReceiptOrder; -import cn.hutool.json.JSONUtil; import com.mhd.common.core.utils.IgnoreNullUtil; import com.mhd.common.core.utils.bean.BeanUtils; +import com.mhd.wms.domain.materialMoreDetail.repository.todo.MaterialMoreDetailDO; +import com.mhd.wms.domain.receiptMaterialDetail.repository.todo.ReceiptMaterialDetailDO; import com.mhd.wms.domain.stockReceiptOrder.repository.todo.StockReceiptOrderDO; +import com.mhd.wms.interfaces.dto.materialMoreDetail.MaterialMoreDetailDTO; +import com.mhd.wms.interfaces.dto.receiptMaterialDetail.ReceiptMaterialDetailDTO; import com.mhd.wms.interfaces.dto.stockReceiptOrder.StockReceiptOrderDTO; import org.springframework.stereotype.Component; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + /** * 收货单Assembler * @@ -30,11 +37,68 @@ public class StockReceiptOrderAssembler { } /** - * 转换实体 - */ + * 编辑/收货提交:DTO → DO。 + * Jackson/Hutool 对嵌套 {@code materialDetailList[].children} 与 {@code MaterialMoreDetailDTO}→DO 的中转易丢子行, + * 导致子项 {@code receiptQuantity} 为 null、不生成收货明细。此处显式递归拷贝,保证子树完整。 + */ public StockReceiptOrderDO toDOByEdit(StockReceiptOrderDTO stockReceiptOrderDTO) { - // 拷贝 - return JSONUtil.toBean(JSONUtil.toJsonStr(stockReceiptOrderDTO), StockReceiptOrderDO.class); + StockReceiptOrderDO target = new StockReceiptOrderDO(); + String[] topIgnore = appendIgnores(IgnoreNullUtil.getNullPropertyNames(stockReceiptOrderDTO), "materialDetailList"); + BeanUtils.copyProperties(stockReceiptOrderDTO, target, topIgnore); + target.setMaterialDetailList(convertMaterialDetailRows(stockReceiptOrderDTO.getMaterialDetailList())); + return target; + } + + private static String[] appendIgnores(String[] base, String... extra) { + if (extra == null || extra.length == 0) { + return base; + } + String[] out = Arrays.copyOf(base, base.length + extra.length); + System.arraycopy(extra, 0, out, base.length, extra.length); + return out; + } + + private static List convertMaterialDetailRows(List src) { + if (src == null) { + return null; + } + List list = new ArrayList<>(src.size()); + for (ReceiptMaterialDetailDTO row : src) { + list.add(convertOneMaterialDetail(row)); + } + return list; + } + + private static ReceiptMaterialDetailDO convertOneMaterialDetail(ReceiptMaterialDetailDTO src) { + if (src == null) { + return null; + } + ReceiptMaterialDetailDO t = new ReceiptMaterialDetailDO(); + String[] ignore = appendIgnores(IgnoreNullUtil.getNullPropertyNames(src), + "children", "materialMoreDetailList"); + BeanUtils.copyProperties(src, t, ignore); + t.setMaterialMoreDetailList(convertMoreDetailList(src.getMaterialMoreDetailList())); + t.setChildren(convertMaterialDetailRows(src.getChildren())); + if (src.getMaterialDetailSerialNumberList() != null) { + t.setMaterialDetailSerialNumberList(new ArrayList<>(src.getMaterialDetailSerialNumberList())); + } + return t; + } + + private static List convertMoreDetailList(List src) { + if (src == null) { + return null; + } + List list = new ArrayList<>(src.size()); + for (MaterialMoreDetailDTO m : src) { + if (m == null) { + continue; + } + MaterialMoreDetailDO d = new MaterialMoreDetailDO(); + BeanUtils.copyProperties(m, d, IgnoreNullUtil.getNullPropertyNames(m)); + list.add(d); + } + return list; } }