Commit a682efdbcf491b73d266e350c4a469ce55fefbcc

Authored by YunaiV
1 parent 6a9c2c25

✨ feat(mes): 添加库存调拨事务创建逻辑,支持出入库操作

yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transfer/MesWmTransferServiceImpl.java
... ... @@ -11,8 +11,12 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.wm.transfer.MesWmTransferDO;
11 11 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.transfer.MesWmTransferDetailDO;
12 12 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.transfer.MesWmTransferLineDO;
13 13 import cn.iocoder.yudao.module.mes.dal.mysql.wm.transfer.MesWmTransferMapper;
  14 +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants;
  15 +import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum;
14 16 import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransferStatusEnum;
15 17 import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService;
  18 +import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService;
  19 +import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO;
16 20 import jakarta.annotation.Resource;
17 21 import org.springframework.stereotype.Service;
18 22 import org.springframework.transaction.annotation.Transactional;
... ... @@ -20,6 +24,7 @@ import org.springframework.validation.annotation.Validated;
20 24  
21 25 import java.math.BigDecimal;
22 26 import java.util.List;
  27 +import java.util.Map;
23 28  
24 29 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
25 30 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
... ... @@ -40,6 +45,8 @@ public class MesWmTransferServiceImpl implements MesWmTransferService {
40 45 private MesWmTransferDetailService transferDetailService;
41 46 @Resource
42 47 private MesWmMaterialStockService materialStockService;
  48 + @Resource
  49 + private MesWmTransactionService wmTransactionService;
43 50  
44 51 @Override
45 52 public Long createTransfer(MesWmTransferSaveReqVO createReqVO) {
... ... @@ -148,25 +155,60 @@ public class MesWmTransferServiceImpl implements MesWmTransferService {
148 155 @Override
149 156 @Transactional(rollbackFor = Exception.class)
150 157 public void finishTransfer(Long id) {
151   - // 校验存在 + 待执行状态
  158 + // 1. 校验存在 + 待执行状态
152 159 MesWmTransferDO transfer = validateTransferExistsAndApproved(id);
153 160 List<MesWmTransferLineDO> lines = transferLineService.getTransferLineListByTransferId(id);
154 161 if (CollUtil.isEmpty(lines)) {
155 162 throw exception(WM_TRANSFER_NO_LINE);
156 163 }
157 164  
158   - // DONE @AI:库存转移涉及出入库落账与库存事务联动,当前提交先保留状态流转与冻结解冻校验,不在本轮 TODO 修复中扩展业务实现
  165 + // 2. 创建库存事务(调拨移出 + 调拨移入)
  166 + createTransferTransactions(transfer, lines);
159 167  
160   - // 更新状态:待执行 -> 已完成
  168 + // 3. 更新状态:待执行 -> 已完成
161 169 transfer.setStatus(MesWmTransferStatusEnum.FINISHED.getStatus());
162 170 transferMapper.updateById(transfer);
163 171  
164   - // 配送模式下,执行完成后解除来源库存冻结
  172 + // 4. 配送模式下,执行完成后解除来源库存冻结
165 173 if (Boolean.TRUE.equals(transfer.getDeliveryFlag())) {
166 174 freezeTransferLineStocks(lines, false);
167 175 }
168 176 }
169 177  
  178 + /**
  179 + * 创建调拨事务:基于 detail (明细) 的视角,不是纯粹的 line(行)的视角。
  180 + * 因为明细才代表了实际调往各个目标仓位的动作,所以每条明細产生一笔出库(MOVE_OUT)和一笔入库(MOVE_IN)。
  181 + */
  182 + private void createTransferTransactions(MesWmTransferDO transfer, List<MesWmTransferLineDO> lines) {
  183 + // 1. 预加载所有明细,按 lineId 分组,避免 N+1 查询
  184 + List<MesWmTransferDetailDO> allDetails = transferDetailService.getTransferDetailListByTransferId(transfer.getId());
  185 + Map<Long, List<MesWmTransferDetailDO>> detailMap = CollectionUtils.convertMultiMap(
  186 + allDetails, MesWmTransferDetailDO::getLineId);
  187 + // 2. 遍历行和对应的明细,创建事务
  188 + for (MesWmTransferLineDO line : lines) {
  189 + List<MesWmTransferDetailDO> details = detailMap.getOrDefault(line.getId(), List.of());
  190 + for (MesWmTransferDetailDO detail : details) {
  191 + // 2.1 先执行出库:调拨移出(从源仓库扣减库存),出库数量基于当前明细的数量
  192 + Long outTransactionId = wmTransactionService.createTransaction(new MesWmTransactionSaveReqDTO()
  193 + .setType(MesWmTransactionTypeEnum.MOVE_OUT.getType()).setItemId(line.getItemId())
  194 + .setQuantity(detail.getQuantity().negate()) // 库存减少(按 detail 的数量出)
  195 + .setBatchId(line.getBatchId())
  196 + .setWarehouseId(line.getFromWarehouseId()).setLocationId(line.getFromLocationId()).setAreaId(line.getFromAreaId())
  197 + .setBizType(MesBizTypeConstants.WM_TRANSFER_OUT).setBizId(transfer.getId())
  198 + .setBizCode(transfer.getCode()).setBizLineId(line.getId()));
  199 + // 2.2 再执行入库:调拨移入(向目标仓库增加库存),入库数量等于相同明细的数量
  200 + wmTransactionService.createTransaction(new MesWmTransactionSaveReqDTO()
  201 + .setType(MesWmTransactionTypeEnum.MOVE_IN.getType()).setItemId(line.getItemId()) // 物料信息来自 line
  202 + .setQuantity(detail.getQuantity()) // 库存增加(按 detail 的数量入)
  203 + .setBatchId(line.getBatchId()) // 批次信息来自 line
  204 + .setWarehouseId(detail.getToWarehouseId()).setLocationId(detail.getToLocationId()).setAreaId(detail.getToAreaId())
  205 + .setBizType(MesBizTypeConstants.WM_TRANSFER_IN).setBizId(transfer.getId())
  206 + .setBizCode(transfer.getCode()).setBizLineId(line.getId())
  207 + .setRelatedTransactionId(outTransactionId)); // 关联本次的具体出库事务
  208 + }
  209 + }
  210 + }
  211 +
170 212 @Override
171 213 @Transactional(rollbackFor = Exception.class)
172 214 public void cancelTransfer(Long id) {
... ...