Aller au contenu principal

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é.