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.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
/**
*
* 盘点计划表 服务实现类
*
*
* @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());
//赋值
//设置盘点商品关联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.insertOrUpdate(stockInventoryCheckPlanDto.getItems());
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));
}
}