Big changes added events for decisions
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\DecisionEvents\Contracts;
|
||||
|
||||
use App\Services\DecisionEvents\DecisionEventContext;
|
||||
|
||||
interface DecisionEventHandler
|
||||
{
|
||||
public function handle(DecisionEventContext $context, array $config = []): void;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\DecisionEvents;
|
||||
|
||||
use App\Models\Activity;
|
||||
use App\Models\Client;
|
||||
use App\Models\ClientCase;
|
||||
use App\Models\Contract;
|
||||
use App\Models\Decision;
|
||||
use App\Models\User;
|
||||
|
||||
class DecisionEventContext
|
||||
{
|
||||
public function __construct(
|
||||
public Activity $activity,
|
||||
public ?Decision $decision,
|
||||
public ?Contract $contract,
|
||||
public ?ClientCase $clientCase,
|
||||
public ?Client $client,
|
||||
public ?User $user,
|
||||
) {}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\DecisionEvents\Handlers;
|
||||
|
||||
use App\Services\DecisionEvents\Contracts\DecisionEventHandler;
|
||||
use App\Services\DecisionEvents\DecisionEventContext;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class AddSegmentHandler implements DecisionEventHandler
|
||||
{
|
||||
public function handle(DecisionEventContext $context, array $config = []): void
|
||||
{
|
||||
$contract = $context->contract;
|
||||
if (! $contract) {
|
||||
// If no contract on activity, nothing to apply
|
||||
return;
|
||||
}
|
||||
|
||||
$segmentId = (int) ($config['segment_id'] ?? 0);
|
||||
if ($segmentId <= 0) {
|
||||
throw new InvalidArgumentException('add_segment requires a valid segment_id');
|
||||
}
|
||||
|
||||
$deactivatePrevious = array_key_exists('deactivate_previous', $config)
|
||||
? (bool) $config['deactivate_previous']
|
||||
: true;
|
||||
|
||||
DB::transaction(function () use ($contract, $segmentId, $deactivatePrevious) {
|
||||
if ($deactivatePrevious) {
|
||||
DB::table('contract_segment')
|
||||
->where('contract_id', $contract->id)
|
||||
->where('active', 1)
|
||||
->update(['active' => 0, 'updated_at' => now()]);
|
||||
}
|
||||
|
||||
// Ensure pivot exists and mark active=1
|
||||
$existing = DB::table('contract_segment')
|
||||
->where('contract_id', $contract->id)
|
||||
->where('segment_id', $segmentId)
|
||||
->first();
|
||||
|
||||
if ($existing) {
|
||||
DB::table('contract_segment')
|
||||
->where('id', $existing->id)
|
||||
->update(['active' => 1, 'updated_at' => now()]);
|
||||
} else {
|
||||
DB::table('contract_segment')->insert([
|
||||
'contract_id' => $contract->id,
|
||||
'segment_id' => $segmentId,
|
||||
'active' => 1,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\DecisionEvents\Handlers;
|
||||
|
||||
use App\Models\ArchiveSetting;
|
||||
use App\Services\Archiving\ArchiveExecutor;
|
||||
use App\Services\DecisionEvents\Contracts\DecisionEventHandler;
|
||||
use App\Services\DecisionEvents\DecisionEventContext;
|
||||
|
||||
class ArchiveContractHandler implements DecisionEventHandler
|
||||
{
|
||||
/**
|
||||
* Config contract:
|
||||
* - archive_setting_id: int (required) – which ArchiveSetting to execute
|
||||
* - reactivate: bool (optional) – override ArchiveSetting->reactivate per run
|
||||
*/
|
||||
public function handle(DecisionEventContext $context, array $config = []): void
|
||||
{
|
||||
$activity = $context->activity;
|
||||
|
||||
// Require a contract_id from the activity per request requirements
|
||||
$contractId = (int) ($activity->contract_id ?? 0);
|
||||
if ($contractId <= 0) {
|
||||
throw new \InvalidArgumentException('ArchiveContractHandler requires activity.contract_id');
|
||||
}
|
||||
|
||||
$settingId = (int) ($config['archive_setting_id'] ?? 0);
|
||||
if ($settingId <= 0) {
|
||||
throw new \InvalidArgumentException('ArchiveContractHandler requires config.archive_setting_id');
|
||||
}
|
||||
|
||||
$setting = ArchiveSetting::query()->findOrFail($settingId);
|
||||
|
||||
// Optionally override reactivate flag for this run
|
||||
if (array_key_exists('reactivate', $config)) {
|
||||
$setting->reactivate = (bool) $config['reactivate'];
|
||||
}
|
||||
|
||||
$results = app(ArchiveExecutor::class)->executeSetting(
|
||||
$setting,
|
||||
['contract_id' => $contractId],
|
||||
$activity->user_id ?? null,
|
||||
null,
|
||||
);
|
||||
|
||||
// If the ArchiveSetting specifies a segment, move the contract to that segment (mirror controller logic)
|
||||
if (! empty($setting->segment_id)) {
|
||||
try {
|
||||
$segmentId = (int) $setting->segment_id;
|
||||
$clientCase = $context->clientCase; // expected per context contract
|
||||
$contract = $context->contract; // already loaded on context
|
||||
if ($clientCase && $contract) {
|
||||
\DB::transaction(function () use ($clientCase, $contract, $segmentId) {
|
||||
// Ensure the segment is attached to the client case (activate if previously inactive)
|
||||
$casePivot = \DB::table('client_case_segment')
|
||||
->where('client_case_id', $clientCase->id)
|
||||
->where('segment_id', $segmentId)
|
||||
->first();
|
||||
if (! $casePivot) {
|
||||
\DB::table('client_case_segment')->insert([
|
||||
'client_case_id' => $clientCase->id,
|
||||
'segment_id' => $segmentId,
|
||||
'active' => true,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
} elseif (! $casePivot->active) {
|
||||
\DB::table('client_case_segment')
|
||||
->where('id', $casePivot->id)
|
||||
->update(['active' => true, 'updated_at' => now()]);
|
||||
}
|
||||
|
||||
// Deactivate all current active contract segments
|
||||
\DB::table('contract_segment')
|
||||
->where('contract_id', $contract->id)
|
||||
->where('active', true)
|
||||
->update(['active' => false, 'updated_at' => now()]);
|
||||
|
||||
// Attach or activate the target segment for this contract
|
||||
$existing = \DB::table('contract_segment')
|
||||
->where('contract_id', $contract->id)
|
||||
->where('segment_id', $segmentId)
|
||||
->first();
|
||||
if ($existing) {
|
||||
\DB::table('contract_segment')
|
||||
->where('id', $existing->id)
|
||||
->update(['active' => true, 'updated_at' => now()]);
|
||||
} else {
|
||||
\DB::table('contract_segment')->insert([
|
||||
'contract_id' => $contract->id,
|
||||
'segment_id' => $segmentId,
|
||||
'active' => true,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
// Do not fail the event; log warning for diagnostics
|
||||
logger()->warning('ArchiveContractHandler: failed to move contract to segment', [
|
||||
'error' => $e->getMessage(),
|
||||
'setting_id' => $setting->id,
|
||||
'segment_id' => $setting->segment_id,
|
||||
'contract_id' => $contractId,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\DecisionEvents\Handlers;
|
||||
|
||||
use App\Jobs\EndFieldJob;
|
||||
use App\Services\DecisionEvents\Contracts\DecisionEventHandler;
|
||||
use App\Services\DecisionEvents\DecisionEventContext;
|
||||
use Illuminate\Support\Facades\Bus;
|
||||
|
||||
class EndFieldJobHandler implements DecisionEventHandler
|
||||
{
|
||||
/**
|
||||
* Config contract:
|
||||
* - any pass-through keys needed by the EndFieldJob implementation
|
||||
*/
|
||||
public function handle(DecisionEventContext $context, array $config = []): void
|
||||
{
|
||||
$activity = $context->activity;
|
||||
$job = new EndFieldJob(
|
||||
activityId: (int) $activity->id,
|
||||
contractId: $activity->contract_id ? (int) $activity->contract_id : null,
|
||||
config: $config,
|
||||
);
|
||||
|
||||
// Run synchronously in local/dev/testing or when debug is on or queue driver is sync; otherwise queue it.
|
||||
$shouldRunSync = app()->environment(['local', 'development', 'dev', 'testing'])
|
||||
|| (bool) config('app.debug')
|
||||
|| config('queue.default') === 'sync';
|
||||
|
||||
if ($shouldRunSync) {
|
||||
Bus::dispatchSync($job);
|
||||
} else {
|
||||
dispatch($job);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\DecisionEvents;
|
||||
|
||||
use App\Services\DecisionEvents\Contracts\DecisionEventHandler;
|
||||
use App\Services\DecisionEvents\Handlers\AddSegmentHandler;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class Registry
|
||||
{
|
||||
/**
|
||||
* Map of event keys to handler classes.
|
||||
*
|
||||
* @var array<string, class-string<DecisionEventHandler>>
|
||||
*/
|
||||
protected static array $map = [
|
||||
'add_segment' => AddSegmentHandler::class,
|
||||
'archive_contract' => \App\Services\DecisionEvents\Handlers\ArchiveContractHandler::class,
|
||||
'end_field_job' => \App\Services\DecisionEvents\Handlers\EndFieldJobHandler::class,
|
||||
];
|
||||
|
||||
public static function resolve(string $key): DecisionEventHandler
|
||||
{
|
||||
$key = trim(strtolower($key));
|
||||
$class = static::$map[$key] ?? null;
|
||||
if (! $class || ! class_exists($class)) {
|
||||
throw new InvalidArgumentException("Unknown decision event handler for key: {$key}");
|
||||
}
|
||||
$handler = app($class);
|
||||
if (! $handler instanceof DecisionEventHandler) {
|
||||
throw new InvalidArgumentException("Handler for key {$key} must implement DecisionEventHandler");
|
||||
}
|
||||
|
||||
return $handler;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user