Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
37 / 37
100.00% covered (success)
100.00%
1 / 1
CRAP
100.00% covered (success)
100.00%
1 / 1
GetDocumentDashboardQuery
100.00% covered (success)
100.00%
37 / 37
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
1 / 1
 execute
100.00% covered (success)
100.00%
37 / 37
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3declare(strict_types=1);
4
5namespace ImovelZapAi\Documents\Application\Queries;
6
7use ImovelZapAi\Documents\Domain\Enums\DocumentStatus;
8use ImovelZapAi\Documents\Infrastructure\Persistence\Eloquent\BusinessDocumentModel;
9
10final class GetDocumentDashboardQuery
11{
12    /** @return array<string, mixed> */
13    public function execute(string $tenantId): array
14    {
15        $sent = BusinessDocumentModel::query()->where('tenant_id', $tenantId)->whereNotNull('shared_at')->count();
16        $open = BusinessDocumentModel::query()->where('tenant_id', $tenantId)->whereIn('status', [
17            DocumentStatus::Shared->value,
18            DocumentStatus::ChangesRequested->value,
19        ])->count();
20        $accepted = BusinessDocumentModel::query()->where('tenant_id', $tenantId)->where('status', DocumentStatus::Accepted)->count();
21        $rejected = BusinessDocumentModel::query()->where('tenant_id', $tenantId)->where('status', DocumentStatus::Rejected)->count();
22        $expired = BusinessDocumentModel::query()->where('tenant_id', $tenantId)->where(function ($q): void {
23            $q->where('status', DocumentStatus::Expired)
24                ->orWhere(function ($q2): void {
25                    $q2->whereIn('status', [DocumentStatus::Shared->value, DocumentStatus::Draft->value])
26                        ->whereNotNull('expires_at')
27                        ->where('expires_at', '<', now());
28                });
29        })->count();
30
31        $decided = $accepted + $rejected;
32        $acceptRate = $decided > 0 ? round(($accepted / $decided) * 100, 1) : null;
33
34        $avgHours = BusinessDocumentModel::query()
35            ->where('tenant_id', $tenantId)
36            ->where('status', DocumentStatus::Accepted)
37            ->whereNotNull('shared_at')
38            ->whereNotNull('decided_at')
39            ->get(['shared_at', 'decided_at'])
40            ->avg(fn (BusinessDocumentModel $d) => $d->shared_at->diffInMinutes($d->decided_at) / 60);
41
42        $totalAmount = BusinessDocumentModel::query()
43            ->where('tenant_id', $tenantId)
44            ->whereIn('status', [DocumentStatus::Shared->value, DocumentStatus::Accepted->value, DocumentStatus::ChangesRequested->value])
45            ->sum('amount');
46
47        return [
48            'sent' => $sent,
49            'open' => $open,
50            'accepted' => $accepted,
51            'accept_rate' => $acceptRate,
52            'avg_accept_hours' => $avgHours !== null ? round((float) $avgHours, 1) : null,
53            'expired' => $expired,
54            'total_amount' => (float) $totalAmount,
55        ];
56    }
57}