
# Charger des données

Une application fraîchement installée a un schéma et aucune ligne. `sovrium seed` la
remplit à partir de fichiers que vous gardez à côté de votre configuration, pour qu'un
nouveau clone s'ouvre sur une application vivante plutôt que sur une grille vide.

```bash
sovrium seed
```

La commande lit `seed/<table>.yaml`, résout les liens entre enregistrements, développe
les jetons de date, puis écrit par le même chemin de code que l'API REST. Aucun serveur
n'a besoin de tourner.

## Le répertoire des données

Un fichier par table, nommé d'après la table :

```
mon-app/
  app.yaml
  config/tables/companies.yaml
  config/tables/contacts.yaml
  seed/companies.yaml
  seed/contacts.yaml
```

`seed/companies.yaml` :

```yaml
records:
  - key: northwind
    fields:
      name: Northwind Trading
      industry: Retail
```

`seed/contacts.yaml` :

```yaml
records:
  - key: priya
    fields:
      name: Priya Raman
      email: priya@northwind.example
      company: '@companies.northwind'
      last_contacted: '{{today-3d}}'
```

Les tables sont écrites parents d'abord. Vous n'avez pas à ordonner les fichiers
vous-même : la commande lit vos champs de relation et en déduit l'ordre. Un vrai cycle
est refusé en le nommant, jamais deviné.

## Lier des enregistrements avec `key`

`key` nomme un enregistrement à l'intérieur de vos fichiers. Il n'est jamais écrit dans
une colonne ni présent dans votre base : il existe pour qu'un enregistrement puisse en
désigner un autre avant que l'un ou l'autre ait un identifiant.

Référencez-le depuis un autre fichier avec `@<table>.<key>` :

```yaml
company: '@companies.northwind'
```

Un champ plusieurs-à-plusieurs prend une liste :

```yaml
tags: ['@tags.urgent', '@tags.renewal']
```

Pour une relation un-à-plusieurs, la clé étrangère se trouve sur l'enfant : vous chargez
donc les enfants en désignant le parent, et non le parent listant ses enfants.

## Des dates qui restent à jour

Une date figée vieillit. Un pipeline dont toutes les affaires se sont conclues au
printemps se lit comme abandonné à l'automne, et un calendrier rempli de jours fixes est
vide dès qu'on regarde un autre mois.

Écrivez les dates relativement au jour où le chargement s'exécute :

```yaml
close_date: '{{today+21d}}'
last_contacted: '{{today-3d}}'
due: '{{today}}'
```

Chaque rejeu les recalcule : une démonstration réinitialisée chaque nuit montre toujours
du travail en cours.

## Modes

| Mode       | Comportement                                                                                                  |
| ---------- | ------------------------------------------------------------------------------------------------------------- |
| `if-empty` | Par défaut. Ne charge une table que si elle est vide. Rejouable sans risque.                                  |
| `upsert`   | Rapproche les lignes existantes par une clé naturelle et les met à jour ; crée les autres.                    |
| `replace`  | Supprime les lignes de la table, puis insère. Pour les environnements de démonstration qui se réinitialisent. |

```bash
sovrium seed --mode replace
```

`if-empty` compte les lignes supprimées en douceur comme présentes : une table que vous
avez vidée depuis l'application n'est pas silencieusement remplie à nouveau dans votre dos.

### Choisir sur quoi `upsert` fait le rapprochement

`upsert` doit savoir quelle colonne identifie une ligne existante. Déclarez-la en tête de
fichier :

```yaml
mergeOn: [email]
records:
  - key: priya
    fields:
      email: priya@northwind.example
      name: Priya Raman
```

Sans `mergeOn`, la commande utilise l'unique champ `unique` de la table. Si la table n'en
a aucun, ou plus d'un, elle s'arrête et vous demande : se rapprocher sur la mauvaise
colonne écraserait des enregistrements sans rapport, donc elle ne devine pas.

Notez que `mergeOn` et `key` sont deux choses différentes. `key` lie des enregistrements
à l'intérieur de vos fichiers ; `mergeOn` nomme de vraies colonnes de votre base.

## Options

| Option           | Signification                                                                                                                                         |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `[config]`       | Fichier de configuration. Par défaut `./app.yaml`.                                                                                                    |
| `--dir <chemin>` | Répertoire des données. Par défaut un dossier `seed` à côté du fichier de configuration. Un chemin explicite est résolu depuis le répertoire courant. |
| `--mode <mode>`  | `if-empty`, `upsert` ou `replace`. Par défaut `if-empty`.                                                                                             |
| `--table <nom>`  | Ne charger que cette table. Répétable.                                                                                                                |
| `--dry-run`      | Rapporter ce qui serait écrit, sans rien écrire.                                                                                                      |

Le répertoire par défaut suit le fichier de configuration plutôt que votre shell : la même
commande se comporte à l'identique que vous l'exécutiez depuis la racine du projet ou
depuis une unité de service au répertoire courant différent.

## Pièces jointes

Placez les fichiers dans `seed/assets/` et référencez-les par leur nom :

```yaml
logo: '@asset:northwind-logo.avif'
```

Le fichier est téléversé et la clé de stockage est écrite dans le champ.

## Ce que le chargement ne fait pas

**Il n'exécute pas vos automatisations.** Les enregistrements sont écrits directement :
une automatisation qui réagit à la création d'un enregistrement ne se sera donc pas
déclenchée. Si la valeur de démonstration de votre application dépend de ce que produit
une automatisation — un journal d'activité, un statut dérivé — chargez-le aussi, écrit
comme l'automatisation l'aurait écrit.

**Certains champs sont refusés plutôt qu'écrits à moitié**, chacun avec un message
nommant le fichier et l'enregistrement :

- Une relation pointant vers sa propre table demande deux passes et n'est pas encore prise en charge.
- Un champ de pièce jointe sur un bucket autre que `default`.
- `upsert` sur une table dont les données portent des liens plusieurs-à-plusieurs.

Ce refus est délibéré. Écrire la ligne en abandonnant les liens vous laisserait des
données qui ont l'air complètes et ne le sont pas.

## Quand un enregistrement est rejeté

Le message nomme le fichier, l'enregistrement, le champ, la valeur et la raison :

```
companies.yaml (key "northwind"): field "size" — 201 is not one of the declared
options ('1-10', '11-50', '51-200', '201-1000', '1000+') — the submitted value is a
number; quote it in YAML to keep it a string [CHECK constraint failed: check_size_enum]
```

### Mettez entre guillemets les valeurs de sélection commençant par un chiffre

Cet exemple est la surprise la plus fréquente. YAML lit un scalaire commençant par un
chiffre comme un nombre, et un intervalle ou un suffixe en fin de valeur ne l'en empêche
pas :

| Vous écrivez     | YAML vous donne |
| ---------------- | --------------- |
| `size: 201-1000` | `201`           |
| `size: 1000+`    | `1000`          |
| `code: 07`       | `7`             |
| `qty: 1e3`       | `1000`          |
| `rate: 2.0`      | `2`             |

Mettez-les entre guillemets, et la valeur survit :

```yaml
size: '201-1000'
```

`yes`, `no`, `on` et `off` sont lus comme des chaînes : ils n'ont pas besoin de guillemets.

## Travailler sur les données

`--dry-run` rapporte le plan sans toucher à la base :

```bash
sovrium seed --dry-run
```

```
[dry-run] companies: would create 5 records
[dry-run] contacts: would create 7 records
[dry-run] no changes written
```

Pour itérer sur un seul fichier, restreignez l'exécution :

```bash
sovrium seed --table contacts --mode replace
```
