diff --git a/klp-wms/src/main/java/com/klp/controller/WmsStockIoController.java b/klp-wms/src/main/java/com/klp/controller/WmsStockIoController.java index 7c2ec79c..8b5c1fa0 100644 --- a/klp-wms/src/main/java/com/klp/controller/WmsStockIoController.java +++ b/klp-wms/src/main/java/com/klp/controller/WmsStockIoController.java @@ -113,4 +113,24 @@ public class WmsStockIoController extends BaseController { public R audit(@NotNull(message = "主键不能为空") @PathVariable Long stockIoId) { return toAjax(iWmsStockIoService.auditStockIo(stockIoId)); } + + /** + * 撤销出入库/移库单 + */ + @SaCheckPermission("klp:stockIo:cancel") + @Log(title = "出入库单主", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PostMapping("/cancel/{stockIoId}") + public R cancel(@NotNull(message = "主键不能为空") @PathVariable Long stockIoId) { + return toAjax(iWmsStockIoService.cancelStockIo(stockIoId)); + } + + /** + * 根据ioType和stockIoId联查明细 + */ + @SaCheckPermission("klp:stockIo:detail") + @GetMapping("/detailByTypeAndId") + public R> detailByTypeAndId(@RequestParam String ioType, @RequestParam Long stockIoId) { + return R.ok(iWmsStockIoService.detailByTypeAndId(ioType, stockIoId)); + } } diff --git a/klp-wms/src/main/java/com/klp/service/IWmsStockIoService.java b/klp-wms/src/main/java/com/klp/service/IWmsStockIoService.java index 59817c25..37f79f17 100644 --- a/klp-wms/src/main/java/com/klp/service/IWmsStockIoService.java +++ b/klp-wms/src/main/java/com/klp/service/IWmsStockIoService.java @@ -51,4 +51,14 @@ public interface IWmsStockIoService { * 审核出入库/移库单,变更库存,含库存校验 */ Boolean auditStockIo(Long stockIoId); + + /** + * 撤销出入库/移库单,库存回滚 + */ + Boolean cancelStockIo(Long stockIoId); + + /** + * 根据ioType和stockIoId联查明细 + */ + java.util.List detailByTypeAndId(String ioType, Long stockIoId); } diff --git a/klp-wms/src/main/java/com/klp/service/impl/WmsStockIoServiceImpl.java b/klp-wms/src/main/java/com/klp/service/impl/WmsStockIoServiceImpl.java index 0512f02c..222837b9 100644 --- a/klp-wms/src/main/java/com/klp/service/impl/WmsStockIoServiceImpl.java +++ b/klp-wms/src/main/java/com/klp/service/impl/WmsStockIoServiceImpl.java @@ -1,6 +1,7 @@ package com.klp.service.impl; import cn.hutool.core.bean.BeanUtil; +import com.klp.common.annotation.RepeatSubmit; import com.klp.common.core.page.TableDataInfo; import com.klp.common.core.domain.PageQuery; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -24,6 +25,7 @@ import java.math.BigDecimal; import java.util.List; import java.util.Map; import java.util.Collection; +import com.klp.common.exception.ServiceException; /** * 出入库单主Service业务层处理 @@ -162,6 +164,77 @@ public class WmsStockIoServiceImpl implements IWmsStockIoService { return true; } + /** + * 撤销出入库/移库单,库存回滚 + */ + @Override + @RepeatSubmit() + @Transactional(rollbackFor = Exception.class) + public Boolean cancelStockIo(Long stockIoId) { + WmsStockIo stockIo = baseMapper.selectById(stockIoId); + if (stockIo == null || stockIo.getStatus() == null || stockIo.getStatus() != 2) { + throw new ServiceException("只能撤销已审核的单据"); + } + List details = stockIoDetailMapper.selectList( + Wrappers.lambdaQuery().eq(WmsStockIoDetail::getStockIoId, stockIoId) + ); + if (details == null || details.isEmpty()) { + throw new ServiceException("单据明细不能为空"); + } + for (WmsStockIoDetail detail : details) { + String ioType = stockIo.getIoType(); + if ("in".equals(ioType)) { + // 入库撤销:目标库位库存减少 + changeStock(detail.getWarehouseId(), detail.getItemType(), detail.getItemId(), detail.getBatchNo(), detail.getQuantity(), false, detail.getUnit()); + } else if ("out".equals(ioType)) { + // 出库撤销:目标库位库存增加 + changeStock(detail.getWarehouseId(), detail.getItemType(), detail.getItemId(), detail.getBatchNo(), detail.getQuantity(), true, detail.getUnit()); + } else if ("transfer".equals(ioType)) { + if (detail.getFromWarehouseId() == null) { + throw new ServiceException("移库明细缺少源库位ID"); + } + // 源库位库存增加 + changeStock(detail.getFromWarehouseId(), detail.getItemType(), detail.getItemId(), detail.getBatchNo(), detail.getQuantity(), true, detail.getUnit()); + // 目标库位库存减少 + changeStock(detail.getWarehouseId(), detail.getItemType(), detail.getItemId(), detail.getBatchNo(), detail.getQuantity(), false, detail.getUnit()); + } else { + throw new ServiceException("未知的出入库类型"); + } + } + // 更新单据状态为已撤销(3) + stockIo.setStatus(3); + baseMapper.updateById(stockIo); + return true; + } + + /** + * 根据ioType和stockIoId联查明细 + */ + @Override + public java.util.List detailByTypeAndId(String ioType, Long stockIoId) { + WmsStockIo stockIo = baseMapper.selectById(stockIoId); + if (stockIo == null) { + throw new ServiceException("单据不存在"); + } + if (!ioType.equals(stockIo.getIoType())) { + throw new ServiceException("单据类型不匹配"); + } + List details = stockIoDetailMapper.selectList( + Wrappers.lambdaQuery().eq(WmsStockIoDetail::getStockIoId, stockIoId) + ); + if (details == null || details.isEmpty()) { + return java.util.Collections.emptyList(); + } + // 转VO + java.util.List voList = new java.util.ArrayList<>(); + for (WmsStockIoDetail detail : details) { + com.klp.domain.vo.WmsStockIoDetailVo vo = new com.klp.domain.vo.WmsStockIoDetailVo(); + org.springframework.beans.BeanUtils.copyProperties(detail, vo); + voList.add(vo); + } + return voList; + } + /** * 库存增减,isAdd=true为增加,false为减少,减少时校验库存是否足够 */