huminmin
16 小时以前 96d416d310d323e68d42d1ed417f6cea21852d57
src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java
@@ -1,26 +1,39 @@
package com.ruoyi.stock.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.basic.mapper.ProductModelMapper;
import com.ruoyi.basic.pojo.ProductModel;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.stock.dto.StockInRecordDto;
import com.ruoyi.stock.dto.StockInventoryDto;
import com.ruoyi.stock.dto.StockOutRecordDto;
import com.ruoyi.stock.dto.StockUninventoryDto;
import com.ruoyi.stock.execl.StockInventoryExportData;
import com.ruoyi.stock.execl.StockUnInventoryExportData;
import com.ruoyi.stock.mapper.StockInventoryMapper;
import com.ruoyi.stock.mapper.StockUninventoryMapper;
import com.ruoyi.stock.pojo.StockInRecord;
import com.ruoyi.stock.pojo.StockInventory;
import com.ruoyi.stock.pojo.StockUninventory;
import com.ruoyi.stock.mapper.StockUninventoryMapper;
import com.ruoyi.stock.service.StockInRecordService;
import com.ruoyi.stock.service.StockOutRecordService;
import com.ruoyi.stock.service.StockUninventoryService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
/**
@@ -32,12 +45,15 @@
 * @since 2026-01-22 10:17:45
 */
@Service
@AllArgsConstructor
@RequiredArgsConstructor
public class StockUninventoryServiceImpl extends ServiceImpl<StockUninventoryMapper, StockUninventory> implements StockUninventoryService {
    private StockUninventoryMapper stockUninventoryMapper;
    private StockOutRecordService stockOutRecordService;
    private StockInRecordService stockInRecordService;
    private final StockUninventoryMapper stockUninventoryMapper;
    private final StockOutRecordService stockOutRecordService;
    private final StockInRecordService stockInRecordService;
    private final ProductModelMapper productModelMapper;
    private final StockInventoryMapper stockInventoryMapper;
    @Override
    public IPage<StockUninventoryDto> pageStockUninventory(Page page, StockUninventoryDto stockUninventoryDto) {
@@ -47,21 +63,32 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer addStockUninventory(StockUninventoryDto stockUninventoryDto) {
        LambdaQueryWrapper<StockUninventory> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StockUninventory::getProductModelId, stockUninventoryDto.getProductModelId());
        if (StringUtils.isEmpty(stockUninventoryDto.getBatchNo())) {
            stockUninventoryDto.setBatchNo(null);
            wrapper.isNull(StockUninventory::getBatchNo);
        } else {
            wrapper.eq(StockUninventory::getBatchNo, stockUninventoryDto.getBatchNo());
        }
        //新增入库记录再添加库存
        StockInRecordDto stockInRecordDto = new StockInRecordDto();
        stockInRecordDto.setRecordId(stockUninventoryDto.getRecordId());
        stockInRecordDto.setRecordType(stockUninventoryDto.getRecordType());
        stockInRecordDto.setStockInNum(stockUninventoryDto.getQualitity());
        stockInRecordDto.setBatchNo(stockUninventoryDto.getBatchNo());
        stockInRecordDto.setProductModelId(stockUninventoryDto.getProductModelId());
        stockInRecordDto.setType("1");
        stockInRecordService.add(stockInRecordDto);
        //再进行新增库存数量库存
        //先查询库存表中的产品是否存在,不存在新增,存在更新
        StockUninventory oldStockUnInventory = stockUninventoryMapper.selectOne(new QueryWrapper<StockUninventory>().lambda().eq(StockUninventory::getProductModelId, stockUninventoryDto.getProductModelId()));
        StockUninventory oldStockUnInventory = stockUninventoryMapper.selectOne(wrapper);
        if (ObjectUtils.isEmpty(oldStockUnInventory)) {
            StockUninventory newStockUnInventory = new StockUninventory();
            newStockUnInventory.setProductModelId(stockUninventoryDto.getProductModelId());
            newStockUnInventory.setQualitity(stockUninventoryDto.getQualitity());
            newStockUnInventory.setLockedQuantity(stockUninventoryDto.getLockedQuantity());
            newStockUnInventory.setBatchNo(stockUninventoryDto.getBatchNo());
            newStockUnInventory.setVersion(1);
            newStockUnInventory.setRemark(stockUninventoryDto.getRemark());
            stockUninventoryMapper.insert(newStockUnInventory);
@@ -81,6 +108,7 @@
        stockOutRecordDto.setRecordType(stockUninventoryDto.getRecordType());
        stockOutRecordDto.setStockOutNum(stockUninventoryDto.getQualitity());
        stockOutRecordDto.setProductModelId(stockUninventoryDto.getProductModelId());
        stockOutRecordDto.setBatchNo(stockUninventoryDto.getBatchNo());
        stockOutRecordDto.setType("1");
        stockOutRecordService.add(stockOutRecordDto);
        StockUninventory oldStockInventory = stockUninventoryMapper.selectOne(new QueryWrapper<StockUninventory>().lambda().eq(StockUninventory::getProductModelId, stockUninventoryDto.getProductModelId()));
@@ -93,9 +121,170 @@
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer addStockInRecordOnly(StockUninventoryDto stockUninventoryDto) {
        StockInRecordDto stockInRecordDto = new StockInRecordDto();
        stockInRecordDto.setRecordId(stockUninventoryDto.getRecordId());
        stockInRecordDto.setRecordType(stockUninventoryDto.getRecordType());
        stockInRecordDto.setStockInNum(stockUninventoryDto.getQualitity());
        String batchNo = StringUtils.trim(stockUninventoryDto.getBatchNo());
        if (StringUtils.isEmpty(batchNo)) {
            batchNo = generateAutoBatchNo(stockUninventoryDto.getProductModelId());
        }
        stockInRecordDto.setBatchNo(batchNo);
        stockInRecordDto.setProductModelId(stockUninventoryDto.getProductModelId());
        stockInRecordDto.setType("1");
        stockInRecordDto.setRemark(stockUninventoryDto.getRemark());
        stockInRecordService.add(stockInRecordDto);
        return 1;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer addStockOutRecordOnly(StockUninventoryDto stockUninventoryDto) {
        LambdaQueryWrapper<StockUninventory> eq = new LambdaQueryWrapper<>();
        eq.eq(StockUninventory::getProductModelId, stockUninventoryDto.getProductModelId());
        if (StringUtils.isEmpty(stockUninventoryDto.getBatchNo())) {
            eq.isNull(StockUninventory::getBatchNo);
        } else {
            eq.eq(StockUninventory::getBatchNo, stockUninventoryDto.getBatchNo());
        }
        StockUninventory stockUninventory = stockUninventoryMapper.selectOne(eq);
        if (stockUninventory == null) {
            throw new BaseException("库存记录不存在");
        }
        BigDecimal lockedQty = stockUninventory.getLockedQuantity();
        if (lockedQty == null) {
            lockedQty = BigDecimal.ZERO;
        }
        BigDecimal pendingOut = stockUninventoryMapper.selectPendingOutQuantity(
                stockUninventoryDto.getProductModelId(),
                stockUninventoryDto.getBatchNo(),
                "1"
        );
        if (pendingOut == null) {
            pendingOut = BigDecimal.ZERO;
        }
        BigDecimal availableQty = stockUninventory.getQualitity().subtract(lockedQty).subtract(pendingOut);
        if (stockUninventoryDto.getQualitity().compareTo(availableQty) > 0) {
            throw new BaseException("申请数量超过可用库存,当前可用库存为:" + availableQty);
        }
        StockOutRecordDto stockOutRecordDto = new StockOutRecordDto();
        stockOutRecordDto.setRecordId(stockUninventoryDto.getRecordId());
        stockOutRecordDto.setRecordType(stockUninventoryDto.getRecordType());
        stockOutRecordDto.setStockOutNum(stockUninventoryDto.getQualitity());
        stockOutRecordDto.setBatchNo(stockUninventoryDto.getBatchNo());
        stockOutRecordDto.setProductModelId(stockUninventoryDto.getProductModelId());
        stockOutRecordDto.setType("1");
        stockOutRecordDto.setRemark(stockUninventoryDto.getRemark());
        stockOutRecordService.add(stockOutRecordDto);
        return 1;
    }
    @Override
    public void exportStockUninventory(HttpServletResponse response, StockUninventoryDto stockUninventoryDto) {
        List<StockInventoryExportData> list = stockUninventoryMapper.listStockInventoryExportData(stockUninventoryDto);
        ExcelUtil<StockInventoryExportData> util = new ExcelUtil<>(StockInventoryExportData.class);
        List<StockUnInventoryExportData> list = stockUninventoryMapper.listStockInventoryExportData(stockUninventoryDto);
        ExcelUtil<StockUnInventoryExportData> util = new ExcelUtil<>(StockUnInventoryExportData.class);
        util.exportExcel(response,list, "不合格库存信息");
    }
    @Override
    public Boolean frozenStock(StockInventoryDto stockInventoryDto) {
        StockUninventory stockUninventory = stockUninventoryMapper.selectById(stockInventoryDto.getId());
        if (stockUninventory.getQualitity().compareTo(stockInventoryDto.getLockedQuantity())<0) {
            throw new RuntimeException("冻结数量不能超过库存数量");
        }
        if (ObjectUtils.isEmpty(stockUninventory.getLockedQuantity())) {
            stockUninventory.setLockedQuantity(stockInventoryDto.getLockedQuantity());
        }else {
            stockUninventory.setLockedQuantity(stockUninventory.getLockedQuantity().add(stockInventoryDto.getLockedQuantity()));
        }
        return this.updateById(stockUninventory);
    }
    @Override
    public Boolean thawStock(StockInventoryDto stockInventoryDto) {
        StockUninventory stockUninventory = stockUninventoryMapper.selectById(stockInventoryDto.getId());
        if (stockUninventory.getLockedQuantity().compareTo(stockInventoryDto.getLockedQuantity())<0) {
            throw new RuntimeException("解冻数量不能超过冻结数量");
        }
        stockUninventory.setLockedQuantity(stockUninventory.getLockedQuantity().subtract(stockInventoryDto.getLockedQuantity()));
        return this.updateById(stockUninventory);
    }
    //规则生成:20260424-产品编号-001
    private String generateAutoBatchNo(Long productModelId) {
        if (productModelId == null) {
            throw new ServiceException("产品规格ID不能为空");
        }
        ProductModel productModel = productModelMapper.selectById(productModelId);
        if (productModel == null) {
            throw new ServiceException("产品规格不存在,ID=" + productModelId);
        }
        String productCode = StringUtils.trim(productModel.getProductCode());
        if (StringUtils.isEmpty(productCode)) {
            throw new ServiceException("产品规格未维护产品编码,ID=" + productModelId);
        }
        String dateText = LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE);
        String prefix = dateText + "-" + productCode + "-";
        int maxSequence = resolveMaxSequence(prefix);
        int sequence = maxSequence + 1;
        while (sequence < 1_000_000) {
            String batchNo = prefix + String.format("%03d", sequence);
            if (!isBatchNoExists(batchNo)) {
                return batchNo;
            }
            sequence++;
        }
        throw new ServiceException("批号序号超出范围,请检查批号数据");
    }
    private int resolveMaxSequence(String prefix) {
        int maxSequence = 0;
        List<StockInventory> stockInventoryList = stockInventoryMapper.selectList(
                Wrappers.<StockInventory>lambdaQuery()
                        .select(StockInventory::getBatchNo)
                        .likeRight(StockInventory::getBatchNo, prefix));
        for (StockInventory stockInventory : stockInventoryList) {
            maxSequence = Math.max(maxSequence, parseSequence(stockInventory.getBatchNo(), prefix));
        }
        List<StockInRecord> stockInRecordList = stockInRecordService.list(
                Wrappers.<StockInRecord>lambdaQuery()
                        .select(StockInRecord::getBatchNo)
                        .likeRight(StockInRecord::getBatchNo, prefix));
        for (StockInRecord stockInRecord : stockInRecordList) {
            maxSequence = Math.max(maxSequence, parseSequence(stockInRecord.getBatchNo(), prefix));
        }
        return maxSequence;
    }
    private int parseSequence(String batchNo, String prefix) {
        if (StringUtils.isEmpty(batchNo) || StringUtils.isEmpty(prefix) || !batchNo.startsWith(prefix)) {
            return 0;
        }
        String sequenceText = batchNo.substring(prefix.length());
        if (StringUtils.isEmpty(sequenceText) || !sequenceText.matches("\\d+")) {
            return 0;
        }
        try {
            return Integer.parseInt(sequenceText);
        } catch (NumberFormatException ignored) {
            return 0;
        }
    }
    private boolean isBatchNoExists(String batchNo) {
        if (StringUtils.isEmpty(batchNo)) {
            return false;
        }
        Long inventoryCount = stockInventoryMapper.selectCount(
                Wrappers.<StockInventory>lambdaQuery().eq(StockInventory::getBatchNo, batchNo));
        if (inventoryCount != null && inventoryCount > 0) {
            return true;
        }
        return stockInRecordService.count(
                Wrappers.<StockInRecord>lambdaQuery().eq(StockInRecord::getBatchNo, batchNo)) > 0;
    }
}