# 🔧 Améliorations : Gestion des Dates de Paiement

**Date** : 12 février 2026  
**Version** : 1.2.0  
**Suite à** : Question sur la détection des paiements avant/après le 10

---

## ❓ Question Initiale

> "Comment savons-nous si une quittance est payée avant le 10 ou pas ?"

## 🎯 Problème Identifié

L'implémentation initiale avait une **lacune importante** :

### Avant (v1.0.0)
```php
// Vérification simpliste
if ($this->is_payer) {
    return false; // Pas de pénalité si payé
}
```

**Problème** :
- ✅ On savait si une quittance était payée (`is_payer = true`)
- ❌ Mais on ne savait PAS **quand** elle a été payée
- ❌ Le champ `payer_at` n'était pas toujours renseigné
- ❌ Impossible de déterminer si le paiement était avant ou après le 10

---

## ✅ Solutions Implémentées

### 1. Enregistrement Automatique de la Date de Paiement

**Fichier modifié** : `src/Controller/Admin/Apis/ApisQuittancesController.php`

```php
// AVANT (ne définissait pas la date)
$quittance->setIsPayer(!$wasPaid);
$quittance->setEtats($etat);

// APRÈS (définit automatiquement la date)
if ($quittance->isIsPayer() === true) {
    $quittance->setEtats($etat);
    // ✅ NOUVEAU : Enregistrer la date de paiement
    if (!$quittance->getPayerAt()) {
        $quittance->setPayerAt(new \DateTime());
    }
}
```

### 2. Logique Améliorée de Vérification des Pénalités

**Fichier modifié** : `src/Entity/Quittances/Quittances.php`

```php
public function shouldApplyPenalty(): bool
{
    // Calcul de la date limite
    $deadline = new \DateTime("{$endYear}-{$endMonth}-10");

    // ✅ NOUVEAU : Vérification avec la date de paiement
    if ($this->is_payer && $this->payer_at) {
        // Si payé AVANT ou LE 10 → PAS de pénalité
        if ($this->payer_at <= $deadline) {
            return false;
        }
        // Si payé APRÈS le 10 → Pas de nouvelle pénalité
        return false;
    }

    // Si NON payé et date actuelle > 10 → Pénalité
    $now = new \DateTime();
    return $now > $deadline;
}
```

### 3. Nouvelles Méthodes Utiles

```php
/**
 * Vérifie si le paiement a été effectué avant le 10 du mois
 */
public function isPaidBeforeDeadline(): bool
{
    if (!$this->is_payer || !$this->payer_at || !$this->end_at) {
        return false;
    }

    $endMonth = (int) $this->end_at->format('m');
    $endYear = (int) $this->end_at->format('Y');
    $deadline = new \DateTime("{$endYear}-{$endMonth}-10");

    return $this->payer_at <= $deadline;
}

/**
 * Retourne le nombre de jours de retard après le 10
 */
public function getDaysLate(): int
{
    // Calcule le retard en jours
    $referenceDate = $this->payer_at ?? new \DateTime();
    
    if ($referenceDate <= $deadline) {
        return 0;
    }

    $interval = $deadline->diff($referenceDate);
    return (int) $interval->format('%a');
}
```

### 4. Mise à Jour du Contrôleur d'Édition

**Fichier modifié** : `src/Controller/Admin/Quittances/AdminQuittancesController.php`

```php
if ($quittance->getEtats() === $etat) {
    $quittance->setIsPayer(true);
    // ✅ NOUVEAU : Définir la date si elle n'existe pas
    if (!$quittance->getPayerAt()) {
        $quittance->setPayerAt(new \DateTime());
    }
}
```

---

## 📊 Comparaison Avant/Après

### Scénario : Paiement en Retard

#### Version 1.0.0 (Avant)
```
Quittance créée : 01/12/2025
Date limite : 10/12/2025

15/12 : Admin clique sur "Payé"
→ is_payer = true
→ payer_at = NULL ❌

Résultat : 
- On ne sait pas quand elle a été payée
- Impossible de calculer le retard
- Gestion manuelle nécessaire
```

#### Version 1.2.0 (Après)
```
Quittance créée : 01/12/2025
Date limite : 10/12/2025

15/12 : Admin clique sur "Payé"
→ is_payer = true
→ payer_at = 15/12/2025 ✅

Résultat :
- Date de paiement enregistrée automatiquement
- Système calcule : 5 jours de retard
- Pénalité déjà appliquée est préservée
```

---

## 📚 Nouvelle Documentation

### Fichiers Créés

1. **`LOGIQUE_PAIEMENT_PENALITES.md`** (NOUVEAU)
   - Explique en détail comment le système détermine les pénalités
   - Diagrammes et exemples concrets
   - Requêtes SQL pour analyse

2. **`migrations/fix_missing_payment_dates.sql`** (NOUVEAU)
   - Script pour corriger les anciennes données
   - 3 options de correction selon le contexte
   - Requêtes de vérification et statistiques

### Fichiers Mis à Jour

- `QUICK_START_PENALITES.md` : Ajout des nouvelles méthodes de debug
- Autres documentations référencent le nouveau fichier

---

## 🔄 Migration des Données Existantes

Pour les quittances existantes marquées comme payées mais sans date :

### Option 1 : Date de Modification (Recommandée)
```sql
UPDATE quittances
SET payer_at = updated_at
WHERE is_payer = 1 
  AND payer_at IS NULL
  AND updated_at IS NOT NULL;
```

### Option 2 : Considérer comme Payées à Temps
```sql
UPDATE quittances
SET payer_at = DATE_FORMAT(end_at, '%Y-%m-10')
WHERE is_payer = 1 
  AND payer_at IS NULL
  AND end_at IS NOT NULL;
```

### Option 3 : Date Actuelle
```sql
UPDATE quittances
SET payer_at = CURDATE()
WHERE is_payer = 1 
  AND payer_at IS NULL;
```

**Voir** : `migrations/fix_missing_payment_dates.sql` pour plus de détails

---

## 📈 Nouveaux Cas d'Usage Gérés

### ✅ Cas 1 : Paiement Avant le 10
```php
// Quittance avec end_at = 31/01/2026
// Payée le 08/01/2026

$quittance->isPaidBeforeDeadline(); // true
$quittance->shouldApplyPenalty();   // false
$quittance->getDaysLate();          // 0
```

### ✅ Cas 2 : Paiement Après le 10
```php
// Quittance avec end_at = 31/01/2026
// Payée le 15/01/2026

$quittance->isPaidBeforeDeadline(); // false
$quittance->shouldApplyPenalty();   // false (déjà payé)
$quittance->getDaysLate();          // 5 jours
```

### ✅ Cas 3 : Quittance Non Payée en Retard
```php
// Quittance avec end_at = 31/01/2026
// Date actuelle : 20/01/2026
// Statut : Non payée

$quittance->isPaidBeforeDeadline(); // false
$quittance->shouldApplyPenalty();   // true
$quittance->getDaysLate();          // 10 jours
```

---

## 🎨 Améliorations Interface (À Venir)

### Suggestions pour v1.3.0

1. **Afficher le nombre de jours de retard**
   ```twig
   {% if quittance.daysLate > 0 %}
       <span class="badge badge-warning">
           {{ quittance.daysLate }} jours de retard
       </span>
   {% endif %}
   ```

2. **Indicateur de paiement à temps**
   ```twig
   {% if quittance.isPaidBeforeDeadline %}
       <span class="badge badge-success">
           ✅ Payé à temps
       </span>
   {% endif %}
   ```

3. **Historique des dates importantes**
   ```
   📅 Dates Clés
   - Créée : 01/12/2025
   - Échéance : 31/12/2025
   - Limite : 10/12/2025
   - Payée : 08/12/2025 ✅
   ```

---

## 🧪 Tests à Effectuer

### Test 1 : Marquer une Quittance comme Payée

```bash
# 1. Créer une quittance test
# 2. Cliquer sur le toggle "Payé"
# 3. Vérifier en SQL :

SELECT code, is_payer, payer_at 
FROM quittances 
WHERE code = 'QT-TEST-001';

# Attendu : payer_at = date du jour
```

### Test 2 : Vérifier les Méthodes

```php
// Dans un contrôleur de test
$quittance = $quittancesRepository->findOneBy(['code' => 'QT-TEST-001']);

dump([
    'isPaidBeforeDeadline' => $quittance->isPaidBeforeDeadline(),
    'shouldApplyPenalty' => $quittance->shouldApplyPenalty(),
    'daysLate' => $quittance->getDaysLate(),
]);
```

### Test 3 : Migration des Anciennes Données

```sql
-- Avant correction
SELECT COUNT(*) FROM quittances 
WHERE is_payer = 1 AND payer_at IS NULL;

-- Exécuter le script de correction

-- Après correction
SELECT COUNT(*) FROM quittances 
WHERE is_payer = 1 AND payer_at IS NULL;

-- Attendu : 0
```

---

## 📊 Statistiques Disponibles

Avec les nouvelles améliorations, vous pouvez maintenant :

```sql
-- Taux de paiement à temps
SELECT 
    COUNT(*) as total,
    SUM(CASE WHEN payer_at <= DATE_FORMAT(end_at, '%Y-%m-10') 
        THEN 1 ELSE 0 END) as a_temps,
    ROUND(100.0 * SUM(CASE WHEN payer_at <= DATE_FORMAT(end_at, '%Y-%m-10') 
        THEN 1 ELSE 0 END) / COUNT(*), 2) as taux_paiement_temps
FROM quittances
WHERE is_payer = 1 AND payer_at IS NOT NULL;

-- Retard moyen en jours
SELECT 
    AVG(DATEDIFF(payer_at, DATE_FORMAT(end_at, '%Y-%m-10'))) as retard_moyen_jours
FROM quittances
WHERE is_payer = 1 
  AND payer_at > DATE_FORMAT(end_at, '%Y-%m-10');
```

---

## ✅ Checklist de Validation

- [x] Date de paiement enregistrée automatiquement lors du toggle
- [x] Méthode `isPaidBeforeDeadline()` implémentée
- [x] Méthode `getDaysLate()` implémentée
- [x] Logique de pénalité prend en compte `payer_at`
- [x] Documentation complète créée (`LOGIQUE_PAIEMENT_PENALITES.md`)
- [x] Script de migration pour anciennes données
- [x] Tests de vérification SQL
- [ ] Tests unitaires (à implémenter)
- [ ] Interface utilisateur améliorée (v1.3.0)

---

## 🎉 Résultat Final

### Avant v1.0.0
```
❌ Date de paiement non enregistrée
❌ Impossible de savoir si payé avant/après le 10
❌ Gestion manuelle nécessaire
```

### Après v1.2.0
```
✅ Date de paiement automatique
✅ Détection précise paiement avant/après le 10
✅ Calcul du nombre de jours de retard
✅ Statistiques complètes disponibles
✅ Documentation exhaustive
```

---

**Merci pour cette excellente question qui a permis d'améliorer considérablement le système ! 🙏**

---

## 📚 Fichiers à Consulter

1. **`LOGIQUE_PAIEMENT_PENALITES.md`** → Comprendre la logique complète
2. **`migrations/fix_missing_payment_dates.sql`** → Corriger les données existantes
3. **`QUICK_START_PENALITES.md`** → Guide de démarrage
4. **`RESUME_IMPLEMENTATION_PENALITES.md`** → Vue d'ensemble

**Version** : 1.2.0  
**Date** : 12 février 2026
