# Migration Mapping — Ancienne BDD → Nouvelle BDD v2

> Basé sur la comparaison directe des DDL : `ancienne_bdd.sql` (amc_database) et `nouvelle_bdd.sql` (amc_database_v2)
>
> Convention : `→` = mapping direct | `UUID()` = générer un nouveau UUID | `NULL` = pas d'équivalent | `RESOLVE` = résoudre l'UUID via lookup

---

## Règles générales

- Ancienne BDD : clés primaires `id` (BIGINT AUTO_INCREMENT)
- Nouvelle BDD : clés primaires `uuid` (CHAR(36))
- Toutes les FK de l'ancienne BDD référencent des `id` entiers → doivent être résolues en UUID via une table de correspondance `id_to_uuid`
- Générer un UUID pour chaque ligne migrée et conserver la correspondance `ancien_id → nouveau_uuid`

---

## 1. `entreprises` → `companies` + `companies_infos` + `companies_hashtags`

### 1a. `entreprises` → `companies`

| Ancienne colonne | Nouvelle colonne | Remarque |
|---|---|---|
| `id` | — | Conserver dans table de correspondance |
| `name` | `name` | Direct |
| `sector` | `sector` | Direct (vérifier les valeurs ENUM) |
| `logo` | `media_id` | Créer une entrée dans `medias` avec `public_url = logo`, puis mettre l'UUID ici |
| `created_at` | `created_at` | Direct |
| `updated_at` | `updated_at` | Direct |
| `description` | → `companies_infos.description` | Voir 1b |
| `vision` | → `companies_infos.vision` | Voir 1b |
| `ton_editorial` | → `companies_infos.editorial_guidelines` | Voir 1b |
| `valeurs` | → `companies_infos.values` | Voir 1b |
| `tonalites_valeurs` | → `companies_infos.value_tone` | Voir 1b |
| `weekly_post_objective` | → `companies_infos.weekly_post_count` | Voir 1b |
| `analyse_editoriale` | → `companies_infos.editorial_guidelines` | Fusionner avec `ton_editorial` si besoin |
| `hashtags_recommandes` | → `companies_hashtags` type `recommandes` | Voir 1c |
| `hashtags_signature` | → `companies_hashtags` type `signature` | Voir 1c |
| `hashtags_metier` | → `companies_hashtags` type `metier` | Voir 1c |
| `hashtags_valeurs_tonalite` | → `companies_hashtags` type `valeurs_tonalite` | Voir 1c |
| `hashtags_opportunite` | → `companies_hashtags` type `opportunity` | Voir 1c |
| `hashtags_evenement` | → `companies_hashtags` type `event` | Voir 1c |
| `monthly_post_objective` | — | Abandonné (pas d'équivalent v2) |
| `is_active` | — | Abandonné (pas de champ dans `companies`) |

### 1b. `entreprises` → `companies_infos`

Créer une ligne par entreprise.

| Source (`entreprises`) | Destination (`companies_infos`) | Remarque |
|---|---|---|
| UUID() | `uuid` | Générer |
| `id` → UUID | `company_id` | RESOLVE |
| `description` | `description` | Direct |
| `vision` | `vision` | Direct |
| `ton_editorial` / `analyse_editoriale` | `editorial_guidelines` | Fusionner |
| `valeurs` | `values` | Direct (JSON) |
| `tonalites_valeurs` | `value_tone` | Direct (JSON) |
| `weekly_post_objective` | `weekly_post_count` | Direct |
| — | `linkedin_url` | NULL |
| — | `website` | NULL |
| — | `employer_count` | NULL |
| — | `company_version` | NULL |
| — | `require_referent_validation` | 0 par défaut |

### 1c. `entreprises` → `companies_hashtags`

Pour chaque champ hashtag non NULL, créer une ligne dans `companies_hashtags` :

| Source (`entreprises`) | `hashtag_type` | `content_hashtag` |
|---|---|---|
| `hashtags_recommandes` | `recommandes` | valeur JSON |
| `hashtags_signature` | `signature` | valeur JSON |
| `hashtags_metier` | `metier` | valeur JSON |
| `hashtags_valeurs_tonalite` | `valeurs_tonalite` | valeur JSON |
| `hashtags_opportunite` | `opportunity` | valeur JSON |
| `hashtags_evenement` | `event` | valeur JSON |

---

## 2. `users` → `users`

| Ancienne colonne | Nouvelle colonne | Remarque |
|---|---|---|
| `id` | — | Conserver dans table de correspondance |
| `first_name` | `firstname` | Renommé |
| `last_name` | `lastname` | Renommé |
| `email` | `email` | Direct |
| `phone` | `telephone` | Renommé |
| `fonction` | `fonction` | Direct |
| `role` | `role` | Direct (vérifier ENUM : v2 ajoute `admin` et `consultant`) |
| `entreprise_id` → UUID | `company_id` | RESOLVE |
| `linkedin_id` | `linkedin_id` | Direct |
| `linkedin_connected_at` | `linkedin_connected_at` | Direct |
| `is_active` | `is_active` | Direct |
| `password` | `password` | Direct |
| `editorial_persona_id` → UUID | `editorial_persona_id` | RESOLVE |
| `last_login_at` | `last_login` | Renommé |
| `last_logout_at` | `last_logout` | Renommé |
| — | `last_activity` | NULL |
| — | `profile_picture_media_id` | NULL (pas de photo de profil dans ancienne BDD users) |
| `email_verified_at` | — | Abandonné |
| `remember_token` | — | Abandonné |
| `first_login_at` | — | Abandonné |
| `linkedin_objectives` | → `linkedin_profiles.linkedin_objectif` | Voir section 10 |
| `expertise_themes` | → `linkedin_profiles.expertise_themes` | Voir section 10 |
| `target_audience` | → `linkedin_profiles.target_audience` | Voir section 10 |
| `professional_positioning` | → `linkedin_profiles.professionnal_positioning` | Voir section 10 |
| `core_values` | → `linkedin_profiles.core_values` | Voir section 10 |
| `topics_to_avoid` | → `linkedin_profiles.topic_id_avoid_communication_tone` | Voir section 10 |
| `communication_tone` | — | Abandonné (pas d'équivalent direct) |
| `industry_sector` | — | Abandonné |

---

## 3. `pending_posts` → `companies_posts`

| Ancienne colonne | Nouvelle colonne | Remarque |
|---|---|---|
| `id` | — | Conserver dans table de correspondance |
| UUID() | `uuid` | Générer |
| `company_name` → UUID | `company_id` | RESOLVE via `companies.name` ou table de correspondance |
| `user_id` → UUID | `user_id` | RESOLVE |
| `author_id` → UUID | `author_id` | RESOLVE |
| `linkedin_post_id` | `linkedin_post_id` | Direct |
| `linkedin_url` | `linkedin_url` | Direct |
| `content` | `content` | Direct |
| `tone` | `tone` | Direct |
| `target_audience` | `target_audience` | Direct |
| `content_type` | `post_type` | Mapper les valeurs (ex: `post` → `texte`) |
| `media_type` | `media_type` | Direct |
| `hashtags` | `hashtags` | Direct (JSON) |
| `publication_status` | `publication_status` | Direct |
| `status` | `status` | Direct |
| `workflow_step` | `workflow_step` | Direct |
| `created_by_role` | `created_by_role` | Direct |
| `published_at` | `published_at` | Direct |
| `reviewed_at` | `reviewed_at` | Direct |
| `validated_at` | `validated_at` | Direct |
| `reminder_sent_at` | `reminder_sent_at` | Direct |
| `review_notes` | `review_notes` | Direct |
| `rejection_reason` | `rejection_reason` | Direct |
| `rejected_by` → UUID | `rejected_by` | RESOLVE |
| `last_reminder_sent_at` | `last_reminder_sent_at` | Direct |
| `draft_reminder_sent_at` | `draft_reminder_sent_at` | Direct |
| `queued_at` | `queued_at` | Direct |
| `scheduled_at` | `scheduled_at` | Direct |
| `original_scheduled_at` | `original_scheduled_at` | Direct |
| `change_reason` | `change_reason` | Direct |
| `likes` | `like_count` | Renommé |
| `comments` | `comments_count` | Renommé |
| `shares` | `shares_count` | Renommé |
| `views` | `views_count` | Renommé |
| `reach` | `reach_count` | Renommé |
| `engagement_rate` | `engagement_rate` | Direct |
| `ai_analysis` | `ai_analysis` | Direct (JSON) |
| `ai_analysis_version` | `ai_analysis_version` | Direct |
| `ai_analyzed_at` | `ai_analyzed_at` | Direct |
| `created_at` | `created_at` | Direct |
| `updated_at` | `updated_at` | Direct |
| `media_urls` | `media_library_id` | NULL (pas de mapping direct, les médias sont dans `medias_libraries`) |
| `referent_id` | — | Abandonné |
| `publish_type` | — | Abandonné |
| `linkedin_published` | — | Abandonné (remplacé par `publication_status`) |
| `destination_type` | — | Abandonné |
| `assigned_to` | — | Abandonné |
| `author_name` | — | Abandonné |

---

## 4. `news` → `actualities`

| Ancienne colonne | Nouvelle colonne | Remarque |
|---|---|---|
| `id` | — | Conserver dans table de correspondance |
| UUID() | `uuid` | Générer |
| `title` | `title` | Direct |
| `content` | `content` | Direct |
| `excerpt` | `excerpt` | Direct |
| `image_url` | `image_url` | Direct |
| `entreprise_id` → UUID | `company_id` | RESOLVE |
| — | `media_id` | NULL |
| — | `statut` | 0 par défaut |
| `created_at` | `created_at` | Direct |
| `updated_at` | `updated_at` | Direct |

---

## 5. `competitors` → `competitors`

| Ancienne colonne | Nouvelle colonne | Remarque |
|---|---|---|
| `id` | — | Conserver dans table de correspondance |
| UUID() | `uuid` | Générer |
| `name` | `name` | Direct |
| `sector` | `sector` | Direct |
| `description` | `description` | Direct |
| `linkedin_url` | `linkedin_url` | Direct |
| `website` | `website` | Direct |
| `employees_count` | `employees_count` | Direct |
| — | `media_id` | NULL (pas de logo dans ancienne BDD) |
| `created_at` | `created_at` | Direct |
| `updated_at` | `updated_at` | Direct |
| `market_position` | — | Abandonné |

---

## 6. `competitor_entreprise` → `company_competitor`

| Ancienne colonne | Nouvelle colonne | Remarque |
|---|---|---|
| `competitor_id` → UUID | `competitor_id` | RESOLVE |
| `entreprise_id` → UUID | `company_id` | RESOLVE |
| `created_at` | `created_at` | Direct |
| `updated_at` | `updated_at` | Direct |

---

## 7. `post_competiteur` → `competitor_post`

| Ancienne colonne | Nouvelle colonne | Remarque |
|---|---|---|
| `id` | — | Conserver dans table de correspondance |
| UUID() | `uuid` | Générer |
| `linkedin_url` | `post_url` | Renommé |
| `contenu` | `content` | Renommé |
| `date_creation` + `heure_creation` | `publication_date` | Combiner en TIMESTAMP |
| `heure_creation` | `publication_time` | Direct (varchar) |
| `hashtags` | `hashtag` | Renommé (TEXT → JSON : parser si besoin) |
| `competitor_id` → UUID | `competitor_id` | RESOLVE |
| `format` | `post_type` | Renommé |
| `author_name` | `author_name` | Direct |
| `likes` | `like_count` | Renommé |
| `commentaires` | `comment_count` | Renommé |
| `shares` | `share_count` | Renommé |
| `views` | `views_count` | Renommé |
| `impressions` | `impressions_count` | Renommé |
| `engagement_rate_calculated` | `engagement_rate_calculated` | Direct |
| `engagement_rate` | `engagement_rate` | Direct |
| `detected_theme` | `detected_theme_id` | RESOLVE via `communication_themes.name` → UUID |
| `detected_tone` | `detected_tone_id` | RESOLVE via `tone_definitions.name` → UUID |
| `sentiment_score` | `sentiment_score` | Direct |
| `analyzed_at` | `analyzed_at` | Direct |
| `created_at` | `created_at` | Direct |
| `updated_at` | `updated_at` | Direct |
| `media_type` | — | Abandonné |

---

## 8. `competitor_post_comments` → `competitor_comment`

| Ancienne colonne | Nouvelle colonne | Remarque |
|---|---|---|
| `id` | — | Conserver dans table de correspondance |
| UUID() | `uuid` | Générer |
| `post_competiteur_id` → UUID | `competitor_post_id` | RESOLVE |
| `contenu_commentaire` | `content` | Renommé |
| `nom_auteur_commentaire` | `author_name` | Renommé |
| `poste_auteur` | `author_post` | Renommé |
| `created_at` | `created_at` | Direct |
| `updated_at` | `updated_at` | Direct |

---

## 9. `competitor_post_likes` → `competitor_likes`

| Ancienne colonne | Nouvelle colonne | Remarque |
|---|---|---|
| `id` | — | Conserver dans table de correspondance |
| UUID() | `uuid` | Générer |
| `post_competiteur_id` → UUID | `competitor_post_id` | RESOLVE |
| `type_like` | `like_type` | Renommé |
| `nom_personne` | `author_name` | Renommé |
| `poste_occupe` | `author_post` | Renommé |
| `created_at` | `created_at` | Direct |
| `updated_at` | `updated_at` | Direct |

---

## 10. `comments_posts` → `companies_comments`

| Ancienne colonne | Nouvelle colonne | Remarque |
|---|---|---|
| `id` | — | Conserver dans table de correspondance |
| UUID() | `uuid` | Générer |
| `post_id` → UUID | `company_post_id` | RESOLVE |
| `contenu_commentaire` | `content` | Renommé |
| `nom_auteur_commentaire` | `author_name` | Renommé |
| `poste_auteur` | `author_title` | Renommé |
| `created_at` | `created_at` | Direct |
| `updated_at` | `updated_at` | Direct |

---

## 11. `likes_posts` → `company_likes`

| Ancienne colonne | Nouvelle colonne | Remarque |
|---|---|---|
| `id` | — | Conserver dans table de correspondance |
| UUID() | `uuid` | Générer |
| `post_id` → UUID | `company_post_id` | RESOLVE |
| `type_like` | `like_type` | Renommé (vérifier ENUM v2) |
| `nom_personne` | `author_name` | Renommé |
| `poste_occupe` | `author_title` | Renommé |
| `created_at` | `created_at` | Direct |
| `updated_at` | `updated_at` | Direct |

---

## 12. `testimonials` → `testimonials`

| Ancienne colonne | Nouvelle colonne | Remarque |
|---|---|---|
| `id` | — | Conserver dans table de correspondance |
| UUID() | `uuid` | Générer |
| `content` | `content` | Direct |
| `rating` | `rating` | Direct |
| `entreprise_id` → UUID | `company_id` | RESOLVE |
| `created_by` → UUID | `created_by` | RESOLVE |
| — | `statut` | 0 par défaut |
| `created_at` | `created_at` | Direct |
| `updated_at` | `updated_at` | Direct |

---

## 13. `communication_themes` → `communication_themes`

| Ancienne colonne | Nouvelle colonne | Remarque |
|---|---|---|
| `id` | — | Conserver dans table de correspondance |
| UUID() | `uuid` | Générer |
| `name` | `name` | Direct |
| `keywords` | `keywords` | Direct (JSON) |
| `description` | `description` | Direct |
| `created_at` | `created_at` | Direct |
| `updated_at` | `updated_at` | Direct |

---

## 14. `tone_definitions` → `tone_definitions`

| Ancienne colonne | Nouvelle colonne | Remarque |
|---|---|---|
| `id` | — | Conserver dans table de correspondance |
| UUID() | `uuid` | Générer |
| `name` | `name` | Direct |
| `description` | `description` | Direct |
| `keywords` | `keywords` | Direct (JSON) |
| `created_at` | `created_at` | Direct |
| `updated_at` | `updated_at` | Direct |

---

## 15. `editorial_personas` → `editorial_personas`

| Ancienne colonne | Nouvelle colonne | Remarque |
|---|---|---|
| `id` | — | Conserver dans table de correspondance |
| UUID() | `id` (CHAR(36) en v2) | Générer |
| `persona_editorial` | `persona_editorial` | Direct |
| `role_strategie` | `role_strategie` | Direct |
| `type_contenu` | `type_contenu` | Direct |
| `created_at` | `created_at` | Direct |
| `updated_at` | `updated_at` | Direct |

---

## 16. `media_items` → `medias_libraries` + `medias`

### 16a. `media_items` → `medias_libraries` (cible principale)

| Ancienne colonne | Nouvelle colonne | Remarque |
|---|---|---|
| `id` | — | Conserver dans table de correspondance |
| UUID() | `uuid` | Générer |
| — | `media` | NULL (champ générique v2) |
| `entreprise_id` → UUID | `company_id` | RESOLVE |
| `user_id` → UUID | `user_id` | RESOLVE |
| `file_name` | `file_name` | Direct |
| `file_path` | `file_path` | Direct |
| `file_size` | `file_size` | Direct |
| `mime_type` | `mime_type` | Direct |
| `tags` | `tags` | Direct (JSON) |
| `alt_text` | `alt_text` | Direct |
| `is_active` | `is_active` | Direct |
| `created_at` | `created_at` | Direct |
| `updated_at` | `updated_at` | Direct |
| `status` | — | Abandonné |

### 16b. `media_items` → `medias` (pour les références FK)

Pour chaque `media_item`, créer aussi une entrée dans `medias` :

| Source | Destination (`medias`) | Remarque |
|---|---|---|
| UUID() | `uuid` | Générer (même UUID que `medias_libraries` ou nouveau) |
| `file_path` | `public_url` | Construire l'URL publique depuis le chemin |
| `created_at` | `created_at` | Direct |
| `updated_at` | `updated_at` | Direct |

---

## 17. `invitations` → `invitations`

| Ancienne colonne | Nouvelle colonne | Remarque |
|---|---|---|
| `id` | `id` | Direct (BIGINT) |
| UUID() | `uuid` | Générer |
| `email` | `email` | Direct |
| `role` | `role` | Direct (vérifier ENUM : v2 ajoute `admin`, `consultant`) |
| `entreprise_id` → UUID | `company_id` | RESOLVE |
| `first_name` | `firstname` | Renommé |
| `last_name` | `lastname` | Renommé |
| `phone` | `telephone` | Renommé |
| `fonction` | `fonction` | Direct |
| `token` | `token` | Direct |
| `status` | `status` | Direct (vérifier ENUM : v2 n'a pas `used` ni `cancelled`) |
| `expires_at` | `expires_at` | Direct |
| `used_at` | `used_at` | Direct |
| `user_id` → UUID | `user_id` | RESOLVE |
| `created_at` | `created_at` | Direct |
| `updated_at` | `updated_at` | Direct |
| — | `sent_at` | NULL |
| — | `editorial_persona_id` | NULL |
| — | `linkedin_objectif` | NULL |
| — | `expertise_themes` | NULL |
| — | `target_audience` | NULL |
| — | `professionnal_positioning` | NULL |
| — | `core_values` | NULL |
| — | `topic_id_avoid_communication_tone` | NULL |
| — | `industry_sector` | NULL |
| `invited_by` | — | Abandonné (pas de champ équivalent en v2) |

---

## 18. `historical_posts` → `historical_posts`

| Ancienne colonne | Nouvelle colonne | Remarque |
|---|---|---|
| `id` | — | Conserver dans table de correspondance |
| UUID() | `uuid` | Générer |
| — | `linkedin_url` | NULL (pas dans ancienne BDD) |
| — | `post_type` | NULL |
| `content` | `content` | Direct |
| `likes` | `like_count` | Renommé |
| `comments` | `comment_count` | Renommé |
| `shares` | `share_count` | Renommé |
| `views` | `views_count` | Renommé |
| `reach` | `reach_count` | Renommé |
| `engagement_rate` | `engagement_rate` | Direct |
| `original_date` | `publication_date` | Renommé |
| `source` | `source` | Direct |
| `created_at` | `created_at` | Direct |
| `updated_at` | `updated_at` | Direct |
| `company_name` | `company_id` | RESOLVE via `companies.name` → `companies.uuid` |
| `linkedin_post_id` | — | Abandonné |
| `hashtags` | — | Abandonné |
| `media_urls` | — | Abandonné |

---

## 19. `users` (champs AI profil) → `linkedin_profiles`

Les champs AI profil de l'ancienne table `users` migrent vers `linkedin_profiles` :

| Source (`users`) | Destination (`linkedin_profiles`) | Remarque |
|---|---|---|
| UUID() | `uuid` | Générer |
| `id` → UUID | `user_id` | RESOLVE |
| `linkedin_objectives` | `linkedin_objectif` | Renommé |
| `expertise_themes` | `expertise_themes` | Direct (JSON → TEXT) |
| `target_audience` | `target_audience` | Direct |
| `professional_positioning` | `professionnal_positioning` | Renommé |
| `core_values` | `core_values` | Direct (JSON → TEXT) |
| `topics_to_avoid` | `topic_id_avoid_communication_tone` | Renommé (JSON → TEXT) |
| `editorial_persona_id` → UUID | `editorial_persona_id` | RESOLVE |
| `created_at` | `created_at` | Direct |
| `updated_at` | `updated_at` | Direct |

> Créer une ligne dans `linkedin_profiles` uniquement si au moins un champ AI profil est non NULL.

---

## 20. `linked_in_profiles` + `linkedin_tokens` / `linked_in_tokens` → `linkedin_accounts`

| Source | Destination (`linkedin_accounts`) | Remarque |
|---|---|---|
| UUID() | `uuid` | Générer |
| `linked_in_profiles.user_id` → UUID | `user_id` | RESOLVE |
| UUID() | `linkedin_profile_id` | Lier à `linkedin_profiles` créé en section 19 |
| `linked_in_profiles.first_name` | `first_name` | Direct |
| `linked_in_profiles.last_name` | `last_name` | Direct |
| `linked_in_profiles.full_name` | `full_name` | Direct |
| `linked_in_profiles.headline` | `headline` | Direct |
| `linked_in_profiles.summary` | `summary` | Direct |
| `linked_in_profiles.industry` | `industry` | Direct |
| `linked_in_profiles.location_name` | `location_name` | Direct |
| `linked_in_profiles.picture_url` | `picture_url` | Direct |
| `linked_in_profiles.public_profile_url` | `public_profile_url` | Direct |
| `linked_in_profiles.raw_data` | `raw_data` | Direct |
| `linked_in_profiles.last_synced_at` | `last_synced_at` | Direct |
| `linkedin_tokens.access_token` | `access_token` | Direct |
| `linkedin_tokens.refresh_token` | `refresh_token` | Direct |
| `linkedin_tokens.expires_at` | `expires_at` | Direct |
| `linkedin_tokens.token_type` | `token_type` | Direct |
| `linkedin_tokens.scope` | `scope` | Direct (VARCHAR → JSON) |
| `linked_in_profiles.created_at` | `created_at` | Direct |
| `linked_in_profiles.updated_at` | `updated_at` | Direct |
| `linked_in_profiles.num_connections` | — | Abandonné |
| `linked_in_profiles.is_active` | — | Abandonné |
| `linked_in_profiles.linkedin_id` | — | Stocké dans `users.linkedin_id` |

---

## 21. Tables abandonnées (pas d'équivalent en v2)

| Table ancienne BDD | Raison |
|---|---|
| `historical_post_comments` | Pas d'équivalent en v2 |
| `historical_post_likes` | Pas d'équivalent en v2 |
| `competitive_insights` | Pas d'équivalent en v2 |
| `competitive_rankings` | Pas d'équivalent en v2 |
| `share_of_voice_metrics` | Pas d'équivalent en v2 |
| `content_library` | Pas d'équivalent en v2 |
| `profiles` | Fusionné dans `users` v2 |
| `secteurs_activite` | Remplacé par ENUM dans `companies.sector` |
| `demo_requests` | Structure différente — voir section 22 |
| `password_resets` | Pas de migration nécessaire |
| `linked_in_tokens` | Fusionné dans `linkedin_accounts` |
| `password_reset_tokens` | Tokens temporaires, pas de migration — les users devront réinitialiser leur mot de passe si besoin |
| `personal_access_tokens` | Tokens Sanctum liés aux sessions actives, invalidés après migration — les users devront se reconnecter |

---

## 22. `demo_requests` → `demo_requests`

Structure différente entre les deux versions : la v2 perd le champ `status` et passe la PK en UUID.

| Ancienne colonne | Nouvelle colonne | Remarque |
|---|---|---|
| `id` | — | Conserver dans table de correspondance |
| UUID() | `uuid` | Générer |
| `email` | `email` | Direct |
| `status` | — | Abandonné (pas de champ équivalent en v2) |
| `created_at` | `created_at` | Direct |
| `updated_at` | `updated_at` | Direct |

> Seules les lignes avec `status = 'pending'` ou `status = 'contacted'` ont un intérêt à migrer. Les `converted` peuvent être ignorées selon le besoin.

---

## Ordre d'exécution recommandé

1. `editorial_personas`
2. `communication_themes`
3. `tone_definitions`
4. `medias` (depuis logos entreprises + media_items)
5. `companies`
6. `companies_infos`
7. `companies_hashtags`
8. `users`
9. `linkedin_profiles` (champs AI profil)
10. `linkedin_accounts` (depuis `linked_in_profiles` + tokens)
11. `medias_libraries` (depuis `media_items`)
12. `competitors`
13. `company_competitor`
14. `competitor_post` (depuis `post_competiteur`)
15. `competitor_comment` (depuis `competitor_post_comments`)
16. `competitor_likes` (depuis `competitor_post_likes`)
17. `companies_posts` (depuis `pending_posts`)
18. `companies_comments` (depuis `comments_posts`)
19. `company_likes` (depuis `likes_posts`)
20. `testimonials`
21. `actualities` (depuis `news`)
22. `historical_posts`
23. `invitations`
24. `demo_requests`
