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.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; import com.ruoyi.common.utils.bean.BeanUtils; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.stock.dto.StockInRecordDto; import com.ruoyi.stock.dto.StockInventoryDto; import com.ruoyi.stock.dto.StockUninventoryDto; import com.ruoyi.stock.execl.StockInRecordExportData; import com.ruoyi.stock.mapper.StockInRecordMapper; 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.service.StockInRecordService; 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 public class StockInRecordServiceImpl extends ServiceImpl 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 listPage(Page page, StockInRecordDto stockInRecordDto) { return stockInRecordMapper.listPage(page, stockInRecordDto); } // 新增入库 @Override @Transactional(rollbackFor = Exception.class) public int add(StockInRecordDto stockInRecordDto) { String no = OrderUtils.countTodayByCreateTime(stockInRecordMapper, "RK"); stockInRecordDto.setInboundBatches(no); StockInRecord stockInRecord = new StockInRecord(); BeanUtils.copyProperties(stockInRecordDto, stockInRecord); return stockInRecordMapper.insert(stockInRecord); } @Override @Transactional(rollbackFor = Exception.class) public int batchDelete(List ids) { for (Long id : ids) { StockInRecord stockInRecord = stockInRecordMapper.selectById(id); 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() .eq(StockInventory::getProductModelId, stockInRecord.getProductModelId()) ); if (stockInventory == null) { throw new BaseException("库存记录中没有对应的产品,无法删除"); } 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() .eq(StockUninventory::getProductModelId, stockInRecord.getProductModelId()) ); if (stockUninventory == null) { 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); } @Override public void exportStockInRecord(HttpServletResponse response, StockInRecordDto stockInRecordDto) { List list = stockInRecordMapper.listStockInRecordExportData(stockInRecordDto); for (StockInRecordExportData stockInRecordExportData : list) { if (stockInRecordExportData.getType().equals("0")) { stockInRecordExportData.setRecordType(EnumUtil.fromCode(StockOutQualifiedRecordTypeEnum.class, Integer.parseInt(stockInRecordExportData.getRecordType())).getValue()); }else { stockInRecordExportData.setRecordType(EnumUtil.fromCode(StockInUnQualifiedRecordTypeEnum.class, Integer.parseInt(stockInRecordExportData.getRecordType())).getValue()); } } ExcelUtil 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().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("库存不足,无法扣减"); } } } }