commit14
This commit is contained in:
@@ -9,26 +9,35 @@ use App\Models\AdmissionPolicy;
|
||||
use App\Models\AdmissionReview;
|
||||
use App\Models\PurchaseAward;
|
||||
use App\Models\Requisition;
|
||||
use App\Services\ConflictGuard;
|
||||
use App\Models\User;
|
||||
use App\Services\FormalAdmission;
|
||||
use App\Services\ProposalOpeningWorkflow;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Inertia\Inertia;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class FormalAdmissionController extends Controller
|
||||
{
|
||||
private function actor(Request $request): User
|
||||
{
|
||||
$actor = $request->user('web');
|
||||
abort_unless($actor instanceof User && $actor->hasFunctions([PurchasingRole::Admin, PurchasingRole::Procurement, PurchasingRole::Finance, PurchasingRole::DepartmentHead]), 403);
|
||||
|
||||
return $actor;
|
||||
}
|
||||
|
||||
private function access(Request $request, int $id): Requisition
|
||||
{
|
||||
abort_unless($request->user()->hasFunctions([PurchasingRole::Admin, PurchasingRole::Procurement, PurchasingRole::Finance, PurchasingRole::DepartmentHead]), 403);
|
||||
abort_unless($this->actor($request)->hasFunctions([PurchasingRole::Admin, PurchasingRole::Procurement, PurchasingRole::Finance, PurchasingRole::DepartmentHead]), 403);
|
||||
|
||||
return Requisition::query()->visibleTo($request->user())->findOrFail($id);
|
||||
return Requisition::query()->visibleTo($this->actor($request))->findOrFail($id);
|
||||
}
|
||||
|
||||
public function policy(Request $request): Response
|
||||
{
|
||||
abort_unless($request->user()->hasFunctions([PurchasingRole::Admin]), 403);
|
||||
abort_unless($this->actor($request)->hasFunctions([PurchasingRole::Admin]), 403);
|
||||
Inertia::encryptHistory();
|
||||
$response = Inertia::render('purchases/admission-policy', ['policies' => AdmissionPolicy::query()->latest('revision')->paginate(20)->withQueryString(), 'latest' => AdmissionPolicy::query()->latest('revision')->first()])->toResponse($request);
|
||||
$response->headers->set('Cache-Control', 'private, no-store, max-age=0');
|
||||
@@ -40,7 +49,7 @@ class FormalAdmissionController extends Controller
|
||||
{
|
||||
$data = $request->validate(['previous_id' => 'required|integer|min:0', 'enabled' => 'required|boolean', 'roles' => 'required|array|min:1|max:2', 'roles.*' => 'required|distinct|in:finance,department_head', 'required_count' => 'required|integer|min:1|max:50', 'reason' => 'required|string|min:10|max:4000', 'tenant_id' => 'prohibited', 'created_by' => 'prohibited', 'snapshot' => 'prohibited']);
|
||||
$data['enabled'] = (bool) $data['enabled'];
|
||||
$workflow->policy($request->user(), $data);
|
||||
$workflow->policy($this->actor($request), $data);
|
||||
|
||||
return to_route('admissions.policy');
|
||||
}
|
||||
@@ -51,27 +60,27 @@ class FormalAdmissionController extends Controller
|
||||
$filter = $request->validate(['version' => 'nullable|integer|min:1']);
|
||||
$adoption = $workflow->adoption($requisition);
|
||||
$selected = isset($filter['version']) ? AdmissionAdoption::query()->where('requisition_id', $requisition->id)->findOrFail((int) $filter['version']) : $adoption;
|
||||
$focusInput = $request->validate(['decision_id' => ['nullable', 'integer', 'min:1', Rule::exists('admission_decisions', 'id')->where('tenant_id', $requisition->tenant_id)->where('admission_adoption_id', $selected->id ?? 0)]]);
|
||||
$focus = isset($focusInput['decision_id']) ? (int) $focusInput['decision_id'] : null;
|
||||
$current = $selected && $selected->id === $adoption?->id;
|
||||
$closed = $requisition->status !== 'approved' || PurchaseAward::query()->where('requisition_id', $requisition->id)->exists();
|
||||
$open = ! $closed && ! app(ConflictGuard::class)->participationBlocked($request->user(), $requisition);
|
||||
$open = $workflow->canParticipate($this->actor($request), $requisition);
|
||||
$decisions = AdmissionDecision::query()->where('admission_adoption_id', $selected->id ?? 0)->latest('id')->get();
|
||||
$latestIds = $decisions->unique('quotation_id')->pluck('id');
|
||||
$proposals = collect($opening->proposals($requisition))->map(function ($quote) use ($workflow, $requisition, $decisions) {
|
||||
$basis = $workflow->basis($requisition, $quote['id']);
|
||||
|
||||
return [...$quote, 'basisHash' => $basis['hash'] ?? null, 'clear' => $basis['clear'] ?? false, 'previousId' => $decisions->firstWhere('quotation_id', $quote['id'])->id ?? 0];
|
||||
});
|
||||
$history = AdmissionDecision::query()->where('admission_adoption_id', $selected->id ?? 0)->latest('id')->paginate(15)->withQueryString();
|
||||
$history->through(function ($decision) use ($workflow, $selected, $current, $latestIds, $requisition, $open, $request) {
|
||||
$basis = $workflow->basis($requisition, $decision->quotation_id);
|
||||
$fresh = $current && $latestIds->contains($decision->id) && $basis && $basis['hash'] === $decision->basis_hash;
|
||||
$history = AdmissionDecision::query()->where('admission_adoption_id', $selected->id ?? 0)->when($focus !== null, fn ($query) => $query->whereKey($focus))->latest('id')->paginate(15)->withQueryString();
|
||||
$history->through(function ($decision) use ($workflow, $selected, $current, $requisition, $request) {
|
||||
$fresh = $current && $workflow->currentReviewBasis($requisition, $selected, $decision);
|
||||
|
||||
return [...$decision->toArray(), 'status' => $workflow->status($decision, $selected), 'current' => (bool) $fresh,
|
||||
'reviews' => AdmissionReview::query()->where('admission_decision_id', $decision->id)->orderBy('id')->get(),
|
||||
'canReview' => $open && $fresh && $workflow->status($decision, $selected) === 'pending' && $workflow->eligible($request->user(), $requisition, $selected, $decision) && ! AdmissionReview::query()->where('admission_decision_id', $decision->id)->where('reviewed_by', $request->user()->id)->exists()];
|
||||
'canReview' => $fresh && $workflow->canReview($this->actor($request), $requisition, $decision)];
|
||||
});
|
||||
Inertia::encryptHistory();
|
||||
$response = Inertia::render('purchases/admission', ['requisition' => $requisition->only(['id', 'number']), 'policy' => AdmissionPolicy::query()->latest('revision')->first(), 'adoptions' => AdmissionAdoption::query()->where('requisition_id', $requisition->id)->latest('revision')->get(), 'adoption' => $adoption, 'selected' => $selected, 'proposals' => $proposals, 'history' => $history, 'canAdopt' => $open && $request->user()->hasFunctions([PurchasingRole::Procurement]), 'canPropose' => $open && $current && $request->user()->hasFunctions([PurchasingRole::Procurement]) && $request->user()->id !== $requisition->requester_id, 'closed' => $closed])->toResponse($request);
|
||||
$response = Inertia::render('purchases/admission', ['focusDecisionId' => $focus, 'requisition' => $requisition->only(['id', 'number']), 'policy' => AdmissionPolicy::query()->latest('revision')->first(), 'adoptions' => AdmissionAdoption::query()->where('requisition_id', $requisition->id)->latest('revision')->get(), 'adoption' => $adoption, 'selected' => $selected, 'proposals' => $proposals, 'history' => $history, 'canAdopt' => $open && $this->actor($request)->hasFunctions([PurchasingRole::Procurement]), 'canPropose' => $open && $current && $this->actor($request)->hasFunctions([PurchasingRole::Procurement]) && $this->actor($request)->id !== $requisition->requester_id, 'closed' => $closed])->toResponse($request);
|
||||
$response->headers->set('Cache-Control', 'private, no-store, max-age=0');
|
||||
|
||||
return $response;
|
||||
@@ -81,7 +90,7 @@ class FormalAdmissionController extends Controller
|
||||
{
|
||||
$this->access($request, $requisition->id);
|
||||
$data = $request->validate(['policy_id' => 'required|integer', 'previous_id' => 'required|integer|min:0', 'reason' => 'required|string|min:10|max:4000', 'tenant_id' => 'prohibited', 'snapshot' => 'prohibited', 'created_by' => 'prohibited']);
|
||||
$workflow->adopt($request->user(), $requisition, (int) $data['policy_id'], (int) $data['previous_id'], $data['reason']);
|
||||
$workflow->adopt($this->actor($request), $requisition, (int) $data['policy_id'], (int) $data['previous_id'], $data['reason']);
|
||||
|
||||
return to_route('admissions.show', $requisition);
|
||||
}
|
||||
@@ -90,7 +99,7 @@ class FormalAdmissionController extends Controller
|
||||
{
|
||||
$this->access($request, $requisition->id);
|
||||
$data = $request->validate(['quotation_id' => 'required|integer', 'previous_id' => 'required|integer|min:0', 'basis_hash' => 'required|string|size:64', 'outcome' => 'required|in:admit,exclude,clarify', 'reason' => 'required|string|min:10|max:4000', 'tenant_id' => 'prohibited', 'created_by' => 'prohibited', 'snapshot' => 'prohibited', 'status' => 'prohibited']);
|
||||
$workflow->propose($request->user(), $requisition, $data);
|
||||
$workflow->propose($this->actor($request), $requisition, $data);
|
||||
|
||||
return to_route('admissions.show', $requisition);
|
||||
}
|
||||
@@ -100,7 +109,7 @@ class FormalAdmissionController extends Controller
|
||||
$adoption = AdmissionAdoption::query()->findOrFail($decision->admission_adoption_id);
|
||||
$this->access($request, $adoption->requisition_id);
|
||||
$data = $request->validate(['verdict' => 'required|in:approved,returned', 'reason' => 'required|string|min:10|max:4000', 'reviewed_by' => 'prohibited', 'snapshot' => 'prohibited', 'tenant_id' => 'prohibited']);
|
||||
$workflow->review($request->user(), $decision, $data['verdict'], $data['reason']);
|
||||
$workflow->review($this->actor($request), $decision, $data['verdict'], $data['reason']);
|
||||
|
||||
return to_route('admissions.show', $adoption->requisition_id);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user