CRM/backend/app/Services/AutomationEngine.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();
});
}
}