feat: insert province district sub-district into db

This commit is contained in:
Methapon Metanipat 2024-08-29 17:10:44 +07:00
parent 09cb20c57d
commit 23717bacaf
3 changed files with 7584 additions and 0 deletions

7437
assets/thailand-area.csv Normal file

File diff suppressed because it is too large Load diff

View file

@ -8,6 +8,7 @@ import morgan from "./middlewares/morgan";
import { RegisterRoutes } from "./routes";
import { addUserRoles, createUser, getRoleByName, listUser } from "./services/keycloak";
import prisma from "./db";
import { initThailandAreaDatabase } from "./utils/thailand-area";
const APP_HOST = process.env.APP_HOST || "0.0.0.0";
const APP_PORT = +(process.env.APP_PORT || 3000);
@ -15,6 +16,8 @@ const APP_PORT = +(process.env.APP_PORT || 3000);
(async () => {
const app = express();
await initThailandAreaDatabase();
let users = await (async () => {
let list = await listUser();
while (!list) {

144
src/utils/thailand-area.ts Normal file
View file

@ -0,0 +1,144 @@
import { parseFile } from "@fast-csv/parse";
import prisma from "../db";
export async function initThailandAreaDatabase() {
const data = await new Promise<Record<string, string>[]>((resolve, reject) => {
const r: Record<string, string>[] = [];
const stream = parseFile("./assets/thailand-area.csv", { headers: true });
stream.on("data", (v) => r.push(v));
stream.on("error", (e) => reject(e));
stream.on("end", () => resolve(r));
}).catch((e) => console.error(e));
if (!data) return;
type Base = { id: string; name: string; nameEN: string };
const province: Base[] = [];
const district: (Base & { provinceId: string })[] = [];
const subDistrict: (Base & { zipCode: string; districtId: string })[] = [];
data.forEach((record) => {
const provinceId = record["TambonID"].slice(0, 2);
const districtId = record["TambonID"].slice(0, 4);
const subDistrictId = record["TambonID"];
if (!province.find((v) => v.id === provinceId)) {
province.push({
id: provinceId,
name: record["ProvinceThai"],
nameEN: record["ProvinceEng"],
});
}
if (!district.find((v) => v.id === districtId)) {
district.push({
id: districtId,
name: record["DistrictThaiShort"],
nameEN: record["DistrictEngShort"],
provinceId,
});
}
if (!subDistrict.find((v) => v.id === subDistrictId)) {
subDistrict.push({
id: subDistrictId,
name: record["DistrictThaiShort"],
nameEN: record["DistrictEngShort"],
zipCode: record["PostCodeMain"],
districtId,
});
}
});
function splitChunk<DataType, ResponseType>(
array: DataType[],
chunkSize: number,
callback: (data: DataType[]) => ResponseType,
) {
const result: ReturnType<typeof callback>[] = [];
for (let i = 0; i < array.length; i += chunkSize) {
result.push(callback(array.slice(i, i + chunkSize)));
}
return result;
}
await prisma.$transaction(async (tx) => {
const meta = {
createdBy: null,
createdAt: new Date(),
updatedBy: null,
updatedAt: new Date(),
};
await Promise.all(
splitChunk(province, 1000, async (r) => {
return await tx.$kysely
.insertInto("Province")
.columns(["id", "name", "nameEN", "createdBy", "createdAt", "updatedBy", "updatedAt"])
.values(r.map((v) => ({ ...v, ...meta })))
.onConflict((oc) =>
oc.column("id").doUpdateSet({
name: (eb) => eb.ref("excluded.name"),
nameEN: (eb) => eb.ref("excluded.nameEN"),
updatedAt: (eb) => eb.ref("excluded.updatedAt"),
}),
)
.execute();
}),
);
await Promise.all(
splitChunk(district, 2000, async (r) => {
return await tx.$kysely
.insertInto("District")
.columns([
"id",
"name",
"nameEN",
"provinceId",
"createdBy",
"createdAt",
"updatedBy",
"updatedAt",
])
.values(r.map((v) => ({ ...v, ...meta })))
.onConflict((oc) =>
oc.column("id").doUpdateSet({
name: (eb) => eb.ref("excluded.name"),
nameEN: (eb) => eb.ref("excluded.nameEN"),
provinceId: (eb) => eb.ref("excluded.provinceId"),
updatedAt: (eb) => eb.ref("excluded.updatedAt"),
}),
)
.execute();
}),
);
await Promise.all(
splitChunk(subDistrict, 1000, async (r) => {
return await tx.$kysely
.insertInto("SubDistrict")
.columns([
"id",
"name",
"nameEN",
"districtId",
"createdBy",
"createdAt",
"updatedBy",
"updatedAt",
])
.values(r.map((v) => ({ ...v, ...meta })))
.onConflict((oc) =>
oc.column("id").doUpdateSet({
name: (eb) => eb.ref("excluded.name"),
nameEN: (eb) => eb.ref("excluded.nameEN"),
districtId: (eb) => eb.ref("excluded.districtId"),
updatedAt: (eb) => eb.ref("excluded.updatedAt"),
}),
)
.execute();
}),
);
});
}