Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
98.00% covered (success)
98.00%
49 / 50
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
CreateDealFinancialBootstrapAction
98.00% covered (success)
98.00%
49 / 50
50.00% covered (danger)
50.00%
1 / 2
8
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 execute
97.96% covered (success)
97.96%
48 / 49
0.00% covered (danger)
0.00%
0 / 1
7
1<?php
2
3declare(strict_types=1);
4
5namespace ImovelZapAi\Financial\Application\Actions;
6
7use App\Models\User;
8use Illuminate\Support\Facades\DB;
9use ImovelZapAi\Financial\Domain\Enums\PaymentScheduleStatus;
10use ImovelZapAi\Financial\Domain\Enums\TransactionStatus;
11use ImovelZapAi\Financial\Domain\Enums\TransactionType;
12use ImovelZapAi\Financial\Domain\Exceptions\FinancialException;
13use ImovelZapAi\Financial\Infrastructure\Persistence\Eloquent\FinancialCommissionModel;
14use ImovelZapAi\Financial\Infrastructure\Persistence\Eloquent\FinancialPaymentScheduleModel;
15use ImovelZapAi\Financial\Infrastructure\Persistence\Eloquent\FinancialTransactionModel;
16use ImovelZapAi\Sales\Infrastructure\Persistence\Eloquent\DealModel;
17
18final class CreateDealFinancialBootstrapAction
19{
20    public function __construct(
21        private readonly EnsureDefaultCommissionRuleAction $ensureRule,
22        private readonly CreateFinancialTransactionAction $createTransaction,
23        private readonly CalculateCommissionAction $calculateCommission,
24    ) {}
25
26    /**
27     * @return array{
28     *     transaction: FinancialTransactionModel,
29     *     commission: FinancialCommissionModel,
30     *     schedule: FinancialPaymentScheduleModel|null,
31     * }
32     */
33    public function execute(
34        string $tenantId,
35        string $dealId,
36        ?User $actor = null,
37        bool $withSchedule = true,
38        ?string $signatureRequestId = null,
39        bool $skipIfExists = false,
40    ): array {
41        return DB::transaction(function () use (
42            $tenantId,
43            $dealId,
44            $actor,
45            $withSchedule,
46            $signatureRequestId,
47            $skipIfExists,
48        ): array {
49            if ($skipIfExists && FinancialTransactionModel::query()
50                ->where('tenant_id', $tenantId)
51                ->where('deal_id', $dealId)
52                ->exists()) {
53                throw FinancialException::alreadyBootstrapped();
54            }
55
56            $deal = DealModel::query()
57                ->where('tenant_id', $tenantId)
58                ->find($dealId);
59
60            if ($deal === null) {
61                throw FinancialException::notFound('Oportunidade');
62            }
63
64            if ($deal->amount === null || (float) $deal->amount <= 0) {
65                throw FinancialException::dealWithoutAmount();
66            }
67
68            $rule = $this->ensureRule->execute($tenantId);
69
70            $transaction = $this->createTransaction->execute($tenantId, $actor, [
71                'deal_id' => $dealId,
72                'type' => TransactionType::Entrance->value,
73                'amount' => $deal->amount,
74                'status' => TransactionStatus::Pending->value,
75                'currency' => $deal->currency ?? 'BRL',
76                'due_at' => now()->addDays(30)->toDateTimeString(),
77                'description' => 'Entrada — '.$deal->title,
78                'signature_request_id' => $signatureRequestId,
79            ]);
80
81            $commission = $this->calculateCommission->execute($tenantId, $deal, $rule);
82
83            $schedule = null;
84            if ($withSchedule) {
85                $schedule = FinancialPaymentScheduleModel::query()->create([
86                    'tenant_id' => $tenantId,
87                    'deal_id' => $dealId,
88                    'transaction_id' => $transaction->id,
89                    'installment_no' => 1,
90                    'due_at' => $transaction->due_at ?? now()->addDays(30),
91                    'amount' => $transaction->amount,
92                    'status' => PaymentScheduleStatus::Pending,
93                ]);
94            }
95
96            return [
97                'transaction' => $transaction,
98                'commission' => $commission,
99                'schedule' => $schedule,
100            ];
101        });
102    }
103}