From 4635770544e2d57416ad88a8983ee293919f5fec Mon Sep 17 00:00:00 2001
From: liyong <18434998025@163.com>
Date: 星期一, 25 五月 2026 09:25:36 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_New_pro' into dev_New_pro

---
 src/main/java/com/ruoyi/ai/tools/PurchaseAgentTools.java |  243 ++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 211 insertions(+), 32 deletions(-)

diff --git a/src/main/java/com/ruoyi/ai/tools/PurchaseAgentTools.java b/src/main/java/com/ruoyi/ai/tools/PurchaseAgentTools.java
index 006438c..bdd1f1f 100644
--- a/src/main/java/com/ruoyi/ai/tools/PurchaseAgentTools.java
+++ b/src/main/java/com/ruoyi/ai/tools/PurchaseAgentTools.java
@@ -2,6 +2,12 @@
 
 import com.alibaba.fastjson2.JSON;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.ruoyi.account.mapper.purchase.AccountPaymentApplicationMapper;
+import com.ruoyi.account.mapper.purchase.AccountPurchaseInvoiceMapper;
+import com.ruoyi.account.mapper.purchase.AccountPurchasePaymentMapper;
+import com.ruoyi.account.pojo.purchase.AccountPaymentApplication;
+import com.ruoyi.account.pojo.purchase.AccountPurchaseInvoice;
+import com.ruoyi.account.pojo.purchase.AccountPurchasePayment;
 import com.ruoyi.ai.context.AiSessionUserContext;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.framework.security.LoginUser;
@@ -13,8 +19,12 @@
 import com.ruoyi.purchase.mapper.PurchaseReturnOrdersMapper;
 import com.ruoyi.purchase.pojo.PurchaseLedger;
 import com.ruoyi.purchase.pojo.PurchaseReturnOrders;
+import com.ruoyi.quality.mapper.QualityInspectMapper;
+import com.ruoyi.quality.pojo.QualityInspect;
 import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
+import com.ruoyi.stock.mapper.StockInRecordMapper;
+import com.ruoyi.stock.pojo.StockInRecord;
 import dev.langchain4j.agent.tool.P;
 import dev.langchain4j.agent.tool.Tool;
 import dev.langchain4j.agent.tool.ToolMemoryId;
@@ -41,6 +51,11 @@
     private final SalesLedgerProductMapper salesLedgerProductMapper;
     private final ProcurementRecordMapper procurementRecordMapper;
     private final InboundManagementMapper inboundManagementMapper;
+    private final AccountPurchasePaymentMapper accountPurchasePaymentMapper;
+    private final AccountPaymentApplicationMapper accountPaymentApplicationMapper;
+    private final AccountPurchaseInvoiceMapper accountPurchaseInvoiceMapper;
+    private final StockInRecordMapper stockInRecordMapper;
+    private final QualityInspectMapper qualityInspectMapper;
     private final AiSessionUserContext aiSessionUserContext;
 
     public PurchaseAgentTools(PurchaseLedgerMapper purchaseLedgerMapper,
@@ -48,12 +63,22 @@
                               SalesLedgerProductMapper salesLedgerProductMapper,
                               ProcurementRecordMapper procurementRecordMapper,
                               InboundManagementMapper inboundManagementMapper,
+                              AccountPurchasePaymentMapper accountPurchasePaymentMapper,
+                              AccountPaymentApplicationMapper accountPaymentApplicationMapper,
+                              AccountPurchaseInvoiceMapper accountPurchaseInvoiceMapper,
+                              StockInRecordMapper stockInRecordMapper,
+                              QualityInspectMapper qualityInspectMapper,
                               AiSessionUserContext aiSessionUserContext) {
         this.purchaseLedgerMapper = purchaseLedgerMapper;
         this.purchaseReturnOrdersMapper = purchaseReturnOrdersMapper;
         this.salesLedgerProductMapper = salesLedgerProductMapper;
         this.procurementRecordMapper = procurementRecordMapper;
         this.inboundManagementMapper = inboundManagementMapper;
+        this.accountPurchasePaymentMapper = accountPurchasePaymentMapper;
+        this.accountPaymentApplicationMapper = accountPaymentApplicationMapper;
+        this.accountPurchaseInvoiceMapper = accountPurchaseInvoiceMapper;
+        this.stockInRecordMapper = stockInRecordMapper;
+        this.qualityInspectMapper = qualityInspectMapper;
         this.aiSessionUserContext = aiSessionUserContext;
     }
 
@@ -115,24 +140,22 @@
         DateRange range = resolveDateRange(startDate, endDate, timeRange);
 
         List<PurchaseLedger> ledgers = queryLedgers(loginUser, range);
-//        List<PaymentRegistration> payments = queryPayments(loginUser, range);
-//        List<InvoicePurchase> invoices = queryInvoices(loginUser, range);
+        List<AccountPurchasePayment> payments = queryPayments(loginUser, range);
+        List<AccountPurchaseInvoice> invoices = queryInvoices(loginUser, range);
         List<PurchaseReturnOrders> returns = queryReturns(loginUser, range);
 
         BigDecimal contractAmount = ledgers.stream()
                 .map(PurchaseLedger::getContractAmount)
                 .filter(Objects::nonNull)
                 .reduce(BigDecimal.ZERO, BigDecimal::add);
-        BigDecimal paymentAmount = BigDecimal.ZERO;
-//        BigDecimal paymentAmount = payments.stream()
-//                .map(PaymentRegistration::getCurrentPaymentAmount)
-//                .filter(Objects::nonNull)
-//                .reduce(BigDecimal.ZERO, BigDecimal::add);
-        BigDecimal invoiceAmount = BigDecimal.ZERO;
-//        BigDecimal invoiceAmount = invoices.stream()
-//                .map(InvoicePurchase::getInvoiceAmount)
-//                .filter(Objects::nonNull)
-//                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        BigDecimal paymentAmount = payments.stream()
+                .map(AccountPurchasePayment::getPaymentAmount)
+                .filter(Objects::nonNull)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        BigDecimal invoiceAmount = invoices.stream()
+                .map(this::invoiceAmountOf)
+                .filter(Objects::nonNull)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
         BigDecimal returnAmount = returns.stream()
                 .map(PurchaseReturnOrders::getTotalAmount)
                 .filter(Objects::nonNull)
@@ -143,10 +166,8 @@
         summary.put("startDate", range.start().toString());
         summary.put("endDate", range.end().toString());
         summary.put("ledgerCount", ledgers.size());
-        summary.put("paymentCount", 0);
-//        summary.put("paymentCount", payments.size());
-//        summary.put("invoiceCount", invoices.size());
-        summary.put("invoiceCount", 0);
+        summary.put("paymentCount", payments.size());
+        summary.put("invoiceCount", invoices.size());
         summary.put("returnCount", returns.size());
         summary.put("contractAmount", contractAmount);
         summary.put("paymentAmount", paymentAmount);
@@ -268,9 +289,15 @@
                                            @P(value = "杩斿洖鏉℃暟锛岄粯璁�10锛屾渶澶�30", required = false) Integer limit) {
         LoginUser loginUser = currentLoginUser(memoryId);
         DateRange range = resolveDateRange(startDate, endDate, null);
-        List<Map<String, Object>> items = queryLedgers(loginUser, range).stream()
+        List<PurchaseLedger> matchedLedgers = queryLedgers(loginUser, range).stream()
                 .filter(ledger -> matchLedgerKeyword(ledger, keyword))
-                .map(ledger -> toPendingPaymentItem(loginUser, ledger))
+                .collect(Collectors.toList());
+        Map<Long, BigDecimal> paidAmountByLedgerId = sumPaymentAmountByLedgerId(loginUser, matchedLedgers.stream()
+                .map(PurchaseLedger::getId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList()));
+        List<Map<String, Object>> items = matchedLedgers.stream()
+                .map(ledger -> toPendingPaymentItem(ledger, paidAmountByLedgerId.getOrDefault(ledger.getId(), BigDecimal.ZERO)))
                 .filter(Objects::nonNull)
                 .sorted(Comparator.comparing(item -> (BigDecimal) item.get("pendingAmount"), Comparator.reverseOrder()))
                 .limit(normalizeLimit(limit))
@@ -411,28 +438,58 @@
         return map;
     }
 
-    private Map<String, Object> toPendingPaymentItem(LoginUser loginUser, PurchaseLedger ledger) {
+    private Map<String, Object> toPendingPaymentItem(PurchaseLedger ledger, BigDecimal paidAmount) {
         BigDecimal contractAmount = defaultDecimal(ledger.getContractAmount());
-        BigDecimal paidAmount = sumPaymentAmount(loginUser, ledger.getId());
-        BigDecimal pendingAmount = contractAmount.subtract(paidAmount);
+        BigDecimal safePaidAmount = defaultDecimal(paidAmount);
+        BigDecimal pendingAmount = contractAmount.subtract(safePaidAmount);
         if (pendingAmount.compareTo(BigDecimal.ZERO) <= 0) {
             return null;
         }
         Map<String, Object> item = toLedgerItem(ledger);
-        item.put("paidAmount", paidAmount);
+        item.put("paidAmount", safePaidAmount);
         item.put("pendingAmount", pendingAmount);
         return item;
     }
 
-    private BigDecimal sumPaymentAmount(LoginUser loginUser, Long purchaseLedgerId) {
-//        LambdaQueryWrapper<PaymentRegistration> wrapper = new LambdaQueryWrapper<>();
-//        applyTenantFilter(wrapper, loginUser.getTenantId(), PaymentRegistration::getTenantId);
-//        wrapper.eq(PaymentRegistration::getPurchaseLedgerId, purchaseLedgerId);
-//        return defaultList(paymentRegistrationMapper.selectList(wrapper)).stream()
-//                .map(PaymentRegistration::getCurrentPaymentAmount)
-//                .filter(Objects::nonNull)
-//                .reduce(BigDecimal.ZERO, BigDecimal::add);
-        return BigDecimal.ZERO;
+    private Map<Long, BigDecimal> sumPaymentAmountByLedgerId(LoginUser loginUser, List<Long> purchaseLedgerIds) {
+        if (purchaseLedgerIds == null || purchaseLedgerIds.isEmpty()) {
+            return Map.of();
+        }
+        List<AccountPurchasePayment> payments = queryPayments(loginUser);
+        if (payments.isEmpty()) {
+            return Map.of();
+        }
+
+        Map<Integer, AccountPaymentApplication> applicationById = queryPaymentApplications(payments);
+        if (applicationById.isEmpty()) {
+            return Map.of();
+        }
+
+        Map<Long, StockInRecord> stockInRecordById = queryStockInRecords(applicationById.values());
+        Map<Long, Long> purchaseLedgerIdByQualityInspectId = queryPurchaseLedgerIdByQualityInspectId(stockInRecordById.values());
+        Set<Long> targetLedgerIdSet = new HashSet<>(purchaseLedgerIds);
+        Map<Long, BigDecimal> result = new HashMap<>();
+
+        for (AccountPurchasePayment payment : payments) {
+            if (payment.getAccountPaymentApplicationId() == null) {
+                continue;
+            }
+            AccountPaymentApplication application = applicationById.get(payment.getAccountPaymentApplicationId());
+            if (application == null) {
+                continue;
+            }
+            Set<Long> ledgerIds = resolvePurchaseLedgerIds(application, stockInRecordById, purchaseLedgerIdByQualityInspectId);
+            if (ledgerIds.isEmpty()) {
+                continue;
+            }
+            BigDecimal amount = defaultDecimal(payment.getPaymentAmount());
+            for (Long ledgerId : ledgerIds) {
+                if (targetLedgerIdSet.contains(ledgerId)) {
+                    result.merge(ledgerId, amount, BigDecimal::add);
+                }
+            }
+        }
+        return result;
     }
 
     private Map<String, Object> toReturnItem(PurchaseReturnOrders item) {
@@ -462,7 +519,129 @@
         if (value instanceof Number number) {
             return new BigDecimal(String.valueOf(number));
         }
-        return BigDecimal.ZERO;
+        try {
+            return new BigDecimal(String.valueOf(value));
+        } catch (Exception ignored) {
+            return BigDecimal.ZERO;
+        }
+    }
+
+    private BigDecimal invoiceAmountOf(AccountPurchaseInvoice invoice) {
+        if (invoice == null) {
+            return BigDecimal.ZERO;
+        }
+        BigDecimal amount = defaultDecimal(invoice.getTaxInclusivePrice());
+        if (amount.compareTo(BigDecimal.ZERO) > 0) {
+            return amount;
+        }
+        return defaultDecimal(invoice.getTaxExclusivelPrice()).add(defaultDecimal(invoice.getTaxPrice()));
+    }
+
+    private List<AccountPurchasePayment> queryPayments(LoginUser loginUser, DateRange range) {
+        LambdaQueryWrapper<AccountPurchasePayment> wrapper = new LambdaQueryWrapper<>();
+        applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), AccountPurchasePayment::getDeptId);
+        wrapper.ge(AccountPurchasePayment::getPaymentDate, range.start())
+                .le(AccountPurchasePayment::getPaymentDate, range.end())
+                .orderByDesc(AccountPurchasePayment::getPaymentDate, AccountPurchasePayment::getId);
+        return defaultList(accountPurchasePaymentMapper.selectList(wrapper));
+    }
+
+    private List<AccountPurchasePayment> queryPayments(LoginUser loginUser) {
+        LambdaQueryWrapper<AccountPurchasePayment> wrapper = new LambdaQueryWrapper<>();
+        applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), AccountPurchasePayment::getDeptId);
+        return defaultList(accountPurchasePaymentMapper.selectList(wrapper));
+    }
+
+    private List<AccountPurchaseInvoice> queryInvoices(LoginUser loginUser, DateRange range) {
+        LambdaQueryWrapper<AccountPurchaseInvoice> wrapper = new LambdaQueryWrapper<>();
+        applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), AccountPurchaseInvoice::getDeptId);
+        wrapper.ge(AccountPurchaseInvoice::getIssueDate, range.start())
+                .le(AccountPurchaseInvoice::getIssueDate, range.end())
+                .orderByDesc(AccountPurchaseInvoice::getIssueDate, AccountPurchaseInvoice::getId);
+        return defaultList(accountPurchaseInvoiceMapper.selectList(wrapper));
+    }
+
+    private Map<Integer, AccountPaymentApplication> queryPaymentApplications(List<AccountPurchasePayment> payments) {
+        List<Integer> ids = payments.stream()
+                .map(AccountPurchasePayment::getAccountPaymentApplicationId)
+                .filter(Objects::nonNull)
+                .distinct()
+                .collect(Collectors.toList());
+        if (ids.isEmpty()) {
+            return Map.of();
+        }
+        return defaultList(accountPaymentApplicationMapper.selectBatchIds(ids)).stream()
+                .filter(item -> item.getId() != null)
+                .collect(Collectors.toMap(AccountPaymentApplication::getId, item -> item, (a, b) -> a));
+    }
+
+    private Map<Long, StockInRecord> queryStockInRecords(Collection<AccountPaymentApplication> applications) {
+        Set<Long> stockInRecordIds = new HashSet<>();
+        for (AccountPaymentApplication application : applications) {
+            stockInRecordIds.addAll(parseLongIds(application.getStockInRecordIds()));
+        }
+        if (stockInRecordIds.isEmpty()) {
+            return Map.of();
+        }
+        return defaultList(stockInRecordMapper.selectBatchIds(stockInRecordIds)).stream()
+                .filter(item -> item.getId() != null)
+                .collect(Collectors.toMap(StockInRecord::getId, item -> item, (a, b) -> a));
+    }
+
+    private Map<Long, Long> queryPurchaseLedgerIdByQualityInspectId(Collection<StockInRecord> stockInRecords) {
+        Set<Long> qualityInspectIds = stockInRecords.stream()
+                .filter(Objects::nonNull)
+                .filter(item -> item.getRecordId() != null && "10".equals(safe(item.getRecordType()).trim()))
+                .map(StockInRecord::getRecordId)
+                .collect(Collectors.toSet());
+        if (qualityInspectIds.isEmpty()) {
+            return Map.of();
+        }
+        return defaultList(qualityInspectMapper.selectBatchIds(qualityInspectIds)).stream()
+                .filter(item -> item.getId() != null && item.getPurchaseLedgerId() != null)
+                .collect(Collectors.toMap(QualityInspect::getId, QualityInspect::getPurchaseLedgerId, (a, b) -> a));
+    }
+
+    private Set<Long> resolvePurchaseLedgerIds(AccountPaymentApplication application,
+                                               Map<Long, StockInRecord> stockInRecordById,
+                                               Map<Long, Long> purchaseLedgerIdByQualityInspectId) {
+        Set<Long> result = new LinkedHashSet<>();
+        for (Long stockInRecordId : parseLongIds(application.getStockInRecordIds())) {
+            StockInRecord stockInRecord = stockInRecordById.get(stockInRecordId);
+            if (stockInRecord == null || stockInRecord.getRecordId() == null) {
+                continue;
+            }
+            if (stockInRecord.getApprovalStatus() != null && stockInRecord.getApprovalStatus() != 1) {
+                continue;
+            }
+            String recordType = safe(stockInRecord.getRecordType()).trim();
+            if ("7".equals(recordType)) {
+                result.add(stockInRecord.getRecordId());
+            } else if ("10".equals(recordType)) {
+                Long purchaseLedgerId = purchaseLedgerIdByQualityInspectId.get(stockInRecord.getRecordId());
+                if (purchaseLedgerId != null) {
+                    result.add(purchaseLedgerId);
+                }
+            }
+        }
+        return result;
+    }
+
+    private List<Long> parseLongIds(String raw) {
+        if (!StringUtils.hasText(raw)) {
+            return List.of();
+        }
+        List<Long> result = new ArrayList<>();
+        for (String part : raw.split(",")) {
+            if (!StringUtils.hasText(part)) {
+                continue;
+            }
+            try {
+                result.add(Long.parseLong(part.trim()));
+            } catch (Exception ignored) {
+            }
+        }
+        return result;
     }
 
 

--
Gitblit v1.9.3