Skip to content

feat(postcodes/LI): add Liechtenstein postcodes (#1039)#1401

Merged
dr5hn merged 1 commit into
masterfrom
feat/postcodes-liechtenstein
Apr 25, 2026
Merged

feat(postcodes/LI): add Liechtenstein postcodes (#1039)#1401
dr5hn merged 1 commit into
masterfrom
feat/postcodes-liechtenstein

Conversation

@dr5hn
Copy link
Copy Markdown
Owner

@dr5hn dr5hn commented Apr 25, 2026

Summary

First country populated against the postcodes table introduced in #1398. Adds Liechtenstein's 13 postal codes (range 9485–9498) covering the country's 11 municipalities.

Mapping

state_code Municipality Postcode(s)
01 Balzers 9496 Balzers
02 Eschen 9485 Nendeln, 9492 Eschen
03 Gamprin 9487 Bendern
04 Mauren 9486 Schaanwald, 9493 Mauren
05 Planken 9498 Planken
06 Ruggell 9491 Ruggell
07 Schaan 9494 Schaan
08 Schellenberg 9488 Schellenberg
09 Triesen 9495 Triesen
10 Triesenberg 9497 Triesenberg
11 Vaduz 9490 Vaduz

(Bold = secondary locality within the municipality.)

Source

source: "manual" — composed from common knowledge. Liechtenstein's postcodes are universally documented and stable for decades. Subsequent country PRs will use automated pipelines (OpenPLZ for DACH, Wikidata SPARQL, Census ZCTA for US, etc.) once their adapter scripts land.

Validation

  • ✅ All 13 records pass schema rules in .github/scripts/utils.js
  • ✅ All country_id / state_id foreign keys resolve against existing data
  • ✅ All state_code values match the corresponding state.iso2
  • ✅ All code values match countries.postal_code_regex for LI (^(\d{4})$)
  • ✅ No auto-managed fields (id, created_at, updated_at, flag) present

Out of scope

  • latitude / longitude — left null. Could be backfilled with municipality centroids in a follow-up.
  • wikiDataId per postcode — left null. Wikidata cross-reference is a separate enhancement.
  • city_id — left null. Most LI postcodes serve a locality that may or may not be in cities; resolving each is a separate sweep.

Test plan

  • JSON syntax valid
  • FK integrity verified locally against contributions/countries/countries.json and contributions/states/states.json
  • Codes match country regex
  • PR validator runs on top of feat(postcodes): add postcodes table and infrastructure (#1039) #1398's validator changes
  • Reviewer confirms locality-to-municipality mapping (especially the two split cases: Eschen=9485+9492, Mauren=9486+9493)

Refs: #1039
Builds on: #1398

🤖 Generated with Claude Code

Adds the 13 Liechtenstein postal codes (range 9485-9498) covering the
country's 11 municipalities. First country populated against the
postcodes table introduced in #1398. Proves the file shape and
validator path end-to-end.

Mapping (state_code -> code -> locality):
  01 Balzers       -> 9496 Balzers
  02 Eschen        -> 9485 Nendeln, 9492 Eschen
  03 Gamprin       -> 9487 Bendern
  04 Mauren        -> 9486 Schaanwald, 9493 Mauren
  05 Planken       -> 9498 Planken
  06 Ruggell       -> 9491 Ruggell
  07 Schaan        -> 9494 Schaan
  08 Schellenberg  -> 9488 Schellenberg
  09 Triesen       -> 9495 Triesen
  10 Triesenberg   -> 9497 Triesenberg
  11 Vaduz         -> 9490 Vaduz

source: "manual" — composed from common knowledge (LI postcodes are
universally documented and stable); next country PRs will switch to
automated pipelines (OpenPLZ, Wikidata, Census, etc.) once their
adapters land.

Validated:
- All 13 records pass schema rules in .github/scripts/utils.js
- All country_id/state_id FKs resolve
- All state_code values match the corresponding state.iso2
- All codes match countries.postal_code_regex for LI (^(\\d{4})$)

Refs: #1039

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 25, 2026 14:36
@dosubot dosubot Bot added size:XS This PR changes 0-9 lines, ignoring generated files. enhancement New feature or request labels Apr 25, 2026
@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

Schema Validation (13 records)

✅ All records passed validation

Cross-Reference Validation

✅ 26 reference(s) verified

Source URL Verification

✅ 1 source URL(s) accessible


All checks passed | Status: Ready for review

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.

Pull request overview

Adds the first country dataset for the newly introduced postcodes contribution pipeline by populating Liechtenstein (LI) postcode records under contributions/postcodes/.

Changes:

  • Add contributions/postcodes/LI.json containing 13 LI postcodes (9485–9498, excluding 9489) mapped to existing LI municipalities via state_id/state_code.
  • Populate locality_name, type, and source metadata per record.

@dr5hn dr5hn merged commit d4e4e85 into master Apr 25, 2026
5 checks passed
@dr5hn dr5hn deleted the feat/postcodes-liechtenstein branch April 25, 2026 15:10
dr5hn added a commit that referenced this pull request Apr 27, 2026
…1431)

Adds two things in one PR (the script + its first run):

1. bin/scripts/sync/import_openplz_postcodes.py — pipeline that walks
   the OpenPLZ REST API hierarchy for Germany, Austria, and
   Switzerland, paginating Localities under each region. ODbL-1.0
   licensed source matches this repo's licence exactly.

2. Three new contribution files:
     contributions/postcodes/DE.json (12,815 records, 2.5 MB)
     contributions/postcodes/AT.json (18,722 records, 4.0 MB)
     contributions/postcodes/CH.json ( 4,059 records, 840 KB)

   Total: 35,596 postcodes across DACH with 100% state_id resolution.

How state resolution works
- DE/CH: exact case-insensitive name match against states.json (with
  light umlaut normalisation and a few translation aliases:
  Luzern->Lucerne, Genève->Geneva, Basel-Landschaft->Basel-Land,
  Fribourg/Freiburg->Fribourg, etc.)
- AT: name match catches the directly-spelt provinces (Salzburg,
  Vorarlberg, Burgenland) and aliases handle translations
  (Wien->Vienna, Tirol->Tyrol, Steiermark->Styria, Kärnten->Carinthia,
  Niederösterreich->Lower Austria, Oberösterreich->Upper Austria).
  A postcode-prefix fallback covers the rest (1xxx=Wien, 8xxx=Steiermark,
  9xxx=Kärnten, etc.) — Austrian Post's well-documented prefix scheme
  is more reliable than fuzzy multilingual name matching.

LI deliberately omitted
- contributions/postcodes/LI.json is already curated (#1401) with 13
  high-quality 1:1 commune-to-code rows. OpenPLZ's per-code endpoint
  returns multiple sub-localities per code (e.g. Vaduz-Triesen,
  Vaduz-Schaan) that would muddy the existing clean mapping.

Validation (zero errors across 35,596 records)
- All codes match countries.postal_code_regex for their ISO2
- All country_id/state_id foreign keys resolve
- All state_code values agree with state.iso2
- No auto-managed fields present (id, created_at, updated_at, flag)
- Idempotent re-runs preserve any future curated rows by (code, locality_name)

License & attribution
- Source: OpenPLZ (https://openplzapi.org), ODbL-1.0
- Each row: source: "openplz" for programmatic attribution

Refs: #1039

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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 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