Aller au contenu

Lot 1 bis — Arbre d'activités du pack fruits

02/10/2026. Séquence L1-4 du plan d’alignement, d’après la note d’amendement (AM-04). Écarts ouverts : EC-108 (types provisoires, contenu de l’arbre), EC-109 (RG-300, aucun profil défini), EC-110 (ce que la note laisse ouvert).

  • Le type est fermé, l’instance est ouverte. Un nœud de l’arbre cite un type du catalogue app.activite ; il n’en crée jamais. Le pack fournit les instances (chemin, libellé, obligatoire, critique, sous-traitable, ordre).
  • L’arbre est copié dans l’organisation (app.noeud_activite) quand on charge le pack. L’état de chaque nœud (actif ou non) reste dans organisation_activite, en ajout seul, daté, motivé, par organisation et par site.
  • La base garde l’autorité sur les garde-fous ; le domaine (peutActiver, peutDesactiver) répond avant l’écriture, avec les mêmes codes.
  • Pas d’écran en L1-4 : l’écran « Activités » est livré en L1-5.

Migration db/migrations/20261003130000_lot1bis_arbre_activites.sql.

Objet Rôle
app.activite.provisoire Vrai pour les types des niveaux 2 et 3, posés avant la validation de Q1 (EC-108)
6 types provisoires pesee_collecte, stockage_frais, preparation_fruits, calibrage (niveau 3), emballage, chargement_conteneur
app.noeud_activite Nœuds de l’arbre d’une organisation, copiés du pack : chemin (pointé, trois niveaux au plus), activite_code (le type), libellés, obligatoire, critique (donc obligatoire), sous_traitable, ordre, pack_version_id. RLS par organisation
app.etat_noeud(org, site, noeud) État courant d’un nœud pour un site : la ligne du site, sinon celle de l’organisation ; désactivé si jamais déclaré
tg_organisation_activite_controle Remplace le contrôle de L0-2 (premier niveau seulement) : les refus ci-dessous
tg_organisation_activite_cascade Désactiver un nœud désactive ses descendants encore actifs, dans la même transaction, pour le même site
app.recette Gelée (commentaire de table) : aucun nouvel appelant, suppression au Lot 2

Même code dans la base (DETAIL), le domaine et l’API.

Refus Code HTTP
Nœud absent de l’arbre de l’organisation noeud_inconnu 404
Type différent de celui du nœud noeud_non_pris_en_charge base seulement
Changement sans effet (état vu du site) etat_inchange 409
Activer un nœud dont le parent est inactif parent_inactif 409
Désactiver un nœud obligatoire ou critique dont le parent est actif noeud_obligatoire_parent_actif 409
Arbre non chargé (ouverture du compte) arbre_non_charge 409

À la création d’un nœud, la base refuse un type qui n’a pas la profondeur du nœud (niveau_du_type), un premier niveau dont le chemin n’est pas son type (racine_differente_du_type) et un parent absent (parent_absent).

  • modules.arbreActif(arbre, historique, site, instant) : nœuds actifs d’un site, triés. Un nœud n’est actif que si lui et tous ses ancêtres le sont.
  • modules.peutDesactiver(arbre, actifs, chemin) : refuse selon le tableau ci-dessus ; rend les descendants actifs qui suivront (enfants).
  • modules.peutActiver(arbre, actifs, chemin).
  • packs.validerArbre(arbre, types) : appelée par validerPack ; raisons chemin_en_double, profondeur, type_inconnu, niveau_du_type, racine_differente_du_type, critique_facultatif, parent_absent. validerPack reçoit désormais les types du catalogue en troisième paramètre.

packs/fruits/1.1.0.json : la 1.0.0 plus la section facultative arbre (les packs publiés gardent leur empreinte). Dix nœuds pour l’ananas :

Premier niveau Niveau 2 Niveau 3
Collecte auprès des membres Pesée et reçu de collecte (obligatoire, critique)
Stockage Stockage de fruits frais (obligatoire)
Conditionnement et étiquetage Préparation des fruits (obligatoire) ; Emballage (facultatif, sous-traitable) Calibrage (obligatoire, critique)
Exportation Chargement du conteneur (obligatoire, critique)

Le caractère obligatoire, critique ou sous-traitable est une hypothèse de travail (EC-108). chargerPack copie les nœuds, parents d’abord ; un nœud déjà chargé n’est jamais réécrit.

Route Droit Rend
GET /v1/arbre-activites (site_id facultatif) membre actif Les nœuds, parents avant enfants, avec leur état et leur dernier changement. L’état d’un enfant tient compte de ses ancêtres
POST /v1/arbre-activites/initialiser modules.manage Ouverture du compte : active les nœuds choisis, ou tout l’arbre par défaut du pack (préréglage de RG-300, EC-109). Rejouable
POST /v1/arbre-activites/{chemin}/etat modules.manage Le nœud après le changement (etat, motif, site_id facultatif)

L’instant de référence de l’état est celui de la base, qui date les changements.

Le chargeur publie le pack 1.1.0, copie ses dix nœuds dans l’organisation d’ananas et active ceux des niveaux 2 et 3 (les quatre activités de premier niveau étaient déjà déclarées). Rejouable : le second passage ne change rien.

Test Ce qu’il vérifie
db/tests/l1bis-4.sql Types provisoires, contrôle des nœuds, parent d’abord, garde-fous, cascade sur trois niveaux, état par site, ajout seul, RLS
VT-MOD-200 à 206, 210 à 216, 220 à 223 arbreActif, peutDesactiver, peutActiver
VT-PACK-010 à 017 validerArbre
apps/api/test/arbre-activites.test.ts Publication, refus d’un arbre invalide, chargement rejouable, ordre de lecture, ouverture du compte, garde-fous, cascade, état par site, droit modules.manage, absence d’écart de portée causé par les nœuds de niveaux 2 et 3
db/tests/l0bis-2.sql Un nœud de niveau 2 hors de l’arbre est refusé par noeud_inconnu (avant : noeud_non_pris_en_charge)

Les nœuds de niveaux 2 et 3 entrent dans activite_en_vigueur. L’écart de portée (AM-07) ne compte désormais que les activités de premier niveau ; sans cela, « Calibrage » aurait été un écart contre tout certificat.

  • Fait en L1-5 : écran « Activités », menus, synchronisation filtrée par module (page).
  • Points de grille liés à un nœud désactivé : voir EC-110 (7).
  • Suppression de recette (Lot 2).