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.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 dto) { Long masterId = dto.getId(); // 编辑场景:回滚旧库存并删除旧记录 if (masterId != null) { rollbackOldInventory(masterId); deleteChildRecords(masterId); } // 校验使用量并减少库存 validateAndReduceInventory(dto.getProductionInventoryList()); // 构造主表实体对象 ProductionMaster master = buildProductionMaster(dto); // 插入或更新主表 if (masterId == null) { productionMasterMapper.insert(master); masterId = master.getId(); } else { master.setId(masterId); productionMasterMapper.updateById(master); } // 批量插入生产记录与库存记录 batchInsertProductions(masterId, dto.getProductionList()); batchInsertInventories(masterId, dto.getProductionInventoryList()); // 插入待入库数据 insertPendingInventory(dto.getProductionList()); return 1; } /** * 回滚旧的库存数据(将库存数量还原) */ private void rollbackOldInventory(Long masterId) { List oldInventories = productionInventoryMapper.selectList( new LambdaQueryWrapper().eq(ProductionInventory::getProductionMasterId, masterId)); for (ProductionInventory oldInv : oldInventories) { OfficialInventory inv = officialInventoryMapper.selectById(oldInv.getOfficialId()); if (inv != null) { inv.setInventoryQuantity(inv.getInventoryQuantity().add(new BigDecimal(oldInv.getUsedQuantity()))); officialInventoryMapper.updateById(inv); } } } /** * 删除旧的子表数据及待入库数据 */ private void deleteChildRecords(Long masterId) { productionMapper.delete(new LambdaQueryWrapper().eq(Production::getProductionMasterId, masterId)); productionInventoryMapper.delete(new LambdaQueryWrapper().eq(ProductionInventory::getProductionMasterId, masterId)); pendingInventoryMapper.delete(new LambdaQueryWrapper().eq(PendingInventory::getMasterId, masterId)); } /** * 校验每条使用量是否足够,并减少正式库存数量 */ private void validateAndReduceInventory(List inventoryList) { for (ProductionInventory inv : inventoryList) { OfficialInventory official = officialInventoryMapper.selectById(inv.getOfficialId()); BigDecimal used = new BigDecimal(inv.getUsedQuantity()); if (official.getInventoryQuantity().compareTo(used) < 0) { throw new BaseException("库存不足"); } official.setInventoryQuantity(official.getInventoryQuantity().subtract(used)); officialInventoryMapper.updateById(official); } } /** * 构造主表对象并聚合字段值(如总成本、煤种等) */ private ProductionMaster buildProductionMaster(ProductionMasterDto dto) { BigDecimal totalPurchase = BigDecimal.ZERO; BigDecimal totalLabor = BigDecimal.ZERO; BigDecimal totalEnergy = BigDecimal.ZERO; BigDecimal totalCost = BigDecimal.ZERO; BigDecimal totalDepreciation = BigDecimal.ZERO; BigDecimal totalQuantity = BigDecimal.ZERO; List coalIds = new ArrayList<>(); for (Production p : dto.getProductionList()) { totalPurchase = totalPurchase.add(p.getPurchasePrice()); totalLabor = totalLabor.add(p.getLaborCost()); totalEnergy = totalEnergy.add(p.getEnergyConsumptionCost()); totalCost = totalCost.add(p.getTotalCost()); totalDepreciation = totalDepreciation.add(p.getEquipmentDepreciation()); totalQuantity = totalQuantity.add(p.getProductionQuantity()); coalIds.add(p.getCoalId()); } List coalInfos = coalInfoMapper.selectList(new LambdaQueryWrapper().in(CoalInfo::getId, coalIds)); ProductionMaster master = new ProductionMaster(); master.setProductionQuantity(totalQuantity); master.setTotalCost(totalCost); master.setLaborCost(totalLabor); master.setEnergyConsumptionCost(totalEnergy); master.setEquipmentDepreciation(totalDepreciation); master.setCoal(coalInfos.stream().map(CoalInfo::getCoal).collect(Collectors.joining(","))); master.setCoalId(coalIds.stream().map(String::valueOf).collect(Collectors.joining(","))); return master; } /** * 批量插入生产子表数据 */ private void batchInsertProductions(Long masterId, List list) { if (list.isEmpty()) return; for (Production p : list) { Production copy = new Production(); BeanUtils.copyProperties(p, copy); copy.setId(null); copy.setProductionMasterId(masterId); productionMapper.insert(copy); } } /** * 批量插入库存使用子表数据 */ private void batchInsertInventories(Long masterId, List list) { if (list.isEmpty()) return; for (ProductionInventory p : list) { p.setId(null); p.setProductionMasterId(masterId); productionInventoryMapper.insert(p); } } /** * 将加工产生的产品记录到待入库表 */ private void insertPendingInventory(List list) { for (Production p : list) { PendingInventory pending = new PendingInventory(); pending.setCoalId(p.getCoalId()); pending.setInventoryQuantity(p.getProductionQuantity()); pending.setSupplierName("生产加工入库"); pending.setTotalPriceIncludingTax(p.getTotalCost()); pending.setPriceIncludingTax(p.getPurchasePrice()); pending.setPriceIncludingTax(p.getPurchasePrice()); pendingInventoryMapper.insert(pending); } } @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(); } }