@isofh/chuyen-doi-dia-chi-2-cap
v1.0.7
Published
Chuan hoa dia chi hanh chinh cu sang format 2 cap moi
Maintainers
Readme
@isofh/chuyen-doi-dia-chi-2-cap
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.
Mục tiêu
- cung cấp bộ dữ liệu hành chính dùng cho chuẩn hóa địa chỉ
- 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
- đóng gói thành npm package để dùng lại giữa nhiều dự án
Cài đặt
npm install @isofh/chuyen-doi-dia-chi-2-capAPI
Package export các thành phần sau:
convertDiaChiMoi(input, options?)verifyXaName(tenXa, tinh?, options?)splitAddressByValidXa(input, tinh?, options?)parseCccdQrString(input)extractCccdAddressText(input)extractAndConvertCccdAddress(input, ngayCap?, options?)dataXacreateUniqueText(text)stripAdministrativePrefix(text)normalizeAdministrativeCode(text)
Cách dùng cơ bản
const {
convertDiaChiMoi,
verifyXaName,
splitAddressByValidXa,
extractAndConvertCccdAddress,
} = require("@isofh/chuyen-doi-dia-chi-2-cap");
const verifyResult = verifyXaName("Xuân Thành", "Đồng Nai");
console.log(verifyResult.isValid);
const splitResult = splitAddressByValidXa("Phú Thạch, Phú Trung, Đồng Nai", "Đồng Nai");
console.log(splitResult);
(async () => {
const output = await convertDiaChiMoi("Xuân Thành, Xuân Lộc, Đồng Nai");
console.log(output);
const cccdResult = await extractAndConvertCccdAddress(
"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"
);
console.log(cccdResult.soNha);
console.log(cccdResult.diaChi);
})();Input hỗ trợ
convertDiaChiMoi nhận:
- chuỗi địa chỉ hành chính, ví dụ
"Xuân Thành, Xuân Lộc, Đồng Nai" - hoặc mảng các phần tử địa chỉ, ví dụ
['Xuân Thành', 'Xuân Lộc', 'Đồng Nai'] - ngoài ra hàm cũng cố gắng tự bóc đuôi hành chính nếu input có kèm
số nhà, tên đường, quốc gia...
Lưu ý quan trọng
Hàm này ưu tiên xử lý phần địa chỉ hành chính.
Nếu input gốc có cả số nhà, tên đường, khu phố..., hàm sẽ cố gắng nhận diện đuôi hành chính hợp lệ để convert. Dù vậy, trong các case nhập liệu quá nhiễu hoặc thiếu tỉnh/xã rõ ràng, caller vẫn nên tách phần hành chính trước khi gọi để đảm bảo độ chính xác cao nhất.
Ví dụ:
const fullAddress = "4A Lê Thánh Tông, Cửa Nam, Hà Nội";
// Caller tự chuẩn hóa/tách phần hành chính trước
const administrativeAddress = "Cửa Nam, Hà Nội";
(async () => {
const output = await convertDiaChiMoi(administrativeAddress);
console.log(output);
})();Nguyên tắc xử lý
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.
Thứ tự xử lý chính:
- Match tỉnh trước bằng tên mới hoặc tên cũ trong
dsTinh. - Nếu input là 3 vế thì ưu tiên hiểu là
xã/phường, huyện/quận, tỉnh/thànhvà chỉ giữ xã + tỉnh để đưa về 2 cấp. - Tìm xã/phường theo thứ tự từ chặt đến lỏng:
- match chính xác tên xã hiện tại
- match trong
satNhapTu - match gần đúng trong
satNhapTu - fallback về match chính xác tên xã hiện tại nhưng bỏ điều kiện huyện
Ví dụ
const { convertDiaChiMoi } = require("@isofh/chuyen-doi-dia-chi-2-cap");
(async () => {
console.log(await convertDiaChiMoi("Xuân Thành, Xuân Lộc, Đồng Nai"));
console.log(await convertDiaChiMoi("Cửa Nam, Hà Nội"));
console.log(await convertDiaChiMoi(["Phú Thạch", "Phú Trung", "Đồng Nai"]));
})();Verify tên xã
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:
- tên xã hiện tại trong
dsXa - tên xã cũ trong
satNhapTu
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.
Ví dụ:
const { verifyXaName } = require("@isofh/chuyen-doi-dia-chi-2-cap");
console.log(verifyXaName("Cửa Nam", "Hà Nội"));
console.log(verifyXaName("Xuân Thành", "Đồng Nai"));Kết quả trả về có dạng:
{
input: "Xuân Thành",
normalizedInput: "xuanthanh",
isValid: true,
matches: [
{
matchType: "current",
tenXa: "Xuân Thành",
tenTinh: "Đồng Nai"
},
{
matchType: "satNhapTu",
tenXa: "Long Khánh",
tenTinh: "Đồng Nai",
tenXaCu: "Xuân Thành"
}
]
}options hỗ trợ:
dataXa: truyền bộ dữ liệu khác nếu caller muốn override
Ngoài export thường, package cũng tự mount sẵn các hàm này lên globalThis khi được require:
globalThis.verifyXaName;
globalThis.splitAddressByValidXa;
globalThis.extractAndConvertCccdAddress;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.
Trích xuất địa chỉ căn cước
parseCccdQrString dùng để parse chuỗi QR CCCD dạng pipe, ví dụ:
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|26012022Hà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.
extractCccdAddressText dùng để lấy đúng field địa chỉ từ chuỗi QR CCCD dạng pipe.
Ví dụ:
const { extractCccdAddressText } = require("@isofh/chuyen-doi-dia-chi-2-cap");
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"));extractAndConvertCccdAddress là hàm mức cao để:
- lấy field địa chỉ từ QR căn cước
- parse theo logic
toAddress - convert phần địa chỉ hành chính về format mới bằng
convertDiaChiMoi - trả về object đúng shape của
String.prototype.toAddress - giữ lại
soNhaở top-level output - bổ sung
data.soNhavàdata.diaChiGocđể caller có thể dùng lại dữ liệu trước và sau bước convert
Ví dụ:
const { extractAndConvertCccdAddress } = require("@isofh/chuyen-doi-dia-chi-2-cap");
(async () => {
console.log(
await extractAndConvertCccdAddress(
"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"
)
);
})();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.
Ví dụ output rút gọn:
{
soNha: "19/20 Tổ 71, Khu, Phố 6",
diaChi: "Tân Hòa, Hồ Chí Minh",
data: {
soNha: "19/20 Tổ 71, Khu, Phố 6",
diaChiGoc: "06, Tân Bình, TP.Hồ Chí Minh",
convertedDiaChi: "Tân Hòa, Hồ Chí Minh"
}
}Tách số nhà dựa trên xã hợp lệ
Ý tưởng của hàm splitAddressByValidXa là:
- nếu một phần tử không phải xã hợp lệ
- nhưng phần tử đứng sau nó lại là xã hợp lệ trong tỉnh tương ứng
- thì phần tử không hợp lệ phía trước sẽ được coi là
soNha
Ví dụ:
const { splitAddressByValidXa } = require("@isofh/chuyen-doi-dia-chi-2-cap");
console.log(splitAddressByValidXa("Phú Thạch, Phú Trung, Đồng Nai", "Đồng Nai"));
console.log(splitAddressByValidXa("4A Lê Thánh Tông, Cửa Nam, Hà Nội", "Hà Nội"));
console.log(splitAddressByValidXa("Tổ 6, Quang Trung, Phủ Lý, Hà Nam", "Hà Nam"));Kết quả kỳ vọng:
{
soNha: "Phú Thạch",
diaChi: "Phú Trung, Đồng Nai"
}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.
Dependency string utils
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.
Vì vậy package cần khai báo đúng dependency này trong package.json.
Export dữ liệu
const { dataXa } = require("@isofh/chuyen-doi-dia-chi-2-cap");
console.log(dataXa.length);Nguồn dữ liệu
dataXa.jsonlà bộ dữ liệu hành chính dùng cho logic chuyển đổi địa chỉ
Ghi chú
- package ưu tiên giữ behavior ổn định theo các case nghiệp vụ thực tế
- có thể tiếp tục mở rộng thêm test case khi phát sinh dữ liệu mới
