# Pinguin-Corp — Vue d'ensemble du projet

> Fichier de synthèse pour comprendre l'architecture, les choix techniques, et les points clés à étudier.

---

## 1. C'est quoi ce projet ?

Une application web de gestion de "pingouins" (employés fictifs). Deux types d'utilisateurs :

- **Admin** : gère tout (pingouins, projets, départements, managers)
- **Manager** : gère uniquement ses propres pingouins et lance des missions

Stack technique : **PHP 8.2 + Symfony 7.4 + Doctrine ORM + Twig + MariaDB**

---

## 2. Structure des dossiers

```
src/
├── Controller/   → Ce qui reçoit les requêtes HTTP et renvoie une réponse
├── Entity/       → Les "fiches" qui représentent les tables en base de données
├── Form/         → Les formulaires Symfony (validation + rendu HTML)
├── Repository/   → Les requêtes SQL (via Doctrine QueryBuilder)
├── Security/     → Authentification + contrôle d'accès fin (Voter)
├── Service/      → Logique métier réutilisable
└── DataFixtures/ → Données de test à injecter en base

templates/        → Les vues HTML (moteur Twig)
migrations/       → Historique des modifications de la base de données
config/           → Configuration Symfony (sécurité, services, routes…)
public/           → Seul dossier accessible depuis le navigateur (index.php)
```

---

## 3. Les entités (= les tables en base)

### User
Représente un utilisateur connecté. Peut être Admin ou Manager.
- `email`, `password`, `name`, `avatar`, `budget`
- Appartient à un `Departement` (optionnel)
- Possède plusieurs `Pingouin` via `$pingouins` (relation OneToMany)
- Possède plusieurs `Project` via `$projects` (relation OneToMany)
- Rôles : `ROLE_USER` (tout le monde), `ROLE_MANAGER`, `ROLE_ADMIN`

### Pingouin
L'employé fictif géré par l'application.
- `firstname`, `lastname`, `poste`, `speciality`, `salaire`, `satisfaction` (0-100), `status`, `avatar`, `hiredAt`
- Appartient à un `Departement` (obligatoire)
- Appartient à un `User` (manager, optionnel)
- Possède plusieurs `Ability` (compétences) via relation ManyToMany
- Participe à plusieurs `Project` via relation ManyToMany
- Statuts possibles : `actif`, `en_mission`, `congé`, `demissionne`

### Project
Une mission/projet auquel des pingouins participent.
- `name`, `description`, `budget`, `difficulte` (1-5), `statut`, `tauxSucces`, `launchedAt`
- Géré par un `User` (manager, optionnel)
- Équipe de `Pingouin` via relation ManyToMany
- Statuts : `planifie` → `en_cours` → `termine` ou `echoue`

### Departement
Service/département de l'entreprise.
- `name`, `description`, `budget`
- Contient plusieurs `Pingouin`

### Ability
Compétence qu'un pingouin peut avoir.
- `name`, `description`, `icon`

### Stock
Budget global de l'entreprise.
- `budget`, `updateAt`
- ⚠️ Jamais modifié depuis l'interface — fonctionnalité incomplète

---

## 4. Les controllers (= les routes)

| Controller | Préfixe URL | Rôle requis | Ce qu'il fait |
|---|---|---|---|
| `AdminController` | `/admin` | ROLE_ADMIN | Dashboard admin + édition de son profil |
| `DashboardController` | `/manager` | ROLE_MANAGER | Dashboard manager + CRUD pingouins + missions |
| `ManagerController` | `/admin/managers` | ROLE_ADMIN | CRUD des comptes managers |
| `PingouinController` | `/pingouins` | ROLE_ADMIN | CRUD complet des pingouins (vue admin) |
| `ProjectController` | `/admin/projects` | ROLE_ADMIN | CRUD des projets |
| `DepartementController` | `/admin/departements` | ROLE_ADMIN | CRUD des départements |
| `RegistrationController` | `/register` | ROLE_ADMIN | Création d'un nouveau manager (restreint) |
| `SecurityController` | `/login`, `/logout` | — | Connexion / déconnexion |
| `ResetPasswordController` | `/reset-password` | — | Réinitialisation de mot de passe par email |

### Routes missions (DashboardController)

| Route | URL | Méthode | Ce qu'elle fait |
|---|---|---|---|
| `app_mana_mission_lancer` | `/manager/projets/{id}/lancer` | GET/POST | Formulaire de sélection des pingouins + lancement |
| `app_mana_mission_resoudre` | `/manager/projets/{id}/resoudre` | POST | Résolution de la mission (tirage aléatoire) |

---

## 5. La sécurité

### Comment ça fonctionne

Symfony gère la sécurité en deux étapes :

1. **`security.yaml` — access_control** : bloque l'accès à une URL entière selon le rôle.
   C'est la première barrière, vérifiée avant même d'entrer dans le controller.

2. **`#[IsGranted(...)]`** sur un controller : deuxième vérification, plus précise.

3. **Voter (`PingouinVoter`)** : logique d'accès fine sur un objet spécifique
   (ex : "peut-on VOIR ce pingouin précis ?")

### Hiérarchie des rôles

```
ROLE_ADMIN
    └── inclut automatiquement ROLE_MANAGER (défini dans security.yaml)
            └── ROLE_USER (tout utilisateur connecté en hérite)
```

### Authenticator (`UserAuthAuthenticator`)

Gère la connexion par email/mot de passe. Après connexion :
- Admin → redirigé vers `/admin/` (dashboard admin)
- Manager → redirigé vers `/manager/` (dashboard manager)
- Autre → redirigé vers `/login`

---

## 6. Les formulaires

Symfony génère les formulaires HTML depuis des classes PHP (`src/Form/`).
Chaque champ peut avoir des contraintes de validation (`NotBlank`, `Email`, `Length`…).

| Formulaire | Entité | Utilisé dans |
|---|---|---|
| `PingouinType` | Pingouin | Admin et Manager |
| `ManagerType` | User | AdminController (managers) |
| `UserFormType` | User | AdminController (profil admin) |
| `ProjectType` | Project | ProjectController |
| `DepartementType` | Departement | DepartementController |
| `RegistrationFormType` | User | RegistrationController |
| `LancerMissionType` | — (pas d'entité liée) | DashboardController (lancement de mission) |

### Particularité de `LancerMissionType`
Ce formulaire ne correspond à aucune entité directement (`data_class` absent). Il reçoit le manager connecté en option pour filtrer dynamiquement les pingouins disponibles via `query_builder`. C'est un bon exemple de formulaire contextuel en Symfony.

---

## 7. Les services

### `AvatarUploader`
Gère l'upload de fichiers image (profil admin).
- Vérifie l'extension (jpg, jpeg, png, webp)
- Limite la taille à 2 Mo
- Génère un nom de fichier unique avec un slug
- Supprime l'ancienne image lors d'un remplacement
- Configuré dans `config/services.yaml` avec le dossier d'upload

### `MissionService`
Gère toute la logique de lancement et résolution des missions.

**`lancerMission(Project, iterable $pingouins, User $manager)`**
1. Vérifie que l'équipe fait entre 1 et 5 pingouins
2. Calcule le taux de succès (voir formule ci-dessous) et le stocke dans `project->tauxSucces`
3. Déduit le budget de la mission du budget du manager
4. Passe chaque pingouin en statut `en_mission`
5. Ajoute les pingouins à l'équipe du projet
6. Passe le projet en statut `en_cours`

**`resoudreMission(Project)`**
1. Lit le taux de succès calculé au lancement
2. Tire un nombre aléatoire entre 1 et 100
3. Si le tirage ≤ taux → succès (`termine`), sinon échec (`echoue`)
4. Remet tous les pingouins en statut `actif`
5. Succès → +15 satisfaction par pingouin (max 100)
6. Échec → -10 satisfaction par pingouin (min 0)

**Formule du taux de succès (0–100)**
```
score_satisfaction = (moyenne satisfaction équipe / 100) × 60
score_difficulte   = ((6 - difficulté) / 5) × 40
taux               = score_satisfaction + score_difficulte
pénalité budget    = -20 si budget manager < budget projet
résultat final     = max(0, min(100, taux + pénalité))
```

Exemples :
- Équipe satisfaite à 80%, difficulté 2, budget OK → `(0.8×60) + (4/5×40)` = 48 + 32 = **80%**
- Équipe satisfaite à 40%, difficulté 5, budget insuffisant → `(0.4×60) + (1/5×40) - 20` = 24 + 8 - 20 = **12%**

---

## 8. Les repositories (= les requêtes SQL)

Les repositories sont les classes qui font les requêtes vers la base de données.
Symfony/Doctrine en génère un par entité. On y ajoute des méthodes personnalisées.

### `PingouinRepository` — méthodes notables
- `findActifs()` : pingouins non démissionnés
- `findByFilters($departement, $status)` : liste filtrée (page d'index admin)
- `findInsatisfaits($seuil)` : pingouins avec satisfaction < seuil
- `findAtRisk($manager)` : pingouins à risque de démission pour un manager
- `findCritical()` : pingouins très à risque (tous managers confondus)
- `search($mot)` : recherche par nom/prénom (utilisée en AJAX)

### `UserRepository` — méthodes notables
- `findManagers()` : liste des users ayant ROLE_MANAGER
- `countManagers()` : nombre de managers

### `ProjectRepository` — méthodes notables
- `findActifs()` : projets en cours ou planifiés
- `getStats()` : totaux et moyennes pour le dashboard

---

## 9. Les migrations

Les migrations sont des fichiers PHP qui décrivent l'évolution de la base de données.
Commandes utiles :

```bash
# Voir l'état des migrations
php bin/console doctrine:migrations:status

# Appliquer les migrations en attente
php bin/console doctrine:migrations:migrate

# Générer une migration après avoir modifié une entité
php bin/console doctrine:migrations:diff

# Vérifier que les entités et la BDD sont synchronisées
php bin/console doctrine:schema:validate
```

---

## 10. Les fixtures (= données de test)

Le fichier `src/DataFixtures/AppFixtures.php` injecte des données de démo en base.

```bash
# Réinitialiser la BDD et charger les fixtures
php bin/console doctrine:fixtures:load
```

Données créées :
- 1 admin (`admin@pingouin.com` / `admin123`)
- 1 manager (`user@pingouin.com` / `user123`)
- 4 départements, 6 compétences, 6 pingouins, 4 projets, 1 stock

> ⚠️ Les fixtures ne créent pas de manager avec budget et pingouins assignés.
> Pour tester les missions, connecte-toi en admin et édite le manager pour lui assigner des pingouins et un budget.

---

## 11. Points à approfondir (sujets d'étude)

### Priorité haute (bases Symfony)
- **Les entités et Doctrine** : comment PHP représente une table SQL, les annotations `#[ORM\...]`
- **Les relations Doctrine** : ManyToOne, OneToMany, ManyToMany — comment les données se lient
- **Les migrations** : pourquoi on ne modifie jamais la BDD à la main en prod
- **Les formulaires Symfony** : `FormType`, `handleRequest`, `isSubmitted/isValid`
- **La sécurité** : `access_control`, `#[IsGranted]`, les Voters

### Priorité moyenne (aller plus loin)
- **Les repositories et QueryBuilder** : comment écrire des requêtes SQL en PHP
- **Les services Symfony** : injection de dépendances, `autowire`
- **Twig** : moteur de templates, héritage de layouts (`extends`), macros
- **Les fixtures avec Foundry** : alternative plus puissante aux fixtures manuelles

### Ce qui manque dans ce projet (pour aller plus loin)
- Aucun test automatisé (unitaires, fonctionnels)
- `Stock` non gérable depuis l'interface
- Pas de pagination sur les listes
- Les fixtures ne pré-configurent pas le manager pour les missions (setup manuel requis)

---

## 12. Historique des modifications

### Corrections de bugs et sécurité
| Problème | Correction |
|---|---|
| `APP_SECRET` vide | Généré et déplacé dans `.env.local` |
| Credentials BDD/mailer dans `.env` | Déplacés dans `.env.local` (non commité) |
| `/register` public → création libre de managers | `#[IsGranted('ROLE_ADMIN')]` ajouté |
| `updateSatisfaction` sans vérification de propriété | Vérification `pingouin->getUser() === $user` ajoutée |
| `promote` sans vérification du rôle | `denyAccessUnlessGrantedToManager()` appelé |
| `promote` avec `persist()` inutile | `persist()` supprimé |
| Bug DQL `findAtRisk()` (priorité OR/AND) | Conditions OR regroupées entre parenthèses |
| Flash `'sucess'` invisible | Corrigé en `'success'` |
| `Stock` absent des fixtures | Stock initial ajouté |
| `createView()` déprécié | `$form` passé directement aux templates |
| `UserFormType` sans validation | `NotBlank`, `Email`, `Length` ajoutés |
| `AvatarUploader` sans limite de taille | Limite 2 Mo ajoutée |
| `UserRepository::findManagers` via LIKE simple | LIKE avec guillemets JSON `%"ROLE_MANAGER"%` |
| `User::getRelation()` nom confusant | Renommé en `getPingouins()` dans les 4 fichiers concernés |
| Template `manager/_form.html.twig` pas mis à jour | `form.relation` → `form.pingouins` |
| PHPDoc invalide dans `AvatarUploader` | Nettoyé |
| 12 migrations non tracées | Marquées comme exécutées (`--add --all`) |
| `PingouinVoter` commentaire trompeur | Clarifié (code mort expliqué) |

### Fonctionnalités ajoutées
| Fonctionnalité | Fichiers créés / modifiés |
|---|---|
| **Système de missions complet** | `MissionService`, `LancerMissionType`, `DashboardController` (2 routes), `lancer_mission.html.twig`, `projets.html.twig` |
| **Suppression page d'accueil générique** | `HomeController` supprimé, `home/index.html.twig` supprimé, `UserAuthAuthenticator` mis à jour, `security.yaml` nettoyé, logo manager redirige vers `/manager/` |
| **Correction page détail pingouin (page blanche)** | `pingouin/show.html.twig` réécrit — étendait `base.html.twig` au lieu de `admin/_admin_layout.html.twig` |
