# TODO - Évolutions CLEO

## Fonctionnalités à développer

### Module Devis

#### 8. Dupliquer une ligne produit
**Priorité**: Moyenne  
**Description**: Permettre la duplication d'une ligne produit dans un même devis (utile pour les gratuités).  
**Tâches**:
- [ ] Ajouter un bouton "Dupliquer" sur chaque ligne produit
- [ ] Gérer la duplication avec prix à 0 pour les gratuités
- [ ] Conserver l'ordre des lignes après duplication
- [ ] Mettre à jour automatiquement les totaux

#### 16. Système de recherche avancée
**Priorité**: Haute  
**Description**: Ajouter une recherche multi-critères pour les devis en cours et archivés.  
**Tâches**:
- [ ] Créer une interface de recherche unifiée
- [ ] Implémenter la recherche par :
  - [ ] Numéro de devis
  - [ ] Nom d'établissement/client
  - [ ] Référence produit
  - [ ] Numéro d'opportunité
- [ ] Ajouter des filtres par statut (en cours/archivé)
- [ ] Paginer les résultats de recherche
- [ ] Export des résultats en Excel

#### 21. Actualisation tarifaire
**Priorité**: Moyenne
**Description**: Permettre l'actualisation des prix selon la dernière grille tarifaire.
**Tâches**:
- [ ] Ajouter un bouton "Actualiser les tarifs"
- [ ] Comparer les prix actuels avec la grille en vigueur
- [ ] Afficher les différences avant validation
- [ ] Recalculer automatiquement les marges
- [ ] Tracer l'actualisation dans l'historique

#### 22. Marchés hybrides et onglet Mercurial
**Priorité**: Haute
**Description**: Ajouter un onglet "Mercurial" dans la page devis pour les marchés de type hybride, listant tous les produits du marché.

**Tâches - Phase 1 (Onglet Mercurial)** :
- [x] Identifier le type de marché du devis sélectionné
- [x] Détecter si le marché est de type "hybride"
- [x] Ajouter un nouvel onglet "Mercurial" dans l'interface devis (au niveau de l'onglet Produits)
- [x] Récupérer tous les produits associés au marché
- [x] Filtrer les produits "Hors Marché 999"
- [x] Afficher la liste des produits dans l'onglet Mercurial
- [x] Gérer l'affichage/masquage de l'onglet selon le type de marché

**Tâches - Phase 2 (Améliorations visuelles et règles métier)** :
- [ ] **Visibilité de l'onglet Mercurial** : Rendre l'onglet "Mercurial" visuellement distinct (couleur de fond différente, par exemple) pour qu'il soit clairement identifiable par les commerciaux

**Types de marchés hybrides** :
Deux cas de marchés hybrides doivent être gérés différemment :

**CAS 1 - Mercuriale sans remise** :
- Liste mercuriale en prix nets SANS remise applicable sur ces références
- Reste du catalogue disponible avec possibilité de remises en autonomie

**CAS 2 - Mercuriale avec remise possible** :
- Liste mercuriale en prix nets AVEC possibilité de remises sur ces références
- Reste du catalogue disponible avec possibilité de remises en autonomie

**Règles communes aux 2 cas** :
- Quand le devis contient UNIQUEMENT des références mercuriales → pas de demande d'accord nécessaire, le RR peut valider directement
- Quand le devis contient références mercuriales + catalogue général → seules les références du catalogue sont concernées par les seuils de marge et peuvent générer une demande d'accord
- Si geste commercial souhaité sur un devis 100% mercurial → utiliser le champ "Demande geste commercial" existant

**Tâches - Paramétrage base de données** :
- [ ] Ajouter un champ dans la table `marches` pour définir le type de marché hybride :
  - `type_mercurial` (ENUM ou INT) : NULL = non hybride, 1 = CAS 1 (sans remise), 2 = CAS 2 (avec remise)
- [ ] Modifier la fiche marché pour permettre la sélection du type de marché hybride

**Tâches - Logique métier de validation** :
- [ ] Détecter si un devis contient uniquement des produits mercuriaux
- [ ] Détecter si un devis contient un mix mercurial + catalogue
- [ ] Adapter le calcul des seuils de marge :
  - Si devis 100% mercurial → pas de vérification de seuil, validation RR directe
  - Si devis mixte → calculer les seuils uniquement sur les produits du catalogue général
- [ ] Bloquer/autoriser les remises sur produits mercuriaux selon le type de marché (CAS 1 vs CAS 2)
- [ ] Tester le workflow complet avec les 2 types de marchés hybrides

### Module SAP

#### 13. Import et contrôle des clients SAP
**Priorité**: Haute
**Description**: Contrôler les nouveaux clients créés dans la base CLEO et vérifier la correspondance avec la base SAP.
**Tâches**:
- [ ] Identifier le script/contrôleur d'import des clients SAP
- [ ] Analyser la structure des données importées
- [ ] Mettre en place un système de contrôle de correspondance
  - [ ] Vérifier l'unicité du `clients.code` (identifiant SAP)
  - [ ] Détecter les doublons potentiels (nom, adresse)
  - [ ] Signaler les incohérences entre SAP et CLEO
- [ ] Créer un rapport d'import avec :
  - [ ] Nombre de clients importés
  - [ ] Nombre de clients mis à jour
  - [ ] Nombre d'anomalies détectées
- [ ] Gestion des cas particuliers :
  - [ ] Client existe dans CLEO mais pas dans SAP
  - [ ] Client existe dans SAP mais code différent dans CLEO
  - [ ] Contacts orphelins après import

#### 14. Gestion de la prise en charge
**Priorité**: Haute  
**Description**: Ajouter la traçabilité de la prise en charge et du transfert EDI.  
**Tâches**:
- [ ] Ajouter les champs en base de données :
  - [ ] `chk_prise_en_charge` (boolean)
  - [ ] `fk_user_prise_en_charge` (int)
  - [ ] `date_prise_en_charge` (datetime)
  - [ ] `fk_user_transfert_edi` (int)
  - [ ] `date_transfert_edi` (datetime)
  - [ ] `erreur_transfert_edi` (text)
- [ ] Interface de prise en charge avec case à cocher
- [ ] Affichage du nom du gestionnaire (ex: "Angela Monteiro")
- [ ] Possibilité de décocher en cas d'erreur
- [ ] Log des transferts EDI
- [ ] Gestion et affichage des erreurs EDI

#### 16. Recherche dans le module SAP
**Priorité**: Moyenne  
**Description**: Implémenter la recherche dans le module SAP (voir point 16 des Devis).  
**Tâches**:
- [ ] Réutiliser le composant de recherche des devis
- [ ] Adapter aux spécificités SAP
- [ ] Filtres supplémentaires (état EDI, prise en charge)

## Migration Infrastructure - Séparation Application/Base de données

### ✅ PHASE 1 COMPLÉTÉE (12 septembre 2025)

**Description**: Migration réussie de l'architecture DEV/RECETTE vers la nouvelle structure avec séparation application/base de données.

### Architecture actuelle (après migration DEV)
- **DEV/RECETTE**: Host IN3 ✅
  - Container `dva-front` (application PHP uniquement) ✅
  - Container `maria3` (MariaDB dédié avec base `cleo`) ✅
- **PROD**: Host IN2 (actuel, à migrer)
  - Container `nx4` (application + BDD intégrées)
  - Bases de données: `uof_frontal` et `uof_linet`

### Architecture cible PROD (à faire)
- **PROD**: Host IN4 (nouveau)
  - Container `pra-front` (import depuis IN3.dva-front)
  - Container `maria4` (import depuis IN3.maria3)
- **Décommissionnement**: Host IN2 (après migration PROD)

### ✅ Refactoring de la base de données (COMPLÉTÉ)
**Changements réalisés**:
1. ✅ **Suppression de la base `uof_frontal`**
   - Configuration externalisée dans `.env`
   - Table `y_pages` migrée vers `cleo`
2. ✅ **Fusion `uof_frontal` + `uof_linet` → `cleo`**
   - Une seule base de données
   - Connexion PDO avec pattern Singleton
3. ✅ **Intégration des logs**
   - Table `z_logs` dans la base `cleo`
   - Tables `z_sessions` et `z_stats` créées

### Plan de migration - État d'avancement

✅ **Migration complétée** - Toutes les phases (0 à 4) sont terminées.

### Configuration technique

#### Variables d'environnement
**DEV (IN3) - Actuel:**
```env
DB_HOST=13.23.33.4  # IP de maria3
DB_PORT=3306
DB_DATABASE=cleo
DB_USERNAME=cleo_user
DB_PASSWORD=CleoDev2025!
```

**PROD (IN4) - À configurer:**
```env
DB_HOST=<IP_maria4>  # À définir sur IN4
DB_PORT=3306
DB_DATABASE=cleo
DB_USERNAME=cleo_user
DB_PASSWORD=<PROD_PASSWORD>  # À sécuriser
```

#### Sécurité réseau
- ✅ Connexions uniquement depuis les containers applicatifs
- ✅ Pas d'exposition directe des ports MariaDB
- [ ] Firewall entre containers à configurer sur IN4

#### Backup et restauration
- [ ] Scripts de backup automatisés à mettre en place
- [ ] Réplication master-slave pour haute disponibilité (optionnel)

## ⚠️ CRITIQUE - Risque de collision de codes clients (EN ATTENTE CLIENT)

### Problématique identifiée
**Date**: 26 novembre 2025
**Statut**: 🔴 EN ATTENTE RÉPONSE CLIENT

#### Situation actuelle
Lorsqu'un commercial crée un nouveau client manuellement dans CLEO (client non présent dans SAP), le système génère automatiquement un code via :
```php
$newCode = MAX(code) + 1;  // cjxdevis.php ligne 1326
```

#### Risque de collision
**Scénario catastrophe** :
1. Commercial crée un client manuel → code auto = `12345`
2. Commercial ajoute des contacts, fait des devis
3. **Import SAP suivant** : un nouveau client SAP arrive avec le code `12345`
4. L'import trouve le client existant (même code) et **écrase toutes les données** du client manuel
5. Les contacts du client manuel deviennent incohérents (pointent vers le mauvais client SAP)
6. Les devis du client manuel sont rattachés au mauvais client SAP

#### Question posée au client
**"Que se passe-t-il lorsqu'un devis avec un nouveau client (code = MAX+1) est intégré dans SAP ?"**
- Le client manuel reçoit-il un vrai code SAP ?
- Le code est-il synchronisé dans CLEO après intégration ?
- Existe-t-il un processus de réconciliation ?

### Solutions techniques envisagées

#### Option A : Plage réservée pour clients manuels
```php
// Codes 9000000+ réservés aux créations manuelles
$newCode = 9000000 + $compteur;
```
**Avantages** : Simple, pas de collision possible
**Inconvénients** : Nécessite coordination avec SAP

#### Option B : Codes négatifs pour clients manuels
```php
// Codes négatifs = clients manuels non SAP
$newCode = -1 * (MAX(ABS(code)) + 1);
```
**Avantages** : Distinction claire SAP/Manuel
**Inconvénients** : Peut poser problème avec certains systèmes

#### Option C : Flag `chk_manual` + protection
```sql
ALTER TABLE clients ADD COLUMN chk_manual TINYINT DEFAULT 0;
```
- `chk_manual = 1` → Client créé manuellement, jamais écrasé par import SAP
- Lors de l'import SAP, ignorer les clients avec `chk_manual = 1`
- Processus manuel de réconciliation si le client est créé dans SAP

**Avantages** : Protection garantie, traçabilité
**Inconvénients** : Nécessite gestion manuelle de la réconciliation

#### Option D : Code temporaire + synchronisation
- Client manuel créé avec code `TEMP_XXXXX`
- Lors de l'intégration SAP, récupération du vrai code SAP
- Mise à jour du code client + tous les contacts/devis associés

**Avantages** : Cohérence totale avec SAP
**Inconvénients** : Complexe, nécessite API ou process de sync

### Actions en attente
- [ ] **Réponse client** sur le processus actuel d'intégration SAP
- [ ] Choix de la solution technique selon la réponse
- [ ] Implémentation de la solution retenue
- [ ] Tests de non-régression sur imports SAP
- [ ] Documentation du processus de gestion des clients manuels

### Impact sur le code existant
**Fichiers concernés** :
- `controllers/cjxdevis.php` : fonction `save_new_client` (ligne 1308)
- `controllers/cjximport.php` : fonction `upload_clients` (ligne 112)
- Documentation utilisateur à mettre à jour

---

## Modification Contacts Clients - Migration vers clients.code

### Contexte
La relation entre `clients_contacts` et `clients` utilise `clients.code` comme clé de référence.
Le système a été conçu pour utiliser le `code` SAP (clé métier immuable) plutôt que le `rowid` (clé technique auto-incrémentée).

### Plan de correction

#### 1. Vérification préalable
- [ ] Lire la structure actuelle de la table `clients`
  - [ ] Confirmer que `code` est de type INT
  - [ ] Vérifier la contrainte UNIQUE sur `code`
  - [ ] Vérifier l'index sur `code`
- [ ] Lire la structure de `clients_contacts`
  - [ ] État actuel de `fk_client`
  - [ ] Contraintes de clé étrangère existantes
- [ ] Vérifier les données existantes
  - [ ] Nombre de contacts déjà enregistrés
  - [ ] Cohérence des relations actuelles

#### 2. Modification de la structure
- [ ] Supprimer la contrainte FK actuelle sur `clients_contacts.fk_client`
- [ ] Modifier le type de `clients_contacts.fk_client` pour correspondre à `clients.code`
- [ ] Ajouter la nouvelle contrainte FK référençant `clients.code`
  - [ ] `ON DELETE CASCADE`
  - [ ] `ON UPDATE CASCADE`
- [ ] Vérifier/ajouter index UNIQUE sur `clients.code` si nécessaire

#### 3. Migration des données
- [ ] Créer un script de migration SQL
- [ ] Sauvegarder les données actuelles de `clients_contacts`
- [ ] Convertir les `fk_client` (rowid → code)
- [ ] Valider la cohérence des données migrées
- [ ] Tester l'intégrité référentielle

#### 4. Adaptation du code applicatif
- [x] ✅ Contrôleur `cjxcontacts.php`
  - Aucune modification nécessaire (utilise déjà `fk_client` de manière générique)
- [x] ✅ Contrôleur `cjxdevis.php`
  - `load_clients_devis` : modifié pour retourner `clients.code`
  - `save_new_client` : modifié pour utiliser `newCode` au lieu de `newClientId`
- [x] ✅ JavaScript `jdevis.js`
  - Fonction `autocompleteClient` : modifiée pour utiliser `list[i]['code']` au lieu de `list[i]['rowid']`
  - `loadContactsClient(list[i]['code'])` : passe maintenant le code SAP
- [ ] **Import clients SAP** : À TRAITER EN PRIORITÉ
  - [ ] Fichier concerné : identifier le contrôleur/script d'import
  - [ ] Lors de l'import, si un client existe déjà (même `code`), mettre à jour ses infos SANS changer le `code`
  - [ ] Gérer la mise à jour des contacts : les contacts existants doivent conserver leur lien via `fk_client = code`
  - [ ] Si import d'un nouveau client : créer avec le `code` SAP fourni
  - [ ] IMPORTANT : Ne jamais modifier `clients.code` après création (immuable)

#### 5. Tests et validation
- [ ] Tests de création de contact
- [ ] Tests de modification de contact
- [ ] Tests de suppression de contact (soft delete)
- [ ] Tests de sélection de contact dans un devis
- [ ] Simuler un import SAP et vérifier la stabilité des relations

### Notes techniques
```sql
-- Exemple de modification FK
ALTER TABLE clients_contacts
  DROP FOREIGN KEY fk_clients_contacts_client;

ALTER TABLE clients_contacts
  ADD CONSTRAINT fk_clients_contacts_client
  FOREIGN KEY (fk_client)
  REFERENCES clients(code)
  ON DELETE CASCADE
  ON UPDATE CASCADE;
```

---

## Améliorations techniques prioritaires

### Sécurité
- [x] ✅ Migrer les credentials DB vers des variables d'environnement
- [x] ✅ Classe Database avec requêtes préparées PDO
- [x] ✅ Audit complet et correction de toutes les injections SQL (14 vulnérabilités corrigées)
- [ ] Correction des failles XSS potentielles
- [ ] Implémentation des tokens CSRF
- [ ] Tests de sécurité automatisés

### Performance
- [ ] Implémenter la pagination côté serveur pour toutes les listes
- [ ] Ajouter des index sur les colonnes fréquemment recherchées
- [ ] Mettre en cache les requêtes récurrentes

### Qualité du code
- [ ] Ajouter la documentation PHPDoc sur les fonctions principales
- [ ] Créer des tests unitaires pour les fonctions critiques
- [ ] Standardiser la gestion des erreurs

## Planning prévisionnel

### Sprint 1 (2 semaines) - Sécurité
- Correction des vulnérabilités critiques
- Migration des configurations sensibles

### Sprint 2 (3 semaines) - Fonctionnalités prioritaires
- Point 6 : Modification devis archivés
- Point 14 : Prise en charge SAP
- Point 16 : Recherche avancée

### Sprint 3 (3 semaines) - Gestion des contacts
- Point 19 : Contacts multiples
- Migration des données existantes

### Sprint 4 (2 semaines) - Améliorations
- Point 8 : Duplication lignes produits
- Point 21 : Actualisation tarifaire

### Sprint 5 (2 semaines) - Optimisations
- Performances et pagination
- Tests et documentation

## Notes de développement

### ✅ Structure de la table `clients_contacts` (CRÉÉE - v2.0.3)
Table créée et opérationnelle avec :
- Clé étrangère vers `clients` avec CASCADE
- Gestion du contact principal (un seul par client)
- Soft delete via champ `active`
- Traçabilité (date_creat, fk_user_creat, date_modif, fk_user_modif)
- Index sur fk_client, principal et email
- Contrainte UNIQUE sur rowid
- Voir `docs/migration_clients_contacts.sql` pour la structure complète

### Modifications table `devis` pour SAP
```sql
ALTER TABLE devis ADD COLUMN chk_prise_en_charge TINYINT DEFAULT 0;
ALTER TABLE devis ADD COLUMN fk_user_prise_en_charge INT;
ALTER TABLE devis ADD COLUMN date_prise_en_charge DATETIME;
ALTER TABLE devis ADD COLUMN fk_user_transfert_edi INT;
ALTER TABLE devis ADD COLUMN date_transfert_edi DATETIME;
ALTER TABLE devis ADD COLUMN erreur_transfert_edi TEXT;
```

## Résumé de l'état actuel

### ✅ Réalisations
**v2.0.1 (12 septembre 2025)**
1. **Migration DEV complétée** : Architecture séparée application/BDD
2. **Base unique `cleo`** : Fusion réussie de 3 bases en une seule
3. **Sécurité renforcée** : PDO, requêtes préparées, variables d'environnement
4. **Container `dva-front`** : MariaDB supprimé, application PHP uniquement
5. **Container `maria3`** : Base de données centralisée opérationnelle

**v2.0.2 (12 septembre 2025)**
1. **Audit de sécurité complété** : 14 vulnérabilités SQL identifiées et corrigées
   - 8 critiques (fonction autocomplete, injections dans cjxpost.php, mclients.php, mdevis.php)
   - 6 moyennes (cjxdevis.php, cjxexport.php, cjximport.php, mexpxls.php)
2. **Fonctionnalité Réactivation devis** : Bouton permettant de réactiver les devis archivés (statut 20 → 1)

**v2.0.3 (21 octobre 2025)**
1. **Gestion multi-contacts par client** : Table `clients_contacts` opérationnelle
2. **Interface CRUD complète** : Modale Bootstrap avec création/modification/suppression de contacts
3. **Contrôleur AJAX `cjxcontacts.php`** : 5 endpoints sécurisés avec requêtes préparées
4. **Intégration dans les devis** : Sélecteur de contact avec affichage des infos en lecture seule
5. **Gestion automatique du contact principal** : Un seul contact principal par client
6. **Soft delete** : Prévention de la suppression du dernier contact actif

### 🎯 Prochaines étapes prioritaires
1. **Nettoyage BDD** : Supprimer les anciens champs contact de la table `clients` (après validation)
2. **Migration PROD vers IN4** : Export/Import des containers vers `pra-front` et `maria4`
3. **Fonctionnalités métier** : Points 8, 14, 16, 21 (voir sections ci-dessus)
4. **Sécurité XSS** : Audit et correction des failles XSS potentielles
5. **Tests** : Mise en place de tests automatisés de sécurité

---

*Document mis à jour le 21 octobre 2025*
*Version 2.0.3 - Gestion multi-contacts*