commit21
This commit is contained in:
@@ -21,6 +21,46 @@ use Illuminate\Validation\ValidationException;
|
||||
|
||||
class SupplySuggestions
|
||||
{
|
||||
private function independentReviewer(User $actor, SupplyRecord $record): bool
|
||||
{
|
||||
return ! in_array($actor->id, $record->snapshot['contributors'], true);
|
||||
}
|
||||
|
||||
/** Participation only: approval/conversion still revalidate the frozen sources. */
|
||||
public function canAct(User $actor, SupplyRecord $record, string $action): bool
|
||||
{
|
||||
$permission = match ($action) {
|
||||
'approve', 'return', 'close' => 'supply_suggest_review',
|
||||
'convert' => 'supply_suggest_convert',
|
||||
'cancel' => 'supply_suggest_prepare',
|
||||
default => null,
|
||||
};
|
||||
if ($record->kind !== 'suggestion' || $actor->tenant_id !== $record->tenant_id || $permission === null
|
||||
|| ! app(SupplyPlanning::class)->allows($actor, $permission)) {
|
||||
return false;
|
||||
}
|
||||
$latest = app(SupplyPlanning::class)->latest('suggestion')->where('record_key', $record->record_key)->first();
|
||||
if ($latest?->id !== $record->id || (in_array($action, ['approve', 'return', 'close'], true) && ! $this->independentReviewer($actor, $record))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return match ($action) {
|
||||
'approve', 'cancel' => in_array($record->state, ['draft', 'returned'], true),
|
||||
'return' => in_array($record->state, ['draft', 'approved'], true),
|
||||
'convert' => $record->state === 'approved' && ($record->snapshot['reviewed_by'] ?? null) !== $actor->id && app(OrganizationAccess::class)->canRequest($actor),
|
||||
'close' => $record->state === 'converted' && $this->completionReady($record),
|
||||
};
|
||||
}
|
||||
|
||||
private function completionReady(SupplyRecord $record): bool
|
||||
{
|
||||
$request = Requisition::query()->whereKey($record->data['requisition_id'])->firstOrFail();
|
||||
$orders = PurchaseOrder::query()->where('requisition_id', $request->id)->get();
|
||||
$complete = $orders->isNotEmpty() && $orders->every(fn ($order) => app(ReceiptWorkflow::class)->progress($order)['state'] === 'complete');
|
||||
|
||||
return $request->status === 'rejected' || $complete;
|
||||
}
|
||||
|
||||
/** @param array<string,mixed> $input */
|
||||
public function save(User $actor, array $input): SupplyRecord
|
||||
{
|
||||
@@ -90,7 +130,7 @@ class SupplySuggestions
|
||||
$snapshot = $old->snapshot;
|
||||
$state = $old->state;
|
||||
if (in_array($v['action'], ['approve', 'return', 'close'], true)) {
|
||||
$this->require(! in_array($actor->id, $snapshot['contributors'], true), 'action', 'A conferência exige independência de todos os preparadores.');
|
||||
$this->require($this->independentReviewer($actor, $old), 'action', 'A conferência exige independência de todos os preparadores.');
|
||||
}
|
||||
if ($v['action'] === 'approve') {
|
||||
$this->require(in_array($state, ['draft', 'returned'], true), 'action', 'A sugestão não está disponível para decisão.');
|
||||
@@ -128,10 +168,7 @@ class SupplySuggestions
|
||||
$state = 'converted';
|
||||
} elseif ($v['action'] === 'close') {
|
||||
$this->require($state === 'converted', 'action', 'Apenas uma sugestão convertida pode encerrar acompanhamento.');
|
||||
$request = Requisition::query()->whereKey($data['requisition_id'])->firstOrFail();
|
||||
$orders = PurchaseOrder::query()->where('requisition_id', $request->id)->get();
|
||||
$complete = $orders->isNotEmpty() && $orders->every(fn ($order) => app(ReceiptWorkflow::class)->progress($order)['state'] === 'complete');
|
||||
$this->require($request->status === 'rejected' || $complete, 'action', 'A necessidade continua em acompanhamento. Aguarde rejeição da requisição ou recepção completa da ordem.');
|
||||
$this->require($this->completionReady($old), 'action', 'A necessidade continua em acompanhamento. Aguarde rejeição da requisição ou recepção completa da ordem.');
|
||||
$state = 'closed';
|
||||
}
|
||||
if ($v['action'] === 'approve') {
|
||||
|
||||
Reference in New Issue
Block a user