docs signalR

This commit is contained in:
Pierre Marx
2025-09-04 11:55:08 -04:00
parent 7e34c471de
commit e6eaba3018
2 changed files with 585 additions and 5 deletions

View File

@@ -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 = '<option value="">Chargement des terminaux...</option>';
// 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 = '<option value="">Aucun terminal disponible</option>';
}
} 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 = '<option value="">Sélectionner un terminal...</option>';
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
<!-- Formulaire de connexion avec sélection du terminal -->
<form id="loginForm">
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" required>
</div>
<div class="form-group">
<label for="password">Mot de passe</label>
<input type="password" id="password" required>
</div>
<div class="form-group">
<label for="terminal-select">Terminal téléphonique</label>
<select id="terminal-select" required>
<option value="">Chargement...</option>
</select>
</div>
<button type="submit">Se connecter</button>
</form>
```
#### 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

452
docs/WORKFLOW_AGENT.md Normal file
View File

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