@isofh/chuyen-doi-dia-chi-2-cap 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -23
- package/dataXa.json +12 -11
- package/index.js +98 -20
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# @isofh/chuyen-doi-dia-chi-2-cap
|
|
2
2
|
|
|
3
|
-
Package chuẩn hóa địa chỉ hành chính
|
|
3
|
+
Package chuẩn hóa địa chỉ hành chính sang format 2 cấp, kèm theo bộ dữ liệu `dataXa.json`.
|
|
4
4
|
|
|
5
5
|
## Mục tiêu
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
7
|
+
- cung cấp bộ dữ liệu hành chính dùng cho chuẩn hóa địa chỉ
|
|
8
|
+
- cung cấp các hàm chuẩn hóa, kiểm tra xã hợp lệ và bóc địa chỉ từ QR CCCD
|
|
9
9
|
- đóng gói thành npm package để dùng lại giữa nhiều dự án
|
|
10
10
|
|
|
11
11
|
## Cài đặt
|
|
@@ -39,19 +39,22 @@ const {
|
|
|
39
39
|
extractAndConvertCccdAddress,
|
|
40
40
|
} = require("@isofh/chuyen-doi-dia-chi-2-cap");
|
|
41
41
|
|
|
42
|
-
const output = convertDiaChiMoi("Xuân Thành, Xuân Lộc, Đồng Nai");
|
|
43
|
-
console.log(output);
|
|
44
|
-
|
|
45
42
|
const verifyResult = verifyXaName("Xuân Thành", "Đồng Nai");
|
|
46
43
|
console.log(verifyResult.isValid);
|
|
47
44
|
|
|
48
45
|
const splitResult = splitAddressByValidXa("Phú Thạch, Phú Trung, Đồng Nai", "Đồng Nai");
|
|
49
46
|
console.log(splitResult);
|
|
50
47
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
);
|
|
54
|
-
|
|
48
|
+
(async () => {
|
|
49
|
+
const output = await convertDiaChiMoi("Xuân Thành, Xuân Lộc, Đồng Nai");
|
|
50
|
+
console.log(output);
|
|
51
|
+
|
|
52
|
+
const cccdResult = await extractAndConvertCccdAddress(
|
|
53
|
+
"079306006606||Vũ Ngọc Như Lan|27102006|Nữ|19/20 Tổ 71, Khu, Phố 6, Phường 06, Tân Bình, TP.Hồ Chí Minh|26012022"
|
|
54
|
+
);
|
|
55
|
+
console.log(cccdResult.soNha);
|
|
56
|
+
console.log(cccdResult.diaChi);
|
|
57
|
+
})();
|
|
55
58
|
```
|
|
56
59
|
|
|
57
60
|
## Input hỗ trợ
|
|
@@ -75,17 +78,20 @@ const fullAddress = "4A Lê Thánh Tông, Cửa Nam, Hà Nội";
|
|
|
75
78
|
// Caller tự chuẩn hóa/tách phần hành chính trước
|
|
76
79
|
const administrativeAddress = "Cửa Nam, Hà Nội";
|
|
77
80
|
|
|
78
|
-
|
|
81
|
+
(async () => {
|
|
82
|
+
const output = await convertDiaChiMoi(administrativeAddress);
|
|
83
|
+
console.log(output);
|
|
84
|
+
})();
|
|
79
85
|
```
|
|
80
86
|
|
|
81
87
|
## Nguyên tắc xử lý
|
|
82
88
|
|
|
83
|
-
Logic hiện tại bám theo bộ quy tắc
|
|
89
|
+
Logic hiện tại bám theo bộ quy tắc chuẩn hóa địa chỉ hành chính 2 cấp.
|
|
84
90
|
|
|
85
91
|
Thứ tự xử lý chính:
|
|
86
92
|
|
|
87
93
|
1. Match tỉnh trước bằng tên mới hoặc tên cũ trong `dsTinh`.
|
|
88
|
-
2. Nếu input là 3 vế thì ưu tiên hiểu là `
|
|
94
|
+
2. Nếu input là 3 vế thì ưu tiên hiểu là `xã/phường, huyện/quận, tỉnh/thành` và chỉ giữ xã + tỉnh để đưa về 2 cấp.
|
|
89
95
|
3. Tìm xã/phường theo thứ tự từ chặt đến lỏng:
|
|
90
96
|
- match chính xác tên xã hiện tại
|
|
91
97
|
- match trong `satNhapTu`
|
|
@@ -97,9 +103,11 @@ Thứ tự xử lý chính:
|
|
|
97
103
|
```js
|
|
98
104
|
const { convertDiaChiMoi } = require("@isofh/chuyen-doi-dia-chi-2-cap");
|
|
99
105
|
|
|
100
|
-
|
|
101
|
-
console.log(convertDiaChiMoi("
|
|
102
|
-
console.log(convertDiaChiMoi(
|
|
106
|
+
(async () => {
|
|
107
|
+
console.log(await convertDiaChiMoi("Xuân Thành, Xuân Lộc, Đồng Nai"));
|
|
108
|
+
console.log(await convertDiaChiMoi("Cửa Nam, Hà Nội"));
|
|
109
|
+
console.log(await convertDiaChiMoi(["Phú Thạch", "Phú Trung", "Đồng Nai"]));
|
|
110
|
+
})();
|
|
103
111
|
```
|
|
104
112
|
|
|
105
113
|
## Verify tên xã
|
|
@@ -155,11 +163,11 @@ globalThis.splitAddressByValidXa;
|
|
|
155
163
|
globalThis.extractAndConvertCccdAddress;
|
|
156
164
|
```
|
|
157
165
|
|
|
158
|
-
Mục đích là để
|
|
166
|
+
Mục đích là để caller có thể tận dụng các helper này ở runtime mà không cần tự truyền tay qua nhiều lớp.
|
|
159
167
|
|
|
160
168
|
## Trích xuất địa chỉ căn cước
|
|
161
169
|
|
|
162
|
-
`parseCccdQrString` dùng để parse chuỗi QR CCCD dạng
|
|
170
|
+
`parseCccdQrString` dùng để parse chuỗi QR CCCD dạng pipe, ví dụ:
|
|
163
171
|
|
|
164
172
|
```txt
|
|
165
173
|
079306006606||Vũ Ngọc Như Lan|27102006|Nữ|19/20 Tổ 71, Khu, Phố 6, Phường 06, Tân Bình, TP.Hồ Chí Minh|26012022
|
|
@@ -183,21 +191,39 @@ console.log(extractCccdAddressText("079306006606||Vũ Ngọc Như Lan|27102006|N
|
|
|
183
191
|
- parse theo logic `toAddress`
|
|
184
192
|
- convert phần địa chỉ hành chính về format mới bằng `convertDiaChiMoi`
|
|
185
193
|
- trả về object đúng shape của `String.prototype.toAddress`
|
|
194
|
+
- giữ lại `soNha` ở top-level output
|
|
195
|
+
- bổ sung `data.soNha` và `data.diaChiGoc` để caller có thể dùng lại dữ liệu trước và sau bước convert
|
|
186
196
|
|
|
187
197
|
Ví dụ:
|
|
188
198
|
|
|
189
199
|
```js
|
|
190
200
|
const { extractAndConvertCccdAddress } = require("@isofh/chuyen-doi-dia-chi-2-cap");
|
|
191
201
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
)
|
|
202
|
+
(async () => {
|
|
203
|
+
console.log(
|
|
204
|
+
await extractAndConvertCccdAddress(
|
|
205
|
+
"079306006606||Vũ Ngọc Như Lan|27102006|Nữ|19/20 Tổ 71, Khu, Phố 6, Phường 06, Tân Bình, TP.Hồ Chí Minh|26012022"
|
|
206
|
+
)
|
|
207
|
+
);
|
|
208
|
+
})();
|
|
197
209
|
```
|
|
198
210
|
|
|
199
211
|
Nếu không truyền `ngayCap`, hàm sẽ tự lấy ngày cấp từ field QR CCCD nếu chuỗi input đúng format pipe.
|
|
200
212
|
|
|
213
|
+
Ví dụ output rút gọn:
|
|
214
|
+
|
|
215
|
+
```js
|
|
216
|
+
{
|
|
217
|
+
soNha: "19/20 Tổ 71, Khu, Phố 6",
|
|
218
|
+
diaChi: "Tân Hòa, Hồ Chí Minh",
|
|
219
|
+
data: {
|
|
220
|
+
soNha: "19/20 Tổ 71, Khu, Phố 6",
|
|
221
|
+
diaChiGoc: "06, Tân Bình, TP.Hồ Chí Minh",
|
|
222
|
+
convertedDiaChi: "Tân Hòa, Hồ Chí Minh"
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
201
227
|
## Tách số nhà dựa trên xã hợp lệ
|
|
202
228
|
|
|
203
229
|
Ý tưởng của hàm `splitAddressByValidXa` là:
|
package/dataXa.json
CHANGED
|
@@ -23849,7 +23849,7 @@
|
|
|
23849
23849
|
"huyen": "xuanloc",
|
|
23850
23850
|
"satNhapTu": [
|
|
23851
23851
|
{ "ten": "Suối Cao", "timKiem": "suoicao" },
|
|
23852
|
-
{ "ten": "Xuân Thành", "timKiem": "xuanthanh", "huyen":"xuanloc" }
|
|
23852
|
+
{ "ten": "Xuân Thành", "timKiem": "xuanthanh", "huyen": "xuanloc" }
|
|
23853
23853
|
]
|
|
23854
23854
|
},
|
|
23855
23855
|
{
|
|
@@ -24313,6 +24313,7 @@
|
|
|
24313
24313
|
"timKiem": "hochiminh",
|
|
24314
24314
|
"dsTinh": [
|
|
24315
24315
|
{ "ten": "Bà Rịa - Vũng Tàu", "timKiem": "baria-vungtau" },
|
|
24316
|
+
{ "ten": "BR-VT", "timKiem": "br-vt" },
|
|
24316
24317
|
{ "ten": "Bình Dương", "timKiem": "binhduong" }
|
|
24317
24318
|
],
|
|
24318
24319
|
"dsXa": [
|
|
@@ -26887,8 +26888,8 @@
|
|
|
26887
26888
|
"ten": "Mỹ Tho",
|
|
26888
26889
|
"timKiem": "mytho",
|
|
26889
26890
|
"satNhapTu": [
|
|
26890
|
-
{ "ten": "1", "timKiem": "1" },
|
|
26891
|
-
{ "ten": "2", "timKiem": "2" },
|
|
26891
|
+
{ "ten": "1", "timKiem": "1", "huyen": "mytho" },
|
|
26892
|
+
{ "ten": "2", "timKiem": "2", "huyen": "mytho" },
|
|
26892
26893
|
{ "ten": "Tân Long", "timKiem": "tanlong" }
|
|
26893
26894
|
]
|
|
26894
26895
|
},
|
|
@@ -26914,7 +26915,7 @@
|
|
|
26914
26915
|
"ten": "Thới Sơn",
|
|
26915
26916
|
"timKiem": "thoison",
|
|
26916
26917
|
"satNhapTu": [
|
|
26917
|
-
{ "ten": "6", "timKiem": "6" },
|
|
26918
|
+
{ "ten": "6", "timKiem": "6", "huyen": "mytho" },
|
|
26918
26919
|
{ "ten": "Thới Sơn", "timKiem": "thoison" }
|
|
26919
26920
|
]
|
|
26920
26921
|
},
|
|
@@ -26922,7 +26923,7 @@
|
|
|
26922
26923
|
"ten": "Trung An",
|
|
26923
26924
|
"timKiem": "trungan",
|
|
26924
26925
|
"satNhapTu": [
|
|
26925
|
-
{ "ten": "10", "timKiem": "10" },
|
|
26926
|
+
{ "ten": "10", "timKiem": "10", "huyen": "mytho" },
|
|
26926
26927
|
{ "ten": "Trung An", "timKiem": "trungan" },
|
|
26927
26928
|
{ "ten": "Phước Thạnh", "timKiem": "phuocthanh" }
|
|
26928
26929
|
]
|
|
@@ -26931,8 +26932,8 @@
|
|
|
26931
26932
|
"ten": "Gò Công",
|
|
26932
26933
|
"timKiem": "gocong",
|
|
26933
26934
|
"satNhapTu": [
|
|
26934
|
-
{ "ten": "1", "timKiem": "1" },
|
|
26935
|
-
{ "ten": "5", "timKiem": "5" },
|
|
26935
|
+
{ "ten": "1", "timKiem": "1", "huyen": "gocong" },
|
|
26936
|
+
{ "ten": "5", "timKiem": "5", "huyen": "gocong" },
|
|
26936
26937
|
{ "ten": "Long Hòa", "timKiem": "longhoa" }
|
|
26937
26938
|
]
|
|
26938
26939
|
},
|
|
@@ -26940,7 +26941,7 @@
|
|
|
26940
26941
|
"ten": "Long Thuận",
|
|
26941
26942
|
"timKiem": "longthuan",
|
|
26942
26943
|
"satNhapTu": [
|
|
26943
|
-
{ "ten": "2", "timKiem": "2" },
|
|
26944
|
+
{ "ten": "2", "timKiem": "2", "huyen": "gocong" },
|
|
26944
26945
|
{ "ten": "Long Thuận", "timKiem": "longthuan" }
|
|
26945
26946
|
]
|
|
26946
26947
|
},
|
|
@@ -26965,8 +26966,8 @@
|
|
|
26965
26966
|
"ten": "Mỹ Phước Tây",
|
|
26966
26967
|
"timKiem": "myphuoctay",
|
|
26967
26968
|
"satNhapTu": [
|
|
26968
|
-
{ "ten": "1", "timKiem": "1" },
|
|
26969
|
-
{ "ten": "3", "timKiem": "3" },
|
|
26969
|
+
{ "ten": "1", "timKiem": "1", "huyen": "cailay" },
|
|
26970
|
+
{ "ten": "3", "timKiem": "3", "huyen": "cailay" },
|
|
26970
26971
|
{ "ten": "Mỹ Hạnh Trung", "timKiem": "myhanhtrung" },
|
|
26971
26972
|
{ "ten": "Mỹ Phước Tây", "timKiem": "myphuoctay" }
|
|
26972
26973
|
]
|
|
@@ -26975,7 +26976,7 @@
|
|
|
26975
26976
|
"ten": "Thanh Hòa",
|
|
26976
26977
|
"timKiem": "thanhhoa",
|
|
26977
26978
|
"satNhapTu": [
|
|
26978
|
-
{ "ten": "2", "timKiem": "2" },
|
|
26979
|
+
{ "ten": "2", "timKiem": "2", "huyen": "cailay" },
|
|
26979
26980
|
{ "ten": "Tân Bình", "timKiem": "tanbinh" },
|
|
26980
26981
|
{ "ten": "Thanh Hòa", "timKiem": "thanhhoa" }
|
|
26981
26982
|
]
|
package/index.js
CHANGED
|
@@ -1,6 +1,39 @@
|
|
|
1
1
|
require("mainam-react-native-string-utils");
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
let dataXa = null;
|
|
4
|
+
let dataXaPromise = null;
|
|
5
|
+
|
|
6
|
+
// Resolve global runtime để hỗ trợ các hook override giống contract gốc ở repo cũ.
|
|
7
|
+
const getGlobalTarget = () =>
|
|
8
|
+
typeof globalThis !== "undefined"
|
|
9
|
+
? globalThis
|
|
10
|
+
: typeof window !== "undefined"
|
|
11
|
+
? window
|
|
12
|
+
: typeof global !== "undefined"
|
|
13
|
+
? global
|
|
14
|
+
: null;
|
|
15
|
+
|
|
16
|
+
// Nạp dataset hành chính ở thời điểm cần dùng thay vì load ngay khi require package.
|
|
17
|
+
const getDataXaSync = () => {
|
|
18
|
+
if (!dataXa) {
|
|
19
|
+
dataXa = require("./dataXa.json");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return dataXa;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// Giữ contract async của hàm gốc để caller có thể await trước khi convert.
|
|
26
|
+
const loadDataXa = async (customDataXa) => {
|
|
27
|
+
if (customDataXa) {
|
|
28
|
+
return customDataXa;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (!dataXaPromise) {
|
|
32
|
+
dataXaPromise = Promise.resolve().then(() => getDataXaSync());
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return dataXaPromise;
|
|
36
|
+
};
|
|
4
37
|
|
|
5
38
|
// Dùng helper của string-utils để tạo key tìm kiếm không dấu, không khoảng trắng.
|
|
6
39
|
const createUniqueText = (text = "") => `${text ?? ""}`.createUniqueText();
|
|
@@ -164,7 +197,7 @@ const dedupeMatches = (matches = []) => {
|
|
|
164
197
|
// Kiểm tra một tên xã có hợp lệ trong phạm vi tỉnh đích hay không.
|
|
165
198
|
const verifyXaName = (tenXa, tinhOrOptions, maybeOptions) => {
|
|
166
199
|
const { tinh, options } = getVerifyOptions(tinhOrOptions, maybeOptions);
|
|
167
|
-
const sourceDataXa = options.dataXa ||
|
|
200
|
+
const sourceDataXa = options.dataXa || getDataXaSync();
|
|
168
201
|
const normalizedXa = normalizeAdministrativeCode(tenXa);
|
|
169
202
|
const normalizedTinh = normalizeAdministrativeCode(tinh);
|
|
170
203
|
const matchedProvinces = getProvinceCandidates(tinh, sourceDataXa);
|
|
@@ -220,7 +253,7 @@ const verifyXaName = (tenXa, tinhOrOptions, maybeOptions) => {
|
|
|
220
253
|
// Tìm xã hợp lệ đầu tiên trong chuỗi địa chỉ để tách các vế đứng trước thành `soNha`.
|
|
221
254
|
const splitAddressByValidXa = (input, tinhOrOptions, maybeOptions) => {
|
|
222
255
|
const { tinh, options } = getVerifyOptions(tinhOrOptions, maybeOptions);
|
|
223
|
-
const sourceDataXa = options.dataXa ||
|
|
256
|
+
const sourceDataXa = options.dataXa || getDataXaSync();
|
|
224
257
|
const parts = splitAddressParts(input);
|
|
225
258
|
|
|
226
259
|
if (!parts.length) {
|
|
@@ -283,18 +316,21 @@ const splitAddressByValidXa = (input, tinhOrOptions, maybeOptions) => {
|
|
|
283
316
|
};
|
|
284
317
|
|
|
285
318
|
// Bóc địa chỉ từ text căn cước rồi trả về output theo đúng contract của `String.prototype.toAddress`.
|
|
286
|
-
const extractAndConvertCccdAddress = (input, ngayCap, options = {}) => {
|
|
319
|
+
const extractAndConvertCccdAddress = async (input, ngayCap, options = {}) => {
|
|
287
320
|
const sourceText = `${input ?? ""}`;
|
|
288
321
|
const parsedQr = parseCccdQrString(sourceText);
|
|
289
322
|
const extractedText = extractCccdAddressText(sourceText);
|
|
290
323
|
const issueDate = normalizeCccdIssueDate(ngayCap || parsedQr?.ngayCap);
|
|
291
324
|
const parsedAddress = extractedText.toAddress({ ngayCap: issueDate, verifyXaName });
|
|
325
|
+
const soNha = parsedAddress?.soNha || "";
|
|
326
|
+
const diaChiGoc = parsedAddress?.diaChi || "";
|
|
292
327
|
const convertedDiaChi = parsedAddress?.diaChi
|
|
293
|
-
? convertDiaChiMoi(parsedAddress.diaChi, options)
|
|
328
|
+
? await convertDiaChiMoi(parsedAddress.diaChi, options)
|
|
294
329
|
: "";
|
|
295
330
|
|
|
296
331
|
return {
|
|
297
332
|
...(parsedAddress || {}),
|
|
333
|
+
soNha,
|
|
298
334
|
diaChi: convertedDiaChi,
|
|
299
335
|
data: {
|
|
300
336
|
...(parsedAddress?.data || {}),
|
|
@@ -302,6 +338,8 @@ const extractAndConvertCccdAddress = (input, ngayCap, options = {}) => {
|
|
|
302
338
|
cccdFields: parsedQr?.fields || [],
|
|
303
339
|
extractedText,
|
|
304
340
|
issueDate,
|
|
341
|
+
soNha,
|
|
342
|
+
diaChiGoc,
|
|
305
343
|
convertedDiaChi,
|
|
306
344
|
},
|
|
307
345
|
};
|
|
@@ -310,16 +348,54 @@ const extractAndConvertCccdAddress = (input, ngayCap, options = {}) => {
|
|
|
310
348
|
/**
|
|
311
349
|
* Nghiệp vụ chuẩn hóa địa chỉ hành chính cũ về format 2 cấp mới.
|
|
312
350
|
*
|
|
313
|
-
*
|
|
314
|
-
*
|
|
351
|
+
* Đầu vào chấp nhận cả chuỗi lẫn mảng, thường gặp các dạng:
|
|
352
|
+
* - `Xã/Phường, Tỉnh/Thành`
|
|
353
|
+
* - `Xã/Phường cũ, Quận/Huyện cũ, Tỉnh/Thành cũ`
|
|
354
|
+
* - Một số case chỉ có 1 vế nhưng thực chất là tên xã/phường.
|
|
355
|
+
*
|
|
356
|
+
* Quy tắc chung:
|
|
357
|
+
* - Nếu đầu vào là 3 cấp thì chỉ giữ xã và tỉnh để đưa hệ thống về format 2 cấp.
|
|
358
|
+
* - Tỉnh được match trước, hỗ trợ cả tên tỉnh mới lẫn tỉnh cũ trong `dsTinh`.
|
|
359
|
+
* - Nếu không match được tỉnh thì trả nguyên dữ liệu cũ để tránh đổi sai địa chỉ.
|
|
360
|
+
* - Sau khi xác định được tỉnh, xã/phường sẽ được tìm theo thứ tự ưu tiên từ chặt đến lỏng.
|
|
361
|
+
*
|
|
362
|
+
* Thứ tự resolve xã/phường:
|
|
363
|
+
* 1. Case đặc biệt chỉ có 1 vế nhưng thực chất là tên xã trong tỉnh vừa match.
|
|
364
|
+
* 2. Match chính xác tên xã/phường hiện tại, ưu tiên cùng huyện cũ nếu đầu vào có huyện.
|
|
365
|
+
* 3. Match chính xác trong danh sách `satNhapTu`, vẫn ưu tiên cùng huyện cũ nếu có.
|
|
366
|
+
* 4. Nếu chưa ra kết quả thì match gần đúng trong `satNhapTu` và bỏ điều kiện huyện.
|
|
367
|
+
* 5. Cuối cùng mới nới lỏng sang match chính xác tên xã/phường hiện tại nhưng bỏ điều kiện huyện.
|
|
368
|
+
*
|
|
369
|
+
* Kết quả trả về luôn là `Xã/Phường mới, Tỉnh/Thành mới`.
|
|
370
|
+
* Huyện chỉ dùng để phân biệt khi tìm kiếm, không còn nằm trong output cuối.
|
|
371
|
+
*
|
|
372
|
+
* Lưu ý về contract hiện tại của package:
|
|
373
|
+
* - Hàm giữ dạng `async` để caller có thể `await` giống luồng gốc.
|
|
374
|
+
* - Dữ liệu hành chính được nạp lazy qua `loadDataXa()` ở thời điểm cần dùng.
|
|
375
|
+
* - Nếu có `window.modifyDataXa`, dữ liệu sẽ được đi qua hook này trước khi chạy thuật toán mặc định.
|
|
376
|
+
* - Nếu có `window.convertDiaChiMoi`, hàm sẽ ưu tiên giao toàn bộ việc convert cho hook runtime này.
|
|
315
377
|
*/
|
|
316
|
-
const convertDiaChiMoi = (diaChi2CapCu, options = {}) => {
|
|
317
|
-
const
|
|
378
|
+
const convertDiaChiMoi = async (diaChi2CapCu, options = {}) => {
|
|
379
|
+
const globalTarget = getGlobalTarget();
|
|
318
380
|
|
|
319
|
-
if (
|
|
381
|
+
if (
|
|
382
|
+
!globalTarget?.convertDiaChiMoi &&
|
|
383
|
+
typeof diaChi2CapCu === "string" &&
|
|
384
|
+
diaChi2CapCu.length <= 6
|
|
385
|
+
) {
|
|
320
386
|
return diaChi2CapCu;
|
|
321
387
|
}
|
|
322
388
|
|
|
389
|
+
let sourceDataXa = await loadDataXa(options.dataXa);
|
|
390
|
+
|
|
391
|
+
if (globalTarget?.modifyDataXa) {
|
|
392
|
+
sourceDataXa = globalTarget.modifyDataXa(sourceDataXa);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if (globalTarget?.convertDiaChiMoi) {
|
|
396
|
+
return await Promise.resolve(globalTarget.convertDiaChiMoi(diaChi2CapCu, sourceDataXa));
|
|
397
|
+
}
|
|
398
|
+
|
|
323
399
|
let diaChi = [];
|
|
324
400
|
const arr = splitAddressParts(diaChi2CapCu);
|
|
325
401
|
|
|
@@ -430,14 +506,7 @@ const convertDiaChiMoi = (diaChi2CapCu, options = {}) => {
|
|
|
430
506
|
};
|
|
431
507
|
|
|
432
508
|
// Mount helper lên global để các package khác có thể dùng runtime mà không cần dependency ngược.
|
|
433
|
-
const globalTarget =
|
|
434
|
-
typeof globalThis !== "undefined"
|
|
435
|
-
? globalThis
|
|
436
|
-
: typeof window !== "undefined"
|
|
437
|
-
? window
|
|
438
|
-
: typeof global !== "undefined"
|
|
439
|
-
? global
|
|
440
|
-
: null;
|
|
509
|
+
const globalTarget = getGlobalTarget();
|
|
441
510
|
|
|
442
511
|
if (globalTarget) {
|
|
443
512
|
globalTarget.verifyXaName = verifyXaName;
|
|
@@ -445,11 +514,11 @@ if (globalTarget) {
|
|
|
445
514
|
globalTarget.extractAndConvertCccdAddress = extractAndConvertCccdAddress;
|
|
446
515
|
}
|
|
447
516
|
|
|
448
|
-
|
|
449
|
-
dataXa,
|
|
517
|
+
const exported = {
|
|
450
518
|
createUniqueText,
|
|
451
519
|
stripAdministrativePrefix,
|
|
452
520
|
normalizeAdministrativeCode,
|
|
521
|
+
loadDataXa,
|
|
453
522
|
convertDiaChiMoi,
|
|
454
523
|
verifyXaName,
|
|
455
524
|
splitAddressByValidXa,
|
|
@@ -458,3 +527,12 @@ module.exports = {
|
|
|
458
527
|
extractCccdAddressText,
|
|
459
528
|
extractAndConvertCccdAddress,
|
|
460
529
|
};
|
|
530
|
+
|
|
531
|
+
Object.defineProperty(exported, "dataXa", {
|
|
532
|
+
enumerable: true,
|
|
533
|
+
get() {
|
|
534
|
+
return getDataXaSync();
|
|
535
|
+
},
|
|
536
|
+
});
|
|
537
|
+
|
|
538
|
+
module.exports = exported;
|