Commit a682efdbcf491b73d266e350c4a469ce55fefbcc
1 parent
6a9c2c25
✨ feat(mes): 添加库存调拨事务创建逻辑,支持出入库操作
Showing
1 changed file
with
46 additions
and
4 deletions
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) { | ... | ... |