Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 43
0.00% covered (danger)
0.00%
0 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
CreateWorkflowAction
0.00% covered (danger)
0.00%
0 / 43
0.00% covered (danger)
0.00%
0 / 2
42
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 / 42
0.00% covered (danger)
0.00%
0 / 1
30
1<?php
2
3declare(strict_types=1);
4
5namespace ImovelZapAi\Automation\Application\Actions;
6
7use App\Models\User;
8use Illuminate\Support\Facades\DB;
9use ImovelZapAi\Automation\Application\Services\TriggerCatalog;
10use ImovelZapAi\Automation\Domain\Enums\WorkflowStatus;
11use ImovelZapAi\Automation\Domain\Exceptions\AutomationException;
12use ImovelZapAi\Automation\Infrastructure\Persistence\Eloquent\AutomationActionModel;
13use ImovelZapAi\Automation\Infrastructure\Persistence\Eloquent\AutomationConditionModel;
14use ImovelZapAi\Automation\Infrastructure\Persistence\Eloquent\AutomationTriggerModel;
15use ImovelZapAi\Automation\Infrastructure\Persistence\Eloquent\AutomationWorkflowModel;
16use ImovelZapAi\Organizations\Application\Services\PlanLimitGuard;
17use ImovelZapAi\Organizations\Domain\Exceptions\PlanLimitExceededException;
18
19final class CreateWorkflowAction
20{
21    public function __construct(
22        private readonly PlanLimitGuard $planLimitGuard,
23    ) {}
24
25    /**
26     * @param  array{
27     *     name: string,
28     *     description?: string|null,
29     *     status?: string,
30     *     trigger: array{event_key: string, config?: array|null},
31     *     conditions?: list<array{field: string, operator: string, value?: string|null, sort_order?: int}>,
32     *     actions?: list<array{action_key: string, config?: array|null, delay_seconds?: int, sort_order?: int}>,
33     * }  $data
34     */
35    public function execute(string $tenantId, User $user, array $data): AutomationWorkflowModel
36    {
37        try {
38            $this->planLimitGuard->assertFeatureEnabled($tenantId, 'automations');
39        } catch (PlanLimitExceededException $exception) {
40            throw AutomationException::invalidState($exception->getMessage());
41        }
42
43        $eventClass = TriggerCatalog::classForKey($data['trigger']['event_key']);
44
45        if ($eventClass === null) {
46            throw AutomationException::invalidTrigger($data['trigger']['event_key']);
47        }
48
49        return DB::transaction(function () use ($tenantId, $user, $data, $eventClass): AutomationWorkflowModel {
50            $workflow = AutomationWorkflowModel::query()->create([
51                'tenant_id' => $tenantId,
52                'name' => $data['name'],
53                'description' => $data['description'] ?? null,
54                'status' => WorkflowStatus::tryFrom((string) ($data['status'] ?? 'draft')) ?? WorkflowStatus::Draft,
55                'created_by' => $user->id,
56                'meta' => [],
57            ]);
58
59            AutomationTriggerModel::query()->create([
60                'tenant_id' => $tenantId,
61                'workflow_id' => $workflow->id,
62                'event_key' => $data['trigger']['event_key'],
63                'event_class' => $eventClass,
64                'config' => $data['trigger']['config'] ?? null,
65            ]);
66
67            foreach ($data['conditions'] ?? [] as $index => $condition) {
68                AutomationConditionModel::query()->create([
69                    'tenant_id' => $tenantId,
70                    'workflow_id' => $workflow->id,
71                    'field' => $condition['field'],
72                    'operator' => $condition['operator'],
73                    'value' => $condition['value'] ?? null,
74                    'sort_order' => $condition['sort_order'] ?? $index,
75                ]);
76            }
77
78            foreach ($data['actions'] ?? [] as $index => $action) {
79                AutomationActionModel::query()->create([
80                    'tenant_id' => $tenantId,
81                    'workflow_id' => $workflow->id,
82                    'action_key' => $action['action_key'],
83                    'config' => $action['config'] ?? null,
84                    'delay_seconds' => (int) ($action['delay_seconds'] ?? 0),
85                    'sort_order' => $action['sort_order'] ?? $index,
86                ]);
87            }
88
89            return $workflow->fresh(['triggers', 'conditions', 'actions']);
90        });
91    }
92}