# Analyse des Tables Contenant les Informations sur les Clients n'ayant pas Remboursé leurs Crédits

## 📋 Résumé Exécutif

Ce document identifie toutes les tables de la base de données qui stockent des informations sur les clients qui n'ont pas encore remboursé leurs crédits (loans).

---

## 🗄️ TABLES PRINCIPALES

### 1. **`customer`** - Table principale des clients

**Description**: Stocke les informations des clients, y compris leur solde de crédit global.

**Colonnes importantes pour les crédits:**
- `loan_balance_bif` (BIGINT) - **SOLDE TOTAL DES CRÉDITS DU CLIENT** (source de vérité pour le solde global)
- `loan_limit_bif` (BIGINT) - Limite de crédit autorisée
- `loan_terms_days` (INT) - Nombre de jours pour rembourser
- `loan_status` (ENUM: 'inactive', 'active', 'suspended') - Statut du crédit
- `can_pay_by_loan` (TINYINT) - Indique si le client peut payer par crédit
- `loan_last_review_at` (DATETIME) - Dernière révision du crédit

**Filtre pour clients avec crédits non remboursés:**
```sql
WHERE loan_balance_bif > 0
```

**Source de données**: Cette valeur est mise à jour quand:
- Un nouveau crédit est accordé (via `unpaid_invoices`)
- Un paiement de crédit est effectué (via `loan_payment`)

---

### 2. **`unpaid_invoices`** - Factures impayées (INCLUANT LES CRÉDITS)

**Description**: Table la plus importante pour les crédits non remboursés. Contient toutes les factures non payées, y compris les ventes à crédit.

**Colonnes importantes pour les crédits:**
- `id` (INT) - ID de la facture
- `customer_id` (INT) - Référence au client
- `is_loan_sale` (TINYINT) - **1 = Vente à crédit, 0 = Vente normale**
- `loan_outstanding_bif` (BIGINT) - **MONTANT RESTANT À PAYER POUR CETTE FACTURE**
- `loan_due_date` (DATE) - Date d'échéance du crédit
- `loan_status` (ENUM: 'pending', 'overdue', 'settled') - Statut du crédit pour cette facture
- `paid_amount` (BIGINT) - Montant total de la facture
- `status` (ENUM: 'pending', 'paid', 'unpaid') - Statut général de la facture
- `approval_status` (ENUM: 'pending', 'approved', 'rejected') - Statut d'approbation

**Filtre pour factures de crédit non remboursées:**
```sql
WHERE is_loan_sale = 1 
  AND loan_outstanding_bif > 0 
  AND (approval_status IS NULL OR approval_status != 'rejected')
  AND (status IS NULL OR status != 'paid')
```

**Note importante**: Cette table est la **SOURCE DE VÉRITÉ** pour calculer le total des crédits dus, car:
- Chaque facture à crédit a son propre `loan_outstanding_bif`
- Les paiements partiels sont reflétés dans cette colonne
- Exclure les factures rejetées (`approval_status = 'rejected'`)
- Exclure les factures déjà payées (`status = 'paid'`)

---

### 3. **`customer_loan_ledger`** - Grand livre des crédits clients

**Description**: Journal comptable de toutes les transactions de crédit (débits et crédits).

**Colonnes importantes:**
- `id` (INT) - ID de l'entrée
- `customer_id` (INT) - Référence au client
- `entry_type` (ENUM: 'loan_sale', 'loan_repayment', 'adjustment') - Type de transaction
- `direction` (ENUM: 'debit', 'credit') - Direction de la transaction
- `amount_bif` (BIGINT) - Montant de la transaction
- `reference_table` (VARCHAR) - Table de référence (ex: 'unpaid_invoices')
- `reference_id` (INT) - ID dans la table de référence
- `notes` (TEXT) - Notes supplémentaires
- `created_by` (INT) - Utilisateur qui a créé l'entrée
- `created_at` (DATETIME) - Date de création

**Usage**: 
- **'loan_sale' + 'debit'** = Nouveau crédit accordé (augmente la dette)
- **'loan_repayment' + 'credit'** = Remboursement (diminue la dette)
- **'adjustment'** = Ajustement manuel du solde

**Calcul du solde à partir du ledger:**
```sql
SELECT 
    customer_id,
    SUM(CASE WHEN direction = 'debit' THEN amount_bif ELSE -amount_bif END) as total_balance
FROM customer_loan_ledger
WHERE customer_id = ?
GROUP BY customer_id
```

---

### 4. **`loan_payment`** - Historique des paiements de crédits

**Description**: Enregistre tous les paiements effectués par les clients pour rembourser leurs crédits.

**Colonnes importantes:**
- `id` (INT) - ID du paiement
- `customer_id` (INT) - Référence au client
- `invoice_id` (INT) - Référence à la facture impayée (`unpaid_invoices`)
- `payment_amount` (BIGINT) - **Montant payé**
- `payment_method` (ENUM: 'cash', 'bank_transfer', 'mobile') - Méthode de paiement
- `payment_date` (DATETIME) - Date du paiement
- `province_id` (INT) - Province où le paiement a été effectué
- `ledger_entry_id` (INT) - Référence à l'entrée dans `customer_loan_ledger`
- `created_by` (INT) - Utilisateur qui a enregistré le paiement

**Usage**: 
- Historique complet des remboursements
- Permet de calculer combien un client a déjà remboursé

**Calcul des remboursements totaux:**
```sql
SELECT 
    customer_id,
    SUM(payment_amount) as total_repaid
FROM loan_payment
WHERE customer_id = ?
GROUP BY customer_id
```

---

## 📊 RELATIONS ENTRE LES TABLES

```
customer (loan_balance_bif)
    ↓
    ├── unpaid_invoices (loan_outstanding_bif) [Factures à crédit non payées]
    │       └── loan_payment (invoice_id) [Paiements pour cette facture]
    │
    └── customer_loan_ledger (customer_id) [Journal comptable]
            └── loan_payment (ledger_entry_id) [Référence croisée]
```

---

## 🔍 COMMENT CALCULER LES CRÉDITS NON REMBOURSÉS

### Méthode 1: Depuis `customer` (Solde global)
```sql
SELECT SUM(loan_balance_bif) as total_credits_due
FROM customer
WHERE loan_balance_bif > 0;
```
**Avantages**: Rapide, solde déjà calculé
**Inconvénients**: Peut ne pas être synchronisé si les mises à jour échouent

### Méthode 2: Depuis `unpaid_invoices` (RECOMMANDÉ)
```sql
SELECT COALESCE(SUM(loan_outstanding_bif), 0) as total_credits_due
FROM unpaid_invoices
WHERE is_loan_sale = 1 
  AND loan_outstanding_bif > 0 
  AND (approval_status IS NULL OR approval_status != 'rejected')
  AND (status IS NULL OR status != 'paid');
```
**Avantages**: 
- Source de vérité la plus précise
- Reflète les paiements partiels
- Exclut automatiquement les factures rejetées/payées
**Inconvénients**: Nécessite un JOIN avec province si filtrage par province

### Méthode 3: Depuis `customer_loan_ledger` (Plus complexe)
```sql
SELECT 
    customer_id,
    SUM(CASE WHEN direction = 'debit' THEN amount_bif 
             WHEN direction = 'credit' THEN -amount_bif 
             ELSE 0 END) as outstanding_balance
FROM customer_loan_ledger
WHERE entry_type IN ('loan_sale', 'loan_repayment', 'adjustment')
GROUP BY customer_id
HAVING outstanding_balance > 0;
```
**Avantages**: Historique complet, traçabilité
**Inconvénients**: Plus complexe, nécessite agrégation

---

## ✅ RECOMMANDATION POUR LE DASHBOARD ADMIN

**Pour "Total Crédits Dûs"**, utiliser **Méthode 2** (`unpaid_invoices`) car:

1. ✅ Source de vérité la plus précise
2. ✅ Inclut tous les crédits non remboursés avec détails par facture
3. ✅ Exclut automatiquement les factures rejetées et payées
4. ✅ Supporte le filtrage par province
5. ✅ Reflète les paiements partiels

**Requête optimale:**
```sql
SELECT COALESCE(SUM(loan_outstanding_bif), 0) as total_credits_due
FROM unpaid_invoices
WHERE is_loan_sale = 1 
  AND loan_outstanding_bif IS NOT NULL
  AND loan_outstanding_bif > 0 
  AND (approval_status IS NULL OR approval_status != 'rejected')
  AND (status IS NULL OR status != 'paid');
```

**Avec filtrage par province:**
```sql
SELECT COALESCE(SUM(loan_outstanding_bif), 0) as total_credits_due
FROM unpaid_invoices
WHERE is_loan_sale = 1 
  AND loan_outstanding_bif IS NOT NULL
  AND loan_outstanding_bif > 0 
  AND province_id = ?
  AND (approval_status IS NULL OR approval_status != 'rejected')
  AND (status IS NULL OR status != 'paid');
```

---

## 📝 NOTES IMPORTANTES

1. **Synchronisation**: 
   - `customer.loan_balance_bif` doit être égal à la somme de `unpaid_invoices.loan_outstanding_bif` pour ce client
   - Cette synchronisation se fait lors des paiements via `loan_payment`

2. **Factures rejetées**: 
   - Les factures avec `approval_status = 'rejected'` NE DOIVENT PAS être incluses dans le calcul

3. **Factures payées**: 
   - Les factures avec `status = 'paid'` sont déjà payées et doivent être exclues

4. **Paiements partiels**: 
   - `loan_outstanding_bif` dans `unpaid_invoices` diminue à chaque paiement partiel
   - Quand `loan_outstanding_bif = 0`, la facture est considérée comme payée

5. **Province**: 
   - Les factures sont liées à une province via `province_id`
   - Pour un filtre par province, utiliser `WHERE province_id = ?`

---

## 🔄 PROCESSUS DE REMBOURSEMENT

Quand un client rembourse un crédit:

1. **`loan_payment`** → Nouvelle entrée créée avec le montant payé
2. **`customer_loan_ledger`** → Nouvelle entrée 'loan_repayment' + 'credit' créée
3. **`unpaid_invoices`** → `loan_outstanding_bif` est diminué du montant payé
4. **`customer`** → `loan_balance_bif` est diminué du montant payé

Si `loan_outstanding_bif` atteint 0, alors `status` est mis à 'paid'.

---

## 📈 STATISTIQUES POSSIBLES

Avec ces tables, on peut calculer:

- **Total crédits dus** (par client, par province, global)
- **Crédits en retard** (où `loan_due_date < CURDATE()`)
- **Crédits actifs** (où `loan_status = 'pending'` et pas encore payés)
- **Historique des remboursements** (depuis `loan_payment`)
- **Traçabilité complète** (depuis `customer_loan_ledger`)

---

**Date de création**: 2025-11-17
**Dernière mise à jour**: 2025-11-17








