diff --git a/src/controllers/InsigniaController.ts b/src/controllers/InsigniaController.ts new file mode 100644 index 00000000..8e3a49db --- /dev/null +++ b/src/controllers/InsigniaController.ts @@ -0,0 +1,200 @@ +import { + Controller, + Get, + Post, + Put, + Delete, + Patch, + Route, + Security, + Tags, + Body, + Path, + Request, + Example, + SuccessResponse, + Response, + Query, +} from "tsoa"; +import { AppDataSource } from "../database/data-source"; +import HttpSuccess from "../interfaces/http-success"; +import HttpStatusCode from "../interfaces/http-status"; +import HttpError from "../interfaces/http-error"; +import { Equal, ILike, In, IsNull, Like, Not, Brackets, Between } from "typeorm"; +import { InsigniaType, CreateInsigniaType, UpdateInsigniaType } from "../entities/InsigniaType"; +import { Insignia, CreateInsignias, UpdateInsignias } from "../entities/Insignia"; + +@Route("api/v1/org/insignia/Insignias") +@Tags("Insignia") +@Security("bearerAuth") +@Response( + HttpStatusCode.INTERNAL_SERVER_ERROR, + "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง", +) +@SuccessResponse(HttpStatusCode.OK, "สำเร็จ") +export class InsigniaController extends Controller { + + private insigniaTypeRepository = AppDataSource.getRepository(InsigniaType); + private insigniaRepository = AppDataSource.getRepository(Insignia); + + /** + * API เพิ่มข้อมูลเครื่องราชอิสริยาภรณ์ + * + * @summary ORG_ - เพิ่มข้อมูลเครื่องราชอิสริยาภรณ์ (ADMIN) # + * + */ + @Post("") + async CreateInsignia( + @Body() requestBody: CreateInsignias, + @Request() request: { user: Record }, + ) { + + const insignia = Object.assign(new Insignia(), requestBody); + if (!insignia) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูล"); + } + const insigniaType = await this.insigniaTypeRepository.findOne({ + where: { id: requestBody.insigniaTypeId}, + }); + if (!insigniaType) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลลำดับชั้นเครื่องราชอิสริยาภรณ์นี้"); + } + const rowRepeated = await this.insigniaRepository.findOne({ + where: { + name: requestBody.name, + isActive: requestBody.isActive, + }, + }); + if (rowRepeated) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ข้อมูล Row นี้มีอยู่ในระบบแล้ว"); + } + + insignia.createdUserId = request.user.sub; + insignia.createdFullName = request.user.name; + insignia.lastUpdateUserId = request.user.sub; + insignia.lastUpdateFullName = request.user.name; + await this.insigniaRepository.save(insignia); + return new HttpSuccess(insignia.id); + } + + /** + * API แก้ไขเครื่องราชอิสริยาภรณ์ + * + * @summary แก้ไขเครื่องราชอิสริยาภรณ์ (ADMIN) + * + * @param {string} id Id เครื่องราชอิสริยาภรณ์ + */ + @Put("{id}") + async UpdateInsignia( + @Path() id: string, + @Body() requestBody: UpdateInsignias, + @Request() request: { user: Record }, + ) { + const insignia = await this.insigniaRepository.findOne({ + where: { id: id }, + }); + if (!insignia) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลเครื่องราชอิสริยาภรณ์นี้"); + } + const insigniaType = await this.insigniaTypeRepository.findOne({ + where: { id: requestBody.insigniaTypeId}, + }); + if (!insigniaType) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลลำดับชั้นเครื่องราชอิสริยาภรณ์นี้"); + } + const rowRepeated = await this.insigniaRepository.findOne({ + where: { + id: Not(id), + name: requestBody.name, + isActive: requestBody.isActive, + }, + }); + if (rowRepeated) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ข้อมูล Row นี้มีอยู่ในระบบแล้ว"); + } + + insignia.lastUpdateUserId = request.user.sub; + insignia.lastUpdateFullName = request.user.name; + this.insigniaRepository.merge(insignia, requestBody); + await this.insigniaRepository.save(insignia); + return new HttpSuccess(insignia.id); + } + + /** + * API ลบเครื่องราชอิสริยาภรณ์ + * + * @summary ORG_ - ลบเครื่องราชอิสริยาภรณ์ (ADMIN) # + * + * @param {string} id Id เครื่องราชอิสริยาภรณ์ + */ + @Delete("{id}") + async delete(@Path() id: string) { + const delInsignia = await this.insigniaRepository.findOne({ where: { id } }); + if (!delInsignia) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลเครื่องราชอิสริยาภรณ์นี้"); + } + await this.insigniaRepository.remove(delInsignia); + return new HttpSuccess(); + } + + /** + * API รายละเอียดเครื่องราชอิสริยาภรณ์ + * + * @summary ORG_037 - รายละเอียดเครื่องราชอิสริยาภรณ์ (ADMIN) # + * + * @param {string} id Id เครื่องราชอิสริยาภรณ์ + */ + @Get("{id}") + async GetInsigniaById(@Path() id: string) { + const insignia = await this.insigniaRepository.findOne({ + relations: ["insigniaType"], + select: ["id", "name", "shortName", "createdAt", "lastUpdatedAt", "lastUpdateFullName", "isActive", "note"], + where: { id: id }, + }); + if (!insignia) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลเครื่องราชอิสริยาภรณ์นี้"); + } + const mapInsignia = { + id: insignia.id, + name: insignia.name, + shortName: insignia.shortName, + insigniaTypeName: insignia.insigniaType == null ? null : insignia.insigniaType.name, //ลำดับชั้นเครื่องราช + createdAt: insignia.createdAt, + lastUpdatedAt: insignia.lastUpdatedAt, + lastUpdateFullName: insignia.lastUpdateFullName, + isActive: insignia.isActive, + note: insignia.note + } + return new HttpSuccess(mapInsignia); + } + + /** + * API รายการเครื่องราชอิสริยาภรณ์ + * + * @summary ORG_ - รายการเครื่องราชอิสริยาภรณ์ (ADMIN) # + * + */ + @Get("") + async GetInsignia() { + + const insigniaAll = await this.insigniaRepository.find({ + relations: ["insigniaType"], + select: ["id", "name", "shortName", "createdAt", "lastUpdatedAt", "lastUpdateFullName", "isActive", "note"], + }); + if (!insigniaAll) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลเครื่องราชอิสริยาภรณ์นี้"); + } + const mapInsigniaAll = insigniaAll.map((item) => ({ + id: item.id, + name: item.name, + shortName: item.shortName, + insigniaTypeName: item.insigniaType == null ? null : item.insigniaType.name, //ลำดับชั้นเครื่องราช + createdAt: item.createdAt, + lastUpdatedAt: item.lastUpdatedAt, + lastUpdateFullName: item.lastUpdateFullName, + isActive: item.isActive, + note: item.note + })); + return new HttpSuccess(mapInsigniaAll); + } +} diff --git a/src/controllers/InsigniaTypeController.ts b/src/controllers/InsigniaTypeController.ts new file mode 100644 index 00000000..cfd8ec86 --- /dev/null +++ b/src/controllers/InsigniaTypeController.ts @@ -0,0 +1,171 @@ +import { + Controller, + Get, + Post, + Put, + Delete, + Patch, + Route, + Security, + Tags, + Body, + Path, + Request, + Example, + SuccessResponse, + Response, + Query, +} from "tsoa"; +import { AppDataSource } from "../database/data-source"; +import HttpSuccess from "../interfaces/http-success"; +import HttpStatusCode from "../interfaces/http-status"; +import HttpError from "../interfaces/http-error"; +import { Equal, ILike, In, IsNull, Like, Not, Brackets, Between } from "typeorm"; +import { InsigniaType, CreateInsigniaType, UpdateInsigniaType } from "../entities/InsigniaType"; +import { Insignia, } from "../entities/Insignia"; + +@Route("api/v1/org/insignia/insignia-type") +@Tags("InsigniaType") +@Security("bearerAuth") +@Response( + HttpStatusCode.INTERNAL_SERVER_ERROR, + "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง", +) +@SuccessResponse(HttpStatusCode.OK, "สำเร็จ") +export class InsigniaTypeController extends Controller { + + private insigniaTypeRepository = AppDataSource.getRepository(InsigniaType); + private insigniaRepository = AppDataSource.getRepository(Insignia); + + /** + * API เพิ่มข้อมูลลำดับชั้นเครื่องราชอิสริยาภรณ์ + * + * @summary ORG_ - เพิ่มข้อมูลลำดับชั้นเครื่องราชอิสริยาภรณ์ (ADMIN) # + * + */ + @Post("") + async CreateInsigniaType( + @Body() requestBody: CreateInsigniaType, + @Request() request: { user: Record }, + ) { + + const insigniaType = Object.assign(new InsigniaType(), requestBody); + if (!insigniaType) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูล"); + } + + const rowRepeated = await this.insigniaTypeRepository.findOne({ + where: { + name: requestBody.name, + isActive: requestBody.isActive, + }, + }); + if (rowRepeated) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ข้อมูล Row นี้มีอยู่ในระบบแล้ว"); + } + + insigniaType.createdUserId = request.user.sub; + insigniaType.createdFullName = request.user.name; + insigniaType.lastUpdateUserId = request.user.sub; + insigniaType.lastUpdateFullName = request.user.name; + await this.insigniaTypeRepository.save(insigniaType); + return new HttpSuccess(insigniaType.id); + } + + /** + * API แก้ไขลำดับชั้นเครื่องราชอิสริยาภรณ์ + * + * @summary แก้ไขลำดับชั้นเครื่องราชอิสริยาภรณ์ (ADMIN) + * + * @param {string} id Id ลำดับชั้นเครื่องราชอิสริยาภรณ์ + */ + @Put("{id}") + async UpdateInsigniaType( + @Path() id: string, + @Body() requestBody: UpdateInsigniaType, + @Request() request: { user: Record }, + ) { + const insigniaType = await this.insigniaTypeRepository.findOne({ + where: { id: id }, + }); + if (!insigniaType) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลลำดับชั้นเครื่องราชอิสริยาภรณ์นี้"); + } + const rowRepeated = await this.insigniaTypeRepository.findOne({ + where: { + id: Not(id), + name: requestBody.name, + isActive: requestBody.isActive, + }, + }); + if (rowRepeated) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ข้อมูล Row นี้มีอยู่ในระบบแล้ว"); + } + + insigniaType.lastUpdateUserId = request.user.sub; + insigniaType.lastUpdateFullName = request.user.name; + this.insigniaTypeRepository.merge(insigniaType, requestBody); + await this.insigniaTypeRepository.save(insigniaType); + return new HttpSuccess(insigniaType.id); + } + + /** + * API ลบลำดับชั้นเครื่องราชอิสริยาภรณ์ + * + * @summary ORG_ - ลบลำดับชั้นเครื่องราชอิสริยาภรณ์ (ADMIN) # + * + * @param {string} id Id ลำดับชั้นเครื่องราชอิสริยาภรณ์ + */ + @Delete("{id}") + async delete(@Path() id: string) { + const delInsigniaType = await this.insigniaTypeRepository.findOne({ where: { id } }); + if (!delInsigniaType) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลลำดับชั้นเครื่องราชอิสริยาภรณ์นี้"); + } + const Insignia = await this.insigniaRepository.find({ + where: { insigniaTypeId: id } + }); + if (Insignia.length > 0) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่สามารถลบได้ เนื่องจากพบข้อมูลที่ตารางเครื่องราชอิสริยาภรณ์"); + } + await this.insigniaTypeRepository.remove(delInsigniaType); + return new HttpSuccess(); + } + + /** + * API รายละเอียดข้อมูลลำดับชั้นเครื่องราชอิสริยาภรณ์ + * + * @summary ORG_037 - รายละเอียดข้อมูลลำดับชั้นเครื่องราชอิสริยาภรณ์ (ADMIN) # + * + * @param {string} id Id ลำดับชั้นเครื่องราชอิสริยาภรณ์ + */ + @Get("{id}") + async GetInsigniaTypeById(@Path() id: string) { + const insigniaType = await this.insigniaTypeRepository.findOne({ + select: ["id", "name", "createdAt", "lastUpdatedAt", "lastUpdateFullName", "isActive"], + where: { id: id }, + }); + if (!insigniaType) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลลำดับชั้นเครื่องราชอิสริยาภรณ์ นี้"); + } + return new HttpSuccess(insigniaType); + } + + /** + * API รายการลำดับชั้นเครื่องราชอิสริยาภรณ์ + * + * @summary ORG_ - รายการลำดับชั้นเครื่องราชอิสริยาภรณ์ (ADMIN) # + * + */ + @Get("") + async GetInsigniaType() { + + const insigniaTypeAll = await this.insigniaTypeRepository.find({ + select: ["id", "name", "createdAt", "lastUpdatedAt", "lastUpdateFullName", "isActive"] + }); + if (!insigniaTypeAll) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลลำดับชั้นเครื่องราชอิสริยาภรณ์ นี้"); + } + return new HttpSuccess(insigniaTypeAll); + } +} diff --git a/src/entities/Insignia.ts b/src/entities/Insignia.ts new file mode 100644 index 00000000..40771f37 --- /dev/null +++ b/src/entities/Insignia.ts @@ -0,0 +1,72 @@ +import { Entity, Column, ManyToOne, JoinColumn } from "typeorm"; +import { EntityBase } from "./base/Base"; +import { InsigniaType } from "./InsigniaType"; + +@Entity("insignia") +export class Insignia extends EntityBase { + @Column({ + nullable: true, + comment: "ชื่อเครื่องราช", + length: 255, + default: null, + }) + name: string; + + @Column({ + nullable: true, + comment: "ชื่อย่อเครื่องราช", + length: 255, + default: null, + }) + shortName: string; + + @Column({ + nullable: true, + comment: + "ลำดับชั้นของเครื่องราช เอาไว้ตรวจสอบเวลาขอว่าต้องได้ชั้นที่สูงกว่าที่เคยได้รับแล้วเท่านั้น", + default: null, + }) + level: number; + + @Column({ + comment: "สถานะการใช้งาน", + default: false, + }) + isActive: boolean; + + @Column({ + nullable: true, + comment: "หมายเหตุ", + default: null, + }) + note: string; + + @Column({ + length: 40, + comment: "id ประเภทเครื่องราช", + }) + insigniaTypeId: string; + + @ManyToOne(() => InsigniaType, (insigniaType) => insigniaType.insignias) + @JoinColumn({ name: "insigniaTypeId" }) + insigniaType: InsigniaType; +} + +export class CreateInsignias { + @Column() + name: string; + + @Column() + shortName: string; + + @Column() + isActive: boolean; + + @Column() + note: string; + + @Column("uuid") + insigniaTypeId: string; +} + +export type UpdateInsignias = Partial; diff --git a/src/entities/InsigniaType.ts b/src/entities/InsigniaType.ts new file mode 100644 index 00000000..f342cd93 --- /dev/null +++ b/src/entities/InsigniaType.ts @@ -0,0 +1,33 @@ +import { Entity, Column, OneToMany } from "typeorm"; +import { EntityBase } from "./base/Base"; +import { Insignia } from "./Insignia"; + +@Entity("insigniaType") +export class InsigniaType extends EntityBase { + @Column({ + nullable: true, + comment: "ชื่อประเภทเครื่องราช", + length: 255, + default: null, + }) + name: string; + + @Column({ + comment: "สถานะการใช้งาน", + default: false, + }) + isActive: boolean; + + @OneToMany(() => Insignia, (insignia) => insignia.insigniaType) + insignias: Insignia[]; +} + +export class CreateInsigniaType { + @Column() + name: string; + + @Column() + isActive: boolean; +} + +export type UpdateInsigniaType = Partial; diff --git a/src/migration/1710311804080-add_table_insignia.ts b/src/migration/1710311804080-add_table_insignia.ts new file mode 100644 index 00000000..06cb5256 --- /dev/null +++ b/src/migration/1710311804080-add_table_insignia.ts @@ -0,0 +1,18 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class AddTableInsignia1710311804080 implements MigrationInterface { + name = 'AddTableInsignia1710311804080' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`CREATE TABLE \`insignia\` (\`id\` varchar(36) NOT NULL, \`createdAt\` datetime(6) NOT NULL COMMENT 'สร้างข้อมูลเมื่อ' DEFAULT CURRENT_TIMESTAMP(6), \`createdUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่สร้างข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`lastUpdatedAt\` datetime(6) NOT NULL COMMENT 'แก้ไขข้อมูลล่าสุดเมื่อ' DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`lastUpdateUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่แก้ไขข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`createdFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่สร้างข้อมูล' DEFAULT 'string', \`lastUpdateFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่แก้ไขข้อมูลล่าสุด' DEFAULT 'string', \`name\` varchar(255) NULL COMMENT 'ชื่อเครื่องราช', \`shortName\` varchar(255) NULL COMMENT 'ชื่อย่อเครื่องราช', \`level\` int NULL COMMENT 'ลำดับชั้นของเครื่องราช เอาไว้ตรวจสอบเวลาขอว่าต้องได้ชั้นที่สูงกว่าที่เคยได้รับแล้วเท่านั้น', \`isActive\` tinyint NOT NULL COMMENT 'สถานะการใช้งาน' DEFAULT 0, \`note\` varchar(255) NULL COMMENT 'หมายเหตุ', \`insigniaTypeId\` varchar(40) NOT NULL COMMENT 'id ประเภทเครื่องราช', PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); + await queryRunner.query(`CREATE TABLE \`insigniaType\` (\`id\` varchar(36) NOT NULL, \`createdAt\` datetime(6) NOT NULL COMMENT 'สร้างข้อมูลเมื่อ' DEFAULT CURRENT_TIMESTAMP(6), \`createdUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่สร้างข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`lastUpdatedAt\` datetime(6) NOT NULL COMMENT 'แก้ไขข้อมูลล่าสุดเมื่อ' DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`lastUpdateUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่แก้ไขข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`createdFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่สร้างข้อมูล' DEFAULT 'string', \`lastUpdateFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่แก้ไขข้อมูลล่าสุด' DEFAULT 'string', \`name\` varchar(255) NULL COMMENT 'ชื่อประเภทเครื่องราช', \`isActive\` tinyint NOT NULL COMMENT 'สถานะการใช้งาน' DEFAULT 0, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); + await queryRunner.query(`ALTER TABLE \`insignia\` ADD CONSTRAINT \`FK_bf8cd951a7eb12a0eff9b17f82d\` FOREIGN KEY (\`insigniaTypeId\`) REFERENCES \`insigniaType\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`insignia\` DROP FOREIGN KEY \`FK_bf8cd951a7eb12a0eff9b17f82d\``); + await queryRunner.query(`DROP TABLE \`insigniaType\``); + await queryRunner.query(`DROP TABLE \`insignia\``); + } + +} diff --git a/tsoa.json b/tsoa.json index f83c7074..a34af6cb 100644 --- a/tsoa.json +++ b/tsoa.json @@ -88,6 +88,12 @@ }, { "name": "EmployeePosLevel", "description": "ระดับชั้นงานลูกจ้างประจำ" + }, + { + "name": "InsigniaType", "description": "ลำดับชั้นเครื่องราชอิสริยาภรณ์" + }, + { + "name": "Insignia", "description": "เครื่องราชอิสริยาภรณ์" } ] },