# 🔄 Système de Synchronisation - Pressing Yehiya

## 📖 Vue d'Ensemble

Ce système permet de faire fonctionner l'application Pressing Yehiya **en mode local avec synchronisation automatique** vers une base de données distante quand une connexion internet est disponible.

### Architecture

```
┌─────────────────────────┐
│   Application Locale    │
│                         │
│  ┌──────────────────┐  │
│  │  SQLite (Local)  │  │
│  └──────────────────┘  │
│           ↕             │
│   Synchronisation       │
│      Automatique        │
│           ↕             │
└─────────────────────────┘
           ↕
    (Internet)
           ↕
┌─────────────────────────┐
│   Serveur Distant       │
│                         │
│  ┌──────────────────┐  │
│  │  MySQL (Remote)  │  │
│  └──────────────────┘  │
└─────────────────────────┘
```

---

## 🚀 Démarrage Rapide

### Première Installation

1. **Déploiement initial**:
   ```bash
   .\deploy-local.bat
   ```

2. **Configurer `.env`** avec les informations du serveur distant

3. **Démarrer l'application** (2 terminaux):
   ```bash
   # Terminal 1 - Serveur
   .\start-local.bat
   
   # Terminal 2 - Synchronisation
   .\start-queue.bat
   ```

4. **Accéder à l'application**:
   - Application: http://localhost:8000
   - Statut sync: http://localhost:8000/sync/status

---

## 📁 Fichiers Créés

### Configuration
- `config/database.php` - Configuration de la connexion `remote`
- `.env.local.example` - Template de configuration locale

### Modèles et Services
- `app/Models/SyncLog.php` - Journal de synchronisation
- `app/Services/SyncService.php` - Logique de synchronisation
- `app/Traits/Syncable.php` - Trait pour activer la sync sur un modèle
- `app/Providers/SyncServiceProvider.php` - Service provider

### Commandes Artisan
- `app/Console/Commands/SyncToRemote.php` - Commande `sync:to-remote`
- `app/Console/Commands/SyncFromRemote.php` - Commande `sync:from-remote`
- `app/Console/Commands/SyncStatus.php` - Commande `sync:status`

### Jobs
- `app/Jobs/AutoSyncJob.php` - Job de synchronisation automatique

### Contrôleurs et Vues
- `app/Http/Controllers/SyncController.php` - Contrôleur web
- `resources/views/sync/status.blade.php` - Interface de synchronisation

### Migrations
- `database/migrations/2026_02_09_000000_create_sync_logs_table.php` - Table des logs

### Scripts et Documentation
- `deploy-local.bat` - Script de déploiement
- `start-local.bat` - Démarrer le serveur
- `start-queue.bat` - Démarrer la queue
- `DEPLOIEMENT_LOCAL.md` - Guide détaillé
- `GUIDE_RAPIDE.md` - Guide rapide
- `README_SYNCHRONISATION.md` - Ce fichier

---

## 🔧 Comment ça Marche?

### 1. Mode Offline (Hors Ligne)

Quand il n'y a **pas d'internet**:

```
Utilisateur crée un client
        ↓
Enregistré dans SQLite (local)
        ↓
Ajouté à la file de synchronisation (sync_logs)
        ↓
Reste en attente jusqu'à connexion internet
```

### 2. Mode Online (En Ligne)

Quand il y a **internet**:

```
Queue Worker détecte la connexion
        ↓
Lit les sync_logs en attente
        ↓
Envoie les données au serveur distant
        ↓
Marque comme synchronisé
        ↓
Supprime de la file d'attente
```

### 3. Synchronisation Automatique

Le trait `Syncable` capture automatiquement:
- ✅ Création d'enregistrements (`created`)
- ✅ Modification d'enregistrements (`updated`)
- ✅ Suppression d'enregistrements (`deleted`)

---

## 🎯 Modèles Synchronisés

Les modèles suivants sont **automatiquement synchronisés**:

- ✅ `Customer` - Clients
- ✅ `Deposit` - Dépôts
- ✅ `Payment` - Paiements
- ✅ `Article` - Articles
- ✅ `Category` - Catégories
- ✅ `Expense` - Dépenses

### Ajouter la Synchronisation à un Nouveau Modèle

```php
use App\Traits\Syncable;

class MonModele extends Model
{
    use Syncable; // Ajouter cette ligne
    
    // ... reste du code
}
```

---

## 📊 Commandes Disponibles

### Vérifier le Statut

```bash
php artisan sync:status
```

Affiche:
- État de la connexion (en ligne/hors ligne)
- Nombre d'enregistrements en attente
- Nombre d'enregistrements synchronisés
- Nombre d'échecs
- Dernière synchronisation

### Synchroniser Manuellement

**Vers le serveur** (local → distant):
```bash
php artisan sync:to-remote
```

**Depuis le serveur** (distant → local):
```bash
php artisan sync:from-remote
```
⚠️ **ATTENTION**: Cette commande écrase les données locales!

---

## 🌐 Interface Web

### Page de Statut

Accédez à: **http://localhost:8000/sync/status**

Fonctionnalités:
- 📊 Statistiques en temps réel
- 🌐 État de la connexion
- 🕐 Dernière synchronisation
- ⚡ Boutons d'action:
  - Synchroniser vers le serveur
  - Récupérer depuis le serveur

La page se rafraîchit automatiquement toutes les 30 secondes.

---

## ⚙️ Configuration

### Fichier `.env`

```env
# Base de données LOCALE (SQLite)
DB_CONNECTION=sqlite
DB_DATABASE=C:\Softsys\pressing_yehiya\database\database.sqlite

# Base de données DISTANTE (MySQL - Serveur en ligne)
REMOTE_DB_DRIVER=mysql
REMOTE_DB_HOST=votre-serveur.com
REMOTE_DB_PORT=3306
REMOTE_DB_DATABASE=pressing_db
REMOTE_DB_USERNAME=votre_utilisateur
REMOTE_DB_PASSWORD=votre_mot_de_passe

# Queue pour synchronisation
QUEUE_CONNECTION=database
```

### Synchronisation Automatique Programmée

Pour une synchronisation automatique toutes les 15 minutes, ajoutez dans `app/Console/Kernel.php`:

```php
protected function schedule(Schedule $schedule): void
{
    $schedule->job(new \App\Jobs\AutoSyncJob())
             ->everyFifteenMinutes()
             ->when(function () {
                 return app(\App\Services\SyncService::class)->isOnline();
             });
}
```

Puis démarrez le scheduler:
```bash
php artisan schedule:work
```

---

## 🐛 Dépannage

### Problème: Les données ne se synchronisent pas

**Solutions**:
1. Vérifier que le queue worker est actif
2. Vérifier la connexion:
   ```bash
   php artisan sync:status
   ```
3. Consulter les logs:
   ```bash
   type storage\logs\laravel.log
   ```

### Problème: Database locked (SQLite)

**Cause**: SQLite ne supporte qu'une écriture à la fois

**Solutions**:
- Fermer les autres connexions à la base
- Redémarrer le queue worker
- Réduire le nombre de workers

### Problème: Erreur de connexion distante

**Solutions**:
1. Vérifier les informations dans `.env`
2. Tester manuellement:
   ```bash
   php artisan tinker
   >>> app(\App\Services\SyncService::class)->testRemoteConnection()
   ```
3. Vérifier le firewall/pare-feu

### Problème: Synchronisation échoue en boucle

**Solutions**:
1. Voir les erreurs dans `sync_logs`:
   ```bash
   php artisan tinker
   >>> App\Models\SyncLog::where('status', 'failed')->get()
   ```
2. Corriger les données problématiques
3. Relancer:
   ```bash
   php artisan sync:to-remote
   ```

---

## 📝 Base de Données

### Table `sync_logs`

Stocke les opérations à synchroniser:

| Colonne | Type | Description |
|---------|------|-------------|
| `model_type` | string | Type du modèle (Customer, Deposit, etc.) |
| `model_id` | integer | ID de l'enregistrement |
| `action` | enum | create, update, delete |
| `data` | json | Données à synchroniser |
| `status` | enum | pending, synced, failed |
| `error_message` | text | Message d'erreur si échec |
| `synced_at` | timestamp | Date de synchronisation |
| `retry_count` | integer | Nombre de tentatives |

---

## 🔒 Sécurité

### Bonnes Pratiques

1. **Ne jamais committer** `.env` dans Git
2. **Utiliser HTTPS** pour la connexion distante
3. **Chiffrer les sauvegardes** de `database.sqlite`
4. **Limiter les accès** à la base distante (IP whitelist)
5. **Sauvegarder régulièrement** la base locale

### Sauvegarde

```bash
# Copier la base de données
copy database\database.sqlite database\backup_$(date +%Y%m%d).sqlite

# Ou avec compression
tar -czf backup_$(date +%Y%m%d).tar.gz database\database.sqlite
```

---

## 📚 Flux de Travail Recommandé

### Quotidien

1. **Matin**: Démarrer l'application
   ```bash
   .\start-local.bat  # Terminal 1
   .\start-queue.bat  # Terminal 2
   ```

2. **Travail**: Utiliser normalement l'application
   - Créer des clients, dépôts, paiements
   - Tout est sauvegardé localement
   - Synchronisation automatique en arrière-plan

3. **Soir**: Vérifier que tout est synchronisé
   ```bash
   php artisan sync:status
   ```

### Hebdomadaire

1. **Vérifier les échecs** de synchronisation
2. **Sauvegarder** la base de données locale
3. **Nettoyer** les anciens logs:
   ```bash
   php artisan tinker
   >>> App\Models\SyncLog::where('status', 'synced')
       ->where('created_at', '<', now()->subDays(7))
       ->delete()
   ```

---

## 🎓 Exemples d'Utilisation

### Exemple 1: Créer un Client (Mode Offline)

```php
// L'utilisateur crée un client sans internet
$customer = Customer::create([
    'name' => 'Jean Dupont',
    'phone' => '0612345678',
]);

// Automatiquement:
// 1. Sauvegardé dans SQLite
// 2. Ajouté à sync_logs avec status='pending'
// 3. Sera synchronisé dès que internet revient
```

### Exemple 2: Synchronisation Manuelle

```php
use App\Services\SyncService;

$syncService = app(SyncService::class);

// Vérifier la connexion
if ($syncService->isOnline()) {
    // Synchroniser
    $result = $syncService->syncPendingRecords();
    
    if ($result['success']) {
        echo "{$result['synced']} enregistrements synchronisés";
    }
}
```

### Exemple 3: Vérifier le Statut Programmatiquement

```php
use App\Services\SyncService;

$syncService = app(SyncService::class);
$stats = $syncService->getSyncStats();

echo "En attente: {$stats['pending']}\n";
echo "Synchronisés: {$stats['synced']}\n";
echo "Échoués: {$stats['failed']}\n";
echo "En ligne: " . ($stats['online'] ? 'Oui' : 'Non') . "\n";
```

---

## 🔮 Fonctionnalités Avancées

### Synchronisation Sélective

Si vous voulez synchroniser seulement certains modèles:

```php
// Dans SyncService.php
protected array $syncOrder = [
    'customers',    // Synchroniser
    'deposits',     // Synchroniser
    // 'expenses',  // Ne pas synchroniser
];
```

### Gestion des Conflits

En cas de conflit (modification locale et distante), **les données du serveur ont priorité**.

Pour changer ce comportement, modifiez `syncRecord()` dans `SyncService.php`.

### Logs Détaillés

Pour plus de logs:

```php
// Dans .env
LOG_LEVEL=debug

// Voir les logs
tail -f storage/logs/laravel.log
```

---

## 📞 Support

### Ressources

- [Documentation Laravel](https://laravel.com/docs)
- [Laravel Queues](https://laravel.com/docs/queues)
- [SQLite](https://www.sqlite.org/docs.html)

### Debugging

```bash
# Vérifier la queue
php artisan queue:failed

# Relancer les jobs échoués
php artisan queue:retry all

# Vider la queue
php artisan queue:flush

# Mode debug du queue worker
php artisan queue:work --verbose
```

---

## ✅ Checklist de Déploiement

- [ ] Copier le code sur la machine locale
- [ ] Exécuter `deploy-local.bat`
- [ ] Configurer `.env` avec les informations distantes
- [ ] Tester la connexion: `php artisan sync:status`
- [ ] Synchroniser depuis le serveur: `php artisan sync:from-remote`
- [ ] Démarrer le serveur: `start-local.bat`
- [ ] Démarrer la queue: `start-queue.bat`
- [ ] Accéder à http://localhost:8000
- [ ] Vérifier la page de sync: http://localhost:8000/sync/status
- [ ] Créer un enregistrement test
- [ ] Vérifier qu'il se synchronise

---

## 🎉 Conclusion

Vous disposez maintenant d'un système complet de synchronisation offline/online pour votre application de pressing.

**Points clés**:
- ✅ Travaillez sans interruption, même sans internet
- ✅ Synchronisation automatique en arrière-plan
- ✅ Interface web pour suivre le statut
- ✅ Commandes CLI pour contrôle manuel
- ✅ Gestion des erreurs et retry automatique

Bon courage avec votre déploiement! 🚀
