xpeditis2.0/docs/architecture/database.md
2026-05-14 21:11:54 +02:00

18 KiB

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

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