Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
AcceptInvitationAction
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 2
30
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 31
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2
3declare(strict_types=1);
4
5namespace ImovelZapAi\Organizations\Application\Actions;
6
7use App\Models\User;
8use Illuminate\Support\Facades\DB;
9use Illuminate\Validation\ValidationException;
10use ImovelZapAi\Organizations\Application\Services\PlanLimitGuard;
11use ImovelZapAi\Organizations\Domain\Enums\InvitationStatus;
12use ImovelZapAi\Organizations\Infrastructure\Persistence\Eloquent\OrganizationInvitationModel;
13use ImovelZapAi\Tenancy\Infrastructure\Persistence\Eloquent\TenantModel;
14use ImovelZapAi\Users\Application\Actions\CreateUserAction;
15
16final class AcceptInvitationAction
17{
18    public function __construct(
19        private readonly CreateUserAction $createUser,
20        private readonly PlanLimitGuard $planLimitGuard,
21        private readonly EnsureOrganizationBootstrapAction $bootstrap,
22    ) {}
23
24    /**
25     * @return array{user: User, invitation: OrganizationInvitationModel, tenant: TenantModel}
26     */
27    public function execute(string $token, string $name, string $password): array
28    {
29        /** @var OrganizationInvitationModel|null $invitation */
30        $invitation = OrganizationInvitationModel::query()
31            ->where('token', $token)
32            ->first();
33
34        if ($invitation === null || ! $invitation->isPending()) {
35            throw ValidationException::withMessages([
36                'token' => ['Convite inválido ou expirado.'],
37            ]);
38        }
39
40        $tenantId = (string) $invitation->tenant_id;
41        $this->planLimitGuard->assertCanAddUser($tenantId);
42        $this->bootstrap->execute($tenantId);
43
44        return DB::transaction(function () use ($invitation, $name, $password, $tenantId): array {
45            $user = $this->createUser->execute(
46                tenantId: $tenantId,
47                name: $name,
48                email: (string) $invitation->email,
49                password: $password,
50                role: $invitation->role,
51            );
52
53            $invitation->forceFill([
54                'status' => InvitationStatus::Accepted,
55                'accepted_at' => now(),
56            ])->save();
57
58            $tenant = TenantModel::query()->findOrFail($tenantId);
59
60            if ($tenant->owner_user_id === null) {
61                $tenant->forceFill(['owner_user_id' => $user->id])->save();
62            }
63
64            return [
65                'user' => $user,
66                'invitation' => $invitation->fresh() ?? $invitation,
67                'tenant' => $tenant->fresh() ?? $tenant,
68            ];
69        });
70    }
71}