package com.ruoyi.business.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.basic.entity.CoalInfo; import com.ruoyi.basic.mapper.CoalInfoMapper; import com.ruoyi.business.dto.ProductionMasterDto; import com.ruoyi.business.entity.*; import com.ruoyi.business.mapper.*; import com.ruoyi.business.service.ProductionMasterService; import com.ruoyi.common.exception.base.BaseException; import com.ruoyi.common.utils.bean.BeanUtils; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; /** *

* 生产主表 服务实现类 *

* * @author ruoyi * @since 2025-06-13 */ @Service @RequiredArgsConstructor public class ProductionMasterServiceImpl extends ServiceImpl implements ProductionMasterService { private final ProductionMasterMapper productionMasterMapper; private final ProductionInventoryMapper productionInventoryMapper; private final ProductionMapper productionMapper; private final OfficialInventoryMapper officialInventoryMapper; private final CoalInfoMapper coalInfoMapper; private final PendingInventoryMapper pendingInventoryMapper; @Override public IPage selectPMList(Page page, ProductionMasterDto productionMasterDto) { // 1. 构建主表查询条件 LambdaQueryWrapper masterQueryWrapper = new LambdaQueryWrapper<>(); // 2. 执行主表分页查询 IPage entityPage = productionMasterMapper.selectPage(page, masterQueryWrapper); // 3. 提取主表ID列表用于批量查询子表数据 List masterIds = entityPage.getRecords().stream() .map(ProductionMaster::getId) .collect(Collectors.toList()); // 4. 批量查询关联数据(避免N+1问题) Map> productionMap = queryProductionByMasterIds(masterIds); Map> inventoryMap = queryInventoryByMasterIds(masterIds); // 5. 转换数据并组装结果 List dtoList = entityPage.getRecords().stream() .map(record -> { ProductionMasterDto dto = new ProductionMasterDto(); BeanUtils.copyProperties(record, dto); dto.setProductionList(productionMap.getOrDefault(record.getId(), Collections.emptyList())); dto.setProductionInventoryList(inventoryMap.getOrDefault(record.getId(), Collections.emptyList())); return dto; }) .collect(Collectors.toList()); // 6. 构建返回结果 IPage dtoPage = new Page<>(); BeanUtils.copyProperties(entityPage, dtoPage, "records"); dtoPage.setRecords(dtoList); return dtoPage; } /** * 批量查询Production数据 */ private Map> queryProductionByMasterIds(List masterIds) { if (masterIds.isEmpty()) { return Collections.emptyMap(); } LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.in(Production::getProductionMasterId, masterIds); List productions = productionMapper.selectList(queryWrapper); return productions.stream() .collect(Collectors.groupingBy(Production::getProductionMasterId)); } /** * 批量查询ProductionInventory数据 */ private Map> queryInventoryByMasterIds(List masterIds) { if (masterIds.isEmpty()) { return Collections.emptyMap(); } LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.in(ProductionInventory::getProductionMasterId, masterIds); List inventoryList = productionInventoryMapper.selectList(queryWrapper); return inventoryList.stream() .collect(Collectors.groupingBy(ProductionInventory::getProductionMasterId)); } @Override @Transactional public int addOrEditPM(ProductionMasterDto productionMasterDto) { // 1. 直接计算聚合值,避免创建多余列表 BigDecimal totalPurchasePrice = BigDecimal.ZERO; BigDecimal totalLaborCost = BigDecimal.ZERO; BigDecimal totalEnergyConsumptionCost = BigDecimal.ZERO; BigDecimal totalTotalCost = BigDecimal.ZERO; BigDecimal totalEquipmentDepreciation = BigDecimal.ZERO; BigDecimal totalProductionQuantity = BigDecimal.ZERO; for (Production production : productionMasterDto.getProductionList()) { totalPurchasePrice = totalPurchasePrice.add(production.getPurchasePrice()); totalLaborCost = totalLaborCost.add(production.getLaborCost()); totalEnergyConsumptionCost = totalEnergyConsumptionCost.add(production.getEnergyConsumptionCost()); totalTotalCost = totalTotalCost.add(production.getTotalCost()); totalEquipmentDepreciation = totalEquipmentDepreciation.add(production.getEquipmentDepreciation()); totalProductionQuantity = production.getProductionQuantity().add(totalProductionQuantity); } //煤种字段 List coalIds = productionMasterDto.getProductionList().stream() .map(Production::getCoalId) .collect(Collectors.toList()); List coalInfos = coalInfoMapper.selectList(new LambdaQueryWrapper().in(CoalInfo::getId, coalIds)); // 2. 创建主表对象 ProductionMaster productionMaster = new ProductionMaster(); productionMaster.setProductionQuantity(totalProductionQuantity); productionMaster.setTotalCost(totalTotalCost); productionMaster.setEquipmentDepreciation(totalEquipmentDepreciation); productionMaster.setEnergyConsumptionCost(totalEnergyConsumptionCost); productionMaster.setLaborCost(totalLaborCost); productionMaster.setCoal(coalInfos.stream().map(CoalInfo::getCoal).collect(Collectors.joining(","))); productionMaster.setCoalId(coalIds.stream().map(String::valueOf).collect(Collectors.joining(","))); Long masterId = productionMasterDto.getId(); productionMaster.setId(masterId); // 3. 统一子表处理逻辑 if (masterId == null) { productionMasterMapper.insert(productionMaster); masterId = productionMaster.getId(); // 获取新生成的ID } else { // 删除关联子表数据 productionMapper.delete(new LambdaQueryWrapper() .eq(Production::getProductionMasterId, masterId)); productionInventoryMapper.delete(new LambdaQueryWrapper() .eq(ProductionInventory::getProductionMasterId, masterId)); productionMasterMapper.updateById(productionMaster); } //库存更新 for (ProductionInventory productionInventory : productionMasterDto.getProductionInventoryList()) { OfficialInventory officialInventory = officialInventoryMapper.selectById(productionInventory.getOfficialId()); BigDecimal subtract = officialInventory.getInventoryQuantity().subtract(new BigDecimal(productionInventory.getUsedQuantity())); if (subtract.compareTo(BigDecimal.ZERO) < 0) { throw new BaseException("库存不足"); } officialInventory.setInventoryQuantity(subtract); officialInventoryMapper.updateById(officialInventory); } // 4. 批量插入子表数据 batchInsertProductions(masterId, productionMasterDto.getProductionList()); batchInsertInventories(masterId, productionMasterDto.getProductionInventoryList()); //5. 插入到待入库 for (Production production : productionMasterDto.getProductionList()) { PendingInventory pendingInventory = new PendingInventory(); pendingInventory.setCoalId(production.getCoalId()); pendingInventory.setInventoryQuantity(production.getProductionQuantity()); pendingInventory.setSupplierName("生产加工入库"); pendingInventory.setTotalPriceIncludingTax(production.getTotalCost()); pendingInventory.setPriceIncludingTax(production.getPurchasePrice()); } return 1; } // 批量插入生产数据 private void batchInsertProductions(Long masterId, List productions) { if (productions.isEmpty()) { return; } // 1. 收集所有需要查询的coalId List coalIds = productions.stream() .map(Production::getCoalId) .filter(Objects::nonNull) .distinct() .collect(Collectors.toList()); // 2. 批量查询coalInfo数据 Map coalInfoMap = coalIds.isEmpty() ? Collections.emptyMap() : coalInfoMapper.selectList(new LambdaQueryWrapper().in(CoalInfo::getId, coalIds)) .stream() .collect(Collectors.toMap(CoalInfo::getId, Function.identity())); if (coalInfoMap.isEmpty()){ throw new BaseException("煤种信息不存在"); } // 3. 准备批量插入数据 List batchInsertList = productions.stream() .map(production -> { Production p = new Production(); // 创建新对象避免副作用 BeanUtils.copyProperties(production, p); // 复制必要字段 p.setProductionMasterId(masterId); p.setCoalId(production.getCoalId()); return p; }) .collect(Collectors.toList()); if (!batchInsertList.isEmpty()) { for (Production production : batchInsertList) { production.setId(null); productionMapper.insert(production); } } } // 批量插入库存数据 private void batchInsertInventories(Long masterId, List inventories) { List insertList = inventories.stream() .peek(inv -> { inv.setId(null); inv.setProductionMasterId(masterId); }) .collect(Collectors.toList()); if (!insertList.isEmpty()) { for (ProductionInventory inventory : inventories) { inventory.setId(null); inventory.setProductionMasterId(masterId); productionInventoryMapper.insert(inventory); } } } @Override @Transactional(rollbackFor = Exception.class) public int delByIds(Long[] ids) { if (ids == null || ids.length == 0) { return 0; } List idList = Arrays.asList(ids); // 1. 预加载所有关联数据 List allInventoryList = productionInventoryMapper.selectList( new LambdaQueryWrapper() .in(ProductionInventory::getProductionMasterId, idList) ); // 2. 按官方库存ID分组并计算库存调整量 Map inventoryAdjustMap = allInventoryList.stream() .collect(Collectors.groupingBy( ProductionInventory::getOfficialId, Collectors.reducing( BigDecimal.ZERO, inv -> new BigDecimal(inv.getUsedQuantity()), BigDecimal::add ) )); // 3. 批量更新官方库存 (使用SQL直接更新) if (!inventoryAdjustMap.isEmpty()) { inventoryAdjustMap.forEach((officialId, adjustAmount) -> officialInventoryMapper.addInventoryQuantity(officialId, adjustAmount) ); } // 4. 批量删除关联数据 if (!allInventoryList.isEmpty()) { List inventoryIds = allInventoryList.stream() .map(ProductionInventory::getId) .collect(Collectors.toList()); productionInventoryMapper.deleteBatchIds(inventoryIds); } // 删除生产明细 productionMapper.delete( new LambdaQueryWrapper() .in(Production::getProductionMasterId, idList) ); // 5. 删除主记录 return productionMasterMapper.deleteBatchIds(idList); } @Override @Transactional(rollbackFor = Exception.class) public int deleteProductionInventory(ProductionMasterDto productionMasterDto) { List inventories = productionMasterDto.getProductionInventoryList(); if (CollectionUtils.isEmpty(inventories)) { return 0; } // 预收集数据用于批量操作 Map inventoryAdjustMap = new HashMap<>(); List productionIdsToDelete = new ArrayList<>(inventories.size()); for (ProductionInventory inventory : inventories) { // 收集需要删除的生产库存ID productionIdsToDelete.add(inventory.getId()); // 累计库存调整量(相同officialId的用量累加) BigDecimal adjustment = new BigDecimal(inventory.getUsedQuantity()); inventoryAdjustMap.merge( inventory.getOfficialId(), adjustment, BigDecimal::add ); } // 批量更新官方库存 for (Map.Entry entry : inventoryAdjustMap.entrySet()) { OfficialInventory official = officialInventoryMapper.selectById(entry.getKey()); if (official == null) { throw new BaseException("官方库存不存在,ID: " + entry.getKey()); } // 使用线程安全的BigDecimal操作 official.setInventoryQuantity( Optional.ofNullable(official.getInventoryQuantity()) .orElse(BigDecimal.ZERO) .add(entry.getValue()) ); officialInventoryMapper.updateById(official); } // 批量删除生产库存 if (!productionIdsToDelete.isEmpty()) { productionInventoryMapper.deleteBatchIds(productionIdsToDelete); } return productionIdsToDelete.size(); } }