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.business.dto.ProductionMasterDto; import com.ruoyi.business.entity.OfficialInventory; import com.ruoyi.business.entity.Production; import com.ruoyi.business.entity.ProductionInventory; import com.ruoyi.business.entity.ProductionMaster; import com.ruoyi.business.mapper.OfficialInventoryMapper; import com.ruoyi.business.mapper.ProductionInventoryMapper; import com.ruoyi.business.mapper.ProductionMapper; import com.ruoyi.business.mapper.ProductionMasterMapper; import com.ruoyi.business.service.ProductionMasterService; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.exception.base.BaseException; import com.ruoyi.common.utils.bean.BeanUtils; import com.ruoyi.system.mapper.SysUserMapper; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.util.*; 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 SysUserMapper sysUserMapper; @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; int totalProductionQuantity = 0; StringBuilder coalBuilder = new StringBuilder(); 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(); if (coalBuilder.length() > 0) { coalBuilder.append(","); // 在元素之间添加逗号 } coalBuilder.append(production.getCoal()); } String coalStr = coalBuilder.toString(); // 直接获取拼接结果 // 2. 创建主表对象 ProductionMaster productionMaster = new ProductionMaster(); productionMaster.setProductionQuantity(totalProductionQuantity); productionMaster.setTotalCost(totalTotalCost); productionMaster.setEquipmentDepreciation(totalEquipmentDepreciation); productionMaster.setEnergyConsumptionCost(totalEnergyConsumptionCost); productionMaster.setLaborCost(totalLaborCost); productionMaster.setCoal(coalStr); Long masterId = productionMasterDto.getId(); productionMaster.setId(masterId); // 3. 统一子表处理逻辑 Long producerId = productionMasterDto.getProducerId(); if (producerId == null) { throw new BaseException("请选择生产者"); } SysUser sysUser = sysUserMapper.selectUserById(producerId); productionMaster.setProducer(sysUser.getUserName()); 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()); return 1; } // 批量插入生产数据 private void batchInsertProductions(Long masterId, List productions) { List insertList = productions.stream() .peek(p -> { p.setId(null); p.setProductionMasterId(masterId); }) .collect(Collectors.toList()); if (!insertList.isEmpty()) { for (Production production : productions) { production.setId(null); production.setProductionMasterId(masterId); 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(); } }