Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
97.83% covered (success)
97.83%
45 / 46
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
SendSignatureRequestAction
97.83% covered (success)
97.83%
45 / 46
50.00% covered (danger)
50.00%
1 / 2
7
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.78% covered (success)
97.78%
44 / 45
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3declare(strict_types=1);
4
5namespace ImovelZapAi\Signatures\Application\Actions;
6
7use App\Models\User;
8use Illuminate\Support\Facades\DB;
9use ImovelZapAi\Signatures\Application\Services\SignatureAccessTokenService;
10use ImovelZapAi\Signatures\Application\Services\SignatureAuditWriter;
11use ImovelZapAi\Signatures\Application\Services\SignatureProviderRegistry;
12use ImovelZapAi\Signatures\Application\Services\SignatureStatusSynchronizer;
13use ImovelZapAi\Signatures\Domain\Enums\SignatureAuditEvent;
14use ImovelZapAi\Signatures\Domain\Enums\SignatureRequestStatus;
15use ImovelZapAi\Signatures\Domain\Events\SignatureRequested;
16use ImovelZapAi\Signatures\Domain\Exceptions\SignatureException;
17use ImovelZapAi\Signatures\Infrastructure\Persistence\Eloquent\SignatureReminderModel;
18use ImovelZapAi\Signatures\Infrastructure\Persistence\Eloquent\SignatureRequestModel;
19
20final class SendSignatureRequestAction
21{
22    public function __construct(
23        private readonly SignatureAccessTokenService $tokens,
24        private readonly SignatureProviderRegistry $providers,
25        private readonly SignatureAuditWriter $audit,
26        private readonly SignatureStatusSynchronizer $sync,
27    ) {}
28
29    public function execute(SignatureRequestModel $request, User $actor): SignatureRequestModel
30    {
31        if (! in_array($request->status, [SignatureRequestStatus::Draft, SignatureRequestStatus::InReview], true)) {
32            throw SignatureException::invalidState('somente rascunhos podem ser enviados.');
33        }
34
35        return DB::transaction(function () use ($request, $actor): SignatureRequestModel {
36            $request->load('signers');
37
38            $signerUrls = [];
39            $signerPlains = [];
40            foreach ($request->signers as $signer) {
41                $issued = $this->tokens->issueForSigner($signer);
42                $signerUrls[$signer->id] = $issued['url'];
43                $signerPlains[$signer->id] = $issued['plain'];
44            }
45
46            $meta = $request->meta ?? [];
47            $meta['signer_urls'] = $signerUrls;
48            if (app()->environment('testing')) {
49                $meta['signer_plains'] = $signerPlains;
50            }
51            $request->forceFill(['meta' => $meta])->save();
52
53            $provider = $this->providers->get($request->provider);
54            $provider->send($request->fresh(['signers', 'deal.conversation', 'document.contact']));
55
56            $request->forceFill([
57                'status' => SignatureRequestStatus::AwaitingSignatures,
58                'sent_at' => now(),
59            ])->save();
60
61            $hours = (array) config('signatures.reminder_hours', [24, 72]);
62            foreach ($request->signers as $signer) {
63                foreach ($hours as $hour) {
64                    SignatureReminderModel::query()->create([
65                        'tenant_id' => $request->tenant_id,
66                        'signature_request_id' => $request->id,
67                        'signer_id' => $signer->id,
68                        'channel' => 'whatsapp',
69                        'scheduled_at' => now()->addHours((int) $hour),
70                        'status' => 'pending',
71                    ]);
72                }
73            }
74
75            $this->audit->write(
76                $request->tenant_id,
77                $request->id,
78                SignatureAuditEvent::Sent,
79                actorType: 'broker',
80                actorUserId: (int) $actor->id,
81                payload: ['signer_urls' => $signerUrls],
82                message: 'Solicitação de assinatura enviada.',
83            );
84
85            SignatureRequested::dispatch($request->tenant_id, $request->id);
86
87            $this->sync->sync($request);
88
89            return $request->fresh(['signers', 'steps', 'document', 'reminders']);
90        });
91    }
92}