This commit is contained in:
2026-11-03 11:51:44 +02:00
parent badaada043
commit e753f7a0a4
309 changed files with 14537 additions and 529 deletions
+13 -2
View File
@@ -20,6 +20,17 @@ use Illuminate\Validation\ValidationException;
/** Physical supplier returns and write-offs; financial corrections remain distinct. */
class InventoryDispositions
{
public function executionSourceCurrent(SupplyRecord $record): bool
{
return $record->kind === 'stock_event' && app(InventoryReviewParticipation::class)->executionSourceCurrent($record, fn (array $data) => $this->basis($data));
}
/** Participation only: source, stock and physical evidence are revalidated by save. */
public function canAct(User $actor, SupplyRecord $record, string $action): bool
{
return app(InventoryReviewParticipation::class)->canAct($actor, $record, 'stock_event', $action, fn (string $capability) => $this->allows($actor, $capability));
}
public function allows(User $actor, string $capability): bool
{
return ! app(OrganizationAccess::class)->maintenanceOnly($actor) && $actor->hasFunctions(match ($capability) {
@@ -163,7 +174,7 @@ class InventoryDispositions
$data = $old->data;
$snapshot = $old->snapshot;
if ($v['action'] === 'execute') {
$this->check($old->state === 'approved' && $actor->id !== $snapshot['reviewed_by'], 'action', 'A saída exige aprovação prévia e operador diferente de quem aprovou.');
$this->check($old->state === 'approved' && app(InventoryReviewParticipation::class)->independentExecutor($actor, $old), 'action', 'A saída exige aprovação prévia e operador diferente de quem aprovou.');
$event = Validator::make($v['data'], ['event_on' => 'required|date_format:Y-m-d|before_or_equal:today', 'evidence' => 'required|string|min:10|max:3000'])->validate();
$this->check($event['event_on'] >= $old->created_at->toDateString(), 'data.event_on', 'A saída não pode anteceder a aprovação.');
$current = $this->basis($data);
@@ -174,7 +185,7 @@ class InventoryDispositions
$snapshot['execution_observed'] = $current['observed'];
$state = 'executed';
} else {
$this->check(! in_array($actor->id, $snapshot['contributors'], true), 'action', 'A decisão exige pessoa independente de todos os preparadores.');
$this->check(app(InventoryReviewParticipation::class)->independentReviewer($actor, $old), 'action', 'A decisão exige pessoa independente de todos os preparadores.');
$this->check($v['action'] === 'return' ? in_array($old->state, ['draft', 'returned', 'approved'], true) : in_array($old->state, ['draft', 'returned'], true), 'action', 'Estado incompatível com a decisão.');
$state = $v['action'] === 'approve' ? 'approved' : 'returned';
if ($state === 'approved') {