Isi-APP Docs fonctionnelles
Toutes les docs
Markdown brut
Demo Account - Export / Import
Actif demo functional Revu le 2026-07-06 demo/demo-account.md

Demo Account - Export / Import

Ce module permet d'exporter les données d'un client existant vers un fichier XLSX, puis de les importer pour créer un nouveau compte client de démonstration.

Cas d'usage

  • Créer des comptes de démonstration à partir de données réelles anonymisées
  • Dupliquer un client pour des tests
  • Préparer des templates de données pré-remplies

Commandes

Export

Exporte toutes les données d'un client vers un fichier XLSX.

php artisan demo:export {source_idc} [--output=chemin]

Arguments: | Argument | Description | |----------|-------------| | source_idc | ID du customer source à exporter |

Options: | Option | Description | |--------|-------------| | --output | Chemin du fichier de sortie (défaut: storage/app/exports/demo_YYYYMMDD_HHMMSS.xlsx) |

Exemple:

# Exporter le client 999
php artisan demo:export 999

# Exporter vers un fichier spécifique
php artisan demo:export 999 --output=exports/template_hopital.xlsx

Import

Importe les données depuis un fichier XLSX pour créer un nouveau client.

php artisan demo:import {file} [options]

Arguments: | Argument | Description | |----------|-------------| | file | Chemin vers le fichier XLSX à importer |

Options: | Option | Description | |--------|-------------| | --target-idc | ID du customer cible (requis pour import réel) | | --target-name | Nom du customer cible (requis pour import réel) | | --dry-run | Prévisualiser sans insérer les données | | --date-offset | Décalage de dates en jours (défaut: auto) | | --skip-validation | Ignorer la validation du fichier | | --force | Forcer l'import même avec des avertissements |

Exemples:

# Prévisualisation (dry-run)
php artisan demo:import storage/app/exports/demo.xlsx --dry-run

# Import réel
php artisan demo:import storage/app/exports/demo.xlsx --target-idc=888 --target-name="Hôpital Demo"

# Import avec décalage de dates personnalisé (30 jours)
php artisan demo:import storage/app/exports/demo.xlsx --target-idc=888 --target-name="Demo" --date-offset=30

# Forcer l'import malgré les avertissements
php artisan demo:import storage/app/exports/demo.xlsx --target-idc=888 --target-name="Demo" --force

Commandes d'instance (Hospital, Mairie, Stinglay)

php artisan demo:hospital {idc} {name} [options]
php artisan demo:mairie   {idc} {name} [options]
php artisan demo:stinglay {idc} {name} [options]

Options: | Option | Description | |--------|-------------| | --reset | Purge toutes les données de l'idc avant import | | --merge | Fusionne le template avec l'instance existante (mode idempotent) | | --dry-run | Simule l'import sans rien écrire en DB | | --force-restore | Ignore les tombstones et recrée les lignes seed supprimées par le PO (nécessite --merge) |

Exemples:

# Créer ou réinitialiser
php artisan demo:hospital 985 "Hôpital Providence Sud" --reset

# Mettre à jour un compte existant (merge idempotent)
php artisan demo:hospital 985 "Hôpital Providence Sud" --merge

# Merge en ignorant les suppressions PO (force-restore)
php artisan demo:hospital 985 "Hôpital Providence Sud" --merge --force-restore

# Prévisualiser un merge sans rien écrire
php artisan demo:hospital 985 "Hôpital Providence Sud" --merge --dry-run

Mode merge (--merge)

Le mode merge permet de remettre à jour un compte de démonstration existant sans écraser les modifications apportées par le PO ou l'équipe commerciale.

Stratégies de merge

Trois stratégies coexistent selon le type de données :

1. SemiIdempotentMergeStrategy (tables configurables)

Pour les tables avec des colonnes SEED (données template) et des colonnes FREE (données PO). Le merge met à jour uniquement les colonnes SEED en préservant les colonnes FREE.

2. NonIdempotentMergeStrategy (24 tables)

Pour les tables dont les données ne peuvent pas être réconciliées ligne par ligne (événements, interventions, équipements, tâches, projets...).

Comportement : delete ciblé des lignes seed (via demo_seed_map) + re-insert complet à chaque merge. Les lignes créées par le PO ne sont jamais touchées.

Tables concernées : cyber_ev, customer_event, dsi_hw, dsi_lic, _com_interv, _com_contr, equipment_types, crm_aff, cust_suivi, dsi_hw_users, project_step, project_news, project_meeting, project_backlog, equipments, project_kpival, _com_task, _com_livrable, equipment_counters, project_crit, risk_mesure, risk_item, project_matrice, project_for

3. SkipIfExistsMergeStrategy (2 tables)

Pour les tables où la présence de données PO active indique une appropriation métier complète du module.

Comportement : si le tenant a des lignes actives (hors dtdel), les données seed sont entièrement ignorées pour cette table.

Tables concernées : tickets, crm_miss


Tombstones

Un tombstone est une ligne seed supprimée par le PO (hard delete ou soft delete dtdel). Le système détecte ces suppressions avant chaque merge et les enregistre dans demo_seed_map avec deleted_by_po=1.

Comportement par défaut (sans --force-restore) :

  • Les tombstones ne sont pas re-insérés lors du merge suivant.
  • Des avertissements sont affichés en sortie de commande.

Comportement avec --force-restore :

  • Les tombstones sont ignorés : toutes les lignes seed sont re-insérées comme si elles n'avaient jamais été supprimées.
  • À utiliser quand le PO a fait une erreur de suppression ou après une réinitialisation partielle.

Note : --force-restore ne fonctionne qu'avec --merge. Le SkipIfExistsMergeStrategy n'est pas affecté par --force-restore (protection des données PO actives).


Format du fichier XLSX

Onglet _config

Premier onglet obligatoire contenant les métadonnées:

Clé Valeur Description
version 1.0 Version du format
source_idc 999 ID du client source
export_date 2026-01-13 10:30:00 Date d'export
target_idc (vide) Rempli à l'import
target_name (vide) Rempli à l'import

Onglets de tables

Chaque table a son propre onglet avec:

  • Ligne 1: Noms des colonnes (correspondant aux colonnes DB)
  • Ligne 2: Métadonnées (PK, FK:table.col, DATE, R=requis, O=optionnel)
  • Ligne 3+: Données

Convention des IDs temporaires

Les IDs sont remplacés par des identifiants temporaires au format:

TEMP_{TABLE}_{NNNN}

Exemples:

  • TEMP_CUSTOMER_0001
  • TEMP_USERS_0042
  • TEMP_PROJECT_0003

Ces IDs permettent de maintenir les relations entre les enregistrements. À l'import, ils sont automatiquement remplacés par les vrais IDs générés.


Tables supportées

L'import/export gère 45+ tables organisées par niveau de dépendance:

Niveau Tables
0 customer
1 customer_addr, users, _customer_sub, customer_group, customer_event, crm_cust, customer_fac, dsi_param, dsi_param_po, customer_ask_system, supplier
2 customer_addr_bat, users_profile, dsi_hw, dsi_hwvm, dsi_con, dsi_app, dsi_lic, dsi_tel, dsi_planip, tickets, _com_interv, _com_contr, customer_act_san, customer_act_ms, _com_wiki, _com_know, project
3 customer_addr_bat_lo, project_team, project_step, project_role, project_news, project_danger, project_kpi, project_meeting, project_budget
4 customer_addr_bat_lo_loc, customer_addr_bat_lo_pi, project_kpival, _com_task, _com_acl, _term

Décalage des dates

Pour les commandes d'instance (demo:hospital, demo:mairie, demo:stinglay), les dates sont automatiquement fraîches à chaque exécution : le template génère ses dates via Carbon::now() et la valeur export_date est positionnée à l'heure courante, ce qui donne un décalage effectif de 0 jours.

Pour les imports depuis fichier XLSX (demo:import), le décalage est calculé automatiquement à partir de la date d'export contenue dans l'onglet _config.

Valeurs du paramètre dateOffsetDays (API interne) : | Valeur | Comportement | |--------|-------------| | -1 | Auto : calcule le décalage depuis export_date (défaut pour demo:import) | | 0 | Aucun décalage (dates importées telles quelles) | | N > 0 | Décalage forcé de N jours |

Pour désactiver le décalage sur un import fichier : --date-offset=0


Données par défaut

Si un onglet est absent ou vide dans le fichier XLSX, des données par défaut peuvent être insérées pour certaines tables (ex: project). Ceci est configurable dans DefaultDataConfig.php.


Transformations automatiques

À l'import, certaines données sont automatiquement transformées:

Table Transformation
customer SIRET unique généré, email modifié
users Email rendu unique (format email+demoXXX@domain), mot de passe hashé
Toutes Colonne _id mise à jour vers le target_idc

Validation

Avant l'import, le fichier est validé:

  1. Structure: Présence de _config, colonnes requises
  2. Références: Vérification que les FK pointent vers des IDs existants
  3. Données: Colonnes obligatoires remplies

Les erreurs bloquent l'import. Les avertissements sont affichés mais n'empêchent pas l'import (sauf si --force n'est pas utilisé).


Architecture technique

app/
├── Services/DemoAccount/
│   ├── DemoAccountService.php           # Façade principale
│   ├── Config/
│   │   ├── TableConfig.php              # PK, FK, dates par table
│   │   └── DefaultDataConfig.php        # Données par défaut
│   ├── Export/
│   │   └── DemoExporter.php
│   ├── Import/
│   │   ├── DemoImporter.php
│   │   └── Validators/XlsxValidator.php
│   └── Helpers/
│       ├── IdMappingHelper.php          # Mapping temp_id → real_id
│       └── DateOffsetHelper.php
├── Exports/DemoAccount/
│   ├── DemoAccountExport.php
│   └── Sheets/
│       ├── ConfigSheet.php
│       └── TableSheet.php
└── Console/Commands/DemoAccount/
    ├── ExportDemoCommand.php
    └── ImportDemoCommand.php

Utilisation programmatique

use App\Services\DemoAccount\DemoAccountService;

$service = new DemoAccountService();

// Export
$filePath = $service->export(999, 'exports/demo.xlsx');

// Validation
$result = $service->validate('storage/app/exports/demo.xlsx');
if (!$result->isValid) {
    foreach ($result->errors as $error) {
        echo $error;
    }
}

// Import
$result = $service->import(
    filePath: 'storage/app/exports/demo.xlsx',
    targetIdc: 888,
    targetName: 'Mon Client Demo',
    dryRun: false,
    dateOffsetDays: -1 // auto
);

if ($result->success) {
    echo "Import réussi: {$result->statistics['customer']['inserted']} customers créés";
}

Troubleshooting

Erreur "Duplicate entry for key 'PRIMARY'"

Le target_idc existe déjà. Choisissez un autre ID.

Erreur "Column cannot be null"

Une colonne NOT NULL n'a pas de valeur dans le fichier. Vérifiez les données ou ajoutez une valeur par défaut dans DefaultDataConfig.php.

Avertissements de références introuvables

Des FK pointent vers des enregistrements non exportés (utilisateurs supprimés, etc.). Ces références seront nulles à l'import.

Décalage de dates incorrect

Utilisez --date-offset=N pour forcer un décalage spécifique en jours.

Tombstones persistants après --force-restore

Si une ligne n'est toujours pas recréée après --force-restore, vérifier qu'elle n'est pas aussi filtrée par une collision PK (tables non auto-increment). Consulter les warnings de la commande.


Voir aussi

  • Scénarios de validation SQL (merge) : docs/demo/demo-merge-tests.md
  • Documentation technique instances : .claude/technical-docs/demo/demo-instances.md