Files
geo/app/docs/GESTION-SECTEURS.md
pierre 1018b86537 feat: Gestion des secteurs et migration v3.0.4+304
- Ajout système complet de gestion des secteurs avec contours géographiques
- Import des contours départementaux depuis GeoJSON
- API REST pour la gestion des secteurs (/api/sectors)
- Service de géolocalisation pour déterminer les secteurs
- Migration base de données avec tables x_departements_contours et sectors_adresses
- Interface Flutter pour visualisation et gestion des secteurs
- Ajout thème sombre dans l'application
- Corrections diverses et optimisations

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-07 11:01:45 +02:00

15 KiB

Gestion des Secteurs et de la Carte

Ce document centralise toutes les règles de gestion des secteurs et de la carte dans l'application Geosector.

Dernière mise à jour : Décembre 2024 - Améliorations de la détection d'adjacence et de l'ergonomie du drag

Table des matières

  1. Vue d'ensemble
  2. Structure des données
  3. Modes de la carte
  4. Création d'un secteur
  5. Gestion des secteurs adjacents
  6. Modification d'un secteur
  7. Suppression d'un secteur
  8. Affichage des secteurs
  9. Affichage des passages
  10. Permissions et rôles
  11. Synchronisation API/Hive
  12. Interactions utilisateur
  13. Bonnes pratiques

Vue d'ensemble

La carte administrative (AdminMapPage) permet aux administrateurs de gérer les secteurs géographiques d'une opération. Chaque secteur est un polygone défini par des coordonnées GPS et peut contenir des passages (adresses à visiter).

Technologies utilisées

  • flutter_map avec MapBox pour l'affichage de la carte
  • Hive pour le stockage local des données
  • ValueListenableBuilder pour la mise à jour réactive de l'interface

Structure des données

SectorModel

{
  id: int,                  // Identifiant unique
  libelle: String,          // Nom du secteur
  color: String,            // Couleur hexadécimale (#RRGGBB)
  sector: String            // Coordonnées "lat/lng#lat/lng#..."
}

PassageModel

{
  id: int,
  fk_sector: int,          // ID du secteur
  fk_user: int,            // ID de l'utilisateur assigné
  fk_type: int,            // Type de passage (1-6)
  gps_lat: String,         // Latitude
  gps_lng: String,         // Longitude
  numero: String,          // Numéro de rue
  rue: String,             // Nom de la rue
  ville: String,           // Ville
  // ... autres champs
}

Types de passages

  • 1 : Effectué (vert)
  • 2 : À finaliser (orange)
  • 3 : Refusé (rouge)
  • 4 : Don (bleu)
  • 5 : Lot (violet)
  • 6 : Maison vide (gris)

Modes de la carte

La carte peut être dans l'un des modes suivants :

MapMode.view (Mode visualisation)

  • Mode par défaut
  • Permet de naviguer sur la carte
  • Affiche les secteurs et passages
  • Permet la sélection d'un secteur via la combobox

MapMode.drawing (Mode création)

  • Activé par le bouton "Créer un secteur"
  • Affiche une carte d'aide explicative
  • Permet de dessiner un nouveau secteur en cliquant sur la carte
  • Points verts pour le premier point, bleus pour les suivants
  • Fermeture du polygone en cliquant sur le premier point

MapMode.editing (Mode édition)

  • Activé par le bouton "Modifier un secteur"
  • Permet de modifier les contours d'un secteur existant
  • Sélectionner un secteur par clic ou via la combobox puis cliquer "Modifier"
  • Points orange draggables avec magnétisme automatique
  • Ajout de points via les points intermédiaires gris
  • Suppression de points avec clic droit ou Ctrl+clic

MapMode.deleting (Mode suppression)

  • Activé par le bouton "Supprimer un secteur"
  • Affiche une carte d'aide avec avertissements
  • Permet de sélectionner un secteur à supprimer en cliquant dessus
  • Le secteur sélectionné apparaît en rouge

Création d'un secteur

Processus de création

  1. Dessin du secteur

    • L'administrateur clique sur le bouton "Créer un secteur"
    • Il dessine le contour en cliquant sur la carte (minimum 3 points)
    • Il ferme le polygone en cliquant sur le premier point
  2. Dialog de création

    • Nom du secteur (obligatoire)
    • Couleur du secteur (sélection dans une palette)
    • Sélection des membres assignés (au moins un obligatoire)
  3. Envoi à l'API

    {
      "id": 0,
      "libelle": "Nom du secteur",
      "color": "#2196F3",
      "sector": "lat/lng#lat/lng#...",
      "operation_id": 3124,
      "fk_entite": 5,
      "users": [9999980, 9999985]
    }
    
  4. Réponse de l'API

    {
      "status": "success",
      "sector": { /* ou sector_id */ },
      "passages_sector": [...],
      "passages_created": 86,
      "passages_integrated": 0,
      "users_sectors": [...],
      "warning": "Avertissement si débordement départemental",
      "intersecting_departments": [
        {
          "code_dept": "35",
          "nom_dept": "Ille-et-Vilaine",
          "percentage_overlap": 85.2
        }
      ]
    }
    
  5. Traitement de la réponse

    • Le secteur est sauvegardé dans Hive
    • Les passages sont créés avec les coordonnées GPS
    • Les associations utilisateur-secteur sont traitées
    • La carte se centre sur le nouveau secteur

Règles de création

  • Un secteur doit avoir au moins 3 points
  • Le nom est obligatoire
  • Au moins un membre doit être assigné
  • Les coordonnées sont au format "latitude/longitude"
  • Le dernier point doit fermer le polygone
  • Les secteurs adjacents sont automatiquement corrigés (voir section dédiée)

Gestion des secteurs adjacents

Vue d'ensemble

L'application gère automatiquement la création de secteurs adjacents (partageant une bordure commune) sans générer d'erreur de chevauchement. Cette fonctionnalité est cruciale pour permettre un découpage précis du territoire.

Correction automatique des points

Méthode _correctPointsForAdjacency

Cette méthode est appelée automatiquement lors de :

  • La validation d'un nouveau secteur (création)
  • La validation d'un secteur modifié (modification)

Paramètres de correction :

  • Distance de détection : 10 mètres
  • Décalage de correction : 2 mètres vers l'intérieur
  • Décalage fort : 5 mètres (si chevauchement persistant)

Processus en deux passes :

  1. Première passe - Détection et correction des segments adjacents

    // Pour chaque segment du nouveau secteur
    // Vérifier s'il est proche d'un segment existant
    // Si oui, corriger les deux points du segment
    
  2. Deuxième passe - Vérification et correction forte

    // Appel à _ensureNoIntersection
    // Si chevauchement détecté → _applyStrongerCorrection
    

Calcul du décalage vers l'intérieur

Méthode _offsetPointInward

Principe :

  • Calcule la bissectrice des segments adjacents
  • Utilise le produit vectoriel pour déterminer la direction intérieure
  • Applique un décalage en tenant compte de la latitude

Formule de conversion :

offsetDegreesLat = offsetMeters / 111320.0
offsetDegreesLng = offsetMeters / (111320.0 * cos(latitude))

Détection intelligente des chevauchements

Méthode _doPolygonsOverlap

Tolérance d'adjacence : 2 mètres

Règles de détection améliorées :

  1. Points intérieurs : Un point est considéré à l'intérieur seulement s'il est à plus de 2m du bord
  2. Vertices partagés : Les vertices à moins de 5m de distance sont considérés comme partagés et ignorés
  3. Segments adjacents : Deux segments alignés et proches ne sont pas considérés comme un chevauchement
  4. Seuil de détection : Il faut au moins 3 points intérieurs ou 3 intersections pour détecter un chevauchement réel
  5. Exclusion du secteur en cours : Lors de la modification, le secteur lui-même est exclu de la détection

Méthode _areSegmentsAdjacent

Détermine si deux segments sont adjacents (partagent une partie commune) :

  • Vérifie l'alignement des segments
  • Vérifie la proximité des points aux lignes opposées
  • Retourne true si les segments sont sur la même ligne

Magnétisme automatique

Lors de la sélection d'un secteur pour modification :

  • Application automatique du magnétisme aux points proches
  • Visualisation immédiate des ajustements
  • Message d'information si des points ont été magnétisés

Exemple de création de secteurs adjacents

Secteur A (existant) :     Nouveau secteur B :
+--------+                 +--------+
|        |                 |        |
|   A    | <-- bordure --> |   B    |
|        |     commune     |        |
+--------+                 +--------+

Résultat après correction automatique :

  • Les points de B sur la bordure commune sont décalés de 2m vers l'intérieur
  • Aucune erreur de chevauchement
  • Les secteurs restent visuellement adjacents

Messages utilisateur

  • Correction appliquée : "Les points ont été ajustés automatiquement pour éviter les chevauchements" (bleu)
  • Chevauchement détecté : "Le nouveau secteur chevauche avec le secteur [nom]" (rouge)
  • Logging détaillé : En cas de chevauchement détecté, les coordonnées des zones problématiques sont loggées

Modification d'un secteur

Processus de modification

  1. Sélection du secteur

    • Via la combobox ou clic sur la carte
    • Bouton "Modifier" dans la barre d'outils
  2. Mode édition

    • Application automatique du magnétisme dès la sélection
    • Points draggables instantanément (clic et drag immédiat)
    • Points orange avec zone de détection élargie (50x50px)
    • Ajout de points via les points intermédiaires gris
    • Suppression avec clic droit ou Ctrl+clic
    • Désactivation du drag de la carte pendant le déplacement d'un point
  3. Validation

    • Mêmes vérifications que pour la création
    • Application de _correctPointsForAdjacency avec exclusion du secteur en cours
    • Dialog pour modifier nom, couleur et membres
    • Les membres déjà affectés sont automatiquement présélectionnés
    • Affichage d'un dialog récapitulatif avec statistiques

Règles de modification

  • Minimum 3 points maintenu
  • Correction automatique des adjacences
  • Même processus de validation que la création
  • Les passages sont automatiquement réaffectés selon le nouveau contour

Suppression d'un secteur

Processus de suppression

  1. Sélection du secteur

    • L'administrateur clique sur "Supprimer un secteur"
    • Il clique sur le secteur à supprimer (surbrillance rouge)
  2. Dialog de confirmation

    • Affichage du nom du secteur
    • Avertissements sur les conséquences
  3. Règles de suppression des passages

    • Passages "à finaliser" (type 2) sans nom d'habitant → supprimés
    • Autres passages → conservés mais réassignés au secteur 0
  4. Réponse de l'API

    {
      "status": "success",
      "passages_deleted": 45,
      "passages_reassigned": 125
    }
    
  5. Mise à jour locale

    • Suppression du secteur de Hive
    • Mise à jour des passages selon les règles
    • Actualisation automatique de la carte

Affichage des secteurs

Représentation visuelle

  • Polygones colorés avec transparence (30% en normal, 50% si sélectionné)
  • Bordure de la couleur du secteur (épaisseur 2px, 3px si sélectionné)
  • Mode suppression : secteur en rouge avec bordure épaisse (4px)

Filtrage par secteur

  • Combobox en haut à gauche
  • "Tous les secteurs" par défaut
  • Sélection d'un secteur → zoom et centrage automatique
  • Filtrage des passages affichés

Affichage des passages

Représentation visuelle

  • Marqueurs circulaires de 14x14 pixels
  • Couleur principale selon le type de passage
  • Bordure blanche de 1px
  • Cliquables pour afficher les détails

Conditions d'affichage

  • Coordonnées GPS valides (gps_lat et gps_lng)
  • Type de passage reconnu (1-6)
  • Appartenance au secteur sélectionné (si filtre actif)

Informations au clic

  • Adresse complète
  • Nom de l'habitant (si disponible)
  • Type de passage
  • Informations de règlement (si applicable)
  • Boutons d'édition/suppression

Permissions et rôles

Accès à la carte administrative

  • Rôle minimum requis : Admin Amicale (rôle > 1)
  • Rôle 1 (Membre) : Pas d'accès à la carte admin
  • Rôle 2+ (Admin) : Accès complet aux fonctionnalités

Actions autorisées

  • Création de secteur : Admin+
  • Modification de secteur : Admin+
  • Suppression de secteur : Admin+
  • Visualisation : Admin+

Synchronisation API/Hive

Principe "API First"

  1. Toute modification passe d'abord par l'API
  2. En cas de succès, mise à jour de Hive
  3. En cas d'échec, aucune modification locale

Flux de données

Chargement initial

API (login) → Secteurs/Passages → Hive → ValueListenableBuilder → UI

Création de secteur

UI → API → Réponse (secteur + passages) → Hive → Auto-refresh UI

Suppression de secteur

UI → API → Réponse (stats) → Mise à jour Hive → Auto-refresh UI

Gestion des erreurs

  • Affichage de SnackBar avec message d'erreur
  • Pas de modification locale en cas d'échec API
  • Log des erreurs pour debug

Performance

  • Utilisation de box caching dans les repositories
  • ValueListenableBuilder pour éviter les rebuilds inutiles
  • Chargement asynchrone des données

Interactions utilisateur

Gestion du drag des points

Technologie utilisée : Listener avec onPointerDown/onPointerMove/onPointerUp

Avantages :

  • Démarrage instantané du drag au clic (onPointerDown)
  • Pas de conflit avec les gestes de la carte
  • Conversion directe des coordonnées écran en coordonnées géographiques

Interactions supportées :

  • Clic gauche : Démarre le drag immédiatement
  • Clic droit / Ctrl+clic : Supprime le point
  • Clic sur premier point (mode dessin) : Ferme le polygone si 3+ points
  • Drag : Déplace le point avec magnétisme en temps réel

Dialog récapitulatif

Après chaque opération (création/modification/suppression), un dialog affiche :

  • Statistiques des passages : créés, mis à jour, orphelins, total
  • Avertissements départementaux : si le secteur est à cheval sur plusieurs départements
  • Icônes et couleurs adaptées selon le type d'opération

Bonnes pratiques

Pour les développeurs

  1. Toujours passer par l'API pour les modifications
  2. Utiliser les repositories pour l'accès aux données
  3. Ne pas faire de setState dans les ValueListenableBuilder
  4. Gérer les erreurs avec ApiException
  5. Valider les données avant envoi à l'API
  6. Logger les actions importantes pour le debug
  7. Utiliser les mêmes méthodes de validation pour création et modification :
    • _correctPointsForAdjacency pour la correction automatique
    • _doPolygonsOverlap pour la détection de chevauchement
    • _isValidPolygon pour la validation de base
  8. Sauvegarder le contexte parent avant d'ouvrir des dialogs pour éviter les erreurs de contexte
  9. Implémenter le chargement des associations (ex: UserSectorModel) pour présélectionner les données

Pour les utilisateurs

  1. Dessiner des secteurs cohérents (pas de croisements)
  2. Nommer clairement les secteurs
  3. Assigner les bons membres dès la création
  4. Vérifier avant suppression (action irréversible)
  5. Utiliser des couleurs distinctes pour différencier les secteurs
  6. Pour les secteurs adjacents :
    • Dessiner normalement sans se soucier de la précision
    • Le système ajuste automatiquement les bordures
    • Vérifier le résultat après la correction automatique
  7. Pour la modification des secteurs :
    • Cliquer directement sur un point pour le déplacer (pas besoin de maintenir)
    • Utiliser les points gris intermédiaires pour ajouter des sommets
    • Clic droit ou Ctrl+clic pour supprimer un point
    • Le magnétisme s'applique automatiquement aux bordures adjacentes