Files
compras/app/Services/InventoryReviewParticipation.php
2026-11-03 11:51:44 +02:00

54 lines
2.2 KiB
PHP

<?php
namespace App\Services;
use App\Models\SupplyRecord;
use App\Models\User;
use Closure;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Validation\ValidationException;
/** Shared participation in physical dispositions/reversals; source and stock checks remain in their commands. */
class InventoryReviewParticipation
{
/** @param Closure(array<string,mixed>):array<string,mixed> $basis */
public function executionSourceCurrent(SupplyRecord $record, Closure $basis): bool
{
if ($record->state !== 'approved' || ! isset($record->snapshot['source'])) {
return false;
}
try {
return $basis($record->data)['source'] === $record->snapshot['source'];
} catch (ValidationException|ModelNotFoundException) {
return false;
}
}
public function independentReviewer(User $actor, SupplyRecord $record): bool
{
return ! in_array($actor->id, $record->snapshot['contributors'], true);
}
public function independentExecutor(User $actor, SupplyRecord $record): bool
{
return isset($record->snapshot['reviewed_by']) && $actor->id !== $record->snapshot['reviewed_by'];
}
/** @param Closure(string):bool $allows */
public function canAct(User $actor, SupplyRecord $record, string $kind, string $action, Closure $allows): bool
{
if (! in_array($kind, ['stock_event', 'stock_reversal'], true) || $record->kind !== $kind || $record->tenant_id !== $actor->tenant_id
|| ! in_array($action, ['approve', 'return', 'execute'], true) || ! $allows($action === 'execute' ? 'execute' : 'review')) {
return false;
}
$latest = app(SupplyPlanning::class)->latest($kind)->where('record_key', $record->record_key)->first();
if ($latest?->id !== $record->id) {
return false;
}
return $action === 'execute'
? $record->state === 'approved' && $this->independentExecutor($actor, $record)
: $this->independentReviewer($actor, $record) && in_array($record->state, $action === 'return' ? ['draft', 'returned', 'approved'] : ['draft', 'returned'], true);
}
}