{
  "PROJECT_SUMMARY": {
    "title": "Base de Données Industriels — SRM-RSK",
    "scope": "Cartographie complète du tissu industriel de la région Rabat-Salé-Kénitra : identification, abonnements eau/assainissement, enquêtes, analyses physico-chimiques, conformité réglementaire, zones industrielles, réclamations/incidents, documents, nomenclatures et KPI.",
    "vision": "Centraliser l'information industrielle en temps réel, renforcer la conformité environnementale, piloter par indicateurs, protéger les ressources hydriques (Oued Sebou) et optimiser le suivi des redevances de déversement.",
    "anchor": "Le CODE_INDUSTRIEL est la clé métier unique qui relie les 12 onglets / domaines. Depuis la v2, il est numéroté par direction provinciale / préfectorale : IN + CODE_DP + '-' + NNNN, par exemple INDPK-0001 pour le 1er industriel de la Direction provinciale de Kénitra. L'ancien code IND-0001… est conservé dans ANCIEN_CODE. La présentation annonce 12 onglets thématiques ; le canevas CSV détaille 11 onglets opérationnels (01 à 11), le sommaire 00 étant une page APEX et non une table.",
    "code_format": "IN + CODE_DP + '-' + NNNN : IN = Industrie, CODE_DP = direction provinciale / préfectorale, NNNN = ordre d'enregistrement dans cette direction",
    "automation": "L'utilisateur ne saisit que les résultats bruts d'analyse. Le code industriel est généré automatiquement à partir de la direction ; conformité, vigilance, alertes, total métaux lourds, KPI, cartographie et audit sont dérivés par vues, colonnes virtuelles, triggers, materialized views et APEX Automations."
  },
  "OBJECTIVES": [
    [
      "Vision globale",
      "Cartographie complète du tissu industriel régional et fiche 360° par industriel."
    ],
    [
      "Accès rapide",
      "Information centralisée, recherche facettée et disponibilité en temps réel."
    ],
    [
      "Conformité",
      "Suivi rigoureux des valeurs limites du cahier des charges (Art. 42, 44, 45) et des dossiers réglementaires."
    ],
    [
      "Pilotage",
      "KPI calculés, tableaux de bord, alertes automatiques et reporting mensuel."
    ],
    [
      "Traçabilité",
      "Journal MAJ automatique, audit, gestion des accès et archivage documentaire."
    ],
    [
      "Protection",
      "Réduction de la pollution, protection de l'Oued Sebou et optimisation des redevances de déversement."
    ]
  ],
  "STAKEHOLDERS": [
    [
      "Chargé SIG / Service SIG",
      "Identification, zones industrielles, géolocalisation, cartographie",
      "SIG / Cartographie / Référentiels"
    ],
    [
      "Service Clientèle",
      "Abonnements, branchements, compteurs, consommations",
      "Abonnements / Relevés"
    ],
    [
      "Équipe Enquêtes Industrielles / Enquêteurs terrain",
      "Enquêtes et contrôles terrain, constats",
      "Enquêtes / Mobile"
    ],
    [
      "Laboratoire SRM-RSK",
      "Prélèvements et résultats physico-chimiques",
      "Saisie des résultats / Analyses"
    ],
    [
      "Cellule Environnement",
      "Conformité, EIE, MED, réclamations et incidents",
      "Conformité / Alertes"
    ],
    [
      "Division reporting / Direction & Pilotage",
      "KPI, tableaux de bord, décisions",
      "Dashboard / Reporting"
    ],
    [
      "Administrateur",
      "Nomenclatures, seuils, utilisateurs, journal",
      "Administration / Audit"
    ],
    [
      "Tous services",
      "Documents, photos, plans, rapports, archivage SharePoint",
      "Documents"
    ],
    [
      "Distributeur SRM-RSK / Industriels / Autorités",
      "Convention de déversement, contrôles Art. 48, obligations réglementaires",
      "Parties prenantes externes"
    ]
  ],
  "DIRECTIONS": [
    [
      "DPR",
      "Direction provinciale / préfectorale de Rabat",
      "Rabat",
      1,
      "INDPR-0001"
    ],
    [
      "DPS",
      "Direction provinciale / préfectorale de Salé",
      "Salé",
      2,
      "INDPS-0001"
    ],
    [
      "DPST",
      "Direction provinciale de Skhirat-Témara",
      "Skhirat-Témara",
      3,
      "INDPST-0001"
    ],
    [
      "DPK",
      "Direction provinciale de Kénitra",
      "Kénitra",
      4,
      "INDPK-0001"
    ],
    [
      "DPKH",
      "Direction provinciale de Khemisset",
      "Khemisset",
      5,
      "INDPKH-0001"
    ],
    [
      "DPSK",
      "Direction provinciale de Sidi Kacem",
      "Sidi Kacem",
      6,
      "INDPSK-0001"
    ],
    [
      "DPSS",
      "Direction provinciale de Sidi Slimane",
      "Sidi Slimane",
      7,
      "INDPSS-0001"
    ]
  ],
  "CANEVAS": [
    [
      "00",
      "00_Sommaire",
      "Navigation et vue d'ensemble",
      "Tous services",
      "Temps réel",
      "Aucune table — page APEX 0 / 1",
      "Cards + KPI + liste"
    ],
    [
      "01",
      "01_Identification_Industriel",
      "Fiche signalétique de chaque industriel de la région",
      "Chargé SIG / SRM-RSK",
      "À chaque nouvelle implantation",
      "DIRECTION, INDUSTRIEL, CONTACT_INDUSTRIEL, ZONE_INDUSTRIELLE, REF_PROVINCE, REF_SECTEUR_ACTIVITE",
      "Faceted Search + Select List direction + Form + Display Only code"
    ],
    [
      "02",
      "02_Abonnement_Eau_Assainissement",
      "Suivi des compteurs, raccordements et consommations",
      "Service Clientèle",
      "Mensuelle",
      "ABONNEMENT, BRANCHEMENT, COMPTEUR, RELEVE_COMPTEUR",
      "Interactive Grid + Chart"
    ],
    [
      "03",
      "03_Enquetes_Controles",
      "Historique des enquêtes terrain et contrôles",
      "Équipe Enquêtes Industrielles",
      "À chaque enquête",
      "ENQUETE_CONTROLE, CONSTAT_ENQUETE, REF_TYPE_VISITE",
      "Calendar + Master-Detail"
    ],
    [
      "04",
      "04_Analyses_Physico_Chimiques",
      "Résultats des analyses de rejets industriels",
      "Laboratoire SRM-RSK",
      "À chaque prélèvement",
      "PRELEVEMENT, RESULTAT_ANALYSE, REF_PARAMETRE, REF_SEUIL_REGLEMENTAIRE",
      "Interactive Grid + Dynamic Action"
    ],
    [
      "05",
      "05_Conformite_Reglementaire",
      "Autorisations, EIE, mises en demeure, certifications",
      "Cellule Environnement",
      "Trimestrielle",
      "DOSSIER_REGLEMENTAIRE, REF_TYPE_DOSSIER, DEROGATION_SEUIL",
      "Interactive Report + Approvals"
    ],
    [
      "06",
      "06_Indicateurs_KPI",
      "Tableau de bord des indicateurs de pilotage",
      "Division reporting",
      "Mensuelle",
      "Aucune table de saisie — V_KPI_GENERAL, V_KPI_MENSUEL, MV_KPI_MENSUEL",
      "Dashboard + JET Charts"
    ],
    [
      "07",
      "07_Zones_Industrielles",
      "Cartographie des zones industrielles",
      "Service SIG",
      "Annuelle",
      "ZONE_INDUSTRIELLE, REF_PROVINCE, SDO_GEOMETRY",
      "Map Region"
    ],
    [
      "08",
      "08_Reclamations_Incidents",
      "Suivi des réclamations et incidents environnementaux",
      "Cellule Environnement",
      "Continue",
      "RECLAMATION_INCIDENT, REF_TYPE_RECLAMATION",
      "Interactive Report + Workflow"
    ],
    [
      "09",
      "09_Documents_Photos",
      "Référentiel documentaire (photos, plans, rapports)",
      "Tous services",
      "Continue",
      "DOCUMENT",
      "Cards + BLOB download + REST SharePoint"
    ],
    [
      "10",
      "10_Nomenclatures",
      "Listes de référence pour standardisation des saisies",
      "Administrateur",
      "Annuelle",
      "DIRECTION, REF_LISTE, REF_VALEUR_LISTE, REF_UNITE, toutes REF_*",
      "Interactive Grid admin + LOV CODE_DP"
    ],
    [
      "11",
      "11_Journal_MAJ",
      "Traçabilité des modifications de la base",
      "Administrateur",
      "Automatique",
      "JOURNAL_MAJ",
      "Interactive Report read-only"
    ]
  ],
  "AUDIT_COLS": [
    "CREE_PAR|VARCHAR2(64 CHAR)|NOT NULL|Audit · APEX user / trigger",
    "CREE_LE|TIMESTAMP(6) WITH TIME ZONE|NOT NULL|Audit · DEFAULT SYSTIMESTAMP",
    "MODIFIE_PAR|VARCHAR2(64 CHAR)|NULL|Audit · trigger UPDATE",
    "MODIFIE_LE|TIMESTAMP(6) WITH TIME ZONE|NULL|Audit · trigger UPDATE",
    "DATE_ARCHIVAGE|DATE|NULL|Soft delete · exclure des vues actives"
  ],
  "SCHEMA_TABLES": [
    {
      "n": "REF_PROVINCE",
      "d": "Référentiel géographique",
      "p": "Provinces / préfectures de la région Rabat-Salé-Kénitra.",
      "pk": "PROVINCE_ID",
      "fk": "—",
      "c": [
        "PROVINCE_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "CODE_PROVINCE|VARCHAR2(10 CHAR)|NOT NULL|UK",
        "LIBELLE|VARCHAR2(100 CHAR)|NOT NULL|—",
        "REGION|VARCHAR2(100 CHAR)|NOT NULL|DEFAULT 'Rabat-Salé-Kénitra'",
        "ACTIF|CHAR(1)|NOT NULL|CHECK IN ('O','N')"
      ]
    },
    {
      "n": "DIRECTION",
      "d": "Onglet 01 / 10 · Codification",
      "p": "Directions provinciales / préfectorales. Porte le compteur atomique DERNIER_ORDRE utilisé par le trigger de génération du CODE_INDUSTRIEL.",
      "pk": "CODE_DP",
      "fk": "PROVINCE_ID → REF_PROVINCE",
      "c": [
        "CODE_DP|VARCHAR2(10 CHAR)|NOT NULL|PK · CHECK REGEXP '^DP[A-Z]+$'",
        "LIBELLE|VARCHAR2(150 CHAR)|NOT NULL|—",
        "PROVINCE_ID|NUMBER(10)|NOT NULL|FK → REF_PROVINCE",
        "ORDRE_AFFICHAGE|NUMBER(3)|NOT NULL|UK · CHECK > 0",
        "DERNIER_ORDRE|NUMBER(6) DEFAULT 0|NOT NULL|Compteur du dernier NNNN attribué dans la direction",
        "UNIQUE (ORDRE_AFFICHAGE)|—|—|UK",
        "CHECK (DERNIER_ORDRE >= 0)|—|—|Cohérence du compteur"
      ]
    },
    {
      "n": "ZONE_INDUSTRIELLE",
      "d": "Onglet 07 · SIG",
      "p": "Zones industrielles et emprise géographique.",
      "pk": "ZONE_ID",
      "fk": "PROVINCE_ID → REF_PROVINCE",
      "c": [
        "ZONE_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "CODE_ZONE|VARCHAR2(30 CHAR)|NOT NULL|UK",
        "LIBELLE|VARCHAR2(150 CHAR)|NOT NULL|—",
        "PROVINCE_ID|NUMBER(10)|NOT NULL|FK → REF_PROVINCE",
        "LATITUDE|NUMBER(9,6)|NULL|CHECK BETWEEN -90 AND 90",
        "LONGITUDE|NUMBER(9,6)|NULL|CHECK BETWEEN -180 AND 180",
        "GEOMETRIE|SDO_GEOMETRY|NULL|Oracle Spatial / Map Region",
        "SUPERFICIE_HA|NUMBER(10,2)|NULL|CHECK >= 0"
      ]
    },
    {
      "n": "REF_SECTEUR_ACTIVITE",
      "d": "Nomenclature",
      "p": "Secteurs d'activité normalisés.",
      "pk": "SECTEUR_ID",
      "fk": "—",
      "c": [
        "SECTEUR_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "CODE_SECTEUR|VARCHAR2(30 CHAR)|NOT NULL|UK",
        "LIBELLE|VARCHAR2(150 CHAR)|NOT NULL|—",
        "CODE_NAF|VARCHAR2(20 CHAR)|NULL|Référentiel externe",
        "ACTIF|CHAR(1)|NOT NULL|CHECK IN ('O','N')"
      ]
    },
    {
      "n": "REF_LISTE",
      "d": "Onglet 10 · Nomenclatures",
      "p": "Registre des listes de référence génériques.",
      "pk": "CODE_LISTE",
      "fk": "—",
      "c": [
        "CODE_LISTE|VARCHAR2(40 CHAR)|NOT NULL|PK",
        "LIBELLE|VARCHAR2(150 CHAR)|NOT NULL|—",
        "DESCRIPTION|VARCHAR2(4000 CHAR)|NULL|—",
        "MODIFIABLE|CHAR(1)|NOT NULL|CHECK IN ('O','N')"
      ]
    },
    {
      "n": "REF_VALEUR_LISTE",
      "d": "Onglet 10 · Nomenclatures",
      "p": "Valeurs normalisées des petites listes (statuts, gravités, fréquences, types).",
      "pk": "(CODE_LISTE, CODE_VALEUR)",
      "fk": "CODE_LISTE → REF_LISTE",
      "c": [
        "CODE_LISTE|VARCHAR2(40 CHAR)|NOT NULL|PK, FK → REF_LISTE",
        "CODE_VALEUR|VARCHAR2(40 CHAR)|NOT NULL|PK",
        "LIBELLE|VARCHAR2(150 CHAR)|NOT NULL|—",
        "ORDRE_AFFICHAGE|NUMBER(5)|NOT NULL|CHECK >= 0",
        "ACTIF|CHAR(1)|NOT NULL|CHECK IN ('O','N')",
        "VALEUR_NUM|NUMBER(12,3)|NULL|Seuil / pondération éventuelle"
      ]
    },
    {
      "n": "INDUSTRIEL",
      "d": "Onglet 01 · Cœur du modèle",
      "p": "Fiche signalétique. CODE_INDUSTRIEL est généré par DIRECTION_ID + ORDRE_DP ; ANCIEN_CODE conserve la clé historique IND-0001… pour la reprise.",
      "pk": "INDUSTRIEL_ID",
      "fk": "ZONE_ID, PROVINCE_ID, SECTEUR_ID, DIRECTION_ID → DIRECTION",
      "c": [
        "INDUSTRIEL_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "CODE_INDUSTRIEL|VARCHAR2(20 CHAR)|NOT NULL|UK · généré · CHECK REGEXP '^INDP[A-Z]*-[0-9]{4,}$'",
        "ANCIEN_CODE|VARCHAR2(20 CHAR)|NULL|UK · code IND-0001… conservé pour traçabilité",
        "DIRECTION_ID|VARCHAR2(10 CHAR)|NOT NULL|FK → DIRECTION(CODE_DP)",
        "CODE_DP|VARCHAR2(10 CHAR)|NOT NULL|CHECK CODE_DP = DIRECTION_ID · alias pour exports/API",
        "ORDRE_DP|NUMBER(6)|NOT NULL|CHECK > 0 · ordre dans la direction",
        "UNIQUE (DIRECTION_ID, ORDRE_DP)|—|—|UK composite",
        "CHECK CODE_INDUSTRIEL = 'IN'||DIRECTION_ID||'-'||LPAD(ORDRE_DP,4,'0')|—|—|Cohérence code / direction",
        "RAISON_SOCIALE|VARCHAR2(200 CHAR)|NOT NULL|—",
        "ICE|CHAR(15)|NULL|UK · CHECK REGEXP '^[0-9]{15}$'",
        "RC|VARCHAR2(30 CHAR)|NULL|Registre de commerce",
        "SECTEUR_ID|NUMBER(10)|NOT NULL|FK → REF_SECTEUR_ACTIVITE",
        "ZONE_ID|NUMBER(10)|NULL|FK → ZONE_INDUSTRIELLE",
        "PROVINCE_ID|NUMBER(10)|NOT NULL|FK → REF_PROVINCE",
        "STATUT|VARCHAR2(30 CHAR)|NOT NULL|FK logique → REF_VALEUR_LISTE('STATUT_INDUSTRIEL')",
        "GPS_LAT|NUMBER(9,6)|NULL|CHECK BETWEEN -90 AND 90",
        "GPS_LON|NUMBER(9,6)|NULL|CHECK BETWEEN -180 AND 180",
        "EFFECTIF|NUMBER(8)|NULL|CHECK >= 0",
        "SURFACE_M2|NUMBER(12,2)|NULL|CHECK >= 0",
        "CAPACITE_PRODUCTION|VARCHAR2(200 CHAR)|NULL|—",
        "REGIME_TRAVAIL|VARCHAR2(50 CHAR)|NULL|—",
        "DATE_IMPLANTATION|DATE|NULL|—",
        "INTERLOCUTEUR_PRINCIPAL|VARCHAR2(150 CHAR)|NULL|Redondance évitée via CONTACT_INDUSTRIEL"
      ]
    },
    {
      "n": "CONTACT_INDUSTRIEL",
      "d": "Onglet 01 · 3NF",
      "p": "Contacts multiples par industriel, sans colonnes répétées.",
      "pk": "CONTACT_ID",
      "fk": "INDUSTRIEL_ID → INDUSTRIEL",
      "c": [
        "CONTACT_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "INDUSTRIEL_ID|NUMBER(10)|NOT NULL|FK → INDUSTRIEL ON DELETE CASCADE",
        "TYPE_CONTACT|VARCHAR2(30 CHAR)|NOT NULL|FK logique → REF_VALEUR_LISTE",
        "NOM|VARCHAR2(120 CHAR)|NOT NULL|—",
        "FONCTION|VARCHAR2(100 CHAR)|NULL|—",
        "TELEPHONE|VARCHAR2(30 CHAR)|NULL|—",
        "EMAIL|VARCHAR2(150 CHAR)|NULL|CHECK REGEXP simplified",
        "PRINCIPAL|CHAR(1)|NOT NULL|CHECK IN ('O','N') · index unique conditionnel"
      ]
    },
    {
      "n": "REF_TYPE_BRANCHEMENT",
      "d": "Art. 47 · Nomenclature",
      "p": "Branchements distincts : eaux usées domestiques, eaux pluviales, eaux industrielles.",
      "pk": "TYPE_BRANCHEMENT_ID",
      "fk": "—",
      "c": [
        "TYPE_BRANCHEMENT_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "CODE_TYPE|VARCHAR2(30 CHAR)|NOT NULL|UK",
        "LIBELLE|VARCHAR2(120 CHAR)|NOT NULL|—"
      ]
    },
    {
      "n": "BRANCHEMENT",
      "d": "Onglet 02 / Art. 47",
      "p": "Raccordement physique par industriel et par type.",
      "pk": "BRANCHEMENT_ID",
      "fk": "INDUSTRIEL_ID, TYPE_BRANCHEMENT_ID",
      "c": [
        "BRANCHEMENT_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "INDUSTRIEL_ID|NUMBER(10)|NOT NULL|FK → INDUSTRIEL",
        "TYPE_BRANCHEMENT_ID|NUMBER(10)|NOT NULL|FK → REF_TYPE_BRANCHEMENT",
        "REFERENCE_BRANCHEMENT|VARCHAR2(50 CHAR)|NOT NULL|UK",
        "DATE_MISE_EN_SERVICE|DATE|NULL|—",
        "ETAT|VARCHAR2(30 CHAR)|NOT NULL|—",
        "REGARD_ACCES|VARCHAR2(100 CHAR)|NULL|Art. 47 · regard accessible",
        "UNIQUE (INDUSTRIEL_ID, TYPE_BRANCHEMENT_ID, DATE_MISE_EN_SERVICE)|—|—|UK composite"
      ]
    },
    {
      "n": "ABONNEMENT",
      "d": "Onglet 02",
      "p": "Contrat d'eau / assainissement et convention spéciale de déversement.",
      "pk": "ABONNEMENT_ID",
      "fk": "INDUSTRIEL_ID",
      "c": [
        "ABONNEMENT_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "INDUSTRIEL_ID|NUMBER(10)|NOT NULL|FK → INDUSTRIEL",
        "NUMERO_ABONNEMENT|VARCHAR2(40 CHAR)|NOT NULL|UK",
        "TYPE_ABONNEMENT|VARCHAR2(30 CHAR)|NOT NULL|EAU / ASSAINISSEMENT / DEVERSEMENT",
        "DATE_DEBUT|DATE|NOT NULL|—",
        "DATE_FIN|DATE|NULL|CHECK DATE_FIN >= DATE_DEBUT",
        "CONVENTION_DEVERSEMENT|VARCHAR2(80 CHAR)|NULL|Art. 46 / 48",
        "STATUT|VARCHAR2(30 CHAR)|NOT NULL|—"
      ]
    },
    {
      "n": "COMPTEUR",
      "d": "Onglet 02",
      "p": "Compteur rattaché à un abonnement ou à un branchement.",
      "pk": "COMPTEUR_ID",
      "fk": "ABONNEMENT_ID, BRANCHEMENT_ID",
      "c": [
        "COMPTEUR_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "NUMERO_COMPTEUR|VARCHAR2(50 CHAR)|NOT NULL|UK",
        "ABONNEMENT_ID|NUMBER(10)|NULL|FK → ABONNEMENT",
        "BRANCHEMENT_ID|NUMBER(10)|NULL|FK → BRANCHEMENT",
        "TYPE_COMPTEUR|VARCHAR2(30 CHAR)|NOT NULL|—",
        "UNITE|VARCHAR2(20 CHAR)|NOT NULL|DEFAULT 'm3'",
        "DATE_POSE|DATE|NULL|—",
        "CHECK (ABONNEMENT_ID IS NOT NULL OR BRANCHEMENT_ID IS NOT NULL)|—|—|Au moins un rattachement"
      ]
    },
    {
      "n": "RELEVE_COMPTEUR",
      "d": "Onglet 02 · KPI consommation",
      "p": "Relevés mensuels ; source de 'Conso totale 2025 = 4,2 M m³'.",
      "pk": "RELEVE_ID",
      "fk": "COMPTEUR_ID",
      "c": [
        "RELEVE_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "COMPTEUR_ID|NUMBER(10)|NOT NULL|FK → COMPTEUR",
        "DATE_RELEVE|DATE|NOT NULL|—",
        "INDEX_RELEVE|NUMBER(14,2)|NOT NULL|CHECK >= 0 · trigger croissance",
        "VOLUME_M3|NUMBER(14,2)|NOT NULL|CHECK >= 0 · index courant − index précédent",
        "SOURCE_RELEVE|VARCHAR2(40 CHAR)|NOT NULL|TERRAIN / TELEMESURE / FACTURATION",
        "UNIQUE (COMPTEUR_ID, DATE_RELEVE)|—|—|UK"
      ]
    },
    {
      "n": "REF_TYPE_VISITE",
      "d": "Onglet 03 · Nomenclature",
      "p": "Types d'enquêtes et contrôles.",
      "pk": "TYPE_VISITE_ID",
      "fk": "—",
      "c": [
        "TYPE_VISITE_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "CODE_TYPE|VARCHAR2(30 CHAR)|NOT NULL|UK",
        "LIBELLE|VARCHAR2(120 CHAR)|NOT NULL|—"
      ]
    },
    {
      "n": "ENQUETE_CONTROLE",
      "d": "Onglet 03 / Art. 48",
      "p": "Visites terrain et contrôles inopinés ; source du taux de couverture enquêtes.",
      "pk": "ENQUETE_ID",
      "fk": "INDUSTRIEL_ID, TYPE_VISITE_ID, AGENT_ID",
      "c": [
        "ENQUETE_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "INDUSTRIEL_ID|NUMBER(10)|NOT NULL|FK → INDUSTRIEL",
        "TYPE_VISITE_ID|NUMBER(10)|NOT NULL|FK → REF_TYPE_VISITE",
        "DATE_VISITE|DATE|NOT NULL|—",
        "AGENT_ID|NUMBER(10)|NULL|FK → APP_UTILISATEUR",
        "STATUT|VARCHAR2(30 CHAR)|NOT NULL|PLANIFIEE / REALISEE / REPORTEE",
        "OBSERVATIONS|CLOB|NULL|—",
        "UNIQUE (INDUSTRIEL_ID, DATE_VISITE, TYPE_VISITE_ID)|—|—|UK"
      ]
    },
    {
      "n": "CONSTAT_ENQUETE",
      "d": "Onglet 03 · 3NF",
      "p": "Lignes de constat et actions de suivi, sans colonnes répétées.",
      "pk": "CONSTAT_ID",
      "fk": "ENQUETE_ID",
      "c": [
        "CONSTAT_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "ENQUETE_ID|NUMBER(10)|NOT NULL|FK → ENQUETE_CONTROLE ON DELETE CASCADE",
        "LIBELLE|VARCHAR2(200 CHAR)|NOT NULL|—",
        "GRAVITE|VARCHAR2(30 CHAR)|NOT NULL|FK logique → REF_VALEUR_LISTE",
        "ACTION_REQUISE|VARCHAR2(4000 CHAR)|NULL|—",
        "ECHEANCE|DATE|NULL|—",
        "STATUT_ACTION|VARCHAR2(30 CHAR)|NOT NULL|—"
      ]
    },
    {
      "n": "REF_UNITE",
      "d": "Onglet 10",
      "p": "Unités de mesure normalisées.",
      "pk": "UNITE_ID",
      "fk": "—",
      "c": [
        "UNITE_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "CODE_UNITE|VARCHAR2(20 CHAR)|NOT NULL|UK",
        "LIBELLE|VARCHAR2(80 CHAR)|NOT NULL|mg/L, °C, µS/cm, 0/1…"
      ]
    },
    {
      "n": "REF_PARAMETRE",
      "d": "Onglets 04 / 10",
      "p": "Dictionnaire des paramètres analysés. Une ligne par paramètre, jamais une colonne par polluant.",
      "pk": "PARAMETRE_ID",
      "fk": "UNITE_ID",
      "c": [
        "PARAMETRE_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "CODE_PARAMETRE|VARCHAR2(40 CHAR)|NOT NULL|UK · PH, MES, DCO, DBO5, CR6…",
        "LIBELLE|VARCHAR2(200 CHAR)|NOT NULL|—",
        "UNITE_ID|NUMBER(10)|NOT NULL|FK → REF_UNITE",
        "FAMILLE|VARCHAR2(60 CHAR)|NOT NULL|Admissibilité / Métaux / Composés / Qualitatif",
        "TYPE_VALEUR|VARCHAR2(20 CHAR)|NOT NULL|NUMERIQUE / BOOLEEN / TEXTE",
        "MIN_PHYSIQUE|NUMBER(12,4)|NULL|Validation de vraisemblance",
        "MAX_PHYSIQUE|NUMBER(12,4)|NULL|Validation de vraisemblance",
        "EST_DERIVE|CHAR(1)|NOT NULL|CHECK IN ('O','N') · TOTAL_METAUX",
        "ACTIF|CHAR(1)|NOT NULL|CHECK IN ('O','N')"
      ]
    },
    {
      "n": "REF_SEUIL_REGLEMENTAIRE",
      "d": "Art. 42 / 44 · Versioning",
      "p": "Valeurs limites datées et portées. Source unique de la conformité ; aucune limite en dur dans APEX.",
      "pk": "SEUIL_ID",
      "fk": "PARAMETRE_ID, SECTEUR_ID, INDUSTRIEL_ID",
      "c": [
        "SEUIL_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "PARAMETRE_ID|NUMBER(10)|NOT NULL|FK → REF_PARAMETRE",
        "SEUIL_MIN|NUMBER(14,4)|NULL|pH 5,5 · booléen 1",
        "SEUIL_MAX|NUMBER(14,4)|NULL|MES 500 · DCO 1000 · Cr6+ 0,1",
        "DATE_EFFET|DATE|NOT NULL|—",
        "DATE_FIN|DATE|NULL|CHECK DATE_FIN >= DATE_EFFET",
        "PORTEE|VARCHAR2(20 CHAR)|NOT NULL|TOUS / SECTEUR / INDUSTRIEL",
        "SECTEUR_ID|NUMBER(10)|NULL|FK → REF_SECTEUR_ACTIVITE",
        "INDUSTRIEL_ID|NUMBER(10)|NULL|FK → INDUSTRIEL",
        "ARTICLE|VARCHAR2(30 CHAR)|NOT NULL|Art. 42 / 44 / 45",
        "REFERENCE_TEXTE|VARCHAR2(200 CHAR)|NOT NULL|Cahier des charges",
        "ACTIF|CHAR(1)|NOT NULL|CHECK IN ('O','N')",
        "UNIQUE (PARAMETRE_ID, PORTEE, DATE_EFFET, SECTEUR_ID, INDUSTRIEL_ID)|—|—|UK + trigger anti-chevauchement"
      ]
    },
    {
      "n": "DEROGATION_SEUIL",
      "d": "Art. 42 · Exception chaux",
      "p": "Dérogation pH 5,5–9,5 lorsque la neutralisation est faite à la chaux. Validée, datée et auditée.",
      "pk": "DEROGATION_ID",
      "fk": "INDUSTRIEL_ID, PARAMETRE_ID, SEUIL_ID",
      "c": [
        "DEROGATION_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "INDUSTRIEL_ID|NUMBER(10)|NOT NULL|FK → INDUSTRIEL",
        "PARAMETRE_ID|NUMBER(10)|NOT NULL|FK → REF_PARAMETRE",
        "SEUIL_MIN_DEROG|NUMBER(14,4)|NULL|5,5",
        "SEUIL_MAX_DEROG|NUMBER(14,4)|NULL|9,5",
        "DATE_DEBUT|DATE|NOT NULL|—",
        "DATE_FIN|DATE|NOT NULL|CHECK DATE_FIN >= DATE_DEBUT",
        "MOTIF|VARCHAR2(4000 CHAR)|NOT NULL|—",
        "APPROUVE_PAR|VARCHAR2(64 CHAR)|NOT NULL|—",
        "STATUT|VARCHAR2(20 CHAR)|NOT NULL|PROPOSEE / VALIDEE / REJETEE / EXPIREE"
      ]
    },
    {
      "n": "PRELEVEMENT",
      "d": "Onglet 04 · Échantillon",
      "p": "Prélèvement / échantillon parent. Le détail des mesures est dans RESULTAT_ANALYSE.",
      "pk": "PRELEVEMENT_ID",
      "fk": "INDUSTRIEL_ID, ENQUETE_ID",
      "c": [
        "PRELEVEMENT_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "INDUSTRIEL_ID|NUMBER(10)|NOT NULL|FK → INDUSTRIEL",
        "NUMERO_ECHANTILLON|VARCHAR2(60 CHAR)|NOT NULL|UK",
        "DATE_PRELEVEMENT|TIMESTAMP(6)|NOT NULL|Index DESC",
        "POINT_PRELEVEMENT|VARCHAR2(120 CHAR)|NOT NULL|—",
        "TYPE_PRELEVEMENT|VARCHAR2(40 CHAR)|NOT NULL|REJET / DOMESTIQUE / PLUVIAL / INOPINE",
        "LABORATOIRE|VARCHAR2(120 CHAR)|NOT NULL|—",
        "ENQUETE_ID|NUMBER(10)|NULL|FK → ENQUETE_CONTROLE",
        "TEMPERATURE_AMBIANTE|NUMBER(6,2)|NULL|Contexte",
        "COMMENTAIRE|CLOB|NULL|—",
        "STATUT_PRELEVEMENT|VARCHAR2(20 CHAR) · VUE (non stockée)|CALCULÉ|Dérivé de V_PRELEVEMENT_CONFORMITE"
      ]
    },
    {
      "n": "RESULTAT_ANALYSE",
      "d": "Onglet 04 · Saisie unique",
      "p": "UNE ligne = UN paramètre = UNE valeur mesurée. Aucun champ de conformité saisi.",
      "pk": "RESULTAT_ID",
      "fk": "PRELEVEMENT_ID, PARAMETRE_ID",
      "c": [
        "RESULTAT_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "PRELEVEMENT_ID|NUMBER(10)|NOT NULL|FK → PRELEVEMENT ON DELETE CASCADE",
        "PARAMETRE_ID|NUMBER(10)|NOT NULL|FK → REF_PARAMETRE",
        "VALEUR_NUM|NUMBER(14,4)|NULL|CHECK vraisemblance par paramètre",
        "VALEUR_TEXTE|VARCHAR2(200 CHAR)|NULL|Pour contrôles qualitatifs futurs",
        "VALEUR_BOOL|CHAR(1)|NULL|CHECK IN ('O','N') ou 0/1",
        "LIMITE_DETECTION|NUMBER(14,4)|NULL|—",
        "METHODE_ANALYSE|VARCHAR2(100 CHAR)|NULL|—",
        "SAISI_PAR|VARCHAR2(64 CHAR)|NOT NULL|Audit",
        "DATE_SAISIE|TIMESTAMP(6) WITH TIME ZONE|NOT NULL|DEFAULT SYSTIMESTAMP",
        "STATUT_RESULTAT|VARCHAR2(20 CHAR) · VUE (non stockée)|CALCULÉ|CONFORME / NON_CONFORME",
        "UNIQUE (PRELEVEMENT_ID, PARAMETRE_ID)|—|—|UK · un résultat par paramètre"
      ]
    },
    {
      "n": "REF_TYPE_DOSSIER",
      "d": "Onglet 05 · Nomenclature",
      "p": "EIE, autorisation, MED, certification, convention.",
      "pk": "TYPE_DOSSIER_ID",
      "fk": "—",
      "c": [
        "TYPE_DOSSIER_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "CODE_TYPE|VARCHAR2(30 CHAR)|NOT NULL|UK",
        "LIBELLE|VARCHAR2(120 CHAR)|NOT NULL|—",
        "RENOUVELABLE|CHAR(1)|NOT NULL|CHECK IN ('O','N')"
      ]
    },
    {
      "n": "DOSSIER_REGLEMENTAIRE",
      "d": "Onglet 05 · MED / EIE",
      "p": "Dossiers, mises en demeure et certifications ; source du KPI 'MED actives'.",
      "pk": "DOSSIER_ID",
      "fk": "INDUSTRIEL_ID, TYPE_DOSSIER_ID",
      "c": [
        "DOSSIER_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "INDUSTRIEL_ID|NUMBER(10)|NOT NULL|FK → INDUSTRIEL",
        "TYPE_DOSSIER_ID|NUMBER(10)|NOT NULL|FK → REF_TYPE_DOSSIER",
        "NUMERO_DOSSIER|VARCHAR2(80 CHAR)|NOT NULL|—",
        "AUTORITE|VARCHAR2(150 CHAR)|NULL|—",
        "DATE_DEBUT|DATE|NOT NULL|—",
        "DATE_ECHEANCE|DATE|NULL|CHECK DATE_ECHEANCE >= DATE_DEBUT",
        "STATUT|VARCHAR2(30 CHAR)|NOT NULL|ACTIVE / VALIDEE / CLOTUREE / EXPIREE",
        "OBJET|VARCHAR2(4000 CHAR)|NULL|—",
        "UNIQUE (TYPE_DOSSIER_ID, NUMERO_DOSSIER)|—|—|UK"
      ]
    },
    {
      "n": "REF_TYPE_RECLAMATION",
      "d": "Onglet 08 · Nomenclature",
      "p": "Réclamation / incident / nuisance / déversement.",
      "pk": "TYPE_RECLAMATION_ID",
      "fk": "—",
      "c": [
        "TYPE_RECLAMATION_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "CODE_TYPE|VARCHAR2(30 CHAR)|NOT NULL|UK",
        "LIBELLE|VARCHAR2(120 CHAR)|NOT NULL|—"
      ]
    },
    {
      "n": "RECLAMATION_INCIDENT",
      "d": "Onglet 08",
      "p": "Source du délai moyen de traitement (6,2 j dans la présentation).",
      "pk": "RECLAMATION_ID",
      "fk": "INDUSTRIEL_ID, TYPE_RECLAMATION_ID",
      "c": [
        "RECLAMATION_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "INDUSTRIEL_ID|NUMBER(10)|NULL|FK → INDUSTRIEL",
        "TYPE_RECLAMATION_ID|NUMBER(10)|NOT NULL|FK → REF_TYPE_RECLAMATION",
        "DATE_OUVERTURE|TIMESTAMP(6)|NOT NULL|—",
        "DATE_CLOTURE|TIMESTAMP(6)|NULL|CHECK DATE_CLOTURE >= DATE_OUVERTURE",
        "STATUT|VARCHAR2(30 CHAR)|NOT NULL|—",
        "GRAVITE|VARCHAR2(30 CHAR)|NOT NULL|FK logique → REF_VALEUR_LISTE",
        "OBJET|VARCHAR2(4000 CHAR)|NOT NULL|—",
        "DELAI_TRAITEMENT_J|NUMBER(8,2) GENERATED ALWAYS AS (...)|VIRTUEL|(DATE_CLOTURE − DATE_OUVERTURE)"
      ]
    },
    {
      "n": "DOCUMENT",
      "d": "Onglet 09",
      "p": "Référentiel documentaire ; BLOB ou lien SharePoint/ORDS.",
      "pk": "DOCUMENT_ID",
      "fk": "INDUSTRIEL_ID + contexte",
      "c": [
        "DOCUMENT_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "INDUSTRIEL_ID|NUMBER(10)|NOT NULL|FK → INDUSTRIEL",
        "CONTEXTE|VARCHAR2(30 CHAR)|NOT NULL|CHECK IN (INDUSTRIEL, PRELEVEMENT, ENQUETE, RECLAMATION, DOSSIER)",
        "SOURCE_ID|NUMBER(10)|NOT NULL|Identifiant du parent selon CONTEXTE",
        "TYPE_DOCUMENT|VARCHAR2(60 CHAR)|NOT NULL|PHOTO / PLAN / RAPPORT / MED",
        "NOM_FICHIER|VARCHAR2(255 CHAR)|NOT NULL|—",
        "MIME_TYPE|VARCHAR2(100 CHAR)|NULL|—",
        "CONTENU_BLOB|BLOB|NULL|OU URL_SHAREPOINT",
        "URL_SHAREPOINT|VARCHAR2(500 CHAR)|NULL|—",
        "DATE_DOCUMENT|DATE|NOT NULL|—",
        "CHECK (CONTENU_BLOB IS NOT NULL OR URL_SHAREPOINT IS NOT NULL)|—|—|Au moins un stockage"
      ]
    },
    {
      "n": "ALERTE_NON_CONFORMITE",
      "d": "Générée par trigger",
      "p": "Alerte de dépassement créée automatiquement ; jamais saisie par l'utilisateur.",
      "pk": "ALERTE_ID",
      "fk": "RESULTAT_ID, INDUSTRIEL_ID, PRELEVEMENT_ID",
      "c": [
        "ALERTE_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "RESULTAT_ID|NUMBER(10)|NOT NULL|FK → RESULTAT_ANALYSE",
        "PRELEVEMENT_ID|NUMBER(10)|NOT NULL|FK → PRELEVEMENT",
        "INDUSTRIEL_ID|NUMBER(10)|NOT NULL|FK → INDUSTRIEL",
        "PARAMETRE_ID|NUMBER(10)|NOT NULL|FK → REF_PARAMETRE",
        "VALEUR_MESUREE|NUMBER(14,4)|NOT NULL|—",
        "SEUIL_APPLIQUE|NUMBER(14,4)|NOT NULL|—",
        "DEPASSEMENT_PCT|NUMBER(10,2)|NOT NULL|CHECK >= 0",
        "DATE_ALERTE|TIMESTAMP(6) WITH TIME ZONE|NOT NULL|DEFAULT SYSTIMESTAMP",
        "GRAVITE|VARCHAR2(20 CHAR)|NOT NULL|Calculée selon l'écart",
        "STATUT|VARCHAR2(20 CHAR)|NOT NULL|NOUVELLE / NOTIFIEE / TRAITEE / CLOTUREE",
        "NOTIFIE_LE|TIMESTAMP(6) WITH TIME ZONE|NULL|APEX Automation / email"
      ]
    },
    {
      "n": "JOURNAL_MAJ",
      "d": "Onglet 11 · Append-only",
      "p": "Traçabilité automatique de toutes les écritures. Interdiction UPDATE/DELETE par trigger.",
      "pk": "JOURNAL_ID",
      "fk": "—",
      "c": [
        "JOURNAL_ID|NUMBER(18) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "DATE_ACTION|TIMESTAMP(6) WITH TIME ZONE|NOT NULL|DEFAULT SYSTIMESTAMP",
        "UTILISATEUR|VARCHAR2(64 CHAR)|NOT NULL|—",
        "ACTION|VARCHAR2(40 CHAR)|NOT NULL|INSERT / UPDATE / DELETE / IMPORT",
        "ENTITE|VARCHAR2(60 CHAR)|NOT NULL|Nom de table",
        "IDENTIFIANT_LIGNE|VARCHAR2(80 CHAR)|NULL|—",
        "DETAIL|CLOB|NULL|Anciennes / nouvelles valeurs"
      ]
    },
    {
      "n": "APP_ROLE",
      "d": "Sécurité APEX",
      "p": "Rôles fonctionnels et authorization schemes.",
      "pk": "ROLE_ID",
      "fk": "—",
      "c": [
        "ROLE_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "CODE_ROLE|VARCHAR2(40 CHAR)|NOT NULL|UK · LABO / ENV / SIG / CLIENTELE / REPORTING / ADMIN",
        "LIBELLE|VARCHAR2(120 CHAR)|NOT NULL|—"
      ]
    },
    {
      "n": "APP_UTILISATEUR",
      "d": "Sécurité APEX",
      "p": "Utilisateurs applicatifs (ou mapping SSO / APEX accounts).",
      "pk": "UTILISATEUR_ID",
      "fk": "—",
      "c": [
        "UTILISATEUR_ID|NUMBER(10) GENERATED BY DEFAULT AS IDENTITY|NOT NULL|PK",
        "USERNAME|VARCHAR2(100 CHAR)|NOT NULL|UK",
        "NOM_COMPLET|VARCHAR2(150 CHAR)|NOT NULL|—",
        "EMAIL|VARCHAR2(150 CHAR)|NULL|—",
        "ACTIF|CHAR(1)|NOT NULL|CHECK IN ('O','N')"
      ]
    },
    {
      "n": "AFFECTATION_ROLE",
      "d": "Sécurité APEX",
      "p": "Association many-to-many utilisateur ↔ rôle.",
      "pk": "(UTILISATEUR_ID, ROLE_ID)",
      "fk": "UTILISATEUR_ID, ROLE_ID",
      "c": [
        "UTILISATEUR_ID|NUMBER(10)|NOT NULL|PK, FK → APP_UTILISATEUR",
        "ROLE_ID|NUMBER(10)|NOT NULL|PK, FK → APP_ROLE",
        "DATE_DEBUT|DATE|NOT NULL|—",
        "DATE_FIN|DATE|NULL|CHECK DATE_FIN >= DATE_DEBUT"
      ]
    }
  ],
  "CONSTRAINTS": [
    [
      "Identité",
      "CODE_INDUSTRIEL NOT NULL, UNIQUE, généré : ^INDP[A-Z]*-[0-9]{4,}$",
      "TRG_INDUSTRIEL_CODE + UK + CHECK REGEXP_LIKE",
      "Clé métier reliant les 12 onglets"
    ],
    [
      "Numérotation",
      "CODE_INDUSTRIEL = 'IN'||DIRECTION_ID||'-'||LPAD(ORDRE_DP,4,'0') ; UNIQUE(DIRECTION_ID, ORDRE_DP)",
      "Trigger + CHECK + UK composite",
      "Ordre séquentiel propre à chaque direction"
    ],
    [
      "Numérotation",
      "DIRECTION.DERNIER_ORDRE verrouillé par SELECT … FOR UPDATE avant attribution",
      "Package SRM_PKG_CONFORMITE.RESERVER_ORDRE_DIRECTION",
      "Aucun doublon même en saisie concurrente"
    ],
    [
      "Traçabilité",
      "ANCIEN_CODE UNIQUE ; correspondance IND-0001 → INDPK-0001 conservée",
      "UK + migration v2 + acceptation à l'import",
      "Reprise historique sans rupture des faits liés"
    ],
    [
      "Identité",
      "RAISON_SOCIALE, PROVINCE_ID, SECTEUR_ID, DIRECTION_ID, STATUT NOT NULL",
      "NOT NULL + FK",
      "Fiche signalétique exploitable"
    ],
    [
      "Identité",
      "ICE : exactement 15 chiffres, UNIQUE ; RC contrôlé",
      "CHECK REGEXP_LIKE + UK",
      "Fiabilité de l'identifiant entreprise"
    ],
    [
      "Géographie",
      "GPS_LAT BETWEEN -90 AND 90 ; GPS_LON BETWEEN -180 AND 180",
      "CHECK + validation APEX",
      "Cohérence cartographique"
    ],
    [
      "Prélèvement",
      "NUMERO_ECHANTILLON UNIQUE ; DATE_PRELEVEMENT NOT NULL ; pas de date future",
      "UK + NOT NULL + CHECK/trigger",
      "Un échantillon = une référence"
    ],
    [
      "Résultat",
      "UNIQUE (PRELEVEMENT_ID, PARAMETRE_ID)",
      "UK composite",
      "Interdit les doublons de paramètre"
    ],
    [
      "Résultat",
      "VALEUR_NUM non négative sauf T° ; pH 0–14 ; T° -10–100 ; booléens 0/1",
      "Trigger de validation paramétré par REF_PARAMETRE",
      "Vraisemblance physique avant conformité"
    ],
    [
      "Résultat",
      "Aucun champ STATUT_CONFORMITE / KPI saisi",
      "Colonnes virtuelles + vues + triggers",
      "Une seule source de vérité"
    ],
    [
      "Seuils",
      "SEUIL_MIN <= SEUIL_MAX ; au moins l'un des deux non NULL",
      "CHECK",
      "Règle légale cohérente"
    ],
    [
      "Seuils",
      "Périodes d'effet sans chevauchement pour un même paramètre/portée",
      "UK + trigger anti-chevauchement",
      "Versioning réglementaire"
    ],
    [
      "Seuils",
      "Dérogation pH 5,5–9,5 uniquement si STATUT='VALIDEE' et dates valides",
      "CHECK + workflow APEX Approvals",
      "Exception Art. 42 tracée"
    ],
    [
      "Conformité",
      "Seuil applicable = dérogation > industriel > secteur > global, à la date du prélèvement",
      "PL/SQL SRM_PKG_CONFORMITE + V_RESULTAT_CONFORMITE",
      "Auditabilité dans le temps"
    ],
    [
      "Conformité",
      "TOTAL_METAUX = somme(Cd, Cu, Zn, Cr, Ni, Fe) ≤ 15 mg/L ; non saisissable",
      "Vue / virtual column / trigger",
      "Art. 44 calculé automatiquement"
    ],
    [
      "Conformité",
      "Contrôles qualitatifs Art. 42/45 : 0 = absent/conforme, 1 = présence interdite",
      "CHECK + paramètre BOOLÉEN",
      "Déversements interdits"
    ],
    [
      "Alertes",
      "Tout résultat NON_CONFORME crée exactement une ALERTE_NON_CONFORMITE",
      "AFTER INSERT/UPDATE trigger",
      "Alerte automatique et notification"
    ],
    [
      "Abonnement",
      "DATE_FIN >= DATE_DEBUT ; index compteur non décroissant ; VOLUME_M3 >= 0",
      "CHECK + trigger",
      "Fiabilité consommation / redevance"
    ],
    [
      "Enquêtes",
      "UNIQUE (INDUSTRIEL_ID, DATE_VISITE, TYPE_VISITE_ID) ; STATUT normalisé",
      "UK + FK logique",
      "Taux de couverture exact"
    ],
    [
      "Dossiers",
      "UNIQUE (TYPE_DOSSIER_ID, NUMERO_DOSSIER) ; DATE_ECHEANCE >= DATE_DEBUT",
      "UK + CHECK",
      "KPI MED actives fiable"
    ],
    [
      "Réclamations",
      "DATE_CLOTURE >= DATE_OUVERTURE ; délai calculé",
      "CHECK + colonne virtuelle",
      "KPI délai moyen"
    ],
    [
      "Documents",
      "Exactement un contexte parent + BLOB ou URL SharePoint",
      "CHECK + validation APEX",
      "Pas de référentiel orphelin"
    ],
    [
      "Audit",
      "JOURNAL_MAJ append-only ; CREE_PAR/CREE_LE NOT NULL sur tables métier",
      "Triggers + default SYSTIMESTAMP",
      "Traçabilité complète"
    ],
    [
      "Cycle de vie",
      "Soft delete via DATE_ARCHIVAGE ; FK restrict sur référentiels",
      "FK + vues filtrées",
      "Pas de perte d'historique"
    ],
    [
      "Sécurité",
      "Authorization schemes par rôle ; seuils modifiables uniquement par ADMIN",
      "APEX Authorization Scheme + VPD optionnel",
      "Séparation des responsabilités"
    ]
  ],
  "APEX_COMPONENTS": [
    [
      "Page 1 · Pilotage",
      "Dashboard + Cards + JET Charts + Map Region",
      "KPI calculés par V_KPI_GENERAL, alertes, conformité, consommation, cartographie"
    ],
    [
      "Saisie résultats",
      "Master-Detail Form + Interactive Grid sur RESULTAT_ANALYSE",
      "Saisie unique des valeurs ; Dynamic Action recalcule statut et total métaux en temps réel"
    ],
    [
      "Import laboratoire",
      "Data Load / RESTful ORDS / APEX_DATA_PARSER",
      "Intégration CSV ou instrument LIMS sans ressaisie"
    ],
    [
      "Création industriel",
      "Select List (DIRECTION / province) + Display Only + Dynamic Action",
      "La province déduit CODE_DP ; le code INDPK-0007 est calculé, jamais saisi"
    ],
    [
      "Répertoire industriels",
      "Faceted Search + Cards / Interactive Report",
      "Filtres direction CODE_DP, province, secteur, zone, statut, conformité, GPS ; colonne ANCIEN_CODE"
    ],
    [
      "Fiche 360°",
      "Master-Detail (Form + tabs + related reports)",
      "Identification, direction et code généré, abonnements, enquêtes, analyses, dossiers, documents"
    ],
    [
      "Analyses & conformité",
      "Interactive Report + Drill-down + Highlight rules",
      "Rouge = dépassement, orange = vigilance, vert = conforme"
    ],
    [
      "Alertes",
      "Interactive Report + APEX Automations + Email",
      "Notification Cellule Environnement, workflow de traitement"
    ],
    [
      "Enquêtes terrain",
      "Calendar + Mobile Form + Master-Detail",
      "Planification, saisie terrain, constats, photos"
    ],
    [
      "Abonnements / consommation",
      "Interactive Grid + Charts",
      "Relevés mensuels, contrôle de croissance, conso annuelle"
    ],
    [
      "Dossiers / MED",
      "Interactive Report + Form + Approvals",
      "Workflow de validation, échéances, KPI MED actives"
    ],
    [
      "Réclamations / incidents",
      "Interactive Report + Workflow / Task List",
      "Délai moyen, gravité, clôture"
    ],
    [
      "Cartographie SIG",
      "Map Region (SDO_GEOMETRY / GeoJSON)",
      "Points colorés par dernier statut, couches zones industrielles"
    ],
    [
      "Documents",
      "Cards + Report with BLOB download + REST SharePoint",
      "Photos, plans, rapports, archivage"
    ],
    [
      "Référentiels & seuils",
      "Interactive Grid admin + Approval + LOV",
      "Versioning des seuils, dérogations, nomenclatures"
    ],
    [
      "Reporting",
      "Interactive Report / Pivot / PDF / Excel + Materialized View",
      "Export mensuel, snapshot KPI, distribution direction"
    ],
    [
      "Journal MAJ",
      "Interactive Report read-only",
      "Audit append-only, aucune modification possible depuis l'UI"
    ]
  ],
  "NAVIGATION": [
    [
      "1",
      "Pilotage",
      "Tableau de bord",
      "Cards, JET Charts, Map, alertes",
      "Direction, Reporting, Environnement"
    ],
    [
      "2",
      "Exploitation",
      "Saisie des résultats",
      "Master-Detail + Interactive Grid",
      "Laboratoire SRM-RSK"
    ],
    [
      "3",
      "Exploitation",
      "Import / LIMS",
      "Data Load, ORDS REST",
      "Laboratoire, Administrateur"
    ],
    [
      "4",
      "Exploitation",
      "Analyses & conformité",
      "Interactive Report + drill-down",
      "Laboratoire, Environnement"
    ],
    [
      "5",
      "Référentiel",
      "Industriels (Faceted Search)",
      "Faceted Search + Cards + Form + LOV DIRECTION",
      "SIG, Clientèle, tous services"
    ],
    [
      "6",
      "Référentiel",
      "Fiche industriel 360°",
      "Master-Detail onglets",
      "Tous services"
    ],
    [
      "7",
      "Exploitation",
      "Enquêtes & contrôles",
      "Calendar + Mobile Form",
      "Équipe Enquêtes"
    ],
    [
      "8",
      "Exploitation",
      "Abonnements & compteurs",
      "Interactive Grid + Charts",
      "Service Clientèle"
    ],
    [
      "9",
      "Conformité",
      "Dossiers, EIE & MED",
      "IR + Approvals",
      "Cellule Environnement"
    ],
    [
      "10",
      "Conformité",
      "Alertes de dépassement",
      "IR + Automations + email",
      "Cellule Environnement"
    ],
    [
      "11",
      "Conformité",
      "Réclamations & incidents",
      "IR + workflow",
      "Cellule Environnement"
    ],
    [
      "12",
      "SIG",
      "Cartographie des zones",
      "Map Region",
      "Service SIG, Direction"
    ],
    [
      "13",
      "Documents",
      "Documents / photos / plans",
      "Cards + BLOB + SharePoint",
      "Tous services"
    ],
    [
      "14",
      "Reporting",
      "KPI & exports",
      "IR / Pivot / PDF / Excel",
      "Division reporting"
    ],
    [
      "15",
      "Administration",
      "Référentiels & valeurs limites",
      "IG + Approvals",
      "Administrateur"
    ],
    [
      "16",
      "Administration",
      "Utilisateurs & rôles",
      "IG + Authorization Schemes",
      "Administrateur"
    ],
    [
      "17",
      "Administration",
      "Journal MAJ / audit",
      "IR read-only",
      "Administrateur, Auditeur"
    ],
    [
      "99",
      "Global",
      "Page 0 · LOV, items, sécurité",
      "Shared components",
      "Tous"
    ]
  ],
  "AUTO_RULES": [
    [
      "Code industriel",
      "À la création d'une fiche, la direction provinciale / préfectorale détermine CODE_DP ; le trigger réserve ORDRE_DP et compose IN + CODE_DP + '-' + NNNN. Aucun code n'est saisi."
    ],
    [
      "Résultat saisi",
      "Une seule valeur brute est enregistrée dans RESULTAT_ANALYSE avec horodatage et utilisateur."
    ],
    [
      "Seuil applicable",
      "Le moteur choisit la règle valide à la date du prélèvement : dérogation, industriel, secteur, puis règle générale."
    ],
    [
      "Conformité",
      "V_RESULTAT_CONFORMITE puis V_PRELEVEMENT_CONFORMITE calculent CONFORME / NON_CONFORME ; aucun statut n'est saisi."
    ],
    [
      "Vigilance",
      "Un résultat légalement conforme mais à moins de 10 % d'un seuil de plage, ou ≥ 80 % d'un seuil maximal, est marqué À SURVEILLER."
    ],
    [
      "Total métaux lourds",
      "Cd + Cu + Zn + Cr + Ni + Fe est sommé automatiquement puis comparé à 15 mg/L (Art. 44)."
    ],
    [
      "Alerte",
      "Un trigger crée ALERTE_NON_CONFORMITE avec écart en %, gravité et référence article ; APEX Automation notifie par email."
    ],
    [
      "KPI",
      "V_KPI_GENERAL et MV_KPI_MENSUEL recalculent 247 industriels, 78 % conformité, 92 % couverture, 14 MED, 4,2 M m³, 6,2 j à partir des faits."
    ],
    [
      "Cartographie",
      "Le dernier statut de chaque industriel colore la Map Region sans mise à jour manuelle."
    ],
    [
      "Audit",
      "JOURNAL_MAJ est alimenté par triggers : INSERT/UPDATE/DELETE, import, changement de seuil et dérogation."
    ],
    [
      "Référentiels",
      "Toute nouvelle valeur limite crée une version datée ; les anciens prélèvements restent évalués avec le seuil de leur époque."
    ]
  ]
}