Files
InvoiceShelf/app/Platform/Ai/Application/Tools/GetCompanyStatsTool.php
T
Darko Gjorgjijoski 5ef7804e60 refactor: adopt modular domain architecture (#747)
* refactor: stabilize model identities for domain migration

* refactor: extract module platform context

* refactor: assign models to domain contexts

* refactor: extract ai platform context

* refactor: extract storage platform context

* refactor: extract mail platform context

* refactor: extract pdf platform context

* refactor: extract operations platform context

* refactor: move installation into operations platform

* refactor: extract money domain context

* refactor: extract taxation domain context

* refactor: extract catalog domain context

* refactor: extract metadata domain context

* refactor: extract reporting domain context

* refactor: extract purchases domain context

* refactor: extract receivables domain context

* refactor: extract accounts domain context

* refactor: complete reporting statement boundary

* refactor: extract contacts domain context

* refactor: extract sales domain context

* refactor: remove legacy application layers

* fix: migrate legacy bouncer role identities
2026-08-05 17:40:03 +02:00

121 lines
4.0 KiB
PHP

<?php
namespace App\Platform\Ai\Application\Tools;
use App\Domains\Purchases\Models\Expense;
use App\Domains\Receivables\Models\Payment;
use App\Domains\Sales\Models\Invoice;
use App\Platform\Ai\Application\Tools\Concerns\ResolvesPeriod;
/**
* Aggregate stats for the current company over a time window.
*
* Use this when the user asks "how much did we make/spend/invoice in <period>".
* Much cheaper than fetching full invoice lists and summing client-side.
*/
class GetCompanyStatsTool extends AiTool
{
use ResolvesPeriod;
/**
* Bounded periods only — stats over `all_time` is almost always useless
* (collapses every record into one giant bucket), so we don't offer it
* here. The ranking tools do expose `all_time` because ranking by totals
* across the full history is a meaningful question.
*/
private const PERIODS = [
'today',
'this_week',
'this_month',
'last_month',
'this_quarter',
'this_year',
'last_year',
];
public function name(): string
{
return 'get_company_stats';
}
public function description(): string
{
return "Aggregate stats for the current company over a named time period: invoice count and total, payment count and total, expense count and total. Use this for 'how much did we earn/spend' questions.";
}
public function parameterSchema(): array
{
return [
'type' => 'object',
'properties' => [
'period' => [
'type' => 'string',
'enum' => self::PERIODS,
'description' => 'Named time window.',
],
],
'required' => ['period'],
];
}
public function requiredAbility(): ?array
{
// Cross-entity financial snapshot — gated like the company dashboard.
return ['dashboard', null];
}
public function execute(array $arguments, int $companyId, int $userId): mixed
{
$period = (string) ($arguments['period'] ?? 'this_month');
if (! in_array($period, self::PERIODS, true)) {
return ['error' => 'invalid_period', 'valid' => self::PERIODS];
}
// Stats are always date-scoped (the enum above excludes `all_time`),
// so rangeFor() is guaranteed to return a non-null pair here.
[$start, $end] = $this->rangeFor($period);
// Counts issued invoices only; the total below keeps the credit notes,
// whose negated amounts are what net the sales figure back out.
$invoiceCount = Invoice::query()
->where('company_id', $companyId)
->where('type', Invoice::TYPE_INVOICE)
->whereBetween('invoice_date', [$start, $end])
->count();
$invoiceTotal = (float) Invoice::query()
->where('company_id', $companyId)
->whereBetween('invoice_date', [$start, $end])
->sum('total');
$paymentCount = Payment::query()
->where('company_id', $companyId)
->whereBetween('payment_date', [$start, $end])
->count();
$paymentTotal = (float) Payment::query()
->where('company_id', $companyId)
->whereBetween('payment_date', [$start, $end])
->sum('amount');
$expenseCount = Expense::query()
->where('company_id', $companyId)
->whereBetween('expense_date', [$start, $end])
->count();
$expenseTotal = (float) Expense::query()
->where('company_id', $companyId)
->whereBetween('expense_date', [$start, $end])
->sum('amount');
return [
'period' => $period,
'start' => $start->toDateString(),
'end' => $end->toDateString(),
'invoices' => ['count' => $invoiceCount, 'total' => $invoiceTotal],
'payments' => ['count' => $paymentCount, 'total' => $paymentTotal],
'expenses' => ['count' => $expenseCount, 'total' => $expenseTotal],
];
}
}