Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
49 / 49
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
CreateDealTaskAction
100.00% covered (success)
100.00%
49 / 49
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%
48 / 48
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2
3declare(strict_types=1);
4
5namespace ImovelZapAi\Sales\Application\Actions;
6
7use App\Models\User;
8use Illuminate\Support\Facades\DB;
9use ImovelZapAi\Sales\Application\Services\DealActivityRecorder;
10use ImovelZapAi\Sales\Application\Services\DealHistoryWriter;
11use ImovelZapAi\Sales\Domain\Enums\DealActivityType;
12use ImovelZapAi\Sales\Domain\Enums\DealHistoryEvent;
13use ImovelZapAi\Sales\Domain\Enums\DealPriority;
14use ImovelZapAi\Sales\Domain\Enums\DealTaskStatus;
15use ImovelZapAi\Sales\Domain\Enums\DealTaskType;
16use ImovelZapAi\Sales\Domain\Events\DealTaskCreated;
17use ImovelZapAi\Sales\Domain\Exceptions\DealException;
18use ImovelZapAi\Sales\Infrastructure\Persistence\Eloquent\DealModel;
19use ImovelZapAi\Sales\Infrastructure\Persistence\Eloquent\DealTaskModel;
20
21final class CreateDealTaskAction
22{
23    public function __construct(
24        private readonly DealActivityRecorder $activities,
25        private readonly DealHistoryWriter $history,
26    ) {}
27
28    /**
29     * @param  array{
30     *     type: string,
31     *     title: string,
32     *     description?: string|null,
33     *     due_at?: string|null,
34     *     priority?: string|null,
35     *     responsible_user_id?: int|null,
36     *     is_automatic?: bool,
37     *     set_as_next_action?: bool,
38     * }  $data
39     */
40    public function execute(DealModel $deal, User $actor, array $data): DealTaskModel
41    {
42        if ($deal->isClosed() && ! (bool) ($data['is_automatic'] ?? false)) {
43            throw DealException::alreadyClosed();
44        }
45
46        return DB::transaction(function () use ($deal, $actor, $data): DealTaskModel {
47            $type = DealTaskType::from($data['type']);
48            $task = DealTaskModel::query()->create([
49                'tenant_id' => $deal->tenant_id,
50                'deal_id' => $deal->id,
51                'responsible_user_id' => $data['responsible_user_id'] ?? $deal->responsible_user_id ?? $actor->id,
52                'created_by' => $actor->id,
53                'type' => $type,
54                'priority' => DealPriority::tryFrom((string) ($data['priority'] ?? 'medium')) ?? DealPriority::Medium,
55                'status' => DealTaskStatus::Open,
56                'title' => $data['title'],
57                'description' => $data['description'] ?? null,
58                'due_at' => $data['due_at'] ?? null,
59                'is_automatic' => (bool) ($data['is_automatic'] ?? false),
60            ]);
61
62            $this->activities->record(
63                $deal,
64                DealActivityType::TaskCreated,
65                $task->title,
66                $task->description,
67                (int) $actor->id,
68                ['task_id' => $task->id, 'type' => $type->value],
69            );
70
71            $this->history->write(
72                $deal->tenant_id,
73                $deal->id,
74                DealHistoryEvent::TaskCreated,
75                actorUserId: (int) $actor->id,
76                after: ['task_id' => $task->id],
77                message: $task->title,
78            );
79
80            if (($data['set_as_next_action'] ?? true) === true) {
81                $deal->forceFill([
82                    'next_action_at' => $task->due_at,
83                    'next_action_type' => $type,
84                    'next_action_notes' => $task->title,
85                ])->save();
86
87                $this->activities->record(
88                    $deal,
89                    DealActivityType::NextActionSet,
90                    'Próxima ação: '.$task->title,
91                    actorUserId: (int) $actor->id,
92                );
93            }
94
95            DealTaskCreated::dispatch($deal->tenant_id, $deal->id, $task->id);
96
97            return $task->fresh();
98        });
99    }
100}