feat(absences) : avancement module absences + suppression du portail client

Deux lots regroupés sur la branche feat/absence-management.

Suppression complète du portail client :
- retire ROLE_CLIENT (security.yaml) ; User::getRoles() ajoute toujours ROLE_USER
- supprime l'entité ClientTicket (+ repo, states, relations), User.client et
  User.allowedProjects, NotificationService, ProjectAllowedExtension, le bloc
  ROLE_CLIENT de MailAccessChecker
- front : pages /portal, layout portal, composants client-ticket/,
  AdminClientTicketTab, services/dto/i18n/docs associés
- fixtures : retire les users client-liot / client-acme
- migration Version20260522110000 (drop client_ticket, user_allowed_projects,
  colonnes liées ; task_document.task_id -> NOT NULL)
- tests : retire les cas obsolètes testant le blocage des clients sur le mail

Module gestion des absences (WIP) :
- entités / migrations (Version20260521160000, Version20260522090000)
- pages absences.vue / team-absences.vue, composants frontend/components/absence/
- services front, AccrueLeaveCommand, PublicHolidayController

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matthieu
2026-05-22 11:31:31 +02:00
parent de98924fd3
commit 2a0b202d32
109 changed files with 3918 additions and 3656 deletions

View File

@@ -1,28 +1,13 @@
<script setup lang="ts">
import type { Task } from '~/services/dto/task'
import { useMailStore } from '~/stores/mail'
import { useAuthStore } from '~/stores/auth'
const { t } = useI18n()
const router = useRouter()
const route = useRoute()
const auth = useAuthStore()
useHead({ title: t('mail.title') })
// ─── Contrôle d'accès ROLE_CLIENT ─────────────────────────────────────────
// Le middleware global gère auth + ROLE_CLIENT → /portal. Ici : double check
// en SPA car la session peut être hydratée après le rendu initial.
const isClientOnly = computed(() =>
auth.user?.roles?.includes('ROLE_CLIENT') === true
&& auth.user?.roles?.includes('ROLE_ADMIN') !== true,
)
if (isClientOnly.value) {
await navigateTo('/portal')
}
// ─── Store ────────────────────────────────────────────────────────────────
const store = useMailStore()
@@ -40,11 +25,6 @@ const {
// ─── Init : charge les dossiers + deep-link ───────────────────────────────
onMounted(async () => {
if (isClientOnly.value) {
router.replace('/portal')
return
}
if (folderTree.value.length === 0) {
await store.fetchFolders()
}