From a76e9c43678f9900c95d54654123f2d1d431e4d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=A6=E9=B8=BF=E5=B1=95?= <18031053041@163.com> Date: Mon, 27 Apr 2026 09:47:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=A5=E5=BA=93=E5=87=BA=E5=BA=93=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A=E5=8D=95=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BatchDetailApplicationService.java | 3 +- .../service/BatchDetailDomainService.java | 5 + mhd_wms/sql/pdaSql.sql | 4 + .../StockReceiptOrderApplicationService.java | 4 + .../StockShelfOrderApplicationService.java | 3 + .../ReceiptMaterialDetailImpl.java | 17 + .../persistence/ShelfMaterialDetailImpl.java | 55 +-- .../persistence/StockInTaskOrderImpl.java | 80 ++++- .../repository/po/StockInTaskOrderPO.java | 2 +- .../StockInTaskOrderDomainService.java | 26 +- .../repository/po/StockOutTaskOrderPO.java | 2 +- .../StockReceiptOrderDomainService.java | 171 ++++++++++ .../service/StockShelfOrderDomainService.java | 318 ++++++++++++------ .../po/TaskPickingMaterialDetailPO.java | 4 +- .../TaskShelfMaterialDetailImpl.java | 36 +- .../stockInTaskOrder/StockInTaskOrderDTO.java | 2 +- .../StockOutTaskOrderDTO.java | 2 +- .../StockInTaskOrderMapper.xml | 4 +- 18 files changed, 553 insertions(+), 185 deletions(-) diff --git a/mhd-modules/mhd-system/src/main/java/com/mhd/basic/application/service/batchDetail/BatchDetailApplicationService.java b/mhd-modules/mhd-system/src/main/java/com/mhd/basic/application/service/batchDetail/BatchDetailApplicationService.java index 9ca5b92f5..b0dc1861d 100644 --- a/mhd-modules/mhd-system/src/main/java/com/mhd/basic/application/service/batchDetail/BatchDetailApplicationService.java +++ b/mhd-modules/mhd-system/src/main/java/com/mhd/basic/application/service/batchDetail/BatchDetailApplicationService.java @@ -106,7 +106,8 @@ public class BatchDetailApplicationService { throw new ServiceException("获取物料规则信息失败"); } MaterialGoodsRuleFeign materialGoodsRuleFeign = JSON.parseObject(JSONObject.toJSONString(ajaxResult.get("data")), MaterialGoodsRuleFeign.class); - if (ObjectUtil.isNull(materialGoodsRuleFeign)){ + if (ObjectUtil.isNull(materialGoodsRuleFeign) || materialGoodsRuleFeign.getBatchId() == null) { + // 未绑定批次时只返回空列表,不可按空 batchId 全表查 batch_detail return new ArrayList<>(); } return getBatchDetailListByBatchId(materialGoodsRuleFeign.getBatchId()); diff --git a/mhd-modules/mhd-system/src/main/java/com/mhd/basic/domain/batchDetail/service/BatchDetailDomainService.java b/mhd-modules/mhd-system/src/main/java/com/mhd/basic/domain/batchDetail/service/BatchDetailDomainService.java index 17fec80d7..738e4a94d 100644 --- a/mhd-modules/mhd-system/src/main/java/com/mhd/basic/domain/batchDetail/service/BatchDetailDomainService.java +++ b/mhd-modules/mhd-system/src/main/java/com/mhd/basic/domain/batchDetail/service/BatchDetailDomainService.java @@ -7,6 +7,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.util.ArrayList; import java.util.List; /** * 批次管理详情 @@ -66,6 +67,10 @@ public class BatchDetailDomainService { * 获取批次管理详情详细信息 */ public List getBatchDetailListByBatchId(Long batchId) { + if (batchId == null) { + // batchId 为 null 时不能按 batchId 条件查询,否则 MyBatis 会略过 batch_id 条件导致整表全量 + return new ArrayList<>(); + } BatchDetailDO batchDetailDO = new BatchDetailDO(); batchDetailDO.setBatchId(batchId); return batchDetailService.queryList(batchDetailDO); diff --git a/mhd_wms/sql/pdaSql.sql b/mhd_wms/sql/pdaSql.sql index 920387f00..129f0edfb 100644 --- a/mhd_wms/sql/pdaSql.sql +++ b/mhd_wms/sql/pdaSql.sql @@ -59,4 +59,8 @@ ALTER TABLE NGWL_TEST_WMS.PICKING_MATERIAL_DETAIL ADD IN_ORDER_NUMBER varchar(10 +ALTER TABLE stock_receipt_order ADD oms_stock_in_order_id VARCHAR(64); + + + 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 525eb77f2..7a89e7891 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 @@ -216,6 +216,10 @@ public class StockReceiptOrderApplicationService { Map> batchDetailMap = new HashMap<>(); for (Long materialBaseInfoId : materialBaseInfoIdSet) { try { + MaterialGoodsRulePO localGoodsRule = materialGoodsRuleService.getInfoByMaterialBaseInfoIds(materialBaseInfoId); + if (localGoodsRule == null || localGoodsRule.getBatchId() == null) { + continue; + } AjaxResult ajaxResult = systemServiceFeign.getBatchDetailListByMaterialBaseInfoId(materialBaseInfoId); if (ajaxResult != null && "200".equals(String.valueOf(ajaxResult.get("code")))) { List batchDetailFeignPOList = JSON.parseArray( diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockShelfOrder/StockShelfOrderApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockShelfOrder/StockShelfOrderApplicationService.java index 3b1ba6640..a689a7f1d 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockShelfOrder/StockShelfOrderApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockShelfOrder/StockShelfOrderApplicationService.java @@ -2328,6 +2328,9 @@ public class StockShelfOrderApplicationService { } } } + if (materialMoreDetailList.isEmpty() && !CollectionUtils.isEmpty(existingList)) { + materialMoreDetailList.addAll(existingList); + } shelfMaterialDetailPO.setMaterialMoreDetailList(materialMoreDetailList); log.info("物料明细 uniqueId={}, materialBaseInfoId={}, materialMoreDetailList大小={}", shelfMaterialDetailPO.getUniqueId(), shelfMaterialDetailPO.getMaterialBaseInfoId(), diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/receiptMaterialDetail/repository/persistence/ReceiptMaterialDetailImpl.java b/mhd_wms/src/main/java/com/mhd/wms/domain/receiptMaterialDetail/repository/persistence/ReceiptMaterialDetailImpl.java index ef5dc2610..a71718ac9 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/receiptMaterialDetail/repository/persistence/ReceiptMaterialDetailImpl.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/receiptMaterialDetail/repository/persistence/ReceiptMaterialDetailImpl.java @@ -39,6 +39,8 @@ import com.mhd.wms.domain.materialInventory.entity.MaterialInventory; import com.mhd.wms.domain.materialInventory.repository.facade.IMaterialInventoryService; import com.mhd.wms.domain.materialInventory.repository.todo.MaterialInventoryDO; import com.mhd.wms.domain.materialInventory.repository.mapper.MaterialInventoryMapper; +import com.mhd.wms.domain.materialGoodsRule.repository.facade.IMaterialGoodsRuleService; +import com.mhd.wms.domain.materialGoodsRule.repository.po.MaterialGoodsRulePO; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -85,6 +87,8 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl loadBatchDetailIdToFieldName(Long materialBaseInfoId) { Map result = new HashMap<>(); + MaterialGoodsRulePO gr = materialGoodsRuleService.getInfoByMaterialBaseInfoIds(materialBaseInfoId); + if (gr == null || gr.getBatchId() == null) { + return result; + } try { AjaxResult ajaxResult = systemServiceFeign.getBatchDetailListByMaterialBaseInfoId(materialBaseInfoId); if (ajaxResult == null || !"200".equals(String.valueOf(ajaxResult.get("code")))) { @@ -1055,6 +1068,10 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl materialMoreDetailList = IMaterialMoreDetailService.queryList(materialMoreDetailDO); - if (CollectionUtils.isEmpty(materialMoreDetailList)) { - AjaxResult ajaxResult = systemServiceFeign.getBatchDetailListByMaterialBaseInfoId(shelfMaterialDetailPO.getMaterialBaseInfoId()); - if (ajaxResult != null && "200".equals(String.valueOf(ajaxResult.get("code")))) { - List batchList = JSON.parseArray(JSONObject.toJSONString(ajaxResult.get("data")), BatchDetailFeignPO.class); - materialMoreDetailList = filterAndConvertToMaterialMoreDetail(batchList); - } + if (materialMoreDetailList == null) { + materialMoreDetailList = new ArrayList<>(); } fillAttributeValueFromShelfMaterialDetail(shelfMaterialDetailPO, materialMoreDetailList); shelfMaterialDetailPO.setMaterialMoreDetailList(materialMoreDetailList); @@ -112,12 +100,8 @@ public class ShelfMaterialDetailImpl extends ServiceImpl materialMoreDetailList = IMaterialMoreDetailService.queryList(materialMoreDetailDO); - if (CollectionUtils.isEmpty(materialMoreDetailList)) { - AjaxResult ajaxResult = systemServiceFeign.getBatchDetailListByMaterialBaseInfoId(childrenDetailPO.getMaterialBaseInfoId()); - if (ajaxResult != null && "200".equals(String.valueOf(ajaxResult.get("code")))) { - List batchList = JSON.parseArray(JSONObject.toJSONString(ajaxResult.get("data")), BatchDetailFeignPO.class); - materialMoreDetailList = filterAndConvertToMaterialMoreDetail(batchList); - } + if (materialMoreDetailList == null) { + materialMoreDetailList = new ArrayList<>(); } fillAttributeValueFromShelfMaterialDetail(childrenDetailPO, materialMoreDetailList); childrenDetailPO.setMaterialMoreDetailList(materialMoreDetailList); @@ -210,13 +194,6 @@ public class ShelfMaterialDetailImpl extends ServiceImpl materialMoreDetailList = IMaterialMoreDetailService.queryList(materialMoreDetailDO); - if (CollectionUtils.isEmpty(materialMoreDetailList)) { - AjaxResult ajaxResult = systemServiceFeign.getBatchDetailListByMaterialBaseInfoId(row.getMaterialBaseInfoId()); - if (ajaxResult != null && "200".equals(String.valueOf(ajaxResult.get("code")))) { - List batchList = JSON.parseArray(JSONObject.toJSONString(ajaxResult.get("data")), BatchDetailFeignPO.class); - materialMoreDetailList = filterAndConvertToMaterialMoreDetail(batchList); - } - } if (materialMoreDetailList == null) { materialMoreDetailList = new ArrayList<>(); } @@ -224,30 +201,6 @@ public class ShelfMaterialDetailImpl extends ServiceImpl filterAndConvertToMaterialMoreDetail(List batchList) { - List 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; - } - /** * 从上架明细中获取收货数量、重量、体积、面积、批次属性值并填充到 materialMoreDetailList 的 attributeValue */ diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/stockInTaskOrder/repository/persistence/StockInTaskOrderImpl.java b/mhd_wms/src/main/java/com/mhd/wms/domain/stockInTaskOrder/repository/persistence/StockInTaskOrderImpl.java index 2ae7458e7..241fbc6d5 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/stockInTaskOrder/repository/persistence/StockInTaskOrderImpl.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/stockInTaskOrder/repository/persistence/StockInTaskOrderImpl.java @@ -2,6 +2,7 @@ package com.mhd.wms.domain.stockInTaskOrder.repository.persistence; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.mhd.common.core.constant.SnowFlakeConstants; +import com.mhd.common.core.utils.StringUtils; import com.mhd.common.core.utils.uuid.IdGenerator; import com.mhd.common.security.utils.SecurityUtils; import com.mhd.system.api.model.LoginUser; @@ -38,6 +39,11 @@ import java.util.List; */ @Service public class StockInTaskOrderImpl extends ServiceImpl implements IStockInTaskOrderService{ + /** + * 与收货侧同步写 remark 的约定前缀(见 StockReceiptOrderDomainService),用于 PDA/PC 收货后回写 task_receipt_material_detail。 + */ + public static final String TASK_RECEIPT_REMARK_RUID_PREFIX = "__RUID__:"; + @Autowired private StockInTaskOrderMapper stockInTaskOrderMapper; @Autowired @@ -99,6 +105,7 @@ public class StockInTaskOrderImpl extends ServiceImpl taskReceiptMaterialDetailDOList = taskReceiptMaterialDetailDO.getChildren(); if (taskReceiptMaterialDetailDOList != null){ @@ -114,6 +122,7 @@ public class StockInTaskOrderImpl extends ServiceImpl { + Long shelfLineBizUid = taskShelfMaterialDetailDO.getUniqueId(); TaskShelfMaterialDetail taskShelfMaterialDetail = new TaskShelfMaterialDetail(); BeanUtils.copyProperties(taskShelfMaterialDetailDO, taskShelfMaterialDetail, "materialDetailId","createBy","createByName","createTime", "updateBy","updateByName","updateTime"); @@ -168,28 +211,33 @@ public class StockInTaskOrderImpl extends ServiceImpl { - TaskShelfMaterialDetail taskShelfMaterialDetailChildren = new TaskShelfMaterialDetail(); - BeanUtils.copyProperties(taskShelfMaterialDetailDOChildren, taskShelfMaterialDetailChildren, "materialDetailId","createBy","createByName","createTime", + if (taskShelfMaterialDetailDO.getChildren() != null) { + taskShelfMaterialDetailDO.getChildren().forEach(taskShelfMaterialDetailDOChildren -> { + Long childShelfLineBizUid = taskShelfMaterialDetailDOChildren.getUniqueId(); + TaskShelfMaterialDetail taskShelfMaterialDetailChildren = new TaskShelfMaterialDetail(); + BeanUtils.copyProperties(taskShelfMaterialDetailDOChildren, taskShelfMaterialDetailChildren, "materialDetailId","createBy","createByName","createTime", "updateBy","updateByName","updateTime"); - taskShelfMaterialDetailChildren.setOrganizationId(loginUser.getUserPo().getOrganizationId()); - taskShelfMaterialDetailChildren.setOrganizationName(loginUser.getUserPo().getOrganizationName()); - taskShelfMaterialDetailChildren.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId()); - taskShelfMaterialDetailChildren.setTaskNumber(stockInTaskOrderDO.getTaskNumber()); - taskShelfMaterialDetailChildren.setUniqueId(idGenerator.snowflakeId(SnowFlakeConstants.wmsId)); - taskShelfMaterialDetailChildren.setParentUniqueId(taskShelfMaterialDetail.getUniqueId()); - taskShelfMaterialDetailChildren.setCreateBy(loginUser.getUserid()); - taskShelfMaterialDetailChildren.setCreateByName(loginUser.getUsername()); - taskShelfMaterialDetailChildren.setCreateTime(new Date()); - taskShelfMaterialDetailList.add(taskShelfMaterialDetailChildren); - //序列号 - materialDetailSerialNumberList.addAll(genMaterialDetailSerialNumberByShelf(taskShelfMaterialDetailDOChildren)); - }); + taskShelfMaterialDetailChildren.setOrganizationId(loginUser.getUserPo().getOrganizationId()); + taskShelfMaterialDetailChildren.setOrganizationName(loginUser.getUserPo().getOrganizationName()); + taskShelfMaterialDetailChildren.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId()); + taskShelfMaterialDetailChildren.setTaskNumber(stockInTaskOrderDO.getTaskNumber()); + mergeShelfLineUniqueIdIntoTaskRemark(taskShelfMaterialDetailChildren, childShelfLineBizUid); + taskShelfMaterialDetailChildren.setUniqueId(idGenerator.snowflakeId(SnowFlakeConstants.wmsId)); + taskShelfMaterialDetailChildren.setParentUniqueId(taskShelfMaterialDetail.getUniqueId()); + taskShelfMaterialDetailChildren.setCreateBy(loginUser.getUserid()); + taskShelfMaterialDetailChildren.setCreateByName(loginUser.getUsername()); + taskShelfMaterialDetailChildren.setCreateTime(new Date()); + taskShelfMaterialDetailList.add(taskShelfMaterialDetailChildren); + //序列号 + materialDetailSerialNumberList.addAll(genMaterialDetailSerialNumberByShelf(taskShelfMaterialDetailDOChildren)); + }); + } //序列号 materialDetailSerialNumberList.addAll(genMaterialDetailSerialNumberByShelf(taskShelfMaterialDetailDO)); }); diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/stockInTaskOrder/repository/po/StockInTaskOrderPO.java b/mhd_wms/src/main/java/com/mhd/wms/domain/stockInTaskOrder/repository/po/StockInTaskOrderPO.java index 28b201e5b..9ed58c026 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/stockInTaskOrder/repository/po/StockInTaskOrderPO.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/stockInTaskOrder/repository/po/StockInTaskOrderPO.java @@ -98,7 +98,7 @@ public class StockInTaskOrderPO extends BaseVOEntity { private String operatorsName; @ApiModelProperty("作业完成时间") - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") @Excel(name = "作业完成时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") private Date operatorsEndTime; diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/stockInTaskOrder/service/StockInTaskOrderDomainService.java b/mhd_wms/src/main/java/com/mhd/wms/domain/stockInTaskOrder/service/StockInTaskOrderDomainService.java index 285605a62..af6c25fe4 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/stockInTaskOrder/service/StockInTaskOrderDomainService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/stockInTaskOrder/service/StockInTaskOrderDomainService.java @@ -83,18 +83,20 @@ public class StockInTaskOrderDomainService { if (stockInTaskOrderPO == null) { return null; } - if (Integer.valueOf(1).equals(stockInTaskOrderPO.getType())){ + int taskType = resolveStockInTaskOrderType(stockInTaskOrderPO); + if (taskType == 1) { // 收货作业:优先按收货单号查询,查不到再回退作业单号 List receiptDetails = getReceiptInfo(stockInTaskOrderPO.getReceiptOrderNumber()); if (CollectionUtils.isEmpty(receiptDetails)) { receiptDetails = getReceiptInfo(stockInTaskOrderPO.getTaskNumber()); } stockInTaskOrderPO.setTaskReceiptMaterialDetailList(receiptDetails); - } else if (Integer.valueOf(2).equals(stockInTaskOrderPO.getType())) { - // 上架作业:优先按上架单号查询,查不到再回退作业单号 - List shelfDetails = getShelfInfo(stockInTaskOrderPO.getShelfOrderNumber()); + } else if (taskType == 2) { + // 上架作业:task_shelf_material_detail.task_number 存的是「作业单号 SHZY...」(见 genStockShelfTaskOrder), + // 与上架单号 SJ 不一致,须优先用作业单号;再按上架单号兜底历史/异常数据 + List shelfDetails = getShelfInfo(stockInTaskOrderPO.getTaskNumber()); if (CollectionUtils.isEmpty(shelfDetails)) { - shelfDetails = getShelfInfo(stockInTaskOrderPO.getTaskNumber()); + shelfDetails = getShelfInfo(stockInTaskOrderPO.getShelfOrderNumber()); } stockInTaskOrderPO.setTaskShelfMaterialDetailList(shelfDetails); } else { @@ -104,15 +106,25 @@ public class StockInTaskOrderDomainService { receiptDetails = getReceiptInfo(stockInTaskOrderPO.getTaskNumber()); } stockInTaskOrderPO.setTaskReceiptMaterialDetailList(receiptDetails); - List shelfDetails = getShelfInfo(stockInTaskOrderPO.getShelfOrderNumber()); + List shelfDetails = getShelfInfo(stockInTaskOrderPO.getTaskNumber()); if (CollectionUtils.isEmpty(shelfDetails)) { - shelfDetails = getShelfInfo(stockInTaskOrderPO.getTaskNumber()); + shelfDetails = getShelfInfo(stockInTaskOrderPO.getShelfOrderNumber()); } stockInTaskOrderPO.setTaskShelfMaterialDetailList(shelfDetails); } return stockInTaskOrderPO; } + /** 兼容 Integer/Long/Byte 等 JDBC 映射,避免 2L 与 Integer(2) equals 为 false 导致走错分支。 */ + private static int resolveStockInTaskOrderType(StockInTaskOrderPO po) { + if (po == null || po.getType() == null) { + return 0; + } + if (po.getType() instanceof Number) { + return ((Number) po.getType()).intValue(); + } + return 0; + } /** * 获取入库收货作业单详细信息 diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/stockOutTaskOrder/repository/po/StockOutTaskOrderPO.java b/mhd_wms/src/main/java/com/mhd/wms/domain/stockOutTaskOrder/repository/po/StockOutTaskOrderPO.java index 502bba4f1..a47876e0a 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/stockOutTaskOrder/repository/po/StockOutTaskOrderPO.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/stockOutTaskOrder/repository/po/StockOutTaskOrderPO.java @@ -143,7 +143,7 @@ public class StockOutTaskOrderPO extends BaseVOEntity { private String operatorsName; @ApiModelProperty("作业完成时间") - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") @Excel(name = "作业完成时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") private Date operatorsEndTime; 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 6990779be..0173fcf13 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 @@ -5,6 +5,7 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson2.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.mhd.common.core.constant.SnowFlakeConstants; @@ -40,6 +41,7 @@ import com.mhd.wms.domain.inventoryStandingReport.repository.facade.IInventorySt import com.mhd.wms.domain.inventoryStandingReport.repository.todo.InventoryStandingReportDO; import com.mhd.wms.domain.materialGoodsRule.entity.MaterialGoodsRule; import com.mhd.wms.domain.materialGoodsRule.repository.facade.IMaterialGoodsRuleService; +import com.mhd.wms.domain.materialGoodsRule.repository.po.MaterialGoodsRulePO; import com.mhd.wms.domain.materialMoreDetail.repository.facade.IMaterialMoreDetailService; import com.mhd.wms.domain.materialMoreDetail.repository.po.MaterialMoreDetailPO; import com.mhd.wms.domain.materialMoreDetail.repository.todo.MaterialMoreDetailDO; @@ -68,6 +70,8 @@ import com.mhd.wms.domain.stockShelfOrder.repository.facade.IStockShelfOrderServ import com.mhd.wms.domain.stockShelfOrder.repository.po.StockShelfOrderPO; import com.mhd.wms.domain.stockShelfOrder.repository.todo.StockShelfOrderDO; import com.mhd.wms.domain.stockShelfOrder.service.StockShelfOrderDomainService; +import com.mhd.wms.domain.taskReceiptMaterialDetail.entity.TaskReceiptMaterialDetail; +import com.mhd.wms.domain.taskReceiptMaterialDetail.repository.facade.ITaskReceiptMaterialDetailService; import com.mhd.wms.domain.taskReceiptMaterialDetail.repository.todo.TaskReceiptMaterialDetailDO; import com.mhd.wms.interfaces.dto.stockReceiptOrder.StockReceiptOrderDTO; import io.swagger.annotations.ApiModelProperty; @@ -80,6 +84,7 @@ import org.springframework.util.CollectionUtils; import javax.annotation.Resource; import java.math.BigDecimal; import java.util.*; +import java.util.regex.Pattern; import java.util.stream.Collectors; /** @@ -92,6 +97,9 @@ import java.util.stream.Collectors; @Slf4j public class StockReceiptOrderDomainService { + /** 与 {@link com.mhd.wms.domain.stockInTaskOrder.repository.persistence.StockInTaskOrderImpl#TASK_RECEIPT_REMARK_RUID_PREFIX} 一致,用于在作业单 remark 中关联收货行 uniqueId。 */ + private static final String TASK_RECEIPT_REMARK_RUID_PREFIX = "__RUID__:"; + @Autowired private IStockReceiptOrderService stockReceiptOrderService; @Autowired @@ -99,6 +107,8 @@ public class StockReceiptOrderDomainService { @Autowired private IStockInTaskOrderService stockInTaskOrderService; @Autowired + private ITaskReceiptMaterialDetailService taskReceiptMaterialDetailService; + @Autowired private IInOrderAbnormalService iInOrderAbnormalService; @Autowired private StockShelfOrderDomainService stockShelfOrderDomainService; @@ -297,6 +307,11 @@ public class StockReceiptOrderDomainService { if (materialBaseInfoId == null) { return materialMoreDetailPOList; } + // 与 queryListChildren 内 buildMaterialMoreDetailListByMaterialBinding 一致:无商品规则或未绑 batch_id 不调 System + MaterialGoodsRulePO goodsRule = materialGoodsRuleService.getInfoByMaterialBaseInfoIds(materialBaseInfoId); + if (goodsRule == null || goodsRule.getBatchId() == null) { + return materialMoreDetailPOList; + } try { AjaxResult ajaxResult = systemServiceFeign.getBatchDetailListByMaterialBaseInfoId(materialBaseInfoId); if (ajaxResult == null || !"200".equals(String.valueOf(ajaxResult.get("code")))) { @@ -445,6 +460,8 @@ public class StockReceiptOrderDomainService { genInventoryStandingReport(stockReceiptOrderPO, stockReceiptOrderDO); //修改物料明细信息 receiptMaterialDetailService.batchReceiptUpdate(stockReceiptOrderDO); + // 与收货单明细一致:同步更新已下发的「收货」入库作业单 task_receipt_material_detail(PDA/PC 每次提交收货均刷新) + syncTaskReceiptMaterialDetailsWithReceiptLines(stockReceiptOrderDO); // 同步更新入库单明细的收货数量(入库单 totalNetWeight/totalGrossWeight/totalVolume/totalArea 不因收货改库,见 sync 内注释) syncUpdateInMaterialDetailFromReceipt(stockReceiptOrderDO, stockReceiptOrderPO); // 收货类入库作业单在「任务下发」时生成,此处不再生成 type=1 作业单 @@ -459,6 +476,160 @@ public class StockReceiptOrderDomainService { } + /** + * 收货保存后,将收货单明细中的实收数量/状态同步到已生成的「收货」类入库作业单明细(task_receipt_material_detail)。 + * 关联键:生成作业单时在 {@link com.mhd.wms.domain.stockInTaskOrder.repository.persistence.StockInTaskOrderImpl#genStockReceiptTaskOrder} + * 写入 remark 的 {@value #TASK_RECEIPT_REMARK_RUID_PREFIX} + 收货行 business uniqueId。 + */ + private void syncTaskReceiptMaterialDetailsWithReceiptLines(StockReceiptOrderDO stockReceiptOrderDO) { + if (stockReceiptOrderDO == null || CollectionUtils.isEmpty(stockReceiptOrderDO.getMaterialDetailList())) { + return; + } + String receiptOrderNumber = stockReceiptOrderDO.getReceiptOrderNumber(); + if (StringUtils.isBlank(receiptOrderNumber)) { + ReceiptMaterialDetailDO head = stockReceiptOrderDO.getMaterialDetailList().get(0); + if (head != null) { + receiptOrderNumber = head.getReceiptOrderNumber(); + } + } + if (StringUtils.isBlank(receiptOrderNumber)) { + return; + } + String taskNumber = resolveReceiptTypeTaskNumber(receiptOrderNumber); + if (StringUtils.isBlank(taskNumber)) { + return; + } + List taskRows = taskReceiptMaterialDetailService.list( + new LambdaQueryWrapper() + .eq(TaskReceiptMaterialDetail::getTaskNumber, taskNumber) + .eq(TaskReceiptMaterialDetail::getDelFlag, 1)); + if (CollectionUtils.isEmpty(taskRows)) { + return; + } + Map taskByReceiptLineUid = new HashMap<>(); + for (TaskReceiptMaterialDetail tr : taskRows) { + Long uid = extractReceiptLineUniqueIdFromTaskRemark(tr.getRemark()); + if (uid != null && !taskByReceiptLineUid.containsKey(uid)) { + taskByReceiptLineUid.put(uid, tr); + } + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + Date now = new Date(); + String userRealName = resolveUserRealNameForTaskSync(loginUser); + applyReceiptLineToTaskDetails( + stockReceiptOrderDO.getMaterialDetailList(), taskRows, taskByReceiptLineUid, loginUser, userRealName, now); + } + + private static String resolveUserRealNameForTaskSync(LoginUser loginUser) { + if (loginUser == null) { + return null; + } + if (loginUser.getUserPo() != null && StringUtils.isNotBlank(loginUser.getUserPo().getUserName())) { + return loginUser.getUserPo().getUserName().trim(); + } + if (StringUtils.isNotBlank(loginUser.getRealname())) { + return loginUser.getRealname().trim(); + } + return loginUser.getUsername(); + } + + /** + * 本单「收货」类入库作业单(type=1)作业单号;无则未下发或已删。 + */ + private String resolveReceiptTypeTaskNumber(String receiptOrderNumber) { + if (StringUtils.isBlank(receiptOrderNumber)) { + return null; + } + List rows = stockInTaskOrderService.list( + new LambdaQueryWrapper() + .eq(StockInTaskOrder::getReceiptOrderNumber, receiptOrderNumber) + .eq(StockInTaskOrder::getType, 1) + .eq(StockInTaskOrder::getDelFlag, 1) + .orderByDesc(StockInTaskOrder::getInTaskOrderId) + .last("LIMIT 1")); + if (CollectionUtils.isEmpty(rows)) { + return null; + } + return rows.get(0).getTaskNumber(); + } + + private void applyReceiptLineToTaskDetails(List lines, + List allTaskRows, + Map taskByReceiptLineUid, + LoginUser loginUser, String userRealName, Date now) { + if (CollectionUtils.isEmpty(lines)) { + return; + } + for (ReceiptMaterialDetailDO line : lines) { + if (line == null) { + continue; + } + if (line.getUniqueId() != null) { + TaskReceiptMaterialDetail tr = taskByReceiptLineUid.get(line.getUniqueId()); + if (tr == null && allTaskRows != null) { + long uid = line.getUniqueId(); + for (TaskReceiptMaterialDetail row : allTaskRows) { + if (row != null && remarkContainsRuidToken(row.getRemark(), uid)) { + tr = row; + break; + } + } + } + if (tr != null && tr.getMaterialDetailId() != null) { + BigDecimal syncQty = line.getAlreadyReceiptQuantity() != null + ? line.getAlreadyReceiptQuantity() + : line.getReceiptQuantity(); + TaskReceiptMaterialDetail patch = new TaskReceiptMaterialDetail(); + patch.setMaterialDetailId(tr.getMaterialDetailId()); + patch.setReceiptQuantity(syncQty); + patch.setReceiptStatus(line.getReceiptStatus()); + if (loginUser != null) { + patch.setUpdateBy(loginUser.getUserid()); + } + patch.setUpdateByName(userRealName); + patch.setUpdateTime(now); + taskReceiptMaterialDetailService.updateById(patch); + } + } + if (!CollectionUtils.isEmpty(line.getChildren())) { + applyReceiptLineToTaskDetails(line.getChildren(), allTaskRows, taskByReceiptLineUid, loginUser, userRealName, now); + } + } + } + + private static boolean remarkContainsRuidToken(String remark, long uid) { + if (remark == null) { + return false; + } + return Pattern.compile(TASK_RECEIPT_REMARK_RUID_PREFIX + uid + "(?!\\d)").matcher(remark).find(); + } + + /** + * 从作业单 remark 中解析首个「__RUID__:数字」对应的收货行 business id(与 receipt_material_detail.unique_id 一致)。 + */ + private static Long extractReceiptLineUniqueIdFromTaskRemark(String remark) { + if (StringUtils.isBlank(remark)) { + return null; + } + int i = remark.indexOf(TASK_RECEIPT_REMARK_RUID_PREFIX); + if (i < 0) { + return null; + } + int j = i + TASK_RECEIPT_REMARK_RUID_PREFIX.length(); + int k = j; + while (k < remark.length() && Character.isDigit(remark.charAt(k))) { + k++; + } + if (k == j) { + return null; + } + try { + return Long.parseLong(remark.substring(j, k)); + } catch (NumberFormatException e) { + return null; + } + } + private void saveAmount(StockReceiptOrderDO stockReceiptOrderDO) { Long receiptOrderId = stockReceiptOrderDO.getReceiptOrderId(); receiptOrderAccountService.remove(new QueryWrapper().lambda().eq(ReceiptOrderAccount::getOrderId, receiptOrderId)); 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 67c597932..745f05cf1 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 @@ -70,11 +70,14 @@ import com.mhd.wms.domain.stockInOrder.entity.StockInOrder; import com.mhd.wms.domain.stockInOrder.repository.facade.IStockInOrderService; import com.mhd.wms.domain.stockInTaskOrder.entity.StockInTaskOrder; import com.mhd.wms.domain.stockInTaskOrder.repository.facade.IStockInTaskOrderService; +import com.mhd.wms.domain.stockInTaskOrder.repository.persistence.StockInTaskOrderImpl; import com.mhd.wms.domain.stockInTaskOrder.repository.todo.StockInTaskOrderDO; import com.mhd.wms.domain.stockShelfOrder.entity.StockShelfOrder; import com.mhd.wms.domain.stockShelfOrder.repository.facade.IStockShelfOrderService; import com.mhd.wms.domain.stockShelfOrder.repository.po.StockShelfOrderPO; import com.mhd.wms.domain.stockShelfOrder.repository.todo.StockShelfOrderDO; +import com.mhd.wms.domain.taskShelfMaterialDetail.entity.TaskShelfMaterialDetail; +import com.mhd.wms.domain.taskShelfMaterialDetail.repository.facade.ITaskShelfMaterialDetailService; import com.mhd.wms.domain.taskShelfMaterialDetail.repository.todo.TaskShelfMaterialDetailDO; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -85,6 +88,7 @@ import org.springframework.util.CollectionUtils; import javax.annotation.Resource; import java.math.BigDecimal; import java.util.*; +import java.util.regex.Pattern; import java.util.stream.Collectors; /** @@ -116,6 +120,8 @@ public class StockShelfOrderDomainService { @Autowired private IStockInTaskOrderService stockInTaskOrderService; @Autowired + private ITaskShelfMaterialDetailService taskShelfMaterialDetailService; + @Autowired private IInventoryStandingDetailService inventoryStandingDetailService; @Autowired private IDeliveTaskService deliveTaskService; @@ -359,6 +365,8 @@ public class StockShelfOrderDomainService { userRealNameUpShelf); //同步更新入库单明细的上架数量/上架状态 syncShelvesQuantityToInMaterialDetail(stockShelfOrderDO); + // 同步已下发的「上架」入库作业单明细 task_shelf_material_detail(与收货侧回写 task_receipt 一致) + syncTaskShelfMaterialDetailsWithShelfLines(stockShelfOrderDO); // 上架类入库作业单 type=2:PDA 已在收货完成时生成;若尚未生成(如 PC 路径)则在本环节补生成 if (countShelfTypeInTaskOrder(stockShelfOrderPO.getShelfOrderNumber()) == 0) { genStockShelfTaskOrderByUpShelf(stockShelfOrderDO); @@ -572,7 +580,154 @@ public class StockShelfOrderDomainService { log.info("完成同步更新入库单【{}】的明细", inOrderNumber); } - + + /** + * 上架每次提交/完成时,将 shelf_material_detail 的累计上架数量、上架状态写回已下发的 type=2 作业单明细 task_shelf_material_detail。 + * 行关联:{@link StockInTaskOrderImpl#genStockShelfTaskOrder} 在 remark 中写入 __RUID__:+上架行 business uniqueId;无 remark 的旧数据按 in_unique_id+receipt_unique_id+level+物料 匹配。 + */ + private void syncTaskShelfMaterialDetailsWithShelfLines(StockShelfOrderDO stockShelfOrderDO) { + if (stockShelfOrderDO == null || StringUtils.isBlank(stockShelfOrderDO.getShelfOrderNumber())) { + return; + } + String taskNumber = resolveShelfTypeTaskNumberByShelfOrderNumber(stockShelfOrderDO.getShelfOrderNumber()); + if (StringUtils.isBlank(taskNumber)) { + return; + } + List taskRows = taskShelfMaterialDetailService.list( + new LambdaQueryWrapper() + .eq(TaskShelfMaterialDetail::getTaskNumber, taskNumber) + .eq(TaskShelfMaterialDetail::getDelFlag, 1)); + if (CollectionUtils.isEmpty(taskRows)) { + return; + } + Map taskByShelfLineUid = new HashMap<>(); + for (TaskShelfMaterialDetail tr : taskRows) { + Long uid = extractShelfLineUniqueIdFromTaskRemark(tr.getRemark()); + if (uid != null && !taskByShelfLineUid.containsKey(uid)) { + taskByShelfLineUid.put(uid, tr); + } + } + ShelfMaterialDetailDO smq = new ShelfMaterialDetailDO(); + smq.setShelfOrderNumber(stockShelfOrderDO.getShelfOrderNumber()); + List shelfLines = shelfMaterialDetailService.queryList(smq); + if (CollectionUtils.isEmpty(shelfLines)) { + return; + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + Date now = new Date(); + String userRealName = resolveUserRealNameForShelf(loginUser); + for (ShelfMaterialDetailPO line : shelfLines) { + if (line == null) { + continue; + } + TaskShelfMaterialDetail tr = null; + if (line.getUniqueId() != null) { + tr = taskByShelfLineUid.get(line.getUniqueId()); + if (tr == null) { + long uid = line.getUniqueId(); + for (TaskShelfMaterialDetail row : taskRows) { + if (row != null && remarkContainsShelfRuidToken(row.getRemark(), uid)) { + tr = row; + break; + } + } + } + } + if (tr == null) { + tr = findTaskShelfMaterialDetailByFallback(taskRows, line); + } + if (tr == null || tr.getMaterialDetailId() == null) { + continue; + } + BigDecimal syncQty = line.getAlreadyShelvesQuantity() != null + ? line.getAlreadyShelvesQuantity() + : line.getShelvesQuantity(); + TaskShelfMaterialDetail patch = new TaskShelfMaterialDetail(); + patch.setMaterialDetailId(tr.getMaterialDetailId()); + patch.setShelvesQuantity(syncQty); + patch.setShelvesStatus(line.getShelvesStatus()); + if (loginUser != null) { + patch.setUpdateBy(loginUser.getUserid()); + } + patch.setUpdateByName(userRealName); + patch.setUpdateTime(now); + taskShelfMaterialDetailService.updateById(patch); + } + } + + private String resolveShelfTypeTaskNumberByShelfOrderNumber(String shelfOrderNumber) { + if (StringUtils.isBlank(shelfOrderNumber)) { + return null; + } + List rows = stockInTaskOrderService.list( + new LambdaQueryWrapper() + .eq(StockInTaskOrder::getShelfOrderNumber, shelfOrderNumber) + .eq(StockInTaskOrder::getType, 2) + .eq(StockInTaskOrder::getDelFlag, 1) + .orderByDesc(StockInTaskOrder::getInTaskOrderId) + .last("LIMIT 1")); + if (CollectionUtils.isEmpty(rows)) { + return null; + } + return rows.get(0).getTaskNumber(); + } + + private static Long extractShelfLineUniqueIdFromTaskRemark(String remark) { + if (StringUtils.isBlank(remark)) { + return null; + } + int i = remark.indexOf(StockInTaskOrderImpl.TASK_RECEIPT_REMARK_RUID_PREFIX); + if (i < 0) { + return null; + } + int j = i + StockInTaskOrderImpl.TASK_RECEIPT_REMARK_RUID_PREFIX.length(); + int k = j; + while (k < remark.length() && Character.isDigit(remark.charAt(k))) { + k++; + } + if (k == j) { + return null; + } + try { + return Long.parseLong(remark.substring(j, k)); + } catch (NumberFormatException e) { + return null; + } + } + + private static boolean remarkContainsShelfRuidToken(String remark, long uid) { + if (remark == null) { + return false; + } + return Pattern.compile(StockInTaskOrderImpl.TASK_RECEIPT_REMARK_RUID_PREFIX + uid + "(?!\\d)").matcher(remark).find(); + } + + private static TaskShelfMaterialDetail findTaskShelfMaterialDetailByFallback( + List all, ShelfMaterialDetailPO line) { + if (CollectionUtils.isEmpty(all) || line == null) { + return null; + } + for (TaskShelfMaterialDetail tr : all) { + if (tr == null) { + continue; + } + if (!Objects.equals(tr.getInUniqueId(), line.getInUniqueId())) { + continue; + } + if (!Objects.equals(tr.getReceiptUniqueId(), line.getReceiptUniqueId())) { + continue; + } + if (!Objects.equals(tr.getLevel(), line.getLevel())) { + continue; + } + if (line.getMaterialBaseInfoId() != null && tr.getMaterialBaseInfoId() != null + && !Objects.equals(tr.getMaterialBaseInfoId(), line.getMaterialBaseInfoId())) { + continue; + } + return tr; + } + return null; + } /** * @description 设置上架单上架需要更新的数据数据 @@ -700,6 +855,9 @@ public class StockShelfOrderDomainService { } String userRealNameComplete = resolveUserRealNameForShelf(loginUser); updateShelfMaterialDetailShelvesStatusWhenOrderCompleted(stockShelfOrderPO, loginUser, userRealNameComplete); + StockShelfOrderDO taskDetailSync = new StockShelfOrderDO(); + taskDetailSync.setShelfOrderNumber(stockShelfOrderPO.getShelfOrderNumber()); + syncTaskShelfMaterialDetailsWithShelfLines(taskDetailSync); markShelfTypeStockInTaskOrderOnComplete(stockShelfOrderPO.getShelfOrderNumber(), loginUser, userRealNameComplete); //推送业务数据到BMS系统 // pushSyncBmsDomainService.pushInShelfOrder(stockShelfOrderPO.getInOrderNumber()); @@ -708,6 +866,27 @@ public class StockShelfOrderDomainService { return true; } + /** + * 上架单整单完成时回写「上架」类入库作业单(type=2)的作业人、作业完成时间(与 + * {@link com.mhd.wms.domain.stockReceiptOrder.service.StockReceiptOrderDomainService#markReceiptTypeStockInTaskOrderOnComplete} 对收货类作业单一致)。 + */ + private void markShelfTypeStockInTaskOrderOnComplete(String shelfOrderNumber, LoginUser loginUser, String userRealName) { + if (StringUtils.isBlank(shelfOrderNumber) || loginUser == null) { + return; + } + Date now = new Date(); + stockInTaskOrderService.update(null, new UpdateWrapper().lambda() + .set(StockInTaskOrder::getOperatorsBy, loginUser.getUserid()) + .set(StockInTaskOrder::getOperatorsName, userRealName) + .set(StockInTaskOrder::getOperatorsEndTime, now) + .set(StockInTaskOrder::getUpdateBy, loginUser.getUserid()) + .set(StockInTaskOrder::getUpdateByName, userRealName) + .set(StockInTaskOrder::getUpdateTime, now) + .eq(StockInTaskOrder::getShelfOrderNumber, shelfOrderNumber) + .eq(StockInTaskOrder::getType, 2) + .eq(StockInTaskOrder::getDelFlag, 1)); + } + /** * 分批/单次上架提交后:按主行+子行汇总「累计已上架」与主行计划量比较,刷新各明细 shelves_status(待上 1 / 上中 2 / 满 3 / 超 5) */ @@ -920,26 +1099,6 @@ public class StockShelfOrderDomainService { return loginUser.getUsername() != null ? loginUser.getUsername() : ""; } - /** - * 上架实际完成时回写「上架」类入库作业单(type=2)的作业人、作业完成时间(下发/生成时不下发填写)。 - */ - private void markShelfTypeStockInTaskOrderOnComplete(String shelfOrderNumber, LoginUser loginUser, String userRealName) { - if (StringUtils.isBlank(shelfOrderNumber) || loginUser == null) { - return; - } - Date now = new Date(); - stockInTaskOrderService.update(null, new UpdateWrapper().lambda() - .set(StockInTaskOrder::getOperatorsBy, loginUser.getUserid()) - .set(StockInTaskOrder::getOperatorsName, userRealName) - .set(StockInTaskOrder::getOperatorsEndTime, now) - .set(StockInTaskOrder::getUpdateBy, loginUser.getUserid()) - .set(StockInTaskOrder::getUpdateByName, userRealName) - .set(StockInTaskOrder::getUpdateTime, now) - .eq(StockInTaskOrder::getShelfOrderNumber, shelfOrderNumber) - .eq(StockInTaskOrder::getType, 2) - .eq(StockInTaskOrder::getDelFlag, 1)); - } - private synchronized void stockIn(List shelfMaterialDetailDOList, StockShelfOrderDO stockReceiptOrderDO) { for (ShelfMaterialDetail shelfMaterialDetail : shelfMaterialDetailDOList) { Long materialBaseInfoId = shelfMaterialDetail.getMaterialBaseInfoId(); @@ -1460,102 +1619,73 @@ public class StockShelfOrderDomainService { stockInTaskOrderDO.setSerialNumber(OrderSequence.getOrderCode("SHZYLS")); stockInTaskOrderDO.setTaskNumber(OrderSequence.getOrderCode("SHZY")); stockInTaskOrderDO.setType(2);//上架 - stockInTaskOrderDO.setOperatorsBy(null); - stockInTaskOrderDO.setOperatorsName(null); - stockInTaskOrderDO.setOperatorsEndTime(null); - // 作业单「作业数量」对应 stock_in_task_order.actual_quantity;上架单汇总在 receipt_quantity,字段名不一致不会从 copyProperties 带入,需按实际收货量赋值 - BigDecimal workQty = stockInTaskOrderDO.getActualQuantity(); - if (workQty == null || workQty.compareTo(BigDecimal.ZERO) == 0) { - workQty = stockShelfOrderDO.getReceiptQuantity(); - } - if ((workQty == null || workQty.compareTo(BigDecimal.ZERO) == 0) - && !CollectionUtils.isEmpty(stockShelfOrderDO.getMaterialDetailList())) { - workQty = sumShelfMaterialDetailQuantities(stockShelfOrderDO.getMaterialDetailList()); - } - stockInTaskOrderDO.setActualQuantity(workQty != null ? workQty : BigDecimal.ZERO); List taskReceiptMaterialDetailDOList = stockShelfOrderDO.getMaterialDetailList().stream() .map(shelfMaterialDetailDO -> JSONUtil.toBean(JSONUtil.toJsonStr(shelfMaterialDetailDO), TaskShelfMaterialDetailDO.class)) .collect(Collectors.toList()); - for (TaskShelfMaterialDetailDO d : taskReceiptMaterialDetailDOList) { - if (d.getChildren() == null) { - d.setChildren(new ArrayList<>()); - } - } stockInTaskOrderDO.setTaskShelfMaterialDetailList(taskReceiptMaterialDetailDOList); return stockInTaskOrderService.genStockShelfTaskOrder(Collections.singletonList(stockInTaskOrderDO)); } - /** 汇总上架明细计划数量(与收货实际量一致),含子行树 */ - private static BigDecimal sumShelfMaterialDetailQuantities(List lines) { - if (CollectionUtils.isEmpty(lines)) { - return BigDecimal.ZERO; - } - BigDecimal sum = BigDecimal.ZERO; - for (ShelfMaterialDetailDO line : lines) { - if (line == null) { - continue; - } - if (line.getQuantity() != null) { - sum = sum.add(line.getQuantity()); - } - if (!CollectionUtils.isEmpty(line.getChildren())) { - sum = sum.add(sumShelfMaterialDetailQuantities(line.getChildren())); - } - } - return sum; - } - - private long countShelfTypeInTaskOrder(String shelfOrderNumber) { + /** + * 该上架单下是否已存在 type=2(上架)入库作业单。 + */ + private int countShelfTypeInTaskOrder(String shelfOrderNumber) { if (StringUtils.isBlank(shelfOrderNumber)) { - return 0L; + return 0; } - return stockInTaskOrderService.count(new LambdaQueryWrapper() + return (int) stockInTaskOrderService.count(new QueryWrapper().lambda() .eq(StockInTaskOrder::getShelfOrderNumber, shelfOrderNumber) - .eq(StockInTaskOrder::getType, 2) - .eq(StockInTaskOrder::getDelFlag, 1)); + .eq(StockInTaskOrder::getType, 2)); } /** - * PDA 收货完成已生成上架单后,落库「上架」入库作业单(type=2)。与 {@link #genStockShelfTaskOrderByUpShelf} 同结构,避免在上架操作时再生成一条(上架环节仅在上尚未存在时补生成,供 PC 使用)。 + * PDA 收货完成:若该收货单对应上架单尚未生成 type=2 上架入库作业单则补生成(与 {@link #upShelf} 中补生成策略一致)。 */ @Transactional(rollbackFor = Exception.class) public void tryGenStockShelfInTaskOrderAfterPdaReceiptComplete(String receiptOrderNumber) { if (StringUtils.isBlank(receiptOrderNumber)) { return; } - List rows = stockShelfOrderService.list(new LambdaQueryWrapper() - .eq(StockShelfOrder::getReceiptOrderNumber, receiptOrderNumber) - .eq(StockShelfOrder::getDelFlag, 1)); - if (CollectionUtils.isEmpty(rows)) { + StockShelfOrderDO query = new StockShelfOrderDO(); + query.setReceiptOrderNumber(receiptOrderNumber); + List shelfList = stockShelfOrderService.queryList(query); + if (CollectionUtils.isEmpty(shelfList)) { + log.warn("PDA 收货完成补生成上架作业单:未找到收货单号对应上架单,receiptOrderNumber={}", receiptOrderNumber); return; } - rows.sort(Comparator.comparing(StockShelfOrder::getShelfOrderId, Comparator.nullsLast(Comparator.naturalOrder())).reversed()); - StockShelfOrder head = rows.get(0); - if (countShelfTypeInTaskOrder(head.getShelfOrderNumber()) > 0) { - return; + for (StockShelfOrderPO shelfPO : shelfList) { + if (shelfPO == null || StringUtils.isBlank(shelfPO.getShelfOrderNumber())) { + continue; + } + if (countShelfTypeInTaskOrder(shelfPO.getShelfOrderNumber()) > 0) { + continue; + } + StockShelfOrderDO shelfDO = buildStockShelfOrderDOForGenShelfTask(shelfPO); + if (shelfDO == null || CollectionUtils.isEmpty(shelfDO.getMaterialDetailList())) { + log.warn("PDA 收货完成补生成上架作业单:上架单无明细,shelfOrderNumber={}", shelfPO.getShelfOrderNumber()); + continue; + } + genStockShelfTaskOrderByUpShelf(shelfDO); } - StockShelfOrderPO full = getInfo(head.getShelfOrderId()); - if (full == null || CollectionUtils.isEmpty(full.getMaterialDetailList())) { - return; + } + + private StockShelfOrderDO buildStockShelfOrderDOForGenShelfTask(StockShelfOrderPO shelfPO) { + StockShelfOrderDO shelfDO = new StockShelfOrderDO(); + BeanUtils.copyProperties(shelfPO, shelfDO); + ShelfMaterialDetailDO detailQuery = new ShelfMaterialDetailDO(); + detailQuery.setShelfOrderNumber(shelfPO.getShelfOrderNumber()); + List detailPOs = shelfMaterialDetailService.queryList(detailQuery); + if (CollectionUtils.isEmpty(detailPOs)) { + return null; } - StockShelfOrderDO d = new StockShelfOrderDO(); - BeanUtils.copyProperties(full, d); - List dlist = full.getMaterialDetailList().stream() - .map(po -> { - ShelfMaterialDetailDO m = JSONUtil.toBean(JSONUtil.toJsonStr(po), ShelfMaterialDetailDO.class); - if (m.getChildren() == null && !CollectionUtils.isEmpty(po.getChildren())) { - m.setChildren(po.getChildren().stream() - .map(c -> JSONUtil.toBean(JSONUtil.toJsonStr(c), ShelfMaterialDetailDO.class)) - .collect(Collectors.toList())); - } - if (m.getChildren() == null) { - m.setChildren(new ArrayList<>()); - } - return m; - }) - .collect(Collectors.toList()); - d.setMaterialDetailList(dlist); - genStockShelfTaskOrderByUpShelf(d); + List detailDOs = new ArrayList<>(); + for (ShelfMaterialDetailPO po : detailPOs) { + ShelfMaterialDetailDO d = new ShelfMaterialDetailDO(); + BeanUtils.copyProperties(po, d); + detailDOs.add(d); + } + shelfDO.setMaterialDetailList(detailDOs); + return shelfDO; } /** diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/taskPickingMaterialDetail/repository/po/TaskPickingMaterialDetailPO.java b/mhd_wms/src/main/java/com/mhd/wms/domain/taskPickingMaterialDetail/repository/po/TaskPickingMaterialDetailPO.java index a8cc78f98..f1a1cc585 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/taskPickingMaterialDetail/repository/po/TaskPickingMaterialDetailPO.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/taskPickingMaterialDetail/repository/po/TaskPickingMaterialDetailPO.java @@ -236,11 +236,11 @@ public class TaskPickingMaterialDetailPO extends BaseVOEntity { @TableField(exist = false) private BigDecimal workQuantity; - @ApiModelProperty("是否抄码: 1-是 2-否(与物料主数据一致,查询时回填)") + @ApiModelProperty("是否抄码: 1-是 2-否") @TableField(exist = false) private Integer copyCode; - @ApiModelProperty("待拣抄码克重明细(来自 copy_code_reference;顺序与库存抄码 id 列表一致,已按 pickingQuantity 去掉已拣件,仅余待扫)") + @ApiModelProperty("待拣抄码克重明细") @TableField(exist = false) private List weightList; diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/taskShelfMaterialDetail/repository/persistence/TaskShelfMaterialDetailImpl.java b/mhd_wms/src/main/java/com/mhd/wms/domain/taskShelfMaterialDetail/repository/persistence/TaskShelfMaterialDetailImpl.java index 49a35691f..e12d1fe31 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/taskShelfMaterialDetail/repository/persistence/TaskShelfMaterialDetailImpl.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/taskShelfMaterialDetail/repository/persistence/TaskShelfMaterialDetailImpl.java @@ -33,19 +33,39 @@ public class TaskShelfMaterialDetailImpl extends ServiceImpl queryList(TaskShelfMaterialDetailDO taskShelfMaterialDetailDO) { List taskShelfMaterialDetailPOList = taskShelfMaterialDetailMapper.queryList(taskShelfMaterialDetailDO); - // 获取查询的层级 - List askShelfMaterialDetailPOParentList = taskShelfMaterialDetailPOList - .stream().filter(e -> 1 == e.getLevel()).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(taskShelfMaterialDetailPOList)) { + return taskShelfMaterialDetailPOList; + } + // 主行:level=1(与 Integer(1) 比较,避免 level 为 null 时拆箱 NPE) + List askShelfMaterialDetailPOParentList = taskShelfMaterialDetailPOList.stream() + .filter(e -> e != null && Integer.valueOf(1).equals(e.getLevel())) + .collect(Collectors.toList()); + if (CollectionUtils.isEmpty(askShelfMaterialDetailPOParentList)) { + // 无主行时:以无父或 parent=0 为根,仍无则整单平铺为根,避免详情始终为空 + askShelfMaterialDetailPOParentList = taskShelfMaterialDetailPOList.stream() + .filter(e -> e != null && (e.getParentUniqueId() == null || Long.valueOf(0L).equals(e.getParentUniqueId()))) + .collect(Collectors.toList()); + } + if (CollectionUtils.isEmpty(askShelfMaterialDetailPOParentList)) { + askShelfMaterialDetailPOParentList = new ArrayList<>(taskShelfMaterialDetailPOList); + } // 递归查询子集 - askShelfMaterialDetailPOParentList.forEach(materialDetailPO -> materialDetailPO.setChildren(getChildren(materialDetailPO.getUniqueId(), taskShelfMaterialDetailPOList, 2))); + askShelfMaterialDetailPOParentList.forEach(materialDetailPO -> materialDetailPO.setChildren( + getChildren(materialDetailPO.getUniqueId(), taskShelfMaterialDetailPOList, 2))); return askShelfMaterialDetailPOParentList; } - private List getChildren(Long parentUniqueId, List taskShelfMaterialDetailPOList, Integer maxLevel){ - List childrenCityList = taskShelfMaterialDetailPOList.stream().filter(materialDetailPO -> parentUniqueId.equals(materialDetailPO.getParentUniqueId())).collect(Collectors.toList()); - if (!CollectionUtils.isEmpty(childrenCityList)){ + private List getChildren(Long parentUniqueId, List taskShelfMaterialDetailPOList, Integer maxLevel) { + if (parentUniqueId == null) { + return new ArrayList<>(); + } + List childrenCityList = taskShelfMaterialDetailPOList.stream() + .filter(materialDetailPO -> parentUniqueId.equals(materialDetailPO.getParentUniqueId())) + .collect(Collectors.toList()); + if (!CollectionUtils.isEmpty(childrenCityList)) { childrenCityList.forEach(childrenCity -> { - if (childrenCity.getLevel() < maxLevel){ + Integer level = childrenCity.getLevel(); + if (level == null || level < maxLevel) { childrenCity.setChildren(getChildren(childrenCity.getUniqueId(), taskShelfMaterialDetailPOList, maxLevel)); } }); diff --git a/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/stockInTaskOrder/StockInTaskOrderDTO.java b/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/stockInTaskOrder/StockInTaskOrderDTO.java index 3375e6bc0..0a02ad787 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/stockInTaskOrder/StockInTaskOrderDTO.java +++ b/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/stockInTaskOrder/StockInTaskOrderDTO.java @@ -93,7 +93,7 @@ public class StockInTaskOrderDTO extends BaseVOEntity { private String operatorsName; @ApiModelProperty("作业完成时间") - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") @Excel(name = "作业完成时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") private Date operatorsEndTime; diff --git a/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/stockOutTaskOrder/StockOutTaskOrderDTO.java b/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/stockOutTaskOrder/StockOutTaskOrderDTO.java index b3b8d9d6c..5e8011983 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/stockOutTaskOrder/StockOutTaskOrderDTO.java +++ b/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/stockOutTaskOrder/StockOutTaskOrderDTO.java @@ -136,7 +136,7 @@ public class StockOutTaskOrderDTO extends BaseVOEntity { private String operatorsName; @ApiModelProperty("作业完成时间") - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") @Excel(name = "作业完成时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") private Date operatorsEndTime; diff --git a/mhd_wms/src/main/resources/mapper/stockInTaskOrder/StockInTaskOrderMapper.xml b/mhd_wms/src/main/resources/mapper/stockInTaskOrder/StockInTaskOrderMapper.xml index 762379dc9..33b75a843 100644 --- a/mhd_wms/src/main/resources/mapper/stockInTaskOrder/StockInTaskOrderMapper.xml +++ b/mhd_wms/src/main/resources/mapper/stockInTaskOrder/StockInTaskOrderMapper.xml @@ -93,7 +93,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" --- 创建时间为空的排最后 - order by a.create_time is null, a.create_time desc +-- 先按照作业时间来排序,创建时间为空的排最后 + order by a.operators_end_time desc, a.create_time is null, a.create_time desc \ No newline at end of file