". * 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); $invoiceCount = Invoice::query() ->where('company_id', $companyId) ->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], ]; } }