| | |
| | | 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; |
| | |
| | | public class PurchaseAgentTools { |
| | | |
| | | private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd"); |
| | | private static final ZoneId CHINA_ZONE_ID = ZoneId.of("Asia/Shanghai"); |
| | | private static final int DEFAULT_LIMIT = 10; |
| | | 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 AiSessionUserContext aiSessionUserContext; |
| | | |
| | | public PurchaseAgentTools(PurchaseLedgerMapper purchaseLedgerMapper, |
| | | PaymentRegistrationMapper paymentRegistrationMapper, |
| | | InvoicePurchaseMapper invoicePurchaseMapper, |
| | | PurchaseReturnOrdersMapper purchaseReturnOrdersMapper, |
| | | SalesLedgerProductMapper salesLedgerProductMapper, |
| | | ProcurementRecordMapper procurementRecordMapper, |
| | | InboundManagementMapper inboundManagementMapper, |
| | | AiSessionUserContext aiSessionUserContext) { |
| | | this.purchaseLedgerMapper = purchaseLedgerMapper; |
| | | this.paymentRegistrationMapper = paymentRegistrationMapper; |
| | | this.invoicePurchaseMapper = invoicePurchaseMapper; |
| | | this.purchaseReturnOrdersMapper = purchaseReturnOrdersMapper; |
| | | this.salesLedgerProductMapper = salesLedgerProductMapper; |
| | | this.procurementRecordMapper = procurementRecordMapper; |
| | |
| | | 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<PaymentRegistration> payments = queryPayments(loginUser, range); |
| | | // List<InvoicePurchase> 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 = payments.stream() |
| | | .map(PaymentRegistration::getCurrentPaymentAmount) |
| | | .filter(Objects::nonNull) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | BigDecimal invoiceAmount = invoices.stream() |
| | | .map(InvoicePurchase::getInvoiceAmount) |
| | | .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 returnAmount = returns.stream() |
| | | .map(PurchaseReturnOrders::getTotalAmount) |
| | | .filter(Objects::nonNull) |
| | |
| | | summary.put("startDate", range.start().toString()); |
| | | summary.put("endDate", range.end().toString()); |
| | | summary.put("ledgerCount", ledgers.size()); |
| | | summary.put("paymentCount", payments.size()); |
| | | summary.put("invoiceCount", invoices.size()); |
| | | summary.put("paymentCount", 0); |
| | | // summary.put("paymentCount", payments.size()); |
| | | // summary.put("invoiceCount", invoices.size()); |
| | | summary.put("invoiceCount", 0); |
| | | summary.put("returnCount", returns.size()); |
| | | summary.put("contractAmount", contractAmount); |
| | | summary.put("paymentAmount", paymentAmount); |
| | |
| | | .sorted(Comparator.comparing(item -> (BigDecimal) item.get("pendingAmount"), Comparator.reverseOrder())) |
| | | .limit(normalizeLimit(limit)) |
| | | .collect(Collectors.toList()); |
| | | |
| | | BigDecimal totalContractAmount = items.stream() |
| | | .map(item -> asBigDecimal(item.get("contractAmount"))) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | BigDecimal totalPaidAmount = items.stream() |
| | | .map(item -> asBigDecimal(item.get("paidAmount"))) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | BigDecimal totalPendingAmount = items.stream() |
| | | .map(item -> asBigDecimal(item.get("pendingAmount"))) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | Map<String, Object> summary = rangeSummary(range, items.size()); |
| | | summary.put("pendingOrderCount", items.size()); |
| | | summary.put("totalContractAmount", totalContractAmount); |
| | | summary.put("totalPaidAmount", totalPaidAmount); |
| | | summary.put("totalPendingAmount", totalPendingAmount); |
| | | |
| | | return jsonResponse(true, "purchase_pending_payment_list", "已返回待付款采购单。", |
| | | rangeSummary(range, items.size()), Map.of("items", items), Map.of()); |
| | | summary, Map.of("items", items), Map.of()); |
| | | } |
| | | |
| | | @Tool(name = "查询采购退货情况", value = "按时间范围查询采购退货单列表和退货金额。") |
| | |
| | | } |
| | | |
| | | 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); |
| | | // 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<String, Object> toReturnItem(PurchaseReturnOrders item) { |
| | |
| | | return value == null ? BigDecimal.ZERO : value; |
| | | } |
| | | |
| | | private BigDecimal asBigDecimal(Object value) { |
| | | if (value == null) { |
| | | return BigDecimal.ZERO; |
| | | } |
| | | if (value instanceof BigDecimal decimal) { |
| | | return decimal; |
| | | } |
| | | if (value instanceof Number number) { |
| | | return new BigDecimal(String.valueOf(number)); |
| | | } |
| | | return BigDecimal.ZERO; |
| | | } |
| | | |
| | | private List<PaymentRegistration> queryPayments(LoginUser loginUser, DateRange range) { |
| | | LambdaQueryWrapper<PaymentRegistration> wrapper = new LambdaQueryWrapper<>(); |
| | | applyTenantFilter(wrapper, loginUser.getTenantId(), PaymentRegistration::getTenantId); |
| | |
| | | return defaultList(paymentRegistrationMapper.selectList(wrapper)); |
| | | } |
| | | |
| | | 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<PurchaseReturnOrders> queryReturns(LoginUser loginUser, DateRange range) { |
| | | LambdaQueryWrapper<PurchaseReturnOrders> wrapper = new LambdaQueryWrapper<>(); |
| | |
| | | } |
| | | |
| | | private DateRange resolveDateRange(String startDate, String endDate, String timeRange) { |
| | | LocalDate today = LocalDate.now(); |
| | | LocalDate today = LocalDate.now(CHINA_ZONE_ID); |
| | | LocalDate start = parseLocalDate(startDate); |
| | | LocalDate end = parseLocalDate(endDate); |
| | | if (start != null || end != null) { |
| | |
| | | return new DateRange(today.minusDays(29), today, "近30天"); |
| | | } |
| | | String text = timeRange.trim(); |
| | | if (text.contains("今天")) { |
| | | return new DateRange(today, today, "今天"); |
| | | } |
| | | if (text.contains("昨天")) { |
| | | LocalDate yesterday = today.minusDays(1); |
| | | return new DateRange(yesterday, yesterday, "昨天"); |
| | | } |
| | | if (text.contains("本周")) { |
| | | LocalDate startOfWeek = today.minusDays(today.getDayOfWeek().getValue() - 1L); |
| | | return new DateRange(startOfWeek, today, "本周"); |
| | | } |
| | | if (text.contains("上周")) { |
| | | LocalDate thisWeekStart = today.minusDays(today.getDayOfWeek().getValue() - 1L); |
| | | LocalDate startOfLastWeek = thisWeekStart.minusWeeks(1); |
| | | return new DateRange(startOfLastWeek, startOfLastWeek.plusDays(6), "上周"); |
| | | } |
| | | if (text.contains("今年") || text.contains("本年")) { |
| | | return new DateRange(today.withDayOfYear(1), today, "今年"); |
| | | } |
| | |
| | | if (!StringUtils.hasText(text)) { |
| | | return null; |
| | | } |
| | | return LocalDate.parse(text.trim(), DATE_FMT); |
| | | try { |
| | | return LocalDate.parse(text.trim(), DATE_FMT); |
| | | } catch (Exception ignored) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | private Date toDate(LocalDate localDate) { |