PDABUG修改一轮

This commit is contained in:
秦鸿展
2026-03-11 16:06:39 +08:00
parent 90136fc654
commit e408266f75
14 changed files with 636 additions and 203 deletions
@@ -561,11 +561,98 @@ public class StockOutOrderApplicationService {
}
/**
* 获取出库单详细信息
* 获取出库单详细信息(PDA复核页面:含批次属性、净重、毛重、面积、体积)
*/
public StockOutOrderPO getInfoByApp(Long outOrderId)
{
return stockOutOrderDomainService.getInfoByApp(outOrderId);
public StockOutOrderPO getInfoByApp(Long outOrderId) {
StockOutOrderPO stockOutOrderPO = stockOutOrderDomainService.getInfoByApp(outOrderId);
enrichStockOutOrderForPdaCheck(stockOutOrderPO);
return stockOutOrderPO;
}
/**
* 为PDA复核页面填充批次属性(根据物料批次标签动态显示,有值显示)及净重、毛重、面积、体积
*/
private void enrichStockOutOrderForPdaCheck(StockOutOrderPO stockOutOrderPO) {
if (stockOutOrderPO == null || CollectionUtils.isEmpty(stockOutOrderPO.getMaterialDetailList())) {
return;
}
List<OutMaterialDetailPO> detailList = stockOutOrderPO.getMaterialDetailList();
Set<Long> materialBaseInfoIdSet = detailList.stream()
.map(OutMaterialDetailPO::getMaterialBaseInfoId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
Map<Long, List<BatchDetailFeignPO>> batchDetailMap = new HashMap<>();
for (Long materialBaseInfoId : materialBaseInfoIdSet) {
try {
AjaxResult ajaxResult = systemServiceFeign.getBatchDetailListByMaterialBaseInfoId(materialBaseInfoId);
if (ajaxResult != null && "200".equals(String.valueOf(ajaxResult.get("code")))) {
List<BatchDetailFeignPO> batchDetailFeignPOList = JSON.parseArray(
JSONObject.toJSONString(ajaxResult.get("data")), BatchDetailFeignPO.class);
if (!CollectionUtils.isEmpty(batchDetailFeignPOList)) {
List<BatchDetailFeignPO> filteredList = batchDetailFeignPOList.stream()
.filter(b -> b.getIsDisplay() != null && b.getIsDisplay() == 1)
.collect(Collectors.toList());
batchDetailMap.put(materialBaseInfoId, filteredList);
}
}
} catch (Exception e) {
log.warn("获取物料批次属性失败,物料基础信息ID:{},错误:{}", materialBaseInfoId, e.getMessage());
}
}
setMaterialMoreDetailListRecursivelyForCheck(detailList, batchDetailMap);
}
/**
* 递归为PDA复核物料明细设置批次属性(有值显示),优先从库存取,否则从出库明细取
*/
private void setMaterialMoreDetailListRecursivelyForCheck(List<OutMaterialDetailPO> outMaterialDetailPOList,
Map<Long, List<BatchDetailFeignPO>> batchDetailMap) {
if (CollectionUtils.isEmpty(outMaterialDetailPOList)) {
return;
}
outMaterialDetailPOList.forEach(outMaterialDetailPO -> {
Long materialBaseInfoId = outMaterialDetailPO.getMaterialBaseInfoId();
Long materialInventoryId = outMaterialDetailPO.getMaterialInventoryId();
List<MaterialMoreDetailPO> materialMoreDetailList = new ArrayList<>();
MaterialInventoryPO inventoryPO = null;
if (materialInventoryId != null && materialInventoryId > 0) {
try {
inventoryPO = materialInventoryMapper.selectByIdWithBatchAttributes(materialInventoryId);
} catch (Exception e) {
log.warn("从库存表获取批次属性失败,materialInventoryId={},错误:{}", materialInventoryId, e.getMessage());
}
}
Object sourceObj = inventoryPO != null ? inventoryPO : outMaterialDetailPO;
if (materialBaseInfoId != null && batchDetailMap.containsKey(materialBaseInfoId)) {
for (BatchDetailFeignPO batchDetailFeignPO : batchDetailMap.get(materialBaseInfoId)) {
MaterialMoreDetailPO materialMoreDetailPO = new MaterialMoreDetailPO();
materialMoreDetailPO.setBatchId(batchDetailFeignPO.getBatchId());
materialMoreDetailPO.setBatchDetailId(batchDetailFeignPO.getBatchDetailId());
materialMoreDetailPO.setBatchLabels(batchDetailFeignPO.getBatchLabels());
materialMoreDetailPO.setInputControl(batchDetailFeignPO.getInputControl());
materialMoreDetailPO.setAttributeFormat(batchDetailFeignPO.getAttributeFormat());
materialMoreDetailPO.setAttributeOption(batchDetailFeignPO.getAttributeOption());
materialMoreDetailPO.setRemark(batchDetailFeignPO.getRemark());
String fieldValue = null;
if (StringUtils.isNotBlank(batchDetailFeignPO.getFieldName())) {
fieldValue = getFieldValueByFieldName(sourceObj, batchDetailFeignPO.getFieldName());
} else if (StringUtils.isNotBlank(batchDetailFeignPO.getBatchLabels())) {
String fieldNameByLabel = getFieldNameByBatchLabel(batchDetailFeignPO.getBatchLabels());
if (StringUtils.isNotBlank(fieldNameByLabel)) {
fieldValue = getFieldValueByFieldName(sourceObj, fieldNameByLabel);
}
}
if (fieldValue != null) {
materialMoreDetailPO.setAttributeValue(fieldValue);
materialMoreDetailList.add(materialMoreDetailPO);
}
}
}
outMaterialDetailPO.setMaterialMoreDetailList(materialMoreDetailList);
if (!CollectionUtils.isEmpty(outMaterialDetailPO.getChildren())) {
setMaterialMoreDetailListRecursivelyForCheck(outMaterialDetailPO.getChildren(), batchDetailMap);
}
});
}
/**
@@ -1,13 +1,25 @@
package com.mhd.wms.application.service.stockOutTaskOrder;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.mhd.common.core.exception.ServiceException;
import com.mhd.common.core.utils.StringUtils;
import com.mhd.common.core.utils.bean.BeanUtils;
import com.mhd.common.core.web.domain.AjaxResult;
import com.mhd.common.security.utils.SecurityUtils;
import com.mhd.system.api.SystemServiceFeign;
import com.mhd.system.api.domain.BatchDetailFeignPO;
import com.mhd.system.api.domain.cache.AssociationWarehouseCacheDO;
import com.mhd.system.api.domain.cache.SystemServiceCacheUtil;
import com.mhd.system.api.model.LoginUser;
import com.mhd.wms.domain.materialMoreDetail.repository.po.MaterialMoreDetailPO;
import com.mhd.wms.domain.pickingMaterialDetail.repository.facade.IPickingMaterialDetailService;
import com.mhd.wms.domain.pickingMaterialDetail.repository.po.PickingMaterialDetailPO;
import com.mhd.wms.domain.pickingMaterialDetail.repository.todo.PickingMaterialDetailDO;
import com.mhd.wms.domain.stockOutTaskOrder.repository.po.StockOutTaskOrderPO;
import com.mhd.wms.domain.stockOutTaskOrder.repository.po.TaskMaterialPO;
import com.mhd.wms.domain.stockOutTaskOrder.repository.po.TaskStoragePO;
import com.mhd.wms.domain.stockOutTaskOrder.repository.todo.StockOutTaskOrderDO;
import com.mhd.wms.domain.stockOutTaskOrder.service.StockOutTaskOrderDomainService;
import com.mhd.wms.domain.taskPickingMaterialDetail.repository.po.TaskPickingMaterialDetailPO;
@@ -18,10 +30,11 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -39,6 +52,12 @@ public class StockOutTaskOrderApplicationService {
@Autowired
private TaskPickingMaterialDetailDomainService taskPickingMaterialDetailDomainService;
@Resource
private IPickingMaterialDetailService pickingMaterialDetailService;
@Resource
private SystemServiceFeign systemServiceFeign;
/**
* 分页查询拣货作业单列表
@@ -135,17 +154,19 @@ public class StockOutTaskOrderApplicationService {
/**
* 按库位拣货 获取拣货作业单详细信息
*/
public StockOutTaskOrderPO getInfoByStorageLocation(Long outTaskOrderId)
{
return stockOutTaskOrderDomainService.getInfoByStorageLocation(outTaskOrderId);
public StockOutTaskOrderPO getInfoByStorageLocation(Long outTaskOrderId) {
StockOutTaskOrderPO po = stockOutTaskOrderDomainService.getInfoByStorageLocation(outTaskOrderId);
enrichStockOutTaskOrderWithBatchAndWeight(po);
return po;
}
/**
*按物料拣货 获取拣货作业单详细信息
* 按物料拣货 获取拣货作业单详细信息
*/
public StockOutTaskOrderPO getInfoByMaterial(Long outTaskOrderId)
{
return stockOutTaskOrderDomainService.getInfoByMaterial(outTaskOrderId);
public StockOutTaskOrderPO getInfoByMaterial(Long outTaskOrderId) {
StockOutTaskOrderPO po = stockOutTaskOrderDomainService.getInfoByMaterial(outTaskOrderId);
enrichStockOutTaskOrderWithBatchAndWeight(po);
return po;
}
/**
@@ -224,4 +245,202 @@ public class StockOutTaskOrderApplicationService {
return returnStockOutTaskOrderDO;
}
/**
* 为拣货作业单的物料明细填充批次属性、净重、毛重、面积、体积
*/
private void enrichStockOutTaskOrderWithBatchAndWeight(StockOutTaskOrderPO stockOutTaskOrderPO) {
if (stockOutTaskOrderPO == null) {
return;
}
List<TaskPickingMaterialDetailPO> allDetails = new ArrayList<>();
if (!CollectionUtils.isEmpty(stockOutTaskOrderPO.getTaskStorageList())) {
for (TaskStoragePO taskStorage : stockOutTaskOrderPO.getTaskStorageList()) {
if (!CollectionUtils.isEmpty(taskStorage.getTaskPickingMaterialDetailList())) {
allDetails.addAll(taskStorage.getTaskPickingMaterialDetailList());
}
}
}
if (!CollectionUtils.isEmpty(stockOutTaskOrderPO.getTaskMaterialList())) {
for (TaskMaterialPO taskMaterial : stockOutTaskOrderPO.getTaskMaterialList()) {
if (!CollectionUtils.isEmpty(taskMaterial.getTaskPickingMaterialDetailList())) {
allDetails.addAll(taskMaterial.getTaskPickingMaterialDetailList());
}
}
}
if (CollectionUtils.isEmpty(allDetails)) {
return;
}
// 批量查询 picking_material_detail(按 pickingUniqueId = unique_id
Set<Long> pickingUniqueIds = allDetails.stream()
.map(TaskPickingMaterialDetailPO::getPickingUniqueId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
Map<Long, PickingMaterialDetailPO> pickingDetailMap = new HashMap<>();
for (Long pickingUniqueId : pickingUniqueIds) {
PickingMaterialDetailDO queryDO = new PickingMaterialDetailDO();
queryDO.setUniqueId(pickingUniqueId);
List<PickingMaterialDetailPO> list = pickingMaterialDetailService.queryList(queryDO);
if (!CollectionUtils.isEmpty(list)) {
pickingDetailMap.put(pickingUniqueId, list.get(0));
}
}
// 批量获取物料批次属性
Set<Long> materialBaseInfoIdSet = allDetails.stream()
.map(TaskPickingMaterialDetailPO::getMaterialBaseInfoId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
Map<Long, List<BatchDetailFeignPO>> batchDetailMap = new HashMap<>();
for (Long materialBaseInfoId : materialBaseInfoIdSet) {
try {
AjaxResult ajaxResult = systemServiceFeign.getBatchDetailListByMaterialBaseInfoId(materialBaseInfoId);
if (ajaxResult != null && "200".equals(String.valueOf(ajaxResult.get("code")))) {
List<BatchDetailFeignPO> batchDetailFeignPOList = JSON.parseArray(
JSONObject.toJSONString(ajaxResult.get("data")), BatchDetailFeignPO.class);
if (!CollectionUtils.isEmpty(batchDetailFeignPOList)) {
List<BatchDetailFeignPO> filteredList = batchDetailFeignPOList.stream()
.filter(b -> b.getIsDisplay() != null && b.getIsDisplay() == 1)
.collect(Collectors.toList());
batchDetailMap.put(materialBaseInfoId, filteredList);
}
}
} catch (Exception e) {
log.warn("获取物料批次属性失败,物料基础信息ID:{},错误:{}", materialBaseInfoId, e.getMessage());
}
}
// 为每个 TaskPickingMaterialDetailPO 填充
for (TaskPickingMaterialDetailPO detail : allDetails) {
PickingMaterialDetailPO pickingDetail = detail.getPickingUniqueId() != null
? pickingDetailMap.get(detail.getPickingUniqueId()) : null;
if (pickingDetail != null) {
detail.setTotalNetWeight(pickingDetail.getTotalNetWeight());
detail.setTotalGrossWeight(pickingDetail.getTotalGrossWeight());
detail.setTotalVolume(pickingDetail.getTotalVolume());
detail.setTotalArea(pickingDetail.getTotalArea());
}
// 批次属性(根据物料绑定且isDisplay=1动态显示,无值也可展示)
Long materialBaseInfoId = detail.getMaterialBaseInfoId();
if (materialBaseInfoId != null && batchDetailMap.containsKey(materialBaseInfoId)) {
List<MaterialMoreDetailPO> materialMoreDetailList = new ArrayList<>();
Object sourceObj = pickingDetail != null ? pickingDetail : detail;
for (BatchDetailFeignPO batchDetailFeignPO : batchDetailMap.get(materialBaseInfoId)) {
MaterialMoreDetailPO materialMoreDetailPO = new MaterialMoreDetailPO();
materialMoreDetailPO.setBatchId(batchDetailFeignPO.getBatchId());
materialMoreDetailPO.setBatchDetailId(batchDetailFeignPO.getBatchDetailId());
materialMoreDetailPO.setBatchLabels(batchDetailFeignPO.getBatchLabels());
materialMoreDetailPO.setInputControl(batchDetailFeignPO.getInputControl());
materialMoreDetailPO.setAttributeFormat(batchDetailFeignPO.getAttributeFormat());
materialMoreDetailPO.setAttributeOption(batchDetailFeignPO.getAttributeOption());
materialMoreDetailPO.setRemark(batchDetailFeignPO.getRemark());
String fieldValue = null;
if (StringUtils.isNotBlank(batchDetailFeignPO.getFieldName())) {
fieldValue = getFieldValueByFieldName(sourceObj, batchDetailFeignPO.getFieldName());
} else if (StringUtils.isNotBlank(batchDetailFeignPO.getBatchLabels())) {
String fieldNameByLabel = getFieldNameByBatchLabel(batchDetailFeignPO.getBatchLabels());
if (StringUtils.isNotBlank(fieldNameByLabel)) {
fieldValue = getFieldValueByFieldName(sourceObj, fieldNameByLabel);
}
}
if (fieldValue != null) {
materialMoreDetailPO.setAttributeValue(fieldValue);
}
materialMoreDetailList.add(materialMoreDetailPO);
}
detail.setMaterialMoreDetailList(materialMoreDetailList);
}
}
}
private String getFieldNameByBatchLabel(String batchLabel) {
if (StringUtils.isBlank(batchLabel)) {
return null;
}
Map<String, String> labelToFieldNameMap = new HashMap<>();
labelToFieldNameMap.put("Invoice No.", "invoiceNo");
labelToFieldNameMap.put("Invoice No", "invoiceNo");
labelToFieldNameMap.put("发票号", "invoiceNo");
labelToFieldNameMap.put("Batch Ref NO's", "batchRefNo");
labelToFieldNameMap.put("Batch Ref NO", "batchRefNo");
labelToFieldNameMap.put("批次参考号", "batchRefNo");
labelToFieldNameMap.put("Sheet Ref NO's", "sheetRefNo");
labelToFieldNameMap.put("Sheet Ref NO", "sheetRefNo");
labelToFieldNameMap.put("单据参考号", "sheetRefNo");
labelToFieldNameMap.put("箱号/卡板号", "boxPalletNo");
labelToFieldNameMap.put("箱号", "boxPalletNo");
labelToFieldNameMap.put("卡板号", "boxPalletNo");
labelToFieldNameMap.put("批次号", "batchNumber");
labelToFieldNameMap.put("生产日期", "productionDate");
labelToFieldNameMap.put("过期日期", "expiryDate");
labelToFieldNameMap.put("存货日期", "inventoryDate");
labelToFieldNameMap.put("扩展字段1", "extAttr1");
labelToFieldNameMap.put("扩展字段2", "extAttr2");
labelToFieldNameMap.put("扩展字段3", "extAttr3");
labelToFieldNameMap.put("扩展字段4", "extAttr4");
String fieldName = labelToFieldNameMap.get(batchLabel.trim());
if (StringUtils.isNotBlank(fieldName)) {
return fieldName;
}
for (Map.Entry<String, String> entry : labelToFieldNameMap.entrySet()) {
if (batchLabel.contains(entry.getKey()) || entry.getKey().contains(batchLabel)) {
return entry.getValue();
}
}
return null;
}
private String getFieldValueByFieldName(Object obj, String fieldName) {
if (obj == null || StringUtils.isBlank(fieldName)) {
return null;
}
try {
String normalizedFieldName = fieldName;
if (normalizedFieldName.contains("_")) {
normalizedFieldName = snakeToCamel(normalizedFieldName);
}
Class<?> clazz = obj.getClass();
Field field = null;
Class<?> currentClass = clazz;
while (currentClass != null && field == null) {
try {
field = currentClass.getDeclaredField(normalizedFieldName);
} catch (NoSuchFieldException e) {
currentClass = currentClass.getSuperclass();
}
}
if (field == null) {
return null;
}
field.setAccessible(true);
Object value = field.get(obj);
if (value == null) {
return null;
}
if (value instanceof Date) {
return new SimpleDateFormat("yyyy-MM-dd").format((Date) value);
}
return value.toString();
} catch (Exception e) {
log.warn("通过反射获取字段值失败,字段名:{},错误:{}", fieldName, e.getMessage());
return null;
}
}
private String snakeToCamel(String snake) {
if (StringUtils.isBlank(snake)) {
return null;
}
String s = snake.trim().toLowerCase();
StringBuilder sb = new StringBuilder();
boolean upperNext = false;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '_') {
upperNext = true;
continue;
}
sb.append(upperNext ? Character.toUpperCase(c) : c);
upperNext = false;
}
return sb.toString();
}
}
@@ -22,6 +22,8 @@ import com.mhd.system.api.domain.cache.AssociationWarehouseCacheDO;
import com.mhd.system.api.domain.cache.SystemServiceCacheUtil;
import com.mhd.system.api.model.LoginUser;
import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailDO;
import com.mhd.wms.domain.materialBarCode.repository.facade.IMaterialBarCodeService;
import com.mhd.wms.domain.materialBarCode.repository.po.MaterialBarCodePO;
import com.mhd.wms.domain.materialBaseInfo.repository.facade.IMaterialBaseInfoService;
import com.mhd.wms.domain.materialBaseInfo.repository.po.MaterialBaseInfoPO;
import com.mhd.wms.domain.materialGoodsRule.repository.facade.IMaterialGoodsRuleService;
@@ -75,6 +77,8 @@ public class StockReceiptOrderApplicationService {
@Autowired
private IMaterialBaseInfoService materialBaseInfoService;
@Autowired
private IMaterialBarCodeService materialBarCodeService;
@Autowired
private IMaterialGoodsRuleService materialGoodsRuleService;
@Autowired
private SystemServiceFeign systemServiceFeign;
@@ -249,6 +253,10 @@ public class StockReceiptOrderApplicationService {
// 4.3 为每个明细行填充物料单位信息(如果单位信息为空)
fillMaterialDetailUnitInfoRecursively(receiptMaterialDetailPOList, materialBaseInfoMap, packDetailMap);
// 4.4 为每个明细行填充物料条码(为空时取物料维护的条码信息第一行的 barCode)
Map<Long, String> materialBarCodeMap = buildMaterialBarCodeMap(materialBaseInfoIdSet);
fillBarCodeFromMaterialBarCodeRecursively(receiptMaterialDetailPOList, materialBarCodeMap);
// 5. 清空质检相关字段(如果是否质检为否)
clearQualityInspectionFieldsRecursively(receiptMaterialDetailPOList);
@@ -269,6 +277,10 @@ public class StockReceiptOrderApplicationService {
stockReceiptOrderPO.setTotalGrossWeight(totalGrossWeight);
stockReceiptOrderPO.setTotalVolume(totalVolume);
stockReceiptOrderPO.setTotalArea(totalArea);
// 扁平化明细:将子项收货数据合并到主项
flattenMaterialDetailList(receiptMaterialDetailPOList);
// PC 端子项计划数量不展示:递归清空所有子项的 quantity
clearChildQuantityRecursively(receiptMaterialDetailPOList);
stockReceiptOrderPO.setMaterialDetailList(receiptMaterialDetailPOList);
log.info("返回收货单信息,receiptOrderId={}, materialDetailList大小={}, totalNetWeight={}, totalGrossWeight={}, totalVolume={}, totalArea={}",
stockReceiptOrderPO.getReceiptOrderId(),
@@ -369,7 +381,7 @@ public class StockReceiptOrderApplicationService {
}
/**
* 扁平化明细:将子项收货数据合并到父级并清空 children,使每条明细只显示一行(PDA 与 PC 端收货一致
* 扁平化明细:将第一条子项变为主行,两条子项收货数量累加到主行 ALREADY_RECEIPT_QUANTITY,主行展示第一条子项的批次属性(收货时修改的值
* @param receiptMaterialDetailPOList 物料明细列表(树形,level 1 父级含 children
*/
private void flattenMaterialDetailList(List<ReceiptMaterialDetailPO> receiptMaterialDetailPOList) {
@@ -381,43 +393,61 @@ public class StockReceiptOrderApplicationService {
if (CollectionUtils.isEmpty(children)) {
continue;
}
// 将子项收货数据合并到父级
// 第一条子项变为主行:用第一条子项的数据(含批次属性)覆盖主行展示
ReceiptMaterialDetailPO firstChild = children.get(0);
if (!CollectionUtils.isEmpty(firstChild.getMaterialMoreDetailList())) {
parent.setMaterialMoreDetailList(firstChild.getMaterialMoreDetailList());
}
parent.setBatchRefNo(firstChild.getBatchRefNo());
parent.setSheetRefNo(firstChild.getSheetRefNo());
parent.setBoxPalletNo(firstChild.getBoxPalletNo());
parent.setProductionDate(firstChild.getProductionDate());
parent.setExpiryDate(firstChild.getExpiryDate());
parent.setInventoryDate(firstChild.getInventoryDate());
parent.setExtAttr1(firstChild.getExtAttr1());
parent.setExtAttr2(firstChild.getExtAttr2());
parent.setExtAttr3(firstChild.getExtAttr3());
parent.setExtAttr4(firstChild.getExtAttr4());
// 两条子项收货数量累加到主行(净重、毛重、体积、面积不累加,保持主行原值)
BigDecimal receiptQuantitySum = parent.getReceiptQuantity() != null ? parent.getReceiptQuantity() : BigDecimal.ZERO;
BigDecimal totalNetWeightSum = parent.getTotalNetWeight() != null ? parent.getTotalNetWeight() : BigDecimal.ZERO;
BigDecimal totalGrossWeightSum = parent.getTotalGrossWeight() != null ? parent.getTotalGrossWeight() : BigDecimal.ZERO;
BigDecimal totalVolumeSum = parent.getTotalVolume() != null ? parent.getTotalVolume() : BigDecimal.ZERO;
BigDecimal totalAreaSum = parent.getTotalArea() != null ? parent.getTotalArea() : BigDecimal.ZERO;
Integer maxReceiptStatus = parent.getReceiptStatus();
for (ReceiptMaterialDetailPO child : children) {
if (child.getReceiptQuantity() != null) {
receiptQuantitySum = receiptQuantitySum.add(child.getReceiptQuantity());
}
if (child.getTotalNetWeight() != null) {
totalNetWeightSum = totalNetWeightSum.add(child.getTotalNetWeight());
}
if (child.getTotalGrossWeight() != null) {
totalGrossWeightSum = totalGrossWeightSum.add(child.getTotalGrossWeight());
}
if (child.getTotalVolume() != null) {
totalVolumeSum = totalVolumeSum.add(child.getTotalVolume());
}
if (child.getTotalArea() != null) {
totalAreaSum = totalAreaSum.add(child.getTotalArea());
}
if (child.getReceiptStatus() != null && (maxReceiptStatus == null || child.getReceiptStatus() > maxReceiptStatus)) {
maxReceiptStatus = child.getReceiptStatus();
}
// 子项不需要展示计划数量字段
child.setQuantity(null);
}
parent.setReceiptQuantity(receiptQuantitySum);
parent.setTotalNetWeight(totalNetWeightSum);
parent.setTotalGrossWeight(totalGrossWeightSum);
parent.setTotalVolume(totalVolumeSum);
parent.setTotalArea(totalAreaSum);
// 主行 ALREADY_RECEIPT_QUANTITYDB 已存汇总时用其值,否则用子项合计
if (parent.getAlreadyReceiptQuantity() == null || parent.getAlreadyReceiptQuantity().compareTo(receiptQuantitySum) < 0) {
parent.setAlreadyReceiptQuantity(receiptQuantitySum);
}
if (maxReceiptStatus != null) {
parent.setReceiptStatus(maxReceiptStatus);
}
// 清空子项,使前端只显示父级一行
parent.setChildren(new ArrayList<>());
// 保留子项,子项展示其自己填写的值(收货数量、批次属性、净重毛重体积面积等)
}
}
/**
* PC 端子项计划数量不展示:递归清空所有子项的 quantity
*/
private void clearChildQuantityRecursively(List<ReceiptMaterialDetailPO> receiptMaterialDetailPOList) {
if (CollectionUtils.isEmpty(receiptMaterialDetailPOList)) {
return;
}
for (ReceiptMaterialDetailPO detail : receiptMaterialDetailPOList) {
List<ReceiptMaterialDetailPO> children = detail.getChildren();
if (!CollectionUtils.isEmpty(children)) {
for (ReceiptMaterialDetailPO child : children) {
child.setQuantity(null);
clearChildQuantityRecursively(child.getChildren());
}
}
}
}
@@ -587,6 +617,53 @@ public class StockReceiptOrderApplicationService {
});
}
/**
* 批量查询物料条码,取物料维护的条码信息第一行的 barCode
* @param materialBaseInfoIdSet 物料基础信息ID集合
* @return Map<materialBaseInfoId, barCode>
*/
private Map<Long, String> buildMaterialBarCodeMap(Set<Long> materialBaseInfoIdSet) {
Map<Long, String> materialBarCodeMap = new HashMap<>();
if (materialBaseInfoIdSet == null || materialBaseInfoIdSet.isEmpty()) {
return materialBarCodeMap;
}
for (Long materialBaseInfoId : materialBaseInfoIdSet) {
try {
List<MaterialBarCodePO> list = materialBarCodeService.getInfoByMaterialBaseInfoIds(materialBaseInfoId);
if (!CollectionUtils.isEmpty(list) && StringUtils.isNotBlank(list.get(0).getBarCode())) {
materialBarCodeMap.put(materialBaseInfoId, list.get(0).getBarCode());
}
} catch (Exception e) {
log.warn("获取物料条码信息失败,物料基础信息ID:{},错误:{}", materialBaseInfoId, e.getMessage());
}
}
return materialBarCodeMap;
}
/**
* 递归填充物料条码(为空时取物料维护的条码信息第一行的 barCode)
*/
private void fillBarCodeFromMaterialBarCodeRecursively(List<ReceiptMaterialDetailPO> receiptMaterialDetailPOList,
Map<Long, String> materialBarCodeMap) {
if (CollectionUtils.isEmpty(receiptMaterialDetailPOList) || materialBarCodeMap == null) {
return;
}
receiptMaterialDetailPOList.forEach(receiptMaterialDetailPO -> {
if (StringUtils.isBlank(receiptMaterialDetailPO.getBarCode())) {
Long materialBaseInfoId = receiptMaterialDetailPO.getMaterialBaseInfoId();
if (materialBaseInfoId != null) {
String barCode = materialBarCodeMap.get(materialBaseInfoId);
if (StringUtils.isNotBlank(barCode)) {
receiptMaterialDetailPO.setBarCode(barCode);
}
}
}
if (!CollectionUtils.isEmpty(receiptMaterialDetailPO.getChildren())) {
fillBarCodeFromMaterialBarCodeRecursively(receiptMaterialDetailPO.getChildren(), materialBarCodeMap);
}
});
}
/**
* 递归清空质检相关字段(如果是否质检为否)
* @param receiptMaterialDetailPOList 收货物料明细列表
@@ -846,6 +923,9 @@ public class StockReceiptOrderApplicationService {
}
}
fillMaterialDetailUnitInfoRecursively(materialDetailList, materialBaseInfoMap, packDetailMap);
// 物料条码为空时取物料维护的条码信息第一行的 barCode
Map<Long, String> materialBarCodeMap = buildMaterialBarCodeMap(materialBaseInfoIdSet);
fillBarCodeFromMaterialBarCodeRecursively(materialDetailList, materialBarCodeMap);
}
return stockReceiptOrderPO;
}
@@ -961,9 +1041,8 @@ public class StockReceiptOrderApplicationService {
}
/**
* 收货时:将 children 中第一条parent_copy的值赋给主项1,并删除第一条;不合并数量,仅赋值替换
* getInfoByApp 有子项时会将 parent_copy 作为 children 第一条,PDA 可能不传 materialDetailId/uniqueId
* 故用 materialDetailId、uniqueId、materialBaseInfoId 综合判断,避免误合并真实子项导致第一条被覆盖。
* 收货时:将 children 中第一条的值赋给主项,并删除第一条。
* PDA 收两条时只生成 2 条(主项 + 第二条子项),主项展示第一条子项的数据。
*/
private void assignFirstChildToParentAndRemove(StockReceiptOrderDO stockReceiptOrderDO) {
List<ReceiptMaterialDetailDO> list = stockReceiptOrderDO.getMaterialDetailList();
@@ -976,14 +1055,10 @@ public class StockReceiptOrderApplicationService {
continue;
}
ReceiptMaterialDetailDO firstChild = children.get(0);
if (!isParentCopy(parent, firstChild)) {
// 第一条是真实子项,不合并,保留主项和子项各自独立
continue;
}
// 将 parent_copy 的值赋给主项(赋值替换,不合并数量)
// 将第一条子项的值赋给主项(含批次属性、收货数量等)
BeanUtils.copyProperties(firstChild, parent, "children", "parentUniqueId", "uniqueId", "materialDetailId",
"organizationIdList", "permissionMenuId", "receiptOrderNumberList", "compoundOrQuery");
// 删除 children 中的第一条parent_copy
// 删除 children 中的第一条
List<ReceiptMaterialDetailDO> newChildren = new ArrayList<>();
for (int i = 1; i < children.size(); i++) {
newChildren.add(children.get(i));
@@ -992,46 +1067,6 @@ public class StockReceiptOrderApplicationService {
}
}
/**
* 判断第一条子项是否为 parent_copy(主项拷贝,供 PDA 收货编辑用)。
* parent_copy 与主项同 materialDetailId/uniqueId/materialBaseInfoId;真实子项则不同。
* PDA 可能不传 materialDetailId/uniqueId/materialBaseInfoId,需综合判断。
*/
private boolean isParentCopy(ReceiptMaterialDetailDO parent, ReceiptMaterialDetailDO firstChild) {
Long parentId = parent.getMaterialDetailId();
Long firstChildId = firstChild.getMaterialDetailId();
Long parentUniqueId = parent.getUniqueId();
Long firstChildUniqueId = firstChild.getUniqueId();
Long parentBaseInfoId = parent.getMaterialBaseInfoId();
Long firstChildBaseInfoId = firstChild.getMaterialBaseInfoId();
// 1. materialDetailId 相同 → parent_copy
if (parentId != null && parentId.equals(firstChildId)) {
return true;
}
// 2. uniqueId 相同 → parent_copy
if (parentUniqueId != null && parentUniqueId.equals(firstChildUniqueId)) {
return true;
}
// 3. 子项有与主项不同的 materialDetailId → 真实子项
if (firstChildId != null && !firstChildId.equals(parentId)) {
return false;
}
// 4. 子项有与主项不同的 uniqueId → 真实子项
if (firstChildUniqueId != null && !firstChildUniqueId.equals(parentUniqueId)) {
return false;
}
// 5. 子项 materialBaseInfoId 与主项不同 → 真实子项(不同物料)
if (firstChildBaseInfoId != null && parentBaseInfoId != null && !firstChildBaseInfoId.equals(parentBaseInfoId)) {
return false;
}
// 6. 子项无 materialDetailId 且无 uniqueId:可能是新创建的子项(同一次收 250+250),不能视为 parent_copy
// 收货 getInfoByApp 不添加 parent_copyparent_copy 必有 materialDetailId 或 uniqueId 与主项相同
if (firstChildId == null && firstChildUniqueId == null) {
return false;
}
return false;
}
/**
* PDA 收货回传时,将 materialDetailList 的第一项作为主项(level 1),其余项作为其子项(level 2)
* 仅当数据库中第二项为 level 2(真实子项)时才转换,避免将两条平铺明细错误转为父子导致第一条被覆盖
@@ -1342,14 +1377,12 @@ public class StockReceiptOrderApplicationService {
orderLevelQuantity = orderLevelQuantity.add(childReceiptQty);
}
}
// 主项本次收货增量 = 新子项数量 + 已存在子项增量;若均为 0 则使用主项 receiptQuantity 或子项合计(再次收货时 PDA 传相同值,主项可能为 0)
// 主项本次收货增量 = 主项 receiptQuantity(含 assignFirstChildToParentAndRemove 合并的第一条子项)+ 其余子项合计
// 无子项时使用主项 receiptQuantity
BigDecimal childrenTotalIncrement = newChildrenTotalQuantity.add(existingChildrenIncrement);
mainItemActualQuantity = CollectionUtils.isEmpty(receiptMaterialDetailDOChildList)
? receiptQuantity
: (childrenTotalIncrement.compareTo(BigDecimal.ZERO) > 0
? childrenTotalIncrement
: (receiptQuantity.compareTo(BigDecimal.ZERO) > 0 ? receiptQuantity : childrenTotalQuantity));
: receiptQuantity.add(childrenTotalIncrement);
//主项已收货数量 = 原有 + 主项本次收货增量
receiptMaterialDetailDO.setAlreadyReceiptQuantity(receiptMaterialDetailPO.getAlreadyReceiptQuantity().add(mainItemActualQuantity));
//记录本次收货单收货总数(主项+子项合计,用于收货单级统计)
@@ -311,15 +311,16 @@ public class HandoverTaskOrderDomainService {
inventoryAdjustmentRecord.setFreezeAfterQuantity(newFreezeQuantity);
inventoryAdjustmentRecord.setInventoryBeforeQuantity(oldInventoryQuantity);
inventoryAdjustmentRecord.setInventoryAfterQuantity(newInventoryQuantity);
inventoryAdjustmentRecord.setNetWeight(outMaterialDetail.getTotalNetWeight() == null ? BigDecimal.ZERO : outMaterialDetail.getTotalNetWeight());
inventoryAdjustmentRecord.setGrossWeight(outMaterialDetail.getTotalGrossWeight() == null ? BigDecimal.ZERO : outMaterialDetail.getTotalGrossWeight());
inventoryAdjustmentRecord.setVolume(outMaterialDetail.getTotalVolume() == null ? BigDecimal.ZERO : outMaterialDetail.getTotalVolume());
inventoryAdjustmentRecord.setArea(outMaterialDetail.getTotalArea() == null ? BigDecimal.ZERO : outMaterialDetail.getTotalArea());
inventoryAdjustmentRecord.setAdjustedNetWeight(materialInventoryPO.getNetWeight());
inventoryAdjustmentRecord.setAdjustedGrossWeight(materialInventoryPO.getGrossWeight());
inventoryAdjustmentRecord.setAdjustedVolume(materialInventoryPO.getVolume() );
inventoryAdjustmentRecord.setAdjustedArea(materialInventoryPO.getArea() );
// 调整前库存数量净重毛重体积面积
inventoryAdjustmentRecord.setNetWeight(oldNetWeight);
inventoryAdjustmentRecord.setGrossWeight(oldGrossWeight);
inventoryAdjustmentRecord.setVolume(oldVolume);
inventoryAdjustmentRecord.setArea(oldArea);
// 调整后库存数量 - 复核时填写的数量
inventoryAdjustmentRecord.setAdjustedNetWeight(newNetWeight);
inventoryAdjustmentRecord.setAdjustedGrossWeight(newGrossWeight);
inventoryAdjustmentRecord.setAdjustedVolume(newVolume);
inventoryAdjustmentRecord.setAdjustedArea(newArea);
inventoryAdjustmentRecordMapper.insert(inventoryAdjustmentRecord);
}
@@ -103,20 +103,9 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
{
List<ReceiptMaterialDetailPO> receiptMaterialDetailPOList = receiptMaterialDetailMapper.queryList(receiptMaterialDetailDO);
//回显带上更多属性值
//回显带上更多属性值始终以物料绑定的批次属性为结构合并 material_more_detail 中已填写的值
receiptMaterialDetailPOList.forEach(receiptMaterialDetailPO -> {
MaterialMoreDetailDO materialMoreDetailDO = new MaterialMoreDetailDO();
materialMoreDetailDO.setMaterialDetailUniqueId(receiptMaterialDetailPO.getUniqueId());
List<MaterialMoreDetailPO> materialMoreDetailList = IMaterialMoreDetailService.queryList(materialMoreDetailDO);
//如果收货单的物料批属性还没存入值那么需要从批属性表获取
AjaxResult ajaxResult = null;
if (CollectionUtils.isEmpty(materialMoreDetailList)) {
ajaxResult = systemServiceFeign.getBatchDetailListByMaterialBaseInfoId(receiptMaterialDetailPO.getMaterialBaseInfoId());
if (ajaxResult != null && "200".equals(String.valueOf(ajaxResult.get("code")))) {
List<BatchDetailFeignPO> batchList = JSON.parseArray(JSONObject.toJSONString(ajaxResult.get("data")), BatchDetailFeignPO.class);
materialMoreDetailList = filterAndConvertToMaterialMoreDetail(batchList);
}
}
List<MaterialMoreDetailPO> materialMoreDetailList = buildMaterialMoreDetailListByMaterialBinding(receiptMaterialDetailPO);
// 从入库单明细表中获取InvoiceNoBatchRefNoSheetRefNoBoxPalletNo字段的值
fillAttributeValueFromInMaterialDetail(receiptMaterialDetailPO, materialMoreDetailList);
receiptMaterialDetailPO.setMaterialMoreDetailList(materialMoreDetailList);
@@ -137,18 +126,7 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
for(ReceiptMaterialDetailPO materialDetailPO :receiptMaterialDetailPOParentList){
List<ReceiptMaterialDetailPO> children = getChildren(materialDetailPO.getUniqueId(), materialDetailPO.getInUniqueId(), receiptMaterialDetailPOList, 2);
children.forEach(childrenDetailPO -> {
MaterialMoreDetailDO materialMoreDetailDO = new MaterialMoreDetailDO();
materialMoreDetailDO.setMaterialDetailUniqueId(childrenDetailPO.getUniqueId());
List<MaterialMoreDetailPO> materialMoreDetailList = IMaterialMoreDetailService.queryList(materialMoreDetailDO);
//如果收货单的物料批属性还没存入值那么需要从批属性表获取
AjaxResult ajaxResult = null;
if (CollectionUtils.isEmpty(materialMoreDetailList)) {
ajaxResult = systemServiceFeign.getBatchDetailListByMaterialBaseInfoId(childrenDetailPO.getMaterialBaseInfoId());
if (ajaxResult != null && "200".equals(String.valueOf(ajaxResult.get("code")))) {
List<BatchDetailFeignPO> batchList = JSON.parseArray(JSONObject.toJSONString(ajaxResult.get("data")), BatchDetailFeignPO.class);
materialMoreDetailList = filterAndConvertToMaterialMoreDetail(batchList);
}
}
List<MaterialMoreDetailPO> materialMoreDetailList = buildMaterialMoreDetailListByMaterialBinding(childrenDetailPO);
// 从入库单明细表中获取InvoiceNoBatchRefNoSheetRefNoBoxPalletNo字段的值
fillAttributeValueFromInMaterialDetail(childrenDetailPO, materialMoreDetailList);
childrenDetailPO.setMaterialMoreDetailList(materialMoreDetailList);
@@ -176,6 +154,52 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
}
}
/**
* 根据物料绑定的批次属性构建更多属性列表并合并 material_more_detail 中已填写的值
* 始终以物料绑定为准确保收货查询时批次属性按物料绑定显示
*/
private List<MaterialMoreDetailPO> buildMaterialMoreDetailListByMaterialBinding(ReceiptMaterialDetailPO receiptMaterialDetailPO) {
List<MaterialMoreDetailPO> result = new ArrayList<>();
Long materialBaseInfoId = receiptMaterialDetailPO != null ? receiptMaterialDetailPO.getMaterialBaseInfoId() : null;
if (materialBaseInfoId == null) {
return result;
}
try {
AjaxResult ajaxResult = systemServiceFeign.getBatchDetailListByMaterialBaseInfoId(materialBaseInfoId);
if (ajaxResult == null || !"200".equals(String.valueOf(ajaxResult.get("code")))) {
return result;
}
List<BatchDetailFeignPO> batchList = JSON.parseArray(JSONObject.toJSONString(ajaxResult.get("data")), BatchDetailFeignPO.class);
result = filterAndConvertToMaterialMoreDetail(batchList);
if (CollectionUtils.isEmpty(result)) {
return result;
}
// 合并 material_more_detail 中已填写的 attributeValue batchDetailId 匹配
Long uniqueId = receiptMaterialDetailPO.getUniqueId();
if (uniqueId != null) {
MaterialMoreDetailDO materialMoreDetailDO = new MaterialMoreDetailDO();
materialMoreDetailDO.setMaterialDetailUniqueId(uniqueId);
List<MaterialMoreDetailPO> savedList = IMaterialMoreDetailService.queryList(materialMoreDetailDO);
if (!CollectionUtils.isEmpty(savedList)) {
Map<Long, String> batchDetailIdToValue = new HashMap<>();
for (MaterialMoreDetailPO saved : savedList) {
if (saved.getBatchDetailId() != null && StringUtils.isNotBlank(saved.getAttributeValue())) {
batchDetailIdToValue.put(saved.getBatchDetailId(), saved.getAttributeValue());
}
}
for (MaterialMoreDetailPO mpo : result) {
if (mpo.getBatchDetailId() != null && batchDetailIdToValue.containsKey(mpo.getBatchDetailId())) {
mpo.setAttributeValue(batchDetailIdToValue.get(mpo.getBatchDetailId()));
}
}
}
}
} catch (Exception e) {
log.warn("构建物料批次属性失败,materialBaseInfoId{},错误:{}", materialBaseInfoId, e.getMessage());
}
return result;
}
/**
* 过滤 isDisplay=1 的批次属性并转换为 MaterialMoreDetailPO PC getInfo 一致
*/
@@ -41,6 +41,11 @@ public interface IStockOutTaskOrderService extends IService<StockOutTaskOrder>
*/
public StockOutTaskOrderPO getInfo(Long outTaskOrderId);
/**
* 查询拣货作业单并加行锁防止并发重复拣货
*/
public StockOutTaskOrderPO getInfoForUpdate(Long outTaskOrderId);
/**
* @description 生成拣货作业单
* @author ZhouGY
@@ -1,5 +1,6 @@
package com.mhd.wms.domain.stockOutTaskOrder.repository.persistence;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mhd.common.core.constant.SnowFlakeConstants;
@@ -94,6 +95,20 @@ public class StockOutTaskOrderImpl extends ServiceImpl<StockOutTaskOrderMapper,
return stockOutTaskOrderPO;
}
@Override
public StockOutTaskOrderPO getInfoForUpdate(Long outTaskOrderId) {
StockOutTaskOrder stockOutTaskOrder = this.getOne(new QueryWrapper<StockOutTaskOrder>()
.eq("out_task_order_id", outTaskOrderId)
.eq("del_flag", 1)
.last("FOR UPDATE"));
if (stockOutTaskOrder == null) {
return null;
}
StockOutTaskOrderPO stockOutTaskOrderPO = new StockOutTaskOrderPO();
BeanUtils.copyProperties(stockOutTaskOrder, stockOutTaskOrderPO);
return stockOutTaskOrderPO;
}
/**
* @description 生成拣货作业单
* @author ZhouGY
@@ -269,7 +269,8 @@ public class StockOutTaskOrderDomainService {
if (ObjectUtil.isNull(stockOutTaskOrderDO.getUpdateTime())){
throw new ServiceException("拣货单修改时间不能为空");
}
StockOutTaskOrderPO stockOutTaskOrderPODb = stockOutTaskOrderService.getInfo(stockOutTaskOrderDO.getOutTaskOrderId());
// 加行锁防止并发重复拣货
StockOutTaskOrderPO stockOutTaskOrderPODb = stockOutTaskOrderService.getInfoForUpdate(stockOutTaskOrderDO.getOutTaskOrderId());
if (stockOutTaskOrderPODb == null){
throw new ServiceException("拣货单不存在");
}
@@ -377,8 +378,9 @@ public class StockOutTaskOrderDomainService {
if (ObjectUtil.isNull(stockOutTaskOrderPO)){
throw new ServiceException("部分拣货拣货数量不能为空");
}
pickingQuantity = stockOutTaskOrderPO.getPickingQuantity().add(stockOutTaskOrderPO.getPickingQuantity());
pickingMaterialQuantity = stockOutTaskOrderPO.getPickingMaterialQuantity() + stockOutTaskOrderPO.getPickingMaterialQuantity();
// 本批次增量 + 原已拣货数量避免重复累加导致拣货数量翻倍
pickingQuantity = (stockOutTaskOrderPODb.getPickingQuantity() != null ? stockOutTaskOrderPODb.getPickingQuantity() : BigDecimal.ZERO).add(stockOutTaskOrderPO.getPickingQuantity() != null ? stockOutTaskOrderPO.getPickingQuantity() : BigDecimal.ZERO);
pickingMaterialQuantity = (stockOutTaskOrderPODb.getPickingMaterialQuantity() != null ? stockOutTaskOrderPODb.getPickingMaterialQuantity() : 0) + (stockOutTaskOrderPO.getPickingMaterialQuantity() != null ? stockOutTaskOrderPO.getPickingMaterialQuantity() : 0);
actualPickingQuantity = stockOutTaskOrderPO.getPickingQuantity();
actualPickingMaterialQuantity = stockOutTaskOrderPO.getPickingMaterialQuantity();
}
@@ -209,11 +209,6 @@ public class StockReceiptOrderDomainService {
List<InMaterialDetailSerialNumberPO> inMaterialDetailSerialNumberPOList = inMaterialDetailSerialNumberService.queryList(inMaterialDetailSerialNumberDO);
Map<Long, List<InMaterialDetailSerialNumberPO>> inMaterialDetailSerialNumberMap = inMaterialDetailSerialNumberPOList.stream()
.collect(Collectors.groupingBy(InMaterialDetailSerialNumberPO::getMaterialDetailUniqueId));
MaterialMoreDetailDO materialMoreDetailDO = new MaterialMoreDetailDO();
materialMoreDetailDO.setOrderNumber(stockReceiptOrderPO.getReceiptOrderNumber());
List<MaterialMoreDetailPO> materialMoreDetailPOList = iMaterialMoreDetailService.queryList(materialMoreDetailDO);
Map<Long, List<MaterialMoreDetailPO>> materialMoreDetailMap = materialMoreDetailPOList.stream()
.collect(Collectors.groupingBy(MaterialMoreDetailPO::getMaterialDetailUniqueId));
receiptMaterialDetailPOList.forEach(receiptMaterialDetailPO -> {
//子集level 2 的真实子项PDA 端不添加 parent_copy PC 端一致避免主项重复展示
List<ReceiptMaterialDetailPO> receiptMaterialDetailPOChildrenList = receiptMaterialDetailPO.getChildren();
@@ -225,14 +220,12 @@ public class StockReceiptOrderDomainService {
} else {
receiptMaterialDetailPOChildren.setMaterialDetailSerialNumberList(new ArrayList<>());
}
List<MaterialMoreDetailPO> materialMoreDetailChildrenList = materialMoreDetailMap.get(receiptMaterialDetailPOChildren.getUniqueId());
if (!CollectionUtils.isEmpty(materialMoreDetailChildrenList)) {
receiptMaterialDetailPOChildren.setMaterialMoreDetailList(materialMoreDetailChildrenList);
} else if (CollectionUtils.isEmpty(receiptMaterialDetailPOChildren.getMaterialMoreDetailList())) {
// material_more_detail 表无记录时queryListChildren 已填充 attributeValue仅当子项本身无批次属性时才从物料获取
// queryListChildren 已按物料绑定构建批次属性并合并 material_more_detail 的值不再用 materialMoreDetailMap 覆盖避免批次属性与物料绑定不一致
if (CollectionUtils.isEmpty(receiptMaterialDetailPOChildren.getMaterialMoreDetailList())) {
receiptMaterialDetailPOChildren.setMaterialMoreDetailList(getMaterialMoreDetail(receiptMaterialDetailPOChildren));
}
// 否则保留 queryListChildren 已填充的 materialMoreDetailList BatchRefNoSheetRefNoBoxPalletNo attributeValue
// 子行计划数量不需要显示
receiptMaterialDetailPOChildren.setQuantity(null);
});
} else {
// 主项无子项时点击分批收货前确保主项也有批次属性否则 PDA 不显示
@@ -868,57 +861,57 @@ public class StockReceiptOrderDomainService {
stockShelfOrderDO.setStatus(1);
List<ShelfMaterialDetailDO> shelfMaterialDetailDOList = new ArrayList<>();
stockReceiptOrderDO.getMaterialDetailList().forEach(receiptMaterialDetailDO -> {
// 如果已收货数量为0跳过该明细不生成上架单明细任务
if (receiptMaterialDetailDO.getReceiptQuantity() == null ||
receiptMaterialDetailDO.getReceiptQuantity().compareTo(BigDecimal.ZERO) <= 0) {
boolean parentHasReceipt = receiptMaterialDetailDO.getReceiptQuantity() != null
&& receiptMaterialDetailDO.getReceiptQuantity().compareTo(BigDecimal.ZERO) > 0;
boolean hasChildrenWithReceipt = receiptMaterialDetailDO.getChildren() != null
&& !receiptMaterialDetailDO.getChildren().isEmpty()
&& receiptMaterialDetailDO.getChildren().stream().anyMatch(c ->
c.getReceiptQuantity() != null && c.getReceiptQuantity().compareTo(BigDecimal.ZERO) > 0);
// 主项和子项均无收货数量时跳过
if (!parentHasReceipt && !hasChildrenWithReceipt) {
return;
}
ShelfMaterialDetailDO shelfMaterialDetailDO = new ShelfMaterialDetailDO();
BeanUtils.copyProperties(receiptMaterialDetailDO, shelfMaterialDetailDO);
shelfMaterialDetailDO.setQuantity(receiptMaterialDetailDO.getReceiptQuantity());
shelfMaterialDetailDO.setInUniqueId(receiptMaterialDetailDO.getInUniqueId());
shelfMaterialDetailDO.setReceiptUniqueId(receiptMaterialDetailDO.getUniqueId());
// 传递生产日期过期日期存货日期Batch Ref NO'sSheet Ref NO's箱号/卡板号扩展属性1-4
shelfMaterialDetailDO.setProductionDate(receiptMaterialDetailDO.getProductionDate());
shelfMaterialDetailDO.setTotalArea(receiptMaterialDetailDO.getTotalArea());
shelfMaterialDetailDO.setTotalVolume(receiptMaterialDetailDO.getTotalVolume());
shelfMaterialDetailDO.setTotalNetWeight(receiptMaterialDetailDO.getTotalNetWeight());
shelfMaterialDetailDO.setTotalGrossWeight(receiptMaterialDetailDO.getTotalGrossWeight());
shelfMaterialDetailDO.setExpiryDate(receiptMaterialDetailDO.getExpiryDate());
shelfMaterialDetailDO.setInventoryDate(receiptMaterialDetailDO.getInventoryDate());
shelfMaterialDetailDO.setBatchRefNo(receiptMaterialDetailDO.getBatchRefNo());
shelfMaterialDetailDO.setSheetRefNo(receiptMaterialDetailDO.getSheetRefNo());
shelfMaterialDetailDO.setBoxPalletNo(receiptMaterialDetailDO.getBoxPalletNo());
shelfMaterialDetailDO.setExtAttr1(receiptMaterialDetailDO.getExtAttr1());
shelfMaterialDetailDO.setExtAttr2(receiptMaterialDetailDO.getExtAttr2());
// extAttr3和extAttr4在ReceiptMaterialDetailDO中是String类型在ShelfMaterialDetailDO中是Date类型需要转换
if (receiptMaterialDetailDO.getExtAttr3() != null && !receiptMaterialDetailDO.getExtAttr3().isEmpty()) {
try {
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
shelfMaterialDetailDO.setExtAttr3(sdf.parse(receiptMaterialDetailDO.getExtAttr3()));
} catch (Exception e) {
// 如果转换失败不设置该字段
// 主项有收货数量时生成一条上架明细
if (parentHasReceipt) {
ShelfMaterialDetailDO shelfMaterialDetailDO = new ShelfMaterialDetailDO();
BeanUtils.copyProperties(receiptMaterialDetailDO, shelfMaterialDetailDO);
shelfMaterialDetailDO.setQuantity(receiptMaterialDetailDO.getReceiptQuantity());
shelfMaterialDetailDO.setInUniqueId(receiptMaterialDetailDO.getInUniqueId());
shelfMaterialDetailDO.setReceiptUniqueId(receiptMaterialDetailDO.getUniqueId());
shelfMaterialDetailDO.setProductionDate(receiptMaterialDetailDO.getProductionDate());
shelfMaterialDetailDO.setTotalArea(receiptMaterialDetailDO.getTotalArea());
shelfMaterialDetailDO.setTotalVolume(receiptMaterialDetailDO.getTotalVolume());
shelfMaterialDetailDO.setTotalNetWeight(receiptMaterialDetailDO.getTotalNetWeight());
shelfMaterialDetailDO.setTotalGrossWeight(receiptMaterialDetailDO.getTotalGrossWeight());
shelfMaterialDetailDO.setExpiryDate(receiptMaterialDetailDO.getExpiryDate());
shelfMaterialDetailDO.setInventoryDate(receiptMaterialDetailDO.getInventoryDate());
shelfMaterialDetailDO.setBatchRefNo(receiptMaterialDetailDO.getBatchRefNo());
shelfMaterialDetailDO.setSheetRefNo(receiptMaterialDetailDO.getSheetRefNo());
shelfMaterialDetailDO.setBoxPalletNo(receiptMaterialDetailDO.getBoxPalletNo());
shelfMaterialDetailDO.setExtAttr1(receiptMaterialDetailDO.getExtAttr1());
shelfMaterialDetailDO.setExtAttr2(receiptMaterialDetailDO.getExtAttr2());
if (receiptMaterialDetailDO.getExtAttr3() != null && !receiptMaterialDetailDO.getExtAttr3().isEmpty()) {
try {
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
shelfMaterialDetailDO.setExtAttr3(sdf.parse(receiptMaterialDetailDO.getExtAttr3()));
} catch (Exception e) { }
}
}
if (receiptMaterialDetailDO.getExtAttr4() != null && !receiptMaterialDetailDO.getExtAttr4().isEmpty()) {
try {
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
shelfMaterialDetailDO.setExtAttr4(sdf.parse(receiptMaterialDetailDO.getExtAttr4()));
} catch (Exception e) {
// 如果转换失败不设置该字段
if (receiptMaterialDetailDO.getExtAttr4() != null && !receiptMaterialDetailDO.getExtAttr4().isEmpty()) {
try {
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
shelfMaterialDetailDO.setExtAttr4(sdf.parse(receiptMaterialDetailDO.getExtAttr4()));
} catch (Exception e) { }
}
shelfMaterialDetailDOList.add(shelfMaterialDetailDO);
}
// 处理子项如果子项的已收货数量为0跳过该子项
if (receiptMaterialDetailDO.getChildren() != null && !receiptMaterialDetailDO.getChildren().isEmpty()) {
// 子项有收货数量时每个子项生成一条上架明细一明细两子项 两条上架明细
if (hasChildrenWithReceipt && receiptMaterialDetailDO.getChildren() != null) {
receiptMaterialDetailDO.getChildren().forEach(receiptMaterialDetailDOChildren -> {
// 如果子项的已收货数量为0跳过该子项不生成上架单明细任务
if (receiptMaterialDetailDOChildren.getReceiptQuantity() == null ||
receiptMaterialDetailDOChildren.getReceiptQuantity().compareTo(BigDecimal.ZERO) <= 0) {
return;
}
ShelfMaterialDetailDO shelfMaterialDetailDOChildren = new ShelfMaterialDetailDO();
BeanUtils.copyProperties(receiptMaterialDetailDOChildren, shelfMaterialDetailDOChildren);
shelfMaterialDetailDOChildren.setQuantity(receiptMaterialDetailDOChildren.getReceiptQuantity());
@@ -928,7 +921,6 @@ public class StockReceiptOrderDomainService {
shelfMaterialDetailDOChildren.setTotalVolume(receiptMaterialDetailDOChildren.getTotalVolume());
shelfMaterialDetailDOChildren.setTotalNetWeight(receiptMaterialDetailDOChildren.getTotalNetWeight());
shelfMaterialDetailDOChildren.setTotalGrossWeight(receiptMaterialDetailDOChildren.getTotalGrossWeight());
// 传递生产日期过期日期存货日期Batch Ref NO'sSheet Ref NO's箱号/卡板号扩展属性1-4
shelfMaterialDetailDOChildren.setProductionDate(receiptMaterialDetailDOChildren.getProductionDate());
shelfMaterialDetailDOChildren.setExpiryDate(receiptMaterialDetailDOChildren.getExpiryDate());
shelfMaterialDetailDOChildren.setInventoryDate(receiptMaterialDetailDOChildren.getInventoryDate());
@@ -937,27 +929,21 @@ public class StockReceiptOrderDomainService {
shelfMaterialDetailDOChildren.setBoxPalletNo(receiptMaterialDetailDOChildren.getBoxPalletNo());
shelfMaterialDetailDOChildren.setExtAttr1(receiptMaterialDetailDOChildren.getExtAttr1());
shelfMaterialDetailDOChildren.setExtAttr2(receiptMaterialDetailDOChildren.getExtAttr2());
// extAttr3和extAttr4在ReceiptMaterialDetailDO中是String类型在ShelfMaterialDetailDO中是Date类型需要转换
if (receiptMaterialDetailDOChildren.getExtAttr3() != null && !receiptMaterialDetailDOChildren.getExtAttr3().isEmpty()) {
try {
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
shelfMaterialDetailDOChildren.setExtAttr3(sdf.parse(receiptMaterialDetailDOChildren.getExtAttr3()));
} catch (Exception e) {
// 如果转换失败不设置该字段
}
} catch (Exception e) { }
}
if (receiptMaterialDetailDOChildren.getExtAttr4() != null && !receiptMaterialDetailDOChildren.getExtAttr4().isEmpty()) {
try {
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
shelfMaterialDetailDOChildren.setExtAttr4(sdf.parse(receiptMaterialDetailDOChildren.getExtAttr4()));
} catch (Exception e) {
// 如果转换失败不设置该字段
}
} catch (Exception e) { }
}
shelfMaterialDetailDOList.add(shelfMaterialDetailDOChildren);
});
}
shelfMaterialDetailDOList.add(shelfMaterialDetailDO);
});
stockShelfOrderDO.setMaterialDetailList(shelfMaterialDetailDOList);
stockShelfOrderDO.setMaterialQuantity(shelfMaterialDetailDOList.size());
@@ -1055,18 +1041,46 @@ public class StockReceiptOrderDomainService {
shelfMaterialDetailDOList.add(shelfMaterialDetailDO);
receiptQuantity = receiptQuantity.add(receiptMaterialDetailPO.getReceiptQuantity());
}
//
// for (ReceiptMaterialDetailPO receiptMaterialDetailPOChildren : receiptMaterialDetailPO.getChildren()) {
// if (2 == receiptMaterialDetailPO.getGenStockShelf()) {
// ShelfMaterialDetailDO shelfMaterialDetailDOChildren = new ShelfMaterialDetailDO();
// BeanUtils.copyProperties(receiptMaterialDetailPOChildren, shelfMaterialDetailDOChildren);
// shelfMaterialDetailDOChildren.setQuantity(receiptMaterialDetailPOChildren.getReceiptQuantity());
// shelfMaterialDetailDOChildren.setInUniqueId(receiptMaterialDetailPOChildren.getInUniqueId());
// shelfMaterialDetailDOChildren.setReceiptUniqueId(receiptMaterialDetailPOChildren.getUniqueId());
// shelfMaterialDetailDOList.add(shelfMaterialDetailDOChildren);
// receiptQuantity = receiptQuantity.add(receiptMaterialDetailPO.getReceiptQuantity());
// }
// }
// 子项有收货数量时每个子项生成一条上架明细一明细两子项 两条上架明细
if (2 == receiptMaterialDetailPO.getGenStockShelf() && !CollectionUtils.isEmpty(receiptMaterialDetailPO.getChildren())) {
for (ReceiptMaterialDetailPO receiptMaterialDetailPOChildren : receiptMaterialDetailPO.getChildren()) {
if (receiptMaterialDetailPOChildren.getReceiptQuantity() == null ||
receiptMaterialDetailPOChildren.getReceiptQuantity().compareTo(BigDecimal.ZERO) <= 0) {
continue;
}
ShelfMaterialDetailDO shelfMaterialDetailDOChildren = new ShelfMaterialDetailDO();
BeanUtils.copyProperties(receiptMaterialDetailPOChildren, shelfMaterialDetailDOChildren);
shelfMaterialDetailDOChildren.setQuantity(receiptMaterialDetailPOChildren.getReceiptQuantity());
shelfMaterialDetailDOChildren.setInUniqueId(receiptMaterialDetailPO.getInUniqueId());
shelfMaterialDetailDOChildren.setReceiptUniqueId(receiptMaterialDetailPO.getUniqueId());
shelfMaterialDetailDOChildren.setTotalArea(receiptMaterialDetailPOChildren.getTotalArea());
shelfMaterialDetailDOChildren.setTotalVolume(receiptMaterialDetailPOChildren.getTotalVolume());
shelfMaterialDetailDOChildren.setTotalNetWeight(receiptMaterialDetailPOChildren.getTotalNetWeight());
shelfMaterialDetailDOChildren.setTotalGrossWeight(receiptMaterialDetailPOChildren.getTotalGrossWeight());
shelfMaterialDetailDOChildren.setProductionDate(receiptMaterialDetailPOChildren.getProductionDate());
shelfMaterialDetailDOChildren.setExpiryDate(receiptMaterialDetailPOChildren.getExpiryDate());
shelfMaterialDetailDOChildren.setInventoryDate(receiptMaterialDetailPOChildren.getInventoryDate());
shelfMaterialDetailDOChildren.setBatchRefNo(receiptMaterialDetailPOChildren.getBatchRefNo());
shelfMaterialDetailDOChildren.setSheetRefNo(receiptMaterialDetailPOChildren.getSheetRefNo());
shelfMaterialDetailDOChildren.setBoxPalletNo(receiptMaterialDetailPOChildren.getBoxPalletNo());
shelfMaterialDetailDOChildren.setExtAttr1(receiptMaterialDetailPOChildren.getExtAttr1());
shelfMaterialDetailDOChildren.setExtAttr2(receiptMaterialDetailPOChildren.getExtAttr2());
if (receiptMaterialDetailPOChildren.getExtAttr3() != null && !receiptMaterialDetailPOChildren.getExtAttr3().isEmpty()) {
try {
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
shelfMaterialDetailDOChildren.setExtAttr3(sdf.parse(receiptMaterialDetailPOChildren.getExtAttr3()));
} catch (Exception e) { }
}
if (receiptMaterialDetailPOChildren.getExtAttr4() != null && !receiptMaterialDetailPOChildren.getExtAttr4().isEmpty()) {
try {
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
shelfMaterialDetailDOChildren.setExtAttr4(sdf.parse(receiptMaterialDetailPOChildren.getExtAttr4()));
} catch (Exception e) { }
}
shelfMaterialDetailDOList.add(shelfMaterialDetailDOChildren);
receiptQuantity = receiptQuantity.add(receiptMaterialDetailPOChildren.getReceiptQuantity());
}
}
}
if(shelfMaterialDetailDOList.isEmpty()){
throw new ServiceException("不存在需要生成上架单的收货记录!");
@@ -162,7 +162,8 @@ public class TaskPickingMaterialDetailImpl extends ServiceImpl<TaskPickingMateri
}
PickingMaterialDetailDO pickingMaterialDetailDO = new PickingMaterialDetailDO();
pickingMaterialDetailDO.setUniqueId(taskPickingMaterialDetailDb.getPickingUniqueId());
pickingMaterialDetailDO.setPickingQuantity(taskPickingMaterialDetailDO.getPickingQuantity());
// 拣货增量用 actualQuantitypicking_quantity += actualQuantity
pickingMaterialDetailDO.setPickingQuantity(taskPickingMaterialDetailDO.getActualQuantity() != null ? taskPickingMaterialDetailDO.getActualQuantity() : BigDecimal.ZERO);
pickingMaterialDetailList.add(pickingMaterialDetailDO);
totalPickingQuantity = totalPickingQuantity.add(taskPickingMaterialDetailDO.getActualQuantity());
}
@@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.mhd.common.core.annotation.Excel;
import com.mhd.common.core.web.domain.BaseVOEntity;
import com.mhd.wms.domain.materialMoreDetail.repository.po.MaterialMoreDetailPO;
import com.mhd.wms.domain.outMaterialDetailSerialNumber.repository.po.OutMaterialDetailSerialNumberPO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@@ -204,4 +205,19 @@ public class TaskPickingMaterialDetailPO extends BaseVOEntity {
@ApiModelProperty("序列号")
private List<OutMaterialDetailSerialNumberPO> materialDetailSerialNumberList;
@ApiModelProperty("更多属性(批次属性,按物料绑定动态显示)")
private List<MaterialMoreDetailPO> materialMoreDetailList;
@ApiModelProperty("总净重(KG)")
private BigDecimal totalNetWeight;
@ApiModelProperty("总毛重(KG)")
private BigDecimal totalGrossWeight;
@ApiModelProperty("总体积(CBM)")
private BigDecimal totalVolume;
@ApiModelProperty("总面积(SQM)")
private BigDecimal totalArea;
}
@@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.mhd.common.core.annotation.Excel;
import com.mhd.common.core.web.domain.BaseVOEntity;
import com.mhd.wms.domain.materialMoreDetail.repository.po.MaterialMoreDetailPO;
import com.mhd.wms.domain.outMaterialDetailSerialNumber.repository.todo.OutMaterialDetailSerialNumberDO;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -213,4 +214,19 @@ public class TaskPickingMaterialDetailDTO extends BaseVOEntity {
@ApiModelProperty("作业数量:拣货数量")
@Excel(name = "作业数量:拣货数量")
private BigDecimal actualQuantity;
@ApiModelProperty("更多属性(批次属性)")
private List<MaterialMoreDetailPO> materialMoreDetailList;
@ApiModelProperty("总净重(KG)")
private BigDecimal totalNetWeight;
@ApiModelProperty("总毛重(KG)")
private BigDecimal totalGrossWeight;
@ApiModelProperty("总体积(CBM)")
private BigDecimal totalVolume;
@ApiModelProperty("总面积(SQM)")
private BigDecimal totalArea;
}
@@ -203,7 +203,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<set>
<trim prefix="picking_quantity = CASE unique_id" suffix="END,">
<foreach collection="pickingMaterialDetailList" item="item" index="index">
WHEN #{item.uniqueId} THEN picking_quantity + #{item.pickingQuantity}
WHEN #{item.uniqueId} THEN LEAST(picking_quantity + #{item.pickingQuantity}, quantity)
</foreach>
</trim>
update_by = #{updateBy},
@@ -149,7 +149,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<update id="addQuantity" parameterType="com.mhd.wms.domain.pickingOrder.repository.todo.PickingOrderDO" >
UPDATE picking_order
<set>
picking_quantity = picking_quantity + #{pickingQuantity},
picking_quantity = LEAST(picking_quantity + #{pickingQuantity}, quantity),
picking_material_quantity = picking_material_quantity + #{pickingMaterialQuantity},
status = #{status},
update_by = #{updateBy},