"""Route accueil — écran dynamique par rôle.""" from fastapi import APIRouter, Depends from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from app.core.database import get_db from app.core.security import get_current_membre from app.models.affectation import Affectation from app.models.poste import Poste from app.models.groupe import Groupe from app.models.poste_module import PosteModule from app.schemas.schemas import AccueilResponse, ModuleTuile, MembrePublic router = APIRouter(prefix="/accueil", tags=["Accueil"]) # ── Définition des modules ── MODULES_CONSULTATION = [ ModuleTuile(code="C1", nom="Rapports PDF", description="Finances, PV, résolutions", icone="📄", couleur="blue"), ModuleTuile(code="C2", nom="Événements", description="Anniversaires et événements", icone="📅", couleur="green"), ModuleTuile(code="C4", nom="Littérature", description="Inventaire et prix", icone="📚", couleur="purple"), ModuleTuile(code="C5", nom="Décisions en cours", description="Suivi réunion d'affaires", icone="📌", couleur="red"), ModuleTuile(code="C6", nom="Votes ouverts", description="Conscience de groupe", icone="🗳️", couleur="indigo"), ModuleTuile(code="C7", nom="Mon profil", description="Modifier, PIN, notifications", icone="👤", couleur="gray"), ModuleTuile(code="C8", nom="Propositions", description="Soumettre, seconder, résolutions", icone="📋", couleur="orange"), ModuleTuile(code="C9", nom="Postes à pourvoir", description="Postes disponibles, candidature", icone="🙋", couleur="yellow"), ModuleTuile(code="C10", nom="État financier", description="Résultats et transactions", icone="📊", couleur="blue"), ] MODULES_PAR_CODE = {m.code: m for m in MODULES_CONSULTATION} # Modules de saisie visibles par TOUS les membres MODULES_SAISIE_TOUS = [ ModuleTuile(code="S1", nom="Collecte 7e", description="Saisir le panier", icone="💰", couleur="green"), ModuleTuile(code="S5", nom="Dépense", description="Soumettre une dépense", icone="💸", couleur="red"), ] # Modules de saisie par poste MODULES_SAISIE = { "Trésorier(ière)": [ ModuleTuile(code="S1T", nom="Trésorerie", description="Réceptions, dépôts, soldes", icone="🏦", couleur="green"), ModuleTuile(code="M4", nom="Envoi contributions", description="District, région, BSG", icone="📮", couleur="blue"), ], "Secrétaire": [ ModuleTuile(code="M1", nom="Rédiger PV", description="Procès-verbal", icone="📝", couleur="blue"), ModuleTuile(code="M2", nom="Présences", description="Réunion d'affaires", icone="✅", couleur="green"), ], "RSG": [ ModuleTuile(code="M3", nom="Rapport RSG", description="Compte-rendu district", icone="📋", couleur="blue"), ], "RSG Substitut(e)": [ ModuleTuile(code="M3", nom="Rapport RSG", description="Compte-rendu district", icone="📋", couleur="blue"), ], "Animateur(trice)": [ ModuleTuile(code="S4", nom="Rapport réunion", description="Thème et annonces", icone="🎤", couleur="purple"), ], "Responsable littérature": [ ModuleTuile(code="S3", nom="Vente littérature", description="Enregistrer une vente", icone="📖", couleur="purple"), ModuleTuile(code="M5", nom="Ajuster inventaire", description="Mettre à jour le stock", icone="📦", couleur="orange"), ], "Responsable jetons": [ ModuleTuile(code="S2", nom="Remise jeton", description="Enregistrer un jeton", icone="🏅", couleur="yellow"), ModuleTuile(code="M6", nom="Commander jetons", description="Commander à l'Intergroupe", icone="📦", couleur="orange"), ], } MODULES_GESTION = [ ModuleTuile(code="G2", nom="Gestion des membres", description="Membres, invitations, désactivation", icone="👥", couleur="blue"), ModuleTuile(code="G6", nom="Lancer un sondage", description="Conscience de groupe", icone="📊", couleur="indigo"), ModuleTuile(code="G9", nom="Paramètres groupe", description="Nom, horaire, adresse", icone="🔧", couleur="gray"), ModuleTuile(code="G11", nom="Gestion des mandats", description="Affecter, terminer, rotations", icone="🎯", couleur="purple"), ModuleTuile(code="G12", nom="Gestion des postes", description="Postes, candidatures, accès", icone="📋", couleur="purple"), ] for _modules in [MODULES_SAISIE_TOUS, MODULES_GESTION, *MODULES_SAISIE.values()]: for _m in _modules: MODULES_PAR_CODE[_m.code] = _m @router.get("/", response_model=AccueilResponse) async def accueil( membre=Depends(get_current_membre), db: AsyncSession = Depends(get_db), ): """Écran d'accueil dynamique — retourne les modules selon les postes du membre.""" # Récupérer les affectations actives result = await db.execute( select(Affectation).join(Poste).where( Affectation.membre_id == membre.id, Affectation.statut == "actif", ) ) affectations = result.scalars().all() postes_noms = [] postes_categories = [] poste_ids = [] for a in affectations: poste = await db.get(Poste, a.poste_id) if poste: postes_noms.append(poste.nom) postes_categories.append(poste.categorie) poste_ids.append(poste.id) # Modules de consultation : toujours visibles modules_consultation = MODULES_CONSULTATION # Modules de saisie : collecte pour tous + modules par poste modules_saisie = list(MODULES_SAISIE_TOUS) codes_vus = {"S1", "S5"} result = await db.execute(select(PosteModule).where(PosteModule.poste_id.in_(poste_ids))) if poste_ids else None modules_configures = result.scalars().all() if result else [] if modules_configures: codes = sorted({pm.module_code for pm in modules_configures}) for code in codes: m = MODULES_PAR_CODE.get(code) if m and not code.startswith("G") and m.code not in codes_vus: modules_saisie.append(m) codes_vus.add(m.code) else: for nom_poste in postes_noms: for m in MODULES_SAISIE.get(nom_poste, []): if m.code not in codes_vus: modules_saisie.append(m) codes_vus.add(m.code) # Modules de gestion : seulement si exécutif if modules_configures: modules_gestion = [ MODULES_PAR_CODE[code] for code in sorted({pm.module_code for pm in modules_configures}) if code.startswith("G") and code in MODULES_PAR_CODE ] else: modules_gestion = MODULES_GESTION if "executif" in postes_categories else [] # Info groupe pour le frontend groupe = await db.get(Groupe, membre.groupe_id) groupe_info = None if groupe: groupe_info = { "id": str(groupe.id), "nom": groupe.nom, "jour_reunion": groupe.jour_reunion, "heure_reunion": groupe.heure_reunion.strftime("%H:%M") if groupe.heure_reunion else None, "adresse_local": groupe.adresse_local, } return AccueilResponse( membre=MembrePublic.model_validate(membre), postes=postes_noms, modules_consultation=modules_consultation, modules_saisie=modules_saisie, modules_gestion=modules_gestion, groupe=groupe_info, )