Files
compras/app/Http/Controllers/ExternalPaymentController.php
2026-11-02 20:27:11 +02:00

72 lines
4.7 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Enums\PurchasingRole;
use App\Models\ExternalPayment;
use App\Models\Invoice;
use App\Models\PurchaseOrder;
use App\Models\Supplier;
use App\Models\SupplierBankDetail;
use App\Models\User;
use App\Services\ExternalPaymentWorkflow;
use App\Services\OrganizationAccess;
use App\Services\RequisitionWorkflow;
use App\Services\SupplierBankWorkflow;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Inertia\Inertia;
use Symfony\Component\HttpFoundation\Response;
class ExternalPaymentController extends Controller
{
public function index(Request $request, ExternalPaymentWorkflow $workflow): Response
{
$actor = $request->user('web');
abort_unless($actor instanceof User, 403);
abort_unless($actor->hasFunctions([PurchasingRole::Admin, PurchasingRole::Finance]), 403);
$filter = $request->validate(['payment_id' => ['nullable', 'integer', 'min:1', Rule::exists('external_payments', 'id')->where('tenant_id', $actor->tenant_id)], 'invoice_id' => ['nullable', 'integer', 'min:1', Rule::exists('invoices', 'id')->where('tenant_id', $actor->tenant_id)]]);
$focus = isset($filter['payment_id']) ? (int) $filter['payment_id'] : null;
$focusInvoice = isset($filter['invoice_id']) ? (int) $filter['invoice_id'] : null;
$canManage = $actor->hasFunctions([PurchasingRole::Finance]) && ! app(OrganizationAccess::class)->maintenanceOnly($actor);
$visibleInvoices = Invoice::query()->whereIn('purchase_order_id', PurchaseOrder::query()->visibleTo($actor)->select('id'));
$payments = ExternalPayment::query()->whereIn('invoice_id', (clone $visibleInvoices)->select('id'))->when($focus !== null, fn ($q) => $q->whereKey($focus))->when($focusInvoice !== null, fn ($q) => $q->where('invoice_id', $focusInvoice))->latest('id')->paginate(15)->withQueryString()
->through(fn (ExternalPayment $payment) => [...$payment->toArray(), 'canReview' => $workflow->reviewerEligible($actor, $payment), 'external_reference' => $canManage ? $payment->external_reference : null, 'evidence_reference' => $canManage ? $payment->evidence_reference : null]);
if ($canManage && $payments->count() > 0) {
app(RequisitionWorkflow::class)->audit($actor, 'payment.viewed', null, null, ['payment_ids' => $payments->pluck('id')->all()]);
}
$invoices = $visibleInvoices->where('status', 'validated')->when($focus !== null, fn ($q) => $q->whereIn('id', $payments->pluck('invoice_id')))->when($focusInvoice !== null, fn ($q) => $q->whereKey($focusInvoice))->latest('id')->get()->map(function (Invoice $invoice) use ($workflow) {
$supplier = Supplier::query()->findOrFail($invoice->supplier_id);
$bank = SupplierBankDetail::query()->where('supplier_id', $supplier->id)->latest('revision')->first();
return ['id' => $invoice->id, 'number' => $invoice->number, 'supplier_id' => $supplier->id, 'supplier_name' => $supplier->name, 'total_minor' => $invoice->total_minor, 'outstanding_minor' => $workflow->outstanding($invoice), 'bank_id' => $bank->id ?? 0, 'bank_revision' => $bank->revision ?? 0, 'bank_state' => app(SupplierBankWorkflow::class)->state($supplier)];
});
Inertia::encryptHistory();
$response = Inertia::render('payments/index', ['focusPaymentId' => $focus, 'focusInvoiceId' => $focusInvoice, 'invoices' => $invoices, 'payments' => $payments, 'canManage' => $canManage])->toResponse($request);
$response->headers->set('Cache-Control', 'private, no-store, max-age=0');
return $response;
}
public function store(Request $request, Invoice $invoice, ExternalPaymentWorkflow $workflow): RedirectResponse
{
$actor = $request->user('web');
abort_unless($actor instanceof User && $actor->hasFunctions([PurchasingRole::Finance]), 403);
$data = $request->validate(['supplier_bank_detail_id' => 'required|integer|min:1', 'amount' => ['required', 'regex:/^\d{1,12}(\.\d{1,2})?$/'], 'paid_on' => 'required|date_format:Y-m-d', 'external_reference' => 'required|string|max:150', 'evidence_reference' => 'required|string|max:1000']);
$workflow->register($actor, $invoice, $data);
return to_route('payments.index');
}
public function review(Request $request, ExternalPayment $payment, ExternalPaymentWorkflow $workflow): RedirectResponse
{
$actor = $request->user('web');
abort_unless($actor instanceof User, 403);
$data = $request->validate(['decision' => 'required|in:confirmed,rejected', 'reason' => 'required|string|max:2000', 'independently_verified' => 'accepted']);
$workflow->review($actor, $payment, $data['decision'], $data['reason']);
return back();
}
}