'TVA', FolderType::VatMonthly => 'TVA mensuelle', FolderType::VatQuarterly => 'TVA trimestrielle', FolderType::CorporateTax => 'IS', FolderType::IncomeTax => 'IR', FolderType::CNSS => 'CNSS', FolderType::AnnualBalance => 'Bilan', FolderType::Other => 'Autre', ]; } protected function folderStatusLabels(): array { return [ FolderStatus::Draft => 'Brouillon', FolderStatus::WaitingDocuments => 'En attente documents', FolderStatus::DocumentsReceived => 'Documents reçus', FolderStatus::Processing => 'En cours de traitement', FolderStatus::AdditionalDocumentsRequested => 'Pièces complémentaires demandées', FolderStatus::WaitingClientValidation => 'En attente validation client', FolderStatus::Validated => 'Validé', FolderStatus::Closed => 'Clôturé', FolderStatus::Cancelled => 'Annulé', ]; } protected function folderPriorityLabels(): array { return [ FolderPriority::Low => 'Basse', FolderPriority::Medium => 'Normale', FolderPriority::High => 'Haute', ]; } protected function currentWorkspace(Request $request): Workspace { $workspaceId = $request->session()->get('current_workspace_id'); return Workspace::query()->findOrFail($workspaceId); } /** * Display a listing of the folders. */ public function index(Request $request): Response { $workspace = $this->currentWorkspace($request); $perPage = min(max((int) $request->input('per_page', 10), 10), 100); $folders = $workspace->folders() ->with(['client', 'assignee']) ->latest() ->paginate($perPage) ->through(fn (Folder $folder) => [ 'id' => $folder->id, 'title' => $folder->title, 'type' => $folder->type->value, 'client_name' => $folder->client->company_name, 'status' => $folder->status->value, 'due_date' => $folder->due_date?->format('Y-m-d'), 'showUrl' => route('folders.show', $folder), 'editUrl' => route('folders.edit', $folder), 'destroyUrl' => route('folders.destroy', $folder), ]); return Inertia::render('folders/Index', [ 'folders' => $folders, 'createUrl' => route('folders.create'), 'workspaceName' => $workspace->name, ]); } /** * Show the form for creating a new folder. */ public function create(Request $request): Response { $workspace = $this->currentWorkspace($request); $initialClientId = $request->integer('client_id', 0) ?: null; return Inertia::render('folders/Create', [ 'indexUrl' => route('folders.index'), 'storeUrl' => route('folders.store'), 'initialClientId' => $initialClientId, 'folderTypeLabels' => $this->folderTypeLabels(), 'folderStatusLabels' => $this->folderStatusLabels(), 'folderPriorityLabels' => $this->folderPriorityLabels(), 'clients' => $workspace->clients()->orderBy('company_name')->get(['id', 'company_name'])->map(fn (Client $c) => [ 'id' => $c->id, 'company_name' => $c->company_name, ])->values()->all(), 'workspaceUsers' => $workspace->users() ->orderBy('users.name') ->select('users.id', 'users.name', 'users.email') ->get() ->map(fn ($u) => [ 'id' => $u->id, 'name' => $u->name, 'email' => $u->email, ])->values()->all(), ]); } /** * Store a newly created folder in storage. */ public function store(StoreFolderRequest $request): RedirectResponse { $workspace = $this->currentWorkspace($request); $data = $request->validated(); $data['workspace_id'] = $workspace->id; $data['created_by'] = $request->user()?->id; $data['status'] = $data['status'] ?? FolderStatus::Draft->value; Folder::query()->create($data); return to_route('folders.index'); } /** * Display the specified folder. */ public function show(Request $request, Folder $folder): Response { $workspace = $this->currentWorkspace($request); $this->authorizeFolder($workspace, $folder); $folder->load(['client', 'creator', 'assignee', 'messages' => fn ($q) => $q->with(['senderUser', 'senderClient'])->latest()]); $allMedia = $folder->getMedia('documents'); $downloadedMediaIds = MediaDownload::query() ->where('user_id', $request->user()->id) ->whereIn('media_id', $allMedia->pluck('id')) ->pluck('media_id') ->all(); $messages = $folder->messages->map(function ($m) use ($folder, $allMedia, $downloadedMediaIds) { $attachments = $allMedia ->filter(fn ($media) => $media->getCustomProperty('message_id') === $m->id) ->map(fn ($media) => [ 'id' => $media->id, 'file_name' => $media->file_name, 'mime_type' => $media->mime_type, 'size' => $media->human_readable_size, 'downloadUrl' => route('folders.media.download', ['folder' => $folder, 'mediaId' => $media->id]), 'is_downloaded' => in_array($media->id, $downloadedMediaIds), ]) ->values() ->all(); $confirmationStatus = null; if ($m->type->value === 'confirmation') { $confirmationStatus = $folder->refused_at ? 'refused' : ($folder->validated_at ? 'confirmed' : 'pending'); } return [ 'id' => $m->id, 'type' => $m->type->value, 'body' => $m->body, 'sent_by_type' => $m->sent_by_type->value, 'sender_name' => $m->sender_name, 'created_at' => $m->created_at->format('Y-m-d H:i'), 'attachments' => $attachments, 'confirmation_status' => $confirmationStatus, ]; })->values()->all(); $documents = $allMedia->map(fn ($m) => [ 'id' => $m->id, 'name' => $m->name, 'file_name' => $m->file_name, 'size' => $m->human_readable_size, 'created_at' => $m->created_at->format('d/m/Y H:i'), 'uploaded_by' => $m->getCustomProperty('uploaded_by_type') === 'user' ? 'Comptable' : 'Client', 'downloadUrl' => route('folders.media.download', ['folder' => $folder, 'mediaId' => $m->id]), 'is_downloaded' => in_array($m->id, $downloadedMediaIds), ])->values()->all(); return Inertia::render('folders/Show', [ 'folder' => [ 'id' => $folder->id, 'title' => $folder->title, 'type' => $folder->type->value, 'client_id' => $folder->client_id, 'client_name' => $folder->client->company_name, 'period_year' => $folder->period_year, 'period_month' => $folder->period_month, 'period_quarter' => $folder->period_quarter, 'due_date' => $folder->due_date?->format('Y-m-d'), 'status' => $folder->status->value, 'priority' => $folder->priority?->value, 'assigned_to' => $folder->assigned_to, 'assignee_name' => $folder->assignee?->name, 'validated_at' => $folder->validated_at?->format('Y-m-d H:i'), 'closed_at' => $folder->closed_at?->format('Y-m-d H:i'), 'notes_internal' => $folder->notes_internal, 'notes_client' => $folder->notes_client, 'created_at' => $folder->created_at?->format('Y-m-d H:i'), ], 'messages' => $messages, 'documents' => $documents, 'messagesStoreUrl' => route('folders.messages.store', $folder), 'mediaStoreUrl' => route('folders.media.store', $folder), 'messageTypeLabels' => [ 'invite' => 'Invitation', 'situation' => 'Situation', 'file_request' => 'Demande de pièces', 'confirmation' => 'Demande de validation', 'text' => 'Message', ], 'indexUrl' => route('folders.index'), 'editUrl' => route('folders.edit', $folder), 'workspaceUsers' => $workspace->users()->orderBy('users.name') ->select('users.id', 'users.name', 'users.email') ->get()->map(fn ($u) => ['id' => $u->id, 'name' => $u->name]) ->values()->all(), 'mentionStoreUrl' => route('folders.mentions.store', $folder), 'canMention' => in_array( $workspace->users()->where('users.id', $request->user()->id)->first()?->pivot?->role?->value, ['owner', 'manager'] ), ]); } /** * Show the form for editing the specified folder. */ public function edit(Request $request, Folder $folder): Response { $workspace = $this->currentWorkspace($request); $this->authorizeFolder($workspace, $folder); return Inertia::render('folders/Edit', [ 'folder' => [ 'id' => $folder->id, 'title' => $folder->title, 'type' => $folder->type->value, 'client_id' => $folder->client_id, 'period_year' => $folder->period_year, 'period_month' => $folder->period_month, 'period_quarter' => $folder->period_quarter, 'due_date' => $folder->due_date?->format('Y-m-d'), 'status' => $folder->status->value, 'priority' => $folder->priority?->value, 'assigned_to' => $folder->assigned_to, 'notes_internal' => $folder->notes_internal, 'notes_client' => $folder->notes_client, 'created_at' => $folder->created_at?->format('Y-m-d H:i'), ], 'indexUrl' => route('folders.index'), 'updateUrl' => route('folders.update', $folder), 'folderTypeLabels' => $this->folderTypeLabels(), 'folderStatusLabels' => $this->folderStatusLabels(), 'folderPriorityLabels' => $this->folderPriorityLabels(), 'clients' => $workspace->clients()->orderBy('company_name')->get(['id', 'company_name'])->map(fn (Client $c) => [ 'id' => $c->id, 'company_name' => $c->company_name, ])->values()->all(), 'workspaceUsers' => $workspace->users() ->orderBy('users.name') ->select('users.id', 'users.name', 'users.email') ->get() ->map(fn ($u) => [ 'id' => $u->id, 'name' => $u->name, 'email' => $u->email, ])->values()->all(), ]); } /** * Update the specified folder in storage. */ public function update(UpdateFolderRequest $request, Folder $folder): RedirectResponse { $workspace = $this->currentWorkspace($request); $this->authorizeFolder($workspace, $folder); $folder->update($request->validated()); return to_route('folders.index'); } /** * Remove the specified folder from storage. */ public function destroy(Request $request, Folder $folder): RedirectResponse { $workspace = $this->currentWorkspace($request); $this->authorizeFolder($workspace, $folder); $folder->delete(); return to_route('folders.index'); } protected function authorizeFolder(Workspace $workspace, Folder $folder): void { if ($folder->workspace_id !== $workspace->id) { abort(404); } } }