package com.ruoyi.purchase.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 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.mapper.SupplierManageMapper; import com.ruoyi.basic.pojo.SupplierManage; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.framework.security.LoginUser; import com.ruoyi.purchase.dto.PaymentLedgerDto; import com.ruoyi.purchase.dto.PaymentRegistrationDto; import com.ruoyi.purchase.mapper.*; import com.ruoyi.purchase.pojo.PaymentRegistration; import com.ruoyi.purchase.pojo.ProductRecord; import com.ruoyi.purchase.pojo.PurchaseLedger; import com.ruoyi.purchase.pojo.TicketRegistration; import com.ruoyi.purchase.service.IPaymentRegistrationService; import com.ruoyi.sales.mapper.SalesLedgerMapper; import com.ruoyi.sales.mapper.SalesLedgerProductMapper; import com.ruoyi.sales.pojo.SalesLedger; import com.ruoyi.sales.pojo.SalesLedgerProduct; import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.YearMonth; import java.util.*; import java.util.stream.Collectors; /** * 付款登记Service业务层处理 * * @author ruoyi * @date 2025-05-15 */ @Service @AllArgsConstructor public class PaymentRegistrationServiceImpl extends ServiceImpl implements IPaymentRegistrationService { private PaymentRegistrationMapper paymentRegistrationMapper; private PurchaseLedgerMapper purchaseLedgerMapper; private InvoicePurchaseMapper invoicePurchaseMapper; private SalesLedgerMapper salesLedgerMapper; private SupplierManageMapper supplierManageMapper; private SalesLedgerProductMapper salesLedgerProductMapper; private TicketRegistrationMapper ticketRegistrationMapper; private ProductRecordMapper productRecordMapper; /** * 查询付款登记 * * @param id 付款登记主键 * @return 付款登记 */ @Override public PaymentRegistration selectPaymentRegistrationById(Long id) { return paymentRegistrationMapper.selectPaymentRegistrationById(id); } /** * 查询付款登记列表 * * @param paymentRegistrationDto 付款登记 * @return 付款登记 */ @Override public List selectPaymentRegistrationList(PaymentRegistrationDto paymentRegistrationDto) { List list = paymentRegistrationMapper.selectPaymentRegistrationList(paymentRegistrationDto); for (PaymentRegistrationDto registrationDto : list) { List paymentRegistrations = paymentRegistrationMapper.selectList(new QueryWrapper() .eq("ticket_registration_id", registrationDto.getTicketRegistrationId())); BigDecimal total = paymentRegistrations.stream().map(PaymentRegistration::getCurrentPaymentAmount).reduce(BigDecimal.ZERO, BigDecimal::add); registrationDto.setUnPaymentAmount(registrationDto.getInvoiceAmount().subtract(total)); } return list; } /** * 新增付款登记 * * @param paymentRegistration 付款登记 * @return 结果 */ @Override public int insertPaymentRegistration(PaymentRegistration paymentRegistration) { PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(paymentRegistration.getPurchaseLedgerId()); SalesLedger salesLedger = salesLedgerMapper.selectOne(new QueryWrapper(). eq("sales_contract_no", purchaseLedger.getSalesContractNo())); if (salesLedger == null) { throw new RuntimeException("关联销售合同号不存在"); } paymentRegistration.setSaleLedgerId(salesLedger.getId()); paymentRegistration.setSupplierId(purchaseLedger.getSupplierId()); TicketRegistration tr = ticketRegistrationMapper.selectOne(new LambdaQueryWrapper().eq(TicketRegistration::getId, paymentRegistration.getTicketRegistrationId())); if (tr == null) { throw new RuntimeException("关联发票不存在"); } List paymentRegistrations = paymentRegistrationMapper.selectList(new QueryWrapper() .eq("ticket_registration_id", tr.getId())); BigDecimal total = paymentRegistrations.stream().map(PaymentRegistration::getCurrentPaymentAmount).reduce(BigDecimal.ZERO, BigDecimal::add); if (total.add(paymentRegistration.getCurrentPaymentAmount()).compareTo(tr.getInvoiceAmount()) > 0) { throw new RuntimeException("付款金额超出发票金额"); } LoginUser loginUser = SecurityUtils.getLoginUser(); Integer tenantId = loginUser.getTenantId(); paymentRegistration.setTenantId(tenantId.longValue()); paymentRegistration.setRegistrantId(loginUser.getUserId()); paymentRegistration.setCreateTime(DateUtils.getNowDate()); paymentRegistration.setUpdateTime(DateUtils.getNowDate()); return paymentRegistrationMapper.insert(paymentRegistration); } /** * 修改付款登记 * * @param paymentRegistration 付款登记 * @return 结果 */ @Override public int updatePaymentRegistration(PaymentRegistration paymentRegistration) { TicketRegistration ticketRegistration = ticketRegistrationMapper.selectById(paymentRegistration.getTicketRegistrationId()); List paymentRegistrations = paymentRegistrationMapper.selectList(new QueryWrapper() .eq("ticket_registration_id", paymentRegistration.getTicketRegistrationId()).ne("id", paymentRegistration.getId())); BigDecimal total = paymentRegistrations.stream().map(PaymentRegistration::getCurrentPaymentAmount).reduce(BigDecimal.ZERO, BigDecimal::add); if (total.add(paymentRegistration.getCurrentPaymentAmount()).compareTo(ticketRegistration.getInvoiceAmount()) > 0) { throw new RuntimeException("付款金额超出发票金额"); } paymentRegistration.setUpdateTime(DateUtils.getNowDate()); return paymentRegistrationMapper.updateById(paymentRegistration); } /** * 批量删除付款登记 * * @param ids 需要删除的付款登记主键 * @return 结果 */ @Override public int deletePaymentRegistrationByIds(Long[] ids) { return paymentRegistrationMapper.delete(new QueryWrapper().in("id", ids)); } @Override public PaymentRegistration selectPaymentRegistrationByPurchaseId(Long id) { PaymentRegistrationDto paymentRegistrationDto = new PaymentRegistrationDto(); PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(id); paymentRegistrationDto.setSalesContractNo(purchaseLedger.getSalesContractNo()); paymentRegistrationDto.setSupplierName(purchaseLedger.getSupplierName()); paymentRegistrationDto.setSupplierId(purchaseLedger.getSupplierId()); List ticketRegistrations = ticketRegistrationMapper.selectList(new QueryWrapper() .eq("purchase_contract_number", purchaseLedger.getPurchaseContractNumber())); if (ticketRegistrations != null && ticketRegistrations.size() > 0) { paymentRegistrationDto.setInvoiceNumber(ticketRegistrations.get(0).getInvoiceNumber()); paymentRegistrationDto.setInvoiceAmount(ticketRegistrations.get(0).getInvoiceAmount()); } return paymentRegistrationDto; } @Override public IPage> selectPaymentLedgerList( PaymentLedgerDto paymentLedgerDto, Page page, Integer detailPageNum, Integer detailPageSize) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); Optional.ofNullable(paymentLedgerDto) .ifPresent(dto -> { if (StringUtils.hasText(dto.getSupplierName())) { queryWrapper.like(SupplierManage::getSupplierName, dto.getSupplierName()); } }); IPage supplierPage = supplierManageMapper.selectPage(page, queryWrapper); List supplierManages = supplierPage.getRecords(); IPage> resultPage = new Page<>(page.getCurrent(), page.getSize(), supplierPage.getTotal()); List> result = new ArrayList<>(); for (SupplierManage supplierManage : supplierManages) { Map res = new HashMap<>(); res.put("supplierName", supplierManage.getSupplierName()); // 应付金额计算 BigDecimal payableAmount = BigDecimal.ZERO; List purchaseLedgers = purchaseLedgerMapper.selectList( new QueryWrapper().eq("supplier_id", supplierManage.getId()) ); List salesLedgerProducts = purchaseLedgers.stream() .filter(Objects::nonNull) .map(PurchaseLedger::getId) .filter(Objects::nonNull) .flatMap(id -> salesLedgerProductMapper.selectList( new QueryWrapper().eq("sales_ledger_id", id) ).stream()) .collect(Collectors.toList()); payableAmount = salesLedgerProducts.stream() .map(SalesLedgerProduct::getTaxInclusiveTotalPrice) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); // 来票金额计算 List ticketRegistrations = purchaseLedgers.stream() .map(PurchaseLedger::getId) .filter(Objects::nonNull) .map(id -> ticketRegistrationMapper.selectList( new LambdaQueryWrapper().eq(TicketRegistration::getPurchaseLedgerId, id) )) .flatMap(Collection::stream) .collect(Collectors.toList()); BigDecimal invoiceAmount = ticketRegistrations.stream() .map(TicketRegistration::getInvoiceAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); // 付款记录及详情分页 List paymentRegistrations = paymentRegistrationMapper.selectList( new QueryWrapper().eq("supplier_id", supplierManage.getId()) ); BigDecimal paymentAmount = paymentRegistrations.stream() .map(PaymentRegistration::getCurrentPaymentAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); // 详情分页处理 detailPageNum = detailPageNum != null ? detailPageNum : 1; detailPageSize = detailPageSize != null ? detailPageSize : paymentRegistrations.size(); // 默认显示全部 int totalDetails = paymentRegistrations.size(); int start = (detailPageNum - 1) * detailPageSize; int end = Math.min(start + detailPageSize, totalDetails); List pagedDetails = paymentRegistrations.subList(start, end); // 构建详情列表 List> details = pagedDetails.stream() .filter(Objects::nonNull) .map(pr -> { Map detail = new HashMap<>(); detail.put("paymentAmount", pr.getCurrentPaymentAmount()); // 批量查询 TicketRegistration(避免 N+1) TicketRegistration ticketRegistration = ticketRegistrationMapper.selectById(pr.getTicketRegistrationId()); if (ticketRegistration != null) { detail.put("payableAmount", ticketRegistration.getInvoiceAmount()); BigDecimal voteCount = productRecordMapper.selectList( new LambdaQueryWrapper().eq(ProductRecord::getTicketRegistrationId, ticketRegistration.getId()) ).stream() .map(ProductRecord::getTicketsNum) .map(BigDecimal::new) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); detail.put("voteCount", voteCount); } // 日期格式化(建议使用 LocalDateTime) if (pr.getPaymentDate() != null) { detail.put("paymentDate", new SimpleDateFormat("yyyy-MM-dd").format(pr.getPaymentDate())); } return detail; }) .collect(Collectors.toList()); // 封装详情分页元数据 Map detailPagination = new HashMap<>(); detailPagination.put("total", totalDetails); detailPagination.put("pageNum", detailPageNum); detailPagination.put("pageSize", detailPageSize); detailPagination.put("pages", (int) Math.ceil((double) totalDetails / detailPageSize)); res.put("invoiceAmount", invoiceAmount); res.put("payableAmount", payableAmount); res.put("paymentAmount", paymentAmount); res.put("details", details); res.put("detailPagination", detailPagination); // 添加详情分页信息 result.add(res); } resultPage.setRecords(result); return resultPage; } @Override public Map paymentMonthList() { // 查询供应商列表 List suppliers = supplierManageMapper.selectList(null); if (CollectionUtils.isEmpty(suppliers)) { Map result = new HashMap<>(); result.put("payableAmount", BigDecimal.ZERO); result.put("paymentAmount", BigDecimal.ZERO); return result; } // 提取所有供应商ID List supplierIds = suppliers.stream() .map(SupplierManage::getId) // 先获取Integer类型的ID .filter(Objects::nonNull) // 过滤掉可能的null值 .map(Integer::longValue) // 将Integer转换为Long .collect(Collectors.toList()); // 获取当月的开始和结束日期 YearMonth currentMonth = YearMonth.now(); LocalDate startDate = currentMonth.atDay(1); LocalDate endDate = currentMonth.atEndOfMonth(); // 批量查询采购台账(当月) Map> purchaseLedgerMap = batchQueryPurchaseLedgers(supplierIds, startDate, endDate); // 批量查询销售台账产品 Map> salesLedgerProductMap = batchQuerySalesLedgerProducts(purchaseLedgerMap); // 批量查询付款记录(当月) Map> paymentRegistrationMap = batchQueryPaymentRegistrations(supplierIds, startDate, endDate); // 计算应付金额和付款金额 BigDecimal totalPayableAmount = calculateTotalPayableAmount(purchaseLedgerMap, salesLedgerProductMap); BigDecimal totalPaymentAmount = calculateTotalPaymentAmount(paymentRegistrationMap); // 构建结果 Map result = new HashMap<>(); result.put("payableAmount", totalPayableAmount); result.put("paymentAmount", totalPaymentAmount); return result; } // 批量查询采购台账(当月) private Map> batchQueryPurchaseLedgers(List supplierIds, LocalDate startDate, LocalDate endDate) { LambdaQueryWrapper query = new LambdaQueryWrapper<>(); query.in(PurchaseLedger::getSupplierId, supplierIds) .ge(PurchaseLedger::getCreatedAt, startDate) .le(PurchaseLedger::getCreatedAt, endDate); List purchaseLedgers = purchaseLedgerMapper.selectList(query); return purchaseLedgers.stream() .filter(pl -> pl.getSupplierId() != null) .collect(Collectors.groupingBy(PurchaseLedger::getSupplierId)); } // 批量查询销售台账产品 private Map> batchQuerySalesLedgerProducts(Map> purchaseLedgerMap) { // 提取所有采购台账ID List purchaseLedgerIds = purchaseLedgerMap.values().stream() .flatMap(Collection::stream) .map(PurchaseLedger::getId) .filter(Objects::nonNull) .collect(Collectors.toList()); if (purchaseLedgerIds.isEmpty()) { return Collections.emptyMap(); } LambdaQueryWrapper query = new LambdaQueryWrapper<>(); query.in(SalesLedgerProduct::getSalesLedgerId, purchaseLedgerIds); List products = salesLedgerProductMapper.selectList(query); return products.stream() .filter(slp -> slp.getSalesLedgerId() != null) .collect(Collectors.groupingBy(SalesLedgerProduct::getSalesLedgerId)); } // 批量查询付款记录(当月) private Map> batchQueryPaymentRegistrations(List supplierIds, LocalDate startDate, LocalDate endDate) { LambdaQueryWrapper query = new LambdaQueryWrapper<>(); query.in(PaymentRegistration::getSupplierId, supplierIds) .ge(PaymentRegistration::getPaymentDate, startDate) .le(PaymentRegistration::getPaymentDate, endDate); List paymentRegistrations = paymentRegistrationMapper.selectList(query); return paymentRegistrations.stream() .filter(pr -> pr.getSupplierId() != null) .collect(Collectors.groupingBy(PaymentRegistration::getSupplierId)); } // 计算总应付金额 private BigDecimal calculateTotalPayableAmount(Map> purchaseLedgerMap, Map> salesLedgerProductMap) { return purchaseLedgerMap.values().stream() .flatMap(Collection::stream) .map(pl -> salesLedgerProductMap.getOrDefault(pl.getId(), Collections.emptyList())) .flatMap(Collection::stream) .map(SalesLedgerProduct::getTaxInclusiveTotalPrice) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); } // 计算总付款金额 private BigDecimal calculateTotalPaymentAmount(Map> paymentRegistrationMap) { return paymentRegistrationMap.values().stream() .flatMap(Collection::stream) .map(PaymentRegistration::getCurrentPaymentAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); } }