feat: employment office (#5)

* feat: add table employment office

* feat: add tag

* feat: add employment office

* chore: migrations

* feat: order employment office

* feat: delete old employment office when special got added
This commit is contained in:
Methapon Metanipat 2024-11-14 15:10:58 +07:00 committed by GitHub
parent 22b3981aa7
commit 401d376a63
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 171 additions and 1 deletions

View file

@ -0,0 +1,26 @@
-- CreateTable
CREATE TABLE "EmploymentOffice" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"nameEN" TEXT NOT NULL,
"provinceId" TEXT NOT NULL,
CONSTRAINT "EmploymentOffice_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "EmploymentOfficeDistrict" (
"areaId" TEXT NOT NULL,
"districtId" TEXT NOT NULL,
CONSTRAINT "EmploymentOfficeDistrict_pkey" PRIMARY KEY ("areaId","districtId")
);
-- AddForeignKey
ALTER TABLE "EmploymentOffice" ADD CONSTRAINT "EmploymentOffice_provinceId_fkey" FOREIGN KEY ("provinceId") REFERENCES "Province"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "EmploymentOfficeDistrict" ADD CONSTRAINT "EmploymentOfficeDistrict_areaId_fkey" FOREIGN KEY ("areaId") REFERENCES "EmploymentOffice"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "EmploymentOfficeDistrict" ADD CONSTRAINT "EmploymentOfficeDistrict_districtId_fkey" FOREIGN KEY ("districtId") REFERENCES "District"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

View file

@ -164,6 +164,7 @@ model Province {
customerBranchCitizen CustomerBranchCitizen[]
customerBranchHouseRegis CustomerBranchHouseRegis[]
institution Institution[]
employmentOffice EmploymentOffice[]
}
model District {
@ -187,6 +188,7 @@ model District {
customerBranchCitizen CustomerBranchCitizen[]
customerBranchHouseRegis CustomerBranchHouseRegis[]
institution Institution[]
employmentOffice EmploymentOfficeDistrict[]
}
model SubDistrict {
@ -212,6 +214,28 @@ model SubDistrict {
institution Institution[]
}
model EmploymentOffice {
id String @id @default(cuid())
name String
nameEN String
provinceId String
province Province @relation(fields: [provinceId], references: [id])
district EmploymentOfficeDistrict[]
}
model EmploymentOfficeDistrict {
areaId String
area EmploymentOffice @relation(fields: [areaId], references: [id])
districtId String
district District @relation(fields: [districtId], references: [id])
@@id([areaId, districtId])
}
enum Status {
CREATED
ACTIVE

View file

@ -4,7 +4,7 @@ import express, { json, urlencoded } from "express";
import error from "./middlewares/error";
import morgan from "./middlewares/morgan";
import { RegisterRoutes } from "./routes";
import { initThailandAreaDatabase } from "./utils/thailand-area";
import { initEmploymentOffice, initThailandAreaDatabase } from "./utils/thailand-area";
import { initFirstAdmin } from "./utils/database";
import { apiReference } from "@scalar/express-api-reference";
import { initSchedule } from "./services/schedule";
@ -17,6 +17,7 @@ const APP_PORT = +(process.env.APP_PORT || 3000);
await initThailandAreaDatabase();
await initFirstAdmin();
await initEmploymentOffice();
initSchedule();

View file

@ -0,0 +1,28 @@
import { Controller, Get, Query, Route, Tags } from "tsoa";
import prisma from "../db";
@Route("/api/v1/employment-office")
@Tags("Employment Office")
export class EmploymentOfficeController extends Controller {
@Get()
async getEmploymentOfficeList(@Query() districtId?: string) {
return await prisma.employmentOffice.findMany({
where: {
OR: [
{
province: {
district: { some: { id: districtId } },
},
district: { none: {} },
},
{
district: {
some: { districtId },
},
},
],
},
orderBy: [{ provinceId: "asc" }, { id: "asc" }],
});
}
}

View file

@ -141,4 +141,94 @@ export async function initThailandAreaDatabase() {
}),
);
});
console.log("[INFO]: Sync thailand province, district and subdistrict, OK.");
}
export async function initEmploymentOffice() {
const name = (provinceName: string) => `สำนักงานจัดหางานจังหวัด${provinceName}`;
const nameEN = (provinceNameEN: string) => `${provinceNameEN} Employment Office`;
const nameSpecial = (provinceName: string, areaNo: number) =>
`สำนักงานจัดหางาน${provinceName} พื้นที่ ${areaNo}`;
const nameSpecialEN = (provinceNameEN: string, areaNo: number) =>
`${provinceNameEN} Employment Office Area ${areaNo}`;
const special: Record<string, { [key: string]: string[] }> = {
"10": {
"1": ["1004", "1007", "1012", "1028", "1031"],
"2": ["1021", "1024", "1035", "1049", "1050"],
"3": ["1009", "1032", "1033", "1034", "1039", "1047"],
"4": ["1006", "1038", "1043", "1027", "1045"],
"5": ["1003", "1010", "1011", "1042", "1044", "1046"],
"6": ["1015", "1016", "1018", "1020", "1025"],
"7": ["1019", "1022", "1023", "1040", "1048"],
"8": ["1001", "1002", "1008", "1013"],
"9": ["1005", "1029", "1030", "1041"],
"10": ["1014", "1017", "1026", "1036", "1037"],
},
};
const list = await prisma.province.findMany();
await prisma.$transaction(async (tx) => {
await Promise.all(
list
.map(async (province) => {
if (special[province.id]) {
await tx.employmentOffice.deleteMany({
where: { provinceId: province.id, district: { none: {} } },
});
return Object.entries(special[province.id]).map(([key, val]) => {
const id = province.id + "-" + key.padStart(2, "0");
return tx.employmentOffice.upsert({
where: { id },
create: {
id,
name: nameSpecial(province.name, +key),
nameEN: nameSpecialEN(province.nameEN, +key),
provinceId: province.id,
district: {
createMany: {
data: val.map((districtId) => ({ districtId })),
skipDuplicates: true,
},
},
},
update: {
id,
name: nameSpecial(province.name, +key),
nameEN: nameSpecialEN(province.nameEN, +key),
provinceId: province.id,
district: {
deleteMany: { districtId: { notIn: val } },
createMany: {
data: val.map((districtId) => ({ districtId })),
skipDuplicates: true,
},
},
},
});
});
}
return tx.employmentOffice.upsert({
where: { id: province.id },
create: {
id: province.id,
name: name(province.name),
nameEN: nameEN(province.nameEN),
provinceId: province.id,
},
update: {
name: name(province.name),
nameEN: nameEN(province.nameEN),
provinceId: province.id,
},
});
})
.flat(),
);
});
console.log("[INFO]: Sync employment office, OK.");
}

View file

@ -21,6 +21,7 @@
{ "name": "Notification" },
{ "name": "Permission" },
{ "name": "Address" },
{ "name": "Employment Office" },
{ "name": "Branch" },
{ "name": "User" },
{ "name": "Branch User" },