# Architecture

## Vue d'ensemble

Récré est un système de caisse + gestion de stock **multi-association** pour des stands scolaires (friandises, chips, boissons). Appli web auto-hébergée, base centralisée, utilisée en multi-élèves / multi-appareils.

**L'appli ne touche jamais l'argent.** Elle enregistre uniquement le moyen de paiement (espèces / SumUp). Aucun encaissement, aucune intégration de terminal.

## Multi-tenant

Chaque association est un tenant isolé. Toutes les données métier (produits, caisses, sessions, ventes, stock) sont scopées à une `Association`. Un super-admin crée les associations et désigne leurs admins.

## Deux interfaces

- **Front de vente** — mobile-first (Twig + Stimulus/Turbo), pour les vendeurs (élèves). Rapide à taper.
- **Back-office** — EasyAdmin, pour les admins (contrôle ventes, stock, stats, config) et le super-admin (gestion des assos).

## Stack technique

| Composant | Choix |
|-----------|-------|
| Framework | Symfony 7 |
| Back-office | EasyAdmin |
| Base de données | MariaDB 11 |
| PHP | 8.3 |
| Front de vente | Twig + Stimulus/Turbo |
| Conteneurisation | Docker (docker compose) |
| Hébergement | Auto-hébergé |

## Modèle de données

### Entités Doctrine

- **Association** — nom, slug, active. Tenant racine, tout est scopé dessous.
- **User** — lié à une `Association` (sauf super-admin). Rôles : `ROLE_SUPER_ADMIN`, `ROLE_ADMIN`, `ROLE_VENDEUR`.
- **Product** — nom, prix de vente, stock courant. Scopé à l'asso. Champs optionnels (toggles) : prix d'achat, taux de TVA.
- **Register** (Caisse) — libellé. Scopé à l'asso. Il peut en exister plusieurs par asso.
- **CashSession** — rattachée à un `Register`. `openedAt`/`closedAt`, `openedBy`/`closedBy` (User), fond de caisse initial, espèces comptées à la clôture, écart calculé, statut (enum `OPEN`/`CLOSED`). N'est PAS liée à un seul vendeur.
- **Sale** — rattachée à une `CashSession` + un vendeur (User) + moyen de paiement (enum `CASH`/`SUMUP`). Total, date.
- **SaleLine** — rattachée à une `Sale` : produit, quantité, prix unitaire figé (snapshot).
- **StockMovement** — produit, type (enum `ENTRY`/`ADJUSTMENT`/`SALE`), quantité, motif, date.

### Enums PHP

- `PaymentMethod` : CASH, SUMUP
- `SessionStatus` : OPEN, CLOSED
- `StockMovementType` : ENTRY, ADJUSTMENT, SALE

### Règle de clôture

Espèces attendues = fond initial + Σ(ventes CASH de la session).
Écart = comptage réel saisi − attendu.

## Périmètre v1

### Dans le scope

- Multi-asso avec super-admin.
- Auth : trois rôles (super-admin, admin asso, vendeur).
- Caisses multiples par asso, sessions ouvertes/clôturées par les vendeurs.
- Clôture avec calcul d'écart.
- Vente front mobile-first : panier, choix moyen de paiement, décrément stock.
- Stock : entrées, niveau, ajustements manuels.
- Stats : ventes par période, par vendeur, par produit, écarts.
- Config : produits, prix, toggles marge & TVA.

### Hors scope (reporté)

- Offline / PWA — online-only en v1.
- Réassort automatique.
- SKU par marque — suivi produit générique.
