src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java
@@ -1,11 +1,14 @@
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.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.enums.StockQualifiedRecordTypeEnum;
import com.ruoyi.common.enums.StockUnQualifiedRecordTypeEnum;
import com.ruoyi.basic.mapper.ProductModelMapper;
import com.ruoyi.basic.pojo.ProductModel;
import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum;
import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.EnumUtil;
import com.ruoyi.common.utils.OrderUtils;
@@ -22,20 +25,29 @@
import com.ruoyi.stock.pojo.StockInventory;
import com.ruoyi.stock.pojo.StockUninventory;
import com.ruoyi.stock.service.StockInRecordService;
import lombok.AllArgsConstructor;
import com.ruoyi.stock.word.WeighbridgeDocGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
@Service
@AllArgsConstructor
public class StockInRecordServiceImpl extends ServiceImpl<StockInRecordMapper, StockInRecord> implements StockInRecordService {
    @Autowired
    private StockInRecordMapper stockInRecordMapper;
    @Autowired
    private StockInventoryMapper stockInventoryMapper;
    @Autowired
    private StockUninventoryMapper stockUninventoryMapper;
    @Autowired
    private WeighbridgeDocGenerator weighbridgeDocGenerator;
    @Autowired
    private ProductModelMapper productModelMapper;
    @Override
    public IPage<StockInRecordDto> listPage(Page page, StockInRecordDto stockInRecordDto) {
@@ -55,45 +67,74 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int update(Long id, StockInRecordDto stockInRecordDto) {
        // 判断对象是否存在
        StockInRecord stockInRecord = stockInRecordMapper.selectById(id);
        if (stockInRecord == null){
            throw new BaseException("该入库记录不存在,无法更新!!!");
        }
        String[] ignoreProperties = {"id", "inbound_batches"};//排除id属性
        BeanUtils.copyProperties(stockInRecordDto, stockInRecord, ignoreProperties);
        return stockInRecordMapper.updateById(stockInRecord);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchDelete(List<Long> ids) {
        for (Long id : ids) {
            StockInRecord stockInRecord = stockInRecordMapper.selectById(id);
            if (stockInRecord.getType().equals("0")) {
                StockInventory stockInventory = stockInventoryMapper.selectOne(new LambdaQueryWrapper<StockInventory>().eq(StockInventory::getProductModelId, stockInRecord.getProductModelId()));
            if (stockInRecord == null) {
                throw new BaseException("入库记录不存在,ID:" + id);
            }
            // 查询产品型号(用于单位转换)
            ProductModel productModel = productModelMapper.selectById(stockInRecord.getProductModelId());
            if (productModel == null) {
                throw new BaseException("产品型号不存在,无法删除");
            }
            // 获取入库数量及其单位,转换为库存单位
            BigDecimal stockInNum = stockInRecord.getStockInNum();  // 入库记录中存储的数量
            String sourceUnit = stockInRecord.getUnit();  // 入库记录的单位
            String stockUnit = productModel.getUnit();  // 库存单位
            // 将入库数量转换为库存单位
            BigDecimal convertedQuantity = convertQuantityToStockUnit(stockInNum, sourceUnit, stockUnit);
            // 根据入库类型处理不同的库存表
            if ("0".equals(stockInRecord.getType())) {
                // 正常入库,删除时扣减库存
                StockInventory stockInventory = stockInventoryMapper.selectOne(
                        new LambdaQueryWrapper<StockInventory>()
                                .eq(StockInventory::getProductModelId, stockInRecord.getProductModelId())
                );
                if (stockInventory == null) {
                    throw new BaseException("库存记录中没有对应的产品,无法删除!!!");
                }else {
                    StockInventoryDto stockInRecordDto = new StockInventoryDto();
                    stockInRecordDto.setProductModelId(stockInventory.getProductModelId());
                    stockInRecordDto.setQualitity(stockInRecord.getStockInNum());
                    stockInventoryMapper.updateAddStockInventory(stockInRecordDto);
                    throw new BaseException("库存记录中没有对应的产品,无法删除");
                }
            }else if (stockInRecord.getType().equals("1")) {
                StockUninventory stockUninventory = stockUninventoryMapper.selectOne(new LambdaQueryWrapper<StockUninventory>().eq(StockUninventory::getProductModelId, stockInRecord.getProductModelId()));
                StockInventoryDto inventoryDto = new StockInventoryDto();
                inventoryDto.setProductModelId(stockInventory.getProductModelId());
                inventoryDto.setQualitity(convertedQuantity);
                // 扣减库存(删除入库记录相当于减少库存)
                int affectedRows = stockInventoryMapper.updateSubtractStockInventory(inventoryDto);
                if (affectedRows == 0) {
                    throw new BaseException("扣减库存失败,库存可能不足");
                }
            } else if ("1".equals(stockInRecord.getType())) {
                // 非正常入库,删除时扣减非正常库存
                StockUninventory stockUninventory = stockUninventoryMapper.selectOne(
                        new LambdaQueryWrapper<StockUninventory>()
                                .eq(StockUninventory::getProductModelId, stockInRecord.getProductModelId())
                );
                if (stockUninventory == null) {
                    throw new BaseException("库存记录中没有对应的产品,无法删除!!!");
                }else {
                    StockUninventoryDto stockUninventoryDto = new StockUninventoryDto();
                    stockUninventoryDto.setProductModelId(stockUninventory.getProductModelId());
                    stockUninventoryDto.setQualitity(stockInRecord.getStockInNum());
                    stockUninventoryMapper.updateAddStockUnInventory(stockUninventoryDto);
                    throw new BaseException("非正常库存记录中没有对应的产品,无法删除");
                }
                // 创建非正常库存更新DTO
                StockUninventoryDto uninventoryDto = new StockUninventoryDto();
                uninventoryDto.setProductModelId(stockUninventory.getProductModelId());
                uninventoryDto.setQualitity(convertedQuantity);
                // 扣减非正常库存
                int affectedRows = stockUninventoryMapper.updateSubtractStockUnInventory(uninventoryDto);
                if (affectedRows == 0) {
                    throw new BaseException("扣减非正常库存失败");
                }
            }
        }
        // 5. 批量删除入库记录
        return stockInRecordMapper.deleteBatchIds(ids);
    }
@@ -102,12 +143,158 @@
        List<StockInRecordExportData> list = stockInRecordMapper.listStockInRecordExportData(stockInRecordDto);
        for (StockInRecordExportData stockInRecordExportData : list) {
            if (stockInRecordExportData.getType().equals("0")) {
                stockInRecordExportData.setRecordType(EnumUtil.fromCode(StockQualifiedRecordTypeEnum.class, Integer.parseInt(stockInRecordExportData.getRecordType())).getValue());
                stockInRecordExportData.setRecordType(EnumUtil.fromCode(StockOutQualifiedRecordTypeEnum.class, Integer.parseInt(stockInRecordExportData.getRecordType())).getValue());
            }else {
                stockInRecordExportData.setRecordType(EnumUtil.fromCode(StockUnQualifiedRecordTypeEnum.class, Integer.parseInt(stockInRecordExportData.getRecordType())).getValue());
                stockInRecordExportData.setRecordType(EnumUtil.fromCode(StockInUnQualifiedRecordTypeEnum.class, Integer.parseInt(stockInRecordExportData.getRecordType())).getValue());
            }
        }
        ExcelUtil<StockInRecordExportData> util = new ExcelUtil<>(StockInRecordExportData.class);
        util.exportExcel(response,list, "入库记录信息");
    }
    @Override
    public int editStockInStock(StockInRecordDto stockInRecordDto) {
        if (stockInRecordDto.getId() == null) {
            throw new BaseException("入库记录ID不能为空");
        }
        // 1. 查询原始入库记录
        StockInRecord originalRecord = stockInRecordMapper.selectById(stockInRecordDto.getId());
        if (originalRecord == null) {
            throw new BaseException("入库记录不存在");
        }
        // 2. 查询产品型号信息(用于单位转换)
        ProductModel productModel = productModelMapper.selectById(originalRecord.getProductModelId());
        if (productModel == null) {
            throw new BaseException("产品型号不存在");
        }
        // 3. 获取原始入库数量及其单位
        BigDecimal originalNetWeight = originalRecord.getStockInNum();  // 原始记录中存储的数量
        String originalUnit = originalRecord.getUnit();  // 原始记录的单位
        String stockUnit = productModel.getUnit();  // 库存单位
        // 将原始入库数量转换为库存单位
        BigDecimal originalNetWeightInStockUnit = convertQuantityToStockUnit(originalNetWeight, originalUnit, stockUnit);
        // 4. 获取新入库数量及其单位
        BigDecimal newNetWeight = stockInRecordDto.getNetWeight();  // 新输入的数量
        if (newNetWeight == null) {
            throw new BaseException("净重不能为空");
        }
        String newUnit = stockInRecordDto.getUnit();  // 新输入的单位
        // 将新入库数量转换为库存单位
        BigDecimal newNetWeightInStockUnit = convertQuantityToStockUnit(newNetWeight, newUnit, stockUnit);
        // 5. 计算库存变化量(使用统一转换后的库存单位值)
        // 入库数量变化量(正数表示入库变多,需要增加库存;负数表示入库变少,需要减少库存)
        BigDecimal diffQuantity = newNetWeightInStockUnit.subtract(originalNetWeightInStockUnit);
        // 6. 更新入库记录(保存用户输入的原始数值和单位)
        stockInRecordDto.setStockInNum(stockInRecordDto.getNetWeight());
        stockInRecordDto.setUnit(stockInRecordDto.getUnit());
        // 7. 生成磅单
        String absoluteDocPath = weighbridgeDocGenerator.generateWeighbridgeDoc(stockInRecordDto);
        stockInRecordDto.setWeighbridgeDocPath(absoluteDocPath);
        int updateResult = stockInRecordMapper.updateById(stockInRecordDto);
        // 8. 更新库存(仅在数量发生变化时)
        if (diffQuantity.compareTo(BigDecimal.ZERO) != 0) {
            updateInventory(stockInRecordDto.getProductId(), diffQuantity);
        }
        return updateResult;
    }
    /**
     * 将数量转换为库存单位
     * @param quantity 原始数量
     * @param sourceUnit 原始单位
     * @param targetUnit 目标单位(库存单位)
     * @return 转换后的数量
     */
    private BigDecimal convertQuantityToStockUnit(BigDecimal quantity, String sourceUnit, String targetUnit) {
        if (quantity == null) {
            throw new BaseException("数量不能为空");
        }
        if (sourceUnit == null || sourceUnit.isEmpty()) {
            return quantity;
        }
        if (sourceUnit.equals(targetUnit)) {
            return quantity;
        }
        // 单位转换
        if ("吨".equals(targetUnit)) {
            // 目标单位是吨,需要将源单位转换为吨
            if ("公斤".equals(sourceUnit)) {
                // 公斤转吨:除以1000
                return quantity.divide(BigDecimal.valueOf(1000), 2, RoundingMode.HALF_UP);
            } else if ("克".equals(sourceUnit)) {
                // 克转吨:除以1000000
                return quantity.divide(BigDecimal.valueOf(1000000), 2, RoundingMode.HALF_UP);
            }
        } else if ("公斤".equals(targetUnit)) {
            // 目标单位是公斤
            if ("吨".equals(sourceUnit)) {
                // 吨转公斤:乘以1000
                return quantity.multiply(BigDecimal.valueOf(1000));
            } else if ("克".equals(sourceUnit)) {
                // 克转公斤:除以1000
                return quantity.divide(BigDecimal.valueOf(1000), 2, RoundingMode.HALF_UP);
            }
        } else if ("克".equals(targetUnit)) {
            // 目标单位是克
            if ("吨".equals(sourceUnit)) {
                // 吨转克:乘以1000000
                return quantity.multiply(BigDecimal.valueOf(1000000));
            } else if ("公斤".equals(sourceUnit)) {
                // 公斤转克:乘以1000
                return quantity.multiply(BigDecimal.valueOf(1000));
            }
        }
        return quantity;
    }
    /**
     * 更新库存
     * @param productId 产品ID
     * @param diffQuantity 库存变化量(正数为增加,负数为减少)
     */
    private void updateInventory(Long productId, BigDecimal diffQuantity) {
        // 查询当前库存
        StockInventory stockInventory = stockInventoryMapper.selectOne(
                new QueryWrapper<StockInventory>().lambda()
                        .eq(StockInventory::getProductId, productId)
        );
        if (stockInventory == null) {
            throw new BaseException("库存记录不存在");
        }
        StockInventoryDto inventoryDto = new StockInventoryDto();
        BeanUtils.copyProperties(stockInventory, inventoryDto);
        inventoryDto.setQualitity(diffQuantity.abs());
        // 根据变化量正负调用不同的更新方法
        if (diffQuantity.compareTo(BigDecimal.ZERO) > 0) {
            // 增加库存
            int affectedRows = stockInventoryMapper.updateAddStockInventory(inventoryDto);
            if (affectedRows == 0) {
                throw new BaseException("更新库存失败");
            }
        } else {
            // 减少库存
            int affectedRows = stockInventoryMapper.updateSubtractStockInventory(inventoryDto);
            if (affectedRows == 0) {
                throw new BaseException("库存不足,无法扣减");
            }
        }
    }
}