start notification/mailing process
This commit is contained in:
parent
75e5921be1
commit
346a05e51d
|
|
@ -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. L’administrateur crée un utilisateur depuis l’interface (formulaire “Créer un utilisateur”).
|
||||
2. Le contrôleur valide la requête et appelle le cas d’usage UserAdministrationService->handle(ActionType::NewUser, $admin, $payload).
|
||||
3. Le service crée l’utilisateur en base avec le statut INVITED, associe l’organisation de l’admin, 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 l’email via Symfony Mailer + Twig (emails/user_invitation.html.twig) avec le lien de définition de mot de passe.
|
||||
7. Envoie le mail à l’utilisateur invité.
|
||||
8. Handler async B — NotifyAdminInvitationSentHandler:
|
||||
9. Crée une notification interne (Notifier, canal “in‑app”).
|
||||
10. Pousse un événement temps réel via Mercure sur le topic admin/{adminId}/events avec le type INVITATION_EMAIL_SENT.
|
||||
11. L’UI admin affiche un toast/bannière confirmant “Email d’invitation envoyé”.
|
||||
12. L’utilisateur ouvre l’email 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, l’utilisateur passe au statut ACTIVE et l’action publie UserActivatedEvent { userId, adminId, organizationId } sur Messenger (async).
|
||||
15. Handler async C — NotifyAdminUserActivatedHandler:
|
||||
16. Crée une notification interne (Notifier, canal “in‑app”) “Compte activé”.
|
||||
17. Pousse un événement Mercure sur admin/{adminId}/events avec le type USER_ACTIVATED.
|
||||
18. L’UI admin met à jour la liste des membres (badge “Actif”) et affiche un toast confirmant l’activation.
|
||||
19. Journalisation/Audit:
|
||||
20. Chaque handler écrit une trace (succès/échec) en base ou dans un EmailLog/NotificationLog.
|
||||
21. En cas d’échec d’envoi, 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 l’email existe déjà, on rattache l’utilisateur à la nouvelle organisation et on publie OrganizationUserInvitedEvent.
|
||||
24. Handler dédié envoie un email d’information (“Vous avez été ajouté à une nouvelle organisation”) et notifie l’admin via Notifier + Mercure.
|
||||
25. Cas d’actions dérivées par enum:
|
||||
26. ActionType::NewUser → déclenche UserInvitedEvent (steps 3–6).
|
||||
27. ActionType::ActiveUser (si activé par un flux admin) → déclenche directement UserActivatedEvent (steps 9–10).
|
||||
28. ActionType::OrganizationUserInvited → flux similaire au point 12 pour la multi‑organisation.
|
||||
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 d’invitation et d’information.
|
||||
- Symfony Notifier (canal in‑app) + Mercure: notifications persistées + push temps réel vers l’UI admin.
|
||||
- Enum ActionType: routage clair dans l’application, évite la logique string‑based.
|
||||
|
||||
|
||||
```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;
|
||||
```
|
||||
|
|
@ -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.*",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
Loading…
Reference in New Issue