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
-74
View File
@@ -1,74 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Service;
use App\Entity\ClientTicket;
use App\Entity\Notification;
use App\Repository\UserRepository;
use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface;
final readonly class NotificationService
{
public function __construct(
private EntityManagerInterface $entityManager,
private UserRepository $userRepository,
) {}
/**
* Notify all ROLE_ADMIN users that a new ticket was created.
*/
public function createForTicketCreated(ClientTicket $ticket): void
{
$admins = $this->userRepository->findByRole('ROLE_ADMIN');
$number = sprintf('CT-%03d', $ticket->getNumber());
$projectName = $ticket->getProject()?->getName() ?? '';
foreach ($admins as $admin) {
$notification = new Notification();
$notification->setUser($admin);
$notification->setType('ticket_created');
$notification->setTitle('Nouveau ticket client '.$number);
$notification->setMessage($ticket->getTitle().' — '.$projectName);
$notification->setRelatedTicket($ticket);
$notification->setCreatedAt(new DateTimeImmutable());
$this->entityManager->persist($notification);
}
$this->entityManager->flush();
}
/**
* Notify the ticket submitter that the status has changed.
*/
public function createForStatusChange(ClientTicket $ticket): void
{
$submittedBy = $ticket->getSubmittedBy();
if (null === $submittedBy) {
return;
}
$number = sprintf('CT-%03d', $ticket->getNumber());
$statusComment = $ticket->getStatusComment();
$message = 'Nouveau statut : '.$ticket->getStatus();
if (null !== $statusComment && '' !== $statusComment) {
$message .= ' — '.$statusComment;
}
$notification = new Notification();
$notification->setUser($submittedBy);
$notification->setType('ticket_status_changed');
$notification->setTitle('Ticket '.$number.' mis à jour');
$notification->setMessage($message);
$notification->setRelatedTicket($ticket);
$notification->setCreatedAt(new DateTimeImmutable());
$this->entityManager->persist($notification);
$this->entityManager->flush();
}
}