Lompat ke konten
dokumentasi.id
Commit 493bd1c
v1
Star762

3

Skema Kode dan Level Wilayah

Setiap wilayah di emsifa/api-wilayah-indonesia diidentifikasi oleh satu string kode bertitik. Titik adalah pemisah hierarki: jumlah titik menentukan level, dan potongan sebelum titik terakhir adalah kode induk. Aturan ini menggantikan format v1 yang menempelkan seluruh level menjadi satu angka 1103010, dan berlaku sama untuk berkas unduhan maupun id di setiap response API (README.md:71-72).

erDiagram
    PROVINCE ||--o{ REGENCY : "contains"
    REGENCY ||--o{ DISTRICT : "contains"
    DISTRICT ||--o{ VILLAGE : "contains"
    PROVINCE {
        varchar2 kode PK
        varchar name
    }
    REGENCY {
        varchar5 kode PK
        varchar2 province_kode FK
    }
    DISTRICT {
        varchar8 kode PK
        varchar5 regency_kode FK
    }
    VILLAGE {
        varchar13 kode PK
        varchar8 district_kode FK
        varchar5 postal_code
    }
    style PROVINCE fill:#336791,color:#fff
    style REGENCY fill:#336791,color:#fff
    style DISTRICT fill:#336791,color:#fff
    style VILLAGE fill:#8b5cf6,color:#fff
%% fig: Relasi kode bertitik antar level wilayah
%% desc: Kode induk selalu berupa prefix kode anak; level 1-2 memakai objek rich, level 3-4 memakai objek compact plus postal_code pada village.
Fig. 1: Relasi kode bertitik antar level wilayahKode induk selalu berupa prefix kode anak; level 1-2 memakai objek rich, level 3-4 memakai objek compact plus postal_code pada village.

Jumlah titik menentukan level

genLevelCount hanya menghitung jumlah karakter . di dalam kode (tools/generate_static_api.go:164). Fungsi ini dipakai di dua tempat: saat readWilayah memilah baris wilayah.csv ke dalam map induk masing-masing (tools/generate_static_api.go:451-462), dan saat writeStats menghitung populasi serta luas hanya dari entri level 0 (tools/generate_static_api.go:401-405).

Jumlah titikLevelPanjang kodeContohEndpoint daftar
01 province211/provinces.json
12 regency511.01/regencies/11.json
23 district811.01.01/districts/11.01.json
34 village1311.01.01.2001/villages/11.01.01.json

Panjang karakter per level dan contoh kode diambil langsung dari aturan hitung titik di SKILL.md:170. Nilai meta.level memakai penomoran berbeda satu angka, karena level 0 dipakai untuk stats: 0=stats, 1=province, 2=regency, 3=district, 4=village/postal (SKILL.md:35). Jadi meta.level sama dengan jumlah titik ditambah satu. Untuk /paths/{code}.json nilai ini dihitung ulang lewat genLevelCount(kode)+1 (tools/generate_static_api.go:346), sedangkan /stats.json ditulis dengan level tetap 0 (tools/generate_static_api.go:417).

⚠️ summary.by_level di /missings.json memakai nama level, bukan angka, dan penomorannya mengikuti jumlah titik: province=0 dots, regency=1, district=2, village=3 (SKILL.md:152). Jangan menyamakan angka ini dengan meta.level.

Tiga helper memotong kode untuk mendapat induknya. genProvinceOf mengambil potongan sebelum titik pertama (tools/generate_static_api.go:166-171), genRegencyOf menggabungkan dua segmen pertama (tools/generate_static_api.go:173-179), dan genDistrictOf menggabungkan tiga segmen pertama (tools/generate_static_api.go:181-187). Ketiganya defensif: bila segmen kurang dari yang dibutuhkan, fungsi mengembalikan kode apa adanya.

graph LR
    V["32.73.01.1001<br/>village"] --> D["32.73.01<br/>genDistrictOf"]
    V --> R["32.73<br/>genRegencyOf"]
    V --> P["32<br/>genProvinceOf"]
    D --> R2["32.73"]
    A["11"] -.->|no dot| A2["11"]
    style V fill:#8b5cf6,color:#fff
    style D fill:#336791,color:#fff
    style R fill:#336791,color:#fff
    style P fill:#336791,color:#fff
    style A fill:#f59e0b,color:#000
%% fig: Penurunan kode induk dari satu kode village
%% desc: Setiap helper memotong kode pada jumlah segmen tertentu; kode tanpa titik dikembalikan utuh sehingga aman dipanggil di semua level.
Fig. 2: Penurunan kode induk dari satu kode villageSetiap helper memotong kode pada jumlah segmen tertentu; kode tanpa titik dikembalikan utuh sehingga aman dipanggil di semua level.

Helper ini yang mengisi field parent di objek detail: Province diisi untuk regency (tools/generate_static_api.go:251), Province dan Regency untuk district (tools/generate_static_api.go:259-260), serta ketiganya untuk village (tools/generate_static_api.go:270-272). Parent selalu dibangun oleh genParentPlace, yang hanya menyertakan ID dan Name — tanpa field rich (tools/generate_static_api.go:143-148). Karena itu objek province di dalam sebuah village berisi dua field saja, berbeda dari provinces/{code}.json.

Field rich versus compact

Dua struct memisahkan bentuk response. genShortItem hanya punya id, name, postal_code (opsional), dan has_path (tools/generate_static_api.go:100-105). genPlace punya himpunan field lengkap: id, name, capital, lat, lng, elv, tz, population, total_area, postal_code, has_path, ditambah tiga parent opsional (tools/generate_static_api.go:107-123).

Pemilihan bentuk terjadi di newGenPlace: bila HasRich bernilai false, fungsi mengembalikan genPlace minimal berisi ID, Name, dan PostalCode saja (tools/generate_static_api.go:125-128). Flag HasRich hanya diset true di phaseB, yaitu ketika kode tersebut muncul di wilayah_level_1_2.csv (tools/generate_static_api.go:329-337). Isi berkas itu hanya provinsi dan kab/kota, sesuai komentar header (tools/generate_static_api.go:10-16).

LevelObjekField yang selalu adaField tambahan
1 provincegenPlace richid, name, capital, lat, lng, elv, tz, population, total_areahas_path
2 regencygenPlace richsama dengan provincehas_path, province {id,name}
3 districtgenShortItem di daftarid, namehas_path, lat, lng (diisi generate_boundaries)
3 districtgenPlace di detailid, namehas_path, lat, lng, province, regency
4 villagegenShortItem di daftarid, name, postal_codehas_path, lat, lng
4 villagegenPlace di detailid, name, postal_codehas_path, lat, lng, province, regency, district

Objek rich untuk level 1 dan level 2 ditulis dua kali. phaseA menulis semuanya lebih dulu dengan newGenPlace, lalu phaseB menimpa provinces.json, provinces/{code}.json, regencies/{province}.json, dan regencies/{code}.json setelah kolom rich terbaca (tools/generate_static_api.go:355-378). Daftar regencies/{province}.json pun ikut ditimpa dengan []genPlace, bukan []genShortItem, sehingga daftar kab/kota juga kaya field (tools/generate_static_api.go:366-371).

Daftar district dan village tetap ditulis sebagai []genShortItem murni di phaseA lewat writeList (tools/generate_static_api.go:228-234), yaitu ID, Nama, dan PostalCode saja. Field lat dan lng baru masuk belakangan. updateListLatLng menambahkan pasangan koordinat ke setiap item daftar yang id-nya ada di coordsMap (tools/generate_boundaries.go:645-649), dan updateObjectLatLng menulis lat/lng ke objek detail (tools/generate_boundaries.go:603-604). Untuk kecamatan level ditetapkan 3, untuk kelurahan 4 (tools/generate_boundaries.go:231-234).

⚠️ postal_code hanya ada di village. genPlace memakai tag omitempty untuk field ini, sehingga provinsi, regency, dan district tidak pernah memuat postal_code (tools/generate_static_api.go:117). Pemetaan kode pos dibangun terpisah dari wilayah_kodepos.csv ke map postalToNew (tools/generate_static_api.go:535-547).

has_path melengkapi setiap objek

genPlace dan genShortItem sama-sama mendeklarasikan HasPath dengan tag json:"has_path" tanpa omitempty (tools/generate_static_api.go:104, tools/generate_static_api.go:118). Nilainya tidak diisi oleh kedua fase generate tersebut, melainkan oleh perintah add-has-path, yang memindai api/paths/*.json menjadi himpunan kode lalu menambal setiap berkas target (tools/add_has_path.go:57-61). Penambalan menulis m["has_path"] = hasPathSet[id] untuk item daftar dan v["has_path"] = hasPathSet[id] untuk objek detail (tools/add_has_path.go:151-167).

graph TD
    P["api/paths/*.json"] --> B["buildHasPathSet"]
    B --> S["map code to bool"]
    S --> F["patchFileHasPath"]
    F --> L["data array: set has_path per item"]
    F --> O["data object: set has_path by id"]
    L --> M["meta: drop generated_at, set updated_at"]
    O --> M
    style P fill:#8b5cf6,color:#fff
    style S fill:#336791,color:#fff
    style M fill:#f59e0b,color:#000
%% fig: Penambalan has_path dari daftar berkas polygon
%% desc: Himpunan kode diambil dari nama berkas di api/paths, lalu setiap item dan objek detail ditambal, dan meta ikut disesuaikan.
Fig. 3: Penambalan has_path dari daftar berkas polygonHimpunan kode diambil dari nama berkas di api/paths, lalu setiap item dan objek detail ditambal, dan meta ikut disesuaikan.

Karena has_path bergantung pada keberadaan berkas, nilai false berarti polygon belum tersedia, bukan bahwa kode itu tidak valid. has_latlng adalah penanda kedua, dan hanya muncul di /missings.json bersama has_path (tools/generate_missings.go:31-36). Halaman Kelengkapan Data dan missings.json membahas cara kedua flag itu digabung.

⚠️ ID bertitik adalah string JSON, bukan angka. Membandingkan id dengan == pada nilai hasil parseFloat akan membuang segmen terakhir 11.01.01.1001. Bandingkan sebagai string, persis seperti hasPathSet[id] di tools/add_has_path.go:155-166.

Untuk bentuk response lengkap per endpoint, lihat Format Response dan Wrapper data/meta. Untuk daftar endpoint yang memakai kode ini, lihat Referensi Endpoint.