package com.ruoyi.sales.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.purchase.mapper.PurchaseLedgerMapper; import com.ruoyi.purchase.pojo.PurchaseLedger; import com.ruoyi.sales.dto.InvoiceRegistrationProductDto; import com.ruoyi.sales.mapper.InvoiceRegistrationProductMapper; import com.ruoyi.sales.mapper.SalesLedgerMapper; import com.ruoyi.sales.mapper.SalesLedgerProductMapper; import com.ruoyi.sales.pojo.InvoiceRegistrationProduct; import com.ruoyi.sales.pojo.SalesLedger; import com.ruoyi.sales.pojo.SalesLedgerProduct; import com.ruoyi.sales.service.ISalesLedgerProductService; import lombok.AllArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import java.lang.reflect.Field; import java.math.BigDecimal; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; /** * 产品信息Service业务层处理 * * @author ruoyi * @date 2025-05-08 */ @Service @AllArgsConstructor public class SalesLedgerProductServiceImpl extends ServiceImpl implements ISalesLedgerProductService { private SalesLedgerProductMapper salesLedgerProductMapper; private SalesLedgerMapper salesLedgerMapper; private PurchaseLedgerMapper purchaseLedgerMapper; @Autowired private InvoiceRegistrationProductMapper invoiceRegistrationProductMapper; @Override public SalesLedgerProduct selectSalesLedgerProductById(Long id) { return salesLedgerProductMapper.selectById(id); } @Override public List selectSalesLedgerProductList(SalesLedgerProduct salesLedgerProduct) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(SalesLedgerProduct::getSalesLedgerId, salesLedgerProduct.getSalesLedgerId()) .eq(SalesLedgerProduct::getType, salesLedgerProduct.getType()); List salesLedgerProducts = salesLedgerProductMapper.selectList(queryWrapper); if(!CollectionUtils.isEmpty(salesLedgerProducts)){ InvoiceRegistrationProductDto invoiceRegistrationProductDto = new InvoiceRegistrationProductDto(); invoiceRegistrationProductDto.setSalesLedgerId(salesLedgerProduct.getSalesLedgerId().intValue()); List invoiceRegistrationProductDtoList = invoiceRegistrationProductMapper.invoiceRegistrationProductList(invoiceRegistrationProductDto); // 统计开票登记产品的已开票数/已开票金额 if(!CollectionUtils.isEmpty(invoiceRegistrationProductDtoList)){ for (SalesLedgerProduct ledgerProduct : salesLedgerProducts) { int invoiceNum = 0; BigDecimal invoiceAmount = BigDecimal.ZERO; for (InvoiceRegistrationProductDto registrationProductDto : invoiceRegistrationProductDtoList) { if(ledgerProduct.getId().intValue() == registrationProductDto.getSalesLedgerProductId()){ invoiceNum += registrationProductDto.getInvoiceNum(); invoiceAmount = invoiceAmount.add(registrationProductDto.getInvoiceAmount()); } } ledgerProduct.setInvoiceNum(invoiceNum); ledgerProduct.setInvoiceAmount(invoiceAmount); } } } return salesLedgerProducts; } @Override @Transactional(rollbackFor = Exception.class) public int deleteSalesLedgerProductByIds(Long[] ids) { if (ids == null || ids.length == 0) { return 0; } // 1. 先查询要删除的子表记录,获取对应的 salesLedgerId List deletedProducts = salesLedgerProductMapper.selectBatchIds(Arrays.asList(ids)); if (deletedProducts.isEmpty()) { return 0; // 没有可删除的数据 } // 可能属于多个主表(但通常一个接口只处理一个主表) Set mainIds = deletedProducts.stream() .map(SalesLedgerProduct::getSalesLedgerId) .filter(Objects::nonNull) .collect(Collectors.toSet()); // 2. 执行删除操作 int result = salesLedgerProductMapper.deleteBatchIds(Arrays.asList(ids)); // 3. 对每个主表ID进行金额更新 for (Long salesLedgerId : mainIds) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(SalesLedgerProduct::getSalesLedgerId, salesLedgerId); List remainingProducts = salesLedgerProductMapper.selectList(wrapper); // 调用通用方法更新主表金额 updateMainContractAmount( salesLedgerId, remainingProducts, SalesLedgerProduct::getTaxInclusiveTotalPrice, salesLedgerMapper, SalesLedger.class ); } return result; } @Override @Transactional(rollbackFor = Exception.class) public int addOrUpdateSalesLedgerProduct(SalesLedgerProduct salesLedgerProduct) { int result; Long salesLedgerId = salesLedgerProduct.getSalesLedgerId(); if (salesLedgerProduct.getId() == null) { result = salesLedgerProductMapper.insert(salesLedgerProduct); } else { result = salesLedgerProductMapper.updateById(salesLedgerProduct); } // 如果插入或更新成功,并且有 salesLedgerId,才继续更新主表金额 if (result > 0 && salesLedgerId != null) { // 查询该主表下的所有子表数据 LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(SalesLedgerProduct::getSalesLedgerId, salesLedgerId) .eq(SalesLedgerProduct::getType, salesLedgerProduct.getType()); List productList = salesLedgerProductMapper.selectList(wrapper); if (salesLedgerProduct.getType() == 1) { // 调用通用方法更新主表金额 updateMainContractAmount( salesLedgerId, productList, SalesLedgerProduct::getTaxInclusiveTotalPrice, salesLedgerMapper, SalesLedger.class ); } else { // 调用通用方法更新主表金额 updateMainContractAmount( salesLedgerId, productList, SalesLedgerProduct::getTaxInclusiveTotalPrice, purchaseLedgerMapper, PurchaseLedger.class ); } } return result; } /** * 通用方法:根据主表ID和子表列表,更新主表的合同金额 */ public void updateMainContractAmount( Long mainId, List subList, Function amountGetter, BaseMapper mainMapper, Class mainEntityClass) { if (mainId == null || subList == null || subList.isEmpty()) { return; } BigDecimal totalAmount = subList.stream() .map(amountGetter) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); try { S entity = mainEntityClass.getDeclaredConstructor().newInstance(); Field idField = mainEntityClass.getDeclaredField("id"); idField.setAccessible(true); idField.set(entity, mainId); Field amountField = mainEntityClass.getDeclaredField("contractAmount"); amountField.setAccessible(true); amountField.set(entity, totalAmount); mainMapper.updateById(entity); } catch (Exception e) { throw new RuntimeException("动态更新主表金额失败", e); } } }