From e6eaba3018b395860d8d63d6d8f9426aaf34ea9f Mon Sep 17 00:00:00 2001 From: Pierre Marx Date: Thu, 4 Sep 2025 11:55:08 -0400 Subject: [PATCH] docs signalR --- docs/INTEGRATION_SIGNALR.md | 138 ++++++++++- docs/WORKFLOW_AGENT.md | 452 ++++++++++++++++++++++++++++++++++++ 2 files changed, 585 insertions(+), 5 deletions(-) create mode 100644 docs/WORKFLOW_AGENT.md diff --git a/docs/INTEGRATION_SIGNALR.md b/docs/INTEGRATION_SIGNALR.md index f70f2d2..e9598ba 100644 --- a/docs/INTEGRATION_SIGNALR.md +++ b/docs/INTEGRATION_SIGNALR.md @@ -186,26 +186,154 @@ function handleCallHungUp(event, mainWindow) { } ``` -### 4. Récupération de la liste des terminaux +### 4. Récupération et sélection des terminaux téléphoniques + +#### Processus complet de récupération des terminaux + +La récupération des terminaux se fait en deux phases : récupération depuis le serveur et affichage dans l'interface de connexion. + +##### Côté processus principal (main.js) ```javascript -// Obtenir les terminaux disponibles -async function getTerminalList(connection, serviceProvider) { +// Handler IPC pour récupérer les terminaux +ipcMain.handle('get-terminal-list', async () => { try { - const terminals = await connection.invoke( + const terminals = await signalRConnection.invoke( 'GetTerminalListByServiceProvider', - serviceProvider + config.ServiceProvider // Ex: 'RDVPREM' depuis la config ); console.log('Terminaux disponibles:', terminals); + // Retourne un tableau de numéros: ["3001", "3002", "3003", ...] return terminals; } catch (error) { console.error('Erreur récupération terminaux:', error); return []; } +}); +``` + +##### Côté renderer - Interface de sélection + +```javascript +// Au chargement de la page de connexion +document.addEventListener('DOMContentLoaded', async () => { + try { + // Afficher un loader + const terminalSelect = document.getElementById('terminal-select'); + terminalSelect.innerHTML = ''; + + // Récupérer les terminaux disponibles depuis le serveur + const terminals = await ipcRenderer.invoke('get-terminal-list'); + + if (terminals && terminals.length > 0) { + populateTerminalSelect(terminals); + + // Restaurer la dernière sélection si disponible + const lastTerminal = localStorage.getItem('last-terminal'); + if (lastTerminal && terminals.includes(lastTerminal)) { + terminalSelect.value = lastTerminal; + } + } else { + showError('Aucun terminal téléphonique disponible'); + terminalSelect.innerHTML = ''; + } + } catch (error) { + console.error('Erreur chargement terminaux:', error); + showError('Impossible de récupérer la liste des terminaux'); + } +}); + +// Remplir le select avec les terminaux +function populateTerminalSelect(terminals) { + const select = document.getElementById('terminal-select'); + select.innerHTML = ''; + + terminals.forEach(terminal => { + const option = document.createElement('option'); + option.value = terminal; + option.textContent = `Poste ${terminal}`; + select.appendChild(option); + }); +} + +// Intégration dans le formulaire de connexion +async function handleLogin(e) { + e.preventDefault(); + + const terminal = document.getElementById('terminal-select').value; + + // Validation : terminal obligatoire + if (!terminal) { + showError('Veuillez sélectionner un terminal téléphonique'); + return; + } + + const credentials = { + email: document.getElementById('email').value, + password: document.getElementById('password').value, + terminal: terminal + }; + + // Sauvegarder le terminal pour la prochaine connexion + localStorage.setItem('last-terminal', terminal); + + // Connexion avec le terminal sélectionné + const result = await ipcRenderer.invoke('agent-login', credentials); + + if (result.success) { + // Le terminal est maintenant associé à la session + // Il sera affiché dans le titre de la fenêtre + console.log(`Connecté sur le poste ${terminal}`); + } } ``` +##### Interface HTML correspondante + +```html + +
+
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+``` + +#### Points importants sur les terminaux + +1. **ServiceProvider** : Le paramètre configuré dans `config.json` détermine quels terminaux sont disponibles pour l'organisation + +2. **Filtrage serveur** : Le serveur filtre automatiquement les terminaux selon : + - Le fournisseur de service (ServiceProvider) + - Les droits de l'organisation + - La disponibilité des postes + - Les terminaux déjà utilisés par d'autres agents + +3. **Validation obligatoire** : Un agent DOIT sélectionner un terminal pour se connecter - c'est ce qui permet le routage des appels + +4. **Affichage contextuel** : Après connexion, le terminal est affiché dans le titre : + ```javascript + mainWindow.setTitle(`SimpleConnect - Agent: ${user} (${firstName} ${lastName}) - Tel: ${terminal}`); + ``` + +5. **Association terminal-agent** : Cette association permet au serveur SignalR de router les événements IPBX vers le bon agent + ### 5. Déconnexion propre ```javascript diff --git a/docs/WORKFLOW_AGENT.md b/docs/WORKFLOW_AGENT.md new file mode 100644 index 0000000..c29860f --- /dev/null +++ b/docs/WORKFLOW_AGENT.md @@ -0,0 +1,452 @@ +# Workflow complet d'un agent SimpleConnect + +## Vue d'ensemble + +Ce document décrit le parcours complet d'un agent utilisant SimpleConnect, depuis la connexion jusqu'à la déconnexion, en passant par la gestion des appels et l'utilisation des différentes fonctionnalités. + +## 1. Lancement de l'application + +### Actions au démarrage + +```javascript +// L'agent lance l'application SimpleConnect +// Initialisation automatique des composants +``` + +**Processus système** : +- Connexion automatique au serveur SignalR (configuré dans `config.json`) +- Vérification de la disponibilité du service +- Récupération de la liste des terminaux téléphoniques disponibles +- Création du fichier de log journalier +- Génération du dashboard initial (état : application ouverte, non connecté) + +## 2. Phase de connexion + +### 2.1 Interface de connexion + +L'agent arrive sur l'écran de connexion avec : +- Champ email +- Champ mot de passe +- Sélecteur de terminal téléphonique (liste dynamique) +- Bouton de connexion + +### 2.2 Processus d'authentification + +```javascript +// Envoi des credentials au serveur +AgentLogin(email, password, terminal) → Serveur SignalR + +// Réponse du serveur avec les informations complètes +{ + accessCode: "AGENT001", + firstName: "Marie", + lastName: "DUPONT", + terminal: "3001", + connList: [ // Centres/files assignés à l'agent + { + code: "centre1", + applicationName: "https://pro.doctolib.fr", + accessCode: "user_cardio", + password: "pass123" + }, + { + code: "centre2", + applicationName: "https://pro.mondocteur.fr", + accessCode: "user_clinique", + password: "pass456" + } + // ... + ] +} +``` + +### 2.3 Post-connexion + +**Actions automatiques après connexion réussie** : +1. Génération dynamique des onglets selon les centres assignés +2. Création des webviews pour chaque plateforme +3. Auto-connexion aux plateformes médicales (injection des credentials) +4. Mise à jour de l'interface : + - Titre fenêtre : "SimpleConnect - Agent: Marie DUPONT - Tel: 3001" + - Nom agent affiché dans l'interface + - Statut : "Disponible" (indicateur vert) +5. Activation de l'écoute des événements IPBX +6. Mise à jour du dashboard JSON avec les informations de connexion + +## 3. Phase d'activité - Gestion des appels + +### 3.1 État disponible + +**L'agent est prêt à recevoir des appels** : +- Statut : indicateur vert "Disponible" +- Peut naviguer librement entre les onglets +- Peut consulter les plannings de manière proactive +- Statistiques visibles : appels traités, RDV pris + +### 3.2 Réception d'un appel entrant + +#### Séquence d'événements + +``` +1. Patient appelle le centre + ↓ +2. Système IPBX détecte l'appel + ↓ +3. Serveur SignalR envoie IpbxEvent + ↓ +4. Client reçoit : {eventCode: 1, terminal: "3001", queueName: "centre1"} + ↓ +5. Interface réagit automatiquement +``` + +#### Actions système + +**Notification immédiate** : +```javascript +// Alerte visuelle +showIncomingCallAlert({ + centreName: "Centre Cardio Lyon", + patientInfo: "Marie LAMBERT - 0612345678", + motif: "Consultation urgente" +}); + +// Son de notification +playNotificationSound(); +``` + +**Auto-acceptation** : +- Timer de 3 secondes avant acceptation automatique +- Ou acceptation manuelle immédiate par l'agent + +#### Basculement automatique + +```javascript +// Le système identifie le centre concerné +selectCenter('centre1'); + +// Bascule sur le bon onglet/webview +switchToTab('Centre Cardio Lyon'); + +// Mise à jour du statut +updateStatus('EN APPEL - Centre Cardio Lyon'); +``` + +### 3.3 Pendant l'appel + +**Actions possibles de l'agent** : + +1. **Prise de RDV** : + - Navigation dans le planning actif + - Recherche de créneaux disponibles + - Validation du RDV directement dans la webview + +2. **Prise de notes** : + ```javascript + // Zone de notes rapides + quickNotes.value = "Patient souhaite mardi matin de préférence"; + saveNotes(); // Sauvegarde horodatée + ``` + +3. **Consultation documentation** : + ```javascript + // Ouverture wiki interne (nouvelle fenêtre) + OpenDoc("http://wiki.interne/protocoles"); + + // Consultation infos patient (fenêtre séparée) + OpenDoc("http://crm.interne/patient/12345"); + ``` + +4. **Informations contextuelles** : + - Historique des derniers appels du patient (si disponible) + - Procédures spécifiques au centre + - Tarifs et modalités + +### 3.4 Fin d'appel + +#### Séquence de libération + +``` +1. Patient/Agent raccroche + ↓ +2. Système IPBX détecte la fin d'appel + ↓ +3. Serveur SignalR envoie IpbxEvent + ↓ +4. Client reçoit : {eventCode: 2, terminal: "3001", queueName: "centre1"} + ↓ +5. Libération automatique de la file +``` + +#### Actions post-appel + +```javascript +// Mise à jour automatique +updateStatus('DISPONIBLE'); +callStats.calls++; +callStats.appointments++; // Si RDV pris + +// Sauvegarde dans l'historique +saveCallHistory({ + timestamp: new Date().toISOString(), + duration: 180, // secondes + centre: "centre1", + status: "completed", + appointment: true +}); +``` + +## 4. Fonctionnalités disponibles pendant la session + +### 4.1 Navigation multi-centres + +```javascript +// L'agent peut gérer plusieurs centres simultanément +centres = [ + { id: 'centre1', nom: 'Centre Cardio Lyon', couleur: '#FF6B6B' }, + { id: 'centre2', nom: 'Clinique Saint-Jean', couleur: '#4ECDC4' }, + { id: 'centre3', nom: 'Cabinet Dr Martin', couleur: '#45B7D1' } +]; + +// Navigation libre entre les onglets (hors appel) +selectCenter('centre2'); // Changement manuel +``` + +### 4.2 Outils de productivité + +**Statistiques temps réel** : +```javascript +{ + calls: 15, // Appels traités aujourd'hui + appointments: 12, // RDV confirmés + avgDuration: 180, // Durée moyenne en secondes + successRate: 80 // Taux de conversion +} +``` + +**Notes et historique** : +```javascript +// Notes rapides par appel +saveNotes({ + content: "Patient à rappeler pour confirmation", + centre: "centre1", + timestamp: new Date() +}); + +// Consultation historique +getCallHistory(); // 100 derniers appels +``` + +### 4.3 Fenêtres auxiliaires + +```javascript +// Documentation (DocXplore) +childClientDocXplore = new BrowserWindow({ + x: 1920, y: 0, // Position configurée + title: "SimpleConnect / Wiki" +}); + +// Informations client +childClientDoc = new BrowserWindow({ + x: 2880, y: 0, // Position configurée + title: "SimpleConnect / Infos client" +}); +``` + +## 5. Processus de déconnexion + +### 5.1 Déclenchement + +La déconnexion peut être initiée par : +- Clic sur le bouton "Déconnexion" +- Fermeture de l'application (croix de fenêtre) +- Timeout de session (si configuré) + +### 5.2 Confirmation et nettoyage + +```javascript +// Dialogue de confirmation +if (confirm('Voulez-vous vraiment vous déconnecter ?')) { + // 1. Notification au serveur + AgentLogoff(agentId); + + // 2. Nettoyage local + currentAgent = null; + currentCentres = []; + webviews = {}; + + // 3. Fermeture des fenêtres auxiliaires + if (childClientDocXplore) childClientDocXplore.close(); + if (childClientDoc) childClientDoc.close(); + + // 4. Génération log final + writeDashboardLog({ + "PrestaConnect": { + "Connexion": { + "Connecte": "Non", + "Date_Deconnexion": new Date().toISOString() + } + } + }); + + // 5. Retour page connexion ou fermeture + showLoginPage(); // ou app.quit() +} +``` + +## 6. Logs et monitoring + +### 6.1 Structure du dashboard + +**Fichier** : `./log/log-Dashboard.json` + +```json +{ + "PrestaConnect": { + "Ouverture": { + "Ouvert": "Oui", + "Date": "2024-12-04T10:00:00.000Z", + "IP_Client": "192.168.1.50", + "IP_Serveur": "10.90.20.201:8002", + "Liste_Telephones": ["3001", "3002", "3003"] + }, + "Connexion": { + "Connecte": "Oui", + "Date": "2024-12-04T10:01:00.000Z", + "Agent": "AGENT001", + "Telephone": "3001", + "Nom_Agent": "Marie DUPONT", + "Nombre_Files": 3, + "Files": [ + { + "Nom_File": "centre1", + "URL_File": "https://pro.doctolib.fr" + }, + { + "Nom_File": "centre2", + "URL_File": "https://pro.mondocteur.fr" + } + ] + } + } +} +``` + +### 6.2 Logs détaillés + +**Fichier** : `./log/YYYY-MM-DD-log.txt` + +``` +[2024-12-04 10:00:00.123] [info] Start application +[2024-12-04 10:00:01.456] [info] ip: 10.90.20.201:8002 +[2024-12-04 10:00:02.789] [info] SignalR connected +[2024-12-04 10:01:00.123] [info] Agent login: AGENT001 +[2024-12-04 10:05:30.456] [info] IpbxEvent received: eventCode=1, terminal=3001 +[2024-12-04 10:08:45.789] [info] IpbxEvent received: eventCode=2, terminal=3001 +``` + +## 7. Mode développement et simulation + +### 7.1 Panneau de test CTI + +En mode développement (`NODE_ENV=development`), un panneau de test permet : + +```javascript +// Simulation d'appels +ctiSimulator.generateRandomCall(); + +// Simulation automatique +ctiSimulator.startAutoSimulation(30); // Un appel toutes les 30 secondes + +// Scénarios prédéfinis +ctiSimulator.simulateScenarios(): +- "Appel urgent" +- "Patient régulier" +- "Nouveau patient" +- "Demande résultats" +``` + +### 7.2 Statistiques de simulation + +```javascript +{ + total: 45, // Total appels simulés + today: 15, // Appels aujourd'hui + answered: 14, // Appels traités + missed: 1, // Appels manqués + average_duration: 180 // Durée moyenne +} +``` + +## 8. Diagramme d'états + +``` +┌─────────────┐ +│ DÉCONNECTÉ │ +└─────┬───────┘ + │ Connexion + ↓ +┌─────────────┐ +│ CONNEXION │ +└─────┬───────┘ + │ Authentification réussie + ↓ +┌─────────────┐ Appel entrant ┌─────────────┐ +│ DISPONIBLE │ ←─────────────────→ │ EN APPEL │ +└─────┬───────┘ Fin d'appel └─────────────┘ + │ + │ Déconnexion + ↓ +┌─────────────┐ +│ DÉCONNEXION │ +└─────────────┘ +``` + +## 9. Points clés du workflow + +### Avantages pour l'agent + +1. **Zéro friction** : Pas de recherche manuelle de plateforme +2. **Contexte automatique** : Basculement instantané vers le bon planning +3. **Productivité maximale** : Auto-connexion, notes rapides, historique +4. **Traçabilité complète** : Tous les événements sont enregistrés +5. **Multi-tâches optimisé** : Gestion simultanée de plusieurs centres + +### Optimisations système + +1. **Reconnexion automatique** SignalR en cas de perte réseau +2. **Sessions persistantes** dans les webviews +3. **Cache local** des dernières sélections (terminal, notes) +4. **Logs structurés** pour analyse et monitoring +5. **Mode simulation** pour formation et tests + +## 10. Cas d'usage spéciaux + +### 10.1 Appel urgent + +```javascript +// Identification par priorité haute +if (callData.priority === 'high') { + // Notification visuelle renforcée + showUrgentCallAlert(callData); + // Son différent + playUrgentSound(); + // Auto-acceptation immédiate + acceptCall(callData); +} +``` + +### 10.2 Patient régulier + +```javascript +// Affichage historique patient +if (callData.lastVisit) { + showPatientHistory({ + lastVisit: callData.lastVisit, + appointments: callData.appointmentHistory + }); +} +``` + +### 10.3 Multi-files simultanées + +L'agent peut recevoir des appels de différentes files et le système bascule automatiquement vers la bonne plateforme à chaque appel, permettant une gestion fluide multi-centres. \ No newline at end of file