@isofh/chuyen-doi-dia-chi-2-cap 0.1.0
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 +251 -0
- package/dataXa.json +30104 -0
- package/index.js +460 -0
- package/package.json +25 -0
package/README.md
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
# @isofh/chuyen-doi-dia-chi-2-cap
|
|
2
|
+
|
|
3
|
+
Package chuẩn hóa địa chỉ hành chính cũ sang format 2 cấp mới, kèm theo bộ dữ liệu `dataXa.json`.
|
|
4
|
+
|
|
5
|
+
## Mục tiêu
|
|
6
|
+
|
|
7
|
+
- đóng gói `dataXa.json` để có thể dùng lại giữa nhiều dự án
|
|
8
|
+
- tách logic `convertDiaChiMoi` khỏi component UI
|
|
9
|
+
- đóng gói thành npm package để dùng lại giữa nhiều dự án
|
|
10
|
+
|
|
11
|
+
## Cài đặt
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @isofh/chuyen-doi-dia-chi-2-cap
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## API
|
|
18
|
+
|
|
19
|
+
Package export các thành phần sau:
|
|
20
|
+
|
|
21
|
+
- `convertDiaChiMoi(input, options?)`
|
|
22
|
+
- `verifyXaName(tenXa, tinh?, options?)`
|
|
23
|
+
- `splitAddressByValidXa(input, tinh?, options?)`
|
|
24
|
+
- `parseCccdQrString(input)`
|
|
25
|
+
- `extractCccdAddressText(input)`
|
|
26
|
+
- `extractAndConvertCccdAddress(input, ngayCap?, options?)`
|
|
27
|
+
- `dataXa`
|
|
28
|
+
- `createUniqueText(text)`
|
|
29
|
+
- `stripAdministrativePrefix(text)`
|
|
30
|
+
- `normalizeAdministrativeCode(text)`
|
|
31
|
+
|
|
32
|
+
## Cách dùng cơ bản
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
const {
|
|
36
|
+
convertDiaChiMoi,
|
|
37
|
+
verifyXaName,
|
|
38
|
+
splitAddressByValidXa,
|
|
39
|
+
extractAndConvertCccdAddress,
|
|
40
|
+
} = require("@isofh/chuyen-doi-dia-chi-2-cap");
|
|
41
|
+
|
|
42
|
+
const output = convertDiaChiMoi("Xuân Thành, Xuân Lộc, Đồng Nai");
|
|
43
|
+
console.log(output);
|
|
44
|
+
|
|
45
|
+
const verifyResult = verifyXaName("Xuân Thành", "Đồng Nai");
|
|
46
|
+
console.log(verifyResult.isValid);
|
|
47
|
+
|
|
48
|
+
const splitResult = splitAddressByValidXa("Phú Thạch, Phú Trung, Đồng Nai", "Đồng Nai");
|
|
49
|
+
console.log(splitResult);
|
|
50
|
+
|
|
51
|
+
const cccdResult = extractAndConvertCccdAddress(
|
|
52
|
+
"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"
|
|
53
|
+
);
|
|
54
|
+
console.log(cccdResult);
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Input hỗ trợ
|
|
58
|
+
|
|
59
|
+
`convertDiaChiMoi` nhận:
|
|
60
|
+
|
|
61
|
+
- chuỗi địa chỉ hành chính, ví dụ `"Xuân Thành, Xuân Lộc, Đồng Nai"`
|
|
62
|
+
- hoặc mảng các phần tử địa chỉ, ví dụ `['Xuân Thành', 'Xuân Lộc', 'Đồng Nai']`
|
|
63
|
+
|
|
64
|
+
## Lưu ý quan trọng
|
|
65
|
+
|
|
66
|
+
Hàm này chỉ xử lý phần địa chỉ hành chính.
|
|
67
|
+
|
|
68
|
+
Nếu input gốc có cả số nhà, tên đường, khu phố..., caller nên tách phần hành chính trước khi gọi hàm này.
|
|
69
|
+
|
|
70
|
+
Ví dụ:
|
|
71
|
+
|
|
72
|
+
```js
|
|
73
|
+
const fullAddress = "4A Lê Thánh Tông, Cửa Nam, Hà Nội";
|
|
74
|
+
|
|
75
|
+
// Caller tự chuẩn hóa/tách phần hành chính trước
|
|
76
|
+
const administrativeAddress = "Cửa Nam, Hà Nội";
|
|
77
|
+
|
|
78
|
+
const output = convertDiaChiMoi(administrativeAddress);
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Nguyên tắc xử lý
|
|
82
|
+
|
|
83
|
+
Logic hiện tại bám theo bộ quy tắc chuyển đổi địa chỉ đang dùng trong hệ thống HIS.
|
|
84
|
+
|
|
85
|
+
Thứ tự xử lý chính:
|
|
86
|
+
|
|
87
|
+
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à `xã cũ, huyện cũ, tỉnh cũ` và chỉ giữ xã + tỉnh để đưa về 2 cấp.
|
|
89
|
+
3. Tìm xã/phường theo thứ tự từ chặt đến lỏng:
|
|
90
|
+
- match chính xác tên xã hiện tại
|
|
91
|
+
- match trong `satNhapTu`
|
|
92
|
+
- match gần đúng trong `satNhapTu`
|
|
93
|
+
- fallback về match chính xác tên xã hiện tại nhưng bỏ điều kiện huyện
|
|
94
|
+
|
|
95
|
+
## Ví dụ
|
|
96
|
+
|
|
97
|
+
```js
|
|
98
|
+
const { convertDiaChiMoi } = require("@isofh/chuyen-doi-dia-chi-2-cap");
|
|
99
|
+
|
|
100
|
+
console.log(convertDiaChiMoi("Xuân Thành, Xuân Lộc, Đồng Nai"));
|
|
101
|
+
console.log(convertDiaChiMoi("Cửa Nam, Hà Nội"));
|
|
102
|
+
console.log(convertDiaChiMoi(["Phú Thạch", "Phú Trung", "Đồng Nai"]));
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Verify tên xã
|
|
106
|
+
|
|
107
|
+
Hàm `verifyXaName` dùng để kiểm tra một tên xã/phường có tồn tại hợp lệ hay không bằng cách so sánh:
|
|
108
|
+
|
|
109
|
+
- tên xã hiện tại trong `dsXa`
|
|
110
|
+
- tên xã cũ trong `satNhapTu`
|
|
111
|
+
|
|
112
|
+
Tham số thứ 2 là `tỉnh` để thu hẹp phạm vi tìm kiếm. Đây là tham số nên truyền vào trong các case tách `soNha`, vì cùng một tên xã có thể tồn tại ở nhiều tỉnh khác nhau.
|
|
113
|
+
|
|
114
|
+
Ví dụ:
|
|
115
|
+
|
|
116
|
+
```js
|
|
117
|
+
const { verifyXaName } = require("@isofh/chuyen-doi-dia-chi-2-cap");
|
|
118
|
+
|
|
119
|
+
console.log(verifyXaName("Cửa Nam", "Hà Nội"));
|
|
120
|
+
console.log(verifyXaName("Xuân Thành", "Đồng Nai"));
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Kết quả trả về có dạng:
|
|
124
|
+
|
|
125
|
+
```js
|
|
126
|
+
{
|
|
127
|
+
input: "Xuân Thành",
|
|
128
|
+
normalizedInput: "xuanthanh",
|
|
129
|
+
isValid: true,
|
|
130
|
+
matches: [
|
|
131
|
+
{
|
|
132
|
+
matchType: "current",
|
|
133
|
+
tenXa: "Xuân Thành",
|
|
134
|
+
tenTinh: "Đồng Nai"
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
matchType: "satNhapTu",
|
|
138
|
+
tenXa: "Long Khánh",
|
|
139
|
+
tenTinh: "Đồng Nai",
|
|
140
|
+
tenXaCu: "Xuân Thành"
|
|
141
|
+
}
|
|
142
|
+
]
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
`options` hỗ trợ:
|
|
147
|
+
|
|
148
|
+
- `dataXa`: truyền bộ dữ liệu khác nếu caller muốn override
|
|
149
|
+
|
|
150
|
+
Ngoài export thường, package cũng tự mount sẵn các hàm này lên `globalThis` khi được require:
|
|
151
|
+
|
|
152
|
+
```js
|
|
153
|
+
globalThis.verifyXaName;
|
|
154
|
+
globalThis.splitAddressByValidXa;
|
|
155
|
+
globalThis.extractAndConvertCccdAddress;
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Mục đích là để một package khác như `mainam-react-native-string-utils` có thể tận dụng runtime function này mà không phải tạo dependency ngược.
|
|
159
|
+
|
|
160
|
+
## Trích xuất địa chỉ căn cước
|
|
161
|
+
|
|
162
|
+
`parseCccdQrString` dùng để parse chuỗi QR CCCD dạng đang được app HIS quét vào, ví dụ:
|
|
163
|
+
|
|
164
|
+
```txt
|
|
165
|
+
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
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Hàm sẽ tách ra các field chuẩn như số giấy tờ, họ tên, ngày sinh, giới tính, địa chỉ, ngày cấp.
|
|
169
|
+
|
|
170
|
+
`extractCccdAddressText` dùng để lấy đúng field địa chỉ từ chuỗi QR CCCD dạng pipe.
|
|
171
|
+
|
|
172
|
+
Ví dụ:
|
|
173
|
+
|
|
174
|
+
```js
|
|
175
|
+
const { extractCccdAddressText } = require("@isofh/chuyen-doi-dia-chi-2-cap");
|
|
176
|
+
|
|
177
|
+
console.log(extractCccdAddressText("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"));
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
`extractAndConvertCccdAddress` là hàm mức cao để:
|
|
181
|
+
|
|
182
|
+
- lấy field địa chỉ từ QR căn cước
|
|
183
|
+
- parse theo logic `toAddress`
|
|
184
|
+
- convert phần địa chỉ hành chính về format mới bằng `convertDiaChiMoi`
|
|
185
|
+
- trả về object đúng shape của `String.prototype.toAddress`
|
|
186
|
+
|
|
187
|
+
Ví dụ:
|
|
188
|
+
|
|
189
|
+
```js
|
|
190
|
+
const { extractAndConvertCccdAddress } = require("@isofh/chuyen-doi-dia-chi-2-cap");
|
|
191
|
+
|
|
192
|
+
console.log(
|
|
193
|
+
extractAndConvertCccdAddress(
|
|
194
|
+
"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"
|
|
195
|
+
)
|
|
196
|
+
);
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
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
|
+
|
|
201
|
+
## Tách số nhà dựa trên xã hợp lệ
|
|
202
|
+
|
|
203
|
+
Ý tưởng của hàm `splitAddressByValidXa` là:
|
|
204
|
+
|
|
205
|
+
- nếu một phần tử không phải xã hợp lệ
|
|
206
|
+
- nhưng phần tử đứng sau nó lại là xã hợp lệ trong tỉnh tương ứng
|
|
207
|
+
- thì phần tử không hợp lệ phía trước sẽ được coi là `soNha`
|
|
208
|
+
|
|
209
|
+
Ví dụ:
|
|
210
|
+
|
|
211
|
+
```js
|
|
212
|
+
const { splitAddressByValidXa } = require("@isofh/chuyen-doi-dia-chi-2-cap");
|
|
213
|
+
|
|
214
|
+
console.log(splitAddressByValidXa("Phú Thạch, Phú Trung, Đồng Nai", "Đồng Nai"));
|
|
215
|
+
console.log(splitAddressByValidXa("4A Lê Thánh Tông, Cửa Nam, Hà Nội", "Hà Nội"));
|
|
216
|
+
console.log(splitAddressByValidXa("Tổ 6, Quang Trung, Phủ Lý, Hà Nam", "Hà Nam"));
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Kết quả kỳ vọng:
|
|
220
|
+
|
|
221
|
+
```js
|
|
222
|
+
{
|
|
223
|
+
soNha: "Phú Thạch",
|
|
224
|
+
diaChi: "Phú Trung, Đồng Nai"
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Hàm sẽ dò từ trái sang phải và chọn xã hợp lệ đầu tiên trong tỉnh đích. Toàn bộ phần đứng trước xã đó sẽ được coi là `soNha`.
|
|
229
|
+
|
|
230
|
+
## Dependency string utils
|
|
231
|
+
|
|
232
|
+
Package này đang `require("mainam-react-native-string-utils")` để dùng lại các helper string đã có sẵn như `createUniqueText`, tránh viết lại logic normalize ở nhiều nơi.
|
|
233
|
+
|
|
234
|
+
Vì vậy package cần khai báo đúng dependency này trong `package.json`.
|
|
235
|
+
|
|
236
|
+
## Export dữ liệu
|
|
237
|
+
|
|
238
|
+
```js
|
|
239
|
+
const { dataXa } = require("@isofh/chuyen-doi-dia-chi-2-cap");
|
|
240
|
+
|
|
241
|
+
console.log(dataXa.length);
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Nguồn dữ liệu
|
|
245
|
+
|
|
246
|
+
- `dataXa.json` là bộ dữ liệu hành chính dùng cho logic chuyển đổi địa chỉ
|
|
247
|
+
|
|
248
|
+
## Ghi chú
|
|
249
|
+
|
|
250
|
+
- package ưu tiên giữ behavior ổn định theo các case nghiệp vụ thực tế
|
|
251
|
+
- có thể tiếp tục mở rộng thêm test case khi phát sinh dữ liệu mới
|