手动分配(取消分配)调整

This commit is contained in:
秦鸿展
2026-02-05 09:11:11 +08:00
parent 62c42b3aaa
commit 5f230d03ea
6 changed files with 144 additions and 45 deletions
@@ -192,7 +192,6 @@ public class StockOutOrderApplicationService {
Long materialBaseInfoId = outMaterialDetailPO.getMaterialBaseInfoId(); Long materialBaseInfoId = outMaterialDetailPO.getMaterialBaseInfoId();
Long materialInventoryId = outMaterialDetailPO.getMaterialInventoryId(); Long materialInventoryId = outMaterialDetailPO.getMaterialInventoryId();
// 只保留isDisplay=1的批次属性(从batchDetailMap中获取,已经过滤过了)
// 创建新的materialMoreDetailList,只包含isDisplay=1的属性 // 创建新的materialMoreDetailList,只包含isDisplay=1的属性
List<MaterialMoreDetailPO> materialMoreDetailList = new ArrayList<>(); List<MaterialMoreDetailPO> materialMoreDetailList = new ArrayList<>();
@@ -218,6 +217,7 @@ public class StockOutOrderApplicationService {
} }
} }
// 只保留isDisplay=1的批次属性(从batchDetailMap中获取,已经过滤过了)
if (materialBaseInfoId != null && batchDetailMap.containsKey(materialBaseInfoId)) { if (materialBaseInfoId != null && batchDetailMap.containsKey(materialBaseInfoId)) {
List<BatchDetailFeignPO> batchDetailFeignPOList = batchDetailMap.get(materialBaseInfoId); List<BatchDetailFeignPO> batchDetailFeignPOList = batchDetailMap.get(materialBaseInfoId);
// 用于跟踪已添加到列表中的batchDetailId // 用于跟踪已添加到列表中的batchDetailId
@@ -257,7 +257,7 @@ public class StockOutOrderApplicationService {
String fieldValue = null; String fieldValue = null;
String usedFieldName = null; String usedFieldName = null;
// 优先从库存表获取值(如果已分配库存) // 只有在已分配库存时,才从库存表获取值并设置到attributeValue
if (inventoryPO != null) { if (inventoryPO != null) {
// 优先使用fieldName(如果存在) // 优先使用fieldName(如果存在)
if (StringUtils.isNotBlank(batchDetailFeignPO.getFieldName())) { if (StringUtils.isNotBlank(batchDetailFeignPO.getFieldName())) {
@@ -277,36 +277,18 @@ public class StockOutOrderApplicationService {
usedFieldName, fieldValue); usedFieldName, fieldValue);
} }
} }
}
// 只有当获取到值时才更新attributeValue(已分配库存时)
// 如果从库存表没有获取到值,且未分配库存,则从物料明细表中获取值 if (fieldValue != null) {
if (fieldValue == null && inventoryPO == null && outMaterialDetailPO != null) { materialMoreDetailPO.setAttributeValue(fieldValue);
// 优先使用fieldName(如果存在) log.info("设置更多属性:batchDetailId={}, batchLabels={}, attributeValue={}",
if (StringUtils.isNotBlank(batchDetailFeignPO.getFieldName())) { materialMoreDetailPO.getBatchDetailId(), materialMoreDetailPO.getBatchLabels(),
usedFieldName = batchDetailFeignPO.getFieldName(); materialMoreDetailPO.getAttributeValue());
fieldValue = getFieldValueByFieldName(outMaterialDetailPO, usedFieldName);
log.info("批次属性 batchDetailId={}, fieldName={}, 从物料明细表获取到的值={}",
batchDetailFeignPO.getBatchDetailId(), usedFieldName, fieldValue);
}
// 如果fieldName为空,尝试根据batchLabels映射到字段名
else if (StringUtils.isNotBlank(batchDetailFeignPO.getBatchLabels())) {
String fieldNameByLabel = getFieldNameByBatchLabel(batchDetailFeignPO.getBatchLabels());
if (StringUtils.isNotBlank(fieldNameByLabel)) {
usedFieldName = fieldNameByLabel;
fieldValue = getFieldValueByFieldName(outMaterialDetailPO, usedFieldName);
log.info("批次属性 batchDetailId={}, batchLabels={}, 映射字段名={}, 从物料明细表获取到的值={}",
batchDetailFeignPO.getBatchDetailId(), batchDetailFeignPO.getBatchLabels(),
usedFieldName, fieldValue);
}
} }
} } else {
// 未分配库存时,attributeValue保持为空(不设置值)
// 只有当获取到值时才更新attributeValue(避免覆盖已有的值) log.info("批次属性未分配库存,batchDetailId={}, batchLabels={}, attributeValue为空",
if (fieldValue != null) { materialMoreDetailPO.getBatchDetailId(), materialMoreDetailPO.getBatchLabels());
materialMoreDetailPO.setAttributeValue(fieldValue);
log.info("设置更多属性:batchDetailId={}, batchLabels={}, attributeValue={}",
materialMoreDetailPO.getBatchDetailId(), materialMoreDetailPO.getBatchLabels(),
materialMoreDetailPO.getAttributeValue());
} }
} }
} }
@@ -941,6 +923,8 @@ public class StockOutOrderApplicationService {
outMaterialDetailDO.setContainerCode(materialInventoryPO.getContainerCode()); outMaterialDetailDO.setContainerCode(materialInventoryPO.getContainerCode());
outMaterialDetailDO.setContainerType(materialInventoryPO.getContainerType()); outMaterialDetailDO.setContainerType(materialInventoryPO.getContainerType());
outMaterialDetailDO.setContainerTypeName(materialInventoryPO.getContainerTypeName()); outMaterialDetailDO.setContainerTypeName(materialInventoryPO.getContainerTypeName());
// 库存数量,仅用于前端展示
outMaterialDetailDO.setInventoryQuantity(materialInventoryPO.getInventoryQuantity());
} }
/** /**
@@ -11,6 +11,7 @@ import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Date;
/** /**
@@ -386,6 +387,41 @@ public class OutMaterialDetail extends BaseVOEntity {
@Excel(name = "单位") @Excel(name = "单位")
private String unit; private String unit;
@ApiModelProperty("扩展属性1")
@Excel(name = "扩展属性1")
private String extAttr1;
@ApiModelProperty("扩展属性2")
@Excel(name = "扩展属性2")
private String extAttr2;
@ApiModelProperty("生产日期")
@Excel(name = "生产日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date productionDate;
@ApiModelProperty("过期日期")
@Excel(name = "过期日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date expiryDate;
@ApiModelProperty("存货日期")
@Excel(name = "存货日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date inventoryDate;
@ApiModelProperty("扩展属性3")
@Excel(name = "扩展属性3", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date extAttr3;
@ApiModelProperty("扩展属性4")
@Excel(name = "扩展属性4", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date extAttr4;
/**
* 库存数量(仅用于前端展示,从material_inventory表中带出)
*/
@ApiModelProperty("库存数量")
@TableField(exist = false)
private BigDecimal inventoryQuantity;
@TableField(exist = false) @TableField(exist = false)
private BigDecimal actualQuantity; private BigDecimal actualQuantity;
} }
@@ -377,10 +377,23 @@ public class OutMaterialDetailImpl extends ServiceImpl<OutMaterialDetailMapper,
throw new ServiceException("物料" + outMaterialDetailDb.getMaterialName() + ",取消分配数量不能大于分配总数"); throw new ServiceException("物料" + outMaterialDetailDb.getMaterialName() + ",取消分配数量不能大于分配总数");
} }
// 更新分配数量和已分配数量(减少) // 更新分配数量和已分配数量
outMaterialDetail.setAllocationQuantity(outMaterialDetailDb.getAllocationQuantity().subtract(cancelAllocationQuantity)); // 手动取消分配的业务含义:将该明细上“已经分配”的库存全部撤回,回到可再次分配的状态
outMaterialDetail.setAlreadyAllocationQuantity(outMaterialDetailDb.getAlreadyAllocationQuantity().subtract(cancelAllocationQuantity)); // 因此这里直接将分配数量、已分配数量都置为 0
// 设置 actualQuantity 用于 qxfp 方法更新库存 outMaterialDetail.setAllocationQuantity(BigDecimal.ZERO);
outMaterialDetail.setAlreadyAllocationQuantity(BigDecimal.ZERO);
// 同时清空目标库位 / 目标库区 / 目标仓库等分配相关的信息(仅保留计划信息)
outMaterialDetail.setWarehouseId(null);
outMaterialDetail.setWarehouseCode(null);
outMaterialDetail.setWarehouseName(null);
outMaterialDetail.setStorageSectionId(null);
outMaterialDetail.setStorageCode(null);
outMaterialDetail.setStorageName(null);
outMaterialDetail.setStorageLocationId(null);
outMaterialDetail.setStorageLocationCode(null);
outMaterialDetail.setStorageLocationName(null);
// 设置 actualQuantity 用于 qxfp 方法更新库存(表示本次实际取消的数量)
outMaterialDetail.setActualQuantity(cancelAllocationQuantity); outMaterialDetail.setActualQuantity(cancelAllocationQuantity);
outMaterialDetailList.add(outMaterialDetail); outMaterialDetailList.add(outMaterialDetail);
@@ -519,15 +532,52 @@ public class OutMaterialDetailImpl extends ServiceImpl<OutMaterialDetailMapper,
} }
OutMaterialDetail outMaterialDetailChild = new OutMaterialDetail(); OutMaterialDetail outMaterialDetailChild = new OutMaterialDetail();
outMaterialDetailChild.setMaterialDetailId(outMaterialDetailDOChild.getMaterialDetailId()); outMaterialDetailChild.setMaterialDetailId(outMaterialDetailDOChild.getMaterialDetailId());
outMaterialDetailChild.setAllocationQuantity(outMaterialDetailDOChild.getActualQuantity());
// 子项同样视为全部取消分配:分配数量/已分配数量扣减取消数量,并清空库位/批次等信息
BigDecimal childCancelQty = outMaterialDetailDOChild.getActualQuantity() != null
? outMaterialDetailDOChild.getActualQuantity()
: BigDecimal.ZERO;
BigDecimal childDbAllocationQty = outMaterialDetailChildDb.getAllocationQuantity() != null
? outMaterialDetailChildDb.getAllocationQuantity()
: BigDecimal.ZERO;
BigDecimal childNewAllocationQty = childDbAllocationQty.subtract(childCancelQty);
if (childNewAllocationQty.compareTo(BigDecimal.ZERO) < 0) {
throw new ServiceException("物料" + outMaterialDetailChildDb.getMaterialName() + " 子项,取消分配数量不能大于分配总数");
}
outMaterialDetailChild.setAllocationQuantity(childNewAllocationQty);
BigDecimal childDbAlreadyAlloc = outMaterialDetailChildDb.getAlreadyAllocationQuantity() != null
? outMaterialDetailChildDb.getAlreadyAllocationQuantity()
: BigDecimal.ZERO;
outMaterialDetailChild.setAlreadyAllocationQuantity(childDbAlreadyAlloc.subtract(childCancelQty));
// 清空子项的目标库位/库区/仓库及批次相关信息
outMaterialDetailChild.setWarehouseId(null);
outMaterialDetailChild.setWarehouseCode(null);
outMaterialDetailChild.setWarehouseName(null);
outMaterialDetailChild.setStorageSectionId(null);
outMaterialDetailChild.setStorageCode(null);
outMaterialDetailChild.setStorageName(null);
outMaterialDetailChild.setStorageLocationId(null);
outMaterialDetailChild.setStorageLocationCode(null);
outMaterialDetailChild.setStorageLocationName(null);
outMaterialDetailChild.setMaterialInventoryId(null);
outMaterialDetailChild.setBatchNumber(null);
outMaterialDetailChild.setMaterialStatusCode(null);
outMaterialDetailChild.setMaterialStatusName(null);
outMaterialDetailChild.setContainerId(null);
outMaterialDetailChild.setContainerCode(null);
outMaterialDetailChild.setContainerType(null);
outMaterialDetailChild.setContainerTypeName(null);
outMaterialDetailChild.setUpdateBy(loginUser.getUserid()); outMaterialDetailChild.setUpdateBy(loginUser.getUserid());
outMaterialDetailChild.setUpdateByName(loginUser.getUsername()); outMaterialDetailChild.setUpdateByName(loginUser.getUsername());
outMaterialDetailChild.setUpdateTime(new Date()); outMaterialDetailChild.setUpdateTime(new Date());
outMaterialDetailChild.setAllowModify(1); outMaterialDetailChild.setAllowModify(1);
outMaterialDetailChild.setActualQuantity(childCancelQty);
outMaterialDetailList.add(outMaterialDetailChild); outMaterialDetailList.add(outMaterialDetailChild);
materialDetailIdsByUpdate.add(outMaterialDetailDOChild.getMaterialDetailId()); materialDetailIdsByUpdate.add(outMaterialDetailDOChild.getMaterialDetailId());
allocationQuantity = allocationQuantity.add(outMaterialDetailDO.getActualQuantity()); allocationQuantity = allocationQuantity.add(childCancelQty);
alreadyAllocationQuantity = alreadyAllocationQuantity.add(outMaterialDetailDO.getAlreadyAllocationQuantity()); alreadyAllocationQuantity = alreadyAllocationQuantity.add(childCancelQty);
} }
} }
//判断取消分配数量不能大于已分配数量(取消分配应该检查alreadyAllocationQuantity,而不是allocationQuantity //判断取消分配数量不能大于已分配数量(取消分配应该检查alreadyAllocationQuantity,而不是allocationQuantity
@@ -537,17 +587,37 @@ public class OutMaterialDetailImpl extends ServiceImpl<OutMaterialDetailMapper,
if(allocationQuantity.compareTo(dbAlreadyAllocationQuantity) > 0){ if(allocationQuantity.compareTo(dbAlreadyAllocationQuantity) > 0){
throw new ServiceException("物料" + outMaterialDetailDb.getMaterialName() + ",取消分配数量不能大于已分配数量"); throw new ServiceException("物料" + outMaterialDetailDb.getMaterialName() + ",取消分配数量不能大于已分配数量");
} }
// 取消分配:只减少已分配数量,分配数量保持不变
// 取消分配的目的是:把之前分配给库存的分配给取消掉,让库存可以重新分配
// allocation_quantity(分配数量)不应该减少,因为取消分配后可以重新分配
// already_allocation_quantity(已分配数量)应该减少,表示取消了多少已分配的数量
BigDecimal dbAllocationQuantity = outMaterialDetailDb.getAllocationQuantity() != null BigDecimal dbAllocationQuantity = outMaterialDetailDb.getAllocationQuantity() != null
? outMaterialDetailDb.getAllocationQuantity() ? outMaterialDetailDb.getAllocationQuantity()
: BigDecimal.ZERO; : BigDecimal.ZERO;
// 分配数量保持不变(取消分配后可以重新分配) // 分配数量和已分配数量都减少:本次手动取消分配视为“把这条明细已分配的全部撤回”
outMaterialDetail.setAllocationQuantity(dbAllocationQuantity); BigDecimal newAllocationQuantity = dbAllocationQuantity.subtract(allocationQuantity);
// 已分配数量减少(取消已分配的数量) if (newAllocationQuantity.compareTo(BigDecimal.ZERO) < 0) {
throw new ServiceException("物料" + outMaterialDetailDb.getMaterialName() + ",取消分配数量不能大于分配总数");
}
outMaterialDetail.setAllocationQuantity(newAllocationQuantity);
outMaterialDetail.setAlreadyAllocationQuantity(dbAlreadyAllocationQuantity.subtract(allocationQuantity)); outMaterialDetail.setAlreadyAllocationQuantity(dbAlreadyAllocationQuantity.subtract(allocationQuantity));
// 同时清空该明细的目标仓库/库区/库位信息(回到未分配状态)
outMaterialDetail.setWarehouseId(null);
outMaterialDetail.setWarehouseCode(null);
outMaterialDetail.setWarehouseName(null);
outMaterialDetail.setStorageSectionId(null);
outMaterialDetail.setStorageCode(null);
outMaterialDetail.setStorageName(null);
outMaterialDetail.setStorageLocationId(null);
outMaterialDetail.setStorageLocationCode(null);
outMaterialDetail.setStorageLocationName(null);
// 清空与分配库存相关的批次、容器信息
outMaterialDetail.setMaterialInventoryId(null);
outMaterialDetail.setBatchNumber(null);
outMaterialDetail.setMaterialStatusCode(null);
outMaterialDetail.setMaterialStatusName(null);
outMaterialDetail.setContainerId(null);
outMaterialDetail.setContainerCode(null);
outMaterialDetail.setContainerType(null);
outMaterialDetail.setContainerTypeName(null);
// 设置 actualQuantity 用于 qxfp 方法更新库存(取消分配的数量) // 设置 actualQuantity 用于 qxfp 方法更新库存(取消分配的数量)
outMaterialDetail.setActualQuantity(allocationQuantity); outMaterialDetail.setActualQuantity(allocationQuantity);
outMaterialDetailList.add(outMaterialDetail); outMaterialDetailList.add(outMaterialDetail);
@@ -168,6 +168,9 @@ public class OutMaterialDetailPO extends StockOutOrderBaseDO {
@Excel(name = "容器类型名称 数据字典") @Excel(name = "容器类型名称 数据字典")
private String containerTypeName; private String containerTypeName;
@ApiModelProperty("库存数量(仅展示)")
private BigDecimal inventoryQuantity;
@ApiModelProperty("分配仓库id") @ApiModelProperty("分配仓库id")
private Long warehouseId; private Long warehouseId;
@@ -158,6 +158,9 @@ public class OutMaterialDetailDO extends BaseVOEntity {
@Excel(name = "容器类型名称 数据字典") @Excel(name = "容器类型名称 数据字典")
private String containerTypeName; private String containerTypeName;
@ApiModelProperty("库存数量(仅展示)")
private BigDecimal inventoryQuantity;
@ApiModelProperty("分配仓库id") @ApiModelProperty("分配仓库id")
private Long warehouseId; private Long warehouseId;
@@ -167,6 +167,9 @@ public class OutMaterialDetailDTO extends BaseVOEntity {
@Excel(name = "容器类型名称 数据字典") @Excel(name = "容器类型名称 数据字典")
private String containerTypeName; private String containerTypeName;
@ApiModelProperty("库存数量(仅展示)")
private BigDecimal inventoryQuantity;
@ApiModelProperty("分配仓库id") @ApiModelProperty("分配仓库id")
private Long warehouseId; private Long warehouseId;