My App
Données

Entités

Modèle de données et relations entre entités

Le modèle de données reflète directement les flux métier. Chaque entité correspond à un concept du domaine, pas à une abstraction technique.

Diagramme ER

erDiagram
    User ||--o{ Session : "possède"
    User ||--o{ Account : "possède"
    User }o--|| Establishment : "appartient à"
    User ||--o| UserNotificationConfig : "configure"
    User ||--o{ ReportEvent : "agit sur"

    Establishment ||--o{ Toilet : "contient"
    Establishment ||--o{ User : "a des membres"
    Establishment ||--o{ PredefinedIssue : "définit"

    Toilet ||--|| QRCode : "possède"
    Toilet ||--o{ Report : "reçoit"

    Report ||--o{ Notification : "déclenche"
    Report ||--o{ ReportEvent : "historise"
    Report }o--o| PredefinedIssue : "référence"

Entités principales

User

Utilisateur du dashboard (admin Wcare ou membre d'établissement).

ChampTypeDescription
iduuid (PK)Identifiant unique
namevarcharNom complet
emailvarchar (unique)Email de connexion
roleenumsuper_admin, establishment_admin, establishment_member
establishmentIduuid (FK, nullable)null pour super_admin
emailVerifiedbooleanEmail vérifié
createdAttimestampDate de création
updatedAttimestampDate de mise à jour

Establishment

Un établissement client (hôtel, restaurant, entreprise...).

ChampTypeDescription
iduuid (PK)Identifiant unique
namevarcharNom de l'établissement
typeenumhotel, restaurant, company, agency, other
addressvarcharAdresse postale
cityvarcharVille
postalCodevarcharCode postal
countryvarcharPays (ISO 3166-1 alpha-2)
timezonevarcharTimezone IANA (Europe/Paris)
phonevarchar (nullable)Téléphone
emailvarcharEmail de contact
logovarchar (nullable)URL du logo
whatsappNumbervarchar (nullable)Numéro WhatsApp
isActivebooleanActif/désactivé
createdAttimestampDate de création
updatedAttimestampDate de mise à jour

Toilet

Un WC individuel au sein d'un établissement.

ChampTypeDescription
iduuid (PK)Identifiant unique
establishmentIduuid (FK)Lien vers l'établissement
namevarcharNom interne ("WC Lobby")
locationvarchar (nullable)Localisation détaillée
floorvarchar (nullable)Étage
isActivebooleanActif/inactif
createdAttimestampDate de création
updatedAttimestampDate de mise à jour

QRCode

Le QR code associé à un WC. Relation 1:1 avec Toilet.

ChampTypeDescription
iduuid (PK)Identifiant unique
toiletIduuid (FK, unique)Lien vers le WC
tokenvarchar (unique)Token rotatif pour l'URL
tokenExpiresAttimestampExpiration du token
previousTokenvarchar (nullable)Ancien token (redirect graceful 24h)
previousTokenExpiresAttimestamp (nullable)Fin de la grace period de redirect
customizationjsonbLogo, couleurs, style
createdAttimestampDate de création
updatedAttimestampDate de mise à jour

PredefinedIssue

Problème prédéfini associé à un établissement (personnalisable).

ChampTypeDescription
iduuid (PK)Identifiant unique
establishmentIduuid (FK)Issues globales de l'établissement
categoryenumcleanliness, consumables, equipment, other
labelvarcharTexte affiché ("Toilettes sales")
iconvarchar (nullable)Nom d'icône ou emoji
sortOrderintegerOrdre d'affichage
isActivebooleanActif/inactif

Report

Un signalement de problème par un utilisateur anonyme.

ChampTypeDescription
iduuid (PK)Identifiant unique
toiletIduuid (FK)WC concerné
categoryenumcleanliness, consumables, equipment, other
predefinedIssueIduuid (FK, nullable)Issue prédéfinie sélectionnée
freeTextvarchar(200) (nullable)Texte libre
statusenumnew, seen, in_progress, resolved, ignored
fingerprintvarcharHash device (anti-spam)
ipHashvarcharHash IP (anti-spam)
idempotencyKeyvarchar (unique)hash(fingerprint + toiletId + timestamp_30s)
createdAttimestampDate du signalement
updatedAttimestampDernière modification (optimistic lock)
resolvedAttimestamp (nullable)Date de résolution

ReportEvent

Audit trail — chaque changement de statut d'un signalement.

ChampTypeDescription
iduuid (PK)Identifiant unique
reportIduuid (FK)Signalement concerné
statusenumNouveau statut
userIduuid (FK, nullable)Qui a fait l'action (null si système)
createdAttimestampDate de l'événement

Notification

Notification envoyée suite à un signalement.

ChampTypeDescription
iduuid (PK)Identifiant unique
reportIduuid (FK)Signalement associé
userIduuid (FK)Destinataire
channelenumwhatsapp, email, in_app
statusenumpending, sent, failed
attemptsintegerNombre de tentatives (max 3)
sentAttimestamp (nullable)Date d'envoi
errortext (nullable)Message d'erreur si failed

UserNotificationConfig

Préférences de notification par utilisateur (pas par établissement).

ChampTypeDescription
iduuid (PK)Identifiant unique
userIduuid (FK, unique)Utilisateur concerné
whatsappEnabledbooleanWhatsApp activé
whatsappNumbervarchar (nullable)Numéro WhatsApp personnel
emailEnabledbooleanEmail activé
inAppEnabledbooleanIn-app activé
aggregationWindowMinutesintegerFenêtre d'agrégation WhatsApp (défaut: 5)

NotificationJob

Queue de jobs pour l'envoi async des notifications.

ChampTypeDescription
iduuid (PK)Identifiant unique
typeenumsend_whatsapp, send_email, send_inapp
payloadjsonbDonnées du job
statusenumpending, processing, completed, failed
attemptsintegerTentatives effectuées
maxAttemptsintegerMax tentatives (défaut: 3)
scheduledAttimestampQuand exécuter (pour agrégation)
startedAttimestamp (nullable)Début du processing
completedAttimestamp (nullable)Fin du processing
errortext (nullable)Dernière erreur
createdAttimestampDate de création

Transitions de statut autorisées

stateDiagram-v2
    [*] --> new
    new --> seen : Ouverture par un membre
    new --> ignored : Auto-détecté spam
    seen --> in_progress : Intervention démarrée
    seen --> ignored : Jugé non pertinent
    in_progress --> resolved : Problème corrigé
    in_progress --> seen : Intervention annulée
    resolved --> [*]
    ignored --> [*]

Pas de retour en arrière depuis resolved ou ignored. Si le problème revient, c'est un nouveau signalement.

Index recommandés

TableColonnesTypeRaison
reporttoiletId, createdAt DESCbtreeListe des signalements par WC (dashboard)
reporttoiletId, statusbtreeCompteurs par statut (dashboard overview)
reportfingerprint, createdAtbtreeAnti-spam : cooldown par device
reportipHash, createdAtbtreeAnti-spam : rate limit par IP
reportidempotencyKeyunique btreeDéduplications de signalement
reportcreatedAtbtreePagination cursor-based
qr_codetokenunique btreeLookup par token (scan QR)
qr_codepreviousTokenbtreeRedirect ancien token
toiletestablishmentIdbtreeRequêtes par établissement
notificationreportIdbtreeNotifications par signalement
notification_jobstatus, scheduledAtbtreePoll des jobs à exécuter
report_eventreportId, createdAtbtreeTimeline d'un signalement

On this page