Constat d’écart (AM-15) : chaque ligne vraie, ou impossible à évaluer, laisse une trace explicable (règle, version, source, valeurs). Ne se modifie que par changement de statut ; l’historique est dans le journal.
| Name |
Type |
Default |
Nullable |
Children |
Parents |
Comment |
| id |
uuid |
app.uuid_v7() |
false |
app.evaluation_point app.quarantaine_lot app.registre_annulation |
|
Identifiant stable (UUID v7). |
| organisation_id |
uuid |
|
false |
app.evaluation_point app.quarantaine_lot app.registre_annulation |
app.organisation app.utilisateur |
Organisation concernée. Sert à l’isolation par RLS (EC-032). |
| regle_decision_id |
uuid |
|
true |
|
app.regle_decision |
Ligne de décision évaluée. |
| regle_code |
text |
|
false |
|
|
Code de la ligne, recopié pour la lecture (instantané, PC-08). |
| version |
text |
|
false |
|
|
Version du pack de la ligne, recopiée (instantané, PC-08). |
| source |
text |
|
false |
|
|
Source de la ligne, recopiée (instantané, PC-08). |
| accroche |
text |
|
false |
|
|
Point d’accroche de l’évaluation. |
| objet_type |
text |
|
false |
|
|
Nature de l’objet concerné (reception, lot, collecte…). |
| objet_id |
uuid |
|
false |
|
|
Identifiant de l’objet concerné. |
| resultat |
text |
|
false |
|
|
ecart (condition vraie) ou a_verifier (variable, paramètre ou date absents, erreur d’évaluation : jamais de valeur par défaut, PC-07). |
| issue |
text |
|
true |
|
|
Issue de la ligne pour un écart ; vide pour « à vérifier ». |
| motif |
text |
|
true |
|
|
Raison d’un « à vérifier » ; vide pour un écart. |
| valeurs |
jsonb |
‘{}’::jsonb |
false |
|
|
Valeurs lues par la ligne et paramètres utilisés, au moment de l’évaluation. |
| constatee |
bigint |
|
true |
|
|
Valeur constatée, si la ligne déclare une mesure (entier, unité de la variable). |
| attendue |
bigint |
|
true |
|
|
Valeur attendue, si la ligne déclare une mesure. |
| ecart |
bigint |
|
true |
|
|
Écart constatée − attendue, si la ligne déclare une mesure. |
| controle_id |
uuid |
|
true |
|
sync.controle |
Entrée de la file de contrôle liée, quand l’issue met une commande en contrôle (EC-091). |
| statut |
text |
‘ouvert’::text |
false |
|
|
ouvert, justifie (note exigée), leve, clos (final). |
| note |
text |
|
true |
|
|
Justification écrite (RG-308), obligatoire pour « justifié ». |
| statut_par |
uuid |
|
true |
|
app.utilisateur |
Auteur du dernier changement de statut. |
| statut_le |
timestamp with time zone |
|
true |
|
|
Date du dernier changement de statut, posée par la base. |
| cree_par |
uuid |
|
true |
|
app.utilisateur |
Utilisateur à l’origine de l’évaluation ; vide pour une évaluation du serveur. |
| cree_le |
timestamp with time zone |
clock_timestamp() |
false |
|
|
Date du constat. |
| modifie_le |
timestamp with time zone |
now() |
false |
|
|
Date de la dernière modification, tenue par un déclencheur. |
| origine |
text |
‘pack’::text |
false |
|
|
Origine de la règle : pack (ligne d’une table de décision, regle_decision_id renseigné) ou processus (règle codée comme RG-014 ou RG-172, sans ligne de décision). |
| Name |
Type |
Definition |
| constat_check |
CHECK |
CHECK (((resultat = ‘ecart’::text) = (issue IS NOT NULL))) |
| constat_check1 |
CHECK |
CHECK (((resultat = ‘a_verifier’::text) = (motif IS NOT NULL))) |
| constat_check2 |
CHECK |
CHECK (((statut = ‘ouvert’::text) = (statut_le IS NULL))) |
| constat_check3 |
CHECK |
CHECK (((statut <> ‘justifie’::text) OR (note IS NOT NULL))) |
| constat_issue_check |
CHECK |
CHECK ((issue = ANY (ARRAY[‘signaler’::text, ‘exiger_note’::text, ‘exiger_piece’::text, ‘creer_non_conformite’::text, ‘quarantaine’::text, ‘bloquer’::text]))) |
| constat_motif_check |
CHECK |
CHECK ((motif = ANY (ARRAY[‘variable_manquante’::text, ‘parametre_introuvable’::text, ‘date_reference_absente’::text, ‘erreur_evaluation’::text]))) |
| constat_note_check |
CHECK |
CHECK ((note <> ‘’::text)) |
| constat_objet_type_check |
CHECK |
CHECK ((objet_type ~ ‘^[a-z][a-z0-9_]*$’::text)) |
| constat_origine_check |
CHECK |
CHECK ((origine = ANY (ARRAY[‘pack’::text, ‘processus’::text]))) |
| constat_origine_coherente |
CHECK |
CHECK (((origine = ‘pack’::text) = (regle_decision_id IS NOT NULL))) |
| constat_resultat_check |
CHECK |
CHECK ((resultat = ANY (ARRAY[‘ecart’::text, ‘a_verifier’::text]))) |
| constat_statut_check |
CHECK |
CHECK ((statut = ANY (ARRAY[‘ouvert’::text, ‘justifie’::text, ‘leve’::text, ‘clos’::text]))) |
| constat_organisation_id_fkey |
FOREIGN KEY |
FOREIGN KEY (organisation_id) REFERENCES app.organisation(id) |
| constat_organisation_id_cree_par_fkey |
FOREIGN KEY |
FOREIGN KEY (organisation_id, cree_par) REFERENCES app.utilisateur(organisation_id, id) |
| constat_organisation_id_statut_par_fkey |
FOREIGN KEY |
FOREIGN KEY (organisation_id, statut_par) REFERENCES app.utilisateur(organisation_id, id) |
| constat_controle_id_fkey |
FOREIGN KEY |
FOREIGN KEY (controle_id) REFERENCES sync.controle(id) |
| constat_regle_decision_id_fkey |
FOREIGN KEY |
FOREIGN KEY (regle_decision_id) REFERENCES app.regle_decision(id) |
| constat_pkey |
PRIMARY KEY |
PRIMARY KEY (id) |
| constat_organisation_id_id_key |
UNIQUE |
UNIQUE (organisation_id, id) |
| Name |
Definition |
| constat_pkey |
CREATE UNIQUE INDEX constat_pkey ON app.constat USING btree (id) |
| constat_organisation_id_id_key |
CREATE UNIQUE INDEX constat_organisation_id_id_key ON app.constat USING btree (organisation_id, id) |
| constat_objet_idx |
CREATE INDEX constat_objet_idx ON app.constat USING btree (organisation_id, objet_type, objet_id) |
| Name |
Definition |
| journal |
CREATE TRIGGER journal AFTER INSERT OR DELETE OR UPDATE ON app.constat FOR EACH ROW EXECUTE FUNCTION journal.tg_journaliser() |
| modifie_le |
CREATE TRIGGER modifie_le BEFORE UPDATE ON app.constat FOR EACH ROW EXECUTE FUNCTION app.tg_modifie_le() |
| statut_seul |
CREATE TRIGGER statut_seul BEFORE UPDATE ON app.constat FOR EACH ROW EXECUTE FUNCTION app.tg_constat_statut_seul() |
erDiagram
"app.evaluation_point" }o--|| "app.constat" : "FOREIGN KEY (organisation_id, constat_id) REFERENCES app.constat(organisation_id, id)"
"app.quarantaine_lot" }o--|| "app.constat" : "FOREIGN KEY (organisation_id, constat_id) REFERENCES app.constat(organisation_id, id)"
"app.registre_annulation" }o--|| "app.constat" : "FOREIGN KEY (organisation_id, constat_id) REFERENCES app.constat(organisation_id, id)"
"app.constat" }o--|| "app.organisation" : "FOREIGN KEY (organisation_id) REFERENCES app.organisation(id)"
"app.constat" }o--|| "app.utilisateur" : "FOREIGN KEY (organisation_id, cree_par) REFERENCES app.utilisateur(organisation_id, id)"
"app.constat" }o--|| "app.utilisateur" : "FOREIGN KEY (organisation_id, statut_par) REFERENCES app.utilisateur(organisation_id, id)"
"app.constat" }o--o| "app.regle_decision" : "FOREIGN KEY (regle_decision_id) REFERENCES app.regle_decision(id)"
"app.constat" }o--o| "sync.controle" : "FOREIGN KEY (controle_id) REFERENCES sync.controle(id)"
"app.constat" {
uuid id "Identifiant stable (UUID v7)."
uuid organisation_id FK "Organisation concernée. Sert à l'isolation par RLS (EC-032)."
uuid regle_decision_id FK "Ligne de décision évaluée."
text regle_code "Code de la ligne, recopié pour la lecture (instantané, PC-08)."
text version "Version du pack de la ligne, recopiée (instantané, PC-08)."
text source "Source de la ligne, recopiée (instantané, PC-08)."
text accroche "Point d'accroche de l'évaluation."
text objet_type "Nature de l'objet concerné (reception, lot, collecte…)."
uuid objet_id "Identifiant de l'objet concerné."
text resultat "ecart (condition vraie) ou a_verifier (variable, paramètre ou date absents, erreur d'évaluation : jamais de valeur par défaut, PC-07)."
text issue "Issue de la ligne pour un écart ; vide pour « à vérifier »."
text motif "Raison d'un « à vérifier » ; vide pour un écart."
jsonb valeurs "Valeurs lues par la ligne et paramètres utilisés, au moment de l'évaluation."
bigint constatee "Valeur constatée, si la ligne déclare une mesure (entier, unité de la variable)."
bigint attendue "Valeur attendue, si la ligne déclare une mesure."
bigint ecart "Écart constatée − attendue, si la ligne déclare une mesure."
uuid controle_id FK "Entrée de la file de contrôle liée, quand l'issue met une commande en contrôle (EC-091)."
text statut "ouvert, justifie (note exigée), leve, clos (final)."
text note "Justification écrite (RG-308), obligatoire pour « justifié »."
uuid statut_par FK "Auteur du dernier changement de statut."
timestamp_with_time_zone statut_le "Date du dernier changement de statut, posée par la base."
uuid cree_par FK "Utilisateur à l'origine de l'évaluation ; vide pour une évaluation du serveur."
timestamp_with_time_zone cree_le "Date du constat."
timestamp_with_time_zone modifie_le "Date de la dernière modification, tenue par un déclencheur."
text origine "Origine de la règle : pack (ligne d'une table de décision, regle_decision_id renseigné) ou processus (règle codée comme RG-014 ou RG-172, sans ligne de décision)."
}
"app.evaluation_point" {
uuid id "Identifiant stable (UUID v7)."
uuid organisation_id FK "Organisation propriétaire. Sert à l'isolation par RLS (EC-032)."
uuid point_controle_id FK "Point évalué."
text objet_type "Type de l'objet évalué (lot, site…). Vide : le point est évalué pour toute l'organisation."
uuid objet_id "Identifiant de l'objet évalué. Renseigné avec `objet_type`, ou pas du tout."
text statut "`satisfait`, `preuve_manquante`, `ecart_ouvert`, `a_verifier` ou `non_applicable`. Une personne ne déclare jamais « preuve manquante » : il se déduit des pièces."
text source "`regle` : résultat d'une règle du moteur. `manuelle` : déclaration d'une personne."
uuid constat_id FK "Constat d'écart ouvert par la règle (AM-15), pour une évaluation issue d'une règle."
text motif "Justification de la déclaration. Obligatoire pour déclarer un point satisfait ou non applicable."
uuid evalue_par FK "Utilisateur qui a déclaré. Vide pour un résultat de règle."
timestamp_with_time_zone evalue_le "Date de l'évaluation."
}
"app.quarantaine_lot" {
uuid id "Identifiant de l'événement (UUID v7, ordonné dans le temps)."
uuid organisation_id FK "Organisation propriétaire (isolation par ligne)."
uuid lot_id FK "Lot concerné."
text evenement "Événement : mise (le lot validé passe en quarantaine) ou levee (il redevient validé)."
text motif "Motif de la mise ou de la levée ; toujours renseigné."
uuid constat_id FK "Constat de la règle qui a déclenché la mise en quarantaine ; vide pour une mise ou une levée manuelle."
uuid cree_par FK "Utilisateur qui a mis le lot en quarantaine ou levé la quarantaine."
timestamp_with_time_zone cree_le "Date de l'événement."
}
"app.registre_annulation" {
uuid id "Identifiant de la ligne du registre (UUID v7)."
uuid organisation_id FK "Organisation propriétaire (isolation par ligne)."
text objet_type "Type d'objet défait : reception, etape_realisee, expedition, vente ou lot."
uuid objet_id "Identifiant de l'objet défait."
text nature "devalidation (retour à l'état précédent : réception, étape, expédition) ou annulation (clôture : vente, lot). Deux mécanismes distincts (EC-008)."
text motif "Justification écrite, obligatoire."
uuid lot_id FK "Lot annulé, avec son numéro conservé (RG-143) ; pour une dévalidation de réception, le lot d'origine annulé. Vide pour une vente, une étape ou une expédition."
uuid campagne_id FK "Campagne concernée, pour l'édition du registre par campagne (RG-144) ; vide pour une vente ou une expédition."
uuid mouvement_id FK "Mouvement de contre-passation écrit ; vide pour l'annulation d'une vente, qui n'a pas encore bougé la matière."
uuid constat_id FK "Constat consigné pour la dévalidation (AM-15) ; vide pour une annulation."
uuid cree_par FK "Utilisateur qui défait l'objet (direction)."
timestamp_with_time_zone cree_le "Date de la dévalidation ou de l'annulation."
}
"app.organisation" {
uuid id "Identifiant de l'organisation (UUID v7)."
text code "Code court en majuscules. Immuable : il figure dans les identifiants Keycloak (coopa.agent01). « EXT » est réservé."
text nom "Nom de l'organisation."
text pays "Pays, code ISO 3166-1 alpha-2."
text langue "Langue de l'organisation : fr ou en."
text fuseau_horaire "Fuseau horaire IANA utilisé pour l'affichage des dates."
text devise_defaut "Devise par défaut des montants, code ISO 4217."
text keycloak_organisation_id "Identifiant de l'organisation dans Keycloak."
text organisme_certificateur "Organisme de certification de l'organisation. Aucun contrôle de format (EC-027)."
text code_operateur "Code d'opérateur attribué par l'organisme certificateur."
uuid logo_fichier_id FK "Fichier du logo (EC-029)."
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."
text source_conformite "Source des décisions de conformité : `interne` (contrôle interne de BioTrace) ou `externe` (outil tiers). Une seule source active à la fois ; app.statut_conformite.source doit lui être égale."
text statut "État du compte client : `active` ou `suspendue`. Une organisation suspendue est refusée par la garde d'authentification (`organisation_suspendue`) ; ses données et ses comptes sont conservés. Décidé par l'équipe de l'éditeur (EC-126)."
timestamp_with_time_zone suspendue_le "Date de la suspension en cours ; nulle tant que l'organisation est active."
}
"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."
}
"app.regle_decision" {
uuid id "Identifiant stable (UUID v7)."
uuid pack_version_id FK "Version du pack référentiel qui publie la ligne."
text code "Identifiant de la ligne dans le pack, stable d'une version à l'autre."
text accroche "Point d'accroche où la ligne est évaluée (reception.avant_validation…), déclaré par un manifeste de module."
jsonb contexte "Facteurs cités et leurs valeurs acceptées (produit, référentiel…) ; {} : tous les contextes."
text condition "Condition CEL booléenne sur les variables du dictionnaire ; les seuils passent par param('clé'), jamais en dur."
text__ parametres "Clés de paramètres citées par la condition, résolues par le moteur de paramètres."
text issue "Issue d'une condition vraie, parmi six, de la plus faible à la plus forte : signaler, exiger une note, exiger une pièce, créer une non-conformité, mettre en quarantaine, bloquer l'action."
text source "Texte, article ou règle d'où vient la ligne. Obligatoire (PC-06)."
date date_effet "Date d'effet, incluse (AM-11)."
date date_fin "Date de fin, exclue ; vide si la ligne reste en vigueur."
text date_reference "Date de l'objet comparée à la période d'effet : opération, récolte, création du lot ou émission du certificat (AM-11)."
text evaluation "locale (téléphone et serveur) ou serveur (données absentes du téléphone ; issue connue à la synchronisation, AM-10)."
jsonb mesure "Pour un écart chiffré : variable constatée et paramètre attendu (EC-098)."
timestamp_with_time_zone cree_le "Date de publication de la ligne."
}
"sync.controle" {
uuid id "Identifiant du contrôle (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 commande_id FK "Commande à l'origine du contrôle."
text motif "Motif du contrôle, parmi le catalogue du protocole (§9). « module_inactif » (EC-096) : commande d'un module inactif, conservée sans écriture métier."
jsonb details "Éléments de contexte, en JSON."
text statut "Statut : ouvert, en_cours ou leve."
text decision "Décision de levée. Renseignée si et seulement si le contrôle est levé."
text motif_decision "Motif de la décision."
uuid decide_par FK "Utilisateur qui a levé le contrôle. Jamais l'auteur de la commande."
timestamp_with_time_zone decide_le "Date de la levée."
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."
uuid producteur_id FK "Producteur concerné par le contrôle (de la même organisation), par exemple pour un doublon de pièce d'identité (AV1-02)."
uuid parcelle_version_id FK "Version de polygone concernée par le contrôle (de la même organisation) : polygone invalide ou chevauchement."
}
Generated by tbls