start notification/mailing process

This commit is contained in:
Charles 2025-10-29 10:34:05 +01:00
parent 75e5921be1
commit 346a05e51d
3 changed files with 193 additions and 2 deletions

190
NOTIFICATION.MD Normal file
View File

@ -0,0 +1,190 @@
# Système de notification de l'application
## Vue d'ensemble
Le système de notification de l'application permet d'informer les utilisateurs de diverse action.
## Architecture
### Composants principaux
1. **Service de Notification** : Gère la création, l'envoi et le suivi des notifications.
2. **Interface Utilisateur** : Affiche les notifications aux utilisateurs via des pops-ups, des bannières ou des emails.
3. **Template Email** : Modèles prédéfinis pour les notifications par email.
4. **Type D'action** : Enum d'action qui déclenche des notifications (ex: nouvel utilisateur, utilisateur actif, ...).
### Service de Notification
Le service de notification est responsable de la gestion des notifications. Il inclut les fonctionnalités suivantes :
- Création de notifications basées sur des événements spécifiques.
- Envoi de notifications via différents canaux (email, in-app).
- Suivi de l'état des notifications (envoyé, lu, etc.).
### Interface Utilisateur
L'interface utilisateur affiche les notifications de manière conviviale. Les notifications peuvent apparaître sous forme
de pops-ups, de bannières ou d'emails. (Possibilité d'intéragir avec les notifications)
### Template Email
Les templates email sont utilisés pour formater les notifications envoyées par email. Chaque type de notification
a son propre template pour assurer une communication claire et cohérente.
### Type d'action
```
enum ActionType: String {
case NewUser = "NEW_USER";
case ActiveUser = "ACTIVE_USER";
case PasswordReset = "PASSWORD_RESET";
case SubscriptionExpired = "SUBSCRIPTION_EXPIRED";
case OrganizationInvited = "ORGANIZATION_INVITED";
case OrganizationInactive = "ORGANIZATION_INACTIVE";
case OrganizationDeleted = "ORGANIZATION_DELETED";
case OrginizationUserInvited = "ORGANIZATION_USER_INVITED";
case UserDeleted = "USER_DELETED";
}
```
## Flux de travail
1. Ladministrateur crée un utilisateur depuis linterface (formulaire “Créer un utilisateur”).
2. Le contrôleur valide la requête et appelle le cas dusage UserAdministrationService->handle(ActionType::NewUser, $admin, $payload).
3. Le service crée lutilisateur en base avec le statut INVITED, associe lorganisation de ladmin, et génère un lien signé/jeton de setup de mot de passe (TTL).
4. Le service publie un événement de domaine UserInvitedEvent { userId, adminId, organizationId } sur Messenger (transport async).
5. Handler async A — SendUserInvitationEmailHandler:
6. Construit lemail via Symfony Mailer + Twig (emails/user_invitation.html.twig) avec le lien de définition de mot de passe.
7. Envoie le mail à lutilisateur invité.
8. Handler async B — NotifyAdminInvitationSentHandler:
9. Crée une notification interne (Notifier, canal “inapp”).
10. Pousse un événement temps réel via Mercure sur le topic admin/{adminId}/events avec le type INVITATION_EMAIL_SENT.
11. LUI admin affiche un toast/bannière confirmant “Email dinvitation envoyé”.
12. Lutilisateur ouvre lemail et clique le lien de définition de mot de passe.
13. Le PasswordSetupController vérifie la signature/le jeton et la validité (TTL), affiche le formulaire, puis enregistre le nouveau mot de passe.
14. À la réussite, lutilisateur passe au statut ACTIVE et laction publie UserActivatedEvent { userId, adminId, organizationId } sur Messenger (async).
15. Handler async C — NotifyAdminUserActivatedHandler:
16. Crée une notification interne (Notifier, canal “inapp”) “Compte activé”.
17. Pousse un événement Mercure sur admin/{adminId}/events avec le type USER_ACTIVATED.
18. LUI admin met à jour la liste des membres (badge “Actif”) et affiche un toast confirmant lactivation.
19. Journalisation/Audit:
20. Chaque handler écrit une trace (succès/échec) en base ou dans un EmailLog/NotificationLog.
21. En cas déchec denvoi, Messenger applique la stratégie de retry puis bascule en file failed si nécessaire (tableau de bord de supervision).
22. Cas “utilisateur existant ajouté à une autre organisation”:
23. Si lemail existe déjà, on rattache lutilisateur à la nouvelle organisation et on publie OrganizationUserInvitedEvent.
24. Handler dédié envoie un email dinformation (“Vous avez été ajouté à une nouvelle organisation”) et notifie ladmin via Notifier + Mercure.
25. Cas dactions dérivées par enum:
26. ActionType::NewUser → déclenche UserInvitedEvent (steps 36).
27. ActionType::ActiveUser (si activé par un flux admin) → déclenche directement UserActivatedEvent (steps 910).
28. ActionType::OrganizationUserInvited → flux similaire au point 12 pour la multiorganisation.
29. Autres actions (PasswordReset, UserDeleted, etc.) suivent le même patron: contrôleur → service (match enum) → événement Messenger → handlers (Mailer/Notifier/Mercure) → UI temps réel.
## Stack technologique
- Symfony Messenger: asynchrone, retries, découplage des I/O lents.
- Symfony Mailer + Twig: emails dinvitation et dinformation.
- Symfony Notifier (canal inapp) + Mercure: notifications persistées + push temps réel vers lUI admin.
- Enum ActionType: routage clair dans lapplication, évite la logique stringbased.
```mermaid
flowchart LR
%% Couche 1: Action initiale
A[User action event - Admin cree un utilisateur] --> B[HTTP controller API - Symfony]
B --> C[Domain service - UserAdministrationService]
C -->|Inspecte enum ActionType::NewUser| C1[Create user - status INVITED - liaison organisation - genere lien jeton mot de passe TTL]
C1 --> D[Dispatch UserInvitedEvent - userId adminId organizationId - vers Symfony Messenger bus]
%% Couche 2: Messaging / Infra
D --> E[Transport async - AMQP / Redis / Doctrine]
E --> RQ[Retry queue]
E --> FQ[Failed queue - dead letter]
E --> W[Workers Messenger]
F[Supervisor / systemd] --> W
%% Monolog transversal (logs a chaque etape)
A --> LOG_GLOBAL[Monolog - log event initial]
B --> LOG_GLOBAL
C --> LOG_GLOBAL
C1 --> LOG_GLOBAL
D --> LOG_GLOBAL
E --> LOG_GLOBAL
RQ --> LOG_GLOBAL
FQ --> LOG_GLOBAL
W --> LOG_GLOBAL
%% Handlers pour l'invitation
W --> H1[Handler A - Symfony Mailer + Twig]
H1 --> H1o[Email d'invitation avec lien setup mot de passe]
H1 --> LOG_GLOBAL
W --> H2[Handler B - Symfony Notifier in-app]
H2 --> UI1[Notification UI admin - Email d'invitation envoye]
H2 --> LOG_GLOBAL
W -. optionnel .-> WH1[Webhook HTTP sortant - invitation envoyee]
WH1 --> LOG_GLOBAL
W -. optionnel .-> SMS1[SMS gateway - SMS invitation]
SMS1 --> LOG_GLOBAL
W -. optionnel .-> PUSH1[Mobile push service - notification mobile]
PUSH1 --> LOG_GLOBAL
RQ --> METRICS[Metrics et dashboard]
FQ --> METRICS
LOG_GLOBAL --> METRICS
%% Flux activation utilisateur
subgraph Activation du compte
UA[User action event - Invite clique le lien] --> PS[HTTP controller API - PasswordSetupController]
PS -->|Verifie signature et TTL| PSOK[Set password - user status ACTIVE]
PS --> LOG_GLOBAL
PSOK --> LOG_GLOBAL
PSOK --> D2[Dispatch UserActivatedEvent - userId adminId organizationId - vers Messenger bus]
D2 --> E2[Transport async]
E2 --> RQ2[Retry queue]
E2 --> FQ2[Failed queue]
E2 --> W2[Workers Messenger]
F --> W2
D2 --> LOG_GLOBAL
E2 --> LOG_GLOBAL
RQ2 --> LOG_GLOBAL
FQ2 --> LOG_GLOBAL
W2 --> LOG_GLOBAL
W2 --> H3[Handler C - Notifier in-app]
H3 --> UI2[Notification UI admin - Compte active]
H3 --> LOG_GLOBAL
W2 -. optionnel .-> WH2[Webhook HTTP sortant - user active]
WH2 --> LOG_GLOBAL
W2 -. optionnel .-> MAIL2[Mailer ou SMS ou Push - confirmation utilisateur]
MAIL2 --> LOG_GLOBAL
RQ2 --> METRICS
FQ2 --> METRICS
end
%% Cas particulier : utilisateur existant ajoute a une nouvelle organisation
C -->|Email deja existant| SP1[Rattache a nouvelle organisation]
SP1 --> LOG_GLOBAL
SP1 --> D3[Dispatch OrganizationUserInvitedEvent]
D3 --> E3[Transport async] --> W3[Workers]
F --> W3
D3 --> LOG_GLOBAL
E3 --> LOG_GLOBAL
W3 --> LOG_GLOBAL
W3 --> M3[Mailer - ajoute a une nouvelle organisation]
M3 --> LOG_GLOBAL
W3 --> N3[Notifier in-app - toast admin Utilisateur ajoute]
N3 --> LOG_GLOBAL
W3 -. optionnel .-> WH3[Webhook ou SMS ou Mobile]
WH3 --> LOG_GLOBAL
M3 --> METRICS
N3 --> METRICS
WH3 --> METRICS
%% Styles
classDef infra fill:#e8f0fe,stroke:#5b8def,stroke-width:1px;
classDef handler fill:#dcf7e9,stroke:#2ea66a,stroke-width:1px;
classDef ui fill:#f0d9ff,stroke:#9c27b0,stroke-width:1px;
classDef audit fill:#eeeeee,stroke:#9e9e9e,stroke-width:1px;
class E,E2,E3,RQ,FQ,RQ2,FQ2,METRICS infra;
class W,W2,W3,H1,H2,H3,M3,N3 handler;
class H1o,UI1,UI2 ui;
class LOG_GLOBAL audit;
```

View File

@ -32,8 +32,9 @@
"symfony/intl": "7.2.*",
"symfony/mailer": "7.2.*",
"symfony/mercure-bundle": "^0.3.9",
"symfony/messenger": "7.2.*",
"symfony/mime": "7.2.*",
"symfony/monolog-bundle": "^3.0",
"symfony/monolog-bundle": "^3.10",
"symfony/notifier": "7.2.*",
"symfony/process": "7.2.*",
"symfony/property-access": "7.2.*",

2
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "2e4c0342c6040486970857205e1e8d75",
"content-hash": "6694f361e2e9943b29abdd66ef40904a",
"packages": [
{
"name": "aws/aws-crt-php",