#process#workflow#master-data#province#erp_province#erp_amper#erp_tambon#embedded
โหลดข้อมูลจังหวัด/อำเภอ/ตำบลมาตรฐาน (Province Load)
เมนู menu_setup_province_auto (C# SMLERPConfig/_provinceLoadFromWebControl) ให้ผู้ใช้ติ๊กเลือกจังหวัดจากรายการมาตรฐาน แล้วระบบเขียนจังหวัด อำเภอ ตำบลของจังหวัดนั้นลง erp_province, erp_amper, erp_tambon ฝั่ง C# เคยอ่านจากเว็บเซอร์วิส ฝั่งนี้แทนด้วยไฟล์ JSON ที่ฝังในไบนารี (//go:embed) จึงไม่เรียกเครือข่ายภายนอก
ทำงานอย่างไร
ข้อมูลมาตรฐานที่ฝังไว้
- ไฟล์
province_data/thailand_geo.jsonโหลดครั้งเดียวด้วยsync.OnceValuesเรียงตามรหัสจังหวัด (province_load.go:23,48) - ตรวจจากไฟล์จริง: 77 จังหวัด, 928 อำเภอ, 7,436 ตำบล (ตรงกับคอมเมนต์ :7); แต่ละระดับมี
code,th,en; ตำบลมีzip_codeได้; ทุกระดับมีlat/lngได้ (ฟิลด์ในgeoPlace:26-33) - โครงสร้าง: จังหวัด ->
districts[]->subdistricts[]; คีย์ระดับบนของไฟล์source,license,provinces - ใบอนุญาตข้อมูลอยู่ที่
province_data/thailand_geo.LICENSE.txt(MIT; ตรวจเฉพาะบรรทัดแรก ๆ ของไฟล์)
2 action ใต้ workflow/*
| action | สิทธิ์ | หน้าที่ |
|---|---|---|
province-list |
read (permission.go:36) |
คืนทุกจังหวัดสำหรับตารางติ๊ก: {code, name (ภาษาไทย), lat, lng} ไม่ต้องมี body (ProvinceList :68) |
province-load |
write (permission.go:51) |
โหลดจังหวัดที่ติ๊กลงฐานข้อมูลบริษัท (ProvinceLoad :176) |
province-load ทำอย่างไร
- Input
codes[](รหัสจังหวัดที่ติ๊ก) ->pickProvinces(:108): trim ค่าว่างทิ้ง, ไม่ติ๊กเลย = error "กรุณาเลือกจังหวัดอย่างน้อย 1 จังหวัด", รหัสที่ไม่มีในข้อมูลมาตรฐาน = error "ไม่พบรหัสจังหวัดที่เลือกในข้อมูลมาตรฐาน", รหัสซ้ำถูกตัด และคงลำดับตามข้อมูลมาตรฐาน flattenGeo(:132) แตกเป็น 3 ระดับแบบ parallel array: จังหวัด, อำเภอ (เก็บprovince), ตำบล (เก็บprovince,amper)- ใน
withTxเดียว: ล็อกpg_advisory_xact_lock(hashtext('province_load'))กันสองคนโหลดพร้อมกันแล้ว insert ซ้ำ (คอมเมนต์ :188) จากนั้นรัน 3 statement ตามลำดับ จังหวัด -> อำเภอ -> ตำบล - แต่ละ statement เป็น CTE เดียว:
DELETEแถวเดิมตามคีย์ (code/province,code/province,amper,code) แล้วINSERTใหม่จากอาร์เรย์ (unnest) - เมื่อโหลดซ้ำ ค่าเดิมถูกรักษาไว้:
lat/lngเดิมที่ไม่เป็น 0,zip_codeเดิมที่ไม่ว่าง (เฉพาะตำบล),status,guid_codeมิฉะนั้นใช้ค่าจากไฟล์ฝัง (คอมเมนต์ :145-147 และ SQL :148-173) - เขียน log ผ่าน
writeProcessLogเมนูmenu_setup_province_autoดู กลุ่ม route workflow เมนูกระบวนการระบบ (Workflow Menus)
ผลลัพธ์ ProvinceLoadResult: provinces, amphurs, tambons (จำนวนแถวที่ส่งเข้า insert) -- รันซ้ำได้ผลเท่าเดิม (คอมเมนต์ :174-175 "Re-running it gives the same rows")
ข้อควรระวัง
- ไม่ลบจังหวัดที่ไม่ได้ติ๊ก และไม่ลบอำเภอ/ตำบลที่ไม่อยู่ในไฟล์ (ลบเฉพาะแถวที่คีย์ตรงกับที่จะ insert)
- ข้อมูลมาตรฐานมาจากไฟล์ที่ฝังในรุ่นที่ build ถ้าต้องการรหัสไปรษณีย์ใหม่ต้องเปลี่ยนไฟล์แล้ว build ใหม่
ที่มาในโค้ด
backend/internal/application/process/province_load.go:3-8- คอมเมนต์หลักของเมนูและข้อมูลฝังbackend/internal/application/process/province_load.go:23-58-go:embed, ชนิดgeoPlace/geoDistrict/geoProvince,provinceGeobackend/internal/application/process/province_load.go:60-78-ProvinceRow,ProvinceListbackend/internal/application/process/province_load.go:108-143-pickProvinces,flattenGeobackend/internal/application/process/province_load.go:148-173- SQL สามระดับprovinceInsertSQL,amperInsertSQL,tambonInsertSQLbackend/internal/application/process/province_load.go:174-209-ProvinceLoadbackend/internal/application/process/province_data/thailand_geo.json- ข้อมูลมาตรฐานbackend/internal/adapter/inbound/http/process/workflow_handler.go:115-123- caseprovince-list,province-load