diff --git a/src/controllers/ProfileEmployeeController.ts b/src/controllers/ProfileEmployeeController.ts index 6727ba09..4b8ba5d4 100644 --- a/src/controllers/ProfileEmployeeController.ts +++ b/src/controllers/ProfileEmployeeController.ts @@ -16,28 +16,35 @@ import { } from "tsoa"; import { AppDataSource } from "../database/data-source"; import HttpSuccess from "../interfaces/http-success"; -import HttpStatusCode from "../interfaces/http-status"; +import HttpStatus from "../interfaces/http-status"; import HttpError from "../interfaces/http-error"; import { Brackets, IsNull, Like, Not } from "typeorm"; import { OrgRevision } from "../entities/OrgRevision"; import { calculateRetireDate } from "../interfaces/utils"; import { EmployeePosMaster } from "../entities/EmployeePosMaster"; -import { ProfileEmployee, CreateProfileEmployee } from "../entities/ProfileEmployee"; +import { + ProfileEmployee, + CreateProfileEmployee, + UpdateProfileEmployee, + ProfileEmployeeHistory, +} from "../entities/ProfileEmployee"; import { EmployeePosLevel } from "../entities/EmployeePosLevel"; import { EmployeePosType } from "../entities/EmployeePosType"; +import { RequestWithUser } from "../middlewares/user"; @Route("api/v1/org/profile-employee") @Tags("Profile") @Security("bearerAuth") @Response( - HttpStatusCode.INTERNAL_SERVER_ERROR, + HttpStatus.INTERNAL_SERVER_ERROR, "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง", ) -@SuccessResponse(HttpStatusCode.OK, "สำเร็จ") +@SuccessResponse(HttpStatus.OK, "สำเร็จ") export class ProfileEmployeeController extends Controller { private orgRevisionRepo = AppDataSource.getRepository(OrgRevision); private posMasterRepo = AppDataSource.getRepository(EmployeePosMaster); private profileRepo = AppDataSource.getRepository(ProfileEmployee); + private profileHistoryRepo = AppDataSource.getRepository(ProfileEmployeeHistory); private posLevelRepo = AppDataSource.getRepository(EmployeePosLevel); private posTypeRepo = AppDataSource.getRepository(EmployeePosType); @@ -48,58 +55,32 @@ export class ProfileEmployeeController extends Controller { * */ @Post() - async createProfile( - @Body() - requestBody: CreateProfileEmployee, - @Request() request: { user: Record }, - ) { - const _profile = await this.profileRepo.findOne({ - where: { citizenId: requestBody.citizenId }, - }); - if (_profile) { + async createProfile(@Body() body: CreateProfileEmployee, @Request() request: RequestWithUser) { + if (await this.profileRepo.findOneBy({ citizenId: body.citizenId })) { throw new HttpError( - HttpStatusCode.INTERNAL_SERVER_ERROR, + HttpStatus.INTERNAL_SERVER_ERROR, "เลขประจำตัวประชาชนนี้มีอยู่ในระบบแล้ว", ); } - if (requestBody.posLevelId == "") { - requestBody.posLevelId = null; - } - if (requestBody.posLevelId) { - const checkPosLevel = await this.posLevelRepo.findOne({ - where: { id: requestBody.posLevelId }, - }); - if (!checkPosLevel) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลระดับตำแหน่งนี้"); - } + + if (body.posLevelId === "") body.posLevelId = null; + if (body.posTypeId === "") body.posTypeId = null; + + if (body.posLevelId && !(await this.posLevelRepo.findOneBy({ id: body.posLevelId }))) { + throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลระดับตำแหน่งนี้"); } - if (requestBody.posTypeId == "") { - requestBody.posTypeId = null; - } - if (requestBody.posTypeId) { - const checkPosType = await this.posTypeRepo.findOne({ - where: { id: requestBody.posTypeId }, - }); - if (!checkPosType) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลประเภทตำแหน่งนี้"); - } + if (body.posTypeId && !(await this.posTypeRepo.findOneBy({ id: body.posTypeId }))) { + throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลประเภทตำแหน่งนี้"); } - const checkCitizenId = await this.profileRepo.findOne({ - where: { citizenId: requestBody.citizenId }, - }); - - if (checkCitizenId) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "เลขประจำตัวประชาชนนี้มีอยู่ในระบบแล้ว"); - } - - const profile = Object.assign(new ProfileEmployee(), requestBody); + const profile = Object.assign(new ProfileEmployee(), body); profile.createdUserId = request.user.sub; profile.createdFullName = request.user.name; profile.lastUpdateUserId = request.user.sub; profile.lastUpdateFullName = request.user.name; await this.profileRepo.save(profile); + return new HttpSuccess(); } @@ -112,65 +93,49 @@ export class ProfileEmployeeController extends Controller { */ @Put("{id}") async updateProfile( + @Request() request: RequestWithUser, @Path() id: string, - @Body() - requestBody: CreateProfileEmployee, - @Request() request: { user: Record }, + @Body() body: UpdateProfileEmployee, ) { - const profile = await this.profileRepo.findOne({ where: { id: id } }); - if (!profile) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์นี้"); + const exists = + !!body.citizenId && + (await this.profileRepo.findOne({ + where: { id: Not(id), citizenId: body.citizenId }, + })); + + if (exists) { + throw new HttpError(HttpStatus.CONFLICT, "เลขประจำตัวประชาชนนี้มีอยู่ในระบบแล้ว"); } - const _profile = await this.profileRepo.findOne({ - where: { id: Not(id), citizenId: requestBody.citizenId }, - }); - if (_profile) { - throw new HttpError( - HttpStatusCode.INTERNAL_SERVER_ERROR, - "เลขประจำตัวประชาชนนี้มีอยู่ในระบบแล้ว", - ); + if (body.posLevelId === "") body.posLevelId = null; + if (body.posTypeId === "") body.posTypeId = null; + + if (body.posLevelId && !(await this.posLevelRepo.findOneBy({ id: body.posLevelId }))) { + throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลระดับตำแหน่งนี้"); } - if (requestBody.posLevelId == "") { - requestBody.posLevelId = null; - } - if (requestBody.posLevelId) { - const checkPosLevel = await this.posLevelRepo.findOne({ - where: { id: requestBody.posLevelId }, - }); - if (!checkPosLevel) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลระดับตำแหน่งนี้"); - } + if (body.posTypeId && !(await this.posTypeRepo.findOneBy({ id: body.posTypeId }))) { + throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลประเภทตำแหน่งนี้"); } - if (requestBody.posTypeId == "") { - requestBody.posTypeId = null; - } - if (requestBody.posTypeId) { - const checkPosType = await this.posTypeRepo.findOne({ - where: { id: requestBody.posTypeId }, - }); - if (!checkPosType) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลประเภทตำแหน่งนี้"); - } - } + const record = await this.profileRepo.findOneBy({ id }); - const checkCitizenId = await this.profileRepo.findOne({ - where: { - id: Not(id), - citizenId: requestBody.citizenId, - }, - }); + if (!record) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์นี้"); - if (checkCitizenId) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "เลขประจำตัวประชาชนนี้มีอยู่ในระบบแล้ว"); - } + await this.profileHistoryRepo.save( + Object.assign(new ProfileEmployeeHistory(), { + ...record, + profileEmployeeId: id, + id: undefined, + }), + ); + + Object.assign(record, body); + record.lastUpdateUserId = request.user.sub; + record.lastUpdateFullName = request.user.name; + + await this.profileRepo.save(record); - profile.lastUpdateUserId = request.user.sub; - profile.lastUpdateFullName = request.user.name; - this.profileRepo.merge(profile, requestBody); - await this.profileRepo.save(profile); return new HttpSuccess(); } @@ -183,13 +148,12 @@ export class ProfileEmployeeController extends Controller { */ @Delete("{id}") async deleteProfile(@Path() id: string) { - const delProfile = await this.profileRepo.findOne({ - where: { id }, - }); - if (!delProfile) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์นี้"); + const result = await this.profileRepo.delete({ id }); + + if (result.affected && result.affected <= 0) { + throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล"); } - await this.profileRepo.delete({ id: id }); + return new HttpSuccess(); } @@ -203,21 +167,18 @@ export class ProfileEmployeeController extends Controller { @Get("{id}") async detailProfile(@Path() id: string) { const profile = await this.profileRepo.findOne({ + relations: { + posLevel: true, + posType: true, + gender: true, + relationship: true, + bloodGroup: true, + }, where: { id }, - select: [ - "id", - "prefix", - "firstName", - "lastName", - "citizenId", - "position", - "posLevelId", - "posTypeId", - ], }); - if (!profile) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูล"); - } + + if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล"); + return new HttpSuccess(profile); } @@ -231,57 +192,48 @@ export class ProfileEmployeeController extends Controller { async listProfile( @Query("page") page: number = 1, @Query("pageSize") pageSize: number = 10, - @Query("keyword") keyword?: string, + @Query("keyword") keyword: string = "", ) { - const [profile, total] = await this.profileRepo.findAndCount({ - select: [ - "id", - "prefix", - "firstName", - "lastName", - "citizenId", - "position", - "posLevelId", - "posTypeId", + const [record, total] = await this.profileRepo.findAndCount({ + relations: { + posLevel: true, + posType: true, + gender: true, + relationship: true, + bloodGroup: true, + }, + where: [ + { citizenId: Like(`%${keyword}%`) }, + { position: Like(`%${keyword}%`) }, + { prefix: Like(`%${keyword}%`) }, + { firstName: Like(`%${keyword}%`) }, + { lastName: Like(`%${keyword}%`) }, + { email: Like(`%${keyword}%`) }, + { telephoneNumber: Like(`%${keyword}%`) }, ], order: { createdAt: "ASC" }, skip: (page - 1) * pageSize, take: pageSize, }); - if (keyword != undefined && keyword !== "") { - const formattedKeyword = keyword.toLowerCase().replace(/\s+/g, ""); - const filteredProfile = profile.filter( - (x) => - (x.prefix + x.firstName + x.lastName).replace(/\s+/g, "").includes(formattedKeyword) || - x.citizenId?.toString().includes(keyword) || - x.position?.toString().includes(keyword), - ); + return new HttpSuccess({ data: record, total }); + } - const formattedData = filteredProfile.map((item) => ({ - id: item.id, - prefix: item.prefix, - firstName: item.firstName, - lastName: item.lastName, - citizenId: item.citizenId, - position: item.position, - posLevelId: item.posLevelId, - posTypeId: item.posTypeId, - })); + @Get("history/{id}") + async getProfileHistory(@Path() id: string) { + const profile = await this.profileHistoryRepo.find({ + relations: { + posLevel: true, + posType: true, + gender: true, + relationship: true, + bloodGroup: true, + }, + where: { profileEmployeeId: id }, + }); - return new HttpSuccess({ data: formattedData, total: formattedData.length }); - } + if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล"); - const formattedData = profile.map((item) => ({ - id: item.id, - prefix: item.prefix, - firstName: item.firstName, - lastName: item.lastName, - citizenId: item.citizenId, - position: item.position, - posLevelId: item.posLevelId, - posTypeId: item.posTypeId, - })); - return new HttpSuccess({ data: formattedData, total }); + return new HttpSuccess(profile); } /** @@ -310,7 +262,7 @@ export class ProfileEmployeeController extends Controller { relations: ["posMasters"], }); if (!orgRevision) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบแบบร่างโครงสร้าง"); + throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบแบบร่างโครงสร้าง"); } const [profiles, total] = await this.profileRepo .createQueryBuilder("profileEmployee") @@ -417,7 +369,7 @@ export class ProfileEmployeeController extends Controller { relations: ["posLevel", "posType", "current_holders", "current_holders.orgRoot"], }); if (!profile) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ"); + throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ"); } const orgRevisionPublish = await this.orgRevisionRepo @@ -426,7 +378,7 @@ export class ProfileEmployeeController extends Controller { .andWhere("orgRevision.orgRevisionIsCurrent = true") .getOne(); if (!orgRevisionPublish) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบแบบร่างโครงสร้าง"); + throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบแบบร่างโครงสร้าง"); } const _profile = { @@ -780,7 +732,7 @@ export class ProfileEmployeeController extends Controller { }); if (profile) { throw new HttpError( - HttpStatusCode.INTERNAL_SERVER_ERROR, + HttpStatus.INTERNAL_SERVER_ERROR, "เลขประจำตัวประชาชนนี้มีอยู่ในระบบแล้ว", ); } @@ -916,7 +868,7 @@ export class ProfileEmployeeController extends Controller { where: { orgRevisionIsCurrent: true }, }); if (!findRevision) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "not found. OrgRevision"); + throw new HttpError(HttpStatus.NOT_FOUND, "not found. OrgRevision"); } const [findPosMaster, total] = await AppDataSource.getRepository(EmployeePosMaster) @@ -1007,7 +959,7 @@ export class ProfileEmployeeController extends Controller { .take(body.pageSize) .getManyAndCount(); if (!findPosMaster) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "not found. PosMaster"); + throw new HttpError(HttpStatus.NOT_FOUND, "not found. PosMaster"); } const formattedData = findPosMaster.map((item) => { @@ -1119,7 +1071,7 @@ export class ProfileEmployeeController extends Controller { relations: ["posLevel", "posType", "current_holders", "current_holders.orgRoot"], }); if (!profile) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ"); + throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ"); } const _profile = {