3 天以前 5b8e83c5170e570b9247946e799556b53445c458
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -1,6 +1,7 @@
package com.ruoyi.sales.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
@@ -8,6 +9,7 @@
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.account.pojo.AccountIncome;
import com.ruoyi.account.service.AccountIncomeService;
import com.ruoyi.basic.mapper.CustomerMapper;
import com.ruoyi.basic.mapper.ProductMapper;
@@ -38,6 +40,7 @@
import com.ruoyi.sales.mapper.*;
import com.ruoyi.sales.pojo.*;
import com.ruoyi.sales.service.ISalesLedgerService;
import com.ruoyi.sales.service.ReceiptPaymentService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
@@ -128,6 +131,8 @@
    ;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private ReceiptPaymentService receiptPaymentService;
    @Override
    public List<SalesLedger> selectSalesLedgerList(SalesLedgerDto salesLedgerDto) {
@@ -406,6 +411,7 @@
                salesLedgerMapper.insert(salesLedger);
                List<SalesLedgerProduct> insertedProducts = new ArrayList<>();
                for (SalesLedgerProductImportDto salesLedgerProductImportDto : salesLedgerProductImportDtos) {
                    SalesLedgerProduct salesLedgerProduct = new SalesLedgerProduct();
                    BeanUtils.copyProperties(salesLedgerProductImportDto, salesLedgerProduct);
@@ -437,9 +443,12 @@
                    salesLedgerProduct.setApproveStatus(0);
                    salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProductImportDto.getTaxInclusiveTotalPrice());
                    salesLedgerProductMapper.insert(salesLedgerProduct);
                    insertedProducts.add(salesLedgerProduct);
                    // 添加生产数据
                    salesLedgerProductServiceImpl.addProductionData(salesLedgerProduct);
                }
                // 导入时同样自动全额开票、自动全额回款
                autoInvoiceAndReceiptPayment(salesLedger, insertedProducts);
            }
            return AjaxResult.success("导入成功");
@@ -566,6 +575,16 @@
        if (CollectionUtils.isNotEmpty(invoiceLedgerIds)) {
            LambdaQueryWrapper<ReceiptPayment> wrapperTree = new LambdaQueryWrapper<>();
            wrapperTree.in(ReceiptPayment::getInvoiceLedgerId, invoiceLedgerIds);
            List<ReceiptPayment> receiptPayments = receiptPaymentMapper.selectList(wrapperTree);
            // 同步删除回款对应的财务收入记录,避免产生孤儿数据
            if (CollectionUtils.isNotEmpty(receiptPayments)) {
                List<Long> receiptPaymentIds = receiptPayments.stream()
                        .map(item -> item.getId().longValue())
                        .collect(Collectors.toList());
                accountIncomeService.remove(new LambdaQueryWrapper<AccountIncome>()
                        .in(AccountIncome::getBusinessId, receiptPaymentIds)
                        .eq(AccountIncome::getBusinessType, 1));
            }
            receiptPaymentMapper.delete(wrapperTree);
        }
        // 删除发货台账记录
@@ -604,7 +623,8 @@
            salesLedger.setCustomerName(customer.getCustomerName());
            salesLedger.setTenantId(customer.getTenantId());
            // 3. 新增或更新主表
            if (salesLedger.getId() == null) {
            boolean isNew = salesLedger.getId() == null;
            if (isNew) {
                String contractNo = generateSalesContractNo();
                salesLedger.setSalesContractNo(contractNo);
                salesLedgerMapper.insert(salesLedger);
@@ -628,6 +648,11 @@
            // 5. 迁移临时文件到正式目录
            if (salesLedgerDto.getTempFileIds() != null && !salesLedgerDto.getTempFileIds().isEmpty()) {
                migrateTempFilesToFormal(salesLedger.getId(), salesLedgerDto.getTempFileIds());
            }
            // 6. 新增台账时自动全额开票、自动全额回款
            if (isNew && productList != null && !productList.isEmpty()) {
                autoInvoiceAndReceiptPayment(salesLedger, productList);
            }
            return 1;
        } catch (IOException e) {
@@ -743,6 +768,108 @@
        }
    }
    /**
     * 新增销售台账时自动全额开票、自动全额回款
     * <p>
     * 1. 按合同全额自动生成开票登记(invoice_registration + invoice_registration_product + invoice_ledger);
     * 2. 按开票全额自动生成回款登记(receipt_payment)及财务收入记录(account_income)。
     *
     * @param salesLedger 销售台账主表(已入库)
     * @param products    台账产品列表(已入库,含主键ID)
     */
    private void autoInvoiceAndReceiptPayment(SalesLedger salesLedger, List<SalesLedgerProduct> products) {
        // 仅处理销售类产品
        List<SalesLedgerProduct> saleProducts = products.stream()
                .filter(Objects::nonNull)
                .filter(p -> p.getId() != null)
                .filter(p -> SaleEnum.SALE.getCode().equals(p.getType()))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(saleProducts)) {
            return;
        }
        String register = SecurityUtils.getLoginUser().getUser().getNickName();
        // 1. 自动开票:生成一张开票登记主表,覆盖该台账全部产品
        InvoiceRegistration invoiceRegistration = new InvoiceRegistration();
        invoiceRegistration.setSalesLedgerId(salesLedger.getId().intValue());
        invoiceRegistration.setSalesContractNo(salesLedger.getSalesContractNo());
        invoiceRegistration.setCustomerId(salesLedger.getCustomerId() == null ? null : salesLedger.getCustomerId().intValue());
        invoiceRegistration.setSalesman(salesLedger.getSalesman());
        invoiceRegistration.setProjectName(salesLedger.getProjectName());
        invoiceRegistrationMapper.insert(invoiceRegistration);
        List<ReceiptPayment> receiptPaymentList = new ArrayList<>();
        for (SalesLedgerProduct product : saleProducts) {
            BigDecimal invoiceNum = product.getQuantity();
            BigDecimal invoiceAmount = product.getTaxInclusiveTotalPrice();
            // 数量或金额缺失时跳过,不阻断台账新增
            if (invoiceNum == null || invoiceAmount == null
                    || invoiceNum.compareTo(BigDecimal.ZERO) <= 0
                    || invoiceAmount.compareTo(BigDecimal.ZERO) <= 0) {
                continue;
            }
            // 1.1 产品未开票数量/金额清零(全额开票)
            salesLedgerProductMapper.update(
                    null,
                    new LambdaUpdateWrapper<SalesLedgerProduct>()
                            .eq(SalesLedgerProduct::getId, product.getId())
                            .set(SalesLedgerProduct::getNoInvoiceNum, BigDecimal.ZERO)
                            .set(SalesLedgerProduct::getNoInvoiceAmount, BigDecimal.ZERO)
            );
            // 1.2 开票登记产品
            InvoiceRegistrationProduct invoiceRegistrationProduct = new InvoiceRegistrationProduct();
            BeanUtils.copyProperties(product, invoiceRegistrationProduct);
            invoiceRegistrationProduct.setId(null);
            invoiceRegistrationProduct.setSalesLedgerId(salesLedger.getId().intValue());
            invoiceRegistrationProduct.setInvoiceRegistrationId(invoiceRegistration.getId());
            invoiceRegistrationProduct.setSalesLedgerProductId(product.getId().intValue());
            invoiceRegistrationProduct.setInvoiceNum(invoiceNum);
            invoiceRegistrationProduct.setInvoiceAmount(invoiceAmount);
            invoiceRegistrationProduct.setNoInvoiceNum(BigDecimal.ZERO);
            invoiceRegistrationProduct.setNoInvoiceAmount(BigDecimal.ZERO);
            invoiceRegistrationProductMapper.insert(invoiceRegistrationProduct);
            // 1.3 开票台账(发票号自动生成)
            InvoiceLedger invoiceLedger = new InvoiceLedger();
            invoiceLedger.setInvoiceDate(LocalDate.now());
            invoiceLedger.setInvoiceRegistrationProductId(invoiceRegistrationProduct.getId());
            invoiceLedger.setInvoiceTotal(invoiceAmount);
            invoiceLedger.setInvoiceNo(generateAutoInvoiceNo(product.getId()));
            invoiceLedger.setCreateUser(SecurityUtils.getUserId().intValue());
            invoiceLedger.setInvoicePerson(register);
            invoiceLedgerMapper.insert(invoiceLedger);
            // 2. 组装自动回款记录(按开票全额回款)
            ReceiptPayment receiptPayment = new ReceiptPayment();
            receiptPayment.setReceiptPaymentType("0");
            receiptPayment.setReceiptPaymentAmount(invoiceAmount);
            receiptPayment.setRegistrant(register);
            receiptPayment.setInvoiceLedgerId(invoiceLedger.getId());
            receiptPayment.setSalesLedgerId(salesLedger.getId());
            receiptPayment.setSalesLedgerProductId(product.getId());
            receiptPayment.setReceiptPaymentDate(LocalDate.now());
            receiptPaymentList.add(receiptPayment);
        }
        // 3. 自动回款(内部同步更新产品回款金额并生成财务收入记录)
        if (!receiptPaymentList.isEmpty()) {
            receiptPaymentService.receiptPaymentSaveOrUpdate(receiptPaymentList);
        }
    }
    /**
     * 生成自动开票发票号
     *
     * @param salesLedgerProductId 销售台账产品ID
     * @return 自动发票号
     */
    private String generateAutoInvoiceNo(Long salesLedgerProductId) {
        return "AUTO" + System.currentTimeMillis() + salesLedgerProductId;
    }
    private SalesLedger convertToEntity(SalesLedgerDto dto) {
        SalesLedger entity = new SalesLedger();
        BeanUtils.copyProperties(dto, entity);