# eRegulations / TradePortal — État des lieux fonctionnel (ligne 7.x)

> Date : 2026-09-24. Objectif : inventorier toutes les fonctionnalités du système actuel avant de concevoir eRegulations-Next (stack Next.js / Prisma / Postgres, comme les autres `*-Next`), avec import des données existantes.
>
> Sources analysées (lecture seule) : `eRegulations-4.0-Admin` (WebAppCore + Library), `eRegulations-5.0-Admin-SPA`, `eRegulations-4.0-Public` (**origin/main**, le checkout local a 108 commits de retard), `eRegulations-4.0-API`, `eRegulations-API-Docs`, `eRegulations-CR-Alerts`, `eRegulations-Statistics`, `eRegulations-Monitor`, `eRegulations-deploy`, plugin `plugin-marketplace/plugins/eregulations`.
>
> Légende statut : ✅ actif · ⚠️ partiel / douteux · 💀 mort / legacy

---

## 1. Architecture actuelle (7.x)

| Composant | Techno | Rôle |
|---|---|---|
| `admin-api` (repo 4.0-Admin / `WebAppCore`) | ASP.NET Core 8, EF Core 8, SQL Server | API REST du back-office, JWT maison |
| `Unctad.eRegulations.Library` (repo 4.0-Admin) | .NET 8 | Modèle, DAL, métier, snapshots — **partagée** par Admin et Public (ProjectReference) |
| `admin-web` (repo 5.0-Admin-SPA) | Angular 19, PrimeNG, Quill | Back-office |
| `public` (repo 4.0-Public) | ASP.NET Core 8 Razor + jQuery/Backbone/Bootstrap 3 + **Angular 9** (pages procédure) | Site public + API publique de lecture + API legacy |
| ERegWebApi (repo 4.0-API) | ASP.NET Web API classique | 💀 Retirée en 7.x, sous-ensemble compatible servi par Public ≥ 7.6.7 |
| eRegulations-Statistics | .NET 8 console + lib | Snapshots périodiques de KPI → BD `00-dbe-statistics` (lib requise pour compiler Public) |
| eRegulations-CR-Alerts | .NET Framework console | 💀 Digest e-mail « Consistency Review » (inactif) |
| eRegulations-Monitor | Fastify + Drizzle/SQLite + Angular 19 | Supervision de flotte + **provisioner** (création d'instance, migration legacy→7.x) |
| eRegulations-deploy | Compose, Coolify, CLI Python `eregulations migrate` | Descripteurs d'instance, déploiement, import |

**Topologie par instance** : 1 app Coolify (admin-api, admin-web, public) + SQL Server 2022 Express séparé (partagé ou dédié) + répertoires de contenu montés (`media/`, `PublicConfig/`, `PublicContent/`, `Multilang/`).

**Bases par instance** : BD pays (`30-dbe-TradePortal-<Pays>` / `50-dbe-*-<slug>`) + BD mutualisées par `systemId` : `00-dbe-consistency` (tickets de revue), `00-dbe-statistics`, `00-dbe-global` (legacy : SystemInstance, anciens users).

**Flotte** : 7 descripteurs 7.x (burundi, comoros, iasi, past, pilot-tradeportal, south-sudan, lab-next) ; ~90 instances / ~200 « groupes » legacy sur 4 serveurs Windows (4.x/5.x). Releases 7.1.0 → 7.6.x.

**TradePortal** = même base de code. Ce n'est plus un mode : c'est un ensemble de modules activés par configuration (voir §5). Le flag `IsTradeportal` ne change que le logo/libellé du back-office.

---

## 2. Back-office — inventaire fonctionnel

### 2.1 Arborescence des procédures (cœur métier)
| Fonctionnalité | Détail | Statut |
|---|---|---|
| Arbre Objectifs → Blocs → Étapes | Objectif = procédure ou nœud de catégorie ; multi-parents (`Admin_ObjectiveHierarchicalData`) ; blocs ordonnés ; étapes **réutilisables** dans plusieurs blocs | ✅ |
| Drag & drop dans l'arbre | déplacer objectif/bloc/étape, marquer étape **alternative** ; flag `IsParallele` | ✅ |
| Dupliquer, corbeille (2 temps), vider corbeille | objectifs, blocs, étapes (et menus) | ✅ |
| Objectif — onglets | général (nom, parent) ; destinataires feedback ; filtres attachés (option par défaut) ; apparence (description, icône, 3 images, visible invités, visibilité par langue, SEO) ; résumé (visibilité des sections, commentaires, pièces jointes) | ✅ |
| Bloc | nom, description, optionnel, présence physique, représentation par tiers | ✅ (routes blocs autonomes commentées ⚠️) |
| Étape — général | nom, blocs, catégorie, interne/optionnelle, **en ligne** (URL + type : apply/obtain/pay/submit) | ✅ |
| Étape — contact | entité / unité / personne responsable + **surcharges régionales** par région | ✅ |
| Étape — résultats | documents produits, typés, ordonnés, pièces jointes, base légale | ✅ |
| Étape — exigences | documents requis (catalogue ou résultat d'une étape antérieure), séparateurs **ET/OU**, nb originaux/copies/copies certifiées, filtre global (tous/particulier/entreprise/non-résident/représentant), base légale | ✅ |
| Étape — coûts | lignes typées (taxe/frais ext.), valeur fixe, % ou **formule** (variable de coût, liée *par nom*), valeur moyenne, devise, séparateurs, moyens de paiement, « pas de coût » + raison, commentaires | ✅ |
| Étape — délais | min/max × (attente file, temps guichet, attente jusqu'à étape suivante), commentaires, base légale | ✅ |
| Étape — lois, infos complémentaires, recours | recours = étape `IsRecourse` liée + contact/loi du recours | ✅ |
| Visibilité par section | ~20 flags par étape, ~9 par objectif | ✅ |
| Certification d'étape | date, utilisateur, entité certificatrice, fiche jointe | ✅ (⚠️ endpoint sans contrôle de permission) |
| Statut & revues d'étape | historique de statut (workflow InEditing → vérification → approbation → certification ; niveaux A*/A/B/C/D) et tickets de revue — **lecture seule** depuis la BD consistency | ⚠️ (revues en anglais codé en dur) |

### 2.2 Publication & historique
| Fonctionnalité | Détail | Statut |
|---|---|---|
| Publication | Publier objectif/bloc/étape → **snapshot dénormalisé par langue** dans `Snapshot_*` ; tables `Admin_*` = brouillon | ✅ |
| Versions publiées | `Snapshot_Registry` (version, date, IsCurrent) ; `?version=` ignoré côté Public | ⚠️ pas d'UI d'historique |
| Publication par langue | dans l'écran traductions (objectifs/blocs/étapes) | ✅ |
| Audit | intercepteur EF → `AuditRecords` / `AuditRecordFields` (diff champ par champ) ; écran recherche + diff | ✅ |

### 2.3 Catalogues (référentiels)
| Fonctionnalité | Détail | Statut |
|---|---|---|
| Institutions (entités) | adresse, 2 tél/fax/mail/site, carte Google, image, **horaires** 7 j × matin/soir, zone, en ligne, visible annuaire, pièces jointes, étapes liées | ✅ |
| Unités | rattachées à une entité, horaires hérités ou propres | ✅ |
| Personnes | rattachées à une unité, fonction, contacts, image | ✅ |
| Documents (exigences génériques) | type, nb pages, émis par institution, fichier ou URL, **dépendances** (étapes utilisatrices), visibilité | ✅ |
| Lois | nom, description, fichier, dépendances | ✅ |
| Variables de coût | nom, libellé, hypothèse, valeur moyenne, opérateur, ordre | ✅ |
| Devises | sélection parmi une liste, devise par défaut | ✅ |
| Tiers exécutants | CRUD (table générique `Option`) | ✅ |
| Filtres | filtres → options (drag-order), inclusif, **liés produits** (codes SH via widget externe) | ✅ |
| Coût du fardeau administratif (ABC) | niveaux de personnel, matrice zones, coûts impression/informatique, temps par tâche documentaire (`GenericRequirement_Cost`) ; activé par `AdminBurdenCostEnabled` | ✅ (origine TradePortal) |
| Médias | upload `<guid>.<ext>` dans `/media`, miniatures (Skia), fichier par langue, liaison polymorphe `Admin_Object_Media` | ✅ (pas de médiathèque autonome) |

### 2.4 Contenu du site public (géré depuis l'admin)
| Fonctionnalité | Détail | Statut |
|---|---|---|
| Menus publics | arbre drag & drop + corbeille ; général (parent, pleine largeur, visibilité, langues), info, apparence (icônes, 3 images, colonnes), **mapping** vers objectif/bloc, sous-menus, destinataires feedback | ✅ |
| Mise en page accueil | 8 onglets : général, en-tête (logos/HTML, titres), menus hauts, diaporama/vidéo, section centrale (annonces, 4 encarts média), jeux de filtres « Rechercher par », menus bas, pied de page — stocké en **JSON par langue** dans `PublicConfig/` | ✅ |
| CSS personnalisé | `PublicConfig/custom.css` + historique de versions, rollback, check (API ; UI = simple textarea) | ⚠️ versions sans UI |
| Page équipe | texte, image, membres « Autorités » / « Équipe eRegulations » | ✅ |
| Feedback reçus | liste/lecture, catégories ; pas de workflow de réponse | ✅ |

### 2.5 Traductions
| Fonctionnalité | Détail | Statut |
|---|---|---|
| Traduction du contenu | par langue cible : données système (variables, options, filtres, menus admin, libellés), menus, contacts, procédures (objectifs/blocs/étapes/résultats/exigences), documents, lois ; original affiché à côté ; rich text | ✅ (⚠️ **API sans authentification**) |
| Libellés d'interface | fichiers « Multilang central repository » ; clé manquante auto-créée par la SPA | ✅ |
| Langues | `SystemLanguage` (active, principale, RTL) | ✅ |
| « Envoyer en traduction » | commenté | 💀 |

### 2.6 Utilisateurs & droits
| Fonctionnalité | Détail | Statut |
|---|---|---|
| Authentification | login/mot de passe → JWT HS256 30 min, refresh sur activité, sync multi-onglets ; SSO par jeton partagé 30 s (Admin ↔ Public) ; **pas de Keycloak** | ✅ |
| Utilisateurs | CRUD, titre, e-mail, fuseau, image, « reçoit alertes CR », soft delete, master users | ✅ |
| Rôles & permissions | permissions `{ressource}.{action}` ; rôles (Admin, Certifier, Translater, consultants local/régional/admin, ConsistencyReviewer, SysAdmin, SuperAdmin, Manager, SectoralAdmin…) ; surcharges grant/deny par utilisateur ; **permissions par objet** héritées Objectif→Bloc→Étape ; deny l'emporte | ✅ |
| Destinataires de feedback | par objectif/menu/étape | ✅ |

### 2.7 Divers
- Menu latéral de l'admin piloté par le serveur (`SiteMenu` en BD).
- Signaler un problème (e-mail SMTP), lien d'aide, lien vers le site public, mode sombre.
- Paramètres d'app exposés : langue et devise par défaut, nom, URL publique, flags TradePortal/ABC/bug report, URLs produits.
- **Absents** : tableau de bord, statistiques, recherche globale, import/export, prévisualisation, IA, opérations en masse.

---

## 3. Site public — inventaire fonctionnel

### 3.1 Pages
| Page | Fonctionnalité | Statut |
|---|---|---|
| `/` Accueil | diaporama ou vidéo, recherche par jeux de filtres + recherche libre, annonces, 4 encarts média, menus bas, widget revue (connecté) | ✅ |
| `/menu/{id}` | page de menu (texte riche + sous-menus) | ✅ |
| `/objective/{id}`, `/objective/search?flt_…` | nœud d'arbre ; **recherche par filtres** avec désambiguïsation produit ; `POST linear-search` (JSON, aussi pour externes) | ✅ |
| `/procedure/{id}` (Angular 9) | **résumé de procédure** : étapes, totaux coûts/délais, exigences, institutions, lois… | ✅ |
| `/procedure/{pid}/step/{sid}` | fiche étape complète (contact + horaires, exigences, coûts, délais, résultats, lois, recours, certificateur, infos, PJ) | ✅ |
| Impression | aperçu d'impression étape/procédure (impression navigateur, options recours/certification) ; pas de PDF serveur | ✅ |
| `/Procedures` | répertoire A–Z + recherche + pagination | ✅ |
| `/Contacts`, `/Contacts/{id}` | annuaire des institutions + fiche avec carte Google | ✅ |
| `/Laws`, `/Requirements`, `/Partners` | répertoires A–Z | ✅ (Partners ⚠️ table morte côté admin) |
| `/Products` | répertoire de produits (codes SH) issu des options de filtres | ✅ TradePortal |
| `/Tariffs`, `/Tariffs/HsCodesFinder` | calculateur de droits et taxes + recherche SH (voir §5) | ✅ TradePortal |
| `/Team` | à propos / équipe | ✅ |
| `/TradeStatistics` | vide sauf partial fourni par l'instance | ⚠️ |
| `/EmbedSearch`, `?embed=true` | intégration iframe (page ou barre de recherche seule) + générateur de snippet | ✅ |
| `/SystemDashboard` | indicateurs système et statuts dans le temps (BD statistics), connecté | ✅ |
| `/Consistency/*` | **revue de cohérence** : tickets/commentaires par page/section, listes par statut, rapport imprimable | ✅ (connecté) |
| `/User/*` | login cookie ou CAS/OAuth, « aller à l'admin » (SSO) | ✅ |
| `/health`, `/swagger` | santé ; OpenAPI de l'API de lecture | ✅ |
| `/Procedure/Index|Details` (Razor) | rendu legacy + tiroirs ABC + changement de statut | ⚠️ doublon partiel de la version Angular |

### 3.2 Transverse
- **Navigation** : en-tête configurable, « grand menu » arbre d'objectifs, tiroirs gauche (menus) / droite (recherche), fil d'Ariane, pied de page.
- **Coûts** : conversion de devises (API externe avec clé).
- **ABC** (connecté, `AbcActivated`) : calcul du fardeau administratif, édition niveaux/zones/nb d'utilisateurs ; calcul anonyme depuis 7.6.2.
- **Édition « en place » pour utilisateurs connectés** : visibilité publique des lois/docs/entités, changement de statut d'étape, flag EBI, édition de traduction inline.
- **Contact** : modale feedback (catégories, pays, procédure, reCAPTCHA v3, SMTP) ou page contact externe ; chat optionnel (partial d'instance).
- **Multilingue** : `?l=`/`?lang=`, RTL, numéraux alternatifs, widget Google Translate optionnel.
- **Analytics** : GA4/gtag, GA legacy, Hotjar, HubSpot, Facebook Pixel, tracker spécifique Cuba.
- **SEO** : meta via config accueil ; pas de sitemap/robots ; canonical seulement pour Cuba. **Accessibilité** faible.
- **Pré-lancement** : Basic Auth sur tout le site.
- **Personnalisation par instance** : contenu accueil/layout en BD/JSON, cascade CSS (`default-theme.css` → `custom.css` d'instance), partials Razor optionnels (`_customTopHeader`, `_preHomepushes`, `_ePingFooter`, `_TradeStatistics`, `_customChatService`), ~25 flags d'environnement.

### 3.3 Lecture des données
Public lit **en direct les mêmes BD SQL Server** que l'admin (via la Library partagée) : snapshots publiés (`Snapshot_*` IsCurrent), consistency, statistics. Cache mémoire + `Cache-Control: max-age=300` sur l'API. Volumes de fichiers partagés avec l'admin.

---

## 4. API publiques (contrat externe à préserver)

| Groupe | Routes | Auth | Consommateurs |
|---|---|---|---|
| API de lecture 7.x | `/api/objective`, `/api/filter[/search|/product|/combinations]`, `/api/filterobjective`, `/api/procedure/{id}[/summary|totals|details|breadcrumb|costs|timeframe|requirements|laws|results|institutions|blocksteps|calculate…]`, `/api/procedure/{pid}/step/{sid}[/…]` | anonyme, CORS * | Angular public, **Simplifications-Next**, intégrateurs |
| Sous-ensemble legacy (ERegWebApi) | `/Filters*`, `/Objectives*`, `POST /Objectives/SearchByFilters`, `/Procedures/{id}[/Resume|ResumeDetail|Totals]` (camelCase, enveloppe `{links,data}`) | anonyme | comparateur EAC tradehelpdesk, ITC, comparateurs |
| `POST /objective/linear-search` | recherche plate par filtres | anonyme | externes |
| Écriture internes | ABC, visibilité, statut, traduction, tickets/commentaires, feedback, devises, tarifs | cookie / anonyme selon | JS du site |

Non couverts depuis le retrait d'ERegWebApi : Country, Categories, Layouts, Menus, listes Contacts/Units/People/Laws/Forms. Changement d'unité des délais (minutes sur journée de 8 h vs jours de 24 h).

---

## 5. Spécificités TradePortal (modules activables)

| Module | Activation | Détail |
|---|---|---|
| Calculateur de droits et taxes | `Tariffs*` (URL, user, clé) | Proxy vers l'API douanière ASYCUDA/ASYENT du pays : recherche SH, détail marchandise, taux de change, préférences pays, estimation ; cache BD 7 j (`TariffsCache`), rate limiting, export CSV/impression, champ additionnel (cylindrée), lien taux préférentiels ; certificat CA Burundi embarqué ; assets Font Awesome Pro sous licence |
| Recherche de codes SH | `HSCodeApi` | autocomplétion sur `hscode.tradeportal.org` ; arbre SH + groupes régionaux |
| Produits | `ProductsURL` | options de filtres portant des codes SH, répertoire `/Products`, désambiguïsation produit dans la recherche |
| ABC | `AbcActivated` / `AdminBurdenCostEnabled` | voir §2.3 et §3.2 |
| Accueil orienté commerce | contenu | filtres import/export/transit, encarts Trade Facilitation Repository / Foreign Statistics, `_TradeStatistics`, pied ePing (OMC) |
| Branding | `IsTradeportal` + titre codé en dur | logo/libellé admin, « TRADEPORTAL » en dur dans l'accueil public |

💀 Maquettes mortes à ne pas reprendre : `static_Index.cshtml` (TradePortal Kenya), `assets/js/tariff.js`, `procedure.js`, `20160602_*.js`, `templates/procedures/*.html`.

---

## 6. Satellites & exploitation

| Composant | Fonctionnalités | Statut |
|---|---|---|
| Statistics | KPI par instance dans le temps (nb procédures/publiques/certifiées, étapes par statut A/B/C/D, exigences, lois, institutions, résultats, feedback, tickets ouverts/archivés par type de page) ; stockage EAV ; vues pivot et procédures stockées ; lus par `/SystemDashboard` | ✅ |
| CR-Alerts | digest e-mail quotidien par consultant (procédures publiques, tickets actifs, étapes par statut, changements récents), adapté au rôle ; templates en/fr/es | 💀 |
| Monitor | disponibilité/latence/erreurs/SSL/version des 3 apps de chaque instance, matrice de versions, alertes (e-mail/webhook), fenêtres de maintenance, audit, découverte | ✅ (hors périmètre produit) |
| Provisioner / CLI migrate | création d'instance depuis `template.bak` ; **migration legacy → 7.x en 8 phases** (restore, schéma, users, historique consistency, contenu, vérification, réimport) | ✅ — base de connaissance précieuse pour l'importeur |

---

## 7. Modèle de données (BD pays 7.x, ~104 tables)

- **Brouillon** : `Admin_Objective` (+ `HierarchicalData`, `SectionVisibility`, `PerLangVisibility`), `Admin_Objective_Block`, `Admin_Block`, `Admin_Block_Step`, `Admin_Step` (~55 colonnes), `Admin_Step_Recourse`, `Admin_StepRequirement`, `Admin_StepResult`, `Admin_StepCost`, `Admin_StepLaw`, `Admin_StepRegional{Entity,Unit,Person}InCharge`, `Admin_StepSectionVisibility`, `Admin_Menu` (+ hiérarchie, visibilité langue).
- **Publié** : `Snapshot_Registry` + ~20 tables `Snapshot_*` dénormalisées par langue.
- **Référentiels** : `EntityInCharge` → `UnitInCharge` → `PersonInCharge`, `GenericRequirement` (+ `_Cost`), `Law`, `Medias` (+ `Media_i18ns`), `Admin_Object_Media` (polymorphe par `Type`), `Filter` → `FilterOption` → `FilterOption_Products`, `Objective_Filters` → `Objective_FilterOptions`, `CostVariable`, `Option` (lookup générique : devise, tiers, catégorie, pays, région, niveau, zone, coûts ABC, catégorie feedback), `SystemLanguage`, `SiteMenu`, `Public_Teams` / `Public_Team_Members`, `Feedback`, `TariffsCache`.
- **Utilisateurs** : `User` (+ `_i18n`), `Role`, `User_Role`, `Permission`, `RolePermission`, `UserPermission`, `ObjectPermission`, `UserFeedback`.
- **Audit** : `AuditRecords`, `AuditRecordFields`.
- **Hors BD pays** : consistency (`consistency_tickets/comments/status`, par `systemId`), statistics (`StatisticSet`, `Systems`), global legacy (`SystemInstance`, anciens users).
- **Fichiers** : `media/` (uploads + miniatures), `PublicConfig/` (`homepage.config.{lang}.json`, `custom.css` + historique), `PublicContent/` (images, vidéos), `Multilang/` (libellés UI).
- 💀 Morts : `XMLSerializedItem*`, `Workspace`, `Partner*` (admin), `ProcedureContext`, `Process*`, `ObjectSecurity`, `User_CRAlert`, colonnes `DeprecatedID`, ~200 procédures stockées / fonctions legacy.

**Conventions** : langue par défaut dans la ligne de base + table sœur `*_i18n(s)` (nommage incohérent) ; soft delete `Deleted` + corbeille `IsInRecycleBin` ; `CreatedUser/ModifiedUser` = nom d'utilisateur (pas de FK).

---

## 8. Points d'attention pour l'import

1. **Source = `.bak` SQL Server** uniquement (aucun export JSON/CSV). Restaurer dans un MSSQL temporaire puis extraire vers Postgres.
2. **Plusieurs lignes de version** : 7.x (EF, identifiables par `__EFMigrationsHistory`) et legacy 4.x/5.x (TradePortal = 5.x). Dérives connues : PK identity absentes sur ~20 `Snapshot_*` avant 02/2024, colonnes optionnelles (`IsVisibleInPublicHomePage`, `IsWidePage`, `IsReachingOffice`, `IsEmittedByInstitution`), `SiteMenu.Id` identity ou non, vues obsolètes. Le provisioner (`eRegulations-Monitor/provisioner/sql/migrate/`) documente déjà tout ça.
3. **Plusieurs BD à fusionner** : pays + consistency (filtré par `systemId`) + global (legacy : users) + statistics (optionnel).
4. **Utilisateurs** : mots de passe en clair / SHA-256 / bcrypt → importer tels quels et re-hasher à la connexion ; doublons de noms (collation insensible à la casse) ; `UserFeedback` lié par ID *ou* par username.
5. **Fichiers** : copier `media/` ; noms de fichiers CP850 dans les zips legacy ; références depuis `Medias`, `Media_i18ns`, colonnes image et JSON d'accueil.
6. **Contenu hors SQL** : accueil (JSON par langue), CSS, libellés Multilang.
7. **Pièges** : `StepCost.Parameter` → `CostVariable` **par nom** ; `Object_Media.Type` détermine la table cible ; lignes supprimées/en corbeille ; snapshots à copier ou à régénérer ; unités de délais.
8. **Contrat API externe** à conserver (API de lecture 7.x + sous-ensemble legacy) pour Simplifications-Next et le comparateur EAC.

---

## 9. Dette & sécurité relevées (à ne pas reproduire)

- `TranslationController` **sans authentification** (écritures et publications anonymes).
- `PUT /api/step/{id}/certification` sans contrôle de permission.
- Secrets JWT/SSO codés en dur dans `appsettings.json` ; identifiants en clair dans `eRegulations-deploy/HANDOVER-2026-06-08.md` et IP de serveurs dans l'inventaire CSS → à faire tourner et purger de git.
- Mot de passe dans l'URL (`/api/login?username&pwd`), lecture anonyme des tickets, CORS `*`.
- `/media` servi publiquement sans liste blanche.
- Trois stacks front coexistantes sur Public (Razor/jQuery/Backbone, Angular 9, Bootstrap 3) ; Library partagée qui couple les releases Admin/Public.
- BD consistency mutualisée (6 Go sur 10 Go max SQL Express).
