groupe-meditation/backend/app/routers/accueil.py

156 lines
7.2 KiB
Python

"""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,
)