Files
compras/app/Http/Controllers/SupplierDocumentController.php
T
nala 4d42f083ce
tests / ci (push) Canceled after 0s
commit
2026-10-28 12:06:05 +02:00

70 lines
3.4 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\Supplier;
use App\Models\SupplierDocument;
use App\Services\RequisitionWorkflow;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Throwable;
class SupplierDocumentController extends Controller
{
public function store(Request $request, Supplier $supplier, RequisitionWorkflow $workflow): RedirectResponse
{
Gate::authorize('update', $supplier);
$data = $request->validate([
'document_type' => ['required', Rule::in(['license', 'tax', 'conflict', 'other'])],
'file' => ['required', 'file', 'mimes:pdf,jpg,jpeg,png', 'extensions:pdf,jpg,jpeg,png', 'min:1', 'max:2048'],
]);
$file = $request->file('file');
abort_unless($file instanceof UploadedFile, 422);
$path = $file->store($supplier->tenant_id.'/'.$supplier->id, 'supplier_documents');
abort_if($path === false, 500);
try {
DB::transaction(function () use ($request, $supplier, $workflow, $data, $file, $path) {
$supplier = Supplier::query()->lockForUpdate()->findOrFail($supplier->id);
$before = $supplier->toArray();
$name = Str::substr(Str::replaceMatches('/[^\pL\pN ._()-]/u', '_', basename(str_replace('\\', '/', $file->getClientOriginalName()))), 0, 180);
$document = $supplier->documents()->create([
'tenant_id' => $supplier->tenant_id, 'uploaded_by' => $request->user()->id,
'document_type' => $data['document_type'], 'original_name' => $name,
'path' => $path, 'mime_type' => $file->getMimeType(), 'size' => $file->getSize(),
'sha256' => hash_file('sha256', $file->getPathname()),
]);
$supplier->update(['status' => 'pending', 'reviewed_by' => null, 'review_comment' => null, 'last_changed_by' => $request->user()->id, 'version' => $supplier->version + 1]);
$workflow->audit($request->user(), 'supplier.document_uploaded', null, $before, ['supplier' => $supplier->toArray(), 'document' => $document->toArray()]);
});
} catch (Throwable $exception) {
Storage::disk('supplier_documents')->delete($path);
throw $exception;
}
return back();
}
public function download(Request $request, Supplier $supplier, SupplierDocument $document, RequisitionWorkflow $workflow): StreamedResponse
{
Gate::authorize('viewDocuments', $supplier);
abort_unless($document->supplier_id === $supplier->id, 404);
$disk = Storage::disk('supplier_documents');
abort_unless($disk->exists($document->path), 404);
$workflow->audit($request->user(), 'supplier.document_downloaded', null, null, ['supplier_id' => $supplier->id, 'document_id' => $document->id, 'name' => $document->original_name]);
return $disk->download($document->path, $document->original_name, [
'Content-Type' => 'application/octet-stream',
'X-Content-Type-Options' => 'nosniff',
'Cache-Control' => 'private, no-store',
'Content-Security-Policy' => "default-src 'none'; sandbox",
]);
}
}