refactor: employee
This commit is contained in:
parent
77739da154
commit
c51a403f2a
7 changed files with 637 additions and 277 deletions
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `entryDate` on the `Employee` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `passportExpiryDate` on the `Employee` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `passportIssueDate` on the `Employee` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `passportIssuingCountry` on the `Employee` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `passportIssuingPlace` on the `Employee` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `passportNumber` on the `Employee` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `passportType` on the `Employee` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `previousPassportReference` on the `Employee` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `tm6Number` on the `Employee` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `visaExpiryDate` on the `Employee` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `visaIssueDate` on the `Employee` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `visaIssuingPlace` on the `Employee` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `visaNumber` on the `Employee` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `visaStayUntilDate` on the `Employee` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `visaType` on the `Employee` table. All the data in the column will be lost.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "Employee" DROP COLUMN "entryDate",
|
||||
DROP COLUMN "passportExpiryDate",
|
||||
DROP COLUMN "passportIssueDate",
|
||||
DROP COLUMN "passportIssuingCountry",
|
||||
DROP COLUMN "passportIssuingPlace",
|
||||
DROP COLUMN "passportNumber",
|
||||
DROP COLUMN "passportType",
|
||||
DROP COLUMN "previousPassportReference",
|
||||
DROP COLUMN "tm6Number",
|
||||
DROP COLUMN "visaExpiryDate",
|
||||
DROP COLUMN "visaIssueDate",
|
||||
DROP COLUMN "visaIssuingPlace",
|
||||
DROP COLUMN "visaNumber",
|
||||
DROP COLUMN "visaStayUntilDate",
|
||||
DROP COLUMN "visaType",
|
||||
ADD COLUMN "workerType" TEXT;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "EmployeePassport" (
|
||||
"id" TEXT NOT NULL,
|
||||
"number" TEXT NOT NULL,
|
||||
"type" TEXT NOT NULL,
|
||||
"issueDate" DATE NOT NULL,
|
||||
"expireDate" DATE NOT NULL,
|
||||
"issueCountry" TEXT NOT NULL,
|
||||
"issuePlace" TEXT NOT NULL,
|
||||
"previousPassportRef" TEXT,
|
||||
"employeeId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "EmployeePassport_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "EmployeeVisa" (
|
||||
"id" TEXT NOT NULL,
|
||||
"number" TEXT NOT NULL,
|
||||
"type" TEXT NOT NULL,
|
||||
"entryCount" INTEGER NOT NULL,
|
||||
"issueCountry" TEXT NOT NULL,
|
||||
"issuePlace" TEXT NOT NULL,
|
||||
"issueDate" DATE NOT NULL,
|
||||
"expireDate" DATE NOT NULL,
|
||||
"mrz" TEXT,
|
||||
"remark" TEXT,
|
||||
"employeeId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "EmployeeVisa_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "EmployeeInCountryNotice" (
|
||||
"id" TEXT NOT NULL,
|
||||
"noticeNumber" TEXT NOT NULL,
|
||||
"noticeDate" TEXT NOT NULL,
|
||||
"nextNoticeDate" DATE NOT NULL,
|
||||
"tmNumber" TEXT NOT NULL,
|
||||
"entryDate" DATE NOT NULL,
|
||||
"travelBy" TEXT NOT NULL,
|
||||
"travelFrom" TEXT NOT NULL,
|
||||
"employeeId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "EmployeeInCountryNotice_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "EmployeePassport" ADD CONSTRAINT "EmployeePassport_employeeId_fkey" FOREIGN KEY ("employeeId") REFERENCES "Employee"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "EmployeeVisa" ADD CONSTRAINT "EmployeeVisa_employeeId_fkey" FOREIGN KEY ("employeeId") REFERENCES "Employee"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "EmployeeInCountryNotice" ADD CONSTRAINT "EmployeeInCountryNotice_employeeId_fkey" FOREIGN KEY ("employeeId") REFERENCES "Employee"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
|
@ -552,22 +552,7 @@ model Employee {
|
|||
subDistrict SubDistrict? @relation(fields: [subDistrictId], references: [id], onDelete: SetNull)
|
||||
subDistrictId String?
|
||||
|
||||
passportType String
|
||||
passportNumber String
|
||||
passportIssueDate DateTime @db.Date
|
||||
passportExpiryDate DateTime @db.Date
|
||||
passportIssuingCountry String
|
||||
passportIssuingPlace String
|
||||
previousPassportReference String?
|
||||
|
||||
visaType String?
|
||||
visaNumber String?
|
||||
visaIssueDate DateTime? @db.Date
|
||||
visaExpiryDate DateTime? @db.Date
|
||||
visaIssuingPlace String?
|
||||
visaStayUntilDate DateTime? @db.Date
|
||||
tm6Number String?
|
||||
entryDate DateTime? @db.Date
|
||||
workerType String?
|
||||
workerStatus String?
|
||||
|
||||
customerBranch CustomerBranch @relation(fields: [customerBranchId], references: [id], onDelete: Cascade)
|
||||
|
|
@ -584,6 +569,9 @@ model Employee {
|
|||
updatedBy User? @relation(name: "EmployeeUpdatedByUser", fields: [updatedByUserId], references: [id], onDelete: SetNull)
|
||||
updatedByUserId String?
|
||||
|
||||
employeePassport EmployeePassport[]
|
||||
employeeVisa EmployeeVisa[]
|
||||
employeeInCountryNotice EmployeeInCountryNotice[]
|
||||
employeeCheckup EmployeeCheckup[]
|
||||
employeeWork EmployeeWork[]
|
||||
employeeOtherInfo EmployeeOtherInfo?
|
||||
|
|
@ -606,6 +594,63 @@ model EmployeeHistory {
|
|||
master Employee @relation(fields: [masterId], references: [id], onDelete: Cascade)
|
||||
}
|
||||
|
||||
model EmployeePassport {
|
||||
id String @id @default(cuid())
|
||||
|
||||
number String
|
||||
type String
|
||||
issueDate DateTime @db.Date
|
||||
expireDate DateTime @db.Date
|
||||
issueCountry String
|
||||
issuePlace String
|
||||
previousPassportRef String?
|
||||
|
||||
employee Employee @relation(fields: [employeeId], references: [id])
|
||||
employeeId String
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model EmployeeVisa {
|
||||
id String @id @default(cuid())
|
||||
|
||||
number String
|
||||
type String
|
||||
entryCount Int
|
||||
issueCountry String
|
||||
issuePlace String
|
||||
issueDate DateTime @db.Date
|
||||
expireDate DateTime @db.Date
|
||||
mrz String?
|
||||
remark String?
|
||||
|
||||
employee Employee @relation(fields: [employeeId], references: [id])
|
||||
employeeId String
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model EmployeeInCountryNotice {
|
||||
id String @id @default(cuid())
|
||||
|
||||
noticeNumber String
|
||||
noticeDate String
|
||||
nextNoticeDate DateTime @db.Date
|
||||
tmNumber String
|
||||
|
||||
entryDate DateTime @db.Date
|
||||
travelBy String
|
||||
travelFrom String
|
||||
|
||||
employee Employee @relation(fields: [employeeId], references: [id])
|
||||
employeeId String
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model EmployeeCheckup {
|
||||
id String @id @default(cuid())
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import {
|
|||
} from "../services/permission";
|
||||
import { connectOrDisconnect, connectOrNot, whereAddressQuery } from "../utils/relation";
|
||||
import { notFoundError, relationError } from "../utils/error";
|
||||
import { deleteFile, fileLocation, getFile, listFile, setFile } from "../utils/minio";
|
||||
import { deleteFile, deleteFolder, fileLocation, getFile, listFile, setFile } from "../utils/minio";
|
||||
|
||||
if (!process.env.MINIO_BUCKET) {
|
||||
throw Error("Require MinIO bucket.");
|
||||
|
|
@ -77,69 +77,13 @@ type EmployeeCreate = {
|
|||
street?: string | null;
|
||||
streetEN?: string | null;
|
||||
|
||||
passportType: string;
|
||||
passportNumber: string;
|
||||
passportIssueDate: Date;
|
||||
passportExpiryDate: Date;
|
||||
passportIssuingCountry: string;
|
||||
passportIssuingPlace: string;
|
||||
previousPassportReference?: string;
|
||||
|
||||
visaType?: string | null;
|
||||
visaNumber?: string | null;
|
||||
visaIssueDate?: Date | null;
|
||||
visaExpiryDate?: Date | null;
|
||||
visaIssuingPlace?: string | null;
|
||||
visaStayUntilDate?: Date | null;
|
||||
tm6Number?: string | null;
|
||||
entryDate?: Date | null;
|
||||
workerStatus?: string | null;
|
||||
|
||||
subDistrictId?: string | null;
|
||||
districtId?: string | null;
|
||||
provinceId?: string | null;
|
||||
|
||||
workerType?: string | null;
|
||||
workerStatus?: string | null;
|
||||
selectedImage?: string | null;
|
||||
|
||||
employeeWork?: {
|
||||
ownerName?: string | null;
|
||||
positionName?: string | null;
|
||||
jobType?: string | null;
|
||||
workplace?: string | null;
|
||||
workPermitNo?: string | null;
|
||||
workPermitIssuDate?: Date | null;
|
||||
workPermitExpireDate?: Date | null;
|
||||
workEndDate?: Date | null;
|
||||
remark?: string | null;
|
||||
}[];
|
||||
|
||||
employeeCheckup?: {
|
||||
checkupType?: string | null;
|
||||
checkupResult?: string | null;
|
||||
|
||||
provinceId?: string | null;
|
||||
|
||||
hospitalName?: string | null;
|
||||
remark?: string | null;
|
||||
medicalBenefitScheme?: string | null;
|
||||
insuranceCompany?: string | null;
|
||||
coverageStartDate?: Date | null;
|
||||
coverageExpireDate?: Date | null;
|
||||
}[];
|
||||
|
||||
employeeOtherInfo?: {
|
||||
citizenId?: string | null;
|
||||
fatherFirstName?: string | null;
|
||||
fatherLastName?: string | null;
|
||||
fatherBirthPlace?: string | null;
|
||||
motherFirstName?: string | null;
|
||||
motherLastName?: string | null;
|
||||
motherBirthPlace?: string | null;
|
||||
|
||||
fatherFirstNameEN?: string | null;
|
||||
fatherLastNameEN?: string | null;
|
||||
motherFirstNameEN?: string | null;
|
||||
motherLastNameEN?: string | null;
|
||||
};
|
||||
};
|
||||
|
||||
type EmployeeUpdate = {
|
||||
|
|
@ -169,71 +113,13 @@ type EmployeeUpdate = {
|
|||
street?: string | null;
|
||||
streetEN?: string | null;
|
||||
|
||||
passportType?: string;
|
||||
passportNumber?: string;
|
||||
passportIssueDate?: Date;
|
||||
passportExpiryDate?: Date;
|
||||
passportIssuingCountry?: string;
|
||||
passportIssuingPlace?: string;
|
||||
previousPassportReference?: string;
|
||||
|
||||
visaType?: string | null;
|
||||
visaNumber?: string | null;
|
||||
visaIssueDate?: Date | null;
|
||||
visaExpiryDate?: Date | null;
|
||||
visaIssuingPlace?: string | null;
|
||||
visaStayUntilDate?: Date | null;
|
||||
tm6Number?: string | null;
|
||||
entryDate?: Date | null;
|
||||
workerType?: string | null;
|
||||
workerStatus?: string | null;
|
||||
selectedImage?: string | null;
|
||||
|
||||
subDistrictId?: string | null;
|
||||
districtId?: string | null;
|
||||
provinceId?: string | null;
|
||||
|
||||
employeeWork?: {
|
||||
id?: string;
|
||||
ownerName?: string | null;
|
||||
positionName?: string | null;
|
||||
jobType?: string | null;
|
||||
workplace?: string | null;
|
||||
workPermitNo?: string | null;
|
||||
workPermitIssuDate?: Date | null;
|
||||
workPermitExpireDate?: Date | null;
|
||||
workEndDate?: Date | null;
|
||||
remark?: string | null;
|
||||
}[];
|
||||
|
||||
employeeCheckup?: {
|
||||
id?: string;
|
||||
checkupType?: string | null;
|
||||
checkupResult?: string | null;
|
||||
|
||||
provinceId?: string | null;
|
||||
|
||||
hospitalName?: string | null;
|
||||
remark?: string | null;
|
||||
medicalBenefitScheme?: string | null;
|
||||
insuranceCompany?: string | null;
|
||||
coverageStartDate?: Date | null;
|
||||
coverageExpireDate?: Date | null;
|
||||
}[];
|
||||
|
||||
employeeOtherInfo?: {
|
||||
citizenId?: string | null;
|
||||
fatherFirstName?: string | null;
|
||||
fatherLastName?: string | null;
|
||||
fatherBirthPlace?: string | null;
|
||||
motherFirstName?: string | null;
|
||||
motherLastName?: string | null;
|
||||
motherBirthPlace?: string | null;
|
||||
|
||||
fatherFirstNameEN?: string | null;
|
||||
fatherLastNameEN?: string | null;
|
||||
motherFirstNameEN?: string | null;
|
||||
motherLastNameEN?: string | null;
|
||||
};
|
||||
};
|
||||
|
||||
@Route("api/v1/employee")
|
||||
|
|
@ -306,7 +192,6 @@ export class EmployeeController extends Controller {
|
|||
{ firstNameEN: { contains: query } },
|
||||
{ lastName: { contains: query } },
|
||||
{ lastNameEN: { contains: query } },
|
||||
{ passportNumber: { contains: query } },
|
||||
...whereAddressQuery(query),
|
||||
],
|
||||
AND: {
|
||||
|
|
@ -403,35 +288,7 @@ export class EmployeeController extends Controller {
|
|||
|
||||
await permissionCheck(req.user, customerBranch.customer.registeredBranch);
|
||||
|
||||
const {
|
||||
provinceId,
|
||||
districtId,
|
||||
subDistrictId,
|
||||
customerBranchId,
|
||||
employeeWork,
|
||||
employeeCheckup,
|
||||
employeeOtherInfo,
|
||||
...rest
|
||||
} = body;
|
||||
|
||||
const listProvinceId = employeeCheckup?.reduce<string[]>((acc, cur) => {
|
||||
if (cur.provinceId && !acc.includes(cur.provinceId)) return acc.concat(cur.provinceId);
|
||||
if (!cur.provinceId) cur.provinceId = null;
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
if (listProvinceId) {
|
||||
const [listProvince] = await prisma.$transaction([
|
||||
prisma.province.findMany({ where: { id: { in: listProvinceId } } }),
|
||||
]);
|
||||
if (listProvince.length !== listProvinceId.length) {
|
||||
throw new HttpError(
|
||||
HttpStatus.BAD_REQUEST,
|
||||
"Some province cannot be found.",
|
||||
"someProvinceNotFound",
|
||||
);
|
||||
}
|
||||
}
|
||||
const { provinceId, districtId, subDistrictId, customerBranchId, ...rest } = body;
|
||||
|
||||
const record = await prisma.$transaction(
|
||||
async (tx) => {
|
||||
|
|
@ -465,23 +322,6 @@ export class EmployeeController extends Controller {
|
|||
...rest,
|
||||
statusOrder: +(rest.status === "INACTIVE"),
|
||||
code: `${customerBranch.code}-${`${new Date().getFullYear()}`.slice(-2).padStart(2, "0")}${`${last.value}`.padStart(7, "0")}`,
|
||||
employeeWork: {
|
||||
createMany: {
|
||||
data: employeeWork || [],
|
||||
},
|
||||
},
|
||||
employeeCheckup: {
|
||||
createMany: {
|
||||
data:
|
||||
employeeCheckup?.map((v) => ({
|
||||
...v,
|
||||
provinceId: !!v.provinceId ? null : v.provinceId,
|
||||
})) || [],
|
||||
},
|
||||
},
|
||||
employeeOtherInfo: {
|
||||
create: employeeOtherInfo,
|
||||
},
|
||||
province: connectOrNot(provinceId),
|
||||
district: connectOrNot(districtId),
|
||||
subDistrict: connectOrNot(subDistrictId),
|
||||
|
|
@ -568,35 +408,7 @@ export class EmployeeController extends Controller {
|
|||
await permissionCheck(req.user, customerBranch.customer.registeredBranch);
|
||||
}
|
||||
|
||||
const {
|
||||
provinceId,
|
||||
districtId,
|
||||
subDistrictId,
|
||||
customerBranchId,
|
||||
employeeWork,
|
||||
employeeCheckup,
|
||||
employeeOtherInfo,
|
||||
...rest
|
||||
} = body;
|
||||
|
||||
const listProvinceId = employeeCheckup?.reduce<string[]>((acc, cur) => {
|
||||
if (cur.provinceId && !acc.includes(cur.provinceId)) return acc.concat(cur.provinceId);
|
||||
if (!cur.provinceId) cur.provinceId = null;
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
if (listProvinceId) {
|
||||
const [listProvince] = await prisma.$transaction([
|
||||
prisma.province.findMany({ where: { id: { in: listProvinceId } } }),
|
||||
]);
|
||||
if (listProvince.length !== listProvinceId.length) {
|
||||
throw new HttpError(
|
||||
HttpStatus.BAD_REQUEST,
|
||||
"Some province cannot be found.",
|
||||
"someProvinceNotFound",
|
||||
);
|
||||
}
|
||||
}
|
||||
const { provinceId, districtId, subDistrictId, customerBranchId, ...rest } = body;
|
||||
|
||||
const record = await prisma.$transaction(async (tx) => {
|
||||
let code: string | undefined;
|
||||
|
|
@ -640,53 +452,6 @@ export class EmployeeController extends Controller {
|
|||
statusOrder: +(rest.status === "INACTIVE"),
|
||||
code,
|
||||
customerBranch: connectOrNot(customerBranchId),
|
||||
employeeWork: employeeWork
|
||||
? {
|
||||
deleteMany: {
|
||||
id: {
|
||||
notIn: employeeWork.map((v) => v.id).filter((v): v is string => !!v) || [],
|
||||
},
|
||||
},
|
||||
upsert: employeeWork.map((v) => ({
|
||||
where: { id: v.id || "" },
|
||||
create: {
|
||||
...v,
|
||||
createdByUserId: req.user.sub,
|
||||
updatedByUserId: req.user.sub,
|
||||
id: undefined,
|
||||
},
|
||||
update: {
|
||||
...v,
|
||||
updatedByUserId: req.user.sub,
|
||||
},
|
||||
})),
|
||||
}
|
||||
: undefined,
|
||||
|
||||
employeeCheckup: employeeCheckup
|
||||
? {
|
||||
deleteMany: {
|
||||
id: {
|
||||
notIn: employeeCheckup.map((v) => v.id).filter((v): v is string => !!v) || [],
|
||||
},
|
||||
},
|
||||
upsert: employeeCheckup.map((v) => ({
|
||||
where: { id: v.id || "" },
|
||||
create: {
|
||||
...v,
|
||||
provinceId: !v.provinceId ? undefined : v.provinceId,
|
||||
createdByUserId: req.user.sub,
|
||||
updatedByUserId: req.user.sub,
|
||||
id: undefined,
|
||||
},
|
||||
update: {
|
||||
...v,
|
||||
updatedByUserId: req.user.sub,
|
||||
},
|
||||
})),
|
||||
}
|
||||
: undefined,
|
||||
employeeOtherInfo: employeeOtherInfo ? { update: employeeOtherInfo } : undefined,
|
||||
province: connectOrDisconnect(provinceId),
|
||||
district: connectOrDisconnect(districtId),
|
||||
subDistrict: connectOrDisconnect(subDistrictId),
|
||||
|
|
@ -698,13 +463,7 @@ export class EmployeeController extends Controller {
|
|||
|
||||
const historyEntries: { field: string; valueBefore: string; valueAfter: string }[] = [];
|
||||
|
||||
for (const k of Object.keys(body)) {
|
||||
const field = k as keyof typeof body;
|
||||
|
||||
if (field === "employeeCheckup") continue;
|
||||
if (field === "employeeOtherInfo") continue;
|
||||
if (field === "employeeWork") continue;
|
||||
|
||||
for (const field of Object.keys(body) as (keyof typeof body)[]) {
|
||||
let valueBefore = employee[field];
|
||||
let valueAfter = body[field];
|
||||
|
||||
|
|
@ -757,6 +516,14 @@ export class EmployeeController extends Controller {
|
|||
throw new HttpError(HttpStatus.FORBIDDEN, "Employee is in used.", "employeeInUsed");
|
||||
}
|
||||
|
||||
await Promise.all([
|
||||
deleteFolder(fileLocation.employee.img(employeeId)),
|
||||
deleteFolder(fileLocation.employee.attachment(employeeId)),
|
||||
deleteFolder(fileLocation.employee.passport(employeeId)),
|
||||
deleteFolder(fileLocation.employee.visa(employeeId)),
|
||||
deleteFolder(fileLocation.employee.inCountryNotice(employeeId)),
|
||||
]);
|
||||
|
||||
return await prisma.employee.delete({
|
||||
include: {
|
||||
createdBy: true,
|
||||
|
|
@ -876,4 +643,111 @@ export class EmployeeFileController extends Controller {
|
|||
await this.checkPermission(req.user, employeeId);
|
||||
return await deleteFile(fileLocation.employee.attachment(employeeId, name));
|
||||
}
|
||||
|
||||
@Get("file-passport")
|
||||
@Security("keycloak")
|
||||
async listPassport(@Request() req: RequestWithUser, @Path() employeeId: string) {
|
||||
await this.checkPermission(req.user, employeeId);
|
||||
return await listFile(fileLocation.employee.passport(employeeId));
|
||||
}
|
||||
|
||||
@Get("file-passport/{passportId}")
|
||||
@Security("keycloak")
|
||||
async getPassport(@Path() employeeId: string, @Path() passportId: string) {
|
||||
return await getFile(fileLocation.employee.passport(employeeId, passportId));
|
||||
}
|
||||
|
||||
@Put("file-passport/{passportId}")
|
||||
@Security("keycloak")
|
||||
async putPassport(
|
||||
@Request() req: RequestWithUser,
|
||||
@Path() employeeId: string,
|
||||
@Path() passportId: string,
|
||||
) {
|
||||
await this.checkPermission(req.user, employeeId);
|
||||
return req.res?.redirect(await setFile(fileLocation.employee.passport(employeeId, passportId)));
|
||||
}
|
||||
|
||||
@Delete("file-passport/{passportId}")
|
||||
@Security("keycloak")
|
||||
async delPassport(
|
||||
@Request() req: RequestWithUser,
|
||||
@Path() employeeId: string,
|
||||
@Path() passportId: string,
|
||||
) {
|
||||
await this.checkPermission(req.user, employeeId);
|
||||
return await deleteFile(fileLocation.employee.passport(employeeId, passportId));
|
||||
}
|
||||
|
||||
@Get("file-visa")
|
||||
@Security("keycloak")
|
||||
async listVisa(@Request() req: RequestWithUser, @Path() employeeId: string) {
|
||||
await this.checkPermission(req.user, employeeId);
|
||||
return await listFile(fileLocation.employee.visa(employeeId));
|
||||
}
|
||||
|
||||
@Get("file-visa/{visaId}")
|
||||
@Security("keycloak")
|
||||
async getVisa(@Path() employeeId: string, @Path() visaId: string) {
|
||||
return await getFile(fileLocation.employee.visa(employeeId, visaId));
|
||||
}
|
||||
|
||||
@Put("file-visa/{visaId}")
|
||||
@Security("keycloak")
|
||||
async putVisa(
|
||||
@Request() req: RequestWithUser,
|
||||
@Path() employeeId: string,
|
||||
@Path() visaId: string,
|
||||
) {
|
||||
await this.checkPermission(req.user, employeeId);
|
||||
return req.res?.redirect(await setFile(fileLocation.employee.visa(employeeId, visaId)));
|
||||
}
|
||||
|
||||
@Delete("file-visa/{visaId}")
|
||||
@Security("keycloak")
|
||||
async delVisa(
|
||||
@Request() req: RequestWithUser,
|
||||
@Path() employeeId: string,
|
||||
@Path() visaId: string,
|
||||
) {
|
||||
await this.checkPermission(req.user, employeeId);
|
||||
return await deleteFile(fileLocation.employee.visa(employeeId, visaId));
|
||||
}
|
||||
|
||||
@Get("file-in-country-notice")
|
||||
@Security("keycloak")
|
||||
async listNotice(@Request() req: RequestWithUser, @Path() employeeId: string) {
|
||||
await this.checkPermission(req.user, employeeId);
|
||||
return await listFile(fileLocation.employee.inCountryNotice(employeeId));
|
||||
}
|
||||
|
||||
@Get("file-in-country-notice/{noticeId}")
|
||||
@Security("keycloak")
|
||||
async getNotice(@Path() employeeId: string, @Path() noticeId: string) {
|
||||
return await getFile(fileLocation.employee.inCountryNotice(employeeId, noticeId));
|
||||
}
|
||||
|
||||
@Put("file-in-country-notice/{noticeId}")
|
||||
@Security("keycloak")
|
||||
async putNotice(
|
||||
@Request() req: RequestWithUser,
|
||||
@Path() employeeId: string,
|
||||
@Path() noticeId: string,
|
||||
) {
|
||||
await this.checkPermission(req.user, employeeId);
|
||||
return req.res?.redirect(
|
||||
await setFile(fileLocation.employee.inCountryNotice(employeeId, noticeId)),
|
||||
);
|
||||
}
|
||||
|
||||
@Delete("file-in-country-notice/{noticeId}")
|
||||
@Security("keycloak")
|
||||
async delNotice(
|
||||
@Request() req: RequestWithUser,
|
||||
@Path() employeeId: string,
|
||||
@Path() noticeId: string,
|
||||
) {
|
||||
await this.checkPermission(req.user, employeeId);
|
||||
return await deleteFile(fileLocation.employee.inCountryNotice(employeeId, noticeId));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
116
src/controllers/03-employee-in-country-notice-controller.ts
Normal file
116
src/controllers/03-employee-in-country-notice-controller.ts
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Middlewares,
|
||||
Path,
|
||||
Post,
|
||||
Put,
|
||||
Route,
|
||||
Security,
|
||||
Tags,
|
||||
} from "tsoa";
|
||||
import { RequestWithUser } from "../interfaces/user";
|
||||
import prisma from "../db";
|
||||
import HttpStatus from "../interfaces/http-status";
|
||||
import { permissionCheck } from "../middlewares/employee";
|
||||
import { notFoundError } from "../utils/error";
|
||||
|
||||
const MANAGE_ROLES = [
|
||||
"system",
|
||||
"head_of_admin",
|
||||
"admin",
|
||||
"head_of_account",
|
||||
"account",
|
||||
"head_of_sale",
|
||||
];
|
||||
|
||||
function globalAllow(user: RequestWithUser["user"]) {
|
||||
const allowList = ["system", "head_of_admin", "admin", "head_of_account", "head_of_sale"];
|
||||
return allowList.some((v) => user.roles?.includes(v));
|
||||
}
|
||||
|
||||
type EmployeeInCountryNoticePayload = {
|
||||
noticeNumber: string;
|
||||
noticeDate: string;
|
||||
nextNoticeDate: Date;
|
||||
tmNumber: string;
|
||||
entryDate: Date;
|
||||
travelBy: string;
|
||||
travelFrom: string;
|
||||
};
|
||||
|
||||
@Route("api/v1/employee/{employeeId}/work")
|
||||
@Tags("Employee Work")
|
||||
@Middlewares(permissionCheck(globalAllow))
|
||||
export class EmployeeInCountryNoticeController extends Controller {
|
||||
@Get()
|
||||
@Security("keycloak")
|
||||
async list(@Path() employeeId: string) {
|
||||
return prisma.employeeInCountryNotice.findMany({
|
||||
orderBy: { createdAt: "asc" },
|
||||
where: { employeeId },
|
||||
});
|
||||
}
|
||||
|
||||
@Get("{passportId}")
|
||||
@Security("keycloak")
|
||||
async getById(@Path() employeeId: string, @Path() passportId: string) {
|
||||
const record = await prisma.employeeInCountryNotice.findFirst({
|
||||
where: { id: passportId, employeeId },
|
||||
});
|
||||
if (!record) throw notFoundError("Employee Work");
|
||||
return record;
|
||||
}
|
||||
|
||||
@Post()
|
||||
@Security("keycloak", MANAGE_ROLES)
|
||||
async create(@Path() employeeId: string, @Body() body: EmployeeInCountryNoticePayload) {
|
||||
const record = await prisma.employeeInCountryNotice.create({
|
||||
data: {
|
||||
...body,
|
||||
employee: { connect: { id: employeeId } },
|
||||
},
|
||||
});
|
||||
|
||||
this.setStatus(HttpStatus.CREATED);
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
@Put("{passportId}")
|
||||
@Security("keycloak", MANAGE_ROLES)
|
||||
async editById(
|
||||
@Path() employeeId: string,
|
||||
@Path() passportId: string,
|
||||
@Body() body: EmployeeInCountryNoticePayload,
|
||||
) {
|
||||
const work = await prisma.employeeInCountryNotice.findUnique({
|
||||
where: { id: passportId, employeeId },
|
||||
});
|
||||
|
||||
if (!work) throw notFoundError("Employee Work");
|
||||
|
||||
const record = await prisma.employeeInCountryNotice.update({
|
||||
where: { id: passportId, employeeId },
|
||||
data: { ...body },
|
||||
});
|
||||
|
||||
this.setStatus(HttpStatus.CREATED);
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
@Delete("{passportId}")
|
||||
@Security("keycloak", MANAGE_ROLES)
|
||||
async deleteById(@Path() employeeId: string, @Path() passportId: string) {
|
||||
const record = await prisma.employeeInCountryNotice.findFirst({
|
||||
where: { id: passportId, employeeId },
|
||||
});
|
||||
|
||||
if (!record) throw notFoundError("Employee Work");
|
||||
|
||||
return await prisma.employeeInCountryNotice.delete({ where: { id: passportId, employeeId } });
|
||||
}
|
||||
}
|
||||
116
src/controllers/03-employee-passport-controller.ts
Normal file
116
src/controllers/03-employee-passport-controller.ts
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Middlewares,
|
||||
Path,
|
||||
Post,
|
||||
Put,
|
||||
Route,
|
||||
Security,
|
||||
Tags,
|
||||
} from "tsoa";
|
||||
import { RequestWithUser } from "../interfaces/user";
|
||||
import prisma from "../db";
|
||||
import HttpStatus from "../interfaces/http-status";
|
||||
import { permissionCheck } from "../middlewares/employee";
|
||||
import { notFoundError } from "../utils/error";
|
||||
|
||||
const MANAGE_ROLES = [
|
||||
"system",
|
||||
"head_of_admin",
|
||||
"admin",
|
||||
"head_of_account",
|
||||
"account",
|
||||
"head_of_sale",
|
||||
];
|
||||
|
||||
function globalAllow(user: RequestWithUser["user"]) {
|
||||
const allowList = ["system", "head_of_admin", "admin", "head_of_account", "head_of_sale"];
|
||||
return allowList.some((v) => user.roles?.includes(v));
|
||||
}
|
||||
|
||||
type EmployeePassportPayload = {
|
||||
number: string;
|
||||
type: string;
|
||||
issueDate: Date;
|
||||
expireDate: Date;
|
||||
issueCountry: string;
|
||||
issuePlace: string;
|
||||
previousPassportRef?: string | null;
|
||||
};
|
||||
|
||||
@Route("api/v1/employee/{employeeId}/work")
|
||||
@Tags("Employee Work")
|
||||
@Middlewares(permissionCheck(globalAllow))
|
||||
export class EmployeePassportController extends Controller {
|
||||
@Get()
|
||||
@Security("keycloak")
|
||||
async list(@Path() employeeId: string) {
|
||||
return prisma.employeePassport.findMany({
|
||||
orderBy: { createdAt: "asc" },
|
||||
where: { employeeId },
|
||||
});
|
||||
}
|
||||
|
||||
@Get("{passportId}")
|
||||
@Security("keycloak")
|
||||
async getById(@Path() employeeId: string, @Path() passportId: string) {
|
||||
const record = await prisma.employeePassport.findFirst({
|
||||
where: { id: passportId, employeeId },
|
||||
});
|
||||
if (!record) throw notFoundError("Employee Work");
|
||||
return record;
|
||||
}
|
||||
|
||||
@Post()
|
||||
@Security("keycloak", MANAGE_ROLES)
|
||||
async create(@Path() employeeId: string, @Body() body: EmployeePassportPayload) {
|
||||
const record = await prisma.employeePassport.create({
|
||||
data: {
|
||||
...body,
|
||||
employee: { connect: { id: employeeId } },
|
||||
},
|
||||
});
|
||||
|
||||
this.setStatus(HttpStatus.CREATED);
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
@Put("{passportId}")
|
||||
@Security("keycloak", MANAGE_ROLES)
|
||||
async editById(
|
||||
@Path() employeeId: string,
|
||||
@Path() passportId: string,
|
||||
@Body() body: EmployeePassportPayload,
|
||||
) {
|
||||
const work = await prisma.employeePassport.findUnique({
|
||||
where: { id: passportId, employeeId },
|
||||
});
|
||||
|
||||
if (!work) throw notFoundError("Employee Work");
|
||||
|
||||
const record = await prisma.employeePassport.update({
|
||||
where: { id: passportId, employeeId },
|
||||
data: { ...body },
|
||||
});
|
||||
|
||||
this.setStatus(HttpStatus.CREATED);
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
@Delete("{passportId}")
|
||||
@Security("keycloak", MANAGE_ROLES)
|
||||
async deleteById(@Path() employeeId: string, @Path() passportId: string) {
|
||||
const record = await prisma.employeePassport.findFirst({
|
||||
where: { id: passportId, employeeId },
|
||||
});
|
||||
|
||||
if (!record) throw notFoundError("Employee Work");
|
||||
|
||||
return await prisma.employeePassport.delete({ where: { id: passportId, employeeId } });
|
||||
}
|
||||
}
|
||||
118
src/controllers/03-employee-visa-controller.ts
Normal file
118
src/controllers/03-employee-visa-controller.ts
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Middlewares,
|
||||
Path,
|
||||
Post,
|
||||
Put,
|
||||
Route,
|
||||
Security,
|
||||
Tags,
|
||||
} from "tsoa";
|
||||
import { RequestWithUser } from "../interfaces/user";
|
||||
import prisma from "../db";
|
||||
import HttpStatus from "../interfaces/http-status";
|
||||
import { permissionCheck } from "../middlewares/employee";
|
||||
import { notFoundError } from "../utils/error";
|
||||
|
||||
const MANAGE_ROLES = [
|
||||
"system",
|
||||
"head_of_admin",
|
||||
"admin",
|
||||
"head_of_account",
|
||||
"account",
|
||||
"head_of_sale",
|
||||
];
|
||||
|
||||
function globalAllow(user: RequestWithUser["user"]) {
|
||||
const allowList = ["system", "head_of_admin", "admin", "head_of_account", "head_of_sale"];
|
||||
return allowList.some((v) => user.roles?.includes(v));
|
||||
}
|
||||
|
||||
type EmployeeVisaPayload = {
|
||||
number: string;
|
||||
type: string;
|
||||
entryCount: number;
|
||||
issueCountry: string;
|
||||
issuePlace: string;
|
||||
issueDate: Date;
|
||||
expireDate: Date;
|
||||
mrz?: string;
|
||||
remark?: string;
|
||||
};
|
||||
|
||||
@Route("api/v1/employee/{employeeId}/work")
|
||||
@Tags("Employee Work")
|
||||
@Middlewares(permissionCheck(globalAllow))
|
||||
export class EmployeeVisaController extends Controller {
|
||||
@Get()
|
||||
@Security("keycloak")
|
||||
async list(@Path() employeeId: string) {
|
||||
return prisma.employeeVisa.findMany({
|
||||
orderBy: { createdAt: "asc" },
|
||||
where: { employeeId },
|
||||
});
|
||||
}
|
||||
|
||||
@Get("{passportId}")
|
||||
@Security("keycloak")
|
||||
async getById(@Path() employeeId: string, @Path() passportId: string) {
|
||||
const record = await prisma.employeeVisa.findFirst({
|
||||
where: { id: passportId, employeeId },
|
||||
});
|
||||
if (!record) throw notFoundError("Employee Work");
|
||||
return record;
|
||||
}
|
||||
|
||||
@Post()
|
||||
@Security("keycloak", MANAGE_ROLES)
|
||||
async create(@Path() employeeId: string, @Body() body: EmployeeVisaPayload) {
|
||||
const record = await prisma.employeeVisa.create({
|
||||
data: {
|
||||
...body,
|
||||
employee: { connect: { id: employeeId } },
|
||||
},
|
||||
});
|
||||
|
||||
this.setStatus(HttpStatus.CREATED);
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
@Put("{passportId}")
|
||||
@Security("keycloak", MANAGE_ROLES)
|
||||
async editById(
|
||||
@Path() employeeId: string,
|
||||
@Path() passportId: string,
|
||||
@Body() body: EmployeeVisaPayload,
|
||||
) {
|
||||
const work = await prisma.employeeVisa.findUnique({
|
||||
where: { id: passportId, employeeId },
|
||||
});
|
||||
|
||||
if (!work) throw notFoundError("Employee Work");
|
||||
|
||||
const record = await prisma.employeeVisa.update({
|
||||
where: { id: passportId, employeeId },
|
||||
data: { ...body },
|
||||
});
|
||||
|
||||
this.setStatus(HttpStatus.CREATED);
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
@Delete("{passportId}")
|
||||
@Security("keycloak", MANAGE_ROLES)
|
||||
async deleteById(@Path() employeeId: string, @Path() passportId: string) {
|
||||
const record = await prisma.employeeVisa.findFirst({
|
||||
where: { id: passportId, employeeId },
|
||||
});
|
||||
|
||||
if (!record) throw notFoundError("Employee Work");
|
||||
|
||||
return await prisma.employeeVisa.delete({ where: { id: passportId, employeeId } });
|
||||
}
|
||||
}
|
||||
|
|
@ -113,14 +113,6 @@ type QuotationUpdate = {
|
|||
addressEN: string;
|
||||
address: string;
|
||||
zipCode: string;
|
||||
|
||||
passportType: string;
|
||||
passportNumber: string;
|
||||
passportIssueDate: Date;
|
||||
passportExpiryDate: Date;
|
||||
passportIssuingCountry: string;
|
||||
passportIssuingPlace: string;
|
||||
previousPassportReference?: string;
|
||||
}
|
||||
)[];
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue