Teren-app/app/Listeners/TriggerDecisionEvents.php
2025-10-22 23:20:04 +02:00

78 lines
2.5 KiB
PHP

<?php
namespace App\Listeners;
use App\Events\ActivityDecisionApplied;
use App\Jobs\RunDecisionEvent;
use Illuminate\Support\Facades\Bus;
class TriggerDecisionEvents
{
public function handle(ActivityDecisionApplied $event): void
{
$activity = $event->activity->loadMissing(['decision.events' => function ($q) {
$q->wherePivot('active', true);
}, 'contract', 'clientCase.client', 'user']);
$decision = $activity->decision;
if (! $decision) {
return;
}
$events = $decision->events;
if ($events->isEmpty()) {
return;
}
// Sort by run_order when provided; otherwise keep natural order
$sorted = $events->sortBy(function ($ev) {
return $ev->pivot?->run_order ?? PHP_INT_MAX;
})->values();
$jobs = [];
foreach ($sorted as $ev) {
$base = is_array($ev->config ?? null) ? $ev->config : [];
$pivotCfgRaw = $ev->pivot?->config ?? null;
$pivotCfg = is_array($pivotCfgRaw)
? $pivotCfgRaw
: (is_string($pivotCfgRaw) ? (json_decode($pivotCfgRaw, true) ?: []) : []);
$effectiveConfig = array_replace_recursive($base, $pivotCfg);
$jobs[] = new RunDecisionEvent(
activityId: $activity->id,
eventId: $ev->id,
eventKey: (string) ($ev->key ?? ''),
config: $effectiveConfig,
);
}
// If any event has a finite run_order, chain to enforce order; else dispatch in parallel
$hasOrder = $sorted->contains(fn ($ev) => $ev->pivot?->run_order !== null);
// Run synchronously for local/dev/testing (or when debug is on) to ensure immediate effects without a queue worker
$shouldRunSync = app()->environment(['local', 'development', 'dev', 'testing'])
|| (bool) config('app.debug')
|| config('queue.default') === 'sync';
if ($hasOrder) {
if ($shouldRunSync) {
foreach ($jobs as $job) {
Bus::dispatchSync($job);
}
} else {
Bus::chain($jobs)->dispatch();
}
} else {
if ($shouldRunSync) {
foreach ($jobs as $job) {
Bus::dispatchSync($job);
}
} else {
foreach ($jobs as $job) {
dispatch($job);
}
}
}
}
}