package com.vincent.rsf.server.manager.service.impl;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
import com.vincent.rsf.framework.common.R;
|
import com.vincent.rsf.framework.exception.CoolException;
|
import com.vincent.rsf.server.manager.controller.params.ReviseLogParams;
|
import com.vincent.rsf.server.manager.entity.*;
|
import com.vincent.rsf.server.manager.enums.AsnExceStatus;
|
import com.vincent.rsf.server.manager.enums.CommonExceStatus;
|
import com.vincent.rsf.server.manager.enums.OrderType;
|
import com.vincent.rsf.server.manager.enums.OrderWorkType;
|
import com.vincent.rsf.server.manager.mapper.ReviseLogMapper;
|
import com.vincent.rsf.server.manager.service.*;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
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.Set;
|
import java.util.stream.Collectors;
|
|
@Service("reviseLogService")
|
public class ReviseLogServiceImpl extends ServiceImpl<ReviseLogMapper, ReviseLog> implements ReviseLogService {
|
|
@Autowired
|
private LocReviseService locReviseService;
|
|
@Autowired
|
private ReviseLogService reviseLogService;
|
|
@Autowired
|
private LocItemService locItemService;
|
|
@Autowired
|
private LocService locService;
|
|
@Autowired
|
private ReviseLogItemService reviseLogItemService;
|
|
@Autowired
|
private OutStockService outStockService;
|
|
@Autowired
|
private OutStockItemService outStockItemService;
|
|
/**
|
* 库存调整单明细添加
|
*
|
* @param revise
|
* @param loginUserId
|
* @return
|
*/
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public List<ReviseLog> reviseLoc(ReviseLogParams revise, Long loginUserId) {
|
LocRevise locRevise = locReviseService.getById(revise.getReviseId());
|
if (Objects.isNull(locRevise)) {
|
throw new CoolException("调整单据不存在!!");
|
}
|
List<ReviseLog> items = revise.getItems();
|
if (items.isEmpty()) {
|
throw new CoolException("调整单明细参数为空!!");
|
}
|
items.forEach(item -> {
|
ReviseLog reviseLog = new ReviseLog();
|
BeanUtils.copyProperties(item, reviseLog);
|
reviseLog.setAreaId(locRevise.getAreaId())
|
.setReviseId(locRevise.getId())
|
.setCreateBy(loginUserId)
|
.setUpdateBy(loginUserId)
|
.setReviseCode(locRevise.getCode());
|
if (!reviseLogService.save(reviseLog)) {
|
throw new CoolException("调整单明细保存失败!!");
|
}
|
|
List<LocItem> locItems = locItemService.list(new LambdaQueryWrapper<LocItem>()
|
.eq(LocItem::getLocCode, item.getLocCode()));
|
if (!locItems.isEmpty()) {
|
locItems.forEach(ote -> {
|
ReviseLogItem logItem = new ReviseLogItem();
|
BeanUtils.copyProperties(ote, logItem);
|
logItem.setReviseLogId(reviseLog.getId());
|
if (!reviseLogItemService.save(logItem)) {
|
throw new CoolException("明细保存失败!!");
|
}
|
});
|
}
|
|
Double sum = locItems.stream().mapToDouble(LocItem::getAnfme).sum();
|
|
locRevise.setAnfme(Math.round((sum + locRevise.getAnfme()) * 1000000) / 1000000.0);
|
});
|
|
locRevise.setExceStatus(CommonExceStatus.COMMON_EXCE_STATUS_UN_EXCE.val);
|
|
if (!locReviseService.updateById(locRevise)) {
|
throw new CoolException("状态更新失败!!");
|
}
|
return items;
|
}
|
|
/**
|
* @author Ryan
|
* @date 2025/8/18
|
* @description: 确认调整库存
|
* @version 1.0
|
*/
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public R complete(Long id, Long loginUserId) {
|
LocRevise revise = locReviseService.getById(id);
|
if (Objects.isNull(revise)) {
|
throw new CoolException("调整单不存在!!");
|
}
|
if (!revise.getExceStatus().equals(CommonExceStatus.COMMON_EXCE_STATUS_EXCE_ING.val)) {
|
throw new CoolException("单据状态未执行或已完成,无法执行完成操作!!");
|
}
|
List<ReviseLog> logs = reviseLogService.list(new LambdaQueryWrapper<ReviseLog>().eq(ReviseLog::getReviseId, revise.getId()));
|
if (logs.isEmpty()) {
|
throw new CoolException("库存日志不存在!!");
|
}
|
Set<Long> longs = logs.stream().map(ReviseLog::getId).collect(Collectors.toSet());
|
List<ReviseLogItem> logItems = reviseLogItemService.list(new LambdaQueryWrapper<ReviseLogItem>().in(ReviseLogItem::getReviseLogId, longs));
|
if (logItems.isEmpty()) {
|
throw new CoolException("调整明细为空!!");
|
}
|
// 按库位ID分组,如果locId为null则按locCode分组
|
Map<String, List<ReviseLogItem>> listMap = logItems.stream()
|
.filter(item -> item.getLocCode() != null && !item.getLocCode().isEmpty())
|
.collect(Collectors.groupingBy(item -> {
|
// 优先使用locId,如果为null则使用locCode作为key
|
return item.getLocId() != null ? String.valueOf(item.getLocId()) : item.getLocCode();
|
}));
|
|
// 优化:在循环外查询所有未完成的出库单和明细,避免重复查询
|
// 查询所有未完成的出库单状态:初始化、待处理、生成波次、生成工作档、作业中
|
List<WkOrder> outOrders = outStockService.list(new LambdaQueryWrapper<WkOrder>()
|
.eq(WkOrder::getType, OrderType.ORDER_OUT.type)
|
.in(WkOrder::getExceStatus,
|
AsnExceStatus.OUT_STOCK_STATUS_TASK_INIT.val,
|
AsnExceStatus.OUT_STOCK_STATUS_TASK_EXCE.val,
|
AsnExceStatus.OUT_STOCK_STATUS_TASK_WAVE.val,
|
AsnExceStatus.OUT_STOCK_STATUS_TASK_CREATE.val,
|
AsnExceStatus.OUT_STOCK_STATUS_TASK_WORKING.val));
|
|
// 预先查询所有出库单的明细,建立索引以提高查询效率
|
Map<Long, List<WkOrderItem>> orderItemsMap = new HashMap<>();
|
Map<Long, Boolean> orderHasItemsMap = new HashMap<>();
|
if (!outOrders.isEmpty()) {
|
Set<Long> orderIds = outOrders.stream().map(WkOrder::getId).collect(Collectors.toSet());
|
List<WkOrderItem> allOrderItems = outStockItemService.list(
|
new LambdaQueryWrapper<WkOrderItem>().in(WkOrderItem::getOrderId, orderIds));
|
|
// 按orderId分组建立索引
|
orderItemsMap = allOrderItems.stream()
|
.collect(Collectors.groupingBy(WkOrderItem::getOrderId));
|
|
// 记录每个出库单是否有明细
|
for (Long orderId : orderIds) {
|
orderHasItemsMap.put(orderId, orderItemsMap.containsKey(orderId) && !orderItemsMap.get(orderId).isEmpty());
|
}
|
}
|
|
// 使用final变量以便在lambda中使用
|
final Map<Long, List<WkOrderItem>> finalOrderItemsMap = orderItemsMap;
|
final Map<Long, Boolean> finalOrderHasItemsMap = orderHasItemsMap;
|
|
// 批量收集需要创建的WkOrderItem
|
List<WkOrderItem> newOrderItems = new ArrayList<>();
|
|
listMap.keySet().forEach(key -> {
|
List<ReviseLogItem> reviseItems = listMap.get(key);
|
if (Objects.isNull(reviseItems) || reviseItems.isEmpty()) {
|
throw new CoolException("调整明细为空!!");
|
}
|
|
// 获取第一个明细的库位信息
|
ReviseLogItem firstItem = reviseItems.get(0);
|
String locCode = firstItem.getLocCode();
|
Long locId = firstItem.getLocId();
|
|
// 查询库位:优先使用locId,如果为null则使用locCode
|
Loc loc = null;
|
if (locId != null) {
|
loc = locService.getById(locId);
|
}
|
if (loc == null && locCode != null && !locCode.isEmpty()) {
|
loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, locCode).eq(Loc::getDeleted, 0));
|
}
|
|
if (Objects.isNull(loc)) {
|
throw new CoolException("库位不存在!库位编码:" + locCode + ", 库位ID:" + locId);
|
}
|
|
// 删除原库位的库存明细(如果存在)
|
locItemService.remove(new LambdaQueryWrapper<LocItem>().eq(LocItem::getLocId, loc.getId()));
|
|
Loc finalLoc = loc;
|
reviseItems.forEach(logItem -> {
|
LocItem locDetl = new LocItem();
|
BeanUtils.copyProperties(logItem, locDetl);
|
locDetl.setLocId(finalLoc.getId())
|
.setType(OrderType.ORDER_REVISE.type)
|
.setWkType(Short.parseShort(OrderWorkType.ORDER_WORK_TYPE_STOCK_REVISE.type))
|
.setLocCode(finalLoc.getCode())
|
.setAnfme(logItem.getReviseQty())
|
// 如果batch不为空,同时设置splrBatch,以便查询时能匹配
|
.setSplrBatch(StringUtils.isNotBlank(logItem.getBatch()) ? logItem.getBatch() : null)
|
.setUpdateBy(loginUserId)
|
.setId(null)
|
.setCreateBy(loginUserId);
|
if (!locItemService.save(locDetl)) {
|
throw new CoolException("库存明细保存失败!!");
|
}
|
|
// 为库存调整产生的库存创建对应的WkOrderItem
|
// 遍历所有未完成的出库单,检查是否需要这些物料
|
for (WkOrder outOrder : outOrders) {
|
// 从预加载的索引中查找该出库单的明细
|
List<WkOrderItem> orderItems = finalOrderItemsMap.getOrDefault(outOrder.getId(), new ArrayList<>());
|
|
// 检查该出库单是否已有匹配的明细
|
boolean hasMatchingItem = orderItems.stream().anyMatch(item -> {
|
// 物料ID必须匹配
|
if (!Objects.equals(item.getMatnrId(), logItem.getMatnrId())) {
|
return false;
|
}
|
|
// 如果有批次信息,需要匹配批次
|
if (StringUtils.isNotBlank(logItem.getBatch())) {
|
boolean batchMatch = Objects.equals(item.getBatch(), logItem.getBatch()) ||
|
Objects.equals(item.getSplrBatch(), logItem.getBatch());
|
if (!batchMatch) {
|
return false;
|
}
|
}
|
|
// 如果有字段索引,需要匹配
|
if (StringUtils.isNotBlank(logItem.getFieldsIndex())) {
|
if (!Objects.equals(item.getFieldsIndex(), logItem.getFieldsIndex())) {
|
return false;
|
}
|
}
|
|
return true;
|
});
|
|
// 如果该出库单需要这个物料但没有对应的明细,则创建
|
if (!hasMatchingItem) {
|
// 为所有未完成的出库单创建WkOrderItem,即使出库单没有其他明细
|
// 因为库存调整的物料可能需要出库
|
WkOrderItem newOrderItem = new WkOrderItem();
|
newOrderItem.setOrderId(outOrder.getId())
|
.setOrderCode(outOrder.getCode())
|
.setMatnrId(logItem.getMatnrId())
|
.setMatnrCode(logItem.getMatnrCode())
|
.setMaktx(logItem.getMaktx())
|
.setBatch(logItem.getBatch())
|
// 如果batch不为空,同时设置splrBatch,以便查询时能匹配
|
.setSplrBatch(StringUtils.isNotBlank(logItem.getBatch()) ? logItem.getBatch() : null)
|
.setFieldsIndex(logItem.getFieldsIndex())
|
.setAnfme(logItem.getReviseQty())
|
.setWorkQty(0.0)
|
.setStockUnit(logItem.getUnit())
|
.setPurUnit(logItem.getUnit())
|
.setSpec(logItem.getSpec())
|
.setModel(logItem.getModel())
|
.setCreateBy(loginUserId)
|
.setUpdateBy(loginUserId)
|
.setCreateTime(new Date())
|
.setUpdateTime(new Date());
|
|
newOrderItems.add(newOrderItem);
|
}
|
}
|
});
|
});
|
|
// 批量保存WkOrderItem,减少数据库操作次数
|
if (!newOrderItems.isEmpty()) {
|
if (!outStockItemService.saveBatch(newOrderItems)) {
|
throw new CoolException("库存调整单据明细创建失败!!");
|
}
|
}
|
revise.setExceStatus(CommonExceStatus.COMMON_EXCE_STATUS_TASK_DONE.val);
|
if (!locReviseService.updateById(revise)) {
|
throw new CoolException("调整单修改失败!!");
|
}
|
return R.ok();
|
}
|
}
|