Schéma de base de données — Xpeditis
PostgreSQL 15 — 21 tables.
Extensions requises : uuid-ossp, pg_trgm
Vue d'ensemble des tables
| Table |
Description |
| organizations |
Organisations (transitaires, transporteurs) |
| users |
Comptes utilisateurs |
| carriers |
Transporteurs maritimes |
| ports |
Base de données des ports (UN/LOCODE) |
| rate_quotes |
Cotations de tarifs carriers |
| bookings |
Réservations standard |
| containers |
Conteneurs liés aux réservations |
| csv_bookings |
Réservations créées via CSV |
| csv_rate_configs |
Configuration des carriers CSV |
| carrier_profiles |
Profils portail carrier |
| carrier_activities |
Activités du portail carrier |
| audit_logs |
Journal d'audit des actions |
| notifications |
Notifications push (WebSocket) |
| webhooks |
Configuration des webhooks tiers |
| subscriptions |
Abonnements Stripe |
| licenses |
Licences d'utilisation |
| api_keys |
Clés API (auth alternative au JWT) |
| invitation_tokens |
Tokens d'invitation utilisateur |
| password_reset_tokens |
Tokens de réinitialisation mot de passe |
| cookie_consents |
Consentements RGPD cookies |
| blog_posts |
Articles de blog |
Tables détaillées
organizations
| Colonne |
Type |
Contraintes |
Description |
| id |
UUID |
PK |
Identifiant |
| name |
VARCHAR(255) |
NOT NULL, UNIQUE |
Nom de l'organisation |
| type |
VARCHAR(50) |
NOT NULL |
FREIGHT_FORWARDER, CARRIER, SHIPPER |
| scac |
CHAR(4) |
UNIQUE, NULLABLE |
Standard Carrier Alpha Code |
| address_street |
VARCHAR(255) |
NOT NULL |
Adresse |
| address_city |
VARCHAR(100) |
NOT NULL |
Ville |
| address_state |
VARCHAR(100) |
NULLABLE |
État/Province |
| address_postal_code |
VARCHAR(20) |
NOT NULL |
Code postal |
| address_country |
CHAR(2) |
NOT NULL |
Code pays ISO 3166-1 |
| logo_url |
TEXT |
NULLABLE |
URL du logo |
| documents |
JSONB |
DEFAULT '[]' |
Documents compliance |
| siret |
VARCHAR(20) |
NULLABLE |
SIRET (entreprises françaises) |
| status_badge |
VARCHAR(50) |
NULLABLE |
Badge de statut Pappers |
| is_carrier |
BOOLEAN |
DEFAULT FALSE |
Est un carrier (portail) |
| is_active |
BOOLEAN |
DEFAULT TRUE |
Compte actif |
| created_at |
TIMESTAMP |
DEFAULT NOW() |
Création |
| updated_at |
TIMESTAMP |
DEFAULT NOW() |
Mise à jour |
users
| Colonne |
Type |
Contraintes |
Description |
| id |
UUID |
PK |
Identifiant |
| organization_id |
UUID |
FK organizations |
Organisation |
| email |
VARCHAR(255) |
NOT NULL, UNIQUE |
Email (minuscules) |
| password_hash |
VARCHAR(255) |
NOT NULL |
Hash Argon2 |
| role |
VARCHAR(50) |
NOT NULL |
ADMIN, MANAGER, USER, VIEWER, CARRIER |
| first_name |
VARCHAR(100) |
NOT NULL |
Prénom |
| last_name |
VARCHAR(100) |
NOT NULL |
Nom |
| phone_number |
VARCHAR(20) |
NULLABLE |
Téléphone |
| is_email_verified |
BOOLEAN |
DEFAULT FALSE |
Email vérifié |
| is_active |
BOOLEAN |
DEFAULT TRUE |
Compte actif |
| preferred_language |
VARCHAR(10) |
DEFAULT 'fr' |
Langue préférée (fr, en) |
| last_login_at |
TIMESTAMP |
NULLABLE |
Dernière connexion |
| created_at |
TIMESTAMP |
DEFAULT NOW() |
Création |
| updated_at |
TIMESTAMP |
DEFAULT NOW() |
Mise à jour |
Index : idx_users_email, idx_users_organization, idx_users_role
carriers
| Colonne |
Type |
Contraintes |
Description |
| id |
UUID |
PK |
Identifiant |
| name |
VARCHAR(255) |
NOT NULL |
Nom (ex: "Maersk") |
| code |
VARCHAR(50) |
NOT NULL, UNIQUE |
Code (ex: "MAERSK") |
| scac |
CHAR(4) |
NOT NULL, UNIQUE |
Standard Carrier Alpha Code |
| logo_url |
TEXT |
NULLABLE |
URL du logo |
| website |
TEXT |
NULLABLE |
Site web |
| api_config |
JSONB |
NULLABLE |
Config API (credentials, timeout) |
| is_active |
BOOLEAN |
DEFAULT TRUE |
Actif |
| supports_api |
BOOLEAN |
DEFAULT FALSE |
Intégration API disponible |
| created_at |
TIMESTAMP |
DEFAULT NOW() |
Création |
| updated_at |
TIMESTAMP |
DEFAULT NOW() |
Mise à jour |
Carriers seedés : Maersk (MAEU), MSC (MSCU), CMA CGM (CMDU), Hapag-Lloyd (HLCU), ONE (ONEY)
ports
| Colonne |
Type |
Contraintes |
Description |
| id |
UUID |
PK |
Identifiant |
| code |
CHAR(5) |
NOT NULL, UNIQUE |
UN/LOCODE (ex: "NLRTM") |
| name |
VARCHAR(255) |
NOT NULL |
Nom du port |
| city |
VARCHAR(255) |
NOT NULL |
Ville |
| country |
CHAR(2) |
NOT NULL |
Code pays |
| country_name |
VARCHAR(100) |
NOT NULL |
Nom du pays |
| latitude |
DECIMAL(9,6) |
NOT NULL |
Latitude |
| longitude |
DECIMAL(9,6) |
NOT NULL |
Longitude |
| timezone |
VARCHAR(50) |
NULLABLE |
Fuseau horaire IANA |
| is_active |
BOOLEAN |
DEFAULT TRUE |
Actif |
Index GIN pour recherche floue : idx_ports_name_trgm, idx_ports_city_trgm
rate_quotes
| Colonne |
Type |
Contraintes |
Description |
| id |
UUID |
PK |
Identifiant |
| carrier_id |
UUID |
FK carriers |
Carrier |
| carrier_name |
VARCHAR(255) |
NOT NULL |
Nom carrier (dénormalisé) |
| carrier_code |
VARCHAR(50) |
NOT NULL |
Code carrier (dénormalisé) |
| origin_code |
CHAR(5) |
NOT NULL |
Port d'origine |
| destination_code |
CHAR(5) |
NOT NULL |
Port de destination |
| base_freight |
DECIMAL(10,2) |
NOT NULL |
Fret de base |
| surcharges |
JSONB |
DEFAULT '[]' |
Surcharges (BAF, CAF, etc.) |
| total_amount |
DECIMAL(10,2) |
NOT NULL |
Prix total |
| currency |
CHAR(3) |
NOT NULL |
Devise ISO 4217 |
| container_type |
VARCHAR(20) |
NOT NULL |
Type conteneur (20GP, 40HC, etc.) |
| mode |
VARCHAR(10) |
NOT NULL |
FCL ou LCL |
| etd |
TIMESTAMP |
NOT NULL |
Départ estimé |
| eta |
TIMESTAMP |
NOT NULL |
Arrivée estimée |
| transit_days |
INTEGER |
NOT NULL |
Jours de transit |
| route |
JSONB |
NOT NULL |
Escales |
| availability |
INTEGER |
NOT NULL |
Disponibilité conteneurs |
| valid_until |
TIMESTAMP |
NOT NULL |
Expiration (created_at + 15 min) |
bookings
| Colonne |
Type |
Contraintes |
Description |
| id |
UUID |
PK |
Identifiant |
| booking_number |
VARCHAR(20) |
NOT NULL, UNIQUE |
Format WCM-YYYY-XXXXXX |
| user_id |
UUID |
FK users |
Utilisateur créateur |
| organization_id |
UUID |
FK organizations |
Organisation |
| rate_quote_id |
UUID |
FK rate_quotes, NULLABLE |
Cotation source |
| carrier_id |
UUID |
FK carriers |
Carrier |
| status |
VARCHAR(50) |
NOT NULL |
draft, confirmed, shipped, delivered, cancelled |
| shipper |
JSONB |
NOT NULL |
Infos expéditeur |
| consignee |
JSONB |
NOT NULL |
Infos destinataire |
| cargo |
JSONB |
NULLABLE |
Détails marchandise |
| notes |
TEXT |
NULLABLE |
Notes internes |
| created_at |
TIMESTAMP |
DEFAULT NOW() |
Création |
| updated_at |
TIMESTAMP |
DEFAULT NOW() |
Mise à jour |
containers
| Colonne |
Type |
Contraintes |
Description |
| id |
UUID |
PK |
Identifiant |
| booking_id |
UUID |
FK bookings, NULLABLE |
Réservation |
| type |
VARCHAR(20) |
NOT NULL |
20GP, 40HC, 40RF, etc. |
| category |
VARCHAR(20) |
NOT NULL |
DRY, REEFER, OPEN_TOP, FLAT_RACK, TANK |
| container_number |
VARCHAR(11) |
NULLABLE, UNIQUE |
ISO 6346 |
| seal_number |
VARCHAR(50) |
NULLABLE |
Numéro de plomb |
| vgm |
INTEGER |
NULLABLE |
Masse Brute Vérifiée (kg) |
| is_hazmat |
BOOLEAN |
DEFAULT FALSE |
Marchandise dangereuse |
| imo_class |
VARCHAR(10) |
NULLABLE |
Classe IMO |
| cargo_description |
TEXT |
NULLABLE |
Description de la marchandise |
csv_bookings
| Colonne |
Type |
Contraintes |
Description |
| id |
UUID |
PK |
Identifiant |
| organization_id |
UUID |
FK organizations |
Organisation |
| carrier_id |
UUID |
FK carriers, NULLABLE |
Carrier assigné |
| booking_number |
VARCHAR(50) |
NOT NULL, UNIQUE |
Numéro de réservation |
| shipper_name |
VARCHAR(255) |
NOT NULL |
Expéditeur |
| consignee_name |
VARCHAR(255) |
NOT NULL |
Destinataire |
| origin_port |
CHAR(5) |
NOT NULL |
Port d'origine (UN/LOCODE) |
| destination_port |
CHAR(5) |
NOT NULL |
Port de destination |
| container_type |
VARCHAR(20) |
NOT NULL |
Type conteneur |
| commodity |
TEXT |
NULLABLE |
Marchandise |
| weight_kg |
DECIMAL(10,2) |
NULLABLE |
Poids |
| status |
VARCHAR(50) |
NOT NULL |
pending, accepted, rejected, in_transit, delivered |
| carrier_magic_link_token |
VARCHAR(255) |
NULLABLE |
Token lien magique carrier |
| carrier_magic_link_expires_at |
TIMESTAMP |
NULLABLE |
Expiration du token |
| carrier_password_hash |
VARCHAR(255) |
NULLABLE |
Hash mdp portail carrier |
| notes |
TEXT |
NULLABLE |
Notes |
| documents |
JSONB |
DEFAULT '[]' |
Documents joints |
| created_at |
TIMESTAMP |
DEFAULT NOW() |
Création |
| updated_at |
TIMESTAMP |
DEFAULT NOW() |
Mise à jour |
csv_rate_configs
| Colonne |
Type |
Contraintes |
Description |
| id |
UUID |
PK |
Identifiant |
| company_name |
VARCHAR(255) |
NOT NULL, UNIQUE |
Nom du carrier CSV |
| csv_file_path |
VARCHAR(500) |
NOT NULL |
Chemin fichier CSV |
| type |
VARCHAR(50) |
DEFAULT 'CSV_ONLY' |
CSV_ONLY ou CSV_AND_API |
| has_api |
BOOLEAN |
DEFAULT FALSE |
A une API |
| api_connector |
VARCHAR(100) |
NULLABLE |
Identifiant du connecteur API |
| is_active |
BOOLEAN |
DEFAULT TRUE |
Actif |
| uploaded_at |
TIMESTAMP |
NOT NULL |
Upload |
| uploaded_by |
UUID |
FK users, NULLABLE |
Uploadé par |
| row_count |
INTEGER |
NULLABLE |
Nombre de lignes |
carrier_profiles
| Colonne |
Type |
Contraintes |
Description |
| id |
UUID |
PK |
Identifiant |
| organization_id |
UUID |
FK organizations, UNIQUE |
Organisation carrier |
| carrier_code |
VARCHAR(50) |
NOT NULL |
Code carrier |
| contact_email |
VARCHAR(255) |
NOT NULL |
Email de contact |
| contact_name |
VARCHAR(255) |
NULLABLE |
Nom du contact |
| is_active |
BOOLEAN |
DEFAULT TRUE |
Actif |
| created_at |
TIMESTAMP |
DEFAULT NOW() |
Création |
carrier_activities
| Colonne |
Type |
Contraintes |
Description |
| id |
UUID |
PK |
Identifiant |
| carrier_profile_id |
UUID |
FK carrier_profiles |
Profil carrier |
| csv_booking_id |
UUID |
FK csv_bookings |
Réservation CSV |
| action |
VARCHAR(50) |
NOT NULL |
ACCEPTED, REJECTED, VIEWED, DOCUMENT_UPLOADED |
| notes |
TEXT |
NULLABLE |
Notes de l'action |
| created_at |
TIMESTAMP |
DEFAULT NOW() |
Création |
audit_logs
| Colonne |
Type |
Contraintes |
Description |
| id |
UUID |
PK |
Identifiant |
| user_id |
UUID |
FK users, NULLABLE |
Utilisateur |
| organization_id |
UUID |
FK organizations, NULLABLE |
Organisation |
| action |
VARCHAR(100) |
NOT NULL |
Type d'action (26 types) |
| resource_type |
VARCHAR(50) |
NULLABLE |
Type de ressource |
| resource_id |
VARCHAR(255) |
NULLABLE |
ID de la ressource |
| status |
VARCHAR(20) |
NOT NULL |
SUCCESS, FAILURE, WARNING |
| metadata |
JSONB |
NULLABLE |
Données supplémentaires |
| ip_address |
VARCHAR(45) |
NULLABLE |
Adresse IP |
| user_agent |
TEXT |
NULLABLE |
User agent |
| created_at |
TIMESTAMP |
DEFAULT NOW() |
Création |
Index : idx_audit_logs_user_id, idx_audit_logs_action, idx_audit_logs_created_at
notifications
| Colonne |
Type |
Contraintes |
Description |
| id |
UUID |
PK |
Identifiant |
| user_id |
UUID |
FK users |
Destinataire |
| type |
VARCHAR(50) |
NOT NULL |
BOOKING_CREATED, DOCUMENT_UPLOADED, etc. (9 types) |
| title |
VARCHAR(255) |
NOT NULL |
Titre |
| message |
TEXT |
NOT NULL |
Message |
| data |
JSONB |
NULLABLE |
Données associées |
| priority |
VARCHAR(20) |
NOT NULL |
LOW, MEDIUM, HIGH, URGENT |
| read |
BOOLEAN |
DEFAULT FALSE |
Lu |
| read_at |
TIMESTAMP |
NULLABLE |
Date de lecture |
| created_at |
TIMESTAMP |
DEFAULT NOW() |
Création |
webhooks
| Colonne |
Type |
Contraintes |
Description |
| id |
UUID |
PK |
Identifiant |
| organization_id |
UUID |
FK organizations |
Organisation |
| url |
TEXT |
NOT NULL |
URL cible |
| secret |
VARCHAR(255) |
NOT NULL |
Secret HMAC SHA-256 |
| events |
JSONB |
NOT NULL |
Événements souscrits |
| is_active |
BOOLEAN |
DEFAULT TRUE |
Actif |
| last_triggered_at |
TIMESTAMP |
NULLABLE |
Dernier déclenchement |
| failure_count |
INTEGER |
DEFAULT 0 |
Compteur d'échecs |
| created_at |
TIMESTAMP |
DEFAULT NOW() |
Création |
subscriptions
| Colonne |
Type |
Contraintes |
Description |
| id |
UUID |
PK |
Identifiant |
| organization_id |
UUID |
FK organizations, UNIQUE |
Organisation |
| stripe_customer_id |
VARCHAR(255) |
NULLABLE |
ID client Stripe |
| stripe_subscription_id |
VARCHAR(255) |
NULLABLE |
ID abonnement Stripe |
| plan |
VARCHAR(50) |
NOT NULL |
FREE, BRONZE, SILVER, GOLD, PLATINIUM |
| status |
VARCHAR(50) |
NOT NULL |
active, past_due, cancelled, trialing, pending_payment, pending_bank_transfer |
| current_period_start |
TIMESTAMP |
NULLABLE |
Début de période |
| current_period_end |
TIMESTAMP |
NULLABLE |
Fin de période |
| billing_interval |
VARCHAR(20) |
NULLABLE |
monthly, yearly |
| commission_rate |
DECIMAL(5,4) |
DEFAULT 0 |
Taux de commission Xpeditis |
| created_at |
TIMESTAMP |
DEFAULT NOW() |
Création |
| updated_at |
TIMESTAMP |
DEFAULT NOW() |
Mise à jour |
licenses
| Colonne |
Type |
Contraintes |
Description |
| id |
UUID |
PK |
Identifiant |
| organization_id |
UUID |
FK organizations |
Organisation |
| feature |
VARCHAR(100) |
NOT NULL |
Fonctionnalité activée |
| is_active |
BOOLEAN |
DEFAULT TRUE |
Actif |
| valid_until |
TIMESTAMP |
NULLABLE |
Expiration |
| created_at |
TIMESTAMP |
DEFAULT NOW() |
Création |
api_keys
| Colonne |
Type |
Contraintes |
Description |
| id |
UUID |
PK |
Identifiant |
| organization_id |
UUID |
FK organizations |
Organisation |
| user_id |
UUID |
FK users |
Créateur |
| name |
VARCHAR(255) |
NOT NULL |
Nom de la clé |
| key_hash |
VARCHAR(255) |
NOT NULL |
Hash Argon2 de la clé |
| key_prefix |
VARCHAR(10) |
NOT NULL |
Préfixe visible (ex: xped_) |
| last_used_at |
TIMESTAMP |
NULLABLE |
Dernière utilisation |
| expires_at |
TIMESTAMP |
NULLABLE |
Expiration |
| is_active |
BOOLEAN |
DEFAULT TRUE |
Actif |
| created_at |
TIMESTAMP |
DEFAULT NOW() |
Création |
invitation_tokens
| Colonne |
Type |
Contraintes |
Description |
| id |
UUID |
PK |
Identifiant |
| organization_id |
UUID |
FK organizations |
Organisation |
| email |
VARCHAR(255) |
NOT NULL |
Email invité |
| token |
VARCHAR(255) |
NOT NULL, UNIQUE |
Token d'invitation |
| role |
VARCHAR(50) |
NOT NULL |
Rôle assigné |
| expires_at |
TIMESTAMP |
NOT NULL |
Expiration (24h) |
| used_at |
TIMESTAMP |
NULLABLE |
Utilisé le |
| created_by |
UUID |
FK users |
Créateur |
password_reset_tokens
| Colonne |
Type |
Contraintes |
Description |
| id |
UUID |
PK |
Identifiant |
| user_id |
UUID |
FK users |
Utilisateur |
| token |
VARCHAR(255) |
NOT NULL, UNIQUE |
Token de réinitialisation |
| expires_at |
TIMESTAMP |
NOT NULL |
Expiration (1h) |
| used_at |
TIMESTAMP |
NULLABLE |
Utilisé le |
| created_at |
TIMESTAMP |
DEFAULT NOW() |
Création |
cookie_consents
| Colonne |
Type |
Contraintes |
Description |
| id |
UUID |
PK |
Identifiant |
| user_id |
UUID |
FK users, NULLABLE |
Utilisateur (si connecté) |
| session_id |
VARCHAR(255) |
NULLABLE |
Session anonyme |
| analytics |
BOOLEAN |
NOT NULL |
Consentement analytics |
| marketing |
BOOLEAN |
NOT NULL |
Consentement marketing |
| ip_address |
VARCHAR(45) |
NULLABLE |
IP |
| created_at |
TIMESTAMP |
DEFAULT NOW() |
Création |
blog_posts
| Colonne |
Type |
Contraintes |
Description |
| id |
UUID |
PK |
Identifiant |
| slug |
VARCHAR(255) |
NOT NULL, UNIQUE |
Slug URL |
| title_fr |
VARCHAR(500) |
NOT NULL |
Titre en français |
| title_en |
VARCHAR(500) |
NULLABLE |
Titre en anglais |
| content_fr |
TEXT |
NOT NULL |
Contenu en français |
| content_en |
TEXT |
NULLABLE |
Contenu en anglais |
| excerpt_fr |
TEXT |
NULLABLE |
Extrait français |
| excerpt_en |
TEXT |
NULLABLE |
Extrait anglais |
| cover_image_url |
TEXT |
NULLABLE |
Image de couverture |
| author_id |
UUID |
FK users |
Auteur |
| is_published |
BOOLEAN |
DEFAULT FALSE |
Publié |
| published_at |
TIMESTAMP |
NULLABLE |
Date de publication |
| tags |
JSONB |
DEFAULT '[]' |
Tags |
| created_at |
TIMESTAMP |
DEFAULT NOW() |
Création |
| updated_at |
TIMESTAMP |
DEFAULT NOW() |
Mise à jour |
Relations principales
organizations 1──* users
organizations 1──1 subscriptions
organizations 1──* licenses
organizations 1──* api_keys
organizations 1──* webhooks
organizations 1──* bookings
organizations 1──* csv_bookings
organizations 1──1 carrier_profiles
users 1──* bookings
users 1──* audit_logs
users 1──* notifications
users 1──* api_keys
bookings 1──* containers
bookings 1──1 rate_quotes (optionnel)
csv_bookings 1──* carrier_activities (via carrier_profiles)
carrier_profiles 1──* carrier_activities
Stratégie de migrations
Les migrations sont dans apps/backend/src/infrastructure/persistence/typeorm/migrations/.
Ne jamais modifier une migration déjà appliquée — créer une nouvelle migration.
cd apps/backend
npm run migration:generate -- src/infrastructure/persistence/typeorm/migrations/NomMigration
npm run migration:run
Dernière mise à jour : Mai 2026 — 21 tables