Finance Analyst Agent — Plan & Progress¶
Мета¶
Перетворити ESWF-Chat на фінансового аналітика, який відповідає на питання: - "Яка дебіторська заборгованість?" - "Скільки ми отримали за березень?" - "Які рахунки прострочені?" - "Покажи рух грошей за квартал" - "Топ-5 клієнтів по виручці" - "Скільки ми маємо отримати наступного тижня?"
Архітектура¶
Користувач → ChatDrawer → SSE Stream → Django View
↓
llm.py (OpenRouter)
↓
tools.py (Finance Tools)
↓
Django ORM → SQLite/PostgreSQL
↓
JSON результат → LLM → відповідь
Нові Tools (6 штук)¶
| Tool | Опис | Моделі |
|---|---|---|
get_receivables |
Дебіторська заборгованість по клієнтах | Invoice |
get_cashflow |
Рух грошових коштів по місяцях/тижнях | IncomingPayment, OutgoingPayment |
get_revenue_report |
Виручка по клієнтах або по місяцях | Invoice (posted) |
get_top_clients |
Топ клієнтів по виручці або платежах | Invoice, IncomingPayment |
get_payment_plan |
Очікувані надходження (незакриті рахунки) | Invoice |
get_financial_summary |
Зведений P&L за період | Invoice, IncomingPayment, OutgoingPayment |
Деталі реалізації¶
get_receivables¶
Параметри:
- client_name (опціонально)
- min_days_overdue: int (default 0)
- limit: int (default 20)
Логіка:
Invoice.objects.filter(tenant, status IN [sent, overdue, partially_paid])
debt = total_gross - paid_amount
days_overdue = (today - payment_due_date).days (якщо past due)
Сортування: за сумою боргу DESC
Повертає: [{client, invoice_number, total_gross, paid_amount, debt, due_date, days_overdue}]
get_cashflow¶
Параметри:
- date_from: YYYY-MM-DD
- date_to: YYYY-MM-DD
- group_by: "month" | "week" (default "month")
Логіка:
IncomingPayment (posted, functional_amount) → income
OutgoingPayment (posted, functional_amount) → expense
Групування по трункованій даті
Повертає: [{period, income, expense, net}], totals
get_revenue_report¶
Параметри:
- date_from: YYYY-MM-DD
- date_to: YYYY-MM-DD
- group_by: "client" | "month" | "week" (default "month")
- limit: int
Логіка:
Invoice.objects.filter(posted, date range)
.values(group_key).annotate(Sum(total_gross), Sum(vat_amount), Count)
Повертає: [{period/client, revenue, vat, count}], totals
get_top_clients¶
Параметри:
- metric: "revenue" | "payments" (default "revenue")
- date_from: YYYY-MM-DD (опціонально)
- date_to: YYYY-MM-DD (опціонально)
- limit: int (default 10)
Логіка:
revenue: Invoice(posted).group_by(client).sum(total_gross)
payments: IncomingPayment(posted).group_by(client).sum(functional_amount)
Повертає: [{rank, client, amount, count}]
get_payment_plan¶
Параметри:
- date_from: YYYY-MM-DD (default today)
- date_to: YYYY-MM-DD (default today + 30 days)
- group_by: "week" | "client" (default "week")
Логіка:
Invoice.objects.filter(posted, status NOT IN [paid, closed, cancelled])
.filter(payment_due_date range)
expected = total_gross - paid_amount
Повертає: [{period/client, expected_amount, invoice_count}], total
get_financial_summary¶
Параметри:
- date_from: YYYY-MM-DD
- date_to: YYYY-MM-DD
Логіка:
revenue = Invoice(posted, date range).sum(total_gross)
vat = Invoice(posted).sum(vat_amount)
income_received = IncomingPayment(posted).sum(functional_amount)
expenses_paid = OutgoingPayment(posted).sum(functional_amount)
receivables = Invoice(not paid).sum(total_gross - paid_amount)
overdue_count = Invoice(overdue or past_due_date).count()
Повертає: один об'єкт з усіма показниками
SYSTEM_PROMPT — нові інструкції¶
FINANCE ANALYST capabilities:
- When the user asks about receivables, debts, overdue invoices → use get_receivables
- When the user asks about cash flow, money movement, income/expense → use get_cashflow
- When the user asks about revenue, sales, turnover by period → use get_revenue_report
- When the user asks for top clients, best customers → use get_top_clients
- When the user asks about expected payments, payment plan → use get_payment_plan
- When the user asks for a financial summary, P&L, overview → use get_financial_summary
- Always present amounts in UAH with thousands separators
- For overdue invoices, highlight the urgency
- Compare periods when relevant (e.g., this month vs last month)
Хід роботи¶
| # | Задача | Статус | Дата |
|---|---|---|---|
| 1 | Створення MD-файлу плану | ✅ Виконано | 2026-04-03 |
| 2 | Додати 6 tool schemas у DOP_TOOLS |
✅ Виконано | 2026-04-03 |
| 3 | Додати 6 tool implementations у tools.py |
✅ Виконано | 2026-04-03 |
| 4 | Зареєструвати у _TOOL_MAP |
✅ Виконано | 2026-04-03 |
| 5 | Оновити SYSTEM_PROMPT у llm.py |
✅ Виконано | 2026-04-03 |
| 6 | Тестування в чаті | ⏳ Очікує | — |
Приклади запитів після реалізації¶
Користувач: "Яка дебіторська заборгованість?"
Агент: get_receivables() → "Загальна заборгованість: 485,200 грн
Прострочено (понад 30 днів): 3 клієнти, 127,400 грн
Найбільший боржник: ТОВ Альфа — 89,500 грн (45 днів)"
Користувач: "Скільки ми отримали за 1 квартал 2026?"
Агент: get_cashflow(date_from=2026-01-01, date_to=2026-03-31) →
"Надходження Q1: 1,240,000 грн
Витрати Q1: 890,000 грн
Чистий рух: +350,000 грн"
Користувач: "Топ клієнтів цього місяця"
Агент: get_top_clients(date_from=...) → таблиця топ-10
Результат¶
Що реалізовано (2026-04-03)¶
Файли змінено:
- backend/eswf_chat/tools.py — додано 6 tool schemas + 6 реалізацій + реєстрація в _TOOL_MAP
- backend/eswf_chat/llm.py — оновлено SYSTEM_PROMPT з інструкціями фін. аналітика
Нові tools (17 total, було 11):
| Tool | Моделі | Повертає |
|------|--------|---------|
| get_receivables | Invoice | Борги по клієнтах, прострочення |
| get_cashflow | IncomingPayment, OutgoingPayment | Рух грошей по місяцях/тижнях |
| get_revenue_report | Invoice (posted) | Виручка по клієнтах або по місяцях |
| get_top_clients | Invoice / IncomingPayment | Топ-N клієнтів |
| get_payment_plan | Invoice | Очікувані платежі по тижнях |
| get_financial_summary | Invoice + Payments | Зведений P&L за період |
Приклади запитів що тепер працюють: