# Classeo

Application de gestion scolaire moderne - Backend Symfony 8 + Frontend SvelteKit 2.

## Quick Start

### Prérequis

- Docker Desktop 24+ avec Docker Compose 2.20+
- Git

### Installation

```bash
# 1. Cloner le repo
git clone https://github.com/ClasseoEdu/classeo.git
cd classeo

# 2. Configurer /etc/hosts pour le multi-tenant
sudo sh -c 'echo "127.0.0.1 classeo.local ecole-alpha.classeo.local ecole-beta.classeo.local" >> /etc/hosts'

# 3. Installation complète (démarre les services, génère les clés JWT, warmup cache)
make install

# 4. Vérifier que tout fonctionne
make ps
make check-tenants
```

C'est tout ! L'application est prête.

### Deploiement de demo sur VPS

Pour une mise en ligne simple sur un petit serveur Ubuntu 24.04 (type OVH VPS-1), utilise le guide pas a pas :

- [docs/DEPLOYMENT_VPS1.md](docs/DEPLOYMENT_VPS1.md)

La configuration associee est deja prete dans :

- `compose.prod.yaml`
- `deploy/vps/.env.example`
- `deploy/vps/generate-env.sh`
- `deploy/vps/Caddyfile`
- `deploy/vps/generate-jwt.sh`
- `deploy/vps/generate-demo-data.sh`

Pour remplir rapidement une instance de demo une fois le VPS lance :

```bash
./deploy/vps/generate-demo-data.sh
```

### Commandes utiles

```bash
make help          # Afficher toutes les commandes disponibles
make logs          # Voir les logs des services
make test          # Lancer tous les tests
make check         # Lancer tous les linters
```

### Créer un utilisateur de test

```bash
# Mode interactif
make token

# Créer rapidement un parent sur ecole-alpha
make token-alpha

# Créer un prof sur ecole-beta
make token-beta role=ROLE_PROF email=prof@test.com
```

### URLs

#### Multi-tenant

| Service | URL | Description |
|---------|-----|-------------|
| Frontend Alpha | http://ecole-alpha.classeo.local:5174 | Tenant ecole-alpha |
| Frontend Beta | http://ecole-beta.classeo.local:5174 | Tenant ecole-beta |
| API Alpha | http://ecole-alpha.classeo.local:18000/api | API tenant ecole-alpha |
| API Beta | http://ecole-beta.classeo.local:18000/api | API tenant ecole-beta |
| API Docs | http://ecole-alpha.classeo.local:18000/api/docs | Documentation OpenAPI |

#### Services partagés

| Service | URL | Description |
|---------|-----|-------------|
| RabbitMQ | http://localhost:15672 | Admin (guest/guest) |
| Meilisearch | http://localhost:7700 | Dashboard recherche |
| Mailpit | http://localhost:8025 | Emails de test |
| Mercure | http://localhost:3000/.well-known/mercure | SSE Hub |

#### Monitoring (optionnel)

Lancer avec `make up-full` pour activer le stack de monitoring :

| Service | URL | Description |
|---------|-----|-------------|
| Grafana | http://localhost:3001 | Dashboards (admin/admin) |
| Prometheus | http://localhost:9090 | Métriques |
| GlitchTip | http://localhost:8081 | Error tracking |
| Loki | http://localhost:3100 | Logs centralisés |
| Alertmanager | http://localhost:9093 | Gestion alertes |

##### Stack de monitoring expliquée

**GlitchTip** - Error tracking (compatible Sentry)
- Capture automatiquement les exceptions PHP et les envoie avec leur stack trace
- Regroupe les erreurs similaires pour éviter le bruit
- Configuration : ajouter `SENTRY_DSN` dans `compose.override.yaml`

**Prometheus** - Métriques & alertes
- Collecte les métriques applicatives (latence, requêtes, erreurs) toutes les 15s
- Déclenche des alertes si les SLAs sont menacés (P95 > 200ms, error rate > 1%)
- Requêtes PromQL : http://localhost:9090/graph

**Grafana** - Dashboards visuels
- Dashboard principal : vue globale des métriques applicatives
- Dashboard per-tenant : métriques filtrées par établissement
- Credentials : admin/admin

**Loki + Promtail** - Logs centralisés
- Promtail collecte les logs de tous les conteneurs Docker
- Loki les stocke et permet les requêtes LogQL
- Accès via Grafana → Explore → Loki
- Exemple : `{container_name="classeo_php"} |= "error"`

**Alertmanager** - Notification des alertes
- Reçoit les alertes de Prometheus et les route vers les bons canaux
- En dev : envoie les emails à Mailpit (http://localhost:8025)
- En prod : configurable pour Slack, PagerDuty, email, etc.

## Stack Technique

### Backend

- **PHP 8.5** avec property hooks et asymmetric visibility
- **Symfony 8.0** - Framework DDD-friendly
- **API Platform 4.x** - API REST auto-générée
- **Doctrine ORM 3.x** - Persistence avec mappings séparés
- **PHPStan level 9** - Analyse statique stricte

### Frontend

- **SvelteKit 2.x** - SSR, routing, PWA
- **Svelte 5** - Runes (`$state`, `$derived`, `$effect`)
- **TypeScript strict** - Typage fort
- **TanStack Query 5** - Server state management
- **Tailwind CSS 3** - Utility-first CSS

### Infrastructure

- **PostgreSQL 18.1** - Base de données
- **Redis 7.4** - Cache + Sessions
- **RabbitMQ 4.2** - Message queue
- **Mercure** - Real-time SSE
- **Meilisearch 1.12** - Full-text search
- **Mailpit** - Email testing

## Architecture

### Bounded Contexts

```
backend/src/
├── Administration/  # Gestion établissement, utilisateurs
├── Scolarite/       # Notes, classes, emploi du temps
├── VieScolaire/     # Absences, retards, sanctions
├── Communication/   # Messages, notifications
└── Shared/          # Kernel partagé (EntityId, DomainEvent, etc.)
```

### Structure DDD

Chaque Bounded Context suit la même structure :

```
{BC}/
├── Domain/           # Pure PHP - ZERO dépendance framework
│   ├── Model/        # Aggregates, Entities, Value Objects
│   ├── Event/        # Domain Events
│   ├── Repository/   # Interfaces repository
│   └── Service/      # Domain Services
├── Application/      # Use cases
│   ├── Command/      # Write operations
│   ├── Query/        # Read operations
│   └── EventHandler/ # Domain event handlers
└── Infrastructure/   # Implémentations framework
    ├── Persistence/  # Doctrine repositories
    ├── Api/          # API Platform resources
    └── Messaging/    # RabbitMQ handlers
```

## Développement

### Workflow quotidien

```bash
make up              # Démarrer les services (app uniquement)
make up-full         # Démarrer avec monitoring (Grafana, Prometheus, Loki...)
make down            # Arrêter tous les services
make logs            # Suivre les logs
make test            # Lancer les tests avant commit
make check           # Vérifier la qualité du code
```

### Backend

```bash
make phpstan         # Analyse statique
make test-php        # Tests PHPUnit
make cs-fix          # Corriger le code style
make arch            # Tests d'architecture
make console c='...' # Commande Symfony
```

### Frontend

```bash
make lint            # ESLint
make check-types     # TypeScript check
make test-js         # Tests Vitest
make e2e             # Tests Playwright
```

### Shell

```bash
make shell           # Shell dans le container PHP
make shell-frontend  # Shell dans le container frontend
```

## Tests

### Tests unitaires et intégration (dans Docker)

```bash
make test          # Tous les tests (PHPUnit + Vitest)
make test-php      # PHPUnit uniquement
make test-js       # Vitest uniquement
make ci            # Tous les checks + tests
```

### Tests E2E Playwright (depuis l'hôte)

Les tests E2E nécessitent Node.js sur l'hôte (pas dans Docker) :

```bash
# 1. Installer pnpm si pas déjà fait
npm install -g pnpm

# 2. Installer les dépendances frontend
cd frontend && pnpm install

# 3. Installer les navigateurs Playwright
pnpm exec playwright install
# ou avec npx : npx playwright install

# 4. S'assurer que l'app tourne
make up

# 5. Lancer les tests E2E
make e2e

# Ou en mode UI pour debug
cd frontend && pnpm exec playwright test --ui
```

**Pourquoi depuis l'hôte ?** Les tests E2E utilisent `docker compose exec` pour créer des utilisateurs de test, ce qui nécessite l'accès au CLI Docker.

**Problèmes de permissions ?** Si vous avez des erreurs `EACCES`, corrigez les permissions :
```bash
docker run --rm -v $(pwd)/frontend:/app alpine chown -R $(id -u):$(id -g) /app/.svelte-kit /app/node_modules /app/test-results
```

## Documentation

- [Architecture Decision Records](./docs/adr/)
- [Contributing Guide](./CONTRIBUTING.md)
- [API Documentation](http://ecole-alpha.classeo.local:18000/api/docs)

## Licence

Proprietary - ClasseoEdu
