2026-03-04 14:01:00 -05:00
|
|
|
"""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
|
2026-05-25 17:39:38 -04:00
|
|
|
from app.core.security import get_current_membre, is_sysadmin
|
2026-03-04 14:01:00 -05:00
|
|
|
from app.models.affectation import Affectation
|
|
|
|
|
from app.models.poste import Poste
|
2026-04-17 04:04:04 -04:00
|
|
|
from app.models.groupe import Groupe
|
2026-05-15 16:41:17 -04:00
|
|
|
from app.models.poste_module import PosteModule
|
2026-03-04 14:01:00 -05:00
|
|
|
from app.schemas.schemas import AccueilResponse, ModuleTuile, MembrePublic
|
|
|
|
|
|
|
|
|
|
router = APIRouter(prefix="/accueil", tags=["Accueil"])
|
|
|
|
|
|
|
|
|
|
# ── Définition des modules ──
|
|
|
|
|
MODULES_CONSULTATION = [
|
2026-04-17 04:04:04 -04:00
|
|
|
ModuleTuile(code="C1", nom="Rapports PDF", description="Finances, PV, résolutions", icone="📄", couleur="blue"),
|
2026-05-15 16:41:17 -04:00
|
|
|
ModuleTuile(code="C2", nom="Événements", description="Anniversaires et événements", icone="📅", couleur="green"),
|
2026-03-04 14:01:00 -05:00
|
|
|
ModuleTuile(code="C4", nom="Littérature", description="Inventaire et prix", icone="📚", couleur="purple"),
|
2026-05-25 17:39:38 -04:00
|
|
|
ModuleTuile(code="C5", nom="Gouvernance", description="Décisions du groupe", icone="📌", couleur="red"),
|
2026-03-04 14:01:00 -05:00
|
|
|
ModuleTuile(code="C7", nom="Mon profil", description="Modifier, PIN, notifications", icone="👤", couleur="gray"),
|
2026-05-15 16:41:17 -04:00
|
|
|
ModuleTuile(code="C9", nom="Postes à pourvoir", description="Postes disponibles, candidature", icone="🙋", couleur="yellow"),
|
2026-06-01 14:13:44 -04:00
|
|
|
ModuleTuile(code="C11", nom="Charte d'utilisation", description="Outil de service et limites", icone="🧭", couleur="indigo"),
|
|
|
|
|
ModuleTuile(code="C13", nom="Confidentialité", description="Données, accès et journal", icone="🔒", couleur="gray"),
|
2026-05-31 16:50:53 -04:00
|
|
|
ModuleTuile(code="C12", nom="Mode papier", description="Formulaires de reprise en main", icone="🖨️", couleur="gray"),
|
2026-05-25 17:39:38 -04:00
|
|
|
ModuleTuile(code="S1T", nom="Trésorerie", description="État des résultats, soldes, registre", icone="🏦", couleur="green"),
|
2026-04-17 04:04:04 -04:00
|
|
|
]
|
|
|
|
|
|
2026-05-15 16:41:17 -04:00
|
|
|
MODULES_PAR_CODE = {m.code: m for m in MODULES_CONSULTATION}
|
Intégrer rencontres et assemblées pilotées par tuiles
Refond les pages Rencontres et Assemblées autour de tuiles ouvrables avec actions locales, PDF serveur, ventes, collectes, présences, décisions, postes et contributions.
Ajoute les invitations publiques d'assemblée en lecture seule avec lien expirant, l'adoption formelle du rapport du trésorier avec proposeur/secondeur, et bloque les contributions tant que ce rapport n'est pas adopté.
Uniformise la navigation et les entêtes, retire les modules redondants des contextes, ajoute la création de comptes membres par exécutif et les données démo reliées aux nouveaux processus.
Ce commit capture un lot fonctionnel important; une refactorisation ciblée du module Assemblées, puis Trésorerie/Gouvernance, est maintenant pertinente pour isoler les règles métier et faciliter les tests.
2026-05-31 09:02:02 -04:00
|
|
|
MODULES_PAR_CODE["S0"] = ModuleTuile(code="S0", nom="Rencontres", description="Saisies, ventes, jetons et rapports", icone="🗓️", couleur="green")
|
|
|
|
|
MODULES_PAR_CODE["M0"] = ModuleTuile(code="M0", nom="Assemblées", description="Présences, procès-verbal et rapports", icone="🏛️", couleur="indigo")
|
2026-05-25 17:39:38 -04:00
|
|
|
MODULES_PAR_CODE["S1"] = ModuleTuile(code="S1", nom="Collecte 7e", description="Saisir le panier", icone="💰", couleur="green")
|
2026-05-15 16:41:17 -04:00
|
|
|
|
2026-04-17 04:04:04 -04:00
|
|
|
MODULES_SAISIE_TOUS = [
|
|
|
|
|
ModuleTuile(code="S5", nom="Dépense", description="Soumettre une dépense", icone="💸", couleur="red"),
|
2026-03-04 14:01:00 -05:00
|
|
|
]
|
|
|
|
|
|
|
|
|
|
# Modules de saisie par poste
|
|
|
|
|
MODULES_SAISIE = {
|
|
|
|
|
"Trésorier(ière)": [
|
2026-05-26 08:15:28 -04:00
|
|
|
ModuleTuile(code="M4", nom="Donner au suivant", description="Destinataires et contributions", icone="📮", couleur="blue"),
|
2026-03-04 14:01:00 -05:00
|
|
|
],
|
|
|
|
|
"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": [
|
2026-06-01 14:42:37 -04:00
|
|
|
ModuleTuile(code="M3", nom="Services", description="District, région, sujets et suivis", icone="📋", couleur="blue"),
|
2026-03-04 14:01:00 -05:00
|
|
|
],
|
|
|
|
|
"RSG Substitut(e)": [
|
2026-06-01 14:42:37 -04:00
|
|
|
ModuleTuile(code="M3", nom="Services", description="District, région, sujets et suivis", icone="📋", couleur="blue"),
|
2026-03-04 14:01:00 -05:00
|
|
|
],
|
Intégrer rencontres et assemblées pilotées par tuiles
Refond les pages Rencontres et Assemblées autour de tuiles ouvrables avec actions locales, PDF serveur, ventes, collectes, présences, décisions, postes et contributions.
Ajoute les invitations publiques d'assemblée en lecture seule avec lien expirant, l'adoption formelle du rapport du trésorier avec proposeur/secondeur, et bloque les contributions tant que ce rapport n'est pas adopté.
Uniformise la navigation et les entêtes, retire les modules redondants des contextes, ajoute la création de comptes membres par exécutif et les données démo reliées aux nouveaux processus.
Ce commit capture un lot fonctionnel important; une refactorisation ciblée du module Assemblées, puis Trésorerie/Gouvernance, est maintenant pertinente pour isoler les règles métier et faciliter les tests.
2026-05-31 09:02:02 -04:00
|
|
|
"Animateur(trice)": [],
|
2026-03-04 14:01:00 -05:00
|
|
|
"Responsable littérature": [
|
|
|
|
|
ModuleTuile(code="S3", nom="Vente littérature", description="Enregistrer une vente", icone="📖", couleur="purple"),
|
2026-05-31 19:28:55 -04:00
|
|
|
ModuleTuile(code="M5", nom="Gestion des inventaires", description="Littérature et jetons", icone="📦", couleur="orange"),
|
2026-03-04 14:01:00 -05:00
|
|
|
],
|
|
|
|
|
"Responsable jetons": [
|
|
|
|
|
ModuleTuile(code="S2", nom="Remise jeton", description="Enregistrer un jeton", icone="🏅", couleur="yellow"),
|
2026-05-31 19:28:55 -04:00
|
|
|
ModuleTuile(code="M5", nom="Gestion des inventaires", description="Littérature et jetons", icone="📦", couleur="orange"),
|
2026-03-04 14:01:00 -05:00
|
|
|
],
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MODULES_GESTION = [
|
2026-05-15 16:41:17 -04:00
|
|
|
ModuleTuile(code="G2", nom="Gestion des membres", description="Membres, invitations, désactivation", icone="👥", couleur="blue"),
|
2026-03-04 14:01:00 -05:00
|
|
|
ModuleTuile(code="G9", nom="Paramètres groupe", description="Nom, horaire, adresse", icone="🔧", couleur="gray"),
|
2026-05-15 16:41:17 -04:00
|
|
|
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"),
|
2026-05-25 17:39:38 -04:00
|
|
|
ModuleTuile(code="G13", nom="Journal", description="Changements enregistrés", icone="🧾", couleur="gray"),
|
2026-03-04 14:01:00 -05:00
|
|
|
]
|
2026-05-31 22:10:09 -04:00
|
|
|
MODULE_SYSADMIN = ModuleTuile(code="G14", nom="Gestion des groupes", description="Groupes et démonstration", icone="🏷️", couleur="indigo")
|
2026-03-04 14:01:00 -05:00
|
|
|
|
2026-05-15 16:41:17 -04:00
|
|
|
for _modules in [MODULES_SAISIE_TOUS, MODULES_GESTION, *MODULES_SAISIE.values()]:
|
|
|
|
|
for _m in _modules:
|
|
|
|
|
MODULES_PAR_CODE[_m.code] = _m
|
|
|
|
|
|
2026-03-04 14:01:00 -05:00
|
|
|
|
|
|
|
|
@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."""
|
2026-05-25 17:39:38 -04:00
|
|
|
if is_sysadmin(membre):
|
|
|
|
|
modules_saisie_sysadmin = []
|
|
|
|
|
codes_vus = set()
|
Intégrer rencontres et assemblées pilotées par tuiles
Refond les pages Rencontres et Assemblées autour de tuiles ouvrables avec actions locales, PDF serveur, ventes, collectes, présences, décisions, postes et contributions.
Ajoute les invitations publiques d'assemblée en lecture seule avec lien expirant, l'adoption formelle du rapport du trésorier avec proposeur/secondeur, et bloque les contributions tant que ce rapport n'est pas adopté.
Uniformise la navigation et les entêtes, retire les modules redondants des contextes, ajoute la création de comptes membres par exécutif et les données démo reliées aux nouveaux processus.
Ce commit capture un lot fonctionnel important; une refactorisation ciblée du module Assemblées, puis Trésorerie/Gouvernance, est maintenant pertinente pour isoler les règles métier et faciliter les tests.
2026-05-31 09:02:02 -04:00
|
|
|
for module in [MODULES_PAR_CODE["S0"], MODULES_PAR_CODE["M0"], *MODULES_SAISIE_TOUS, *[m for mods in MODULES_SAISIE.values() for m in mods]]:
|
2026-05-25 17:39:38 -04:00
|
|
|
if module.code not in codes_vus:
|
|
|
|
|
modules_saisie_sysadmin.append(module)
|
|
|
|
|
codes_vus.add(module.code)
|
|
|
|
|
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,
|
|
|
|
|
"assemblee_affaires_ordre": groupe.assemblee_affaires_ordre,
|
|
|
|
|
"adresse_local": groupe.adresse_local,
|
|
|
|
|
}
|
|
|
|
|
return AccueilResponse(
|
|
|
|
|
membre=MembrePublic.model_validate(membre),
|
|
|
|
|
postes=["Sysadmin"],
|
|
|
|
|
est_executif=True,
|
|
|
|
|
modules_consultation=MODULES_CONSULTATION,
|
|
|
|
|
modules_saisie=modules_saisie_sysadmin,
|
2026-05-31 22:10:09 -04:00
|
|
|
modules_gestion=[MODULE_SYSADMIN, *MODULES_GESTION],
|
2026-05-25 17:39:38 -04:00
|
|
|
groupe=groupe_info,
|
|
|
|
|
)
|
|
|
|
|
|
2026-03-04 14:01:00 -05:00
|
|
|
# Récupérer les affectations actives
|
|
|
|
|
result = await db.execute(
|
|
|
|
|
select(Affectation).join(Poste).where(
|
|
|
|
|
Affectation.membre_id == membre.id,
|
2026-05-31 18:12:26 -04:00
|
|
|
Affectation.groupe_id == membre.groupe_id,
|
2026-03-04 14:01:00 -05:00
|
|
|
Affectation.statut == "actif",
|
2026-05-31 18:12:26 -04:00
|
|
|
Poste.groupe_id == membre.groupe_id,
|
2026-03-04 14:01:00 -05:00
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
affectations = result.scalars().all()
|
|
|
|
|
|
|
|
|
|
postes_noms = []
|
|
|
|
|
postes_categories = []
|
2026-05-15 16:41:17 -04:00
|
|
|
poste_ids = []
|
2026-03-04 14:01:00 -05:00
|
|
|
for a in affectations:
|
|
|
|
|
poste = await db.get(Poste, a.poste_id)
|
2026-05-31 18:12:26 -04:00
|
|
|
if poste and poste.groupe_id == membre.groupe_id:
|
2026-03-04 14:01:00 -05:00
|
|
|
postes_noms.append(poste.nom)
|
|
|
|
|
postes_categories.append(poste.categorie)
|
2026-05-15 16:41:17 -04:00
|
|
|
poste_ids.append(poste.id)
|
2026-03-04 14:01:00 -05:00
|
|
|
|
|
|
|
|
# Modules de consultation : toujours visibles
|
|
|
|
|
modules_consultation = MODULES_CONSULTATION
|
|
|
|
|
|
2026-04-17 04:04:04 -04:00
|
|
|
# Modules de saisie : collecte pour tous + modules par poste
|
|
|
|
|
modules_saisie = list(MODULES_SAISIE_TOUS)
|
2026-05-25 17:39:38 -04:00
|
|
|
codes_vus = {"S5"}
|
2026-05-15 16:41:17 -04:00
|
|
|
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:
|
2026-05-25 17:39:38 -04:00
|
|
|
if code == "S1" and "executif" not in postes_categories:
|
|
|
|
|
continue
|
2026-05-15 16:41:17 -04:00
|
|
|
m = MODULES_PAR_CODE.get(code)
|
|
|
|
|
if m and not code.startswith("G") and m.code not in codes_vus:
|
2026-03-04 14:01:00 -05:00
|
|
|
modules_saisie.append(m)
|
|
|
|
|
codes_vus.add(m.code)
|
2026-05-15 16:41:17 -04:00
|
|
|
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)
|
2026-05-25 17:39:38 -04:00
|
|
|
if "executif" in postes_categories and "S1" not in codes_vus:
|
|
|
|
|
modules_saisie.insert(0, MODULES_PAR_CODE["S0"])
|
Intégrer rencontres et assemblées pilotées par tuiles
Refond les pages Rencontres et Assemblées autour de tuiles ouvrables avec actions locales, PDF serveur, ventes, collectes, présences, décisions, postes et contributions.
Ajoute les invitations publiques d'assemblée en lecture seule avec lien expirant, l'adoption formelle du rapport du trésorier avec proposeur/secondeur, et bloque les contributions tant que ce rapport n'est pas adopté.
Uniformise la navigation et les entêtes, retire les modules redondants des contextes, ajoute la création de comptes membres par exécutif et les données démo reliées aux nouveaux processus.
Ce commit capture un lot fonctionnel important; une refactorisation ciblée du module Assemblées, puis Trésorerie/Gouvernance, est maintenant pertinente pour isoler les règles métier et faciliter les tests.
2026-05-31 09:02:02 -04:00
|
|
|
modules_saisie.insert(1, MODULES_PAR_CODE["M0"])
|
2026-05-25 17:39:38 -04:00
|
|
|
codes_vus.add("S0")
|
|
|
|
|
codes_vus.add("M0")
|
2026-03-04 14:01:00 -05:00
|
|
|
|
|
|
|
|
# Modules de gestion : seulement si exécutif
|
2026-05-15 16:41:17 -04:00
|
|
|
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 []
|
2026-03-04 14:01:00 -05:00
|
|
|
|
2026-04-17 04:04:04 -04:00
|
|
|
# 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,
|
2026-05-25 17:39:38 -04:00
|
|
|
"assemblee_affaires_ordre": groupe.assemblee_affaires_ordre,
|
2026-04-17 04:04:04 -04:00
|
|
|
"adresse_local": groupe.adresse_local,
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-04 14:01:00 -05:00
|
|
|
return AccueilResponse(
|
|
|
|
|
membre=MembrePublic.model_validate(membre),
|
|
|
|
|
postes=postes_noms,
|
2026-05-25 17:39:38 -04:00
|
|
|
est_executif="executif" in postes_categories,
|
2026-03-04 14:01:00 -05:00
|
|
|
modules_consultation=modules_consultation,
|
|
|
|
|
modules_saisie=modules_saisie,
|
|
|
|
|
modules_gestion=modules_gestion,
|
2026-04-17 04:04:04 -04:00
|
|
|
groupe=groupe_info,
|
2026-03-04 14:01:00 -05:00
|
|
|
)
|