# Analyse des modifications d'état d'options

## 1. Comparaison Tests Behat vs Contrôleurs

### Tests Behat
- **Création d'options** : Utilise `OptionFactory::create()` directement
- **Modification d'états** : Crée directement des états avec `->states()->create()` sans passer par OptionService
- **Recalcul des rangs** : Appelle directement `Option::recalculateRangsForProduct()` après chaque modification
- **Gestion de date_end** : Gère manuellement `date_end = null` pour CANCELED et WAITING

### Contrôleurs Front-Office
- **Création d'options** : Utilise `Option::create()` directement (ligne 362)
- **Renouvellement** : Utilise `OptionService::renew()` (ligne 344)
- **Annulation** : Utilise `OptionService::cancel()` (ligne 599)
- **Expiration** : Crée directement un état EXPIRED (ligne 599)
- **Recalcul des rangs** : Appelle `Option::recalculateRangsForProduct()` après renouvellement (ligne 356) et expiration (ligne 611)

### Contrôleurs Back-Office
- **Création d'options** : Utilise `Option::create()` directement (ligne 151)
- **Validation** : Crée directement un état VALIDATED ou WAITING (ligne 484) - **NE PASSE PAS PAR OptionService**
- **Annulation** : Utilise `OptionService::cancel()` (ligne 549)
- **Refus** : Crée directement un état REFUSED (ligne 583) - **NE PASSE PAS PAR OptionService**
- **Recalcul des rangs** : Appelle `Option::recalculateRangsForProduct()` après refus (ligne 599)

## 2. Duplications de logique

### Gestion de `date_end`

La logique de gestion de `date_end` est dupliquée dans **7 endroits différents** :

1. **StateObserver (BO)** - lignes 53-82
   - Gère CREATED, WAITING, CANCELED, VALIDATED

2. **StateObserver (FO)** - lignes 57-72
   - Gère CREATED, VALIDATED (manque WAITING et CANCELED !)

3. **OptionService::cancel()** - lignes 238-244
   - Met `date_end` à null pour CANCELED

4. **OptionController::validateOption() (BO)** - lignes 468-505
   - Gère WAITING et VALIDATED

5. **OptionController::refuse() (BO)** - lignes 587-591
   - Met `date_end` à null pour REFUSED

6. **Option::saved hook** - lignes 1980-2000
   - Gère CANCELED, WAITING, VALIDATED

7. **Option::updateRenouvellement()** - lignes 201-222
   - Gère VALIDATED, CREATED, WAITING, CANCELED

### Gestion du recalcul des rangs

Le recalcul des rangs est appelé à **8 endroits différents** :

1. **StateObserver (BO)** - ligne 80 (via State::created hook)
2. **StateObserver (FO)** - ligne 80 (via State::created hook)
3. **State::created hook** - ligne 80
4. **OptionService::cancel()** - N'appelle PAS recalculateRangsForProduct (s'appuie sur StateObserver)
5. **OptionController::refuse() (BO)** - ligne 599
6. **OptionController::store() (FO)** - ligne 356
7. **OptionController::renewOption() (FO)** - ligne 473
8. **OptionController::index() (FO)** - ligne 611 (expiration)

### Gestion des états du lot (LIBRE/OPTION/RESERVE)

La logique de changement d'état du lot est dupliquée dans **5 endroits** :

1. **StateObserver (BO)** - lignes 86-100 (CONFIRMED → RESERVE)
2. **StateObserver (BO)** - lignes 179-188 (EXPIRED/CANCELED/REFUSED → LIBRE)
3. **StateObserver (FO)** - lignes 80-89 (CONFIRMED → RESERVE)
4. **StateObserver (FO)** - lignes 168-177 (EXPIRED/CANCELED/REFUSED → LIBRE)
5. **OptionService::cancel()** - lignes 246-261 (CANCELED → LIBRE)

## 3. Chemins de modification d'état

### VALIDATED
- **BO** : `OptionController::validateOption()` → crée directement un état → StateObserver
- **FO** : Pas de méthode directe (utilise OptionService::renew qui peut créer VALIDATED)
- **Tests** : Créent directement un état VALIDATED

### WAITING
- **BO** : `OptionController::validateOption()` → crée directement un état → StateObserver
- **FO** : Créé automatiquement par le hook `Option::created` si Rank 2 + auto_validated
- **Tests** : Créent directement un état WAITING

### CANCELED
- **BO** : `OptionController::cancel()` → `OptionService::cancel()` → crée un état → StateObserver
- **FO** : `OptionController::cancelOption()` → `OptionService::cancel()` → crée un état → StateObserver
- **Tests** : Créent directement un état CANCELED

### REFUSED
- **BO** : `OptionController::refuse()` → crée directement un état → StateObserver
- **FO** : Pas de méthode directe
- **Tests** : Créent directement un état REFUSED

### EXPIRED
- **BO** : Pas de méthode directe (géré automatiquement)
- **FO** : `OptionController::index()` → crée directement un état EXPIRED → StateObserver
- **Tests** : Créent directement un état EXPIRED

### CONFIRMED
- **BO** : `OptionController::confirm()` → `OptionService::confirm()` → crée un état → StateObserver
- **FO** : `OptionController::confirmOption()` → `OptionService::confirm()` → crée un état → StateObserver
- **Tests** : Créent directement un état CONFIRMED

## 4. Problèmes identifiés

### Problème 1 : Tests Behat ne testent pas les mêmes chemins que les contrôleurs

- Les tests créent directement des états sans passer par OptionService
- Les tests appellent manuellement `recalculateRangsForProduct()` alors que les contrôleurs ne le font pas toujours
- Les tests gèrent manuellement `date_end` alors que les contrôleurs s'appuient sur les Observers

### Problème 2 : Duplication massive de la logique `date_end`

- 7 endroits différents gèrent `date_end`
- Risque d'incohérence si une modification est oubliée
- StateObserver FO manque la gestion de WAITING et CANCELED

### Problème 3 : Recalcul des rangs non systématique

- State::created hook appelle automatiquement `recalculateRangsForProduct()` pour EXPIRED, CANCELED, REFUSED
- Mais certains contrôleurs l'appellent aussi manuellement (refuse, store, renewOption, index)
- Duplication : le recalcul est fait deux fois dans certains cas (via hook + manuellement)
- Tests Behat appellent manuellement alors que c'est automatique

### Problème 4 : Validation d'option ne passe pas par OptionService

- `OptionController::validateOption()` (BO) crée directement un état
- `OptionController::refuse()` (BO) crée directement un état
- Ces méthodes devraient utiliser OptionService pour unifier la logique

## 5. Recommandations

### Recommandation 1 : Unifier les chemins de modification d'état

Toutes les modifications d'état devraient passer par OptionService :
- Créer `OptionService::validate()` pour remplacer la logique dans `OptionController::validateOption()`
- Créer `OptionService::refuse()` pour remplacer la logique dans `OptionController::refuse()`
- Créer `OptionService::expire()` pour remplacer la logique dans `OptionController::index()`

### Recommandation 2 : Centraliser la gestion de `date_end`

- Déplacer toute la logique de `date_end` dans `Option::saved` hook ou dans une méthode dédiée
- Supprimer les duplications dans StateObserver, OptionService, et OptionController

### Recommandation 3 : Centraliser le recalcul des rangs

- Le recalcul des rangs est déjà automatique via State::created hook pour EXPIRED, CANCELED, REFUSED
- **Supprimer les appels manuels redondants** à `recalculateRangsForProduct()` dans les contrôleurs (refuse, store, renewOption, index)
- Garder uniquement les appels manuels pour les cas spéciaux (renouvellement, création)
- Les tests Behat ne devraient pas appeler manuellement si c'est géré automatiquement

### Recommandation 4 : Aligner les tests Behat avec les contrôleurs

- Les tests devraient utiliser OptionService au lieu de créer directement des états
- Les tests ne devraient pas appeler manuellement `recalculateRangsForProduct()` si c'est géré automatiquement
- Les tests devraient tester les mêmes chemins que les contrôleurs
