# Systeme de Migrations Incrementales

## Principe

Au lieu de recréer toute la structure de la base à chaque modification (via `Sp_Maj_structure`), ce système permet d'appliquer uniquement les changements nécessaires.

## Compatibilité

- **Application Web** : Intégré automatiquement (login + maintenance)
- **Application WinDev** : Voir section "Intégration WinDev" ci-dessous

## Avantages

- **Rapide** : On n'exécute que les changements manquants
- **Traçable** : On sait exactement ce qui a été appliqué sur chaque base
- **On-premise friendly** : Détection automatique de l'état du client
- **Réversible** : Possibilité d'ajouter des scripts de rollback
- **Simple** : Un fichier SQL par changement

## Structure

```
database/migrations/
├── _init_migrations_table.sql  # Script d'init (automatique)
├── 001_exemple_ajouter_colonne.sql
├── 002_exemple_modifier_type.sql
└── README.md
```

## Comment créer une migration

### Option 1 : Via l'API

```bash
POST /api/migrations/create
Body: { "nom": "ajouter colonne statut client" }
```

Cela crée automatiquement un fichier `003_ajouter_colonne_statut_client.sql`.

### Option 2 : Manuellement

1. Créer un fichier avec le format : `XXX_nom_de_la_migration.sql`
2. Le numéro doit être séquentiel (001, 002, 003...)
3. Écrire votre SQL en suivant le template ci-dessous

## Template de migration

```sql
-- ============================================
-- Migration XXX: Description
-- Date: YYYY-MM-DD
-- ============================================
-- Description:
-- Expliquez ce que fait cette migration
-- ============================================

-- IMPORTANT: Toujours vérifier si le changement existe déjà (idempotence)

-- Exemple: Ajouter une colonne
IF NOT EXISTS (
    SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS
    WHERE TABLE_NAME = 'ma_table' AND COLUMN_NAME = 'nouvelle_colonne'
)
BEGIN
    ALTER TABLE ma_table ADD nouvelle_colonne NVARCHAR(100) NULL;
    PRINT 'Colonne nouvelle_colonne ajoutee a ma_table';
END

GO
```

## Bonnes pratiques

1. **Idempotence** : Toujours vérifier si le changement existe déjà avant de l'appliquer
2. **Atomicité** : Une migration = un changement logique
3. **Pas de rollback automatique** : Tester en dev avant de déployer
4. **Nommage clair** : Le nom doit décrire le changement

## Utilisation via l'API

### Voir le statut des migrations

```
GET /api/migrations/status/:dbName
```

### Appliquer les migrations

```
POST /api/migrations/apply/:dbName
Body: { "dryRun": false }  # true pour simuler
```

### Appliquer sur plusieurs bases

```
POST /api/migrations/apply-multiple
Body: { "dbNames": ["base1", "base2"], "concurrency": 3 }
```

### Lister les migrations disponibles

```
GET /api/migrations/available
```

### Historique d'une base

```
GET /api/migrations/history/:dbName
```

## Intégration avec la maintenance

Les migrations sont automatiquement appliquées :

- Après la maintenance avancée (Sp_Maj_structure)
- Via l'API `/api/migrations/apply/:dbName`

## Table de suivi

Chaque base a une table `_schema_migrations` qui stocke :

- `version` : Numéro de la migration
- `nom` : Nom descriptif
- `fichier` : Nom du fichier SQL
- `date_application` : Quand elle a été appliquée
- `duree_ms` : Temps d'exécution
- `succes` : Si elle a réussi
- `checksum` : Hash du contenu (pour détecter les modifications)

## Exemples de migrations courantes

### Ajouter une colonne

```sql
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'client' AND COLUMN_NAME = 'email')
BEGIN
    ALTER TABLE client ADD email NVARCHAR(255) NULL;
END

```

### Modifier le type d'une colonne

```sql
ALTER TABLE client ALTER COLUMN observation NVARCHAR(2000) NULL;
GO
```

### Ajouter un index

```sql
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'IX_client_email')
BEGIN
    CREATE INDEX IX_client_email ON client(email);
END

```

### Ajouter une valeur par défaut

```sql
IF NOT EXISTS (SELECT 1 FROM sys.default_constraints WHERE name = 'DF_client_actif')
BEGIN
    ALTER TABLE client ADD CONSTRAINT DF_client_actif DEFAULT 1 FOR actif;
END

```

### Renommer une colonne

```sql
IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'client' AND COLUMN_NAME = 'ancien_nom')
   AND NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'client' AND COLUMN_NAME = 'nouveau_nom')
BEGIN
    EXEC sp_rename 'client.ancien_nom', 'nouveau_nom', 'COLUMN';
END

```

---

## Integration WinDev

### Structure du ZIP `omag_system.zip`

```
omag_system.zip/
├── Documents/
│   ├── SP_CreationTables.sql
│   ├── commun/
│   │   ├── Sp_Maj_structure.sql
│   │   ├── Sp_Check_Migrations.sql      ← NOUVEAU
│   │   ├── Sp_Init_Migrations_Table.sql ← NOUVEAU
│   │   ├── Sp_Register_Migration.sql    ← NOUVEAU
│   │   └── Sp_Get_Applied_Migrations.sql← NOUVEAU
│   ├── migrations/                       ← NOUVEAU
│   │   ├── 0001_xxx.sql
│   │   ├── 0002_xxx.sql
│   │   └── ...
│   └── ... (autres fichiers SQL)
```

### Procedures stockees pour WinDev

| Procedure                   | Description                                        |
| --------------------------- | -------------------------------------------------- |
| `Sp_Check_Migrations`       | Retourne 1 si `_schema_migrations` existe, 0 sinon |
| `Sp_Init_Migrations_Table`  | Cree la table `_schema_migrations`                 |
| `Sp_Get_Applied_Migrations` | Liste les versions deja appliquees                 |
| `Sp_Register_Migration`     | Enregistre une migration appliquee                 |

### Flux simplifie WinDev

```
Au choix d'un dossier:
  1. EXEC Sp_Check_Migrations
  2. Si retourne 0 (client ancien):
     → Proc_maj_structure()
     → Proc_maj_standard()
  3. Si retourne 1 (client a jour):
     → Proc_AppliquerMigrations() (seulement les manquantes)
```

### Code WinDev

Voir le fichier `CODE_WINDEV.txt` dans ce dossier pour le code complet.

### Avantages pour WinDev

- **Plus de `Version_Analyse`** : Supprimee de la table dossier
- **Plus de `exeVersion`** : Supprimee de la table dossier
- **Rapide** : Quelques millisecondes au lieu de plusieurs minutes
- **Tracable** : On sait exactement ce qui a ete applique
