167 lines
5.2 KiB
Markdown
167 lines
5.2 KiB
Markdown
# Architecture technique
|
|
|
|
Statut: référence technique
|
|
Public: mainteneurs, exploitants
|
|
Dernière révision: 2026-06-01
|
|
|
|
## Vue d'ensemble
|
|
|
|
L'application est composée de quatre couches:
|
|
|
|
- frontend PWA React;
|
|
- API FastAPI;
|
|
- base PostgreSQL;
|
|
- déploiement systemd, NGINX et Ansible.
|
|
|
|
Le frontend ne contient pas les règles d'autorisation finales. Il adapte l'interface selon les modules retournés par l'API, mais le backend reste responsable de refuser les actions non permises.
|
|
|
|
## Frontend
|
|
|
|
Emplacement: `frontend/src`.
|
|
|
|
Éléments principaux:
|
|
|
|
- `App.jsx`: routeur applicatif côté client;
|
|
- `stores/store.js`: état global Zustand, session, groupe courant, modules;
|
|
- `stores/api.js`: client HTTP et gestion du token;
|
|
- `components/PageHeader.jsx`: entête commun des pages authentifiées;
|
|
- `components/BottomNav.jsx`: navigation par contextes;
|
|
- `pages/`: écrans fonctionnels;
|
|
- `features/assemblees/`: composants et helpers propres aux assemblées;
|
|
- `utils/datesReunion.js`: logique de dates de rencontres;
|
|
- `utils/pushNotifications.js`: abonnement push.
|
|
|
|
Conventions:
|
|
|
|
- les pages protégées sont sélectionnées par code de module;
|
|
- la barre de navigation du bas n'apparaît que sur l'accueil;
|
|
- les tuiles expansibles sont le motif principal pour rencontres, assemblées, décisions, postes et journal;
|
|
- les pages doivent rester utilisables sur petit téléphone.
|
|
|
|
## Backend
|
|
|
|
Emplacement: `backend/app`.
|
|
|
|
Éléments principaux:
|
|
|
|
- `main.py`: application FastAPI, middleware, montage des routers, migrations légères au démarrage;
|
|
- `core/`: sécurité, rôles, audit, concurrence, finances, décisions, configuration;
|
|
- `models/`: modèles SQLAlchemy et tables;
|
|
- `routers/`: endpoints API;
|
|
- `schemas/`: contrats Pydantic;
|
|
- `services/`: logique métier réutilisable.
|
|
|
|
Règle de maintenance:
|
|
|
|
- un router orchestre une action HTTP;
|
|
- une règle métier partagée va dans `services/` ou `core/`;
|
|
- un router ne doit pas importer un autre router pour réutiliser sa logique.
|
|
|
|
## Authentification et session
|
|
|
|
Le membre se connecte par groupe, identifiant/courriel et PIN. Le backend émet un JWT contenant:
|
|
|
|
- `sub`: membre courant;
|
|
- `groupe_id`: groupe courant;
|
|
- `adm`: sysadmin d'origine lors d'une impersonification.
|
|
|
|
Les routes authentifiées récupèrent le membre courant depuis le token. Les données doivent toujours être filtrées par `membre.groupe_id`.
|
|
|
|
## Permissions
|
|
|
|
Les accès sont déterminés par:
|
|
|
|
- les affectations actives du membre;
|
|
- la catégorie du poste (`executif`, `service`, `physique`);
|
|
- les permissions de modules associées aux postes;
|
|
- le statut spécial `Sysadmin`.
|
|
|
|
Les modules visibles sont calculés par `/api/accueil/`.
|
|
|
|
## Multi-groupe
|
|
|
|
Chaque table métier doit avoir un `groupe_id`, ou être reliée à une table parent qui en a un. Une route recevant un identifiant client doit vérifier que l'objet appartient au groupe courant avant lecture ou modification.
|
|
|
|
Voir [Multi-groupe](93_MULTI_GROUPE.md).
|
|
|
|
## Journalisation
|
|
|
|
`AuditMiddleware` journalise les méthodes mutantes réussies (`POST`, `PUT`, `PATCH`, `DELETE`) sous `/api/`.
|
|
|
|
Les journaux techniques sont conservés dans `journal_actions`. Les changements métier détaillés peuvent aussi être enregistrés dans `historique_modifications`, avec ancienne valeur, nouvelle valeur, membre responsable et raison automatique.
|
|
|
|
## Notifications
|
|
|
|
Les notifications push sont optionnelles. Le backend mappe les chemins API vers des catégories (`gouvernance`, `tresorerie`, `membres`, `postes`, `rencontres`, `litterature`, `evenements`, `systeme`) et notifie les membres abonnés selon leurs préférences.
|
|
|
|
## Finances
|
|
|
|
La source de vérité financière est `transactions_comptables`.
|
|
|
|
Conventions:
|
|
|
|
- `compte = banque` ou `encaisse`;
|
|
- `sens = debit` augmente le compte;
|
|
- `sens = credit` diminue le compte;
|
|
- `source_table` et `source_id` relient l'écriture à l'objet métier.
|
|
|
|
Les réserves sont historisées dans `mouvements_reserves`. Le solde courant de `reserves` ne doit pas devenir la seule source de vérité.
|
|
|
|
## Décisions
|
|
|
|
Les propositions et décisions partagent la table `propositions`.
|
|
|
|
Une proposition devient une décision lorsque les champs de décision sont renseignés:
|
|
|
|
- `type_decision`;
|
|
- `date_adoption`;
|
|
- `numero_resolution`;
|
|
- `etant_donne_que`;
|
|
- `groupe_a_decide_de`.
|
|
|
|
La numérotation est produite par `core/decisions.py`.
|
|
|
|
## Rapports PDF
|
|
|
|
Les PDF sont produits côté backend avec WeasyPrint. Les rapports importants doivent rester imprimables en format lettre et utilisables comme reprise papier.
|
|
|
|
## Déploiement
|
|
|
|
La voie supportée est Ansible. Le playbook installe:
|
|
|
|
- paquets système;
|
|
- PostgreSQL;
|
|
- backend Python;
|
|
- frontend compilé;
|
|
- service systemd;
|
|
- NGINX;
|
|
- sauvegardes.
|
|
|
|
Voir [Déploiement Ansible](91_DEPLOIEMENT_ANSIBLE.md).
|
|
|
|
## Initialisation
|
|
|
|
`deploy/seed.py` crée le schéma et initialise `Groupe Démonstration`. Une VM vanille ne crée plus de groupe réel par défaut.
|
|
|
|
Le groupe de démonstration contient:
|
|
|
|
- `Sysadmin` avec PIN `0000`;
|
|
- postes et permissions de base;
|
|
- littérature;
|
|
- 12 mois d'activité fictive crédible.
|
|
|
|
## Tests
|
|
|
|
Tests actuellement présents:
|
|
|
|
```bash
|
|
.venv/bin/python -m pytest backend/tests/test_business_rules.py
|
|
```
|
|
|
|
Build frontend:
|
|
|
|
```bash
|
|
cd frontend
|
|
npm run build
|
|
```
|
|
|