refactor(api): découpe main.py en routeurs par domaine

main.py comptait 829 lignes et regroupait 9 domaines fonctionnels.
Il ne fait plus que l'assemblage de l'application (configuration,
middlewares, montage des routeurs), soit 115 lignes.

- routers/ : un module par domaine, chacun déclarant sa propre
  dépendance d'authentification
- domain.py : enums UserRole et AuditAction, mapping MONITO_TABLES ;
  les rôles étaient jusqu'ici répétés en dur à deux endroits
- helpers.py : conversion des lignes pyodbc, écriture du journal
- rate_limit.py : limiteur partagé, isolé pour éviter un import
  circulaire entre main.py et le routeur d'authentification

Les codes HTTP littéraux (404, 401, 400, 201) passent aux constantes
fastapi.status, comme le faisait déjà auth.py. Les actions du journal
d'audit passent en paramètre SQL au lieu d'être concaténées.

Aucune route modifiée : la comparaison des specs OpenAPI avant/après
confirme que les 26 URL existantes sont identiques.

conftest patchait main.get_cursor ; chaque routeur important désormais
get_cursor dans son propre espace de noms, la fixture remplace le nom
dans tous les modules concernés.
This commit is contained in:
2026-08-15 14:28:45 +02:00
parent 7b3c91509f
commit 934e669774
14 changed files with 1165 additions and 745 deletions
+51
View File
@@ -0,0 +1,51 @@
# ============================================================
# domain.py — Constantes et énumérations du domaine Data Sentinel
# ============================================================
from enum import Enum
class UserRole(str, Enum):
"""Rôles applicatifs — miroir de la contrainte CK_USER_ROLE en base."""
ADMIN = "Admin"
SUPERVISEUR = "Superviseur"
CONSULTANT = "Consultant"
class AuditAction(str, Enum):
"""Actions tracées dans JOURNAL_AUDIT."""
LOGIN = "LOGIN"
CREATE_USER = "CREATE_USER"
UPDATE_USER = "UPDATE_USER"
DELETE_USER = "DELETE_USER"
RESET_PASSWORD = "RESET_PASSWORD"
CREATE_REFERENTIEL = "CREATE_REFERENTIEL"
UPDATE_REFERENTIEL = "UPDATE_REFERENTIEL"
DELETE_REFERENTIEL = "DELETE_REFERENTIEL"
# ============================================================
# Mapping id_monito → table SQL dédiée
# Pour ajouter un monitoring : ajouter une entrée ici.
# ============================================================
MONITO_TABLES: dict[int, str] = {
1: "MONITO_TIERS_PAYEURS",
2: "MONITO_PRELEVEMENT_SANS_RIB",
3: "MONITO_DOM_TOM_TVA",
4: "MONITO_ZONE_VENTES_CRM",
5: "MONITO_MULTI_MODES_REGLEMENT",
6: "MONITO_SANS_SIRET",
7: "MONITO_SANS_CONTREPARTIE",
}
# Colonnes de recherche textuelle par table (pour le filtre search)
SEARCH_COLS: dict[str, list[str]] = {
"MONITO_TIERS_PAYEURS": ["CT_Intitule", "origineClient", "STE"],
"MONITO_PRELEVEMENT_SANS_RIB": ["CT_Intitule", "STE"],
"MONITO_DOM_TOM_TVA": ["CT_Intitule", "agence", "CT_Pays"],
"MONITO_ZONE_VENTES_CRM": ["name", "Agence", "xefi_sagedatabase"],
"MONITO_MULTI_MODES_REGLEMENT": ["CT_Intitule", "Agence"],
"MONITO_SANS_SIRET": ["ct_intitule", "agence", "ct_num"],
"MONITO_SANS_CONTREPARTIE": ["agence", "EC_Piece", "CT_NumCont"],
}