Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
35 / 35
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
ReassignVisitBrokerAction
100.00% covered (success)
100.00%
35 / 35
100.00% covered (success)
100.00%
2 / 2
5
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 execute
100.00% covered (success)
100.00%
34 / 34
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2
3declare(strict_types=1);
4
5namespace ImovelZapAi\Visits\Application\Actions;
6
7use App\Models\User;
8use Illuminate\Support\Facades\DB;
9use ImovelZapAi\Visits\Application\Services\AgendaConflictChecker;
10use ImovelZapAi\Visits\Application\Services\VisitLogWriter;
11use ImovelZapAi\Visits\Application\Services\VisitSnapshotter;
12use ImovelZapAi\Visits\Domain\Enums\VisitLogEvent;
13use ImovelZapAi\Visits\Domain\Enums\VisitParticipantRole;
14use ImovelZapAi\Visits\Domain\Exceptions\VisitException;
15use ImovelZapAi\Visits\Infrastructure\Persistence\Eloquent\VisitModel;
16use ImovelZapAi\Visits\Infrastructure\Persistence\Eloquent\VisitParticipantModel;
17
18final class ReassignVisitBrokerAction
19{
20    public function __construct(
21        private readonly AgendaConflictChecker $conflictChecker,
22        private readonly VisitLogWriter $logWriter,
23        private readonly VisitSnapshotter $snapshotter,
24    ) {}
25
26    public function execute(VisitModel $visit, User $actor, int $newBrokerId): VisitModel
27    {
28        if ($visit->status->isTerminal()) {
29            throw VisitException::invalidState($visit->status->value, 'reassign');
30        }
31
32        if ($visit->scheduled_start !== null && $visit->scheduled_end !== null) {
33            $this->conflictChecker->assertNoConflict(
34                $visit->tenant_id,
35                $newBrokerId,
36                $visit->scheduled_start,
37                $visit->scheduled_end,
38                $visit->id,
39            );
40        }
41
42        return DB::transaction(function () use ($visit, $actor, $newBrokerId): VisitModel {
43            $before = $this->snapshotter->snapshot($visit);
44
45            $visit->forceFill(['responsible_user_id' => $newBrokerId])->save();
46
47            VisitParticipantModel::query()
48                ->where('visit_id', $visit->id)
49                ->where('role', VisitParticipantRole::Responsible)
50                ->delete();
51
52            VisitParticipantModel::query()->create([
53                'tenant_id' => $visit->tenant_id,
54                'visit_id' => $visit->id,
55                'user_id' => $newBrokerId,
56                'role' => VisitParticipantRole::Responsible,
57            ]);
58
59            $this->logWriter->write(
60                $visit->tenant_id,
61                $visit->id,
62                VisitLogEvent::BrokerChanged,
63                actorUserId: (int) $actor->id,
64                before: $before,
65                after: $this->snapshotter->snapshot($visit->fresh()),
66                message: 'Corretor responsável alterado.',
67            );
68
69            return $visit->fresh(['participants', 'responsible']);
70        });
71    }
72}