47 lines
2.5 KiB
PHP
47 lines
2.5 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\ExistingBusiness;
|
|
use App\Models\User;
|
|
use Illuminate\Support\Facades\Crypt;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Gate;
|
|
use Illuminate\Support\Facades\Validator;
|
|
use Illuminate\Support\Str;
|
|
|
|
final class ExistingBusinessIntake
|
|
{
|
|
public function transition(User $actor, string $id, int $version, string $action, string $note, bool $consent = false): ExistingBusiness
|
|
{
|
|
Validator::make(compact('action', 'note'), [
|
|
'action' => ['required', 'in:submitted,in_review,needs_information,withdrawn'],
|
|
'note' => ['required', 'string', 'min:10', 'max:2000'],
|
|
])->validate();
|
|
|
|
return DB::transaction(function () use ($actor, $id, $version, $action, $note, $consent) {
|
|
$business = ExistingBusiness::whereKey($id)->lockForUpdate()->firstOrFail();
|
|
Gate::forUser($actor)->authorize(in_array($action, ['submitted', 'withdrawn'], true) ? 'owns' : 'review', $business);
|
|
abort_unless($business->version_no === $version, 409, 'Versão desactualizada.');
|
|
$allowed = ['submitted' => ['draft', 'needs_information'], 'in_review' => ['submitted'],
|
|
'needs_information' => ['in_review'], 'withdrawn' => ['draft', 'submitted', 'in_review', 'needs_information']];
|
|
abort_unless(in_array($business->status, $allowed[$action], true), 409, 'Transição indisponível neste estado.');
|
|
if ($action === 'submitted') {
|
|
Validator::make([...$business->payload, 'consent' => $consent], [
|
|
'description' => ['required', 'string', 'min:30'], 'source_reference' => ['required', 'string', 'min:10'],
|
|
'valid_until' => ['required', 'date_format:Y-m-d', 'after_or_equal:today'], 'consent' => ['accepted'],
|
|
])->validate();
|
|
}
|
|
$business->status = $action;
|
|
$business->version_no++;
|
|
$business->save();
|
|
DB::table('existing_business_reviews')->insert(['id' => (string) Str::uuid(), 'business_id' => $id, 'actor_id' => $actor->id,
|
|
'version_no' => $business->version_no, 'action' => $action,
|
|
'note' => Crypt::encryptString(json_encode(['note' => $note, 'review_consent' => $action === 'submitted' ? $consent : null], JSON_THROW_ON_ERROR))]);
|
|
app(ExistingBusinessDrafts::class)->snapshot($business, $actor, $action, $note);
|
|
|
|
return $business;
|
|
});
|
|
}
|
|
}
|