PDA抄码修改
This commit is contained in:
+20
-1
@@ -2269,6 +2269,21 @@ public class StockReceiptOrderApplicationService {
|
||||
line.setTotalArea(null);
|
||||
line.setLevel(1);
|
||||
line.setParentUniqueId(null);
|
||||
// 本次抄码/托盘等已落到子行;若不清理主行,assemble 会用请求覆盖库中主行,导致第二笔冲掉第一笔抄码展示(与 batch_number 特例同因)
|
||||
clearPdaParentCopyCodeFieldsAfterSyntheticChildSplit(line);
|
||||
}
|
||||
|
||||
/**
|
||||
* PDA 分批拆子行后,主行仅保留计划行与首笔/累计已收;抄码实绩只在子行,主行抄码字段勿带入第二次请求的覆盖值。
|
||||
*/
|
||||
private static void clearPdaParentCopyCodeFieldsAfterSyntheticChildSplit(ReceiptMaterialDetailDO line) {
|
||||
if (line == null) {
|
||||
return;
|
||||
}
|
||||
line.setPalletNumber(null);
|
||||
line.setCopyBatch(null);
|
||||
line.setCopyQuantity(null);
|
||||
line.setCopyDetails(null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3147,10 +3162,14 @@ public class StockReceiptOrderApplicationService {
|
||||
ReceiptMaterialDetailDO returnReceiptMaterialDetailDO = new ReceiptMaterialDetailDO();
|
||||
BeanUtils.copyProperties(receiptMaterialDetailPO, returnReceiptMaterialDetailDO);
|
||||
BeanUtils.copyProperties(receiptMaterialDetailDO, returnReceiptMaterialDetailDO, IgnoreNullUtil.getNullPropertyNames(receiptMaterialDetailDO));
|
||||
// 主行本次收货件数为 0、仅子行有收货时:不从请求覆盖主行批次号(避免 PDA 把子行新批次回写到主行,冲掉首笔批次)
|
||||
// 主行本次收货件数为 0、仅子行有收货时:不从请求覆盖主行批次号/抄码托盘等(避免 PDA 把子行新批次或第二笔抄码回写到主行,冲掉首笔)
|
||||
if (mainItemActualQuantity.compareTo(BigDecimal.ZERO) == 0
|
||||
&& !CollectionUtils.isEmpty(returnReceiptMaterialDetailDOChildList)) {
|
||||
returnReceiptMaterialDetailDO.setBatchNumber(receiptMaterialDetailPO.getBatchNumber());
|
||||
returnReceiptMaterialDetailDO.setPalletNumber(receiptMaterialDetailPO.getPalletNumber());
|
||||
returnReceiptMaterialDetailDO.setCopyBatch(receiptMaterialDetailPO.getCopyBatch());
|
||||
returnReceiptMaterialDetailDO.setCopyQuantity(receiptMaterialDetailPO.getCopyQuantity());
|
||||
returnReceiptMaterialDetailDO.setCopyDetails(receiptMaterialDetailPO.getCopyDetails());
|
||||
}
|
||||
returnReceiptMaterialDetailDO.setTotalNetWeight(receiptMaterialDetailDO.getTotalNetWeight());
|
||||
returnReceiptMaterialDetailDO.setTotalGrossWeight(receiptMaterialDetailDO.getTotalGrossWeight());
|
||||
|
||||
+183
@@ -1,15 +1,30 @@
|
||||
package com.mhd.wms.domain.copyCodeReference.service;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.mhd.common.core.utils.bean.BeanUtils;
|
||||
import com.mhd.wms.domain.copyCodeReference.entity.CopyCodeReference;
|
||||
import com.mhd.wms.domain.copyCodeReference.repository.facade.ICopyCodeReferenceService;
|
||||
import com.mhd.wms.domain.copyCodeReference.repository.po.CopyCodeReferencePO;
|
||||
import com.mhd.wms.domain.copyCodeReference.repository.todo.CopyCodeReferenceDO;
|
||||
import com.mhd.wms.domain.pickingMaterialDetail.repository.po.PickingMaterialDetailPO;
|
||||
import com.mhd.wms.interfaces.dto.copyCodeReference.CopyCodeReferenceDTO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class CopyCodeReferenceDomainService {
|
||||
@@ -24,4 +39,172 @@ public class CopyCodeReferenceDomainService {
|
||||
public List<CopyCodeReferencePO> queryWeightList(CopyCodeReferenceDTO dto) {
|
||||
return copyCodeReferenceService.queryWeightList(dto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析逗号分隔的抄码对照 id(顺序与字符串一致)
|
||||
*/
|
||||
public List<Long> parseCommaSeparatedLongIds(String csv) {
|
||||
return parseCommaSeparatedLongIdsStatic(csv);
|
||||
}
|
||||
|
||||
private static List<Long> parseCommaSeparatedLongIdsStatic(String csv) {
|
||||
if (!StringUtils.hasText(csv)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<Long> out = new ArrayList<>();
|
||||
for (String part : csv.split(",")) {
|
||||
String t = part.trim();
|
||||
if (t.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
out.add(Long.parseLong(t));
|
||||
} catch (NumberFormatException ignored) {
|
||||
// skip invalid token
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并两段逗号分隔的抄码对照 id(去重,保留先出现的顺序)。仅 incoming 为空时返回 existing。
|
||||
*/
|
||||
public static String mergeCommaSeparatedUniqueIds(String existing, String incoming) {
|
||||
if (!StringUtils.hasText(incoming)) {
|
||||
return StringUtils.hasText(existing) ? existing : null;
|
||||
}
|
||||
LinkedHashSet<Long> order = new LinkedHashSet<>();
|
||||
order.addAll(parseCommaSeparatedLongIdsStatic(existing));
|
||||
order.addAll(parseCommaSeparatedLongIdsStatic(incoming));
|
||||
if (order.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return order.stream().map(String::valueOf).collect(Collectors.joining(","));
|
||||
}
|
||||
|
||||
/**
|
||||
* 抄码拣货(<strong>按顺序</strong>):假定按 {@code copyCodeReferenceIds} 顺序依次拣完前 {@code pickingQuantity} 件。
|
||||
* 若现场<strong>不按顺序</strong>拣货,请改用 {@link #remainingCopyReferenceIdsExcludingPicked} +
|
||||
* {@link #resolveRemainingCopyReferenceIdsForPicking},并在明细上持久化「已拣抄码 id 集合」。
|
||||
*
|
||||
* @return 待拣抄码 id 子列表(去掉前 {@code pickedCount} 个)
|
||||
*/
|
||||
public static List<Long> remainingCopyReferenceIdsAfterPicked(List<Long> orderedIds, BigDecimal pickingQuantity) {
|
||||
if (orderedIds == null || orderedIds.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
int picked = 0;
|
||||
if (pickingQuantity != null) {
|
||||
picked = pickingQuantity.setScale(0, RoundingMode.DOWN).intValue();
|
||||
}
|
||||
if (picked < 0) {
|
||||
picked = 0;
|
||||
}
|
||||
if (picked >= orderedIds.size()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return new ArrayList<>(orderedIds.subList(picked, orderedIds.size()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 抄码拣货(<strong>乱序</strong>):已拣集合由库表/接口显式给出,与拣货顺序无关。
|
||||
* {@code orderedAll} 仅用于输出待拣 id 的先后展示顺序(通常与全量 copy_code_reference_ids 一致)。
|
||||
*
|
||||
* @param pickedIdsCsv 已拣抄码对照 id,逗号分隔(可随扫描追加)
|
||||
* @return 仍待拣的 id 列表(在 {@code orderedAll} 中且不在已拣集合内)
|
||||
*/
|
||||
public static List<Long> remainingCopyReferenceIdsExcludingPicked(List<Long> orderedAll, String pickedIdsCsv) {
|
||||
if (orderedAll == null || orderedAll.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
if (!StringUtils.hasText(pickedIdsCsv)) {
|
||||
return new ArrayList<>(orderedAll);
|
||||
}
|
||||
Set<Long> picked = new HashSet<>();
|
||||
for (String part : pickedIdsCsv.split(",")) {
|
||||
String t = part.trim();
|
||||
if (t.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
picked.add(Long.parseLong(t));
|
||||
} catch (NumberFormatException ignored) {
|
||||
// skip
|
||||
}
|
||||
}
|
||||
List<Long> out = new ArrayList<>();
|
||||
for (Long id : orderedAll) {
|
||||
if (id != null && !picked.contains(id)) {
|
||||
out.add(id);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算待拣抄码 id:若 {@code pickedCopyCodeReferenceIds} 有值则按<strong>集合差</strong>(乱序);
|
||||
* 否则退回 {@link #remainingCopyReferenceIdsAfterPicked}(顺序假设)。
|
||||
*/
|
||||
public static List<Long> resolveRemainingCopyReferenceIdsForPicking(
|
||||
List<Long> orderedIds, BigDecimal pickingQuantity, String pickedCopyCodeReferenceIds) {
|
||||
if (orderedIds == null || orderedIds.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
if (StringUtils.hasText(pickedCopyCodeReferenceIds)) {
|
||||
return remainingCopyReferenceIdsExcludingPicked(orderedIds, pickedCopyCodeReferenceIds);
|
||||
}
|
||||
return remainingCopyReferenceIdsAfterPicked(orderedIds, pickingQuantity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按 id 批量查询抄码对照,转为 PO(含 netWeight、batchNumber、boxPalletNo、serialNumber 等)
|
||||
*/
|
||||
public Map<Long, CopyCodeReferencePO> mapPoByIds(List<Long> distinctIds) {
|
||||
if (CollectionUtils.isEmpty(distinctIds)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
List<CopyCodeReference> list = copyCodeReferenceService.list(
|
||||
new LambdaQueryWrapper<CopyCodeReference>()
|
||||
.in(CopyCodeReference::getId, distinctIds));
|
||||
Map<Long, CopyCodeReferencePO> map = new HashMap<>(list.size());
|
||||
for (CopyCodeReference c : list) {
|
||||
CopyCodeReferencePO po = new CopyCodeReferencePO();
|
||||
BeanUtils.copyProperties(c, po);
|
||||
map.put(c.getId(), po);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 拣货单明细:根据行上 copyCodeReferenceIds 批量回填 weightList(与出库明细 weightList 结构一致)
|
||||
*/
|
||||
public void fillWeightListOnPickingMaterialDetails(List<PickingMaterialDetailPO> lines) {
|
||||
if (CollectionUtils.isEmpty(lines)) {
|
||||
return;
|
||||
}
|
||||
List<Long> all = new ArrayList<>();
|
||||
for (PickingMaterialDetailPO p : lines) {
|
||||
all.addAll(parseCommaSeparatedLongIds(p.getCopyCodeReferenceIds()));
|
||||
}
|
||||
if (all.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Map<Long, CopyCodeReferencePO> refMap = mapPoByIds(all.stream().distinct().collect(Collectors.toList()));
|
||||
for (PickingMaterialDetailPO p : lines) {
|
||||
List<Long> ordered = parseCommaSeparatedLongIds(p.getCopyCodeReferenceIds());
|
||||
if (ordered.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
List<Long> remaining = resolveRemainingCopyReferenceIdsForPicking(
|
||||
ordered, p.getPickingQuantity(), p.getPickedCopyCodeReferenceIds());
|
||||
List<CopyCodeReferencePO> weightList = new ArrayList<>();
|
||||
for (Long id : remaining) {
|
||||
CopyCodeReferencePO po = refMap.get(id);
|
||||
if (po != null) {
|
||||
weightList.add(po);
|
||||
}
|
||||
}
|
||||
p.setWeightList(weightList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -283,4 +283,12 @@ public class PickingMaterialDetail extends BaseVOEntity {
|
||||
@ApiModelProperty("抄码id数组 逗号分隔")
|
||||
@Excel(name = "抄码id数组")
|
||||
private String copyCodeReferenceIds;
|
||||
|
||||
/**
|
||||
* 已拣抄码对照 id(逗号分隔,与 {@link #copyCodeReferenceIds} 同源 id);乱序拣货时每次扫描追加,用于计算待拣集合。
|
||||
* 为空时接口仍按 {@code picking_quantity} 与全量 id 顺序假定「先拣前 N 件」。
|
||||
*/
|
||||
@ApiModelProperty("已拣抄码对照id(逗号分隔,乱序拣货用)")
|
||||
@Excel(name = "已拣抄码对照id")
|
||||
private String pickedCopyCodeReferenceIds;
|
||||
}
|
||||
+8
@@ -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.copyCodeReference.repository.po.CopyCodeReferencePO;
|
||||
import com.mhd.wms.domain.materialMoreDetail.repository.po.MaterialMoreDetailPO;
|
||||
import com.mhd.wms.domain.outMaterialDetailSerialNumber.repository.todo.OutMaterialDetailSerialNumberDO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
@@ -313,4 +314,11 @@ public class PickingMaterialDetailPO extends BaseVOEntity {
|
||||
@Excel(name = "抄码id数组")
|
||||
private String copyCodeReferenceIds;
|
||||
|
||||
@ApiModelProperty("已拣抄码对照id(逗号分隔,乱序拣货用;有值时待拣=全量 id 去掉已拣集合)")
|
||||
private String pickedCopyCodeReferenceIds;
|
||||
|
||||
@ApiModelProperty("待拣抄码克重明细(顺序/乱序规则见 CopyCodeReferenceDomainService#resolveRemainingCopyReferenceIdsForPicking)")
|
||||
@TableField(exist = false)
|
||||
private List<CopyCodeReferencePO> weightList;
|
||||
|
||||
}
|
||||
+3
@@ -295,4 +295,7 @@ public class PickingMaterialDetailDO extends BaseVOEntity {
|
||||
@ApiModelProperty("抄码id数组 逗号分隔")
|
||||
@Excel(name = "抄码id数组")
|
||||
private String copyCodeReferenceIds;
|
||||
|
||||
@ApiModelProperty("已拣抄码对照id(逗号分隔,合并写入)")
|
||||
private String pickedCopyCodeReferenceIds;
|
||||
}
|
||||
+4
-1
@@ -31,6 +31,7 @@ import com.mhd.wms.domain.mobilizeManageDetail.repository.facade.IMobilizeManage
|
||||
import com.mhd.wms.domain.mobilizeManageDetail.repository.po.MobilizeManageDetailPO;
|
||||
import com.mhd.wms.domain.mobilizeManageDetail.repository.todo.MobilizeManageDetailDO;
|
||||
import com.mhd.wms.domain.outMaterialDetail.entity.OutMaterialDetail;
|
||||
import com.mhd.wms.domain.copyCodeReference.service.CopyCodeReferenceDomainService;
|
||||
import com.mhd.wms.domain.outMaterialDetail.repository.mapper.OutMaterialDetailMapper;
|
||||
import com.mhd.wms.domain.outOrderAbnormal.repository.facade.IOutOrderAbnormalService;
|
||||
import com.mhd.wms.domain.outOrderAbnormal.repository.todo.OutOrderAbnormalBaseDO;
|
||||
@@ -118,7 +119,8 @@ public class PickingOrderDomainService {
|
||||
private OutMaterialDetailMapper outMaterialDetailMapper;
|
||||
@Resource
|
||||
private MaterialBaseInfoMapper materialBaseInfoMapper;
|
||||
|
||||
@Autowired
|
||||
private CopyCodeReferenceDomainService copyCodeReferenceDomainService;
|
||||
|
||||
|
||||
/**
|
||||
@@ -239,6 +241,7 @@ public class PickingOrderDomainService {
|
||||
pickingMaterialDetailPO.setCopyCode(materialBaseInfo.getCopyCode());
|
||||
}
|
||||
}
|
||||
copyCodeReferenceDomainService.fillWeightListOnPickingMaterialDetails(pickingMaterialDetailPOList);
|
||||
pickingOrderPO.setMaterialDetailList(pickingMaterialDetailPOList);
|
||||
return pickingOrderPO;
|
||||
}
|
||||
|
||||
+5
@@ -1,5 +1,6 @@
|
||||
package com.mhd.wms.domain.stockOutTaskOrder.repository.po;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.mhd.common.core.annotation.Excel;
|
||||
import com.mhd.common.core.web.domain.BaseVOEntity;
|
||||
@@ -66,6 +67,10 @@ public class TaskMaterialPO extends BaseVOEntity {
|
||||
@Excel(name = "拣货状态: 1-待拣货 2-拣货中 3-已拣货", readConverterExp = "少=拣")
|
||||
private Integer pickingStatus;
|
||||
|
||||
@ApiModelProperty("是否抄码: 1-是 2-否(由分组内首条明细带出,查询时回填)")
|
||||
@TableField(exist = false)
|
||||
private Integer copyCode;
|
||||
|
||||
@ApiModelProperty("拣货作业物料详情")
|
||||
private List<TaskPickingMaterialDetailPO> taskPickingMaterialDetailList;
|
||||
|
||||
|
||||
+181
-4
@@ -12,6 +12,10 @@ import com.mhd.common.core.utils.bean.BeanUtils;
|
||||
import com.mhd.common.security.utils.SecurityUtils;
|
||||
import com.mhd.system.api.model.LoginUser;
|
||||
import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailDO;
|
||||
import com.mhd.wms.domain.copyCodeReference.repository.po.CopyCodeReferencePO;
|
||||
import com.mhd.wms.domain.copyCodeReference.service.CopyCodeReferenceDomainService;
|
||||
import com.mhd.wms.domain.materialBaseInfo.entity.MaterialBaseInfo;
|
||||
import com.mhd.wms.domain.materialBaseInfo.repository.facade.IMaterialBaseInfoService;
|
||||
import com.mhd.wms.domain.materialInventory.entity.MaterialInventory;
|
||||
import com.mhd.wms.domain.materialInventory.repository.facade.IMaterialInventoryService;
|
||||
import com.mhd.wms.domain.materialInventory.repository.todo.MaterialInventoryDO;
|
||||
@@ -59,8 +63,10 @@ import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -97,6 +103,10 @@ public class StockOutTaskOrderDomainService {
|
||||
private IOutOrderAbnormalService outOrderAbnormalService;
|
||||
@Autowired
|
||||
private IMaterialInventoryService materialInventoryService;
|
||||
@Autowired
|
||||
private IMaterialBaseInfoService materialBaseInfoService;
|
||||
@Autowired
|
||||
private CopyCodeReferenceDomainService copyCodeReferenceDomainService;
|
||||
@Resource
|
||||
private OutMaterialDetailMapper outMaterialDetailMapper;
|
||||
|
||||
@@ -215,6 +225,8 @@ public class StockOutTaskOrderDomainService {
|
||||
taskPickingMaterialDetailDO.setTaskNumber(stockOutTaskOrderPO.getTaskNumber());
|
||||
List<TaskPickingMaterialDetailPO> taskPickingMaterialDetailPOList = taskPickingMaterialDetailService.queryList(taskPickingMaterialDetailDO);
|
||||
enrichTaskDetailPlanAndWork(stockOutTaskOrderPO, taskPickingMaterialDetailPOList);
|
||||
fillTaskPickingDetailCopyCode(taskPickingMaterialDetailPOList);
|
||||
fillTaskPickingDetailWeightList(stockOutTaskOrderPO, taskPickingMaterialDetailPOList);
|
||||
Map<Long, List<TaskPickingMaterialDetailPO>> taskPickingMaterialDetailPOMap = taskPickingMaterialDetailPOList.stream().collect(Collectors.groupingBy(TaskPickingMaterialDetailPO::getMaterialBaseInfoId));
|
||||
int totalPickingMaterialQuantity = 0;//拣货单按物料分组 统计已拣货进度
|
||||
for (Map.Entry<Long, List<TaskPickingMaterialDetailPO>> map : taskPickingMaterialDetailPOMap.entrySet()){
|
||||
@@ -266,6 +278,8 @@ public class StockOutTaskOrderDomainService {
|
||||
// .collect(Collectors.groupingBy(OutMaterialDetailSerialNumberPO::getMaterialDetailUniqueId));
|
||||
List<TaskPickingMaterialDetailPO> taskPickingMaterialDetailPOList = taskPickingMaterialDetailService.queryList(taskPickingMaterialDetailDO);
|
||||
enrichTaskDetailPlanAndWork(stockOutTaskOrderPO, taskPickingMaterialDetailPOList);
|
||||
fillTaskPickingDetailCopyCode(taskPickingMaterialDetailPOList);
|
||||
fillTaskPickingDetailWeightList(stockOutTaskOrderPO, taskPickingMaterialDetailPOList);
|
||||
Map<Long, List<TaskPickingMaterialDetailPO>> taskPickingMaterialDetailPOMap = taskPickingMaterialDetailPOList.stream().collect(Collectors.groupingBy(TaskPickingMaterialDetailPO::getStorageLocationId));
|
||||
int totalPickingMaterialQuantity = 0;//拣货单按库位分组 统计已拣货进度(含已完成的库位)
|
||||
int totalStorageCount = taskPickingMaterialDetailPOMap.size();
|
||||
@@ -326,6 +340,8 @@ public class StockOutTaskOrderDomainService {
|
||||
taskPickingMaterialDetailDO.setTaskNumber(stockOutTaskOrderPO.getTaskNumber());
|
||||
List<TaskPickingMaterialDetailPO> taskPickingMaterialDetailPOList = taskPickingMaterialDetailService.queryList(taskPickingMaterialDetailDO);
|
||||
enrichTaskDetailPlanAndWork(stockOutTaskOrderPO, taskPickingMaterialDetailPOList);
|
||||
fillTaskPickingDetailCopyCode(taskPickingMaterialDetailPOList);
|
||||
fillTaskPickingDetailWeightList(stockOutTaskOrderPO, taskPickingMaterialDetailPOList);
|
||||
Map<Long, List<TaskPickingMaterialDetailPO>> taskPickingMaterialDetailPOMap = taskPickingMaterialDetailPOList.stream().collect(Collectors.groupingBy(TaskPickingMaterialDetailPO::getMaterialBaseInfoId));
|
||||
int totalPickingMaterialQuantity = 0;//拣货单按物料分组 统计已拣货进度
|
||||
List<TaskMaterialPO> taskMaterialPOList = new ArrayList<>();
|
||||
@@ -422,6 +438,45 @@ public class StockOutTaskOrderDomainService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析作业行对应的出库明细:picking_unique_id 多为拣货单明细 unique_id,需经 picking_material_detail.out_unique_id 再查 out_material_detail。
|
||||
*/
|
||||
private OutMaterialDetail resolveOutMaterialDetailForPickingLine(StockOutTaskOrderPO header, TaskPickingMaterialDetailPO line) {
|
||||
if (header == null || line == null || line.getPickingUniqueId() == null) {
|
||||
return null;
|
||||
}
|
||||
String outOrderNumber = header.getOrderNumber();
|
||||
if (!StringUtils.hasText(outOrderNumber)) {
|
||||
return null;
|
||||
}
|
||||
OutMaterialDetail direct = outMaterialDetailMapper.selectOne(new LambdaQueryWrapper<OutMaterialDetail>()
|
||||
.eq(OutMaterialDetail::getOutOrderNumber, outOrderNumber)
|
||||
.eq(OutMaterialDetail::getUniqueId, line.getPickingUniqueId())
|
||||
.eq(OutMaterialDetail::getDelFlag, 1));
|
||||
if (direct != null) {
|
||||
return direct;
|
||||
}
|
||||
if (!StringUtils.hasText(header.getPickingOrderNumber())) {
|
||||
return null;
|
||||
}
|
||||
List<PickingMaterialDetail> pmdList = pickingMaterialDetailService.list(
|
||||
new LambdaQueryWrapper<PickingMaterialDetail>()
|
||||
.eq(PickingMaterialDetail::getPickingOrderNumber, header.getPickingOrderNumber())
|
||||
.eq(PickingMaterialDetail::getUniqueId, line.getPickingUniqueId())
|
||||
.eq(PickingMaterialDetail::getDelFlag, 1));
|
||||
if (CollectionUtils.isEmpty(pmdList)) {
|
||||
return null;
|
||||
}
|
||||
Long outUid = pmdList.get(0).getOutUniqueId();
|
||||
if (outUid == null) {
|
||||
return null;
|
||||
}
|
||||
return outMaterialDetailMapper.selectOne(new LambdaQueryWrapper<OutMaterialDetail>()
|
||||
.eq(OutMaterialDetail::getOutOrderNumber, outOrderNumber)
|
||||
.eq(OutMaterialDetail::getUniqueId, outUid)
|
||||
.eq(OutMaterialDetail::getDelFlag, 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* 作业单详情:按任务类型写入明细上的计划/作业展示数量(关联出库明细)
|
||||
*/
|
||||
@@ -439,10 +494,7 @@ public class StockOutTaskOrderDomainService {
|
||||
if (line.getPickingUniqueId() == null) {
|
||||
continue;
|
||||
}
|
||||
OutMaterialDetail omd = outMaterialDetailMapper.selectOne(new LambdaQueryWrapper<OutMaterialDetail>()
|
||||
.eq(OutMaterialDetail::getOutOrderNumber, outOrderNumber)
|
||||
.eq(OutMaterialDetail::getUniqueId, line.getPickingUniqueId())
|
||||
.eq(OutMaterialDetail::getDelFlag, 1));
|
||||
OutMaterialDetail omd = resolveOutMaterialDetailForPickingLine(header, line);
|
||||
if (omd == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -460,6 +512,131 @@ public class StockOutTaskOrderDomainService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 拣货作业明细:按物料主数据回填是否抄码(查询回显)
|
||||
*/
|
||||
private void fillTaskPickingDetailCopyCode(List<TaskPickingMaterialDetailPO> lines) {
|
||||
if (CollectionUtils.isEmpty(lines)) {
|
||||
return;
|
||||
}
|
||||
List<Long> ids = lines.stream()
|
||||
.map(TaskPickingMaterialDetailPO::getMaterialBaseInfoId)
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
if (CollectionUtil.isEmpty(ids)) {
|
||||
return;
|
||||
}
|
||||
List<MaterialBaseInfo> baseList = materialBaseInfoService.list(
|
||||
new LambdaQueryWrapper<MaterialBaseInfo>()
|
||||
.select(MaterialBaseInfo::getMaterialBaseInfoId, MaterialBaseInfo::getCopyCode)
|
||||
.in(MaterialBaseInfo::getMaterialBaseInfoId, ids));
|
||||
if (CollectionUtils.isEmpty(baseList)) {
|
||||
return;
|
||||
}
|
||||
Map<Long, Integer> copyByMaterialId = new HashMap<>(baseList.size());
|
||||
for (MaterialBaseInfo m : baseList) {
|
||||
if (m.getMaterialBaseInfoId() != null) {
|
||||
copyByMaterialId.put(m.getMaterialBaseInfoId(), m.getCopyCode());
|
||||
}
|
||||
}
|
||||
for (TaskPickingMaterialDetailPO line : lines) {
|
||||
if (line.getMaterialBaseInfoId() != null) {
|
||||
line.setCopyCode(copyByMaterialId.get(line.getMaterialBaseInfoId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 拣货作业明细:按抄码 id 列表批量查 copy_code_reference,回填 weightList(与出库明细一致,含净重、批次号、托盘号等)。
|
||||
* <p>说明:作业明细上的 picking_unique_id 对应 {@link PickingMaterialDetail#uniqueId},抄码 id 落在拣货单明细表;
|
||||
* 仅当该值恰好等于出库明细 unique_id 时才能从 out_material_detail 命中,故优先查 picking_material_detail。</p>
|
||||
* <p>抄码待拣:优先用拣货明细 {@code picked_copy_code_reference_ids}(乱序);否则按 {@code picking_quantity} 与 id 顺序假定先拣前 N 件。</p>
|
||||
*/
|
||||
private void fillTaskPickingDetailWeightList(StockOutTaskOrderPO header, List<TaskPickingMaterialDetailPO> lines) {
|
||||
if (header == null || CollectionUtils.isEmpty(lines)) {
|
||||
return;
|
||||
}
|
||||
List<Long> pickingUniqueIds = lines.stream()
|
||||
.map(TaskPickingMaterialDetailPO::getPickingUniqueId)
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
if (CollectionUtil.isEmpty(pickingUniqueIds)) {
|
||||
return;
|
||||
}
|
||||
Map<Long, String> uniqueToCsv = new HashMap<>();
|
||||
Map<Long, String> uniqueToPickedCsv = new HashMap<>();
|
||||
// 1)拣货单明细:picking_unique_id = picking_material_detail.unique_id,COPY_CODE_REFERENCE_IDS 落在此
|
||||
if (StringUtils.hasText(header.getPickingOrderNumber())) {
|
||||
List<PickingMaterialDetail> pmdList = pickingMaterialDetailService.list(
|
||||
new LambdaQueryWrapper<PickingMaterialDetail>()
|
||||
.eq(PickingMaterialDetail::getPickingOrderNumber, header.getPickingOrderNumber())
|
||||
.in(PickingMaterialDetail::getUniqueId, pickingUniqueIds)
|
||||
.eq(PickingMaterialDetail::getDelFlag, 1));
|
||||
if (!CollectionUtils.isEmpty(pmdList)) {
|
||||
for (PickingMaterialDetail pmd : pmdList) {
|
||||
if (pmd.getUniqueId() != null && StringUtils.hasText(pmd.getCopyCodeReferenceIds())) {
|
||||
uniqueToCsv.put(pmd.getUniqueId(), pmd.getCopyCodeReferenceIds());
|
||||
}
|
||||
if (pmd.getUniqueId() != null && StringUtils.hasText(pmd.getPickedCopyCodeReferenceIds())) {
|
||||
uniqueToPickedCsv.put(pmd.getUniqueId(), pmd.getPickedCopyCodeReferenceIds());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 2)出库明细:兼容 picking_unique_id 即 out_material_detail.unique_id 的历史数据
|
||||
if (StringUtils.hasText(header.getOrderNumber())) {
|
||||
List<OutMaterialDetail> omdList = outMaterialDetailMapper.selectList(
|
||||
new LambdaQueryWrapper<OutMaterialDetail>()
|
||||
.eq(OutMaterialDetail::getOutOrderNumber, header.getOrderNumber())
|
||||
.in(OutMaterialDetail::getUniqueId, pickingUniqueIds)
|
||||
.eq(OutMaterialDetail::getDelFlag, 1));
|
||||
if (!CollectionUtils.isEmpty(omdList)) {
|
||||
for (OutMaterialDetail omd : omdList) {
|
||||
if (omd.getUniqueId() != null && StringUtils.hasText(omd.getCopyCodeReferenceIds())) {
|
||||
uniqueToCsv.putIfAbsent(omd.getUniqueId(), omd.getCopyCodeReferenceIds());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (uniqueToCsv.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
List<Long> allRefIds = new ArrayList<>();
|
||||
for (TaskPickingMaterialDetailPO line : lines) {
|
||||
String csv = uniqueToCsv.get(line.getPickingUniqueId());
|
||||
if (StringUtils.hasText(csv)) {
|
||||
allRefIds.addAll(copyCodeReferenceDomainService.parseCommaSeparatedLongIds(csv));
|
||||
}
|
||||
}
|
||||
if (allRefIds.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Map<Long, CopyCodeReferencePO> refMap = copyCodeReferenceDomainService.mapPoByIds(allRefIds.stream().distinct().collect(Collectors.toList()));
|
||||
for (TaskPickingMaterialDetailPO line : lines) {
|
||||
String csv = uniqueToCsv.get(line.getPickingUniqueId());
|
||||
if (!StringUtils.hasText(csv)) {
|
||||
continue;
|
||||
}
|
||||
List<Long> ordered = copyCodeReferenceDomainService.parseCommaSeparatedLongIds(csv);
|
||||
if (ordered.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
String pickedCsv = uniqueToPickedCsv.get(line.getPickingUniqueId());
|
||||
List<Long> remaining = CopyCodeReferenceDomainService.resolveRemainingCopyReferenceIdsForPicking(
|
||||
ordered, line.getPickingQuantity(), pickedCsv);
|
||||
List<CopyCodeReferencePO> weightList = new ArrayList<>();
|
||||
for (Long id : remaining) {
|
||||
CopyCodeReferencePO po = refMap.get(id);
|
||||
if (po != null) {
|
||||
weightList.add(po);
|
||||
}
|
||||
}
|
||||
line.setWeightList(weightList);
|
||||
}
|
||||
}
|
||||
|
||||
private static BigDecimal detailPlanForDisplay(TaskPickingMaterialDetailPO d) {
|
||||
if (d == null) {
|
||||
return BigDecimal.ZERO;
|
||||
|
||||
+43
@@ -1,6 +1,7 @@
|
||||
package com.mhd.wms.domain.taskPickingMaterialDetail.repository.persistence;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.mhd.common.core.exception.ServiceException;
|
||||
@@ -10,6 +11,8 @@ import com.mhd.system.api.model.LoginUser;
|
||||
import com.mhd.wms.domain.outMaterialDetailSerialNumber.entity.OutMaterialDetailSerialNumber;
|
||||
import com.mhd.wms.domain.outMaterialDetailSerialNumber.repository.facade.IOutMaterialDetailSerialNumberService;
|
||||
import com.mhd.wms.domain.outMaterialDetailSerialNumber.repository.todo.OutMaterialDetailSerialNumberDO;
|
||||
import com.mhd.wms.domain.copyCodeReference.service.CopyCodeReferenceDomainService;
|
||||
import com.mhd.wms.domain.pickingMaterialDetail.entity.PickingMaterialDetail;
|
||||
import com.mhd.wms.domain.pickingMaterialDetail.repository.facade.IPickingMaterialDetailService;
|
||||
import com.mhd.wms.domain.pickingMaterialDetail.repository.todo.PickingMaterialDetailDO;
|
||||
import com.mhd.wms.domain.pickingMaterialDetail.repository.todo.PickingMaterialDetailDOByUpdate;
|
||||
@@ -25,12 +28,16 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -126,6 +133,28 @@ public class TaskPickingMaterialDetailImpl extends ServiceImpl<TaskPickingMateri
|
||||
.eq(TaskPickingMaterialDetail::getTaskNumber, stockOutTaskOrderDO.getTaskNumber())
|
||||
.eq(TaskPickingMaterialDetail::getDelFlag, 1));
|
||||
Map<Long, TaskPickingMaterialDetail> taskPickingMaterialDetailMap = taskPickingMaterialDetailDbList.stream().collect(Collectors.toMap(TaskPickingMaterialDetail::getMaterialDetailId, Function.identity()));
|
||||
Set<Long> pickingUniqueIdsInRequest = new HashSet<>();
|
||||
for (TaskPickingMaterialDetailDO row : taskPickingMaterialDetailDOList) {
|
||||
if (ObjectUtil.isNull(row.getActualQuantity()) || row.getActualQuantity().compareTo(BigDecimal.ZERO) == 0) {
|
||||
continue;
|
||||
}
|
||||
TaskPickingMaterialDetail taskDb = taskPickingMaterialDetailMap.get(row.getMaterialDetailId());
|
||||
if (taskDb != null && taskDb.getPickingUniqueId() != null) {
|
||||
pickingUniqueIdsInRequest.add(taskDb.getPickingUniqueId());
|
||||
}
|
||||
}
|
||||
Map<Long, PickingMaterialDetail> pmdByPickingUniqueId = new HashMap<>();
|
||||
if (!pickingUniqueIdsInRequest.isEmpty()) {
|
||||
List<PickingMaterialDetail> pmdRows = pickingMaterialDetailService.list(
|
||||
new LambdaQueryWrapper<PickingMaterialDetail>()
|
||||
.in(PickingMaterialDetail::getUniqueId, pickingUniqueIdsInRequest)
|
||||
.eq(PickingMaterialDetail::getDelFlag, 1));
|
||||
if (!CollectionUtils.isEmpty(pmdRows)) {
|
||||
pmdByPickingUniqueId = pmdRows.stream()
|
||||
.collect(Collectors.toMap(PickingMaterialDetail::getUniqueId, Function.identity(), (a, b) -> a));
|
||||
}
|
||||
}
|
||||
Map<Long, String> pickedCsvByPickingUnique = new HashMap<>();
|
||||
// 批量新增或修改序列号
|
||||
List<OutMaterialDetailSerialNumber> outMaterialDetailSerialNumberList = new ArrayList<>();
|
||||
BigDecimal totalPickingQuantity = BigDecimal.ZERO;
|
||||
@@ -162,11 +191,22 @@ public class TaskPickingMaterialDetailImpl extends ServiceImpl<TaskPickingMateri
|
||||
}
|
||||
Long pickingUniqueId = taskPickingMaterialDetailDb.getPickingUniqueId();
|
||||
BigDecimal qty = taskPickingMaterialDetailDO.getActualQuantity() != null ? taskPickingMaterialDetailDO.getActualQuantity() : BigDecimal.ZERO;
|
||||
String basePickedCsv = pickedCsvByPickingUnique.get(pickingUniqueId);
|
||||
if (basePickedCsv == null) {
|
||||
PickingMaterialDetail pmdRow = pmdByPickingUniqueId.get(pickingUniqueId);
|
||||
basePickedCsv = pmdRow != null ? pmdRow.getPickedCopyCodeReferenceIds() : null;
|
||||
}
|
||||
String mergedPickedCsv = CopyCodeReferenceDomainService.mergeCommaSeparatedUniqueIds(
|
||||
basePickedCsv, taskPickingMaterialDetailDO.getPickedCopyCodeReferenceIds());
|
||||
pickedCsvByPickingUnique.put(pickingUniqueId, mergedPickedCsv);
|
||||
// 按 pickingUniqueId 聚合,同一拣货明细可能对应多条任务明细
|
||||
PickingMaterialDetailDO existing = pickingMaterialDetailList.stream()
|
||||
.filter(p -> pickingUniqueId.equals(p.getUniqueId())).findFirst().orElse(null);
|
||||
if (existing != null) {
|
||||
existing.setPickingQuantity((existing.getPickingQuantity() != null ? existing.getPickingQuantity() : BigDecimal.ZERO).add(qty));
|
||||
if (StringUtils.hasText(mergedPickedCsv)) {
|
||||
existing.setPickedCopyCodeReferenceIds(mergedPickedCsv);
|
||||
}
|
||||
// 净重、毛重、体积、面积:拣货填写值直接覆盖,不累加
|
||||
if (taskPickingMaterialDetailDO.getTotalNetWeight() != null) {
|
||||
existing.setTotalNetWeight(taskPickingMaterialDetailDO.getTotalNetWeight());
|
||||
@@ -184,6 +224,9 @@ public class TaskPickingMaterialDetailImpl extends ServiceImpl<TaskPickingMateri
|
||||
PickingMaterialDetailDO pickingMaterialDetailDO = new PickingMaterialDetailDO();
|
||||
pickingMaterialDetailDO.setUniqueId(pickingUniqueId);
|
||||
pickingMaterialDetailDO.setPickingQuantity(qty);
|
||||
if (StringUtils.hasText(mergedPickedCsv)) {
|
||||
pickingMaterialDetailDO.setPickedCopyCodeReferenceIds(mergedPickedCsv);
|
||||
}
|
||||
pickingMaterialDetailDO.setTotalNetWeight(taskPickingMaterialDetailDO.getTotalNetWeight());
|
||||
pickingMaterialDetailDO.setTotalGrossWeight(taskPickingMaterialDetailDO.getTotalGrossWeight());
|
||||
pickingMaterialDetailDO.setTotalVolume(taskPickingMaterialDetailDO.getTotalVolume());
|
||||
|
||||
+9
@@ -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.copyCodeReference.repository.po.CopyCodeReferencePO;
|
||||
import com.mhd.wms.domain.materialMoreDetail.repository.po.MaterialMoreDetailPO;
|
||||
import com.mhd.wms.domain.outMaterialDetailSerialNumber.repository.po.OutMaterialDetailSerialNumberPO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
@@ -235,4 +236,12 @@ public class TaskPickingMaterialDetailPO extends BaseVOEntity {
|
||||
@TableField(exist = false)
|
||||
private BigDecimal workQuantity;
|
||||
|
||||
@ApiModelProperty("是否抄码: 1-是 2-否(与物料主数据一致,查询时回填)")
|
||||
@TableField(exist = false)
|
||||
private Integer copyCode;
|
||||
|
||||
@ApiModelProperty("待拣抄码克重明细(来自 copy_code_reference;顺序与库存抄码 id 列表一致,已按 pickingQuantity 去掉已拣件,仅余待扫)")
|
||||
@TableField(exist = false)
|
||||
private List<CopyCodeReferencePO> weightList;
|
||||
|
||||
}
|
||||
|
||||
+6
@@ -223,4 +223,10 @@ public class TaskPickingMaterialDetailDO extends BaseVOEntity {
|
||||
@ApiModelProperty("总面积(SQM)")
|
||||
@Excel(name = "总面积(SQM)")
|
||||
private BigDecimal totalArea;
|
||||
|
||||
/**
|
||||
* 本次确认拣货对应的抄码对照 id(逗号分隔,可与多行合并);乱序拣货时与 {@code actualQuantity} 同步上报,服务端合并写入拣货单明细 {@code picked_copy_code_reference_ids}。
|
||||
*/
|
||||
@ApiModelProperty("本次已拣抄码对照id(逗号分隔,乱序拣货用)")
|
||||
private String pickedCopyCodeReferenceIds;
|
||||
}
|
||||
|
||||
+7
@@ -63,6 +63,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="totalVolume" column="total_volume" />
|
||||
<result property="outUniqueId" column="out_unique_id" />
|
||||
<result property="copyCodeReferenceIds" column="COPY_CODE_REFERENCE_IDS" />
|
||||
<result property="pickedCopyCodeReferenceIds" column="picked_copy_code_reference_ids" />
|
||||
</resultMap>
|
||||
|
||||
|
||||
@@ -79,6 +80,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
a.create_time, a.create_by, a.create_by_name, a.update_time, a.update_by, a.update_by_name, a.del_flag,
|
||||
a.total_area, a.total_gross_weight, a.total_net_weight, a.total_volume, a.out_unique_id,
|
||||
a.COPY_CODE_REFERENCE_IDS,
|
||||
a.picked_copy_code_reference_ids,
|
||||
omd.in_order_number, omd.lot_no as lot_number
|
||||
</sql>
|
||||
|
||||
@@ -265,6 +267,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
WHEN #{item.uniqueId} THEN COALESCE(#{item.totalArea}, total_area)
|
||||
</foreach>
|
||||
</trim>
|
||||
<trim prefix="picked_copy_code_reference_ids = CASE unique_id" suffix="END,">
|
||||
<foreach collection="pickingMaterialDetailList" item="item" index="index">
|
||||
WHEN #{item.uniqueId} THEN COALESCE(#{item.pickedCopyCodeReferenceIds}, picked_copy_code_reference_ids)
|
||||
</foreach>
|
||||
</trim>
|
||||
update_by = #{updateBy},
|
||||
update_by_name = #{updateByName},
|
||||
update_time = #{updateTime}
|
||||
|
||||
Reference in New Issue
Block a user