Modèle de données
Stack et accès
La plateforme utilise PostgreSQL 17 comme base de données relationnelle. L'accès se fait exclusivement via Prisma (version 6) en tant qu'ORM. Le schéma source est app/mypromo/prisma/schema.prisma.
Les migrations sont gérées par Prisma Migrate :
pnpm -C app/mypromo run db:migrate # migration dev (crée un fichier de migration)
pnpm -C app/mypromo run db:migrate:deploy # migration de déploiement (CI/prod)
pnpm -C app/mypromo run db:generate # génération du client Prisma
pnpm -C app/mypromo run db:studio # interface visuelle Prisma Studio
Contexte historique
Le schéma conserve des @@map vers les noms des anciennes collections issues de la migration depuis MongoDB. Les noms de tables PostgreSQL correspondent donc aux noms de collections d'origine (user, session, campaigns, stores, etc.) pour assurer la continuité du code applicatif. MongoDB n'est plus utilisé — PostgreSQL est la seule base de données de production.
Conventions du schéma
- Clé primaire :
String @id @default(cuid()). Les ObjectId MongoDB ont été abandonnés. - Énumérations : modélisées en
String; la validation se fait au niveau application/Zod pour limiter la friction avec Better Auth et le code typé en unions de chaînes. - Value-objects 1-1 : aplatis en colonnes préfixées (ex.
legalAddressStreet,georefNormCity). - Tableaux de sous-documents : convertis en tables enfant avec clé étrangère.
- Champs réellement schemaless : typés
Json. - Références inter-entités : colonnes
String(clé métier ou cuid) + index, sans contrainte FK base de données (préserve l'accès par id du code existant).
Module auth — Authentification et organisations
Better Auth (tables de session)
| Table (@@map) | Modèle Prisma | Rôle |
|---|---|---|
user | User | Compte utilisateur, rôle (admin/distributor/industrial), 2FA, ban |
session | Session | Sessions actives, impersonation admin |
account | Account | Comptes OAuth/credentials liés à un user |
verification | Verification | Tokens de vérification (magic link, e-mail) |
twoFactor | TwoFactor | Secret TOTP et codes de secours |
User porte des champs applicatifs additionnels : role, status, actorType, organizationId, firstName, lastName, phoneNumber, cguVersionAccepted.
Organisations et membres
| Table (@@map) | Modèle Prisma | Rôle |
|---|---|---|
organizations | Organization | Organisation (distributeur, industriel) avec statut KYB, données légales |
organization_members | OrganizationMember | Appartenance d'un user à une organisation, rôle de membre |
auth_organization_invitations | OrganizationInvitation | Invitations par email, cycle de vie (pending/accepted/expired) |
organization_billing_profiles | OrganizationBillingProfile | Données de facturation, signataire, IBAN, conditions de paiement |
auth_printer_supplier_profiles | PrinterSupplierProfile | Profil imprimeur : données légales, contraintes fichiers, invitation |
KYB et signatures
| Table (@@map) | Modèle Prisma | Rôle |
|---|---|---|
auth_company_verification_cache | AuthCompanyVerificationCache | Cache des vérifications Pappers (SIREN), TTL, compteur d'usage |
auth_authorized_signatories | AuthAuthorizedSignatory | Signataires autorisés associés à un cache de vérification |
auth_signature_requests | AuthSignatureRequest | Demandes de signature Yousign (statut, liens, métadonnées) |
auth_signature_webhook_events | AuthSignatureWebhookEvent | Événements webhook Yousign reçus, statut de traitement |
Catalogue de marques industrielles
| Table (@@map) | Modèle Prisma | Rôle |
|---|---|---|
organization_industrial_catalogs | OrganizationIndustrialCatalog | Catalogue de marques d'une organisation industrielle |
organization_industrial_brands | OrganizationIndustrialBrand | Marques déclarées dans le catalogue |
organization_industrial_brand_products | OrganizationIndustrialBrandProduct | Produits associés à une marque |
Logs de sécurité
| Table (@@map) | Modèle Prisma | Rôle |
|---|---|---|
security_audit_log | SecurityAuditLog | Événements de sécurité (type, acteur, IP, contexte) |
Templates de documents
| Table (@@map) | Modèle Prisma | Rôle |
|---|---|---|
document_templates | DocumentTemplate | Templates Markdown versionnés (CGU, mandats) avec statut draft/published |
document_template_variables | DocumentTemplateVariable | Variables déclarées d'un template (nom, type, required) |
document_template_audit_logs | DocumentTemplateAuditLog | Historique des actions sur les templates |
Module catalog — Magasins et espaces publicitaires
Magasins
| Table (@@map) | Modèle Prisma | Rôle |
|---|---|---|
stores | Store | Magasin (organisation distributeur, SIRET, adresse, géolocalisation, audience) |
store_interest_signals | StoreInterestSignal | Signaux d'intérêt exprimés par un industriel pour un magasin |
Store embarque les données de géoréférencement (latitude, longitude, champs georef*) et d'audience (audienceCustomerFlowPerDay, audienceCatchmentArea).
Espaces publicitaires
| Table (@@map) | Modèle Prisma | Rôle |
|---|---|---|
ad_spaces | AdSpace | Espace publicitaire (type de support, dimensions, tarif journalier, statut, lien vers le type et la demande d'origine) |
ad_space_photos | AdSpacePhoto | Photos de l'espace, positionnées |
ad_space_availability_windows | AdSpaceAvailabilityWindow | Fenêtres de disponibilité d'un espace |
ad_space_periodic_pricing_rules | AdSpacePeriodicPricingRule | Règles de tarification périodiques (jour de semaine, semaine du mois) |
ad_space_event_pricing_rules | AdSpaceEventPricingRule | Règles de tarification événementielles (plage de dates) |
Catalogue mobilier promotionnel
| Table (@@map) | Modèle Prisma | Rôle |
|---|---|---|
promo_furniture_types | PromoFurnitureType | Type de mobilier (dimensions, surfaces, volumes) |
promo_furniture_type_placement_images | PromoFurnitureTypePlacementImage | Images de positionnement associées à un type de mobilier |
promo_furniture_type_documents | PromoFurnitureTypeDocument | Documents techniques d'un type de mobilier |
promo_furniture_type_catalog_visuals | PromoFurnitureTypeCatalogVisual | Visuels catalogue (gabarits) d'un type de mobilier |
promo_furniture_type_quads | PromoFurnitureTypeQuad | Positionnement d'une zone imprimable sur l'image d'un type (4 points) |
promo_furniture_type_rental_prices | PromoFurnitureTypeRentalPrice | Tarif locatif mensuel borné dans le temps (date-à-date) d'un type de mobilier |
promo_furnitures | PromoFurniture | Instance physique de mobilier (numéro de série unique, magasin/espace affectés) |
furniture_requests | FurnitureRequest | Demande de meuble d'un distributeur (magasin, statut pending/approved/rejected, motif) |
furniture_request_items | FurnitureRequestItem | Ligne d'une demande de meuble (type de mobilier, quantité) |
promo_print_files | PromoPrintFile | Fichier d'impression (code unique, fichier asset, types compatibles) |
promo_print_file_compatible_types | PromoPrintFileCompatibleType | Association entre un fichier d'impression et les types de mobilier compatibles |
promo_print_jobs | PromoPrintJob | Ordre d'impression d'un fichier pour un industriel (statut, localisation) |
Catalogue enseignes
| Table (@@map) | Modèle Prisma | Rôle |
|---|---|---|
catalog_enseignes | CatalogEnseigne | Référentiel des enseignes (code, label, logo, ordre de tri) |
Module campaigns — Campagnes, réservations, médias
Campagnes
| Table (@@map) | Modèle Prisma | Rôle |
|---|---|---|
campaigns | Campaign | Campagne marketing (organisation industrielle, dates, budget, brief) |
campaign_product_snapshots | CampaignProductSnapshot | Snapshot des produits au moment de la création de la campagne |
campaign_templates | CampaignTemplate | Modèle réutilisable de campagne |
campaign_template_product_snapshots | CampaignTemplateProductSnapshot | Snapshot des produits d'un template |
campaign_cart_items | CampaignCartItem | Éléments en cours de panier (espace publicitaire + créneau sélectionné) |
Shortlists
| Table (@@map) | Modèle Prisma | Rôle |
|---|---|---|
industrial_shortlists | IndustrialShortlist | Liste de magasins favoris d'un industriel (nom, couleur, défaut) |
industrial_shortlist_stores | IndustrialShortlistStore | Entrée de magasin dans une shortlist |
Réservations
| Table (@@map) | Modèle Prisma | Rôle |
|---|---|---|
reservations | Reservation | Réservation d'un espace publicitaire (statut, pricing, contre-proposition, mode de support d'impression) |
reservation_print_reused_faces | ReservationPrintReusedFace | Faces d'impression réutilisées dans une réservation en mode hybride/reuse |
reservation_messages | ReservationMessage | Messages échangés sur une réservation, avec statut de modération |
plaque_orders | PlaqueOrder | Commande de plaques physiques liée à une réservation (quantité, logistique) |
Médias et logs
| Table (@@map) | Modèle Prisma | Rôle |
|---|---|---|
media_assets | Media | Fichier media uploadé (kind, statut, URL de stockage) |
audit_logs | AuditLog | Log d'audit applicatif général (action, entité, acteur, IP) |
Module billing — Facturation
| Table (@@map) | Modèle Prisma | Rôle |
|---|---|---|
billing_reservation_financials | BillingReservationFinancial | Financier d'une réservation (montants, commission, dépôt, solde, statut) |
billing_payment_orders | BillingPaymentOrder | Ordre de paiement (SEPA DD, statut, clé d'idempotence) |
billing_invoices | BillingInvoice | Facture émise (numéro unique, montants HT/TVA/TTC, statut) |
billing_ledger_entries | BillingLedgerEntry | Écriture de ledger comptable (direction, code compte, montant) |
invoices | Invoice | Facture simplifiée (organisation, totaux net/taxe/gross) |
billing_sepa_mandates | SepaMandate | Mandat SEPA (référence, statut, date de signature/révocation) |
Module einvoicing — Facturation électronique
| Table (@@map) | Modèle Prisma | Rôle |
|---|---|---|
einvoice_transmissions | EinvoiceTransmission | Transmission d'une facture au provider e-invoicing (statut, tentatives, hash) |
einvoice_webhook_events | EinvoiceWebhookEvent | Événements webhook reçus du provider, statut de traitement |
Module notifications — E-mails transactionnels
| Table (@@map) | Modèle Prisma | Rôle |
|---|---|---|
notification_email_queue | EmailQueueItem | File d'e-mails en attente d'envoi (event, contexte, tentatives, verrou) |
notification_email_dead_letter | EmailDeadLetter | E-mails ayant épuisé toutes les tentatives |
Impression (print) — Domaine transverse
| Table (@@map) | Modèle Prisma | Rôle |
|---|---|---|
print_assets | PrintAsset | Asset PDF déduplicé par hash de contenu (organisation industrielle, métadonnées techniques) |
print_orders | PrintOrder | Ordre d'impression lié à une réservation (statut, imprimeur, livraison) |
print_order_lines | PrintOrderLine | Ligne d'un ordre d'impression (zone, qualifiers, asset, BAT) |
reservation_print_preflights | ReservationPrintPreflight | Rapport de preflight PDF par zone/qualifier d'une réservation |
print_shipment_addresses | PrintShipmentAddress | Adresses de livraison enregistrées par organisation |
printable_zones | PrintableZone | Zone imprimable / face (titre, dimensions) avec gabarits téléchargeables — les vrais fichiers d'impression vierges vivent ici, pas sur le type |
printable_zone_gabarits | PrintableZoneGabarit | Gabarit d'une zone imprimable (URL, format, label) |
promo_furniture_type_faces | PromoFurnitureTypeFace | Table de jointure plusieurs-à-plusieurs entre PrintableZone (face) et PromoFurnitureType : une même face peut être réutilisée sur plusieurs types de meuble |
Fichiers — Registre central
| Table (@@map) | Modèle Prisma | Rôle |
|---|---|---|
files | FileRegistry | Source de vérité des fichiers uploadés (contextId, scopeSegments, MIME, visibilité, soft delete) |
FileRegistry est le registre unique des fichiers de la plateforme. Les URLs de fichiers exposées en API pointent vers /api/files/... et sont résolues dynamiquement depuis ce registre. Les entités métier ne stockent que ces URLs — jamais de chemins absolus locaux.
Résolution des conflits SIRET
| Table (@@map) | Modèle Prisma | Rôle |
|---|---|---|
siret_claim_conflicts | SiretClaimConflict | Conflits de revendication de SIRET entre organisations, suivi de résolution |