From 620bb4712a31791231c4381581f0f60088f079fe Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期三, 27 五月 2026 14:03:45 +0800
Subject: [PATCH] Merge branch 'refs/heads/dev_New_pro' into dev_宁夏_英泽防锈
---
src/main/java/com/ruoyi/ai/tools/PurchaseAgentTools.java | 257 +++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 205 insertions(+), 52 deletions(-)
diff --git a/src/main/java/com/ruoyi/ai/tools/PurchaseAgentTools.java b/src/main/java/com/ruoyi/ai/tools/PurchaseAgentTools.java
index 2ec6003..bdd1f1f 100644
--- a/src/main/java/com/ruoyi/ai/tools/PurchaseAgentTools.java
+++ b/src/main/java/com/ruoyi/ai/tools/PurchaseAgentTools.java
@@ -2,23 +2,29 @@
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;
-import com.ruoyi.purchase.mapper.InvoicePurchaseMapper;
-import com.ruoyi.purchase.mapper.PaymentRegistrationMapper;
-import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
-import com.ruoyi.purchase.mapper.PurchaseReturnOrdersMapper;
-import com.ruoyi.purchase.pojo.InvoicePurchase;
-import com.ruoyi.purchase.pojo.PaymentRegistration;
-import com.ruoyi.purchase.pojo.PurchaseLedger;
-import com.ruoyi.purchase.pojo.PurchaseReturnOrders;
import com.ruoyi.procurementrecord.mapper.InboundManagementMapper;
import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper;
import com.ruoyi.procurementrecord.pojo.InboundManagement;
import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage;
+import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
+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;
@@ -27,15 +33,9 @@
import java.math.BigDecimal;
import java.time.LocalDate;
-import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
-import java.util.Date;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Comparator;
+import java.util.*;
import java.util.stream.Collectors;
@Component
@@ -47,29 +47,38 @@
private static final int MAX_LIMIT = 30;
private final PurchaseLedgerMapper purchaseLedgerMapper;
- private final PaymentRegistrationMapper paymentRegistrationMapper;
- private final InvoicePurchaseMapper invoicePurchaseMapper;
private final PurchaseReturnOrdersMapper purchaseReturnOrdersMapper;
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,
- PaymentRegistrationMapper paymentRegistrationMapper,
- InvoicePurchaseMapper invoicePurchaseMapper,
PurchaseReturnOrdersMapper purchaseReturnOrdersMapper,
SalesLedgerProductMapper salesLedgerProductMapper,
ProcurementRecordMapper procurementRecordMapper,
InboundManagementMapper inboundManagementMapper,
+ AccountPurchasePaymentMapper accountPurchasePaymentMapper,
+ AccountPaymentApplicationMapper accountPaymentApplicationMapper,
+ AccountPurchaseInvoiceMapper accountPurchaseInvoiceMapper,
+ StockInRecordMapper stockInRecordMapper,
+ QualityInspectMapper qualityInspectMapper,
AiSessionUserContext aiSessionUserContext) {
this.purchaseLedgerMapper = purchaseLedgerMapper;
- this.paymentRegistrationMapper = paymentRegistrationMapper;
- this.invoicePurchaseMapper = invoicePurchaseMapper;
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;
}
@@ -131,8 +140,8 @@
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()
@@ -140,11 +149,11 @@
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal paymentAmount = payments.stream()
- .map(PaymentRegistration::getCurrentPaymentAmount)
+ .map(AccountPurchasePayment::getPaymentAmount)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal invoiceAmount = invoices.stream()
- .map(InvoicePurchase::getInvoiceAmount)
+ .map(this::invoiceAmountOf)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal returnAmount = returns.stream()
@@ -280,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))
@@ -423,27 +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);
+ 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) {
@@ -473,25 +519,132 @@
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 List<PaymentRegistration> queryPayments(LoginUser loginUser, DateRange range) {
- LambdaQueryWrapper<PaymentRegistration> wrapper = new LambdaQueryWrapper<>();
- applyTenantFilter(wrapper, loginUser.getTenantId(), PaymentRegistration::getTenantId);
- wrapper.ge(PaymentRegistration::getPaymentDate, toDate(range.start()))
- .lt(PaymentRegistration::getPaymentDate, toExclusiveEndDate(range.end()));
- return defaultList(paymentRegistrationMapper.selectList(wrapper));
+ 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<InvoicePurchase> queryInvoices(LoginUser loginUser, DateRange range) {
- LambdaQueryWrapper<InvoicePurchase> wrapper = new LambdaQueryWrapper<>();
- applyTenantFilter(wrapper, loginUser.getTenantId(), InvoicePurchase::getTenantId);
- wrapper.ge(InvoicePurchase::getIssueDate, range.start())
- .le(InvoicePurchase::getIssueDate, range.end());
- return defaultList(invoicePurchaseMapper.selectList(wrapper));
+ 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;
+ }
+
+
private List<PurchaseReturnOrders> queryReturns(LoginUser loginUser, DateRange range) {
LambdaQueryWrapper<PurchaseReturnOrders> wrapper = new LambdaQueryWrapper<>();
applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), PurchaseReturnOrders::getDeptId);
--
Gitblit v1.9.3