# SRM-RSK — Base de Données Industriels

**Architecture relationnelle 3NF, automatisation de la conformité et recommandations Oracle APEX**  
*Document généré le 03 novembre 2026 — Senior Database Architect / Oracle APEX Expert*

---

## 0. Documents analysés et livrables

### Sources
- `Visualisation_Base_Donnees_Industriels_SRM-RSK.pdf` — 10 pages, juin 2026
- `Base_Donnees_Industriels_SRM-RSK-03-11-2026.csv` — 11 onglets opérationnels
- `valeurs limites du cahier des charges d'assainissement liquide de la SRM-RSK.pdf` — pages 15–16, Articles 42 à 48

### Livrables associés

| Fichier | Rôle |
| --- | --- |
| `SRM_RSK_Dashboard.html` | Dashboard autonome : saisie des résultats, KPI, conformité, alertes, cartographie, architecture intégrée |
| `SRM_RSK_Architecture_APEX.md` | Le présent document : synthèse, schéma complet, contraintes, APEX, navigation |
| `schema_oracle.sql` | DDL Oracle : 32 tables dont DIRECTION, référentiels, vues, package PL/SQL, triggers, matérialisation KPI |
| `dashboard/app.py` | Serveur de démonstration + API JSON + base SQLite normalisée (prototype du schéma Oracle) |
| `dashboard/seed_data.json` | Jeu de démonstration déterministe + valeurs limites réglementaires |
| `livrables.html` | Page d'index accessible en ligne : tous les livrables en un clic |
| `README.md` | Guide d'utilisation, numérotation et déploiement |

### Accès en ligne (aperçu live Arena)

| Ressource | Lien public |
| --- | --- |
| Miroir statique public (sans jeton) | https://dffi0o2hbh.brewpage.app/ |
| Dashboard interactif | https://8000-ips0uqxecikoswqhoil78.e2b.app/ |
| Index de tous les livrables | https://8000-ips0uqxecikoswqhoil78.e2b.app/livrables.html |
| Architecture APEX (Markdown) | https://8000-ips0uqxecikoswqhoil78.e2b.app/SRM_RSK_Architecture_APEX.md |
| DDL Oracle (SQL) | https://8000-ips0uqxecikoswqhoil78.e2b.app/schema_oracle.sql |
| README | https://8000-ips0uqxecikoswqhoil78.e2b.app/README.md |
| Santé de l'API | https://8000-ips0uqxecikoswqhoil78.e2b.app/api/health |

> **Portée des liens :** le miroir statique `https://dffi0o2hbh.brewpage.app/` est publié sans jeton et reste en ligne jusqu'au 03 décembre 2026 ; il sert le dashboard en mode navigateur et tous les documents. L'aperçu `https://8000-ips0uqxecikoswqhoil78.e2b.app` expose en plus l'API SQLite interactive, mais seulement **tant que le processus du sandbox est actif**. Aucun des deux n'est un hébergement permanent : une disponibilité durable nécessite un hébergeur statique et un backend Oracle + ORDS / APEX.

> **Exigence centrale :** *« je ne dois saisir que le résultat trouvé des industriels, le reste doit être systématisé »*. Aucun champ de conformité, d'alerte, de KPI ou de total métaux n'est proposé à la saisie. Tout est dérivé.

## 1. Synthèse projet & objectifs

**Base de Données Industriels — SRM-RSK** — 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.

**Ancrage du modèle :** 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.

**Automatisation :** 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.

### Objectifs

| Objectif | Description |
| --- | --- |
| 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. |

### Périmètre fonctionnel — 12 onglets de la présentation / 11 onglets du canevas

| N° | Onglet | Objectif | Responsable | Fréquence MAJ | Tables cibles | Composant APEX |
| --- | --- | --- | --- | --- | --- | --- |
| 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 |

### Parties prenantes

| Acteur | Périmètre | Espace APEX |
| --- | --- | --- |
| 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 |

## 2. Modèle de données & schéma relationnel (3NF)

### 2.1 Principes d'architecture

- **Clé d'ancrage :** `CODE_INDUSTRIEL` est généré par direction : `IN + CODE_DP + '-' + NNNN` (ex. `INDPK-0001`). `ANCIEN_CODE` conserve `IND-0001…`. Il relie identification, eau, enquêtes, analyses, conformité, zones, réclamations et documents.
- **Direction référentielle :** la table `DIRECTION` porte les 7 codes `CODE_DP`, la province et le compteur `DERNIER_ORDRE` ; le trigger `TRG_INDUSTRIEL_CODE` réserve l'ordre et compose le code sans saisie.
- **Pas de table large d'analyses :** `pH`, `MES`, `DCO`, `DBO5`, métaux… sont des **lignes** dans `RESULTAT_ANALYSE`, pas des colonnes. Ajouter un polluant = ajouter une ligne de référentiel, jamais modifier le schéma.
- **Seuils versionnés :** `REF_SEUIL_REGLEMENTAIRE` porte `DATE_EFFET`, `DATE_FIN`, `PORTEE`, article et texte de référence. Les anciens prélèvements restent évalués avec le seuil de leur époque.
- **Aucune redondance dérivée :** conformité, vigilance, alertes, total métaux, KPI et statut cartographique sont calculés par vues, colonnes virtuelles, triggers et *materialized views*.
- **Référentiels dédiés + listes génériques :** `REF_LISTE` / `REF_VALEUR_LISTE` pour les petites nomenclatures ; tables `REF_*` dédiées pour les domaines à FK fortes.
- **Audit standard :** `CREE_PAR`, `CREE_LE`, `MODIFIE_PAR`, `MODIFIE_LE`, `DATE_ARCHIVAGE` sur toutes les tables métier ; `JOURNAL_MAJ` append-only.
- **Soft delete :** `DATE_ARCHIVAGE` plutôt que DELETE physique ; FK restrict sur les référentiels.

### 2.2 Vue d'ensemble des relations

```mermaid
erDiagram
  REF_PROVINCE ||--o{ ZONE_INDUSTRIELLE : contient
  REF_PROVINCE ||--o{ DIRECTION : porte
  DIRECTION ||--o{ INDUSTRIEL : numerote
  REF_PROVINCE ||--o{ INDUSTRIEL : situe
  REF_SECTEUR_ACTIVITE ||--o{ INDUSTRIEL : classifie
  ZONE_INDUSTRIELLE ||--o{ INDUSTRIEL : accueille
  INDUSTRIEL ||--o{ CONTACT_INDUSTRIEL : possede
  INDUSTRIEL ||--o{ ABONNEMENT : souscrit
  ABONNEMENT ||--o{ COMPTEUR : equipe
  COMPTEUR ||--o{ RELEVE_COMPTEUR : releve
  INDUSTRIEL ||--o{ BRANCHEMENT : raccorde
  INDUSTRIEL ||--o{ ENQUETE_CONTROLE : visite
  ENQUETE_CONTROLE ||--o{ CONSTAT_ENQUETE : constate
  INDUSTRIEL ||--o{ PRELEVEMENT : echantillonne
  PRELEVEMENT ||--o{ RESULTAT_ANALYSE : mesure
  REF_PARAMETRE ||--o{ RESULTAT_ANALYSE : definit
  REF_PARAMETRE ||--o{ REF_SEUIL_REGLEMENTAIRE : limite
  INDUSTRIEL ||--o{ DEROGATION_SEUIL : deroge
  RESULTAT_ANALYSE ||--o| ALERTE_NON_CONFORMITE : declenche
  INDUSTRIEL ||--o{ DOSSIER_REGLEMENTAIRE : concerne
  INDUSTRIEL ||--o{ RECLAMATION_INCIDENT : signale
  INDUSTRIEL ||--o{ DOCUMENT : archive
  APP_UTILISATEUR ||--o{ AFFECTATION_ROLE : affecte
  APP_ROLE ||--o{ AFFECTATION_ROLE : accorde
```

### 2.2.1 Convention de numérotation par direction provinciale / préfectorale

**Format :** `IN + CODE_DP + '-' + NNNN : IN = Industrie, CODE_DP = direction provinciale / préfectorale, NNNN = ordre d'enregistrement dans cette direction`. `IN` = Industrie ; `CODE_DP` identifie la direction ; `NNNN` est l'ordre d'enregistrement **dans cette direction**, remis à 1 pour chaque direction. Le code est calculé par `TRG_INDUSTRIEL_CODE`, jamais saisi.

| Ordre | CODE_DP | Direction provinciale / préfectorale | Province / Préfecture | Exemple |
| --- | --- | --- | --- | --- |
| 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 |

> **Migration et traçabilité :** la colonne `ANCIEN_CODE` conserve l'identifiant historique `IND-0001…` ; les prélèvements, documents et journaux déjà liés ne sont pas recréés. L'import CSV accepte le nouveau code et l'ancien code. Exemple : `IND-0001` → `INDPK-0001`, `IND-0002` → `INDPK-0002`.

### 2.3 Inventaire des 32 tables

| Table | Domaine | PK | FK |
| --- | --- | --- | --- |
| REF_PROVINCE | Référentiel géographique | PROVINCE_ID | — |
| DIRECTION | Onglet 01 / 10 · Codification | CODE_DP | PROVINCE_ID → REF_PROVINCE |
| ZONE_INDUSTRIELLE | Onglet 07 · SIG | ZONE_ID | PROVINCE_ID → REF_PROVINCE |
| REF_SECTEUR_ACTIVITE | Nomenclature | SECTEUR_ID | — |
| REF_LISTE | Onglet 10 · Nomenclatures | CODE_LISTE | — |
| REF_VALEUR_LISTE | Onglet 10 · Nomenclatures | (CODE_LISTE, CODE_VALEUR) | CODE_LISTE → REF_LISTE |
| INDUSTRIEL | Onglet 01 · Cœur du modèle | INDUSTRIEL_ID | ZONE_ID, PROVINCE_ID, SECTEUR_ID, DIRECTION_ID → DIRECTION |
| CONTACT_INDUSTRIEL | Onglet 01 · 3NF | CONTACT_ID | INDUSTRIEL_ID → INDUSTRIEL |
| REF_TYPE_BRANCHEMENT | Art. 47 · Nomenclature | TYPE_BRANCHEMENT_ID | — |
| BRANCHEMENT | Onglet 02 / Art. 47 | BRANCHEMENT_ID | INDUSTRIEL_ID, TYPE_BRANCHEMENT_ID |
| ABONNEMENT | Onglet 02 | ABONNEMENT_ID | INDUSTRIEL_ID |
| COMPTEUR | Onglet 02 | COMPTEUR_ID | ABONNEMENT_ID, BRANCHEMENT_ID |
| RELEVE_COMPTEUR | Onglet 02 · KPI consommation | RELEVE_ID | COMPTEUR_ID |
| REF_TYPE_VISITE | Onglet 03 · Nomenclature | TYPE_VISITE_ID | — |
| ENQUETE_CONTROLE | Onglet 03 / Art. 48 | ENQUETE_ID | INDUSTRIEL_ID, TYPE_VISITE_ID, AGENT_ID |
| CONSTAT_ENQUETE | Onglet 03 · 3NF | CONSTAT_ID | ENQUETE_ID |
| REF_UNITE | Onglet 10 | UNITE_ID | — |
| REF_PARAMETRE | Onglets 04 / 10 | PARAMETRE_ID | UNITE_ID |
| REF_SEUIL_REGLEMENTAIRE | Art. 42 / 44 · Versioning | SEUIL_ID | PARAMETRE_ID, SECTEUR_ID, INDUSTRIEL_ID |
| DEROGATION_SEUIL | Art. 42 · Exception chaux | DEROGATION_ID | INDUSTRIEL_ID, PARAMETRE_ID, SEUIL_ID |
| PRELEVEMENT | Onglet 04 · Échantillon | PRELEVEMENT_ID | INDUSTRIEL_ID, ENQUETE_ID |
| RESULTAT_ANALYSE | Onglet 04 · Saisie unique | RESULTAT_ID | PRELEVEMENT_ID, PARAMETRE_ID |
| REF_TYPE_DOSSIER | Onglet 05 · Nomenclature | TYPE_DOSSIER_ID | — |
| DOSSIER_REGLEMENTAIRE | Onglet 05 · MED / EIE | DOSSIER_ID | INDUSTRIEL_ID, TYPE_DOSSIER_ID |
| REF_TYPE_RECLAMATION | Onglet 08 · Nomenclature | TYPE_RECLAMATION_ID | — |
| RECLAMATION_INCIDENT | Onglet 08 | RECLAMATION_ID | INDUSTRIEL_ID, TYPE_RECLAMATION_ID |
| DOCUMENT | Onglet 09 | DOCUMENT_ID | INDUSTRIEL_ID + contexte |
| ALERTE_NON_CONFORMITE | Générée par trigger | ALERTE_ID | RESULTAT_ID, INDUSTRIEL_ID, PRELEVEMENT_ID |
| JOURNAL_MAJ | Onglet 11 · Append-only | JOURNAL_ID | — |
| APP_ROLE | Sécurité APEX | ROLE_ID | — |
| APP_UTILISATEUR | Sécurité APEX | UTILISATEUR_ID | — |
| AFFECTATION_ROLE | Sécurité APEX | (UTILISATEUR_ID, ROLE_ID) | UTILISATEUR_ID, ROLE_ID |

### 2.4 Dictionnaire de données détaillé

> Les cinq colonnes d'audit standard sont répétées dans chaque table ci-dessous. Les types sont optimisés pour Oracle : `NUMBER` identité, `VARCHAR2(... CHAR)` pour les accents, `TIMESTAMP(6) WITH TIME ZONE`, `NUMBER(14,4)` pour les mesures, `CLOB`/`BLOB`, `SDO_GEOMETRY` optionnel pour la Map Region.

#### 2.4.1 `REF_PROVINCE` — Référentiel géographique

**Rôle :** Provinces / préfectures de la région Rabat-Salé-Kénitra.  
**PK :** `PROVINCE_ID`  
**FK :** —

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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') |
| `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 |

#### 2.4.2 `DIRECTION` — Onglet 01 / 10 · Codification

**Rôle :** 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

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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 |
| `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 |

#### 2.4.3 `ZONE_INDUSTRIELLE` — Onglet 07 · SIG

**Rôle :** Zones industrielles et emprise géographique.  
**PK :** `ZONE_ID`  
**FK :** PROVINCE_ID → REF_PROVINCE

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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 |
| `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 |

#### 2.4.4 `REF_SECTEUR_ACTIVITE` — Nomenclature

**Rôle :** Secteurs d'activité normalisés.  
**PK :** `SECTEUR_ID`  
**FK :** —

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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') |
| `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 |

#### 2.4.5 `REF_LISTE` — Onglet 10 · Nomenclatures

**Rôle :** Registre des listes de référence génériques.  
**PK :** `CODE_LISTE`  
**FK :** —

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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') |
| `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 |

#### 2.4.6 `REF_VALEUR_LISTE` — Onglet 10 · Nomenclatures

**Rôle :** Valeurs normalisées des petites listes (statuts, gravités, fréquences, types).  
**PK :** `(CODE_LISTE, CODE_VALEUR)`  
**FK :** CODE_LISTE → REF_LISTE

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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 |
| `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 |

#### 2.4.7 `INDUSTRIEL` — Onglet 01 · Cœur du modèle

**Rôle :** 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

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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 |
| `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 |

#### 2.4.8 `CONTACT_INDUSTRIEL` — Onglet 01 · 3NF

**Rôle :** Contacts multiples par industriel, sans colonnes répétées.  
**PK :** `CONTACT_ID`  
**FK :** INDUSTRIEL_ID → INDUSTRIEL

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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 |
| `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 |

#### 2.4.9 `REF_TYPE_BRANCHEMENT` — Art. 47 · Nomenclature

**Rôle :** Branchements distincts : eaux usées domestiques, eaux pluviales, eaux industrielles.  
**PK :** `TYPE_BRANCHEMENT_ID`  
**FK :** —

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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 | — |
| `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 |

#### 2.4.10 `BRANCHEMENT` — Onglet 02 / Art. 47

**Rôle :** Raccordement physique par industriel et par type.  
**PK :** `BRANCHEMENT_ID`  
**FK :** INDUSTRIEL_ID, TYPE_BRANCHEMENT_ID

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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 |
| `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 |

#### 2.4.11 `ABONNEMENT` — Onglet 02

**Rôle :** Contrat d'eau / assainissement et convention spéciale de déversement.  
**PK :** `ABONNEMENT_ID`  
**FK :** INDUSTRIEL_ID

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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 | — |
| `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 |

#### 2.4.12 `COMPTEUR` — Onglet 02

**Rôle :** Compteur rattaché à un abonnement ou à un branchement.  
**PK :** `COMPTEUR_ID`  
**FK :** ABONNEMENT_ID, BRANCHEMENT_ID

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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 |
| `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 |

#### 2.4.13 `RELEVE_COMPTEUR` — Onglet 02 · KPI consommation

**Rôle :** Relevés mensuels ; source de 'Conso totale 2025 = 4,2 M m³'.  
**PK :** `RELEVE_ID`  
**FK :** COMPTEUR_ID

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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 |
| `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 |

#### 2.4.14 `REF_TYPE_VISITE` — Onglet 03 · Nomenclature

**Rôle :** Types d'enquêtes et contrôles.  
**PK :** `TYPE_VISITE_ID`  
**FK :** —

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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 | — |
| `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 |

#### 2.4.15 `ENQUETE_CONTROLE` — Onglet 03 / Art. 48

**Rôle :** 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

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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 |
| `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 |

#### 2.4.16 `CONSTAT_ENQUETE` — Onglet 03 · 3NF

**Rôle :** Lignes de constat et actions de suivi, sans colonnes répétées.  
**PK :** `CONSTAT_ID`  
**FK :** ENQUETE_ID

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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 | — |
| `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 |

#### 2.4.17 `REF_UNITE` — Onglet 10

**Rôle :** Unités de mesure normalisées.  
**PK :** `UNITE_ID`  
**FK :** —

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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… |
| `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 |

#### 2.4.18 `REF_PARAMETRE` — Onglets 04 / 10

**Rôle :** Dictionnaire des paramètres analysés. Une ligne par paramètre, jamais une colonne par polluant.  
**PK :** `PARAMETRE_ID`  
**FK :** UNITE_ID

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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') |
| `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 |

#### 2.4.19 `REF_SEUIL_REGLEMENTAIRE` — Art. 42 / 44 · Versioning

**Rôle :** 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

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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 |
| `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 |

#### 2.4.20 `DEROGATION_SEUIL` — Art. 42 · Exception chaux

**Rôle :** 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

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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 |
| `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 |

#### 2.4.21 `PRELEVEMENT` — Onglet 04 · Échantillon

**Rôle :** Prélèvement / échantillon parent. Le détail des mesures est dans RESULTAT_ANALYSE.  
**PK :** `PRELEVEMENT_ID`  
**FK :** INDUSTRIEL_ID, ENQUETE_ID

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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 |
| `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 |

#### 2.4.22 `RESULTAT_ANALYSE` — Onglet 04 · Saisie unique

**Rôle :** UNE ligne = UN paramètre = UNE valeur mesurée. Aucun champ de conformité saisi.  
**PK :** `RESULTAT_ID`  
**FK :** PRELEVEMENT_ID, PARAMETRE_ID

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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 |
| `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 |

#### 2.4.23 `REF_TYPE_DOSSIER` — Onglet 05 · Nomenclature

**Rôle :** EIE, autorisation, MED, certification, convention.  
**PK :** `TYPE_DOSSIER_ID`  
**FK :** —

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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') |
| `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 |

#### 2.4.24 `DOSSIER_REGLEMENTAIRE` — Onglet 05 · MED / EIE

**Rôle :** Dossiers, mises en demeure et certifications ; source du KPI 'MED actives'.  
**PK :** `DOSSIER_ID`  
**FK :** INDUSTRIEL_ID, TYPE_DOSSIER_ID

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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 |
| `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 |

#### 2.4.25 `REF_TYPE_RECLAMATION` — Onglet 08 · Nomenclature

**Rôle :** Réclamation / incident / nuisance / déversement.  
**PK :** `TYPE_RECLAMATION_ID`  
**FK :** —

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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 | — |
| `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 |

#### 2.4.26 `RECLAMATION_INCIDENT` — Onglet 08

**Rôle :** Source du délai moyen de traitement (6,2 j dans la présentation).  
**PK :** `RECLAMATION_ID`  
**FK :** INDUSTRIEL_ID, TYPE_RECLAMATION_ID

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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) |
| `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 |

#### 2.4.27 `DOCUMENT` — Onglet 09

**Rôle :** Référentiel documentaire ; BLOB ou lien SharePoint/ORDS.  
**PK :** `DOCUMENT_ID`  
**FK :** INDUSTRIEL_ID + contexte

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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 |
| `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 |

#### 2.4.28 `ALERTE_NON_CONFORMITE` — Générée par trigger

**Rôle :** Alerte de dépassement créée automatiquement ; jamais saisie par l'utilisateur.  
**PK :** `ALERTE_ID`  
**FK :** RESULTAT_ID, INDUSTRIEL_ID, PRELEVEMENT_ID

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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 |
| `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 |

#### 2.4.29 `JOURNAL_MAJ` — Onglet 11 · Append-only

**Rôle :** Traçabilité automatique de toutes les écritures. Interdiction UPDATE/DELETE par trigger.  
**PK :** `JOURNAL_ID`  
**FK :** —

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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 |
| `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 |

#### 2.4.30 `APP_ROLE` — Sécurité APEX

**Rôle :** Rôles fonctionnels et authorization schemes.  
**PK :** `ROLE_ID`  
**FK :** —

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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 | — |
| `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 |

#### 2.4.31 `APP_UTILISATEUR` — Sécurité APEX

**Rôle :** Utilisateurs applicatifs (ou mapping SSO / APEX accounts).  
**PK :** `UTILISATEUR_ID`  
**FK :** —

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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') |
| `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 |

#### 2.4.32 `AFFECTATION_ROLE` — Sécurité APEX

**Rôle :** Association many-to-many utilisateur ↔ rôle.  
**PK :** `(UTILISATEUR_ID, ROLE_ID)`  
**FK :** UTILISATEUR_ID, ROLE_ID

| Colonne | Type Oracle | Null | PK / FK / règle |
| --- | --- | --- | --- |
| `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 |
| `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 |

### 2.5 Objets calculés — aucune table de KPI à saisir

| Objet | Type | Rôle |
| --- | --- | --- |
| `SRM_PKG_CONFORMITE` | Package PL/SQL | Seuil applicable (dérogation > industriel > secteur > global), statut légal, vigilance, journalisation |
| `V_RESULTAT_CONFORMITE` | Vue | Un résultat = une valeur comparée au seuil ; inclut le total métaux lourds dérivé |
| `V_PRELEVEMENT_CONFORMITE` | Vue | Agrégation : CONFORME / NON_CONFORME, vigilance, nb dépassements |
| `V_DERNIER_STATUT_INDUSTRIEL` | Vue analytique | Dernier statut par industriel pour la fiche 360° et la carte |
| `V_KPI_GENERAL` / `V_KPI_MENSUEL` | Vues | Indicateurs de la présentation, recalculés à la demande |
| `MV_KPI_MENSUEL` | Materialized view | Snapshot mensuel rafraîchi par `DBMS_SCHEDULER` |
| `V_ALERTES_ACTIVES` | Vue | Dépassements en cours pour APEX Automations / email |
| `JOURNAL_MAJ` | Table append-only | Onglet 11 automatisé par triggers |

## 3. Validation & contraintes d'intégrité industrielle

| Domaine | Règle | Implémentation Oracle / APEX | Finalité |
| --- | --- | --- | --- |
| 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 |

### 3.1 Règles réglementaires extraites du cahier des charges

- **Art. 42 :** pH 5,5–8,5 (exception 5,5–9,5 si neutralisation à la chaux), T° ≤ 30 °C, MES ≤ 500 mg/L, DBO5 ≤ 500 mg/L, DCO < 1000 mg/L, azote total ≤ 150 mg/L *ou* ammonium ≤ 200 mg/L, conductivité 2700 µS/cm, huiles et graisses 150 mg/L, écotoxicité conforme AFNOR T90.301, absence de composés cycliques hydroxylés / dérivés halogénés et de substances nuisant au traitement biologique.
- **Art. 43 :** neutralisation / traitement préalable obligatoire pour acides libres, bases fortes, chromates, cyanures, hydrocarbures, gaz nocifs et matières radioactives.
- **Art. 44 :** liste de valeurs limites **non limitative** ; le référentiel doit donc être versionné et extensible. Total métaux lourds (Cd, Cu, Zn, Cr, Ni, Fe) ≤ 15 mg/L.
- **Art. 45 :** déversements interdits (gaz inflammables/toxiques, hydrocarbures halogénés, boues, déchets solides, substances colorantes, eaux non admissibles, déjections animales, substances radioactives…) modélisés comme contrôles qualitatifs 0/1.
- **Art. 47 :** branchements distincts eaux usées domestiques / eaux pluviales (réseau séparatif) / eaux usées industrielles, avec regard accessible.
- **Art. 48 :** prélèvements et contrôles possibles à tout moment à la charge de l'industriel → traçabilité complète des échantillons.

### 3.2 Référentiel des 40 paramètres et seuils implémentés

| Code | Libellé | Unité | Limite | Article | Mode |
| --- | --- | --- | --- | --- | --- |
| PH | pH | - | 5,5 – 8,5 - | Art. 42 | Actif |
| TEMPERATURE | Température | °C | ≤ 30 °C | Art. 42 | Actif |
| MES | Matières en suspension (MES) | mg/L | ≤ 500 mg/L | Art. 42 | Actif |
| DBO5 | Demande biochimique en oxygène (DBO5) | mg/L | ≤ 500 mg/L | Art. 42 | Actif |
| DCO | Demande chimique en oxygène (DCO) | mg/L | ≤ 1000 mg/L | Art. 42 | Actif |
| AZOTE_TOTAL | Azote total (exprimé en N) | mg/L | ≤ 150 mg/L | Art. 42 | Actif |
| AMMONIUM | Azote ammoniacal (ion ammonium) | mg/L | ≤ 200 mg/L | Art. 42 | Actif |
| CONDUCTIVITE | Conductivité | µS/cm | ≤ 2700 µS/cm | Art. 42 | Actif |
| HUILES_GRAISES | Huiles et graisses | mg/L | ≤ 150 mg/L | Art. 42 | Actif |
| ECOTOX | Écotoxicité conforme AFNOR T90.301 | 0/1 | 1 – 1 0/1 | Art. 42 | Actif |
| CYCLIQUES_HALOGENES | Composés cycliques hydroxylés / dérivés halogénés | 0/1 | ≤ 0 0/1 | Art. 42 | Actif |
| ATTEINTE_TRAITEMENT | Substances nuisant au traitement biologique / ouvrages | 0/1 | ≤ 0 0/1 | Art. 42 | Actif |
| DEVERSEMENT_INTERDIT | Corps ou matières interdits (Art. 45) | 0/1 | ≤ 0 0/1 | Art. 45 | Actif |
| PH_CHAUX | pH - dérogation neutralisation à la chaux | - | 5,5 – 9,5 - | Art. 42 | Dérogatoire |
| FE | Fer (Fe) | mg/L | ≤ 0,5 mg/L | Art. 44 | Actif |
| AL | Aluminium (Al) | mg/L | ≤ 5 mg/L | Art. 44 | Actif |
| MGOH2 | Magnésium hydroxyde (Mg(OH)2) | mg/L | ≤ 100 mg/L | Art. 44 | Actif |
| CD | Cadmium (Cd) | mg/L | ≤ 0,5 mg/L | Art. 44 | Actif |
| SO4 | Sulfate ((SO4)2-) | mg/L | ≤ 400 mg/L | Art. 44 | Actif |
| CR6 | Chrome hexavalent (Cr6+) | mg/L | ≤ 0,1 mg/L | Art. 44 | Actif |
| CU | Cuivre (Cu) | mg/L | ≤ 1 mg/L | Art. 44 | Actif |
| CO | Cobalt (Co) | mg/L | ≤ 2 mg/L | Art. 44 | Actif |
| ZN | Zinc (Zn) | mg/L | ≤ 5 mg/L | Art. 44 | Actif |
| HG | Mercure (Hg) | mg/L | ≤ 0,05 mg/L | Art. 44 | Actif |
| NI | Nickel (Ni) | mg/L | ≤ 2 mg/L | Art. 44 | Actif |
| AG | Argent (Ag) | mg/L | ≤ 0,1 mg/L | Art. 44 | Actif |
| PB | Plomb (Pb) | mg/L | ≤ 0,1 mg/L | Art. 44 | Actif |
| CL2 | Chlore libre (Cl2) | mg/L | ≤ 3 mg/L | Art. 44 | Actif |
| AS | Arsenic (As) | mg/L | ≤ 1 mg/L | Art. 44 | Actif |
| S2 | Sulfures (S2-) | mg/L | ≤ 1 mg/L | Art. 44 | Actif |
| CRO3 | Chromates (CrO3) | mg/L | ≤ 2 mg/L | Art. 44 | Actif |
| F | Fluorure (F-) | mg/L | ≤ 10 mg/L | Art. 44 | Actif |
| CN | Cyanure (CN-) | mg/L | ≤ 0,5 mg/L | Art. 44 | Actif |
| NO2 | Nitrites (NO2) | mg/L | ≤ 10 mg/L | Art. 44 | Actif |
| PHENOL | Phénol (C6H5OH) | mg/L | ≤ 5 mg/L | Art. 44 | Actif |
| SN | Étain (Sn) | mg/L | ≤ 0,1 mg/L | Art. 44 | Actif |
| P | Phosphore (P) | mg/L | ≤ 20 mg/L | Art. 44 | Actif |
| MN | Manganèse (Mn) | mg/L | ≤ 2 mg/L | Art. 44 | Actif |
| CL | Chlorures (Cl-) | mg/L | ≤ 1500 mg/L | Art. 44 | Actif |
| TOTAL_METAUX | Total métaux lourds (Cd, Cu, Zn, Cr, Ni, Fe) | mg/L | ≤ 15 mg/L | Art. 44 | Calculé |

> `PH_CHAUX` est une dérogation inactive par défaut ; `TOTAL_METAUX` est calculé automatiquement et ne doit jamais être saisi. La liste de l'Art. 44 pouvant être complétée, toute nouvelle limite se crée comme **nouvelle version datée**, sans modifier l'historique.

## 4. Formules KPI — calcul automatique

| KPI | Formule | Tables sources | Objet Oracle / APEX |
| --- | --- | --- | --- |
| Industriels recensés | COUNT(INDUSTRIEL WHERE DATE_ARCHIVAGE IS NULL) | INDUSTRIEL | V_KPI_GENERAL |
| Taux conformité rejets | 100 × prélèvements CONFORME / prélèvements contrôlés | V_PRELEVEMENT_CONFORMITE | V_KPI_GENERAL / MV_KPI_MENSUEL |
| Taux couverture enquêtes | 100 × industriels actifs enquêtés / industriels actifs | ENQUETE_CONTROLE | V_KPI_GENERAL |
| MED actives | COUNT(DOSSIER type=MED AND statut=ACTIVE AND échéance ≥ SYSDATE) | DOSSIER_REGLEMENTAIRE | V_KPI_GENERAL |
| Consommation annuelle | SUM(RELEVE_COMPTEUR.VOLUME_M3) sur l'année | RELEVE_COMPTEUR | V_KPI_GENERAL |
| Délai moyen réclamation | AVG(DATE_CLOTURE − DATE_OUVERTURE) | RECLAMATION_INCIDENT | Colonne virtuelle + V_KPI_GENERAL |
| Dépassements | COUNT(V_RESULTAT_CONFORMITE.STATUT_RESULTAT = NON_CONFORME) | RESULTAT_ANALYSE | Trigger + V_ALERTES_ACTIVES |
| Total métaux lourds | SUM(Cd, Cu, Zn, Cr, Ni, Fe) ≤ 15 mg/L | RESULTAT_ANALYSE | V_TOTAL_METAUX / V_RESULTAT_CONFORMITE |
| Statut cartographique | Dernier prélèvement par industriel | V_PRELEVEMENT_CONFORMITE | V_DERNIER_STATUT_INDUSTRIEL |

Les valeurs **247 industriels, 78 % de conformité, 92 % de couverture, 14 MED, 4,2 M m³ et 6,2 j** de la présentation sont des **repères de juin 2026**. Elles ne sont pas stockées comme saisies : le dashboard les recalcule à partir des faits.

## 5. Architecture Oracle APEX recommandée

### 5.1 Composants par domaine

| Zone applicative | Composant APEX | Automatisation / usage |
| --- | --- | --- |
| 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 |

### 5.2 Navigation logique / menu

| Page | Groupe menu | Libellé | Composants | Rôles |
| --- | --- | --- | --- | --- |
| 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 |

### 5.3 Chaîne d'automatisation de bout en bout

1. **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.
2. **Résultat saisi** — Une seule valeur brute est enregistrée dans RESULTAT_ANALYSE avec horodatage et utilisateur.
3. **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.
4. **Conformité** — V_RESULTAT_CONFORMITE puis V_PRELEVEMENT_CONFORMITE calculent CONFORME / NON_CONFORME ; aucun statut n'est saisi.
5. **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.
6. **Total métaux lourds** — Cd + Cu + Zn + Cr + Ni + Fe est sommé automatiquement puis comparé à 15 mg/L (Art. 44).
7. **Alerte** — Un trigger crée ALERTE_NON_CONFORMITE avec écart en %, gravité et référence article ; APEX Automation notifie par email.
8. **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.
9. **Cartographie** — Le dernier statut de chaque industriel colore la Map Region sans mise à jour manuelle.
10. **Audit** — JOURNAL_MAJ est alimenté par triggers : INSERT/UPDATE/DELETE, import, changement de seuil et dérogation.
11. **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.

**Intégrations :** APEX Automations (email, relances MED, refresh MV), ORDS / REST Data Sources (LIMS, SharePoint), Authorization Schemes par rôle, Page 0 pour LOV et filtres globaux, Approvals pour les dérogations et changements de seuils.

## 6. Dashboard livré — mode d'emploi

1. Ouvrir `SRM_RSK_Dashboard.html` (mode fichier local, persistance navigateur) ou l'aperçu live du serveur `dashboard/app.py` (mode SQLite normalisé).
2. Aller dans **Saisie des résultats** : choisir l'industriel, la date, puis saisir **uniquement les valeurs mesurées** par paramètre. Le statut se met à jour en direct.
3. Possibilité de coller / importer un CSV laboratoire (format long ou large) ; les doublons, valeurs invraisemblables et paramètres dérivés sont rejetés.
4. Après enregistrement : conformité, vigilance, alertes, total métaux lourds, KPI, cartographie, journal MAJ et exports se mettent à jour automatiquement.
5. Les onglets **Référentiels & seuils** et **Architecture & APEX** contiennent le référentiel réglementaire et le présent document ; **Journal & automatismes** trace toutes les écritures.

### Ce que l'utilisateur ne saisit jamais

| Champ | Pourquoi |
| --- | --- |
| Conformité / Non conformité | Calculée par `V_RESULTAT_CONFORMITE` à partir du seuil applicable à la date du prélèvement |
| Alerte de dépassement | Créée par trigger `TRG_RESULTAT_ALERTE` avec écart %, gravité et article |
| Total métaux lourds | Somme automatique de Cd, Cu, Zn, Cr, Ni, Fe |
| KPI | Vues + materialized view rafraîchie par scheduler |
| Statut carte / couleur | Dérivé du dernier prélèvement |
| Journal MAJ | Alimenté par triggers d'audit |

## 7. Feuille de route d'implémentation

| Phase | Actions | Livrable |
| --- | --- | --- |
| 1 · Fondation | Exécuter `schema_oracle.sql`, charger référentiels et seuils, configurer rôles / Authorization Schemes | Schéma 3NF + données de référence |
| 2 · Saisie | Créer page Master-Detail + Interactive Grid sur `PRELEVEMENT` / `RESULTAT_ANALYSE`, Dynamic Actions de prévisualisation | Saisie unique sans statut manuel |
| 3 · Moteur | Valider package, vues, triggers d'alerte et d'audit, MV KPI + job scheduler | Conformité et KPI automatiques |
| 4 · Pilotage | Dashboard, Faceted Search, Map Region, charts, alertes, exports | Application APEX pages 1–14 |
| 5 · Intégrations | ORDS/LIMS, SharePoint, notifications email, approbations seuils/dérogations | Flux de données et utilisateurs de la présentation |
| 6 · Recette | Reprendre les 4 prélèvements de la présentation et vérifier 78 % / 92 % / 14 / 4,2 M / 6,2 j | Rapport de recette et bascule production |

## 8. Hypothèses et limites

- Les seuils sont ceux du PDF joint (pages 15–16). La liste de l'Art. 44 étant non limitative, elle doit être validée juridiquement et complétée si la réglementation évolue.
- La conductivité est traitée comme `≤ 2700 µS/cm`, interprétation opérationnelle du libellé « Conductivité 2700 µS/cm ».
- `AZOTE_TOTAL` (150 mg/L) et `AMMONIUM` (200 mg/L) sont deux expressions alternatives de l'Art. 42 ; ne pas exiger les deux pour un même prélèvement.
- Le total métaux lourds est calculé à partir des codes `CD, CU, ZN, CR6, NI, FE` ; la correspondance exacte Cr total / Cr⁶⁺ doit être confirmée avec le laboratoire.
- Le dashboard utilise un jeu de démonstration déterministe : les 4 prélèvements de la présentation sont reproduits à l'identique, les autres mesures sont illustratives. Les valeurs limites, elles, sont réglementaires.
- Le serveur local utilise SQLite normalisée comme prototype ; la cible de production est Oracle + APEX selon `schema_oracle.sql`.
