New-Thanasoft/thanasoft-back/app/Http/Controllers/Api/FileAttachmentController.php
2025-12-01 17:02:01 +03:00

439 lines
14 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Resources\FileAttachment\FileAttachmentResource;
use App\Models\File;
use App\Models\FileAttachment;
use App\Models\Intervention;
use App\Models\Client;
use App\Models\Deceased;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;
class FileAttachmentController extends Controller
{
/**
* Attach a file to a model (Intervention, Client, Deceased, etc.)
*/
public function attach(Request $request): JsonResponse
{
try {
$request->validate([
'file_id' => 'required|exists:files,id',
'attachable_type' => 'required|string|in:App\Models\Intervention,App\Models\Client,App\Models\Deceased',
'attachable_id' => 'required|integer',
'label' => 'nullable|string|max:255',
'sort_order' => 'nullable|integer|min:0',
]);
// Verify the attachable model exists
$attachableModel = $this->getAttachableModel($request->attachable_type, $request->attachable_id);
if (!$attachableModel) {
return response()->json([
'message' => 'Le modèle cible n\'existe pas.',
], 404);
}
// Check if file is already attached to this model
$existingAttachment = FileAttachment::where('file_id', $request->file_id)
->where('attachable_type', $request->attachable_type)
->where('attachable_id', $request->attachable_id)
->first();
if ($existingAttachment) {
return response()->json([
'message' => 'Ce fichier est déjà attaché à cet élément.',
], 422);
}
DB::beginTransaction();
try {
// Create the attachment
$attachment = FileAttachment::create([
'file_id' => $request->file_id,
'attachable_type' => $request->attachable_type,
'attachable_id' => $request->attachable_id,
'label' => $request->label,
'sort_order' => $request->sort_order ?? 0,
]);
// Load relationships for response
$attachment->load('file');
DB::commit();
return response()->json([
'data' => new FileAttachmentResource($attachment),
'message' => 'Fichier attaché avec succès.',
], 201);
} catch (\Exception $e) {
DB::rollBack();
throw $e;
}
} catch (\Exception $e) {
Log::error('Error attaching file: ' . $e->getMessage(), [
'exception' => $e,
'trace' => $e->getTraceAsString(),
'request_data' => $request->all(),
]);
return response()->json([
'message' => 'Une erreur est survenue lors de l\'attachement du fichier.',
'error' => config('app.debug') ? $e->getMessage() : null,
], 500);
}
}
/**
* Detach a file from a model
*/
public function detach(Request $request, string $attachmentId): JsonResponse
{
try {
$attachment = FileAttachment::find($attachmentId);
if (!$attachment) {
return response()->json([
'message' => 'Attachement de fichier non trouvé.',
], 404);
}
DB::beginTransaction();
try {
$attachment->delete();
DB::commit();
return response()->json([
'message' => 'Fichier détaché avec succès.',
], 200);
} catch (\Exception $e) {
DB::rollBack();
throw $e;
}
} catch (\Exception $e) {
Log::error('Error detaching file: ' . $e->getMessage(), [
'exception' => $e,
'trace' => $e->getTraceAsString(),
'attachment_id' => $attachmentId,
]);
return response()->json([
'message' => 'Une erreur est survenue lors du détachement du fichier.',
'error' => config('app.debug') ? $e->getMessage() : null,
], 500);
}
}
/**
* Update file attachment metadata
*/
public function update(Request $request, string $attachmentId): JsonResponse
{
try {
$request->validate([
'label' => 'nullable|string|max:255',
'sort_order' => 'nullable|integer|min:0',
]);
$attachment = FileAttachment::find($attachmentId);
if (!$attachment) {
return response()->json([
'message' => 'Attachement de fichier non trouvé.',
], 404);
}
DB::beginTransaction();
try {
$attachment->update($request->only(['label', 'sort_order']));
$attachment->load('file');
DB::commit();
return response()->json([
'data' => new FileAttachmentResource($attachment),
'message' => 'Attachement de fichier mis à jour avec succès.',
], 200);
} catch (\Exception $e) {
DB::rollBack();
throw $e;
}
} catch (\Exception $e) {
Log::error('Error updating file attachment: ' . $e->getMessage(), [
'exception' => $e,
'trace' => $e->getTraceAsString(),
'attachment_id' => $attachmentId,
'request_data' => $request->all(),
]);
return response()->json([
'message' => 'Une erreur est survenue lors de la mise à jour de l\'attachement.',
'error' => config('app.debug') ? $e->getMessage() : null,
], 500);
}
}
/**
* Get files attached to a specific model
*/
public function getAttachedFiles(Request $request): JsonResponse
{
try {
$request->validate([
'attachable_type' => 'required|string|in:App\Models\Intervention,App\Models\Client,App\Models\Deceased',
'attachable_id' => 'required|integer',
]);
$attachments = FileAttachment::where('attachable_type', $request->attachable_type)
->where('attachable_id', $request->attachable_id)
->with('file')
->orderBy('sort_order')
->orderBy('created_at')
->get();
return response()->json([
'data' => FileAttachmentResource::collection($attachments),
'count' => $attachments->count(),
'message' => 'Fichiers attachés récupérés avec succès.',
], 200);
} catch (\Exception $e) {
Log::error('Error getting attached files: ' . $e->getMessage(), [
'exception' => $e,
'trace' => $e->getTraceAsString(),
'request_data' => $request->all(),
]);
return response()->json([
'message' => 'Une erreur est survenue lors de la récupération des fichiers attachés.',
'error' => config('app.debug') ? $e->getMessage() : null,
], 500);
}
}
/**
* Get files attached to an intervention
*/
public function getInterventionFiles(Request $request, int $interventionId): JsonResponse
{
try {
$intervention = Intervention::find($interventionId);
if (!$intervention) {
return response()->json([
'message' => 'Intervention non trouvée.',
], 404);
}
$attachments = $intervention->fileAttachments()->with('file')->get();
return response()->json([
'data' => FileAttachmentResource::collection($attachments),
'count' => $attachments->count(),
'message' => 'Fichiers de l\'intervention récupérés avec succès.',
], 200);
} catch (\Exception $e) {
Log::error('Error getting intervention files: ' . $e->getMessage(), [
'exception' => $e,
'trace' => $e->getTraceAsString(),
'intervention_id' => $interventionId,
]);
return response()->json([
'message' => 'Une erreur est survenue lors de la récupération des fichiers de l\'intervention.',
'error' => config('app.debug') ? $e->getMessage() : null,
], 500);
}
}
/**
* Get files attached to a client
*/
public function getClientFiles(Request $request, int $clientId): JsonResponse
{
try {
$client = Client::find($clientId);
if (!$client) {
return response()->json([
'message' => 'Client non trouvé.',
], 404);
}
$attachments = $client->fileAttachments()->with('file')->get();
return response()->json([
'data' => FileAttachmentResource::collection($attachments),
'count' => $attachments->count(),
'message' => 'Fichiers du client récupérés avec succès.',
], 200);
} catch (\Exception $e) {
Log::error('Error getting client files: ' . $e->getMessage(), [
'exception' => $e,
'trace' => $e->getTraceAsString(),
'client_id' => $clientId,
]);
return response()->json([
'message' => 'Une erreur est survenue lors de la récupération des fichiers du client.',
'error' => config('app.debug') ? $e->getMessage() : null,
], 500);
}
}
/**
* Get files attached to a deceased
*/
public function getDeceasedFiles(Request $request, int $deceasedId): JsonResponse
{
try {
$deceased = Deceased::find($deceasedId);
if (!$deceased) {
return response()->json([
'message' => 'Défunt non trouvé.',
], 404);
}
$attachments = $deceased->fileAttachments()->with('file')->get();
return response()->json([
'data' => FileAttachmentResource::collection($attachments),
'count' => $attachments->count(),
'message' => 'Fichiers du défunt récupérés avec succès.',
], 200);
} catch (\Exception $e) {
Log::error('Error getting deceased files: ' . $e->getMessage(), [
'exception' => $e,
'trace' => $e->getTraceAsString(),
'deceased_id' => $deceasedId,
]);
return response()->json([
'message' => 'Une erreur est survenue lors de la récupération des fichiers du défunt.',
'error' => config('app.debug') ? $e->getMessage() : null,
], 500);
}
}
/**
* Detach multiple files at once
*/
public function detachMultiple(Request $request): JsonResponse
{
try {
$request->validate([
'attachment_ids' => 'required|array|min:1',
'attachment_ids.*' => 'exists:file_attachments,id',
]);
DB::beginTransaction();
try {
$deletedCount = FileAttachment::whereIn('id', $request->attachment_ids)->delete();
DB::commit();
return response()->json([
'deleted_count' => $deletedCount,
'message' => $deletedCount . ' fichier(s) détaché(s) avec succès.',
], 200);
} catch (\Exception $e) {
DB::rollBack();
throw $e;
}
} catch (\Exception $e) {
Log::error('Error detaching multiple files: ' . $e->getMessage(), [
'exception' => $e,
'trace' => $e->getTraceAsString(),
'attachment_ids' => $request->attachment_ids ?? [],
]);
return response()->json([
'message' => 'Une erreur est survenue lors du détachement des fichiers.',
'error' => config('app.debug') ? $e->getMessage() : null,
], 500);
}
}
/**
* Reorder file attachments
*/
public function reorder(Request $request): JsonResponse
{
try {
$request->validate([
'attachments' => 'required|array|min:1',
'attachments.*.id' => 'required|exists:file_attachments,id',
'attachments.*.sort_order' => 'required|integer|min:0',
]);
DB::beginTransaction();
try {
foreach ($request->attachments as $attachmentData) {
FileAttachment::where('id', $attachmentData['id'])
->update(['sort_order' => $attachmentData['sort_order']]);
}
DB::commit();
return response()->json([
'message' => 'Ordre des fichiers mis à jour avec succès.',
], 200);
} catch (\Exception $e) {
DB::rollBack();
throw $e;
}
} catch (\Exception $e) {
Log::error('Error reordering file attachments: ' . $e->getMessage(), [
'exception' => $e,
'trace' => $e->getTraceAsString(),
'attachments' => $request->attachments ?? [],
]);
return response()->json([
'message' => 'Une erreur est survenue lors de la réorganisation des fichiers.',
'error' => config('app.debug') ? $e->getMessage() : null,
], 500);
}
}
/**
* Get the attachable model instance
*/
private function getAttachableModel(string $type, int $id): ?Model
{
return match ($type) {
Intervention::class => Intervention::find($id),
Client::class => Client::find($id),
Deceased::class => Deceased::find($id),
default => null,
};
}
}