Aller au contenu principal

Import en masse

Le problème

Un utilisateur a un CSV (ou XLSX) avec des centaines de lignes et veut les importer dans une table — nouveaux clients d'un salon professionnel, produits d'un catalogue fournisseur, contrats d'une migration. Il ne veut pas saisir chacun via le dialogue d'édition.

Le modèle

Deux parties :

  1. Une action d'écran qui ouvre un dialogue d'Import avec un sélecteur de fichier.
  2. Un job Nomaflow déclenché par le téléversement qui parse le fichier, valide chaque ligne, effectue des upserts, renvoie un rapport par ligne.

Le framework parse le fichier (CSV / XLSX / TSV) ; votre seul travail est de déclarer le mapping entre colonnes source et colonnes cibles.

La recette

1. Préparation du schéma

Si votre table cible a besoin d'une clé externe pour détecter les doublons (et décider insert vs update), assurez-vous qu'elle existe :

ALTER TABLE customers
ADD COLUMN external_code VARCHAR(64) UNIQUE;

L'import en masse mettra en correspondance les lignes entrantes avec cette colonne.

2. Définir le connecteur d'import

Paramètres → Connecteurs → customers → + Ajouter requête :

-- upsert
INSERT INTO customers (external_code, name, status, country)
VALUES (:external_code, :name, :status, :country)
ON CONFLICT (external_code) DO UPDATE SET
name = EXCLUDED.name,
status = EXCLUDED.status,
country = EXCLUDED.country,
updated_by = :session_user,
updated_at = CURRENT_TIMESTAMP;

Opération : Write. Déclarez les quatre paramètres.

Pour Oracle / SQLite, remplacez ON CONFLICT par l'équivalent (MERGE sur Oracle, INSERT OR REPLACE sur SQLite).

3. Construire le job d'import

Paramètres → Jobs → + Nouveau job :

ChampValeur
Nomcustomers-bulk-import
App<app>
Schedulevide (déclenchement manuel uniquement)
Instance unique

Deux étapes :

Étape 1 — parser le fichier

ChampValeur
Nomparse
TypePython
Callableliberty.builtin.bulk_import:parse_file (helper du framework)
Kwargsfile_url = ${params.file_url}, mapping = { "Customer code": "external_code", "Name": "name", "Country": "country", "Status": "status" }

Le helper :

  • Détecte CSV / XLSX depuis l'extension du fichier.
  • Parse les en-têtes ; les met en correspondance avec le mapping.
  • Renvoie une liste de lignes avec les noms de colonnes cibles.

Étape 2 — upsert chaque ligne

ChampValeur
Nomupsert
TypePython
Callableliberty.builtin.bulk_import:upsert_rows
Kwargsrows = ${steps.parse.rows}, connector = "customers", query = "upsert", chunk_size = 500

Le helper :

  • Découpe les lignes en morceaux de 500.
  • Appelle la requête upsert par ligne, capture succès et échecs.
  • Renvoie { "ok": 487, "failed": 13, "failures": [...] }.

Les paramètres du job exposent file_url — déclaré sur l'onglet Paramètres.

4. Ajouter l'action d'écran

Paramètres → Écrans → customers → onglet Actions → + Bouton personnalisé au niveau de la barre d'outils (pas le dialogue) :

ChampValeur
Label↑ Importer
Iconupload
VariantSecondary
ActionExécuter le job
Jobcustomers-bulk-import
Dialogue de paramètres(affiche le sélecteur de fichier avant exécution)

5. Permissions

Accordez job:customers-bulk-import aux rôles autorisés à importer. Passez pour les rôles en lecture seule.

Voir le résultat

Ouvrez l'écran Customers, cliquez sur ↑ Importer. Le framework affiche un dialogue avec un sélecteur de fichier. Déposez un CSV, cliquez sur Exécuter. La page de détail d'exécution du job s'ouvre avec une queue de log en direct ; à la fin vous voyez « 487 importés, 13 échoués », avec les échecs listés par ligne (numéro de ligne + message d'erreur).

Variantes

Vous voulez…Faites ceci
Valider avant d'importerAjoutez une étape entre parse et upsert qui exécute une validation par ligne. Renvoyez la liste d'erreurs ; arrêtez le job s'il y en a.
Afficher un aperçu avant validationExécutez le job en mode dry_run = true ; le helper upsert_rows accepte ce flag et ne journalise que ce qu'il ferait. Puis un second clic déclenche l'exécution réelle.
Annuler sur toute erreurEncadrez les upserts dans une transaction ; le helper a un mode transactional = true.
Planifier un import quotidien depuis S3Même job, définissez un planning cron + remplacez l'étape 1 par une étape http qui tire depuis S3.

Pour aller plus loin