Files
compras/app/Http/Controllers/PurchaseController.php
T

108 lines
5.3 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Enums\PurchasingRole;
use App\Models\AuditLog;
use App\Models\AwardCancellation;
use App\Models\PurchaseAward;
use App\Models\PurchaseOrder;
use App\Models\Requisition;
use App\Services\ProposalComparison;
use App\Services\PurchaseWorkflow;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Inertia\Inertia;
use Inertia\Response;
class PurchaseController extends Controller
{
private function access(Request $request): void
{
abort_unless(in_array($request->user()->purchasing_role, [PurchasingRole::Admin, PurchasingRole::Procurement, PurchasingRole::Finance, PurchasingRole::DepartmentHead]), 403);
}
public function award(Request $request, Requisition $requisition, ProposalComparison $comparison, PurchaseWorkflow $workflow): Response
{
$this->access($request);
Requisition::query()->visibleTo($request->user())->findOrFail($requisition->id);
$award = PurchaseAward::query()->where('requisition_id', $requisition->id)->with('approvals')->first();
$frozen = $award && AwardCancellation::query()->where('purchase_award_id', $award->id)->where('status', 'pending')->exists();
return Inertia::render('purchases/award', [
'requisition' => $requisition, 'comparison' => $comparison->inspect($requisition), 'award' => $award,
'canSelect' => $request->user()->purchasing_role === PurchasingRole::Procurement && $award === null && $request->user()->id !== $requisition->requester_id,
'canDecide' => ! $frozen && $award !== null && $workflow->canDecide($request->user(), $award, $requisition),
'canIssue' => ! $frozen && $award?->status === 'approved' && $request->user()->purchasing_role === PurchasingRole::Procurement,
'order' => PurchaseOrder::query()->where('requisition_id', $requisition->id)->first(['id', 'number']),
]);
}
public function select(Request $request, Requisition $requisition, PurchaseWorkflow $workflow): RedirectResponse
{
$this->access($request);
$data = $request->validate([
'quotation_id' => 'required|integer', 'justification' => 'required|string|min:10|max:5000',
'delivery_date' => 'required|date_format:Y-m-d|after_or_equal:today', 'delivery_location' => 'required|string|min:3|max:500',
'status' => 'prohibited', 'total_minor' => 'prohibited', 'subtotal_minor' => 'prohibited', 'tax_minor' => 'prohibited',
'approval_snapshot' => 'prohibited', 'decision_matrix' => 'prohibited', 'created_by' => 'prohibited', 'tenant_id' => 'prohibited',
'override' => 'prohibited', 'exception' => 'prohibited',
]);
$workflow->select($request->user(), $requisition, $data);
return to_route('purchases.award', $requisition);
}
public function decide(Request $request, PurchaseAward $award, PurchaseWorkflow $workflow): RedirectResponse
{
$this->access($request);
$data = $request->validate(['decision' => ['required', Rule::in(['approved', 'rejected'])], 'comment' => 'nullable|required_if:decision,rejected|string|max:2000']);
$workflow->decide($request->user(), $award, $data['decision'], $data['comment'] ?? null);
return to_route('purchases.award', $award->requisition_id);
}
public function issue(Request $request, PurchaseAward $award, PurchaseWorkflow $workflow): RedirectResponse
{
$this->access($request);
$request->validate([
'status' => 'prohibited', 'snapshot' => 'prohibited', 'total_minor' => 'prohibited', 'subtotal_minor' => 'prohibited', 'tax_minor' => 'prohibited',
'issued_by' => 'prohibited', 'tenant_id' => 'prohibited', 'quotation_id' => 'prohibited', 'override' => 'prohibited', 'exception' => 'prohibited',
]);
$order = $workflow->issue($request->user(), $award);
return to_route('orders.show', $order);
}
public function index(Request $request): Response
{
$this->access($request);
return Inertia::render('purchases/index', [
'orders' => PurchaseOrder::query()->visibleTo($request->user())->latest('id')->paginate(15),
'awards' => PurchaseAward::query()->whereIn('requisition_id', Requisition::query()->visibleTo($request->user())->select('id'))->latest()->paginate(15, ['*'], 'awards_page'),
]);
}
public function show(Request $request, PurchaseOrder $order): Response
{
$this->access($request);
PurchaseOrder::query()->visibleTo($request->user())->findOrFail($order->id);
return Inertia::render('purchases/show', [
'order' => $order->load('items'),
'history' => AuditLog::query()->where('requisition_id', $order->requisition_id)->whereIn('action', ['award.created', 'award.approved', 'award.rejected', 'purchase_order.issued'])->orderBy('id')->get(['id', 'user_id', 'action', 'created_at']),
]);
}
public function print(Request $request, PurchaseOrder $order): View
{
$this->access($request);
PurchaseOrder::query()->visibleTo($request->user())->findOrFail($order->id);
return view('purchases.print', ['order' => $order->load('items'), 'snapshot' => $order->snapshot]);
}
}