Téléphone enrôlé pour un agent. Une installation est enrôlée pour une seule organisation à la fois.
| Name |
Type |
Default |
Nullable |
Children |
Parents |
Comment |
| id |
uuid |
app.uuid_v7() |
false |
app.code_enrolement app.fichier sync.commande sync.commande_resultat app.appel_administration |
|
Identifiant de l’appareil (UUID v7). |
| organisation_id |
uuid |
|
false |
app.code_enrolement app.fichier sync.commande sync.commande_resultat app.appel_administration |
app.utilisateur |
Organisation propriétaire de la ligne. Sert à l’isolation par RLS (EC-032) et au filtrage de la synchronisation. |
| code |
text |
|
false |
|
|
Code court unique de l’appareil, utilisé dans les références provisoires (EC-009). |
| utilisateur_id |
uuid |
|
false |
|
app.utilisateur |
Agent titulaire de l’appareil. |
| modele |
text |
|
true |
|
|
Modèle du téléphone. |
| gnss_bifrequence |
boolean |
|
true |
|
|
Vrai si le téléphone dispose d’un récepteur GNSS bifréquence (GPS-03, GPS-05). |
| version_application |
text |
|
true |
|
|
Dernière version de l’application terrain connue. |
| statut |
text |
‘actif’::text |
false |
|
|
Statut : actif, revoque ou remplace. |
| enrole_le |
timestamp with time zone |
now() |
false |
|
|
Date d’enrôlement. |
| revoque_le |
timestamp with time zone |
|
true |
|
|
Date de révocation. Nulle si l’appareil n’est pas révoqué. |
| revoque_par |
uuid |
|
true |
|
app.utilisateur |
Utilisateur qui a révoqué l’appareil. |
| motif_revocation |
text |
|
true |
|
|
Motif de la révocation, obligatoire dès qu’elle a lieu. |
| derniere_sequence |
bigint |
0 |
false |
|
|
Dernière séquence de commande traitée pour cet appareil. Ne diminue jamais. |
| derniere_synchro |
timestamp with time zone |
|
true |
|
|
Date de la dernière synchronisation. |
| cree_le |
timestamp with time zone |
now() |
false |
|
|
Date de création de la ligne. |
| modifie_le |
timestamp with time zone |
now() |
false |
|
|
Date de la dernière modification, tenue par un déclencheur. |
| Name |
Type |
Definition |
| appareil_check |
CHECK |
CHECK (((statut = ‘revoque’::text) = (revoque_le IS NOT NULL))) |
| appareil_check1 |
CHECK |
CHECK (((revoque_le IS NULL) OR (motif_revocation IS NOT NULL))) |
| appareil_code_check |
CHECK |
CHECK ((code ~ ‘^[A-Z0-9]{4,6}$’::text)) |
| appareil_derniere_sequence_check |
CHECK |
CHECK ((derniere_sequence >= 0)) |
| appareil_statut_check |
CHECK |
CHECK ((statut = ANY (ARRAY[‘actif’::text, ‘revoque’::text, ‘remplace’::text]))) |
| appareil_organisation_id_revoque_par_fkey |
FOREIGN KEY |
FOREIGN KEY (organisation_id, revoque_par) REFERENCES app.utilisateur(organisation_id, id) |
| appareil_organisation_id_utilisateur_id_fkey |
FOREIGN KEY |
FOREIGN KEY (organisation_id, utilisateur_id) REFERENCES app.utilisateur(organisation_id, id) |
| appareil_pkey |
PRIMARY KEY |
PRIMARY KEY (id) |
| appareil_code_key |
UNIQUE |
UNIQUE (code) |
| appareil_organisation_id_id_key |
UNIQUE |
UNIQUE (organisation_id, id) |
| Name |
Definition |
| appareil_pkey |
CREATE UNIQUE INDEX appareil_pkey ON app.appareil USING btree (id) |
| appareil_code_key |
CREATE UNIQUE INDEX appareil_code_key ON app.appareil USING btree (code) |
| appareil_organisation_id_id_key |
CREATE UNIQUE INDEX appareil_organisation_id_id_key ON app.appareil USING btree (organisation_id, id) |
| Name |
Definition |
| journal |
CREATE TRIGGER journal AFTER INSERT OR DELETE OR UPDATE ON app.appareil FOR EACH ROW EXECUTE FUNCTION journal.tg_journaliser() |
| modifie_le |
CREATE TRIGGER modifie_le BEFORE UPDATE ON app.appareil FOR EACH ROW EXECUTE FUNCTION app.tg_modifie_le() |
erDiagram
"app.code_enrolement" }o--|| "app.appareil" : "FOREIGN KEY (organisation_id, appareil_id) REFERENCES app.appareil(organisation_id, id)"
"app.fichier" }o--|| "app.appareil" : "FOREIGN KEY (organisation_id, appareil_id) REFERENCES app.appareil(organisation_id, id)"
"sync.commande" }o--|| "app.appareil" : "FOREIGN KEY (organisation_id, appareil_id) REFERENCES app.appareil(organisation_id, id)"
"sync.commande_resultat" }o--|| "app.appareil" : "FOREIGN KEY (organisation_id, appareil_id) REFERENCES app.appareil(organisation_id, id)"
"app.appel_administration" }o--|| "app.appareil" : "FOREIGN KEY (organisation_id, cible_appareil_id) REFERENCES app.appareil(organisation_id, id)"
"app.appareil" }o--|| "app.utilisateur" : "FOREIGN KEY (organisation_id, revoque_par) REFERENCES app.utilisateur(organisation_id, id)"
"app.appareil" }o--|| "app.utilisateur" : "FOREIGN KEY (organisation_id, utilisateur_id) REFERENCES app.utilisateur(organisation_id, id)"
"app.appareil" {
uuid id "Identifiant de l'appareil (UUID v7)."
uuid organisation_id FK "Organisation propriétaire de la ligne. Sert à l'isolation par RLS (EC-032) et au filtrage de la synchronisation."
text code "Code court unique de l'appareil, utilisé dans les références provisoires (EC-009)."
uuid utilisateur_id FK "Agent titulaire de l'appareil."
text modele "Modèle du téléphone."
boolean gnss_bifrequence "Vrai si le téléphone dispose d'un récepteur GNSS bifréquence (GPS-03, GPS-05)."
text version_application "Dernière version de l'application terrain connue."
text statut "Statut : actif, revoque ou remplace."
timestamp_with_time_zone enrole_le "Date d'enrôlement."
timestamp_with_time_zone revoque_le "Date de révocation. Nulle si l'appareil n'est pas révoqué."
uuid revoque_par FK "Utilisateur qui a révoqué l'appareil."
text motif_revocation "Motif de la révocation, obligatoire dès qu'elle a lieu."
bigint derniere_sequence "Dernière séquence de commande traitée pour cet appareil. Ne diminue jamais."
timestamp_with_time_zone derniere_synchro "Date de la dernière synchronisation."
timestamp_with_time_zone cree_le "Date de création de la ligne."
timestamp_with_time_zone modifie_le "Date de la dernière modification, tenue par un déclencheur."
}
"app.code_enrolement" {
uuid id "Identifiant du code (UUID v7)."
uuid organisation_id FK "Organisation propriétaire de la ligne. Sert à l'isolation par RLS (EC-032) et au filtrage de la synchronisation."
uuid utilisateur_id FK "Agent pour lequel le code a été généré."
text empreinte_code "Empreinte SHA-256 du code, en hexadécimal."
timestamp_with_time_zone expire_le "Date d'expiration du code (24 heures)."
timestamp_with_time_zone utilise_le "Date d'utilisation. Nulle tant que le code n'a pas servi."
uuid appareil_id FK "Appareil enrôlé avec ce code."
uuid cree_par FK "Administrateur qui a généré le code. Différent de l'agent."
timestamp_with_time_zone cree_le "Date de création de la ligne."
timestamp_with_time_zone modifie_le "Date de la dernière modification, tenue par un déclencheur."
}
"app.fichier" {
uuid id "Identifiant du fichier (UUID v7, généré sur l'appareil ou par l'API)."
uuid organisation_id FK "Organisation propriétaire de la ligne. Sert à l'isolation par RLS (EC-032) et au filtrage de la synchronisation."
text cle_objet "Clé de l'objet dans le stockage."
text type_mime "Type MIME du contenu."
bigint taille_octets "Taille en octets."
text sha256 "Empreinte SHA-256 du contenu, en hexadécimal."
text statut "Statut : attendu, recu ou empreinte_invalide. Un fichier reçu n'est plus modifiable."
uuid appareil_id FK "Appareil d'origine du dépôt."
uuid depose_par FK "Utilisateur qui a déposé le fichier."
timestamp_with_time_zone depose_le "Date de réception du contenu par le stockage."
timestamp_with_time_zone cree_le "Date de création de la ligne."
timestamp_with_time_zone modifie_le "Date de la dernière modification, tenue par un déclencheur."
}
"sync.commande" {
uuid id "Identifiant de la commande (UUID v7 généré sur l'appareil). Clé d'idempotence."
uuid organisation_id FK "Organisation propriétaire de la ligne. Sert à l'isolation par RLS (EC-032) et au filtrage de la synchronisation."
uuid appareil_id FK "Appareil émetteur."
uuid utilisateur_id FK "Agent auteur."
bigint sequence "Séquence locale de l'appareil, à partir de 1. Unique par appareil."
text type "Type de commande (ex. collecte.enregistrer)."
integer version_schema "Version du JSON Schema de la charge utile."
timestamp_with_time_zone cree_le_appareil "Heure du téléphone à la saisie."
timestamp_with_time_zone date_operation "Date d'opération retenue par le serveur, jamais postérieure à la réception (protocole §6.4)."
timestamp_with_time_zone recue_le "Heure de réception par le serveur."
text reference_provisoire "Référence provisoire du document de terrain (EC-009)."
text empreinte "Empreinte SHA-256 de la commande canonique."
jsonb enveloppe "Commande complète en JSON, telle que reçue."
}
"sync.commande_resultat" {
uuid id FK "Identifiant de la commande concernée (PowerSync exige une colonne id)."
uuid organisation_id FK "Organisation propriétaire de la ligne. Sert à l'isolation par RLS (EC-032) et au filtrage de la synchronisation."
uuid appareil_id FK "Appareil destinataire."
text issue "Issue : acceptee, acceptee_controle ou rejetee."
text__ motifs "Motifs de contrôle ou de rejet. Vide si la commande est acceptée."
text__ alertes "Alertes non bloquantes."
text numero_officiel "Numéro officiel attribué par le serveur."
jsonb entites "Entités créées, par identifiant, en JSON."
timestamp_with_time_zone date_operation "Date d'opération retenue."
timestamp_with_time_zone traitee_le "Date de traitement par le serveur."
}
"app.appel_administration" {
uuid id "Identifiant de l'appel (UUID v7)."
uuid organisation_id FK "Organisation concernée : l'organisation active, ou celle qui vient d'être créée. Sert à l'isolation par RLS (EC-032)."
uuid auteur_sub "Identifiant Keycloak de l'auteur de l'appel."
uuid auteur_id FK "Ligne app.utilisateur de l'auteur dans l'organisation. Nul pour un membre de l'équipe BioTrace qui crée une organisation."
text action "Action demandée, ex. utilisateur.creer, utilisateur.desactiver, appareil.revoquer, organisation.creer."
uuid cible_utilisateur_id FK "Utilisateur visé, de la même organisation."
uuid cible_keycloak_sub "Identifiant Keycloak du compte visé, conservé même si la ligne app.utilisateur n'existe pas ou plus."
uuid cible_appareil_id FK "Appareil visé, de la même organisation."
text resultat "`reussi`, `refuse` (droit manquant, cible d'une autre organisation) ou `echec` (Keycloak ou base indisponible)."
jsonb details "Éléments utiles à l'audit : motif, code d'erreur, ensemble de permissions. Jamais de mot de passe ni de jeton."
timestamp_with_time_zone cree_le "Date de l'appel."
}
"app.utilisateur" {
uuid id "Identifiant de l'utilisateur (UUID v7)."
uuid organisation_id FK "Organisation propriétaire de la ligne. Sert à l'isolation par RLS (EC-032) et au filtrage de la synchronisation."
uuid keycloak_sub "Identifiant du compte Keycloak (revendication sub). Identique d'une organisation à l'autre pour un compte externe."
text identifiant "Identifiant local de connexion, sans le code de l'organisation : 3 à 32 caractères parmi a-z, 0-9, _ et -. Unique dans l'organisation."
text nom_affiche "Nom affiché dans l'application."
text telephone "Numéro de téléphone. Attribut du compte, jamais son identifiant."
text statut "Statut du compte : actif, suspendu ou desactive."
timestamp_with_time_zone cree_le "Date de création de la ligne."
timestamp_with_time_zone modifie_le "Date de la dernière modification, tenue par un déclencheur."
}
Generated by tbls