74 خطوط
4.1 KiB
PHP
74 خطوط
4.1 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\AutomationRule;
|
|
use App\Models\AutomationRun;
|
|
use App\Models\Lead;
|
|
use App\Models\Notification;
|
|
use App\Models\Task;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Validation\ValidationException;
|
|
|
|
class AutomationEngine
|
|
{
|
|
public function run(AutomationRule $rule, Model $subject, string $eventKey, array $input = []): AutomationRun
|
|
{
|
|
if (! $rule->is_active) {
|
|
throw ValidationException::withMessages(['rule' => 'قانون غیرفعال است.']);
|
|
}
|
|
if ($existing = AutomationRun::where('event_key', $eventKey)->first()) {
|
|
return $existing;
|
|
}
|
|
if ($rule->runs()->where('subject_type', $subject::class)->where('subject_id', $subject->getKey())->count() >= $rule->max_runs_per_record) {
|
|
throw ValidationException::withMessages(['rule' => 'حداکثر دفعات اجرای این قانون برای رکورد تکمیل شده است.']);
|
|
}
|
|
|
|
return DB::transaction(function () use ($rule, $subject, $eventKey, $input): AutomationRun {
|
|
$run = AutomationRun::create([
|
|
'automation_rule_id' => $rule->id, 'subject_type' => $subject::class, 'subject_id' => $subject->getKey(),
|
|
'status' => 'running', 'event_key' => $eventKey, 'input' => $input, 'started_at' => now(),
|
|
]);
|
|
$output = [];
|
|
try {
|
|
foreach ($rule->actions ?? [] as $action) {
|
|
$type = $action['type'] ?? '';
|
|
if ($type === 'create_task') {
|
|
$assignee = $action['assigned_to'] ?? ($subject instanceof Lead ? $subject->assigned_to : auth()->id());
|
|
$task = Task::create([
|
|
'subject' => $action['subject'] ?? "پیگیری خودکار {$rule->name}",
|
|
'taskable_type' => $subject::class, 'taskable_id' => $subject->getKey(),
|
|
'assigned_to' => $assignee, 'assigned_by' => auth()->id(), 'created_by' => auth()->id(),
|
|
'priority' => $action['priority'] ?? 'normal', 'status' => 'open',
|
|
'due_at' => now()->addMinutes((int) ($action['due_in_minutes'] ?? 1440)), 'visibility' => 'team', 'version' => 1,
|
|
]);
|
|
$output[] = ['type' => $type, 'task_id' => $task->id];
|
|
} elseif ($type === 'notify') {
|
|
$userId = $action['user_id'] ?? auth()->id();
|
|
$notification = Notification::firstOrCreate(['idempotency_key' => "automation:{$eventKey}:{$userId}"], [
|
|
'user_id' => $userId, 'title' => $action['title'] ?? $rule->name,
|
|
'message' => $action['message'] ?? 'یک قانون اتوماسیون اجرا شد.', 'type' => 'automation',
|
|
'data' => ['rule_id' => $rule->id, 'subject_id' => $subject->getKey()],
|
|
]);
|
|
$output[] = ['type' => $type, 'notification_id' => $notification->id];
|
|
} elseif ($type === 'set_lead_priority' && $subject instanceof Lead) {
|
|
$subject->update(['priority' => max(0, min(4, (int) ($action['value'] ?? 1)))]);
|
|
$output[] = ['type' => $type, 'value' => $subject->priority];
|
|
} else {
|
|
throw ValidationException::withMessages(['actions' => "عملیات {$type} پشتیبانی نمیشود."]);
|
|
}
|
|
}
|
|
$run->update(['status' => 'completed', 'output' => $output, 'completed_at' => now()]);
|
|
} catch (\Throwable $exception) {
|
|
$run->update(['status' => 'failed', 'error' => $exception->getMessage(), 'completed_at' => now()]);
|
|
throw $exception;
|
|
}
|
|
|
|
ActivityLogger::log('automation_executed', "Automation {$rule->id} executed", $rule, null, ['run_id' => $run->id]);
|
|
|
|
return $run->fresh();
|
|
});
|
|
}
|
|
}
|