Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
86 / 86
100.00% covered (success)
100.00%
1 / 1
CRAP
100.00% covered (success)
100.00%
1 / 1
GetDealFinancialStatementQuery
100.00% covered (success)
100.00%
86 / 86
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
1 / 1
 execute
100.00% covered (success)
100.00%
86 / 86
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare(strict_types=1);
4
5namespace ImovelZapAi\Financial\Application\Queries;
6
7use ImovelZapAi\Financial\Domain\Exceptions\FinancialException;
8use ImovelZapAi\Financial\Infrastructure\Persistence\Eloquent\FinancialCommissionModel;
9use ImovelZapAi\Financial\Infrastructure\Persistence\Eloquent\FinancialPaymentModel;
10use ImovelZapAi\Financial\Infrastructure\Persistence\Eloquent\FinancialReceiptModel;
11use ImovelZapAi\Financial\Infrastructure\Persistence\Eloquent\FinancialTransactionModel;
12use ImovelZapAi\Financial\Infrastructure\Persistence\Eloquent\FinancialTransferModel;
13use ImovelZapAi\Sales\Infrastructure\Persistence\Eloquent\DealModel;
14
15final class GetDealFinancialStatementQuery
16{
17    /**
18     * @return array<string, mixed>
19     */
20    public function execute(string $tenantId, string $dealId): array
21    {
22        $deal = DealModel::query()
23            ->where('tenant_id', $tenantId)
24            ->with(['contact', 'responsible', 'property'])
25            ->find($dealId);
26
27        if ($deal === null) {
28            throw FinancialException::notFound('Oportunidade');
29        }
30
31        $transactions = FinancialTransactionModel::query()
32            ->where('tenant_id', $tenantId)
33            ->where('deal_id', $dealId)
34            ->with(['schedules', 'payments'])
35            ->orderBy('created_at')
36            ->get();
37
38        $payments = FinancialPaymentModel::query()
39            ->where('tenant_id', $tenantId)
40            ->where('deal_id', $dealId)
41            ->with(['receipt', 'schedule', 'transaction'])
42            ->orderBy('paid_at')
43            ->get();
44
45        $commissions = FinancialCommissionModel::query()
46            ->where('tenant_id', $tenantId)
47            ->where('deal_id', $dealId)
48            ->with(['splits.beneficiaryUser', 'rule'])
49            ->orderBy('calculated_at')
50            ->get();
51
52        $transfers = FinancialTransferModel::query()
53            ->where('tenant_id', $tenantId)
54            ->where('deal_id', $dealId)
55            ->with(['commissionSplit', 'payeeUser'])
56            ->orderBy('created_at')
57            ->get();
58
59        $receipts = FinancialReceiptModel::query()
60            ->where('tenant_id', $tenantId)
61            ->where('deal_id', $dealId)
62            ->with('payment')
63            ->orderBy('issued_at')
64            ->get();
65
66        $timeline = collect()
67            ->merge($transactions->map(fn ($t) => [
68                'kind' => 'transaction',
69                'at' => $t->created_at,
70                'item' => $t,
71            ]))
72            ->merge($payments->map(fn ($p) => [
73                'kind' => 'payment',
74                'at' => $p->paid_at,
75                'item' => $p,
76            ]))
77            ->merge($commissions->map(fn ($c) => [
78                'kind' => 'commission',
79                'at' => $c->calculated_at ?? $c->created_at,
80                'item' => $c,
81            ]))
82            ->merge($transfers->map(fn ($t) => [
83                'kind' => 'transfer',
84                'at' => $t->paid_at ?? $t->created_at,
85                'item' => $t,
86            ]))
87            ->merge($receipts->map(fn ($r) => [
88                'kind' => 'receipt',
89                'at' => $r->issued_at,
90                'item' => $r,
91            ]))
92            ->sortBy('at')
93            ->values();
94
95        $totalNegotiated = (float) ($deal->amount ?? 0);
96        $totalReceived = (float) $payments->sum('amount');
97        $totalCommission = (float) $commissions->sum('total_amount');
98        $pendingTransfers = (float) $transfers
99            ->where('status', \ImovelZapAi\Financial\Domain\Enums\TransferStatus::Pending)
100            ->sum('amount');
101
102        return [
103            'deal' => $deal,
104            'summary' => [
105                'negotiated' => $totalNegotiated,
106                'received' => $totalReceived,
107                'pending' => max(0, $totalNegotiated - $totalReceived),
108                'commission_total' => $totalCommission,
109                'pending_transfers' => $pendingTransfers,
110            ],
111            'transactions' => $transactions,
112            'payments' => $payments,
113            'commissions' => $commissions,
114            'transfers' => $transfers,
115            'receipts' => $receipts,
116            'timeline' => $timeline,
117        ];
118    }
119}