refactor: employee
This commit is contained in:
parent
77739da154
commit
c51a403f2a
7 changed files with 637 additions and 277 deletions
|
|
@ -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