diff --git a/src/controllers/EducationLevelController.ts b/src/controllers/EducationLevelController.ts index 67da2294..a4e87734 100644 --- a/src/controllers/EducationLevelController.ts +++ b/src/controllers/EducationLevelController.ts @@ -157,7 +157,7 @@ export class EducationLevelController extends Controller { "createdFullName", "lastUpdateFullName", ], - order: { createdAt: "ASC" }, + order: { rank: "ASC" }, }); // if (!educationLevel) { diff --git a/src/controllers/ProfileGovernmentEmployeeController.ts b/src/controllers/ProfileGovernmentEmployeeController.ts new file mode 100644 index 00000000..1e09d6c1 --- /dev/null +++ b/src/controllers/ProfileGovernmentEmployeeController.ts @@ -0,0 +1,188 @@ +import { Body, Controller, Example, Get, Patch, Path, Delete, Post, Request, Route, Security, Tags } from "tsoa"; +import { AppDataSource } from "../database/data-source"; +import HttpSuccess from "../interfaces/http-success"; +import HttpStatus from "../interfaces/http-status"; +import HttpError from "../interfaces/http-error"; +import { RequestWithUser } from "../middlewares/user"; +import { ProfileEmployee } from "../entities/ProfileEmployee"; +import { CreateProfileEmployeeGovernment, ProfileGovernment, UpdateProfileGovernment } from "../entities/ProfileGovernment"; +import { EmployeePosition } from "../entities/EmployeePosition"; +import { EmployeePosMaster } from "../entities/EmployeePosMaster"; +import { calculateAge, calculateRetireDate } from "../interfaces/utils"; + +@Route("api/v1/org/profile-employee/government") +@Tags("ProfileEmployeeGovernment") +@Security("bearerAuth") +export class ProfileGovernmentEmployeeController extends Controller { + private profileEmployeeRepo = AppDataSource.getRepository(ProfileEmployee); + private govRepo = AppDataSource.getRepository(ProfileGovernment); + private positionRepo = AppDataSource.getRepository(EmployeePosition); + private posMasterRepo = AppDataSource.getRepository(EmployeePosMaster); + + /** + * + * @summary ข้อมูลราชการ + * + */ + @Get("{profileEmployeeId}") + @Example({}) + public async getGovHistory(@Path() profileEmployeeId: string) { + const record = await this.profileEmployeeRepo.findOne({ + where: { id: profileEmployeeId }, + relations: { + posType: true, + posLevel: true, + }, + }); + const posMaster = await this.posMasterRepo.findOne({ + where: { + orgRevision: { + orgRevisionIsCurrent: true, + orgRevisionIsDraft: false, + }, + current_holderId: profileEmployeeId, + }, + order: { createdAt: "DESC" }, + relations: { + orgRoot: true, + orgChild1: true, + orgChild2: true, + orgChild3: true, + orgChild4: true, + }, + }); + const position = await this.positionRepo.findOne({ + where: { + positionIsSelected: true, + posMaster: { + orgRevision: { + orgRevisionIsCurrent: true, + orgRevisionIsDraft: false, + }, + current_holderId: profileEmployeeId, + }, + }, + order: { createdAt: "DESC" }, + }); + + if (!record) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล"); + const fullNameParts = [ + posMaster == null || posMaster.orgChild4 == null ? null : posMaster.orgChild4.orgChild4Name, + posMaster == null || posMaster.orgChild3 == null ? null : posMaster.orgChild3.orgChild3Name, + posMaster == null || posMaster.orgChild2 == null ? null : posMaster.orgChild2.orgChild2Name, + posMaster == null || posMaster.orgChild1 == null ? null : posMaster.orgChild1.orgChild1Name, + posMaster == null || posMaster.orgRoot == null ? null : posMaster.orgRoot.orgRootName, + ]; + const org = fullNameParts.filter((part) => part !== undefined && part !== null).join("/"); + let orgShortName = ""; + if (posMaster != null) { + if (posMaster.orgChild1Id === null) { + orgShortName = posMaster.orgRoot?.orgRootShortName; + } else if (posMaster.orgChild2Id === null) { + orgShortName = posMaster.orgChild1?.orgChild1ShortName; + } else if (posMaster.orgChild3Id === null) { + orgShortName = posMaster.orgChild2?.orgChild2ShortName; + } else if (posMaster.orgChild4Id === null) { + orgShortName = posMaster.orgChild3?.orgChild3ShortName; + } else { + orgShortName = posMaster.orgChild4?.orgChild4ShortName; + } + } + const data = { + org: org, //สังกัด + position: record.position, //ตำแหน่ง + posLevel: record.posLevel == null ? null : record.posLevel.posLevelName, //ระดับ + posMasterNo: posMaster == null ? null : `${orgShortName} ${posMaster.posMasterNo}`, //เลขที่ตำแหน่ง + posType: record.posType == null ? null : record.posType.posTypeName, //ประเภท + dateLeave: record.birthDate == null ? null : calculateRetireDate(record.birthDate), //วันเกษียณ + }; + return new HttpSuccess(data); + } + + /** + * + * @summary ประวัติข้อมูลราชการ + * + */ + @Get("history/{profileEmployeeId}") + @Example({}) + public async govHistory(@Path() profileEmployeeId: string) { + const record = await this.govRepo.find({ + order: { lastUpdatedAt: "DESC" }, + where: { profileEmployeeId: profileEmployeeId }, + }); + return new HttpSuccess(record); + } + + /** + * + * @summary เพิ่มข้อมูลราชการ + * + */ + @Post() + public async newGov(@Request() req: RequestWithUser, @Body() body: CreateProfileEmployeeGovernment) { + if (!body.profileEmployeeId) { + throw new HttpError(HttpStatus.BAD_REQUEST, "กรุณากรอก profileEmployeeId"); + } + + const profile = await this.profileEmployeeRepo.findOneBy({ id: body.profileEmployeeId }); + if (!profile) { + throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบ profile ดังกล่าว"); + } + + const data = new ProfileGovernment(); + const meta = { + createdUserId: req.user.sub, + createdFullName: req.user.name, + lastUpdateUserId: req.user.sub, + lastUpdateFullName: req.user.name, + }; + + Object.assign(data, { ...body, ...meta }); + await this.govRepo.save(data); + return new HttpSuccess(); + } + + /** + * + * @summary แก้ไขข้อมูลราชการ + * + */ + @Patch("{profileEmployeeId}") + public async editGov( + @Request() req: RequestWithUser, + @Body() body: UpdateProfileGovernment, + @Path() profileEmployeeId: string, + ) { + const record = await this.profileEmployeeRepo.findOne({ + where: { id: profileEmployeeId }, + }); + + if (!record) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล"); + const historyData = new ProfileGovernment(); + + Object.assign(historyData, { ...record, ...body, id: undefined }); + Object.assign(record, body); + record.lastUpdateFullName = req.user.name; + record.lastUpdateFullName = req.user.name; + historyData.profileEmployeeId = profileEmployeeId; + historyData.lastUpdateFullName = req.user.name; + historyData.lastUpdateFullName = req.user.name; + await Promise.all([this.profileEmployeeRepo.save(record), this.govRepo.save(historyData)]); + return new HttpSuccess(); + } + + /** + * + * @summary ลบข้อมูลราชการ + * + */ + @Delete("{profileEmployeeId}") + public async deleteGov(@Path() profileEmployeeId: string) { + const result = await this.govRepo.delete({ profileEmployeeId: profileEmployeeId }); + if (result.affected == undefined || result.affected <= 0) { + throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล"); + } + return new HttpSuccess(); + } +} \ No newline at end of file diff --git a/src/entities/ProfileGovernment.ts b/src/entities/ProfileGovernment.ts index 1b35fcb4..0f675353 100644 --- a/src/entities/ProfileGovernment.ts +++ b/src/entities/ProfileGovernment.ts @@ -1,7 +1,7 @@ -import { Column, Entity, ManyToOne } from "typeorm"; +import { Column, Entity, ManyToOne, JoinColumn } from "typeorm"; import { EntityBase } from "./base/Base"; import { Profile } from "./Profile"; - +import { ProfileEmployee } from "./ProfileEmployee"; @Entity("profileGovernment") export class ProfileGovernment extends EntityBase { @Column({ @@ -12,8 +12,13 @@ export class ProfileGovernment extends EntityBase { }) profileId: string; - @ManyToOne(() => Profile, (v) => v.profileGovernment) - profile: Profile; + @Column({ + nullable: true, + length: 40, + comment: "คีย์นอก(FK)ของตาราง ProfileEmployee", + default: null, + }) + profileEmployeeId: string; @Column({ nullable: true, @@ -52,6 +57,14 @@ export class ProfileGovernment extends EntityBase { default: null, }) reasonSameDate: string; + + @ManyToOne(() => Profile, (v) => v.profileGovernment) + @JoinColumn({ name: "profileId" }) + profile: Profile; + + @ManyToOne(() => ProfileEmployee, (ProfileEmployee) => ProfileEmployee.profileTrainings) + @JoinColumn({ name: "profileEmployeeId" }) + profileEmployee: ProfileEmployee; } export type CreateProfileGovernment = { @@ -61,6 +74,13 @@ export type CreateProfileGovernment = { reasonSameDate?: string | null; }; +export type CreateProfileEmployeeGovernment = { + profileEmployeeId: string; + dateAppoint?: Date | null; + dateStart?: Date | null; + reasonSameDate?: string | null; +}; + export type UpdateProfileGovernment = { dateAppoint?: Date | null; dateStart?: Date | null; diff --git a/src/migration/1715662524792-update_table_profileemployee_add_pk5.ts b/src/migration/1715662524792-update_table_profileemployee_add_pk5.ts new file mode 100644 index 00000000..8ab25ed3 --- /dev/null +++ b/src/migration/1715662524792-update_table_profileemployee_add_pk5.ts @@ -0,0 +1,16 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class UpdateTableProfileemployeeAddPk51715662524792 implements MigrationInterface { + name = 'UpdateTableProfileemployeeAddPk51715662524792' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`profileSalary\` ADD \`profileEmployeeId\` varchar(40) NULL COMMENT 'คีย์นอก(FK)ของตาราง ProfileEmployee'`); + await queryRunner.query(`ALTER TABLE \`profileSalary\` ADD CONSTRAINT \`FK_f5758428d496b6d2a051c8af92b\` FOREIGN KEY (\`profileEmployeeId\`) REFERENCES \`profileEmployee\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`profileSalary\` DROP FOREIGN KEY \`FK_f5758428d496b6d2a051c8af92b\``); + await queryRunner.query(`ALTER TABLE \`profileSalary\` DROP COLUMN \`profileEmployeeId\``); + } + +} diff --git a/src/migration/1715662934173-update_table_node_add_duty.ts b/src/migration/1715662934173-update_table_node_add_duty.ts new file mode 100644 index 00000000..d209357c --- /dev/null +++ b/src/migration/1715662934173-update_table_node_add_duty.ts @@ -0,0 +1,14 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class UpdateTableNodeAddDuty1715662934173 implements MigrationInterface { + name = 'UpdateTableNodeAddDuty1715662934173' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`orgRoot\` ADD \`duty\` varchar(255) NULL COMMENT 'หน้าที่ความรับผิดชอบ '`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`orgRoot\` DROP COLUMN \`duty\``); + } + +} diff --git a/src/migration/1715663083281-update_table_profilegov_add_employee.ts b/src/migration/1715663083281-update_table_profilegov_add_employee.ts new file mode 100644 index 00000000..42cb6e97 --- /dev/null +++ b/src/migration/1715663083281-update_table_profilegov_add_employee.ts @@ -0,0 +1,16 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class UpdateTableProfilegovAddEmployee1715663083281 implements MigrationInterface { + name = 'UpdateTableProfilegovAddEmployee1715663083281' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`profileGovernment\` ADD \`profileEmployeeId\` varchar(40) NULL COMMENT 'คีย์นอก(FK)ของตาราง ProfileEmployee'`); + await queryRunner.query(`ALTER TABLE \`profileGovernment\` ADD CONSTRAINT \`FK_bac1952c24999f6576905b32a5a\` FOREIGN KEY (\`profileEmployeeId\`) REFERENCES \`profileEmployee\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`profileGovernment\` DROP FOREIGN KEY \`FK_bac1952c24999f6576905b32a5a\``); + await queryRunner.query(`ALTER TABLE \`profileGovernment\` DROP COLUMN \`profileEmployeeId\``); + } + +}