# Analyse schémas V1 / V2 et scripts d'import ## Sources - **Schéma V1** : `docs/v1-schema.sql` (export pg_dump --schema-only depuis prod, base V1, lecture seule). - **Schéma V2** : `deploy/scripts_v2/schema-v2-initial.sql` (ou Prisma `lecoffre-back-main/prisma/schema.prisma`). - **Script import** : `deploy/scripts_v2/remote/import-v1-data-direct-into-v2.sh` (mode merge). ## 1. Tables traitées par l'import - **Source de la liste** : requête sur la base V1 `information_schema.tables` (schema public, BASE TABLE), tri par nom. - **Exclusions** : `_prisma_migrations`, `system_configuration`, `document_anchors`, `document_notary_anchors`, `office_folder_anchors`. - **Cohérence** : `document_anchors` et `document_notary_anchors` n'existent pas en V1 (tables V2 uniquement) ; les exclure évite toute référence. `office_folder_anchors` existe en V1 mais est exclu volontairement pour ne pas écraser les ancres V2. ## 2. Ordre de merge et dépendances FK (V1) L'ordre est déterminé par `sort_tables_by_dependencies` à partir des FK de la base **cible** (V2). Les dépendances pertinentes côté V1 (schéma) : - **addresses** : référencé par `contacts`, `offices`. - **offices** : référencé par `customers`, `deed_types`, `document_types`, `office_folders`, `office_roles`, `subscriptions`, `users`. - **contacts** : référencé par `customers`, `users`. Donc un ordre cohérent doit avoir : addresses → puis offices et contacts (après addresses) → puis customers, users, office_folders, etc. Le tri topologique du script assure cet ordre. ## 3. Filtre date (import-v1-last-ok) et cohérence FK Quand `IMPORT_V1_LAST_OK_SINCE` est défini, seules les tables **non** listées dans le `case` reçoivent un filtre `WHERE (created_at|updated_at) > since`. Les tables listées sont mergées en totalité (sans filtre). **Règle** : toute table référencée par une table sans filtre doit elle-même être sans filtre, sinon risque de violation FK (ligne importée référence un parent exclu par la date). - **addresses** : parent de `contacts` et `offices`. Si addresses est filtrée et pas contacts/offices → FK `contacts_address_uid_fkey` ou `offices_address_uid_fkey` peut casser. **→ addresses ajoutée à la liste sans filtre.** - **offices** : parent de `customers`, `office_folders`, `deed_types`, `document_types`, `office_roles`, `users`, `subscriptions`. Si offices est filtrée et pas ces tables → FK multiples. **→ offices ajoutée à la liste sans filtre.** - **contacts** : déjà en liste sans filtre (customers.contact_uid_fkey). **Correctif appliqué** : dans le script, la liste des tables sans filtre date inclut désormais `addresses`, `offices`, puis `users`, `subscriptions`, `notifications`, `appointments` (référencés par appointments, documents_notary, seats, user_notifications, votes), en plus de `contacts|deed_types|...`. ## 4. Colonnes différentes V1 / V2 - Le script utilise l’**intersection** des colonnes entre la base temporaire (V1) et la cible (V2). Seules les colonnes présentes des deux côtés sont exportées/importées. - **offices** en V2 a des colonnes supplémentaires (rib_encrypted, office_encryption_key, rib_anchor_*, etc.) ; elles ne sont pas dans V1, donc non exportées → pas d’impact, les lignes V1 sont insérées avec les colonnes communes. - Aucune incohérence bloquante identifiée : pas de colonne obligatoire en V2 absente en V1 pour les tables merge (les colonnes V2-only restent à défaut ou NULL selon le schéma). ## 5. Résumé des incohérences corrigées | Problème | Correction | |----------|------------| | `contacts` filtré par date alors que `customers` non → FK contact_uid | `contacts` mis dans la liste sans filtre (déjà fait). | | `addresses` filtré alors que `contacts` et `offices` non → FK address_uid | `addresses` ajouté à la liste sans filtre. | | `offices` filtré alors que `customers`, `office_folders`, etc. non → FK office_uid | `offices` ajouté à la liste sans filtre. | | `deed` filtré (nom script: deeds) alors que `_DeedHasDocumentTypes`, `office_folders` le référencent → FK _DeedHasDocumentTypes_A_fkey | Liste sans filtre: "deeds" corrigé en "deed" (nom table V1). | `users`, `subscriptions`, `notifications`, `appointments` filtrés alors que `appointments`, `seats`, `user_notifications`, `votes` les référencent → FK | `users`, `subscriptions`, `notifications`, `appointments` ajoutés à la liste sans filtre. | ## 6. V1 n’est jamais modifiée Le script d’import ne fait que **lire** la base V1 (SELECT, COPY TO STDOUT, pg_dump). Aucun INSERT, UPDATE, DELETE, TRUNCATE ni DDL n’est exécuté contre V1. Toutes les écritures ciblent la base V2 ou une base temporaire locale. Voir l’en-tête du script : `# CRITICAL: V1 is READ-ONLY. Never modify V1.` ## 7. Vérifications recommandées (côté V2 / import) - Après tout ajout de colonnes NOT NULL sans défaut ou de nouvelles FK vers des tables importées : revoir l’ordre de merge et la liste des tables sans filtre date (côté script d’import et schéma V2). Cela ne modifie pas V1. - Si de nouvelles tables « parent » sont soumises au filtre date alors que des tables enfants sont sans filtre : les ajouter à la liste sans filtre (comme pour addresses/offices/contacts). - Synchro au login (V1ToV2MergeHelper) : alignée sur l’import du déploiement (--import-v1) — même règle (tables parentes sans filtre date). MERGE_TABLES_WITHOUT_DATE_FILTER = offices, deed, office_folders (sous-ensemble des tables mergées au login). Ne pas modifier le script d’import du déploiement.