package com.ruoyi.production.service.impl;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.production.bean.dto.ProductionOrderPickDto;
|
import com.ruoyi.production.bean.vo.ProductionOrderPickVo;
|
import com.ruoyi.production.mapper.ProductionOperationTaskMapper;
|
import com.ruoyi.production.mapper.ProductionOrderMapper;
|
import com.ruoyi.production.mapper.ProductionOrderPickMapper;
|
import com.ruoyi.production.mapper.ProductionOrderPickRecordMapper;
|
import com.ruoyi.production.pojo.ProductionOrder;
|
import com.ruoyi.production.pojo.ProductionOrderPick;
|
import com.ruoyi.production.pojo.ProductionOrderPickRecord;
|
import com.ruoyi.production.service.ProductionOrderPickService;
|
import com.ruoyi.stock.dto.StockInventoryDto;
|
import com.ruoyi.stock.mapper.StockInventoryMapper;
|
import com.ruoyi.stock.pojo.StockInventory;
|
import lombok.RequiredArgsConstructor;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.math.BigDecimal;
|
import java.util.*;
|
import java.util.function.Function;
|
import java.util.stream.Collectors;
|
|
/**
|
* <p>
|
* 璁㈠崟棰嗘枡绾胯竟浠?鏈嶅姟瀹炵幇绫?
|
* </p>
|
*
|
* @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
|
* @since 2026-04-21 03:55:52
|
*/
|
@Service
|
@RequiredArgsConstructor
|
public class ProductionOrderPickServiceImpl extends ServiceImpl<ProductionOrderPickMapper, ProductionOrderPick> implements ProductionOrderPickService {
|
|
private final ProductionOrderMapper productionOrderMapper;
|
private final ProductionOperationTaskMapper productionOperationTaskMapper;
|
private final ProductionOrderPickRecordMapper productionOrderPickRecordMapper;
|
private final StockInventoryMapper stockInventoryMapper;
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public Boolean savePick(ProductionOrderPickDto dto) {
|
List<ProductionOrderPickDto> pickItems = resolvePickItems(dto);
|
for (int i = 0; i < pickItems.size(); i++) {
|
int rowNo = i + 1;
|
ProductionOrderPickDto resolvedDto = mergeDto(dto, pickItems.get(i));
|
validatePickParam(resolvedDto, rowNo);
|
|
List<String> batchNoList = resolveBatchNoList(resolvedDto);
|
String inventoryBatchNo = pickInventoryBatchNo(batchNoList);
|
String storedBatchNo = formatBatchNoStorage(batchNoList);
|
subtractInventory(resolvedDto.getProductModelId(), inventoryBatchNo, resolvedDto.getPickQuantity(), rowNo);
|
|
ProductionOrderPick orderPick = new ProductionOrderPick();
|
orderPick.setProductionOrderId(resolvedDto.getProductionOrderId());
|
orderPick.setProductModelId(resolvedDto.getProductModelId());
|
orderPick.setBatchNo(storedBatchNo);
|
orderPick.setQuantity(resolvedDto.getPickQuantity());
|
orderPick.setRemark(resolvedDto.getRemark());
|
orderPick.setOperationName(resolvedDto.getOperationName());
|
orderPick.setTechnologyOperationId(resolvedDto.getTechnologyOperationId());
|
orderPick.setDemandedQuantity(resolvedDto.getDemandedQuantity());
|
orderPick.setBom(resolvedDto.getBom());
|
baseMapper.insert(orderPick);
|
|
insertPickRecord(orderPick.getId(),
|
resolvedDto.getProductionOrderId(),
|
resolvedDto.getProductionOperationTaskId(),
|
resolvedDto.getProductModelId(),
|
inventoryBatchNo,
|
resolvedDto.getPickQuantity(),
|
BigDecimal.ZERO,
|
resolvedDto.getPickQuantity(),
|
resolvedDto.getPickType(),
|
resolvedDto.getRemark());
|
}
|
return true;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public Boolean updatePick(ProductionOrderPickDto dto) {
|
if (dto == null) {
|
throw new ServiceException("变更参数不能为空");
|
}
|
Long productionOrderId = resolveProductionOrderId(dto);
|
if (productionOrderId == null) {
|
throw new ServiceException("生产订单ID不能为空");
|
}
|
ProductionOrder productionOrder = productionOrderMapper.selectById(productionOrderId);
|
if (productionOrder == null) {
|
throw new ServiceException("生产订单不存在");
|
}
|
|
List<ProductionOrderPick> existingPickList = baseMapper.selectList(
|
Wrappers.<ProductionOrderPick>lambdaQuery()
|
.eq(ProductionOrderPick::getProductionOrderId, productionOrderId));
|
Map<Long, ProductionOrderPick> existingPickMap = existingPickList.stream()
|
.filter(item -> item.getId() != null)
|
.collect(Collectors.toMap(ProductionOrderPick::getId, Function.identity(), (a, b) -> a));
|
|
processDeletePickIds(dto, existingPickMap, productionOrderId);
|
|
List<ProductionOrderPickDto> pickItems = resolveUpdateItems(dto);
|
Set<Long> keepPickIdSet = new HashSet<>();
|
for (int i = 0; i < pickItems.size(); i++) {
|
int rowNo = i + 1;
|
ProductionOrderPickDto resolvedDto = mergeDto(dto, pickItems.get(i));
|
if (isEmptyUpdateItem(resolvedDto)) {
|
continue;
|
}
|
if (resolvedDto.getProductionOrderId() == null) {
|
resolvedDto.setProductionOrderId(productionOrderId);
|
}
|
validatePickParam(resolvedDto, rowNo);
|
|
if (resolvedDto.getId() == null) {
|
addNewPickInUpdate(resolvedDto, rowNo);
|
continue;
|
}
|
keepPickIdSet.add(resolvedDto.getId());
|
updateExistingPick(resolvedDto, rowNo, existingPickMap);
|
}
|
processMissingPickItems(dto, existingPickMap, productionOrderId, keepPickIdSet);
|
return true;
|
}
|
|
@Override
|
public List<ProductionOrderPickVo> listPickedDetail(Long productionOrderId) {
|
if (productionOrderId == null) {
|
return Collections.emptyList();
|
}
|
List<ProductionOrderPickVo> detailList = baseMapper.listPickedDetailByOrderId(productionOrderId);
|
fillBatchNoList(detailList);
|
fillSelectableBatchNoList(detailList);
|
return detailList;
|
}
|
|
private void processDeletePickIds(ProductionOrderPickDto rootDto,
|
Map<Long, ProductionOrderPick> existingPickMap,
|
Long productionOrderId) {
|
if (rootDto.getDeletePickIds() == null || rootDto.getDeletePickIds().isEmpty()) {
|
return;
|
}
|
Set<Long> deleteIdSet = new LinkedHashSet<>(rootDto.getDeletePickIds());
|
for (Long deleteId : deleteIdSet) {
|
if (deleteId == null) {
|
continue;
|
}
|
ProductionOrderPick existingPick = existingPickMap.get(deleteId);
|
if (existingPick == null || !Objects.equals(existingPick.getProductionOrderId(), productionOrderId)) {
|
throw new ServiceException("要删除的领料记录不存在或不属于当前订单,ID=" + deleteId);
|
}
|
String oldBatchNo = resolveInventoryBatchNoFromStored(existingPick.getBatchNo());
|
BigDecimal oldQuantity = defaultDecimal(existingPick.getQuantity());
|
addInventory(existingPick.getProductModelId(), oldBatchNo, oldQuantity);
|
int affected = baseMapper.deleteById(deleteId);
|
if (affected <= 0) {
|
throw new ServiceException("删除领料失败,ID=" + deleteId);
|
}
|
insertPickRecord(existingPick.getId(),
|
existingPick.getProductionOrderId(),
|
rootDto.getProductionOperationTaskId(),
|
existingPick.getProductModelId(),
|
oldBatchNo,
|
oldQuantity,
|
oldQuantity,
|
BigDecimal.ZERO,
|
rootDto.getPickType(),
|
rootDto.getRemark());
|
existingPickMap.remove(deleteId);
|
}
|
}
|
|
private void processMissingPickItems(ProductionOrderPickDto rootDto,
|
Map<Long, ProductionOrderPick> existingPickMap,
|
Long productionOrderId,
|
Set<Long> keepPickIdSet) {
|
if (rootDto.getPickList() == null) {
|
return;
|
}
|
List<ProductionOrderPick> missingPickList = existingPickMap.values().stream()
|
.filter(Objects::nonNull)
|
.filter(item -> item.getId() != null)
|
.filter(item -> Objects.equals(item.getProductionOrderId(), productionOrderId))
|
.filter(item -> !keepPickIdSet.contains(item.getId()))
|
.collect(Collectors.toList());
|
for (ProductionOrderPick missingPick : missingPickList) {
|
String oldBatchNo = resolveInventoryBatchNoFromStored(missingPick.getBatchNo());
|
BigDecimal oldQuantity = defaultDecimal(missingPick.getQuantity());
|
addInventory(missingPick.getProductModelId(), oldBatchNo, oldQuantity);
|
int affected = baseMapper.deleteById(missingPick.getId());
|
if (affected <= 0) {
|
throw new ServiceException("删除领料失败,ID=" + missingPick.getId());
|
}
|
insertPickRecord(missingPick.getId(),
|
missingPick.getProductionOrderId(),
|
rootDto.getProductionOperationTaskId(),
|
missingPick.getProductModelId(),
|
oldBatchNo,
|
oldQuantity,
|
oldQuantity,
|
BigDecimal.ZERO,
|
rootDto.getPickType(),
|
rootDto.getRemark());
|
existingPickMap.remove(missingPick.getId());
|
}
|
}
|
|
private void addNewPickInUpdate(ProductionOrderPickDto dto, int rowNo) {
|
List<String> batchNoList = resolveBatchNoList(dto);
|
String inventoryBatchNo = pickInventoryBatchNo(batchNoList);
|
String storedBatchNo = formatBatchNoStorage(batchNoList);
|
subtractInventory(dto.getProductModelId(), inventoryBatchNo, dto.getPickQuantity(), rowNo);
|
|
ProductionOrderPick orderPick = new ProductionOrderPick();
|
orderPick.setProductionOrderId(dto.getProductionOrderId());
|
orderPick.setProductModelId(dto.getProductModelId());
|
orderPick.setBatchNo(storedBatchNo);
|
orderPick.setQuantity(dto.getPickQuantity());
|
orderPick.setRemark(dto.getRemark());
|
orderPick.setOperationName(dto.getOperationName());
|
orderPick.setTechnologyOperationId(dto.getTechnologyOperationId());
|
orderPick.setDemandedQuantity(dto.getDemandedQuantity());
|
orderPick.setBom(dto.getBom());
|
baseMapper.insert(orderPick);
|
|
insertPickRecord(orderPick.getId(),
|
dto.getProductionOrderId(),
|
dto.getProductionOperationTaskId(),
|
dto.getProductModelId(),
|
inventoryBatchNo,
|
dto.getPickQuantity(),
|
BigDecimal.ZERO,
|
dto.getPickQuantity(),
|
dto.getPickType(),
|
dto.getRemark());
|
}
|
|
private void updateExistingPick(ProductionOrderPickDto dto,
|
int rowNo,
|
Map<Long, ProductionOrderPick> existingPickMap) {
|
ProductionOrderPick oldPick = existingPickMap.get(dto.getId());
|
if (oldPick == null || !Objects.equals(oldPick.getProductionOrderId(), dto.getProductionOrderId())) {
|
throw new ServiceException("第" + rowNo + "条领料记录不存在或不属于当前订单");
|
}
|
|
Long oldProductModelId = oldPick.getProductModelId();
|
String oldBatchNo = resolveInventoryBatchNoFromStored(oldPick.getBatchNo());
|
BigDecimal oldQuantity = defaultDecimal(oldPick.getQuantity());
|
|
Long newProductModelId = dto.getProductModelId();
|
List<String> newBatchNoList = resolveBatchNoList(dto);
|
String newBatchNo = pickInventoryBatchNo(newBatchNoList);
|
String newStoredBatchNo = formatBatchNoStorage(newBatchNoList);
|
BigDecimal newQuantity = dto.getPickQuantity();
|
|
boolean sameStockKey = Objects.equals(oldProductModelId, newProductModelId)
|
&& Objects.equals(oldBatchNo, newBatchNo);
|
if (sameStockKey) {
|
BigDecimal delta = newQuantity.subtract(oldQuantity);
|
if (delta.compareTo(BigDecimal.ZERO) > 0) {
|
subtractInventory(newProductModelId, newBatchNo, delta, rowNo);
|
} else if (delta.compareTo(BigDecimal.ZERO) < 0) {
|
addInventory(oldProductModelId, oldBatchNo, delta.abs());
|
}
|
} else {
|
addInventory(oldProductModelId, oldBatchNo, oldQuantity);
|
subtractInventory(newProductModelId, newBatchNo, newQuantity, rowNo);
|
}
|
|
oldPick.setProductModelId(newProductModelId);
|
oldPick.setBatchNo(newStoredBatchNo);
|
oldPick.setQuantity(newQuantity);
|
oldPick.setRemark(dto.getRemark());
|
oldPick.setOperationName(dto.getOperationName());
|
oldPick.setTechnologyOperationId(dto.getTechnologyOperationId());
|
if (dto.getDemandedQuantity() != null) {
|
oldPick.setDemandedQuantity(dto.getDemandedQuantity());
|
}
|
if (dto.getBom() != null) {
|
oldPick.setBom(dto.getBom());
|
}
|
int affected = baseMapper.updateById(oldPick);
|
if (affected <= 0) {
|
throw new ServiceException("第" + rowNo + "条领料更新失败");
|
}
|
|
BigDecimal recordQuantity = sameStockKey ? oldQuantity.subtract(newQuantity).abs() : newQuantity;
|
if (recordQuantity.compareTo(BigDecimal.ZERO) > 0 || oldQuantity.compareTo(newQuantity) != 0 || !sameStockKey) {
|
insertPickRecord(oldPick.getId(),
|
dto.getProductionOrderId(),
|
dto.getProductionOperationTaskId(),
|
newProductModelId,
|
newBatchNo,
|
recordQuantity,
|
oldQuantity,
|
newQuantity,
|
dto.getPickType(),
|
dto.getRemark());
|
}
|
}
|
|
private void insertPickRecord(Long pickId,
|
Long productionOrderId,
|
Long productionOperationTaskId,
|
Long productModelId,
|
String batchNo,
|
BigDecimal pickQuantity,
|
BigDecimal beforeQuantity,
|
BigDecimal afterQuantity,
|
Byte pickType,
|
String remark) {
|
ProductionOrderPickRecord pickRecord = new ProductionOrderPickRecord();
|
pickRecord.setPickId(pickId);
|
pickRecord.setProductionOrderId(productionOrderId);
|
pickRecord.setProductionOperationTaskId(productionOperationTaskId);
|
pickRecord.setProductModelId(productModelId);
|
pickRecord.setBatchNo(batchNo);
|
pickRecord.setPickQuantity(defaultDecimal(pickQuantity));
|
pickRecord.setBeforeQuantity(defaultDecimal(beforeQuantity));
|
pickRecord.setAfterQuantity(defaultDecimal(afterQuantity));
|
pickRecord.setPickType(pickType == null ? (byte) 1 : pickType);
|
pickRecord.setRemark(remark);
|
productionOrderPickRecordMapper.insert(pickRecord);
|
}
|
|
private void subtractInventory(Long productModelId, String batchNo, BigDecimal quantity, int rowNo) {
|
StockInventory stockInventory = stockInventoryMapper.selectOne(buildStockWrapper(productModelId, batchNo));
|
if (stockInventory == null) {
|
throw new ServiceException("第" + rowNo + "条领料对应库存不存在");
|
}
|
BigDecimal availableQuantity = defaultDecimal(stockInventory.getQualitity())
|
.subtract(defaultDecimal(stockInventory.getLockedQuantity()));
|
if (quantity.compareTo(availableQuantity) > 0) {
|
throw new ServiceException("第" + rowNo + "条领料可用库存不足");
|
}
|
StockInventoryDto stockInventoryDto = new StockInventoryDto();
|
stockInventoryDto.setProductModelId(productModelId);
|
stockInventoryDto.setBatchNo(batchNo);
|
stockInventoryDto.setQualitity(quantity);
|
int affected = stockInventoryMapper.updateSubtractStockInventory(stockInventoryDto);
|
if (affected <= 0) {
|
throw new ServiceException("第" + rowNo + "条领料扣减库存失败");
|
}
|
}
|
|
private void addInventory(Long productModelId, String batchNo, BigDecimal quantity) {
|
BigDecimal addQuantity = defaultDecimal(quantity);
|
if (addQuantity.compareTo(BigDecimal.ZERO) <= 0) {
|
return;
|
}
|
StockInventory stockInventory = stockInventoryMapper.selectOne(buildStockWrapper(productModelId, batchNo));
|
if (stockInventory == null) {
|
StockInventory newStockInventory = new StockInventory();
|
newStockInventory.setProductModelId(productModelId);
|
newStockInventory.setBatchNo(batchNo);
|
newStockInventory.setQualitity(addQuantity);
|
newStockInventory.setLockedQuantity(BigDecimal.ZERO);
|
newStockInventory.setVersion(1);
|
stockInventoryMapper.insert(newStockInventory);
|
return;
|
}
|
StockInventoryDto stockInventoryDto = new StockInventoryDto();
|
stockInventoryDto.setProductModelId(productModelId);
|
stockInventoryDto.setBatchNo(batchNo);
|
stockInventoryDto.setQualitity(addQuantity);
|
int affected = stockInventoryMapper.updateAddStockInventory(stockInventoryDto);
|
if (affected <= 0) {
|
throw new ServiceException("库存回退失败,产品规格ID=" + productModelId);
|
}
|
}
|
|
private List<ProductionOrderPickDto> resolvePickItems(ProductionOrderPickDto dto) {
|
if (dto == null) {
|
throw new ServiceException("领料参数不能为空");
|
}
|
if (dto.getPickList() != null && !dto.getPickList().isEmpty()) {
|
return dto.getPickList();
|
}
|
return Collections.singletonList(dto);
|
}
|
|
private List<ProductionOrderPickDto> resolveUpdateItems(ProductionOrderPickDto dto) {
|
if (dto.getPickList() != null) {
|
return dto.getPickList();
|
}
|
if (isEmptyUpdateItem(dto)) {
|
return Collections.emptyList();
|
}
|
return Collections.singletonList(dto);
|
}
|
|
private boolean isEmptyUpdateItem(ProductionOrderPickDto dto) {
|
return dto.getId() == null
|
&& dto.getProductModelId() == null
|
&& dto.getPickQuantity() == null
|
&& StringUtils.isEmpty(dto.getBatchNo())
|
&& (dto.getBatchNoList() == null || dto.getBatchNoList().isEmpty())
|
&& dto.getPickType() == null
|
&& dto.getProductionOperationTaskId() == null
|
&& dto.getTechnologyOperationId() == null
|
&& StringUtils.isEmpty(dto.getOperationName())
|
&& dto.getDemandedQuantity() == null
|
&& dto.getBom() == null
|
&& StringUtils.isEmpty(dto.getRemark());
|
}
|
|
private Long resolveProductionOrderId(ProductionOrderPickDto dto) {
|
if (dto.getProductionOrderId() != null) {
|
return dto.getProductionOrderId();
|
}
|
if (dto.getPickList() == null || dto.getPickList().isEmpty()) {
|
return null;
|
}
|
return dto.getPickList().stream()
|
.filter(Objects::nonNull)
|
.map(ProductionOrderPickDto::getProductionOrderId)
|
.filter(Objects::nonNull)
|
.findFirst()
|
.orElse(null);
|
}
|
|
private ProductionOrderPickDto mergeDto(ProductionOrderPickDto rootDto, ProductionOrderPickDto itemDto) {
|
ProductionOrderPickDto merged = new ProductionOrderPickDto();
|
if (itemDto != null) {
|
merged.setId(itemDto.getId());
|
merged.setProductionOrderId(itemDto.getProductionOrderId());
|
merged.setProductionOperationTaskId(itemDto.getProductionOperationTaskId());
|
merged.setProductModelId(itemDto.getProductModelId());
|
merged.setBatchNo(itemDto.getBatchNo());
|
merged.setBatchNoList(itemDto.getBatchNoList());
|
merged.setPickQuantity(itemDto.getPickQuantity());
|
merged.setPickType(itemDto.getPickType());
|
merged.setRemark(itemDto.getRemark());
|
merged.setTechnologyOperationId(itemDto.getTechnologyOperationId());
|
merged.setOperationName(itemDto.getOperationName());
|
merged.setDemandedQuantity(itemDto.getDemandedQuantity());
|
merged.setBom(itemDto.getBom());
|
}
|
if (merged.getId() == null) {
|
merged.setId(rootDto.getId());
|
}
|
if (merged.getProductionOrderId() == null) {
|
merged.setProductionOrderId(rootDto.getProductionOrderId());
|
}
|
if (merged.getProductionOperationTaskId() == null) {
|
merged.setProductionOperationTaskId(rootDto.getProductionOperationTaskId());
|
}
|
if (merged.getProductModelId() == null) {
|
merged.setProductModelId(rootDto.getProductModelId());
|
}
|
if (merged.getBatchNo() == null) {
|
merged.setBatchNo(rootDto.getBatchNo());
|
}
|
if (merged.getBatchNoList() == null || merged.getBatchNoList().isEmpty()) {
|
merged.setBatchNoList(rootDto.getBatchNoList());
|
}
|
if (merged.getPickQuantity() == null) {
|
merged.setPickQuantity(rootDto.getPickQuantity());
|
}
|
if (merged.getPickType() == null) {
|
merged.setPickType(rootDto.getPickType());
|
}
|
if (merged.getRemark() == null) {
|
merged.setRemark(rootDto.getRemark());
|
}
|
if (merged.getTechnologyOperationId() == null) {
|
merged.setTechnologyOperationId(rootDto.getTechnologyOperationId());
|
}
|
if (merged.getOperationName() == null) {
|
merged.setOperationName(rootDto.getOperationName());
|
}
|
if (merged.getDemandedQuantity() == null) {
|
merged.setDemandedQuantity(rootDto.getDemandedQuantity());
|
}
|
if (merged.getBom() == null) {
|
merged.setBom(rootDto.getBom());
|
}
|
return merged;
|
}
|
|
private void validatePickParam(ProductionOrderPickDto dto, int rowNo) {
|
if (dto.getProductionOrderId() == null) {
|
throw new ServiceException("第" + rowNo + "条生产订单ID不能为空");
|
}
|
if (dto.getProductModelId() == null) {
|
throw new ServiceException("第" + rowNo + "条产品规格ID不能为空");
|
}
|
if (dto.getPickQuantity() == null || dto.getPickQuantity().compareTo(BigDecimal.ZERO) <= 0) {
|
throw new ServiceException("第" + rowNo + "条领料数量必须大于0");
|
}
|
if (dto.getPickType() != null && dto.getPickType() != 1 && dto.getPickType() != 2) {
|
throw new ServiceException("第" + rowNo + "条领料类型只能是1或2");
|
}
|
}
|
|
private String normalizeBatchNo(String batchNo) {
|
if (StringUtils.isEmpty(batchNo)) {
|
return null;
|
}
|
String trimBatchNo = batchNo.trim();
|
return trimBatchNo.isEmpty() ? null : trimBatchNo;
|
}
|
private List<String> resolveBatchNoList(ProductionOrderPickDto dto) {
|
List<String> normalizedBatchNoList = normalizeBatchNoList(dto.getBatchNoList());
|
if (!normalizedBatchNoList.isEmpty()) {
|
return normalizedBatchNoList;
|
}
|
return parseBatchNoValue(dto.getBatchNo());
|
}
|
|
private String pickInventoryBatchNo(List<String> batchNoList) {
|
if (batchNoList == null || batchNoList.isEmpty()) {
|
return null;
|
}
|
return batchNoList.get(0);
|
}
|
|
private String resolveInventoryBatchNoFromStored(String storedBatchNo) {
|
return pickInventoryBatchNo(parseBatchNoValue(storedBatchNo));
|
}
|
|
private String formatBatchNoStorage(List<String> batchNoList) {
|
if (batchNoList == null || batchNoList.isEmpty()) {
|
return null;
|
}
|
if (batchNoList.size() == 1) {
|
return batchNoList.get(0);
|
}
|
return String.join(",", batchNoList);
|
}
|
|
private List<String> normalizeBatchNoList(List<String> batchNoList) {
|
if (batchNoList == null || batchNoList.isEmpty()) {
|
return Collections.emptyList();
|
}
|
LinkedHashSet<String> normalizedSet = new LinkedHashSet<>();
|
for (String batchNo : batchNoList) {
|
String normalizedBatchNo = normalizeBatchNo(batchNo);
|
if (!StringUtils.isEmpty(normalizedBatchNo)) {
|
normalizedSet.add(normalizedBatchNo);
|
}
|
}
|
return new ArrayList<>(normalizedSet);
|
}
|
|
private void fillBatchNoList(List<ProductionOrderPickVo> detailList) {
|
if (detailList == null || detailList.isEmpty()) {
|
return;
|
}
|
Map<String, LinkedHashSet<String>> batchNoGroupMap = new HashMap<>();
|
for (ProductionOrderPickVo detail : detailList) {
|
String key = buildBatchNoGroupKey(detail);
|
LinkedHashSet<String> batchSet = batchNoGroupMap.computeIfAbsent(key, k -> new LinkedHashSet<>());
|
batchSet.addAll(parseBatchNoValue(detail.getBatchNo()));
|
if (detail.getBatchNoList() != null && !detail.getBatchNoList().isEmpty()) {
|
batchSet.addAll(normalizeBatchNoList(detail.getBatchNoList()));
|
}
|
}
|
for (ProductionOrderPickVo detail : detailList) {
|
String key = buildBatchNoGroupKey(detail);
|
LinkedHashSet<String> batchSet = batchNoGroupMap.get(key);
|
detail.setBatchNoList(batchSet == null ? Collections.emptyList() : new ArrayList<>(batchSet));
|
}
|
}
|
|
private void fillSelectableBatchNoList(List<ProductionOrderPickVo> detailList) {
|
if (detailList == null || detailList.isEmpty()) {
|
return;
|
}
|
Set<Long> productModelIdSet = detailList.stream()
|
.map(ProductionOrderPickVo::getProductModelId)
|
.filter(Objects::nonNull)
|
.collect(Collectors.toSet());
|
if (productModelIdSet.isEmpty()) {
|
return;
|
}
|
List<StockInventory> stockBatchList = stockInventoryMapper.listSelectableBatchNoByProductModelIds(
|
new ArrayList<>(productModelIdSet));
|
Map<Long, LinkedHashSet<String>> stockBatchMap = new HashMap<>();
|
for (StockInventory stockInventory : stockBatchList) {
|
if (stockInventory == null || stockInventory.getProductModelId() == null) {
|
continue;
|
}
|
String normalizedBatchNo = normalizeBatchNo(stockInventory.getBatchNo());
|
if (StringUtils.isEmpty(normalizedBatchNo)) {
|
continue;
|
}
|
stockBatchMap.computeIfAbsent(stockInventory.getProductModelId(), k -> new LinkedHashSet<>())
|
.add(normalizedBatchNo);
|
}
|
for (ProductionOrderPickVo detail : detailList) {
|
LinkedHashSet<String> mergedBatchSet = new LinkedHashSet<>();
|
mergedBatchSet.addAll(normalizeBatchNoList(detail.getBatchNoList()));
|
LinkedHashSet<String> selectableBatchSet = stockBatchMap.get(detail.getProductModelId());
|
if (selectableBatchSet != null) {
|
mergedBatchSet.addAll(selectableBatchSet);
|
}
|
detail.setBatchNoList(new ArrayList<>(mergedBatchSet));
|
}
|
}
|
|
private String buildBatchNoGroupKey(ProductionOrderPickVo detail) {
|
return String.valueOf(detail.getProductionOrderId()) + "|"
|
+ String.valueOf(detail.getProductModelId()) + "|"
|
+ String.valueOf(detail.getTechnologyOperationId()) + "|"
|
+ String.valueOf(detail.getOperationName());
|
}
|
|
private List<String> parseBatchNoValue(String rawBatchNoValue) {
|
String normalizedValue = normalizeBatchNo(rawBatchNoValue);
|
if (StringUtils.isEmpty(normalizedValue)) {
|
return Collections.emptyList();
|
}
|
if (normalizedValue.startsWith("[") && normalizedValue.endsWith("]")) {
|
String value = normalizedValue.substring(1, normalizedValue.length() - 1);
|
if (StringUtils.isEmpty(value)) {
|
return Collections.emptyList();
|
}
|
List<String> parsed = Arrays.stream(value.split(","))
|
.map(item -> item == null ? null : item.trim().replace("\"", "").replace("'", ""))
|
.collect(Collectors.toList());
|
return normalizeBatchNoList(parsed);
|
}
|
if (normalizedValue.contains(",")) {
|
List<String> parsed = Arrays.stream(normalizedValue.split(","))
|
.map(item -> item == null ? null : item.trim())
|
.collect(Collectors.toList());
|
return normalizeBatchNoList(parsed);
|
}
|
return Collections.singletonList(normalizedValue);
|
}
|
|
private LambdaQueryWrapper<StockInventory> buildStockWrapper(Long productModelId, String batchNo) {
|
LambdaQueryWrapper<StockInventory> wrapper = Wrappers.<StockInventory>lambdaQuery()
|
.eq(StockInventory::getProductModelId, productModelId);
|
if (StringUtils.isEmpty(batchNo)) {
|
wrapper.isNull(StockInventory::getBatchNo);
|
} else {
|
wrapper.eq(StockInventory::getBatchNo, batchNo);
|
}
|
return wrapper;
|
}
|
|
private BigDecimal defaultDecimal(BigDecimal value) {
|
return value == null ? BigDecimal.ZERO : value;
|
}
|
}
|