'TVA', DeclarationType::VatMonthly => 'TVA mensuelle', DeclarationType::VatQuarterly => 'TVA trimestrielle', DeclarationType::CorporateTax => 'IS', DeclarationType::IncomeTax => 'IR', DeclarationType::CNSS => 'CNSS', DeclarationType::AnnualBalance => 'Bilan', DeclarationType::Other => 'Autre', ]; } protected function declarationStatusLabels(): array { return DeclarationStatus::labels(); } protected function declarationPriorityLabels(): array { return [ DeclarationPriority::Low => 'Basse', DeclarationPriority::Medium => 'Normale', DeclarationPriority::High => 'Haute', ]; } protected function isWorker(): bool { return auth()->user()->currentWorkspaceUser()->role->is(WorkspaceUserRole::Worker); } /** * Display a listing of the declarations. */ public function index(Request $request): Response { $workspace = $this->currentWorkspace(); $user = auth()->user(); $workspaceUser = $user->currentWorkspaceUser(); $isWorker = $workspaceUser->role->is(WorkspaceUserRole::Worker); $perPage = min(max((int) $request->input('per_page', 10), 10), 100); $declarations = $workspace->declarations() ->forUser($user, $workspaceUser) ->with(['client', 'assignee']) ->latest() ->paginate($perPage) ->through(fn (Declaration $declaration) => [ 'id' => $declaration->id, 'title' => $declaration->title, 'type' => $declaration->type->value, 'client_name' => $declaration->client->company_name, 'status' => $declaration->status->value, 'due_date' => $declaration->due_date?->format('Y-m-d'), 'showUrl' => route('declarations.show', $declaration), 'editUrl' => route('declarations.edit', $declaration), 'destroyUrl' => route('declarations.destroy', $declaration), ]); return Inertia::render('declarations/Index', [ 'declarations' => $declarations, 'createUrl' => route('declarations.create'), 'workspaceName' => $workspace->name, 'canCreate' => ! $isWorker, 'canEdit' => ! $isWorker, 'canDelete' => ! $isWorker, ]); } /** * Show the form for creating a new declaration. */ public function create(Request $request): Response { if ($this->isWorker()) { abort(404); } $workspace = $this->currentWorkspace(); $initialClientId = $request->integer('client_id', 0) ?: null; return Inertia::render('declarations/Create', [ 'indexUrl' => route('declarations.index'), 'storeUrl' => route('declarations.store'), 'initialClientId' => $initialClientId, 'declarationTypeLabels' => $this->declarationTypeLabels(), 'declarationStatusLabels' => $this->declarationStatusLabels(), 'declarationPriorityLabels' => $this->declarationPriorityLabels(), '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 declaration in storage. */ public function store(StoreDeclarationRequest $request): RedirectResponse { if ($this->isWorker()) { abort(404); } $workspace = $this->currentWorkspace(); $data = $request->validated(); $data['workspace_id'] = $workspace->id; $data['created_by'] = $request->user()?->id; $data['status'] = $data['status'] ?? DeclarationStatus::Created; if (($data['type'] ?? '') === 'vat_monthly') { $data['period_quarter'] = null; } elseif (($data['type'] ?? '') === 'vat_quarterly') { $data['period_month'] = null; } Declaration::query()->create($data); return to_route('declarations.index'); } /** * Display the specified declaration. */ public function show(Request $request, Declaration $declaration): Response { $this->authorizeWorkspaceAccess($declaration); $workspace = $this->currentWorkspace(); $user = auth()->user(); $workspaceUser = $user->currentWorkspaceUser(); $isWorker = $workspaceUser->role->is(WorkspaceUserRole::Worker); if ($isWorker && $declaration->assigned_to !== $user->id) { abort(404); } $declaration->load(['client', 'creator', 'assignee', 'messages' => fn ($q) => $q->with(['senderUser', 'senderClient'])->latest()]); $allMedia = $declaration->getMedia('documents'); $downloadedMediaIds = MediaDownload::query() ->where('user_id', $request->user()->id) ->whereIn('media_id', $allMedia->pluck('id')) ->pluck('media_id') ->all(); $messages = $declaration->messages->map(function ($m) use ($declaration, $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('declarations.media.download', ['declaration' => $declaration, 'mediaId' => $media->id]), 'is_downloaded' => in_array($media->id, $downloadedMediaIds), ]) ->values() ->all(); $confirmationStatus = null; if ($m->type->value === 'confirmation') { $confirmationStatus = $declaration->refused_at ? 'refused' : ($declaration->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('declarations.media.download', ['declaration' => $declaration, 'mediaId' => $m->id]), 'is_downloaded' => in_array($m->id, $downloadedMediaIds), ])->values()->all(); $canMention = ! $isWorker; return Inertia::render('declarations/Show', [ 'declaration' => [ 'id' => $declaration->id, 'title' => $declaration->title, 'type' => $declaration->type->value, 'client_id' => $declaration->client_id, 'client_name' => $declaration->client->company_name, 'period_year' => $declaration->period_year, 'period_month' => $declaration->period_month, 'period_quarter' => $declaration->period_quarter, 'due_date' => $declaration->due_date?->format('Y-m-d'), 'status' => $declaration->status->value, 'priority' => $declaration->priority?->value, 'assigned_to' => $declaration->assigned_to, 'assignee_name' => $declaration->assignee?->name, 'validated_at' => $declaration->validated_at?->format('Y-m-d H:i'), 'closed_at' => $declaration->closed_at?->format('Y-m-d H:i'), 'notes_internal' => $declaration->notes_internal, 'notes_client' => $declaration->notes_client, 'created_at' => $declaration->created_at?->format('Y-m-d H:i'), ], 'messages' => $messages, 'documents' => $documents, 'messagesStoreUrl' => route('declarations.messages.store', $declaration), 'mediaStoreUrl' => route('declarations.media.store', $declaration), 'messageTypeLabels' => [ 'invite' => 'Invitation', 'situation' => 'Situation', 'file_request' => 'Demande de pièces', 'confirmation' => 'Demande de validation', 'text' => 'Message', ], 'indexUrl' => route('declarations.index'), 'editUrl' => route('declarations.edit', $declaration), '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('declarations.mentions.store', $declaration), 'canMention' => $canMention, 'canEdit' => ! $isWorker, 'canDelete' => ! $isWorker, ]); } /** * Show the form for editing the specified declaration. */ public function edit(Request $request, Declaration $declaration): Response { if ($this->isWorker()) { abort(404); } $this->authorizeWorkspaceAccess($declaration); $workspace = $this->currentWorkspace(); return Inertia::render('declarations/Edit', [ 'declaration' => [ 'id' => $declaration->id, 'title' => $declaration->title, 'type' => $declaration->type->value, 'client_id' => $declaration->client_id, 'period_year' => $declaration->period_year, 'period_month' => $declaration->period_month, 'period_quarter' => $declaration->period_quarter, 'due_date' => $declaration->due_date?->format('Y-m-d'), 'status' => $declaration->status->value, 'priority' => $declaration->priority?->value, 'assigned_to' => $declaration->assigned_to, 'notes_internal' => $declaration->notes_internal, 'notes_client' => $declaration->notes_client, 'created_at' => $declaration->created_at?->format('Y-m-d H:i'), ], 'indexUrl' => route('declarations.index'), 'updateUrl' => route('declarations.update', $declaration), 'declarationTypeLabels' => $this->declarationTypeLabels(), 'declarationStatusLabels' => $this->declarationStatusLabels(), 'declarationPriorityLabels' => $this->declarationPriorityLabels(), '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 declaration in storage. */ public function update(UpdateDeclarationRequest $request, Declaration $declaration): RedirectResponse { if ($this->isWorker()) { abort(404); } $this->authorizeWorkspaceAccess($declaration); $data = $request->validated(); if (($data['type'] ?? '') === 'vat_monthly') { $data['period_quarter'] = null; } elseif (($data['type'] ?? '') === 'vat_quarterly') { $data['period_month'] = null; } $declaration->update($data); return to_route('declarations.index'); } /** * Remove the specified declaration from storage. */ public function destroy(Request $request, Declaration $declaration): RedirectResponse { if ($this->isWorker()) { abort(404); } $this->authorizeWorkspaceAccess($declaration); $declaration->delete(); return to_route('declarations.index'); } }