Skip to content

feat(postcodes/LU): 4,491 Luxembourg CACLR codes (#1039)#1488

Merged
dr5hn merged 1 commit into
masterfrom
feat/postcodes-luxembourg
Apr 27, 2026
Merged

feat(postcodes/LU): 4,491 Luxembourg CACLR codes (#1039)#1488
dr5hn merged 1 commit into
masterfrom
feat/postcodes-luxembourg

Conversation

@dr5hn
Copy link
Copy Markdown
Owner

@dr5hn dr5hn commented Apr 27, 2026

Summary

  • Imports the official LU CACLR postcode registry (4,491 codes) for Can we add a postcode for this? #1039
  • 100% state FK resolution across all 12 Luxembourgish cantons
  • Sourced under CC-Zero (public domain) from data.public.lu

Source

  • CACLR (Centre des Adresses du Cadastre du Luxembourg) — the canonical Luxembourg address reference
  • Published on data.public.lu under CC-Zero
  • File: caclr.xlsx, sheet TR.DiCaCoLo.RuCp (denormalised join with district/canton/commune/locality/street/postcode)
  • Refresh date: 2026-04-27 snapshot (URL is date-stamped; importer auto-resolves the latest via the dataset API)

Why this source (not OpenPLZ or population CSV)

  • OpenPLZ does not cover LU (only DE/AT/CH/LI; the research doc's Tier-E hypothesis was wrong on this)
  • The simpler rnpp-code-postal.csv ships only postcode+population — no canton or locality FK
  • Only caclr.xlsx carries the full join chain required for state FK

State FK strategy

13 source canton labels collapse to 12 CSC iso2 codes via SOURCE_TO_ISO2. The only sub-classification handled is LUXEMBOURG-VILLE (the capital city, which is its own administrative entity but sits inside canton Luxembourg) → CSC L.

118 records with ? postcode (newly-named streets without assigned codes) are filtered before regex check.

Distribution

iso2 canton rows
L Luxembourg 1,357
ES Esch-sur-Alzette 1,270
CA Capellen 386
ME Mersch 272
DI Diekirch 263
G Grevenmacher 257
EC Echternach 159
RM Remich 144
CL Clervaux 121
WI Wiltz 118
RD Redange 95
VD Vianden 49

Test plan

  • python3 -m py_compile bin/scripts/sync/import_luxembourg_postcodes.py
  • All 4,491 codes match ^(?:L-)?\d{4}$
  • 100% state_id valid; state.country_id == 127; state_code == state.iso2
  • No auto-managed fields (id, created_at, updated_at, flag)
  • Idempotent merge (re-run produces no diff)

🤖 Generated with Claude Code

Adds the official Luxembourg postcode dataset from CACLR (Centre des
Adresses du Cadastre du Luxembourg) via data.public.lu, CC-Zero.

Why
---
Closes the LU gap on issue #1039. The CACLR registry is the
canonical reference for Luxembourgish addresses, published by the
LU government under public-domain CC-Zero.

Coverage
--------
- 4,491 unique (code, locality, canton) tuples / 100% state FK
- All 12 CSC cantons covered

Source pipeline
---------------
1. data.public.lu API resolves the latest caclr.xlsx URL (URL is
   date-stamped and rotates every refresh)
2. Importer parses the denormalised TR.DiCaCoLo.RuCp join sheet
   directly via openpyxl
3. SOURCE_TO_ISO2 maps 13 source canton labels to 12 CSC iso2
   ('LUXEMBOURG-VILLE' capital sub-classification collapses to L)
4. 118 '?' postcodes (newly named streets without assigned codes)
   are filtered out

License
-------
CC-Zero (public domain). Each row carries
`source: "caclr-data-public-lu"` for export-time provenance.

Validation
----------
- python3 -m py_compile passes
- 100% regex match (^(?:L-)?\d{4}$)
- 100% state_id valid + state.country_id == 127 + state_code agrees
- No auto-managed fields (id, created_at, updated_at, flag)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 27, 2026 15:55
@dosubot dosubot Bot added the size:XS This PR changes 0-9 lines, ignoring generated files. label Apr 27, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review any files in this pull request.

@github-actions
Copy link
Copy Markdown
Contributor

CSC Validation Report

PR Format

  • ✅ Description provided
  • ✅ Data source linked
  • ✅ Issue linked (recommended for data changes)
  • ✅ Justification / context provided

Labels applied: data:postcodes, large-contribution

⚠️ Large Contribution

This PR contains 4491 records. Large contributions require manual review.

Schema Validation (4491 records)

✅ All records passed validation

Cross-Reference Validation

✅ 8982 reference(s) verified

Source URL Verification

✅ 2 source URL(s) accessible


All checks passed | Status: Ready for review

@dr5hn dr5hn merged commit 21fed19 into master Apr 27, 2026
1 check passed
@dr5hn dr5hn deleted the feat/postcodes-luxembourg branch April 27, 2026 15:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

data:postcodes enhancement New feature or request large-contribution ready-for-review size:XS This PR changes 0-9 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants