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 75db99551..9b4982e87 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 @@ -275,7 +275,8 @@ public class StockReceiptOrderApplicationService { // 4.3 为每个明细行填充物料单位信息(如果单位信息为空) fillMaterialDetailUnitInfoRecursively(receiptMaterialDetailPOList, materialBaseInfoMap, packDetailMap); - + fillReceiptOrderHasCopyCodeFromMaterialBase(stockReceiptOrderPO, materialBaseInfoMap); + // 4.4 为每个明细行填充物料条码(为空时取物料维护的条码信息第一行的 barCode) Map materialBarCodeMap = buildMaterialBarCodeMap(materialBaseInfoIdSet); fillBarCodeFromMaterialBarCodeRecursively(receiptMaterialDetailPOList, materialBarCodeMap); @@ -842,6 +843,23 @@ public class StockReceiptOrderApplicationService { * @param materialBaseInfoMap 物料基础信息Map(key: materialBaseInfoId, value: MaterialBaseInfoPO) * @param packDetailMap 包装规格明细Map(key: materialBaseInfoId, value: PackDetailFeignPO,单位代码为EA) */ + /** + * 收货单头:根据本单涉及的物料主数据汇总「整单是否含抄码物料」(与明细行 copyCode 同源) + */ + private void fillReceiptOrderHasCopyCodeFromMaterialBase(StockReceiptOrderPO order, Map materialBaseInfoMap) { + if (order == null) { + return; + } + if (materialBaseInfoMap == null || materialBaseInfoMap.isEmpty()) { + order.setHasCopyCodeMaterial(2); + return; + } + boolean anyCopy = materialBaseInfoMap.values().stream() + .filter(Objects::nonNull) + .anyMatch(m -> m.getCopyCode() != null && m.getCopyCode() == 1); + order.setHasCopyCodeMaterial(anyCopy ? 1 : 2); + } + private void fillMaterialDetailUnitInfoRecursively(List receiptMaterialDetailPOList, Map materialBaseInfoMap, Map packDetailMap) { @@ -865,6 +883,9 @@ public class StockReceiptOrderApplicationService { if (StringUtils.isBlank(receiptMaterialDetailPO.getPackName()) && StringUtils.isNotBlank(materialBaseInfoPO.getPackName())) { receiptMaterialDetailPO.setPackName(materialBaseInfoPO.getPackName()); } + if (materialBaseInfoPO.getCopyCode() != null) { + receiptMaterialDetailPO.setCopyCode(materialBaseInfoPO.getCopyCode()); + } } // 只有当单位信息为空时才填充 if (StringUtils.isBlank(receiptMaterialDetailPO.getUnitCode()) @@ -1167,84 +1188,160 @@ public class StockReceiptOrderApplicationService { return null; } List materialDetailList = stockReceiptOrderPO.getMaterialDetailList(); - if (!CollectionUtils.isEmpty(materialDetailList)) { - // PDA 详情筛选:receiptStatus=1 仅 1 待收货、2 收货中;receiptStatus=3 为 3 已收货、4 少收、5 超收(不含 1、2) - if (receiptStatus != null) { - materialDetailList = filterMaterialDetailsByReceiptStatus(materialDetailList, receiptStatus); - stockReceiptOrderPO.setMaterialDetailList(materialDetailList); - } - if (CollectionUtils.isEmpty(materialDetailList)) { - return stockReceiptOrderPO; - } - Set materialBaseInfoIdSet = new HashSet<>(); - collectMaterialBaseInfoIdsRecursively(materialDetailList, materialBaseInfoIdSet); - Map 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()); + if (CollectionUtils.isEmpty(materialDetailList)) { + stockReceiptOrderPO.setHasCopyCodeMaterial(2); + return stockReceiptOrderPO; + } + // PDA 详情筛选:receiptStatus=1 仅 1 待收货、2 收货中;receiptStatus=3 为 3 已收货、4 少收、5 超收(不含 1、2) + if (receiptStatus != null) { + materialDetailList = filterMaterialDetailsByReceiptStatus(materialDetailList, receiptStatus); + stockReceiptOrderPO.setMaterialDetailList(materialDetailList); + } + if (CollectionUtils.isEmpty(materialDetailList)) { + stockReceiptOrderPO.setHasCopyCodeMaterial(2); + return stockReceiptOrderPO; + } + Set materialBaseInfoIdSet = new HashSet<>(); + collectMaterialBaseInfoIdsRecursively(materialDetailList, materialBaseInfoIdSet); + Map materialBaseInfoMap = new HashMap<>(); + for (Long materialBaseInfoId : materialBaseInfoIdSet) { + try { + MaterialBaseInfoPO materialBaseInfoPO = materialBaseInfoService.getInfo(materialBaseInfoId); + if (materialBaseInfoPO != null) { + materialBaseInfoMap.put(materialBaseInfoId, materialBaseInfoPO); } - } - Map 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); - // 物料条码为空时取物料维护的条码信息第一行的 barCode - Map materialBarCodeMap = buildMaterialBarCodeMap(materialBaseInfoIdSet); - fillBarCodeFromMaterialBarCodeRecursively(materialDetailList, materialBarCodeMap); - // 第一次收货:主项无子项时,收货数量默认等于计划数量 - fillFirstReceiptQuantityDefault(materialDetailList); - // PDA 端与 PC 端一致:主行收货数量取第一条子项,已收货数量汇总所有子项 - flattenMaterialDetailList(materialDetailList); - // 须先算待收指标再清空子项 quantity;已收尾明细(3/4/5)不按「计划−待收」计算,见 isPdaReceiptDetailFullyReceived - if (receiptStatus != null && receiptStatus == 1) { - fillPendingDisplayFieldsRecursively(materialDetailList); - } else { - fillPendingMetricsOnlyRecursively(materialDetailList); - fillPendingReceiptQuantityRecursively(materialDetailList); - syncReceiptQuantityCumulativeDisplayRecursively(materialDetailList); - } - // pending* = plan* − already_receipt_*(主行 already* 已为全部已收汇总) - fillPlanAndPendingMetricsRecursively(materialDetailList); - // 未完成行:total* 与 pending* 同值,即「计划总的 − 全部已收」 - overwriteTotalWithPendingForPdaDisplayRecursively(materialDetailList); - clearChildQuantityRecursively(materialDetailList); - // 仅在未按 tab 筛明细时纠正整单头状态;筛成「待收/已收」子集时不能据子集推断整单是否已收完 - if (receiptStatus == null) { - refreshPdaReceiptOrderHeaderStatusFromDerivedPlanLines(stockReceiptOrderPO, materialDetailList); + } catch (Exception e) { + log.warn("获取物料基础信息失败,物料基础信息ID:{},错误:{}", materialBaseInfoId, e.getMessage()); } } + Map 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); + fillReceiptOrderHasCopyCodeFromMaterialBase(stockReceiptOrderPO, materialBaseInfoMap); + // 物料条码为空时取物料维护的条码信息第一行的 barCode + Map materialBarCodeMap = buildMaterialBarCodeMap(materialBaseInfoIdSet); + fillBarCodeFromMaterialBarCodeRecursively(materialDetailList, materialBarCodeMap); + // 第一次收货:主项无子项时,收货数量默认等于计划数量 + fillFirstReceiptQuantityDefault(materialDetailList); + // PDA 端与 PC 端一致:主行收货数量取第一条子项,已收货数量汇总所有子项 + flattenMaterialDetailList(materialDetailList); + // 须先算待收指标再清空子项 quantity;已收尾明细(3/4/5)不按「计划−待收」计算,见 isPdaReceiptDetailFullyReceived + if (receiptStatus != null && receiptStatus == 1) { + fillPendingDisplayFieldsRecursively(materialDetailList); + } else { + fillPendingMetricsOnlyRecursively(materialDetailList); + fillPendingReceiptQuantityRecursively(materialDetailList); + syncReceiptQuantityCumulativeDisplayRecursively(materialDetailList); + } + // pending* = plan* − already_receipt_*(主行 already* 已为全部已收汇总) + fillPlanAndPendingMetricsRecursively(materialDetailList); + // 未完成行:total* 与 pending* 同值,即「计划总的 − 全部已收」 + overwriteTotalWithPendingForPdaDisplayRecursively(materialDetailList); + clearChildQuantityRecursively(materialDetailList); + // 仅在未按 tab 筛明细时纠正整单头状态;筛成「待收/已收」子集时不能据子集推断整单是否已收完 + if (receiptStatus == null) { + refreshPdaReceiptOrderHeaderStatusFromDerivedPlanLines(stockReceiptOrderPO, materialDetailList); + } return stockReceiptOrderPO; } + /** + * PDA:与 PC 端收货明细上的「抄码方式」同源——物料主数据 {@link MaterialBaseInfoPO#getCopyCode()}(1-是 2-否)。 + * 在列表页未调用 {@link #getInfoByApp(Long, Integer)} 时,可仅凭收货单 ID + 明细 materialDetailId 拉取该标识用于跳转抄码页或普通收货页。 + */ + public Map getCopyCodeForPdaReceiptLine(Long receiptOrderId, Long materialDetailId) { + StockReceiptOrderPO order = stockReceiptOrderDomainService.getInfo(receiptOrderId); + if (order == null) { + throw new ServiceException("收货单不存在"); + } + ReceiptMaterialDetailPO line = receiptMaterialDetailDomainService.getInfo(materialDetailId); + if (line == null) { + throw new ServiceException("收货明细不存在"); + } + if (!Objects.equals(order.getReceiptOrderNumber(), line.getReceiptOrderNumber())) { + throw new ServiceException("收货明细不属于该收货单"); + } + Long materialBaseInfoId = line.getMaterialBaseInfoId(); + Map ret = new HashMap<>(4); + ret.put("materialDetailId", materialDetailId); + ret.put("materialBaseInfoId", materialBaseInfoId); + if (materialBaseInfoId == null) { + ret.put("copyCode", null); + return ret; + } + MaterialBaseInfoPO m = materialBaseInfoService.getInfo(materialBaseInfoId); + ret.put("copyCode", m != null ? m.getCopyCode() : null); + return ret; + } + + /** + * PDA:仅已知物料基础信息 ID 时查询是否抄码(与 PC 物料主数据一致)。列表若带出 materialBaseInfoId 可直接用,无需收货明细 ID。 + */ + public Map getCopyCodeByMaterialBaseInfoId(Long materialBaseInfoId) { + if (materialBaseInfoId == null) { + throw new ServiceException("物料基础信息ID不能为空"); + } + MaterialBaseInfoPO m = materialBaseInfoService.getInfo(materialBaseInfoId); + Map ret = new HashMap<>(4); + ret.put("materialBaseInfoId", materialBaseInfoId); + ret.put("copyCode", m != null ? m.getCopyCode() : null); + return ret; + } + /** * PDA:点击卡片后查询当前计划行下全部分批收货子行(level=2,库表真实数据,不含 getInfoByApp 的 parent_copy)。 */ public List listLevel2ChildrenByParentForApp(Long receiptOrderId, Long parentMaterialDetailId) { - List receiptMaterialDetailPOS = stockReceiptOrderDomainService.listLevel2ChildrenByParentForApp(receiptOrderId, parentMaterialDetailId); - return stockReceiptOrderDomainService.listLevel2ChildrenByParentForApp(receiptOrderId, parentMaterialDetailId); + List list = stockReceiptOrderDomainService.listLevel2ChildrenByParentForApp(receiptOrderId, parentMaterialDetailId); + if (CollectionUtils.isEmpty(list)) { + return list; + } + Set materialBaseInfoIdSet = new HashSet<>(); + for (ReceiptMaterialDetailPO line : list) { + if (line != null && line.getMaterialBaseInfoId() != null) { + materialBaseInfoIdSet.add(line.getMaterialBaseInfoId()); + } + } + Map materialBaseInfoMap = new HashMap<>(); + for (Long id : materialBaseInfoIdSet) { + try { + MaterialBaseInfoPO po = materialBaseInfoService.getInfo(id); + if (po != null) { + materialBaseInfoMap.put(id, po); + } + } catch (Exception e) { + log.warn("获取物料基础信息失败,物料基础信息ID:{},错误:{}", id, e.getMessage()); + } + } + for (ReceiptMaterialDetailPO line : list) { + if (line == null || line.getMaterialBaseInfoId() == null) { + continue; + } + MaterialBaseInfoPO mb = materialBaseInfoMap.get(line.getMaterialBaseInfoId()); + if (mb != null && mb.getCopyCode() != null) { + line.setCopyCode(mb.getCopyCode()); + } + } + return list; } /** @@ -1985,9 +2082,12 @@ public class StockReceiptOrderApplicationService { continue; } ReceiptMaterialDetailDO firstChild = children.get(0); - // 将第一条子项的值赋给主项(含批次属性、收货数量等) - BeanUtils.copyProperties(firstChild, parent, "children", "parentUniqueId", "uniqueId", "materialDetailId", - "organizationIdList", "permissionMenuId", "receiptOrderNumberList", "compoundOrQuery"); + // 主行已携带本次收货/抄码数据时,不再被 children[0] 覆盖(避免 copyDetails/copyQuantity 被清空) + if (!hasPdaSubmittedReceiptOrCopyData(parent)) { + // 将第一条子项的值赋给主项(含批次属性、收货数量等) + BeanUtils.copyProperties(firstChild, parent, "children", "parentUniqueId", "uniqueId", "materialDetailId", + "organizationIdList", "permissionMenuId", "receiptOrderNumberList", "compoundOrQuery"); + } // 删除 children 中的第一条 List newChildren = new ArrayList<>(); for (int i = 1; i < children.size(); i++) { @@ -1997,6 +2097,26 @@ public class StockReceiptOrderApplicationService { } } + private static boolean hasPdaSubmittedReceiptOrCopyData(ReceiptMaterialDetailDO line) { + if (line == null) { + return false; + } + BigDecimal qty = line.getReceiptQuantity() != null ? line.getReceiptQuantity() : BigDecimal.ZERO; + BigDecimal gross = line.getReceiptGrossWeight() != null ? line.getReceiptGrossWeight() : BigDecimal.ZERO; + BigDecimal net = line.getReceiptNetWeight() != null ? line.getReceiptNetWeight() : BigDecimal.ZERO; + BigDecimal volume = line.getReceiptVolume() != null ? line.getReceiptVolume() : BigDecimal.ZERO; + BigDecimal area = line.getReceiptArea() != null ? line.getReceiptArea() : BigDecimal.ZERO; + return qty.compareTo(BigDecimal.ZERO) > 0 + || gross.compareTo(BigDecimal.ZERO) > 0 + || net.compareTo(BigDecimal.ZERO) > 0 + || volume.compareTo(BigDecimal.ZERO) > 0 + || area.compareTo(BigDecimal.ZERO) > 0 + || StringUtils.isNotBlank(line.getCopyQuantity()) + || StringUtils.isNotBlank(line.getCopyDetails()) + || StringUtils.isNotBlank(line.getCopyBatch()) + || StringUtils.isNotBlank(line.getPalletNumber()); + } + /** * PDA 收货回传时,将 materialDetailList 的第一项作为主项(level 1),其余项作为其子项(level 2) * 仅当数据库中第二项为 level 2(真实子项)时才转换,避免将两条平铺明细错误转为父子导致第一条被覆盖 diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/stockReceiptOrder/repository/po/StockReceiptOrderPO.java b/mhd_wms/src/main/java/com/mhd/wms/domain/stockReceiptOrder/repository/po/StockReceiptOrderPO.java index 06f53a37d..471b0dcb2 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/stockReceiptOrder/repository/po/StockReceiptOrderPO.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/stockReceiptOrder/repository/po/StockReceiptOrderPO.java @@ -139,6 +139,9 @@ public class StockReceiptOrderPO extends StockInOrderBasePO { @ApiModelProperty("物料明细") private List materialDetailList; + @ApiModelProperty("整单是否含抄码物料:1-是(至少一行物料主数据 copyCode=1) 2-否;与明细行 copyCode 同源,来自物料主数据") + private Integer hasCopyCodeMaterial; + @ApiModelProperty("收货作业单号") private String receiptTaskNumber; diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/stockShelfOrder/service/StockShelfOrderDomainService.java b/mhd_wms/src/main/java/com/mhd/wms/domain/stockShelfOrder/service/StockShelfOrderDomainService.java index 26ad43765..e6e88eacd 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/stockShelfOrder/service/StockShelfOrderDomainService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/stockShelfOrder/service/StockShelfOrderDomainService.java @@ -1123,33 +1123,92 @@ public class StockShelfOrderDomainService { } } + /** + * 上架完成、库存入账后写入抄码对照表。数据来自上架明细 {@link ShelfMaterialDetail#getCopyDetails()}, + * 与收货明细/PDA 提交的 JSON 一致:key 为序号(字符串),value 为单件净重(千克,支持小数如 1.343)。 + */ private void copyCodeProductComparison(MaterialBaseInfo materialBaseInfo, ShelfMaterialDetail shelfMaterialDetail, MaterialInventoryParamDO materialInventoryId) { - JSONObject jsonObject = JSONObject.parseObject(shelfMaterialDetail.getCopyDetails()); - ArrayList copyCodeReferences = new ArrayList<>(); + if (materialBaseInfo == null || shelfMaterialDetail == null || materialInventoryId == null) { + return; + } + if (StringUtils.isBlank(shelfMaterialDetail.getCopyDetails())) { + return; + } + JSONObject jsonObject; + try { + jsonObject = JSONObject.parseObject(shelfMaterialDetail.getCopyDetails().trim()); + } catch (Exception e) { + log.warn("抄码 copyDetails 非合法 JSON,跳过写入对照表,materialDetailId={},raw={}", + shelfMaterialDetail.getMaterialDetailId(), shelfMaterialDetail.getCopyDetails(), e); + return; + } + if (jsonObject == null || jsonObject.size() == 0) { + return; + } + List copyCodeReferences = new ArrayList<>(); for (String key : jsonObject.keySet()) { + if (StringUtils.isBlank(key)) { + continue; + } + BigDecimal lineNetKg = parseCopyDetailNetWeightKg(jsonObject.get(key)); + if (lineNetKg == null) { + continue; + } + int serial; + try { + serial = Integer.parseInt(key.trim()); + } catch (NumberFormatException e) { + log.warn("抄码 copyDetails 序号非数字,已跳过 key={}", key); + continue; + } CopyCodeReference copyCodeReference = new CopyCodeReference(); BeanUtils.copyProperties(materialBaseInfo, copyCodeReference); BeanUtils.copyProperties(shelfMaterialDetail, copyCodeReference, IgnoreNullUtil.getNullPropertyNames(shelfMaterialDetail)); copyCodeReference.setBoxPalletNo(shelfMaterialDetail.getPalletNumber()); copyCodeReference.setBatchNumber(shelfMaterialDetail.getCopyBatch()); - copyCodeReference.setSerialNumber(Integer.parseInt(key)); - Integer value = jsonObject.getInteger(key); - copyCodeReference.setNetWeight(new BigDecimal(value)); + copyCodeReference.setSerialNumber(serial); + copyCodeReference.setNetWeight(lineNetKg); + copyCodeReference.setGrossWeight(shelfMaterialDetail.getTotalGrossWeight()); copyCodeReference.setMaterialStatusName("可用"); copyCodeReference.setMaterialStatusCode("1"); copyCodeReference.setMaterialDetailId(shelfMaterialDetail.getMaterialDetailId()); copyCodeReference.setMaterialInventoryId(materialInventoryId.getMaterialInventoryId()); copyCodeReference.setInOrderNumber(materialInventoryId.getInOrderNumber()); - copyCodeReference.setInventoryQuantity(new BigDecimal(1)); - copyCodeReference.setNetWeight(shelfMaterialDetail.getTotalNetWeight()); - copyCodeReference.setGrossWeight(shelfMaterialDetail.getTotalGrossWeight()); + copyCodeReference.setInventoryQuantity(BigDecimal.ONE); copyCodeReference.setShipperName(materialBaseInfo.getShipperName()); copyCodeReference.setShipperId(materialBaseInfo.getShipperId()); copyCodeReferences.add(copyCodeReference); } + if (CollectionUtils.isEmpty(copyCodeReferences)) { + return; + } copyCodeReferenceService.saveBatch(copyCodeReferences); } + /** + * 解析 copyDetails JSON 中单件净重(千克),支持整数与小数。 + */ + private static BigDecimal parseCopyDetailNetWeightKg(Object raw) { + if (raw == null) { + return null; + } + try { + if (raw instanceof BigDecimal) { + return (BigDecimal) raw; + } + if (raw instanceof Number) { + return BigDecimal.valueOf(((Number) raw).doubleValue()); + } + String s = raw.toString().trim(); + if (StringUtils.isBlank(s)) { + return null; + } + return new BigDecimal(s); + } catch (Exception e) { + return null; + } + } + private MaterialInventory getParam(ShelfMaterialDetail shelfMaterialDetail, List fieldNames,Long shipperId,String inOrderNumber){ MaterialInventory param = new MaterialInventory(); param.setShipperId(shipperId); diff --git a/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/receiptMaterialDetail/ReceiptMaterialDetailDTO.java b/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/receiptMaterialDetail/ReceiptMaterialDetailDTO.java index a42c4b10c..4c8b0dce1 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/receiptMaterialDetail/ReceiptMaterialDetailDTO.java +++ b/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/receiptMaterialDetail/ReceiptMaterialDetailDTO.java @@ -53,6 +53,9 @@ public class ReceiptMaterialDetailDTO extends BaseVOEntity { @Excel(name = "物料基础信息id") private Long materialBaseInfoId; + @ApiModelProperty("是否抄码(物料主数据): 1-是 2-否,与 PC 明细一致") + private Integer copyCode; + @ApiModelProperty("物料编码") @Excel(name = "物料编码") private String materialCode; @@ -297,7 +300,7 @@ public class ReceiptMaterialDetailDTO extends BaseVOEntity { @Excel(name = "抄码数量") private String copyQuantity; - @ApiModelProperty("抄码数量克重详情") + @ApiModelProperty("抄码数量克重详情:JSON 字符串,key 为序号(1,2,3…),value 为单件净重KG(支持小数)。例:{\"1\":1.343,\"2\":1.343};上架完成后写入 copy_code_reference") @Excel(name = "抄码数量克重详情") private String copyDetails; } \ No newline at end of file diff --git a/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApp/stockReceiptOrder/StockReceiptOrderAppApi.java b/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApp/stockReceiptOrder/StockReceiptOrderAppApi.java index 40e3234fd..c3de72056 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApp/stockReceiptOrder/StockReceiptOrderAppApi.java +++ b/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApp/stockReceiptOrder/StockReceiptOrderAppApi.java @@ -18,9 +18,17 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.List; +import java.util.Map; /** - * 收货单Api + * 收货单 PDA Api + *

+ * 抄码收货方式与 PC 端 {@code StockReceiptOrderApi#getInfo} 一致:均来自物料主数据「是否抄码」({@code copyCode}:1-是 2-否), + * 在明细上由服务端填充(见 {@link com.mhd.wms.application.service.stockReceiptOrder.StockReceiptOrderApplicationService#getInfoByApp} / + * {@link com.mhd.wms.application.service.stockReceiptOrder.StockReceiptOrderApplicationService#getInfo} 中的单位/包装填充逻辑)。 + * 提交收货仍使用 {@link #receivingGoods},抄码实绩字段(托盘号、抄码批次、抄码数量、克重明细等)随明细 JSON 与 PC 相同。 + * 若列表页未拉详情,可在点击「收货」前调用 {@link #getCopyCodeForReceiptLine} 或 {@link #getCopyCodeByMaterialBaseInfoId} 仅取抄码标识。 + *

* * @author gen * @date 2024-05-21 @@ -63,6 +71,31 @@ public class StockReceiptOrderAppApi extends BaseController { return AjaxResult.success(stockReceiptOrderApplicationService.getInfoByApp(receiptOrderId, receiptStatus)); } + /** + * PDA:按收货单行查询是否抄码(与 PC 物料主数据 copyCode 一致)。列表未拉 {@link #getInfoByApp} 时,点击「收货」前调用本接口即可分流抄码页/普通收货页。 + * + * @return data 含 copyCode(1-是 2-否)、materialBaseInfoId、materialDetailId + */ + @ApiOperation("按收货明细行查询是否抄码(与PC同源,供跳转抄码收货页)") + @GetMapping("/getCopyCodeForReceiptLine") + public AjaxResult getCopyCodeForReceiptLine( + @ApiParam(value = "收货单ID", required = true) @RequestParam Long receiptOrderId, + @ApiParam(value = "收货明细 material_detail_id", required = true) @RequestParam Long materialDetailId) { + Map data = stockReceiptOrderApplicationService.getCopyCodeForPdaReceiptLine(receiptOrderId, materialDetailId); + return AjaxResult.success(data); + } + + /** + * PDA:仅已知物料基础信息 ID 时查询是否抄码(与 PC 一致)。列表若已带 materialBaseInfoId 可直调,无需整单详情。 + */ + @ApiOperation("按物料基础信息ID查询是否抄码") + @GetMapping("/getCopyCodeByMaterialBaseInfoId") + public AjaxResult getCopyCodeByMaterialBaseInfoId( + @ApiParam(value = "物料基础信息ID", required = true) @RequestParam Long materialBaseInfoId) { + Map data = stockReceiptOrderApplicationService.getCopyCodeByMaterialBaseInfoId(materialBaseInfoId); + return AjaxResult.success(data); + } + /** * PDA:查询某计划行(卡片)下所有 level=2 分批收货子行(含首笔仅落主行时的主行快照),附带序列号。 */ @@ -78,9 +111,10 @@ public class StockReceiptOrderAppApi extends BaseController { } /** - * 收货 + * 收货(与 PC 同源)。抄码物料请在对应明细上传 copyBatch、palletNumber、copyQuantity、copyDetails; + * copyDetails 为 JSON:序号 → 单件净重(KG),如 {"1":1.343,"2":1.343};抄码对照表在上架完成入账后写入,非本接口直接写。 */ - @ApiOperation("收货") + @ApiOperation("收货(抄码明细字段见 materialDetailList.copyDetails 等,与 PC 一致)") @PostMapping("/receivingGoods") public AjaxResult receivingGoods(@RequestBody StockReceiptOrderDTO stockReceiptOrderDTO) { // 勿用 Hutool JSON 往返转 DO:嵌套 children、receiptGrossWeight/receiptNetWeight/receiptVolume/receiptArea 等会丢失或类型不对,导致累计未落库