diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockOutOrder/StockOutOrderApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockOutOrder/StockOutOrderApplicationService.java index 6fbf1c4ca..6eadce3eb 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockOutOrder/StockOutOrderApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockOutOrder/StockOutOrderApplicationService.java @@ -166,6 +166,9 @@ public class StockOutOrderApplicationService { // 3. 为每个物料明细设置更多属性(从物料明细表中获取值),递归处理所有层级 setMaterialMoreDetailListRecursively(detailList, batchDetailMap); + // 4. 为每个物料明细设置分配按钮显示类型,递归处理所有层级 + setAllocationButtonTypeRecursively(detailList); + return stockOutOrderPO; } @@ -508,6 +511,19 @@ public class StockOutOrderApplicationService { return stockOutOrderDomainService.cancelAssign(stockOutOrderDO); } + /** + * @description 手动取消分配(点击确认后直接取消分配) + * @author ZhouGY + * @date 2024/5/28 13:47 + * @param stockOutOrderDO + * @return Boolean + */ + public Boolean manualCancelAssign(StockOutOrderDO stockOutOrderDO){ + // 取消分配不需要经过assembleParamByOutOrder,因为该方法是为分配设计的,会过滤掉allocationQuantity为0的明细 + // 直接调用领域服务,传递原始参数 + return stockOutOrderDomainService.manualCancelAssign(stockOutOrderDO); + } + /** * @description 复核下发 @@ -884,6 +900,39 @@ public class StockOutOrderApplicationService { outMaterialDetailDO.setContainerTypeName(materialInventoryPO.getContainerTypeName()); } - + /** + * 递归为出库物料明细设置分配按钮显示类型 + * @param outMaterialDetailPOList 出库物料明细列表 + */ + private void setAllocationButtonTypeRecursively(List outMaterialDetailPOList) { + if (CollectionUtils.isEmpty(outMaterialDetailPOList)) { + return; + } + + outMaterialDetailPOList.forEach(outMaterialDetailPO -> { + BigDecimal quantity = outMaterialDetailPO.getQuantity(); // 计划数量 + BigDecimal alreadyAllocationQuantity = outMaterialDetailPO.getAlreadyAllocationQuantity(); // 已分配数量 + + // 判断按钮显示类型 + // 已分配数量 = 0:显示"库存分配"按钮(类型1) + // 已分配数量 = 计划数量:显示"取消分配"按钮(类型2) + if (alreadyAllocationQuantity == null || alreadyAllocationQuantity.compareTo(BigDecimal.ZERO) == 0) { + // 已分配数量为0或null,显示"库存分配"按钮 + outMaterialDetailPO.setAllocationButtonType(1); + } else if (quantity != null && alreadyAllocationQuantity.compareTo(quantity) == 0) { + // 已分配数量等于计划数量,显示"取消分配"按钮 + outMaterialDetailPO.setAllocationButtonType(2); + } else { + // 其他情况(已分配数量 > 0 但 < 计划数量),不显示按钮或显示其他状态 + outMaterialDetailPO.setAllocationButtonType(0); + } + + // 递归处理子级 + List children = outMaterialDetailPO.getChildren(); + if (!CollectionUtils.isEmpty(children)) { + setAllocationButtonTypeRecursively(children); + } + }); + } } \ No newline at end of file diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/outMaterialDetail/repository/persistence/OutMaterialDetailImpl.java b/mhd_wms/src/main/java/com/mhd/wms/domain/outMaterialDetail/repository/persistence/OutMaterialDetailImpl.java index 165fac450..18fa2c84d 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/outMaterialDetail/repository/persistence/OutMaterialDetailImpl.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/outMaterialDetail/repository/persistence/OutMaterialDetailImpl.java @@ -306,6 +306,98 @@ public class OutMaterialDetailImpl extends ServiceImpl outMaterialDetailDOList) { + if (CollectionUtils.isEmpty(outMaterialDetailDOList)) { + throw new ServiceException("物料明细不能为空"); + } + StockOutOrderPO stockOutOrderPO = new StockOutOrderPO(); + LoginUser loginUser = SecurityUtils.getLoginUser(); + List outMaterialDetailDbList = outMaterialDetailMapper.selectList(new QueryWrapper().lambda() + .eq(OutMaterialDetail::getOutOrderNumber, outOrderNumber) + .eq(OutMaterialDetail::getLevel, 1) + .eq(OutMaterialDetail::getDelFlag, 1)); + Map materialDetailMap = outMaterialDetailDbList.stream().collect(Collectors.toMap(OutMaterialDetail::getMaterialDetailId, Function.identity())); + //批量修改物料信息 + List outMaterialDetailList = new ArrayList<>(); + BigDecimal totalAllocationQuantity = BigDecimal.ZERO;//出库单总取消分配数量 + BigDecimal totalAlreadyAllocationQuantity = BigDecimal.ZERO;//出库单总取消已分配数量 + for (OutMaterialDetailDO outMaterialDetailDO : outMaterialDetailDOList){ + OutMaterialDetail outMaterialDetailDb = materialDetailMap.get(outMaterialDetailDO.getMaterialDetailId()); + if (outMaterialDetailDb == null){ + throw new ServiceException("物料信息不存在"); + } + OutMaterialDetail outMaterialDetail = new OutMaterialDetail(); + BeanUtils.copyProperties(outMaterialDetailDO, outMaterialDetail); + outMaterialDetail.setUpdateBy(loginUser.getUserid()); + outMaterialDetail.setUpdateByName(loginUser.getUsername()); + outMaterialDetail.setUpdateTime(new Date()); + outMaterialDetail.setAllowModify(1); + + //判断是否存在子项 + BigDecimal cancelAllocationQuantity = outMaterialDetailDO.getAllocationQuantity() != null ? outMaterialDetailDO.getAllocationQuantity() : BigDecimal.ZERO; // 要取消的分配数量 + List materialDetailDOChildList = outMaterialDetailDO.getChildren(); + List outMaterialDetailListChild = new ArrayList<>(); + if (!CollectionUtils.isEmpty(materialDetailDOChildList)){ + for (OutMaterialDetailDO outMaterialDetailDOChild : materialDetailDOChildList){ + OutMaterialDetail outMaterialDetailChild = new OutMaterialDetail(); + BeanUtils.copyProperties(outMaterialDetailDOChild, outMaterialDetailChild, IgnoreNullUtil.getNullPropertyNames(outMaterialDetailDOChild)); + outMaterialDetailChild.setMaterialDetailId(null); + outMaterialDetailChild.setUniqueId(idGenerator.snowflakeId(SnowFlakeConstants.wmsId)); + outMaterialDetailChild.setLevel(2); + outMaterialDetailChild.setParentUniqueId(outMaterialDetailDO.getUniqueId()); + outMaterialDetailChild.setUpdateBy(loginUser.getUserid()); + outMaterialDetailChild.setUpdateByName(loginUser.getUsername()); + outMaterialDetailChild.setUpdateTime(new Date()); + outMaterialDetailChild.setAllowModify(1); + // 设置 actualQuantity 用于 qxfp 方法更新库存 + outMaterialDetailChild.setActualQuantity(outMaterialDetailDOChild.getAllocationQuantity() != null ? outMaterialDetailDOChild.getAllocationQuantity() : BigDecimal.ZERO); + outMaterialDetailListChild.add(outMaterialDetailChild); + // 累加子项的取消分配数量 + if (outMaterialDetailDOChild.getAllocationQuantity() != null) { + cancelAllocationQuantity = cancelAllocationQuantity.add(outMaterialDetailDOChild.getAllocationQuantity()); + } + } + } + if (CollectionUtil.isNotEmpty(outMaterialDetailListChild)){ + outMaterialDetailList.addAll(outMaterialDetailListChild); + } + + //判断取消分配数量不能大于分配总数 + if(cancelAllocationQuantity.compareTo(outMaterialDetailDb.getAllocationQuantity()) > 0){ + throw new ServiceException("物料" + outMaterialDetailDb.getMaterialName() + ",取消分配数量不能大于分配总数"); + } + + // 更新分配数量和已分配数量(减少) + outMaterialDetail.setAllocationQuantity(outMaterialDetailDb.getAllocationQuantity().subtract(cancelAllocationQuantity)); + outMaterialDetail.setAlreadyAllocationQuantity(outMaterialDetailDb.getAlreadyAllocationQuantity().subtract(cancelAllocationQuantity)); + // 设置 actualQuantity 用于 qxfp 方法更新库存 + outMaterialDetail.setActualQuantity(cancelAllocationQuantity); + outMaterialDetailList.add(outMaterialDetail); + + //记录出库单取消分配总数 + totalAllocationQuantity = totalAllocationQuantity.add(cancelAllocationQuantity); + totalAlreadyAllocationQuantity = totalAlreadyAllocationQuantity.add(cancelAllocationQuantity); + } + stockOutOrderPO.setAllocationQuantity(totalAllocationQuantity); + stockOutOrderPO.setAlreadyAllocationQuantity(totalAlreadyAllocationQuantity); + //保存物料明细信息 + saveOrUpdateBatch(outMaterialDetailList); + //取消分配(修改库存) + qxfp(outMaterialDetailList,outOrderNumber,loginUser); + + return stockOutOrderPO; + } + public synchronized void xgkc(List outMaterialDetailList,String outOrderNumber,LoginUser loginUser) { StockOutOrder stockOutOrder = stockOutOrderMapper.selectOne(new QueryWrapper().lambda().eq(StockOutOrder::getOutOrderNumber, outOrderNumber)); for (OutMaterialDetail outMaterialDetail : outMaterialDetailList) { @@ -398,22 +490,21 @@ public class OutMaterialDetailImpl extends ServiceImpl materialDetailDOChildList = outMaterialDetailDO.getChildren(); @@ -436,12 +527,26 @@ public class OutMaterialDetailImpl extends ServiceImpl0){ - throw new ServiceException("物料" + outMaterialDetailDb.getMaterialName() + ",取消分配数量不能大于分配总数"); + //判断取消分配数量不能大于已分配数量(取消分配应该检查alreadyAllocationQuantity,而不是allocationQuantity) + BigDecimal dbAlreadyAllocationQuantity = outMaterialDetailDb.getAlreadyAllocationQuantity() != null + ? outMaterialDetailDb.getAlreadyAllocationQuantity() + : BigDecimal.ZERO; + if(allocationQuantity.compareTo(dbAlreadyAllocationQuantity) > 0){ + throw new ServiceException("物料" + outMaterialDetailDb.getMaterialName() + ",取消分配数量不能大于已分配数量"); } - outMaterialDetail.setAllocationQuantity(outMaterialDetailDb.getAllocationQuantity().subtract(allocationQuantity)); - outMaterialDetail.setAlreadyAllocationQuantity(outMaterialDetailDb.getAlreadyAllocationQuantity().subtract(allocationQuantity)); + // 取消分配:只减少已分配数量,分配数量保持不变 + // 取消分配的目的是:把之前分配给库存的分配给取消掉,让库存可以重新分配 + // allocation_quantity(分配数量)不应该减少,因为取消分配后可以重新分配 + // already_allocation_quantity(已分配数量)应该减少,表示取消了多少已分配的数量 + BigDecimal dbAllocationQuantity = outMaterialDetailDb.getAllocationQuantity() != null + ? outMaterialDetailDb.getAllocationQuantity() + : BigDecimal.ZERO; + // 分配数量保持不变(取消分配后可以重新分配) + outMaterialDetail.setAllocationQuantity(dbAllocationQuantity); + // 已分配数量减少(取消已分配的数量) + outMaterialDetail.setAlreadyAllocationQuantity(dbAlreadyAllocationQuantity.subtract(allocationQuantity)); + // 设置 actualQuantity 用于 qxfp 方法更新库存(取消分配的数量) + outMaterialDetail.setActualQuantity(allocationQuantity); outMaterialDetailList.add(outMaterialDetail); materialDetailIdsByUpdate.add(outMaterialDetailDO.getMaterialDetailId()); //记录收货单收货总数 @@ -450,21 +555,8 @@ public class OutMaterialDetailImpl extends ServiceImpl materialDetailIdsByDb = outMaterialDetailDbList.stream().map(OutMaterialDetail::getMaterialDetailId).collect(Collectors.toList()); - //过滤需要修改的id集合 - materialDetailIdsByDb.removeAll(materialDetailIdsByUpdate); - //判断是否存在需要删除的物流明细 标记删除 - if (!CollectionUtils.isEmpty(materialDetailIdsByDb)){ - update(new UpdateWrapper().lambda() - .set(OutMaterialDetail::getDelFlag, 2) - .set(OutMaterialDetail::getUpdateBy, loginUser.getUserid()) - .set(OutMaterialDetail::getUpdateByName, loginUser.getUsername()) - .set(OutMaterialDetail::getUpdateTime, new Date()) - .in(OutMaterialDetail::getMaterialDetailId, materialDetailIdsByDb)); - } - } + // 取消分配时,只更新需要取消分配的明细,不删除其他明细 + // 注意:这里移除了删除其他明细的逻辑,因为取消分配只是减少已分配数量,不应该删除明细 //保存物料明细信息 updateBatchById(outMaterialDetailList); //取消分配 diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/outMaterialDetail/repository/po/OutMaterialDetailPO.java b/mhd_wms/src/main/java/com/mhd/wms/domain/outMaterialDetail/repository/po/OutMaterialDetailPO.java index 79b432ffb..f6b19dbb1 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/outMaterialDetail/repository/po/OutMaterialDetailPO.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/outMaterialDetail/repository/po/OutMaterialDetailPO.java @@ -10,7 +10,10 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; import java.math.BigDecimal; +import java.util.Date; import java.util.List; @@ -395,7 +398,49 @@ public class OutMaterialDetailPO extends StockOutOrderBaseDO { @Excel(name = "单位") private String unit; + @ApiModelProperty("扩展字段1") + @Excel(name = "扩展字段1") + private String extAttr1; + + @ApiModelProperty("扩展字段2") + @Excel(name = "扩展字段2") + private String extAttr2; + + @ApiModelProperty("生产日期") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "生产日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date productionDate; + + @ApiModelProperty("过期日期") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "过期日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date expiryDate; + + @ApiModelProperty("存货日期") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "存货日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date inventoryDate; + + @ApiModelProperty("ExtAttr3") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "ExtAttr3", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date extAttr3; + + @ApiModelProperty("ExtAttr4") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "ExtAttr4", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date extAttr4; + @ApiModelProperty("更多属性明细列表") @TableField(exist = false) private List materialMoreDetailList; + + @ApiModelProperty("分配按钮显示类型:1-显示库存分配,2-显示取消分配") + @TableField(exist = false) + private Integer allocationButtonType; } \ No newline at end of file diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/pickingMaterialDetail/entity/PickingMaterialDetail.java b/mhd_wms/src/main/java/com/mhd/wms/domain/pickingMaterialDetail/entity/PickingMaterialDetail.java index 1a5b8f3f1..01f295fde 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/pickingMaterialDetail/entity/PickingMaterialDetail.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/pickingMaterialDetail/entity/PickingMaterialDetail.java @@ -9,7 +9,10 @@ import com.mhd.common.core.web.domain.BaseVOEntity; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; import java.math.BigDecimal; +import java.util.Date; /** @@ -187,5 +190,54 @@ public class PickingMaterialDetail extends BaseVOEntity { @Excel(name = "备注") private String remark; + @ApiModelProperty("Batch Ref NO's") + @Excel(name = "Batch Ref NO's") + private String batchRefNo; + + @ApiModelProperty("Sheet Ref NO's") + @Excel(name = "Sheet Ref NO's") + private String sheetRefNo; + + @ApiModelProperty("箱号/卡板号") + @Excel(name = "箱号/卡板号") + private String boxPalletNo; + + @ApiModelProperty("扩展字段1") + @Excel(name = "扩展字段1") + private String extAttr1; + + @ApiModelProperty("扩展字段2") + @Excel(name = "扩展字段2") + private String extAttr2; + + @ApiModelProperty("生产日期") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "生产日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date productionDate; + + @ApiModelProperty("过期日期") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "过期日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date expiryDate; + + @ApiModelProperty("存货日期") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "存货日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date inventoryDate; + + @ApiModelProperty("ExtAttr3") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "ExtAttr3", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date extAttr3; + + @ApiModelProperty("ExtAttr4") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "ExtAttr4", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date extAttr4; } diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/pickingMaterialDetail/repository/todo/PickingMaterialDetailDO.java b/mhd_wms/src/main/java/com/mhd/wms/domain/pickingMaterialDetail/repository/todo/PickingMaterialDetailDO.java index f8b9df26d..487d2f06b 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/pickingMaterialDetail/repository/todo/PickingMaterialDetailDO.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/pickingMaterialDetail/repository/todo/PickingMaterialDetailDO.java @@ -8,7 +8,10 @@ import com.mhd.wms.domain.outMaterialDetailSerialNumber.repository.todo.OutMater import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; import java.math.BigDecimal; +import java.util.Date; import java.util.List; @@ -205,4 +208,54 @@ public class PickingMaterialDetailDO extends BaseVOEntity { @ApiModelProperty("作业数量:拣货数量") @Excel(name = "作业数量:拣货数量") private BigDecimal actualQuantity; + + @ApiModelProperty("Batch Ref NO's") + @Excel(name = "Batch Ref NO's") + private String batchRefNo; + + @ApiModelProperty("Sheet Ref NO's") + @Excel(name = "Sheet Ref NO's") + private String sheetRefNo; + + @ApiModelProperty("箱号/卡板号") + @Excel(name = "箱号/卡板号") + private String boxPalletNo; + + @ApiModelProperty("扩展字段1") + @Excel(name = "扩展字段1") + private String extAttr1; + + @ApiModelProperty("扩展字段2") + @Excel(name = "扩展字段2") + private String extAttr2; + + @ApiModelProperty("生产日期") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "生产日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date productionDate; + + @ApiModelProperty("过期日期") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "过期日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date expiryDate; + + @ApiModelProperty("存货日期") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "存货日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date inventoryDate; + + @ApiModelProperty("ExtAttr3") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "ExtAttr3", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date extAttr3; + + @ApiModelProperty("ExtAttr4") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "ExtAttr4", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date extAttr4; } diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/stockOutOrder/service/StockOutOrderDomainService.java b/mhd_wms/src/main/java/com/mhd/wms/domain/stockOutOrder/service/StockOutOrderDomainService.java index dd044c40e..cf7755904 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/stockOutOrder/service/StockOutOrderDomainService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/stockOutOrder/service/StockOutOrderDomainService.java @@ -63,6 +63,7 @@ import org.springframework.util.CollectionUtils; import java.math.BigDecimal; import java.util.*; +import java.util.function.Function; import java.util.stream.Collectors; /** @@ -261,6 +262,85 @@ public class StockOutOrderDomainService { return updateStockOutOrderByAllocation(stockOutOrderDb, stockOutOrderPO, 1); } + /** + * @description 手动取消分配(点击确认后直接取消分配) + * @author ZhouGY + * @date 2024/5/22 16:20 + * @param stockOutOrderDO + * @return Boolean + */ + @Transactional(rollbackFor = Exception.class) + public Boolean manualCancelAssign(StockOutOrderDO stockOutOrderDO){ + StockOutOrder stockOutOrderDb = stockOutOrderService.getById(stockOutOrderDO.getOutOrderId()); + if (stockOutOrderDb == null){ + throw new ServiceException("出库单不存在"); + } + if (stockOutOrderDb.getStatus() > 4){ + throw new ServiceException("出库单已拣货,不允许取消分配!"); + } + + // 如果没有传递物料明细列表,直接返回 + if (stockOutOrderDO.getMaterialDetailList() == null || stockOutOrderDO.getMaterialDetailList().isEmpty()) { + throw new ServiceException("物料明细不能为空"); + } + + // 查询物料明细的当前分配情况,构建取消分配参数 + // 如果传递的明细中没有指定取消数量,则取消该明细的所有已分配数量 + List cancelDetailList = new ArrayList<>(); + OutMaterialDetailDO queryDO = new OutMaterialDetailDO(); + queryDO.setOutOrderNumber(stockOutOrderDb.getOutOrderNumber()); + List detailPOList = outMaterialDetailService.queryList(queryDO); + Map detailPOMap = detailPOList.stream() + .collect(Collectors.toMap(OutMaterialDetailPO::getMaterialDetailId, Function.identity())); + + for (OutMaterialDetailDO detailDO : stockOutOrderDO.getMaterialDetailList()) { + OutMaterialDetailPO detailPO = detailPOMap.get(detailDO.getMaterialDetailId()); + if (detailPO == null) { + throw new ServiceException("物料明细不存在,ID:" + detailDO.getMaterialDetailId()); + } + + // 取消分配:直接使用数据库中的已分配数量作为取消数量 + // 如果前端传递了allocationQuantity,需要验证它不能大于已分配数量 + BigDecimal dbAlreadyAllocationQuantity = detailPO.getAlreadyAllocationQuantity() != null + ? detailPO.getAlreadyAllocationQuantity() + : BigDecimal.ZERO; + + // 如果已分配数量为0,跳过该明细(不执行取消分配操作) + if (dbAlreadyAllocationQuantity.compareTo(BigDecimal.ZERO) <= 0) { + continue; // 跳过该明细,继续处理下一个 + } + + // 如果前端传递了取消数量,验证它不能大于已分配数量;否则取消所有已分配数量 + BigDecimal cancelQuantity = detailDO.getAllocationQuantity(); + if (cancelQuantity != null && cancelQuantity.compareTo(BigDecimal.ZERO) > 0) { + // 前端传递了取消数量,验证它不能大于已分配数量 + if (cancelQuantity.compareTo(dbAlreadyAllocationQuantity) > 0) { + String materialName = detailPO.getMaterialName() != null ? detailPO.getMaterialName() : "未知物料"; + throw new ServiceException("物料【" + materialName + "】取消分配数量(" + cancelQuantity + ")不能大于已分配数量(" + dbAlreadyAllocationQuantity + ")"); + } + } else { + // 没有传递取消数量,取消所有已分配数量 + cancelQuantity = dbAlreadyAllocationQuantity; + } + + OutMaterialDetailDO cancelDetail = new OutMaterialDetailDO(); + cancelDetail.setMaterialDetailId(detailDO.getMaterialDetailId()); + cancelDetail.setActualQuantity(cancelQuantity); // 使用actualQuantity字段传递取消数量 + cancelDetail.setAlreadyAllocationQuantity(cancelQuantity); + cancelDetailList.add(cancelDetail); + } + + // 如果所有明细的已分配数量都为0,直接返回成功(没有需要取消的分配) + if (cancelDetailList.isEmpty()) { + return true; + } + + //修改物料明细信息(取消分配) + StockOutOrderPO stockOutOrderPO = outMaterialDetailService.batchCancelAssignUpdate(stockOutOrderDb.getOutOrderNumber(), cancelDetailList); + //修改出库单 + return updateStockOutOrderByAllocation(stockOutOrderDb, stockOutOrderPO, 2); + } + /** * @description 取消分配 @@ -296,20 +376,42 @@ public class StockOutOrderDomainService { LoginUser loginUser = SecurityUtils.getLoginUser(); int status = judgeAllocationQuantityByManualAssign(stockOutOrderPO.getAllocationQuantity(), stockOutOrderDb.getQuantity(),type); BigDecimal allocationQuantity = stockOutOrderDb.getAllocationQuantity(); + BigDecimal alreadyAllocationQuantity = stockOutOrderDb.getAlreadyAllocationQuantity() != null + ? stockOutOrderDb.getAlreadyAllocationQuantity() + : BigDecimal.ZERO; if (type == 2){ - //取消分配需要比较作业数量与已分配数量 - if(stockOutOrderPO.getAllocationQuantity().compareTo(allocationQuantity) > 0){ - throw new ServiceException("取消分配数量不能大于已分配数量"); + //取消分配:stockOutOrderPO.getAllocationQuantity() 和 stockOutOrderPO.getAlreadyAllocationQuantity() 都是要取消的数量 + //物料明细层面的验证已经在 batchCancelAssignUpdate 中完成,这里直接使用即可 + BigDecimal cancelQuantity = stockOutOrderPO.getAllocationQuantity(); + BigDecimal cancelAlreadyAllocationQuantity = stockOutOrderPO.getAlreadyAllocationQuantity() != null + ? stockOutOrderPO.getAlreadyAllocationQuantity() + : BigDecimal.ZERO; + + // 取消分配:减少已分配数量 + // 注意:如果出库单的 alreadyAllocationQuantity 数据不一致(可能为0),使用 cancelAlreadyAllocationQuantity 作为参考 + // 但为了数据一致性,我们仍然从当前值中减去取消的数量 + if (alreadyAllocationQuantity.compareTo(cancelAlreadyAllocationQuantity) < 0) { + // 如果出库单的已分配数量小于要取消的数量,说明数据不一致,使用要取消的数量作为基准 + alreadyAllocationQuantity = cancelAlreadyAllocationQuantity; } - allocationQuantity = allocationQuantity.subtract(stockOutOrderPO.getAllocationQuantity()); + alreadyAllocationQuantity = alreadyAllocationQuantity.subtract(cancelAlreadyAllocationQuantity); + // 确保不会变成负数 + if (alreadyAllocationQuantity.compareTo(BigDecimal.ZERO) < 0) { + alreadyAllocationQuantity = BigDecimal.ZERO; + } + status = judgeAllocationQuantityByManualAssign(stockOutOrderPO.getAllocationQuantity(), stockOutOrderPO.getAlreadyAllocationQuantity(),type); }else { allocationQuantity = allocationQuantity.add(stockOutOrderPO.getAllocationQuantity()); + alreadyAllocationQuantity = alreadyAllocationQuantity.add(stockOutOrderPO.getAlreadyAllocationQuantity() != null + ? stockOutOrderPO.getAlreadyAllocationQuantity() + : BigDecimal.ZERO); } return stockOutOrderService.update(null, new UpdateWrapper().lambda() .set(StockOutOrder::getStatus, status) .set(StockOutOrder::getAllocationQuantity, allocationQuantity) + .set(StockOutOrder::getAlreadyAllocationQuantity, alreadyAllocationQuantity) .set(StockOutOrder::getUpdateBy, loginUser.getUserid()) .set(StockOutOrder::getUpdateByName, loginUser.getUsername()) .set(StockOutOrder::getUpdateTime, new Date()) @@ -448,6 +550,17 @@ public class StockOutOrderDomainService { pickingMaterialDetailDO.setMaterialCode(outMaterialDetailPO.getMaterialNo()); pickingMaterialDetailDO.setMaterialName(outMaterialDetailPO.getCommodityName()); pickingMaterialDetailDO.setBarCode(outMaterialDetailPO.getBarCode()); + //设置批次属性字段(从出库单明细中获取) + pickingMaterialDetailDO.setBatchRefNo(outMaterialDetailPO.getBatchRefNo()); + pickingMaterialDetailDO.setSheetRefNo(outMaterialDetailPO.getSheetRefNo()); + pickingMaterialDetailDO.setBoxPalletNo(outMaterialDetailPO.getBoxPalletNo()); + pickingMaterialDetailDO.setExtAttr1(outMaterialDetailPO.getExtAttr1()); + pickingMaterialDetailDO.setExtAttr2(outMaterialDetailPO.getExtAttr2()); + pickingMaterialDetailDO.setProductionDate(outMaterialDetailPO.getProductionDate()); + pickingMaterialDetailDO.setExpiryDate(outMaterialDetailPO.getExpiryDate()); + pickingMaterialDetailDO.setInventoryDate(outMaterialDetailPO.getInventoryDate()); + pickingMaterialDetailDO.setExtAttr3(outMaterialDetailPO.getExtAttr3()); + pickingMaterialDetailDO.setExtAttr4(outMaterialDetailPO.getExtAttr4()); pickingMaterialDetailList.add(pickingMaterialDetailDO); List outMaterialDetailPOListChildren = outMaterialDetailPO.getChildren(); if (!CollectionUtils.isEmpty(outMaterialDetailPOListChildren)){ @@ -462,7 +575,18 @@ public class StockOutOrderDomainService { pickingMaterialDetailDOChildren.setMaterialCode(outMaterialDetailPOChildren.getMaterialNo()); pickingMaterialDetailDOChildren.setMaterialName(outMaterialDetailPOChildren.getCommodityName()); pickingMaterialDetailDOChildren.setBarCode(outMaterialDetailPOChildren.getBarCode()); - pickingMaterialDetailList.add(pickingMaterialDetailDO); + //设置批次属性字段(从出库单明细中获取) + pickingMaterialDetailDOChildren.setBatchRefNo(outMaterialDetailPOChildren.getBatchRefNo()); + pickingMaterialDetailDOChildren.setSheetRefNo(outMaterialDetailPOChildren.getSheetRefNo()); + pickingMaterialDetailDOChildren.setBoxPalletNo(outMaterialDetailPOChildren.getBoxPalletNo()); + pickingMaterialDetailDOChildren.setExtAttr1(outMaterialDetailPOChildren.getExtAttr1()); + pickingMaterialDetailDOChildren.setExtAttr2(outMaterialDetailPOChildren.getExtAttr2()); + pickingMaterialDetailDOChildren.setProductionDate(outMaterialDetailPOChildren.getProductionDate()); + pickingMaterialDetailDOChildren.setExpiryDate(outMaterialDetailPOChildren.getExpiryDate()); + pickingMaterialDetailDOChildren.setInventoryDate(outMaterialDetailPOChildren.getInventoryDate()); + pickingMaterialDetailDOChildren.setExtAttr3(outMaterialDetailPOChildren.getExtAttr3()); + pickingMaterialDetailDOChildren.setExtAttr4(outMaterialDetailPOChildren.getExtAttr4()); + pickingMaterialDetailList.add(pickingMaterialDetailDOChildren); }); } }); @@ -1021,4 +1145,5 @@ public class StockOutOrderDomainService { return 3; } } + } \ No newline at end of file diff --git a/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/materialInventory/MaterialInventoryDTO.java b/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/materialInventory/MaterialInventoryDTO.java index 3e0e1875b..70da48443 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/materialInventory/MaterialInventoryDTO.java +++ b/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/materialInventory/MaterialInventoryDTO.java @@ -147,4 +147,16 @@ public class MaterialInventoryDTO extends MaterialBaseDTO { @ApiModelProperty("货主id") private Long shipperId; + + @ApiModelProperty("Batch Ref NO's") + @Excel(name = "Batch Ref NO's") + private String batchRefNo; + + @ApiModelProperty("Sheet Ref NO's") + @Excel(name = "Sheet Ref NO's") + private String sheetRefNo; + + @ApiModelProperty("箱号/卡板号") + @Excel(name = "箱号/卡板号") + private String boxPalletNo; } diff --git a/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/stockOutOrder/StockOutOrderApi.java b/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/stockOutOrder/StockOutOrderApi.java index 528949e51..8ba8ebf50 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/stockOutOrder/StockOutOrderApi.java +++ b/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/stockOutOrder/StockOutOrderApi.java @@ -24,6 +24,7 @@ import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.io.IOException; +import java.util.ArrayList; import java.util.List; /** @@ -164,7 +165,48 @@ public class StockOutOrderApi extends BaseController { return toAjax(stockOutOrderApplicationService.cancelAssign(stockOutOrderDO)); } - + /** + * 手动取消分配(点击确认后直接取消分配) + * 前端点击取消分配按钮时弹出确认对话框,点击确认后调用此接口 + * 只需要传递出库单ID和物料明细ID,会自动取消该明细的所有已分配数量 + */ + @ApiOperation("手动取消分配") + @PostMapping("/manualCancelAssign") + public AjaxResult manualCancelAssign(@RequestBody StockOutOrderDTO stockOutOrderDTO) { + // 检查参数 + if (stockOutOrderDTO.getOutOrderId() == null) { + return error("出库单ID不能为空"); + } + if (stockOutOrderDTO.getMaterialDetailList() == null || stockOutOrderDTO.getMaterialDetailList().isEmpty()) { + return error("物料明细不能为空,请选择要取消分配的物料明细"); + } + + StockOutOrderDO stockOutOrderDO = new StockOutOrderDO(); + BeanUtils.copyProperties(stockOutOrderDTO, stockOutOrderDO); + // 转换物料明细列表,手动转换确保materialDetailId字段正确传递 + List materialDetailList = new ArrayList<>(); + for (OutMaterialDetailDTO detailDTO : stockOutOrderDTO.getMaterialDetailList()) { + OutMaterialDetailDO detailDO = new OutMaterialDetailDO(); + // 只复制必要的字段,确保materialDetailId被正确传递 + detailDO.setMaterialDetailId(detailDTO.getMaterialDetailId()); + detailDO.setUniqueId(detailDTO.getUniqueId()); + detailDO.setAllocationQuantity(detailDTO.getAllocationQuantity()); + // 如果有子明细,也转换 + if (detailDTO.getMaterialDetailList() != null && !detailDTO.getMaterialDetailList().isEmpty()) { + List children = new ArrayList<>(); + for (OutMaterialDetailDTO childDTO : detailDTO.getMaterialDetailList()) { + OutMaterialDetailDO childDO = new OutMaterialDetailDO(); + childDO.setMaterialDetailId(childDTO.getMaterialDetailId()); + childDO.setAllocationQuantity(childDTO.getAllocationQuantity()); + children.add(childDO); + } + detailDO.setChildren(children); + } + materialDetailList.add(detailDO); + } + stockOutOrderDO.setMaterialDetailList(materialDetailList); + return toAjax(stockOutOrderApplicationService.manualCancelAssign(stockOutOrderDO)); + } /** * 生成拣货单 diff --git a/mhd_wms/src/main/resources/mapper/OutMaterialDetail/OutMaterialDetailMapper.xml b/mhd_wms/src/main/resources/mapper/OutMaterialDetail/OutMaterialDetailMapper.xml index 472daba29..fcbf40168 100644 --- a/mhd_wms/src/main/resources/mapper/OutMaterialDetail/OutMaterialDetailMapper.xml +++ b/mhd_wms/src/main/resources/mapper/OutMaterialDetail/OutMaterialDetailMapper.xml @@ -75,6 +75,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + + + + + + @@ -109,7 +116,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" a.TOTAL_VOLUME, a.TOTAL_AREA, a.TOTAL_AMOUNT, - a.UNIT + a.UNIT, + a.EXT_ATTR_1, + a.EXT_ATTR_2, + a.PRODUCTION_DATE, + a.EXPIRY_DATE, + a.INVENTORY_DATE, + a.EXT_ATTR_3, + a.EXT_ATTR_4 diff --git a/mhd_wms/src/main/resources/mapper/materialInventory/MaterialInventoryMapper.xml b/mhd_wms/src/main/resources/mapper/materialInventory/MaterialInventoryMapper.xml index e1f020cf7..37ec8af7e 100644 --- a/mhd_wms/src/main/resources/mapper/materialInventory/MaterialInventoryMapper.xml +++ b/mhd_wms/src/main/resources/mapper/materialInventory/MaterialInventoryMapper.xml @@ -69,7 +69,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" a.storage_section_id, a.storage_code, a.storage_name, a.storage_location_id, a.storage_location_code, a.storage_location_name, a.material_base_info_id,a.material_detail_id, a.batch_number,a.material_status_code,a.material_status_name,a.container_id,a.container_code,a.container_type,a.container_type_name,IFNULL(a.freeze_quantity,0) freeze_quantity,a.is_able, IFNULL(a.inventory_quantity,0) inventory_quantity, IFNULL(a.allocation_quantity,0) allocation_quantity, a.remark, a.create_time, a.create_by, a.create_by_name, a.update_time, a.update_by, a.update_by_name, - a.del_flag,a.unit,a.area,a.NET_WEIGHT,a.GROSS_WEIGHT,a.VOLUME + a.del_flag,a.unit,a.area,a.NET_WEIGHT,a.GROSS_WEIGHT,a.VOLUME, + a.BATCH_REF_NO, a.SHEET_REF_NO, a.BOX_PALLET_NO @@ -162,6 +163,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" and (a.storage_location_code = #{storageInfo} or material_code = #{storageInfo} or material_name like concat('%', #{storageInfo}, '%') or bar_code = #{storageInfo}) + + and a.BATCH_REF_NO like concat('%', #{batchRefNo}, '%') + + + and a.SHEET_REF_NO like concat('%', #{sheetRefNo}, '%') + + + and a.BOX_PALLET_NO like concat('%', #{boxPalletNo}, '%') + \ No newline at end of file