Lot 1, séquence A5 — Foncier
1er octobre 2026. Mise en œuvre de la séquence A5 du plan du Lot 1. Décisions : EC-048, EC-049 (amendé), EC-050, EC-069 (appliqué de la même façon).
- Un polygone invalide est conservé, signalé et jamais réparé : pas de
ST_MakeValid. Il n’a ni surface ni périmètre ; sa correction est un nouveau relevé. - La surface mesurée vient de la base (
ST_Areaen géographie). Le domaine la recalcule pour comparaison : elle concorde à 0,1 %. - La tolérance de chevauchement n’est dans aucune table : c’est un paramètre de
app.signaler_chevauchements(version, tolerance_m2). Sa valeur par défaut, 50 m², est arbitraire et destinée à devenir paramétrable (EC-049). - Aucune route REST en A5 : le contrat est gelé en A9, les écrans B3 demanderont leurs routes.
| Objet | Contenu |
|---|---|
app.parcelle |
organisation_id et groupement_id, producteur, produit, code unique, type_surface (cultures, serres, prairies), surface déclarée, facteurs region, mode_culture, type_sol facultatifs |
app.zone_cueillette |
Même mécanisme de polygone (EC-050) |
app.parcelle_version |
Ajout seul. Une cible exactement (parcelle ou zone), numéro de version, geom Polygon 4326, geojson tenu par la base, valide, motif_invalidite, surface et périmètre (vides si invalide), méthode (dont import), précision médiane, appareil, trace brute, incertitude_m2 calculée |
app.parcelle_version_en_vigueur |
Vue de la version la plus récente de chaque cible. security_invoker : elle applique la RLS de l’appelant |
sync.controle |
Nouvelle colonne parcelle_version_id |
Un producteur qui a des parcelles ne change pas de groupement : la parcelle porte groupement_id pour le téléphone, et la clé composée vers le producteur refuse le changement.
Règles tenues par la base
Section intitulée « Règles tenues par la base »- Validité : un déclencheur calcule
ST_IsValidet sa raison, mesure si valide, remplit le GeoJSON, attribue le numéro de version et reprend le groupement de la cible (cible inconnue : erreurP0002explicite). Un second déclencheur ouvre le contrôlepolygone_invalide. app.parcelle_version_a(parcelle, zone, date): la version applicable à une date passée.app.signaler_chevauchements(version, tolérance): compare à la version en vigueur des autres cibles de même nature (parcelles entre elles, zones entre elles), ignore les polygones invalides, mesure l’aire de l’intersection, ouvre un contrôlechevauchement_parcelleau-delà de la tolérance. Un bord partagé ne compte pas. Idempotente : un seul contrôle ouvert par version.app.parcelle_eligible_capacite(parcelle, zone): vrai si la version en vigueur est valide et sans chevauchement non levé (AV1-01). Le producteur en contrôle se juge à part (producteur_en_controle, A4). La capacité (A8) appelle les deux ; A5 ne bloque rien elle-même.
Services de l’API
Section intitulée « Services de l’API »importerPolygone(apps/api/src/foncier/polygones.service.ts) : valide la forme (GeoJSONPolygon, un anneau fermé), insère la version, appellesignaler_chevauchementsavec la tolérance reçue ou celle dePARAMETRES_FONCIER, rend validité, surface, incertitude et contrôles ouverts. Sur une erreur de cible, la transaction est à annuler.evaluerEcartDeLaParcelle: écart entre surface déclarée et mesurée, jugé parevaluerEcartSurfacecontre l’incertitude périmètre × précision (GPS-04). Un écart dans la marge n’est pas une anomalie.evaluerEligibiliteDuGroupement(A4) lit maintenant les surfaces mesurées : un producteur dont une parcelle n’a pas de polygone valide, ou qui n’en a aucune, a un critère « surface » inconnu. On ne conclut pas sur des surfaces incomplètes.
Défaut du jeu de démonstration, trouvé au chargement
Section intitulée « Défaut du jeu de démonstration, trouvé au chargement »Le générateur plaçait les 9 premières parcelles au même endroit (rayon nul pour l’anneau 0) : au chargement réel en base, 9 chevauchements s’ouvraient au lieu de 1. Corrigé dans generer.mjs (anneaux de 1/10 à 10/10 du rayon). Le jeu produit maintenant 1 polygone invalide et 1 chevauchement, et le chargement ne signale que les versions réellement insérées : le rejeu ne rouvre rien. Le commentaire « ~2 m de décalage » de la paire volontaire était aussi faux : 2 000 × 10⁻⁷ degré font environ 22 m.
| Test | Ce qu’il vérifie |
|---|---|
db/tests/l1-a5.sql |
Parcelles et clés, version valide et sa surface, ajout seul, une cible exactement, nœud papillon accepté mais invalide et sans surface, aucune réparation, correction par nouvelle version, lecture à une date passée, chevauchement au-dessus et en dessous de la tolérance, bord partagé, tolérance en paramètre, zones, cible inconnue, isolation |
apps/api/test/foncier.test.ts |
Surface PostGIS contre surfaceM2 à 0,1 % sur 5 polygones du jeu de démonstration, nœud papillon du jeu, correction, anneau non fermé, écart dans et hors incertitude, chevauchement avec deux tolérances, éligibilité sur surfaces mesurées, aucun appel à ST_MakeValid dans la migration |
packages/schemas/src/foncier.test.ts |
Forme du GeoJSON et de la parcelle |
Hors séance
Section intitulée « Hors séance »Routes REST du foncier et import GeoJSON du back-office (écrans B3) ; valeurs de region d’un pack ; capacité (A8) ; règles PowerSync des nouvelles tables (A9) ; trous dans un polygone (un seul anneau au Lot 1).