package com.ruoyi.stock.service.impl; import cn.hutool.core.bean.BeanUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum; import com.ruoyi.common.utils.OrderUtils; import com.ruoyi.framework.web.domain.R; import com.ruoyi.procurementrecord.utils.StockUtils; import com.ruoyi.project.system.domain.SysUser; import com.ruoyi.project.system.mapper.SysUserMapper; import com.ruoyi.stock.dto.*; import com.ruoyi.stock.mapper.StockInventoryCheckItemMapper; import com.ruoyi.stock.mapper.StockInventoryCheckPlanMapper; import com.ruoyi.stock.mapper.StockInventoryCheckProductMapper; import com.ruoyi.stock.pojo.*; import com.ruoyi.stock.service.*; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.util.*; import java.util.stream.Collectors; /** *

* 盘点计划表 服务实现类 *

* * @author 芯导软件(江苏)有限公司 * @since 2026-05-09 10:00:43 */ @Service @RequiredArgsConstructor public class StockInventoryCheckPlanServiceImpl extends ServiceImpl implements StockInventoryCheckPlanService { private final StockInventoryCheckPlanMapper stockInventoryCheckPlanMapper; private final StockInventoryCheckProductMapper stockInventoryCheckProductMapper; private final SysUserMapper sysUserMapper; private final StockInventoryCheckMainService stockInventoryCheckMainService; private final StockInventoryService stockInventoryService; private final StockInventoryCheckItemMapper stockInventoryCheckItemMapper; private final StockUtils stockUtils; private final StockInRecordService stockInRecordService; private final StockOutRecordService stockOutRecordService; @Override public IPage listPage(Page page, StockInventoryCheckPlanDto stockInventoryCheckPlanDto) { IPage stockInventoryCheckPlanDtoIPage = stockInventoryCheckPlanMapper.listPage(page, stockInventoryCheckPlanDto); stockInventoryCheckPlanDtoIPage.getRecords().forEach(item -> { List stockInventoryCheckProducts = stockInventoryCheckProductMapper.selectList(new LambdaQueryWrapper().eq(StockInventoryCheckProduct::getInventoryCheckPlanId, item.getId())); item.setItems(stockInventoryCheckProducts); }); return stockInventoryCheckPlanDtoIPage ; } @Override public R start(Long id) { StockInventoryCheckPlan stockInventoryCheckPlan = this.getById(id); StockInventoryCheckPlanDto stockInventoryCheckPlanDto = new StockInventoryCheckPlanDto(); BeanUtil.copyProperties(stockInventoryCheckPlan, stockInventoryCheckPlanDto); List stockInventoryCheckProducts = stockInventoryCheckProductMapper.selectList(new LambdaQueryWrapper().eq(StockInventoryCheckProduct::getInventoryCheckPlanId, id)); stockInventoryCheckPlanDto.setItems(stockInventoryCheckProducts); BigDecimal totalQuantity = stockInventoryCheckPlanDto.getItems().stream() .peek(item -> { item.setInventoryCheckPlanId(stockInventoryCheckPlanDto.getId()); List list = stockInventoryService.list(new LambdaQueryWrapper().eq(StockInventory::getProductModelId, item.getProductModelId())); BigDecimal systemQty = list.stream() .map(StockInventory::getQualitity) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); item.setSystemQuantity(systemQty); }) .map(StockInventoryCheckProduct::getSystemQuantity) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); //新增库存盘点 ArrayList stockInventoryCheckItemDtos = new ArrayList<>(); StockInventoryCheckMainDto stockInventoryCheckMainDto = new StockInventoryCheckMainDto(); stockInventoryCheckMainDto.setCheckType("1"); stockInventoryCheckMainDto.setTotalQuantity(totalQuantity); stockInventoryCheckMainDto.setSourceType("1"); stockInventoryCheckMainDto.setSourceId(stockInventoryCheckPlanDto.getId()); stockInventoryCheckMainDto.setStatus(0); stockInventoryCheckPlanDto.getItems().forEach(item -> { List list = stockInventoryService.selectStockInvenrory(item.getProductModelId()); //锁定库存 list.forEach(inventory -> { inventory.setLocked(true); stockInventoryService.updateById(inventory); }); for (StockInventoryDto stockInventory : list) { StockInventoryCheckItemDto stockInventoryCheckItemDto = new StockInventoryCheckItemDto(); stockInventoryCheckItemDto.setProductModelId(stockInventory.getProductModelId()); stockInventoryCheckItemDto.setBatchNo(stockInventory.getBatchNo()); stockInventoryCheckItemDto.setSystemQuantity(stockInventory.getQualitity()); stockInventoryCheckItemDto.setModel(stockInventory.getModel()); stockInventoryCheckItemDto.setUnit(stockInventory.getUnit()); stockInventoryCheckItemDto.setProductName(stockInventory.getProductName()); stockInventoryCheckItemDtos.add(stockInventoryCheckItemDto); } }); stockInventoryCheckMainDto.setStockInventoryCheckItemDtos(stockInventoryCheckItemDtos); stockInventoryCheckMainService.add(stockInventoryCheckMainDto); stockInventoryCheckPlan.setStatus(1); this.updateById(stockInventoryCheckPlan); return R.ok(); } @Override public R end(StockInventoryCheckPlanDto stockInventoryCheckPlanDto) { StockInventoryCheckPlan plan = this.getById(stockInventoryCheckPlanDto.getId()); if (plan == null) { return R.fail("盘点单不存在"); } for (StockInventoryCheckItem item : stockInventoryCheckPlanDto.getCheckItems()) { //更新库存锁定状态 stockInventoryService.updateLocked(item.getProductModelId(),item.getBatchNo(), false); if (item.getDifferenceQuantity() == null || item.getDifferenceQuantity().compareTo(BigDecimal.ZERO) == 0) { continue; } StockInventoryDto stockInventoryDto = new StockInventoryDto(); stockInventoryDto.setProductModelId(item.getProductModelId()); stockInventoryDto.setBatchNo(item.getBatchNo()); stockInventoryDto.setQualitity(item.getDifferenceQuantity()); stockInventoryDto.setRecordId(stockInventoryCheckPlanDto.getId()); if (item.getDifferenceQuantity().compareTo(BigDecimal.ZERO) > 0) { stockInventoryDto.setRecordType(StockInQualifiedRecordTypeEnum.INVENTORY_CHECK_STOCK_IN.getCode()); StockInRecordDto stockInRecordDto = stockUtils.addStockWithBatchNo(stockInventoryDto.getProductModelId(), item.getDifferenceQuantity().abs (), stockInventoryDto.getRecordType(), stockInventoryDto.getRecordId(), stockInventoryDto.getBatchNo()); //直接审核通过 stockInRecordService.batchApprove(Collections.singletonList(stockInRecordDto.getId()), 1); }else { stockInventoryDto.setRecordType(StockInQualifiedRecordTypeEnum.INVENTORY_CHECK_STOCK_OUT.getCode()); StockOutRecordDto stock = stockUtils.substractStock(stockInventoryDto.getProductModelId(), item.getDifferenceQuantity().abs(), stockInventoryDto.getRecordType(), stockInventoryDto.getRecordId(), stockInventoryDto.getBatchNo()); //直接审核通过 stockOutRecordService.batchApprove(Collections.singletonList(stock.getId()), 1); } } stockInventoryCheckItemMapper.updateById(stockInventoryCheckPlanDto.getCheckItems()); plan.setStatus(2); this.updateById(plan); return R.ok("盘点完成,库存已调整"); } @Override public StockInventoryCheckPlanDto detail(Long id) { StockInventoryCheckPlan byId = this.getById(id); if (byId == null) { return null; } StockInventoryCheckPlanDto stockInventoryCheckPlanDto = new StockInventoryCheckPlanDto(); BeanUtil.copyProperties(byId, stockInventoryCheckPlanDto); List items = stockInventoryCheckProductMapper.selectList( new LambdaQueryWrapper() .eq(StockInventoryCheckProduct::getInventoryCheckPlanId, id)); stockInventoryCheckPlanDto.setItems(items); StockInventoryCheckMain checkMain = stockInventoryCheckMainService.getOne( new LambdaQueryWrapper() .eq(StockInventoryCheckMain::getSourceId, id)); if (checkMain != null) { List checkItems = stockInventoryCheckItemMapper.selectList( new LambdaQueryWrapper() .eq(StockInventoryCheckItem::getMainId, checkMain.getId())); stockInventoryCheckPlanDto.setCheckItems(checkItems); } return stockInventoryCheckPlanDto; } @Override public R add(StockInventoryCheckPlanDto stockInventoryCheckPlanDto) { SysUser sysUser = sysUserMapper.selectUserById(stockInventoryCheckPlanDto.getCheckerId()); stockInventoryCheckPlanDto.setCheckerName(sysUser.getNickName()); //生成盘点计划编号 if (ObjectUtils.isEmpty(stockInventoryCheckPlanDto.getPlanNo())) { stockInventoryCheckPlanDto.setPlanNo(OrderUtils.countTodayByCreateTime( stockInventoryCheckPlanMapper, "PD", "plan_no")); } //新增计划 this.save(stockInventoryCheckPlanDto); //设置盘点商品关联ID并查询系统库存 stockInventoryCheckPlanDto.getItems().forEach(item -> { item.setInventoryCheckPlanId(stockInventoryCheckPlanDto.getId()); List list = stockInventoryService.list(new LambdaQueryWrapper().eq(StockInventory::getProductModelId, item.getProductModelId())); BigDecimal systemQty = list.stream() .map(StockInventory::getQualitity) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); item.setSystemQuantity(systemQty); }); //新增盘点商品 stockInventoryCheckProductMapper.insert(stockInventoryCheckPlanDto.getItems()); return R.ok(); } @Override public R edit(StockInventoryCheckPlanDto stockInventoryCheckPlanDto) { SysUser sysUser = sysUserMapper.selectUserById(stockInventoryCheckPlanDto.getCheckerId()); stockInventoryCheckPlanDto.setCheckerName(sysUser.getNickName()); // 查询数据库中的旧数据 List oldItems = stockInventoryCheckProductMapper.selectList( new LambdaQueryWrapper() .eq(StockInventoryCheckProduct::getInventoryCheckPlanId, stockInventoryCheckPlanDto.getId())); // 设置盘点商品关联 ID 并查询系统库存 stockInventoryCheckPlanDto.getItems().forEach(item -> { item.setInventoryCheckPlanId(stockInventoryCheckPlanDto.getId()); // 查询并设置系统库存 List list = stockInventoryService.list( new LambdaQueryWrapper().eq(StockInventory::getProductModelId, item.getProductModelId())); BigDecimal systemQty = list.stream() .map(StockInventory::getQualitity) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); item.setSystemQuantity(systemQty); // 如果旧数据中不存在该 ID,说明是新增,需要清空 ID 让数据库自动生成 boolean isExisting = oldItems.stream().anyMatch(old -> old.getId().equals(item.getId())); if (!isExisting) { item.setId(null); } }); // 使用 insertOrUpdate 批量处理,自动区分新增和更新 stockInventoryCheckProductMapper.insertOrUpdate(stockInventoryCheckPlanDto.getItems()); // 处理删除:旧数据中有但新数据中没有的项 Set newItemIds = stockInventoryCheckPlanDto.getItems().stream() .map(StockInventoryCheckProduct::getId) .filter(Objects::nonNull) .collect(Collectors.toSet()); List toDeleteIds = oldItems.stream() .map(StockInventoryCheckProduct::getId) .filter(id -> !newItemIds.contains(id)) .collect(Collectors.toList()); if (!toDeleteIds.isEmpty()) { stockInventoryCheckProductMapper.deleteByIds(toDeleteIds); } return R.ok(this.updateById(stockInventoryCheckPlanDto)); } @Override public R delete(List ids) { List list = this.list(new LambdaQueryWrapper().in(StockInventoryCheckPlan::getId, ids)); boolean hasNonZeroStatus = list.stream().anyMatch(plan -> plan.getStatus() != null && plan.getStatus() != 0); if (hasNonZeroStatus) { return R.fail("存在已执行或者正在执行的盘点计划,不允许删除"); } return R.ok(this.removeByIds(ids)); } }