Diagramme de Flux de Données - Calendrier et Synchronisation
Ce document présente un diagramme complet en Mermaid du flux de données pour le système de calendrier, la synchronisation bidirectionnelle avec Google Calendar, et la gestion de disponibilité.
Flux Complet de Données
graph TB
subgraph "Frontend - CalendarPage"
A[CalendarPage] --> B[useCalendarData]
A --> C[useCalendarDragAndDrop]
A --> D[useAvailabilitySlots]
A --> E[useCalendarEvents]
A --> F[useSessions]
end
subgraph "Frontend - Hooks & State"
B --> G[Group by date]
B --> H[Filter by tags]
C --> I[Optimistic Updates]
C --> J[API Calls]
D --> K[Availability Cache]
E --> L[Events Cache]
F --> M[Sessions Cache]
end
subgraph "Backend - API Endpoints"
J --> N[POST /sessions/:id]
J --> O[PUT /google-calendar/events/:id]
D --> P[GET /availability/slots]
D --> Q[POST /availability/slots]
D --> R[PUT /availability/slots/:id]
D --> S[DELETE /availability/slots/:id]
E --> T[GET /google-calendar/events]
F --> U[GET /sessions]
end
subgraph "Backend - Services"
N --> V[SessionsService]
O --> W[GoogleCalendarService]
P --> X[AvailabilityService]
Q --> X
R --> X
S --> X
T --> W
U --> V
end
subgraph "Backend - Database"
V --> Y[(sessions)]
V --> Z[(session_tags)]
V --> AA[(session_contacts)]
V --> AB[(session_providers)]
X --> AC[(availability_slots)]
W --> AD[(user_metadata)]
end
subgraph "Backend - Google Calendar API"
W --> AE[OAuth2 Client]
AE --> AF[Google Calendar API]
AF --> AG[events.insert]
AF --> AH[events.update]
AF --> AI[events.delete]
AF --> AJ[events.list]
end
subgraph "Backend - Synchronization"
AK[GoogleCalendarSyncScheduler<br/>Every 5 minutes] --> AL[getUsersWithCalendar]
AL --> AM[getEventsWithSessionIds]
AM --> AF
AF --> AN[Compare with sessions]
AN --> AO{Conflict?}
AO -->|Yes| AP[Skip if session newer]
AO -->|No| AQ[updateFromCalendar]
AQ --> V
end
subgraph "Data Flow - Session Creation"
AR[User creates Session] --> AS[SessionFormPage]
AS --> AT[checkAvailability]
AT --> X
X --> AU{Slot available?}
AU -->|No| AV[Error: Blocked]
AU -->|Yes| AW[createSession]
AW --> V
V --> AX[createSessionEvent]
AX --> W
W --> AG
end
subgraph "Data Flow - Drag & Drop"
AY[User drags Session/Event] --> AZ[useCalendarDragAndDrop]
AZ --> BA[Optimistic UI Update]
BA --> BB[API Call]
BB --> BC{Type?}
BC -->|Session| BD[updateSession]
BC -->|Event| BE[updateCalendarEvent]
BD --> V
BE --> W
V --> BF[updateSessionEvent]
BF --> W
W --> AH
BD --> BG[Update Cache]
BE --> BG
BG --> BH[UI Reflects Change]
end
subgraph "Data Flow - Availability Management"
BI[User creates Availability Slot] --> BJ[AvailabilitySlotDialog]
BJ --> BK[useCreateAvailabilitySlot]
BK --> BL[POST /availability/slots]
BL --> X
X --> AC
AC --> BM[React Query Cache Update]
BM --> BN[CalendarPage Re-render]
BN --> BO[AvailabilitySlotDisplay]
end
style A fill:#e1f5ff
style V fill:#fff4e1
style W fill:#fff4e1
style X fill:#fff4e1
style AK fill:#ffe1f5
style AF fill:#e1ffe1
style Y fill:#f0f0f0
style AC fill:#f0f0f0
style AD fill:#f0f0f0
Flux Détaillé de Synchronisation
sequenceDiagram
participant U as Utilisateur
participant CP as CalendarPage
participant SS as SessionsService
participant GCS as GoogleCalendarService
participant GCA as Google Calendar API
participant SCH as SyncScheduler
participant DB as Database
Note over U,DB: Création Session → Google Calendar
U->>CP: Crée session avec dates
CP->>SS: createSession(data)
SS->>DB: INSERT INTO sessions
DB-->>SS: Session créée
SS->>GCS: createSessionEvent(sessionId, ...)
GCS->>GCA: events.insert(extendedProperties)
Note right of GCA: extendedProperties.private:<br/>- sessionId<br/>- syncSource: 'crm'<br/>- sessionUpdatedAt
GCA-->>GCS: Event créé
GCS-->>SS: Success
SS-->>CP: Session avec relations
CP->>CP: Optimistic update UI
Note over SCH,DB: Synchronisation Google Calendar → CRM (5 min)
SCH->>GCS: getUsersWithCalendar()
GCS->>DB: SELECT users avec google_calendar_id
DB-->>GCS: Liste utilisateurs
GCS-->>SCH: Users
loop Pour chaque utilisateur
SCH->>GCS: getEventsWithSessionIds(userId, -7j, +30j)
GCS->>GCA: events.list(privateExtendedProperty)
GCA-->>GCS: Événements avec sessionId
GCS-->>SCH: Events
loop Pour chaque événement
SCH->>SS: findById(sessionId, userId)
SS->>DB: SELECT session
DB-->>SS: Session
SS-->>SCH: Session
SCH->>SCH: Vérifier conflit
alt syncSource === 'crm' ET session.updated_at > event.sessionUpdatedAt
SCH->>SCH: Skip (conflit détecté)
else Pas de conflit
SCH->>SCH: Comparer données
alt Différences détectées
SCH->>SS: updateFromCalendar(sessionId, data)
Note right of SS: Sans callback<br/>Google Calendar
SS->>DB: UPDATE sessions
DB-->>SS: Session mise à jour
SS-->>SCH: Success
end
end
end
end
Note over U,DB: Modification dans Google Calendar
U->>GCA: Modifie événement directement
GCA->>GCA: Event mis à jour
Note right of GCA: syncSource reste 'crm'<br/>ou devient 'calendar'
SCH->>SCH: Détecte changement au prochain cycle
SCH->>SS: updateFromCalendar(...)
SS->>DB: UPDATE sessions
DB-->>SS: Session synchronisée
Flux de Gestion de Disponibilité
graph TD
A[Utilisateur ouvre CalendarPage] --> B[useAvailabilitySlots]
B --> C[GET /availability/slots]
C --> D[AvailabilityService.list]
D --> E[(availability_slots)]
E --> F[React Query Cache]
F --> G[useCalendarData]
G --> H[Group by date]
H --> I[availabilityByDate]
I --> J[DayView/WeekView/MonthView]
J --> K[AvailabilitySlotDisplay]
L[Utilisateur crée créneau] --> M[AvailabilitySlotDialog]
M --> N[useCreateAvailabilitySlot]
N --> O[POST /availability/slots]
O --> P[AvailabilityService.create]
P --> E
P --> Q[Optimistic Update Cache]
Q --> R[UI Update Immédiat]
S[Utilisateur crée Session] --> T[SessionFormPage]
T --> U[checkAvailability]
U --> V[GET /availability/check]
V --> P
P --> W{isSlotAvailable?}
W -->|Non| X[Erreur: Créneau bloqué]
W -->|Oui| Y[createSession]
Y --> Z[Session créée]
Flux de Drag & Drop avec Optimistic Updates
sequenceDiagram
participant U as Utilisateur
participant CP as CalendarPage
participant DND as useCalendarDragAndDrop
participant API as Backend API
participant DB as Database
participant RQ as React Query Cache
U->>CP: Drag session vers nouveau jour
CP->>DND: handleDragEnd
DND->>RQ: onMutate - Snapshot cache
RQ-->>DND: previousSessions
DND->>RQ: Optimistic update cache
Note right of RQ: UI update immédiat
RQ-->>CP: Cache mis à jour
CP->>CP: UI re-render (session déplacée)
DND->>API: PUT /sessions/:id
API->>DB: UPDATE sessions
DB-->>API: Session mise à jour
API-->>DND: Success response
alt Success
DND->>RQ: onSuccess - Update avec réponse serveur
RQ-->>CP: Cache synchronisé
else Error
DND->>RQ: onError - Rollback
RQ->>RQ: Restore previousSessions
RQ-->>CP: UI restaurée
CP->>CP: Afficher erreur
end
Architecture des ExtendedProperties
graph LR
A[Session CRM] --> B[buildSessionEvent]
B --> C[extendedProperties.private]
C --> D[sessionId: UUID]
C --> E[syncSource: 'crm']
C --> F[sessionUpdatedAt: ISO timestamp]
D --> G[Google Calendar Event]
E --> G
F --> G
G --> H[Scheduler détecte changement]
H --> I{Conflit?}
I -->|session.updated_at > sessionUpdatedAt| J[Skip sync]
I -->|Pas de conflit| K[Synchroniser]
K --> L[updateFromCalendar]
L --> A
Vue d'Ensemble du Système
graph TB
subgraph "Interface Utilisateur"
A[CalendarPage]
B[AvailabilitySlotDialog]
C[SessionFormPage]
D[EventDialogs]
end
subgraph "State Management"
E[React Query Cache]
F[Optimistic Updates]
G[Local State]
end
subgraph "API Layer"
H[REST Endpoints]
I[Google Calendar API]
end
subgraph "Business Logic"
J[SessionsService]
K[GoogleCalendarService]
L[AvailabilityService]
M[SyncScheduler]
end
subgraph "Data Layer"
N[(PostgreSQL)]
O[Google Calendar]
end
A --> E
B --> E
C --> E
D --> E
E --> F
F --> H
H --> J
H --> K
H --> L
J --> N
K --> I
L --> N
I --> O
M --> K
M --> J
K --> I
I --> O
O --> M
style A fill:#e1f5ff
style E fill:#fff4e1
style J fill:#ffe1f5
style K fill:#ffe1f5
style L fill:#ffe1f5
style M fill:#e1ffe1
style N fill:#f0f0f0
style O fill:#f0f0f0
Résolution de Conflits Détaillée
graph TD
A[Scheduler détecte événement modifié] --> B[Lire extendedProperties]
B --> C{syncSource?}
C -->|'crm'| D[Événement créé depuis CRM]
C -->|'calendar' ou absent| E[Événement modifié dans Calendar]
D --> F[Lire sessionUpdatedAt]
F --> G[Lire session.updated_at]
G --> H{session.updated_at > sessionUpdatedAt?}
H -->|Oui| I[CONFLIT: Session plus récente]
H -->|Non| J[Pas de conflit]
I --> K[Skip sync - Log conflit]
J --> L[Comparer données]
E --> L
L --> M{Différences?}
M -->|Oui| N[updateFromCalendar]
M -->|Non| O[Skip]
N --> P[UPDATE sessions - Sans callback]
P --> Q[Session synchronisée]
style I fill:#ffcccc
style K fill:#ffcccc
style Q fill:#ccffcc
Ce diagramme complet montre tous les flux de données du système de calendrier, de la synchronisation bidirectionnelle, et de la gestion de disponibilité.