Aller au contenu

Nomos Zonage -- Dentist Geographic Zoning

The nomos_zonage app manages French geographic zoning data for dentist accessibility (Carto Sante program). It maps communes to service-level categories indicating how well-served an area is for dental care.

Architecture

  • Source data: Excel files from official Carto Sante distributions
  • Import: Management commands load postal mappings and zoning data
  • Access: Django admin only (no custom views)

Models

Model Description
PostalCodeMapping INSEE code <-> postal code correspondence (unique together)
CommuneZonage Commune zoning level on a 5-point scale
ZonageImportLog Tracks import operations with status and statistics

Zoning Categories

Level Key Description
1 tres_sous_dotee Very underserved
2 sous_dotee Underserved
3 intermediaire Intermediate
4 bien_dotee Well-served
5 sur_dotee Over-served

Constants defined in apps/nomos_zonage/constants.py with CSS classes for badge display.

Management Commands

Command Description
postal_mapping_import Import postal code <-> INSEE mappings
zonage_import Import zoning data from Excel
zonage_link_orgs Link organizations to their zoning level

Operations -- Full Import Procedure

Overview

The pipeline has 3 steps that must run in order:

  1. postal_mapping_import -- loads the postal code ↔ INSEE commune code lookup table
  2. zonage_import -- loads commune zoning levels from the Carto Santé Excel export
  3. zonage_link_orgs -- resolves each organization's postal code → INSEE code → zonage and writes it to the org record

Source files

File Source Default location Format
laposte_hexasmal.csv data.gouv.fr (La Poste) data/reference/laposte_hexasmal.csv (bundled in repo) CSV
export_zoning.xlsx Carto Santé (ARS) No default -- must be provided via --source-file Excel, sheet "Data", headers on row 4

Step-by-step

1. Upload the zoning file to the server

Copy the Carto Santé Excel export to a location accessible by the container:

scp export_zoning.xlsx your-server:/tmp/cartosante/

2. Open a shell in the web container

make shell ENV=staging

All commands below are run inside this shell.

3. Import postal code mappings (if needed)

This table is rarely updated. Only re-run if La Poste has published a new version or the table is empty.

# Preview
python manage.py postal_mapping_import --dry-run

# Import (uses bundled CSV at data/reference/laposte_hexasmal.csv)
python manage.py postal_mapping_import

4. Import zoning data

# Preview
python manage.py zonage_import --source-file /tmp/cartosante/export_zoning.xlsx --dry-run

# Import (--truncate replaces all existing data)
python manage.py zonage_import --source-file /tmp/cartosante/export_zoning.xlsx --truncate
# Preview resolution stats
python manage.py zonage_link_orgs --dry-run

# Apply (--force overwrites existing zonage values)
python manage.py zonage_link_orgs --force

The command resolves an organization's zonage in this order:

  1. Direct INSEE -- use the org's existing address_insee_code if it matches a known zonage
  2. Single postal match -- if the postal code maps to exactly one commune, use it
  3. City name match -- if multiple communes share a postal code, match on normalized city name
  4. CEDEX fallback -- if the postal code is not in the mapping (common for CEDEX codes), derive the department from the first 2 digits, strip "CEDEX" from the city name, and match against all communes in that department

Unresolved organizations are logged in the output stats.

Checking results

  • Admin: browse PostalCodeMapping, CommuneZonage, and ZonageImportLog in Django admin
  • Frontend: /annuaire/zonage/ shows organizations with their zoning levels
  • Import logs track status, record counts, duration, and errors for each run