Aller au contenu

app.produit

Matière première ou produit fini de l’organisation, instancié depuis un modèle de pack publié ou créé à la main. Jamais supprimé.

Name Type Default Nullable Children Parents Comment
id uuid app.uuid_v7() false app.mouvement_ligne app.produit app.attribut app.sequence_numero app.parcelle app.zone_cueillette app.contrat_ligne app.certificat_portee app.lot app.reception app.sortie_etape app.vente Identifiant stable (UUID v7).
organisation_id uuid false app.mouvement_ligne app.produit app.attribut app.sequence_numero app.parcelle app.zone_cueillette app.contrat_ligne app.certificat_portee app.lot app.reception app.sortie_etape app.vente app.organisation app.produit Organisation propriétaire. Sert à l’isolation par RLS (EC-032).
code text false Code du produit, inséré dans le numéro officiel (segment « produit »). Unique par organisation (EC-063).
nom_fr text false Nom en français.
nom_en text false Nom en anglais.
unite_code text false app.unite Unité de saisie et d’affichage.
est_matiere_premiere boolean false Vrai pour une matière première, faux pour un produit fini.
matiere_premiere_liee_id uuid true app.produit Matière première dont le produit fini est issu. Réservé aux produits finis, de la même organisation.
code_modele text true Code du modèle de produit du pack qui a servi à créer la ligne. Nul pour un produit créé à la main.
pack_version_id uuid true app.pack_version Version de pack d’origine. Nulle pour un produit créé à la main ; nulle exactement quand code_modele l’est.
actif boolean true false Faux quand le produit n’est plus utilisé. Un produit n’est jamais supprimé.
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 dernière modification.
Name Type Definition
produit_check CHECK CHECK (((matiere_premiere_liee_id IS NULL) OR (NOT est_matiere_premiere)))
produit_check1 CHECK CHECK (((code_modele IS NULL) = (pack_version_id IS NULL)))
produit_code_check CHECK CHECK ((code ~ ‘^[A-Z0-9]{2,10}$’::text))
produit_nom_en_check CHECK CHECK ((nom_en <> ‘’::text))
produit_nom_fr_check CHECK CHECK ((nom_fr <> ‘’::text))
produit_organisation_id_fkey FOREIGN KEY FOREIGN KEY (organisation_id) REFERENCES app.organisation(id)
produit_pack_version_id_fkey FOREIGN KEY FOREIGN KEY (pack_version_id) REFERENCES app.pack_version(id)
produit_unite_code_fkey FOREIGN KEY FOREIGN KEY (unite_code) REFERENCES app.unite(code)
produit_pkey PRIMARY KEY PRIMARY KEY (id)
produit_organisation_id_code_key UNIQUE UNIQUE (organisation_id, code)
produit_organisation_id_id_key UNIQUE UNIQUE (organisation_id, id)
produit_organisation_id_matiere_premiere_liee_id_fkey FOREIGN KEY FOREIGN KEY (organisation_id, matiere_premiere_liee_id) REFERENCES app.produit(organisation_id, id)
Name Definition
produit_pkey CREATE UNIQUE INDEX produit_pkey ON app.produit USING btree (id)
produit_organisation_id_code_key CREATE UNIQUE INDEX produit_organisation_id_code_key ON app.produit USING btree (organisation_id, code)
produit_organisation_id_id_key CREATE UNIQUE INDEX produit_organisation_id_id_key ON app.produit USING btree (organisation_id, id)
produit_modele_unique CREATE UNIQUE INDEX produit_modele_unique ON app.produit USING btree (organisation_id, code_modele) WHERE (code_modele IS NOT NULL)
Name Definition
journal CREATE TRIGGER journal AFTER INSERT OR DELETE OR UPDATE ON app.produit FOR EACH ROW EXECUTE FUNCTION journal.tg_journaliser()
modifie_le CREATE TRIGGER modifie_le BEFORE UPDATE ON app.produit FOR EACH ROW EXECUTE FUNCTION app.tg_modifie_le()
erDiagram

"app.mouvement_ligne" }o--|| "app.produit" : "FOREIGN KEY (organisation_id, produit_id) REFERENCES app.produit(organisation_id, id)"
"app.produit" }o--|| "app.produit" : "FOREIGN KEY (organisation_id, matiere_premiere_liee_id) REFERENCES app.produit(organisation_id, id)"
"app.attribut" }o--|| "app.produit" : "FOREIGN KEY (organisation_id, produit_id) REFERENCES app.produit(organisation_id, id)"
"app.sequence_numero" }o--|| "app.produit" : "FOREIGN KEY (organisation_id, produit_id) REFERENCES app.produit(organisation_id, id)"
"app.parcelle" }o--|| "app.produit" : "FOREIGN KEY (organisation_id, produit_id) REFERENCES app.produit(organisation_id, id)"
"app.zone_cueillette" }o--|| "app.produit" : "FOREIGN KEY (organisation_id, produit_id) REFERENCES app.produit(organisation_id, id)"
"app.contrat_ligne" }o--|| "app.produit" : "FOREIGN KEY (organisation_id, produit_id) REFERENCES app.produit(organisation_id, id)"
"app.certificat_portee" }o--|| "app.produit" : "FOREIGN KEY (organisation_id, produit_id) REFERENCES app.produit(organisation_id, id)"
"app.lot" }o--|| "app.produit" : "FOREIGN KEY (organisation_id, produit_id) REFERENCES app.produit(organisation_id, id)"
"app.reception" }o--|| "app.produit" : "FOREIGN KEY (organisation_id, produit_id) REFERENCES app.produit(organisation_id, id)"
"app.sortie_etape" }o--|| "app.produit" : "FOREIGN KEY (organisation_id, produit_id) REFERENCES app.produit(organisation_id, id)"
"app.vente" }o--|| "app.produit" : "FOREIGN KEY (organisation_id, produit_id) REFERENCES app.produit(organisation_id, id)"
"app.produit" }o--|| "app.organisation" : "FOREIGN KEY (organisation_id) REFERENCES app.organisation(id)"
"app.produit" }o--|| "app.unite" : "FOREIGN KEY (unite_code) REFERENCES app.unite(code)"
"app.produit" }o--o| "app.pack_version" : "FOREIGN KEY (pack_version_id) REFERENCES app.pack_version(id)"

"app.produit" {
  uuid id "Identifiant stable (UUID v7)."
  uuid organisation_id FK "Organisation propriétaire. Sert à l'isolation par RLS (EC-032)."
  text code "Code du produit, inséré dans le numéro officiel (segment « produit »). Unique par organisation (EC-063)."
  text nom_fr "Nom en français."
  text nom_en "Nom en anglais."
  text unite_code FK "Unité de saisie et d'affichage."
  boolean est_matiere_premiere "Vrai pour une matière première, faux pour un produit fini."
  uuid matiere_premiere_liee_id FK "Matière première dont le produit fini est issu. Réservé aux produits finis, de la même organisation."
  text code_modele "Code du modèle de produit du pack qui a servi à créer la ligne. Nul pour un produit créé à la main."
  uuid pack_version_id FK "Version de pack d'origine. Nulle pour un produit créé à la main ; nulle exactement quand code_modele l'est."
  boolean actif "Faux quand le produit n'est plus utilisé. Un produit n'est jamais supprimé."
  timestamp_with_time_zone cree_le "Date de création de la ligne."
  timestamp_with_time_zone modifie_le "Date de dernière modification."
}
"app.mouvement_ligne" {
  uuid id "Identifiant de la ligne (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 mouvement_id FK "Mouvement auquel appartient la ligne."
  uuid compte_matiere_id FK "Compte débité ou crédité."
  uuid produit_id FK "Produit concerné, de la même organisation (clé étrangère posée au Lot 1, séquence A2)."
  bigint quantite_g "Quantité en grammes, signée et non nulle."
  timestamp_with_time_zone cree_le "Date de création de la ligne."
}
"app.attribut" {
  uuid id "Identifiant stable (UUID v7)."
  uuid organisation_id FK "Organisation propriétaire. Sert à l'isolation par RLS (EC-032)."
  uuid produit_id FK "Produit décrit, de la même organisation."
  text code "Code de l'attribut, unique pour le produit : calibre, brix…"
  text libelle_fr "Libellé en français, affiché au-dessus du champ."
  text libelle_en "Libellé en anglais."
  jsonb schema "JSON Schema de la valeur de l'attribut (un objet). Entiers seulement pour les mesures (calculs en entiers)."
  boolean obligatoire "Vrai si la valeur doit être fournie à la saisie."
  integer ordre "Rang d'affichage dans le formulaire."
  timestamp_with_time_zone cree_le "Date de création de la ligne."
  timestamp_with_time_zone modifie_le "Date de dernière modification."
}
"app.sequence_numero" {
  uuid id "Identifiant stable (UUID v7)."
  uuid organisation_id FK "Organisation propriétaire. Sert à l'isolation par RLS (EC-032)."
  uuid campagne_id FK "Campagne de la séquence (de la même organisation)."
  text nature "Nature du numéro : MP (matière première), REC (réception), NET (nettoyage), PF (produit fini). « Vente » n'existe plus (avenant n°1). Codes à confirmer, EC-068."
  uuid produit_id FK "Produit de la séquence (de la même organisation)."
  bigint derniere_valeur "Dernier rang attribué ; 0 tant qu'aucun numéro n'est sorti. Ne revient jamais en arrière."
  timestamp_with_time_zone cree_le "Date de création de la ligne."
  timestamp_with_time_zone modifie_le "Date de dernière modification."
}
"app.parcelle" {
  uuid id "Identifiant stable (UUID v7)."
  uuid organisation_id FK "Organisation propriétaire. Sert à l'isolation par RLS (EC-032)."
  uuid groupement_id FK "Groupement de la parcelle, identique à celui de son producteur (clé composée) : un producteur qui a des parcelles ne change pas de groupement."
  uuid producteur_id FK "Producteur propriétaire de la parcelle (de la même organisation)."
  uuid produit_id FK "Produit cultivé (de la même organisation)."
  text code "Code de la parcelle, unique par organisation."
  text type_surface "`cultures`, `serres` ou `prairies` : sert aux seuils d'éligibilité au groupe (RG-024)."
  bigint surface_declaree_m2 "Surface déclarée par le producteur, en m² (EC-030). Jamais la base d'une capacité : c'est la surface mesurée (AV1-01)."
  text region_facteur FK "Constante `region` : nom du facteur de la clé étrangère composée vers facteur_valeur."
  text region FK "Région (valeur du facteur `region`), facultative."
  text mode_culture_facteur FK "Constante `mode_culture` : nom du facteur de la clé étrangère composée vers facteur_valeur."
  text mode_culture FK "Mode de culture (`pluvial` ou `irrigue`), facultatif."
  text type_sol_facteur FK "Constante `type_sol` : nom du facteur de la clé étrangère composée vers facteur_valeur."
  text type_sol FK "Type de sol (valeur du facteur `type_sol`), facultatif."
  boolean actif "Faux quand la parcelle n'est plus utilisée. Une parcelle n'est jamais supprimée."
  timestamp_with_time_zone cree_le "Date de création de la ligne."
  timestamp_with_time_zone modifie_le "Date de dernière modification."
}
"app.zone_cueillette" {
  uuid id "Identifiant stable (UUID v7)."
  uuid organisation_id FK "Organisation propriétaire. Sert à l'isolation par RLS (EC-032)."
  uuid groupement_id FK "Groupement qui exploite la zone (de la même organisation)."
  uuid produit_id FK "Produit cueilli (de la même organisation)."
  text code "Code de la zone, unique par organisation."
  text nom "Nom de la zone."
  boolean actif "Faux quand la zone n'est plus utilisée. Une zone n'est jamais supprimée."
  timestamp_with_time_zone cree_le "Date de création de la ligne."
  timestamp_with_time_zone modifie_le "Date de dernière modification."
}
"app.contrat_ligne" {
  uuid id "Identifiant stable (UUID v7)."
  uuid organisation_id FK "Organisation propriétaire. Sert à l'isolation par RLS (EC-032)."
  uuid contrat_id FK "Contrat de la ligne (de la même organisation)."
  uuid produit_id FK "Produit de la ligne (de la même organisation), unique dans le contrat."
  bigint quantite_engagee_g "Quantité engagée en grammes (EC-030), strictement positive."
  bigint prix_unite_mineure "Prix de base en unités mineures de la devise, par unité de prix (par exemple 150 XOF le kilo). Jamais sans devise."
  text devise FK "Devise du prix, code ISO 4217 connu de app.devise (EC-028)."
  text unite_prix FK "Unité du prix (`g`, `kg`, `t`) : le prix vaut par cette unité. Le stock reste en grammes (EC-030)."
  integer tolerance_cp "Tolérance sur la quantité engagée, en centièmes de point. L'alerte de solde au-delà est calculée au Lot 2."
  jsonb formule_refaction "Formule de réfaction en JSON (aucune, excedent_lineaire, lineaire_simple, bilan_de_masse), forme validée par FormuleRefaction (Ajv) ; le mode d'arrondi en fait partie (EC-051). Lue par calculerPesee à la réception."
  timestamp_with_time_zone cree_le "Date de création de la ligne."
  timestamp_with_time_zone modifie_le "Date de dernière modification."
}
"app.certificat_portee" {
  uuid id "Identifiant stable (UUID v7)."
  uuid organisation_id FK "Organisation propriétaire. Sert à l'isolation par RLS (EC-032)."
  uuid certificat_id FK "Certificat dont la ligne précise la portée (de la même organisation)."
  text dimension "`activite`, `produit`, `site` ou `unite`. Détermine la seule colonne d'élément renseignée."
  text activite_code FK "Activité du catalogue fermé (dimension `activite`)."
  uuid produit_id FK "Produit du catalogue de l'organisation (dimension `produit`). Les produits sont listés un à un : le catalogue n'a pas de catégorie (EC-102)."
  uuid site_id FK "Site de l'organisation (dimension `site`)."
  uuid producteur_id FK "Unité producteur (dimension `unite`). Exactement une unité entre producteur, parcelle et zone de cueillette."
  uuid parcelle_id FK "Unité parcelle (dimension `unite`)."
  uuid zone_cueillette_id FK "Unité zone de cueillette (dimension `unite`)."
  boolean inclus "Vrai : l'élément est couvert par le certificat. Faux : il est exclu expressément, et l'exclusion l'emporte sur une inclusion plus large."
  uuid cree_par FK "Utilisateur qui a déclaré la ligne."
  timestamp_with_time_zone cree_le "Date de création de la ligne."
}
"app.lot" {
  uuid id "Identifiant du lot (UUID v7)."
  uuid organisation_id FK "Organisation propriétaire (isolation par ligne)."
  uuid campagne_id FK "Campagne du lot."
  text reference_provisoire "Référence provisoire, tant que le lot n'est pas validé (BR-AAAA-MM-JJ-NNNN dans le cahier)."
  bigint numero "Rang du numéro officiel, pris par app.attribuer_numero à la validation, jamais réutilisé (I3). Vide avant la validation."
  text nature "Nature de la séquence de numérotation : MP matière première, REC réception, NET nettoyé, PF produit fini (EC-068)."
  uuid produit_id FK "Produit du lot."
  text qualite "Catégorie d'affichage du lot (EC-090) : saisie à la réception, calculée par le mélange (la plus basse catégorie des entrées et des états du résultat, EC-120). La qualité par référentiel est dans app.lot_qualite."
  text statut "Statut : brouillon, en_attente, valide, rejete, annule, consomme, quarantaine, archive. Transitions contrôlées par app.tg_lot_controle."
  uuid compte_matiere_id FK "Compte de matière du lot (nature lot) : son solde est la quantité du lot."
  uuid mouvement_creation_id FK "Mouvement qui crée le lot (I4) : il crédite le compte du lot et n'est pas une contre-passation."
  timestamp_with_time_zone date_operation "Date de l'opération qui crée le lot, saisie sur le terrain."
  text motif_annulation "Motif de l'annulation ; renseigné si et seulement si le statut est annule."
  uuid annule_par FK "Utilisateur qui a annulé le lot."
  timestamp_with_time_zone date_annulation "Date de l'annulation."
  uuid cree_par FK "Utilisateur qui a créé le lot."
  timestamp_with_time_zone cree_le "Date d'enregistrement du lot."
  timestamp_with_time_zone modifie_le "Date de la dernière modification (statut ou numéro)."
}
"app.reception" {
  uuid id "Identifiant de la réception (UUID v7)."
  uuid organisation_id FK "Organisation propriétaire (isolation par ligne)."
  uuid campagne_id FK "Campagne de la réception."
  uuid produit_id FK "Produit reçu."
  uuid producteur_id FK "Producteur qui livre ; vide si la matière vient d'un fournisseur (l'un ou l'autre, jamais les deux)."
  uuid fournisseur_id FK "Fournisseur qui livre ; vide si la matière vient d'un producteur."
  uuid contrat_id FK "Contrat dont la formule de réfaction s'applique ; vide si aucun contrat (aucune réfaction)."
  uuid lot_id FK "Lot créé par la réception, avec son mouvement de création (I4). Un lot naît d'une seule réception."
  timestamp_with_time_zone date_operation "Date de la réception, saisie sur le terrain : c'est elle qui sert à apprécier l'état du certificat (RG-014)."
  text statut "Statut : en_attente, validee ou rejetee. Ne revient jamais en arrière ; une erreur se corrige par annulation (L2-6)."
  jsonb formule_refaction "Formule de réfaction retenue, copiée du contrat à l'enregistrement : c'est elle qui est imprimée sur le bon de réception (RG-171)."
  jsonb detail_calcul "Détail du calcul du poids net marchand (brut, tare, net, excédent, réfaction), figé tel qu'imprimé (RG-171)."
  bigint net_marchand_g "Poids net marchand en grammes : net de pesée moins la réfaction du contrat. Copie du détail pour les lectures."
  uuid ticket_fichier_id FK "Ticket de pesée conservé (RG-170), facultatif tant que le stockage objet n'est pas en place."
  text derogation_motif "Justification de la dérogation de la direction quand une règle bloque la réception (RG-014) ; vide sans dérogation."
  uuid derogation_par FK "Utilisateur de la direction qui a donné la dérogation."
  timestamp_with_time_zone derogation_le "Date de la dérogation."
  uuid decide_par FK "Utilisateur qui a validé ou rejeté la réception ; vide tant qu'elle est en attente."
  timestamp_with_time_zone decide_le "Date de la décision ; vide tant que la réception est en attente."
  uuid cree_par FK "Utilisateur qui a enregistré la réception."
  timestamp_with_time_zone cree_le "Date d'enregistrement de la réception."
  timestamp_with_time_zone modifie_le "Date de la dernière modification (décision ou dérogation)."
}
"app.sortie_etape" {
  uuid id "Identifiant stable (UUID v7)."
  uuid organisation_id FK "Organisation propriétaire (isolation par ligne)."
  uuid etape_realisee_id FK "Étape qui produit la sortie ; elle doit être en cours ou réalisée, pas encore validée."
  text nature "produit_principal (au plus un par étape), coproduit, sous_produit, rebut ou perte."
  uuid produit_id FK "Produit de la sortie."
  bigint quantite_g "Quantité en grammes, strictement positive."
  uuid lot_id FK "Lot créé par un mouvement de l'étape, pour la même quantité ; vide pour un rebut ou une perte, qui ne deviennent jamais un lot."
  text destination "Destination du rebut (obligatoire pour un rebut)."
  text motif "Motif de la perte déclarée (obligatoire pour une perte)."
  uuid cree_par FK "Utilisateur qui a déclaré la sortie."
  timestamp_with_time_zone cree_le "Date de la déclaration."
  boolean reintegre_flux_bio "Vrai si l'opérateur déclare que ce rebut réintègre un flux biologique (EC-120) ; réservé à la nature rebut. Lu par la variable etape.rebut_reintegre_flux_bio des normes."
  uuid mouvement_id FK "Mouvement de transformation qui a produit la sortie. Une sortie dont le mouvement est contre-passé (étape dévalidée) ne compte plus dans le bilan ; vide pour les sorties antérieures à L2-6 sans mouvement retrouvé."
}
"app.vente" {
  uuid id "Identifiant de la vente (UUID v7)."
  uuid organisation_id FK "Organisation propriétaire (isolation par ligne)."
  uuid client_id FK "Client acheteur."
  uuid contrat_id FK "Contrat de vente actif du même client, facultatif : vide pour une vente « spot ». Sa tolérance s'ajoute à la quantité engagée."
  uuid produit_id FK "Produit vendu : celui de tous les lots expédiés."
  text referentiel_code FK "Référentiel revendiqué sur la vente (RG-156, AV1-03) ; vide si la vente ne revendique aucun référentiel."
  bigint quantite_engagee_g "Quantité vendue en grammes. Le total expédié ne la dépasse pas, tolérance du contrat comprise."
  bigint prix_unite_mineure "Prix par unité de prix, en unités mineures de la devise."
  text unite_prix FK "Unité à laquelle le prix s'applique (kilogramme, tonne…)."
  text devise FK "Devise du prix."
  date date_operation "Date de la vente."
  text statut "Statut : brouillon, validee, soldee ou annulee. Une vente annulée ne peut plus avoir d'expédition validée."
  uuid valide_par FK "Utilisateur qui a validé la vente ; vide tant qu'elle est en brouillon."
  timestamp_with_time_zone valide_le "Date de validation de la vente."
  uuid cree_par FK "Utilisateur qui a saisi la vente."
  timestamp_with_time_zone cree_le "Date de saisie de la vente."
  timestamp_with_time_zone modifie_le "Date de la dernière modification de la vente."
}
"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.unite" {
  uuid id "Identifiant stable (UUID v7)."
  text code "Code de l'unité : g, kg, t."
  text libelle_fr "Libellé en français."
  text libelle_en "Libellé en anglais."
  bigint grammes_par_unite "Nombre de grammes dans une unité (entier) : kg 1 000, t 1 000 000."
}
"app.pack_version" {
  uuid id "Identifiant de la version (UUID v7)."
  uuid pack_id FK "Pack concerné."
  text version "Version sémantique (majeure.mineure.correctif)."
  jsonb contenu "Contenu du pack, en JSON."
  text sha256 "Empreinte SHA-256 du contenu."
  boolean calibre "Vrai si les rendements du pack ont été calibrés (EC-007)."
  text statut "Statut : brouillon, publie ou retire."
  timestamp_with_time_zone publie_le "Date de publication. Nulle pour un brouillon."
  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 publie_par "Identifiant Keycloak (sub) du membre de l'équipe de l'éditeur qui a publié la version depuis le cockpit. Nul pour les versions publiées par le pipeline ou la ligne de commande avant CP-5."
}

Generated by tbls