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();
}
}