From 89d22b0274a7df41acb0b9cd8e0a15bc128b83da Mon Sep 17 00:00:00 2001 From: waruneeauy Date: Thu, 7 Aug 2025 13:05:58 +0700 Subject: [PATCH] add api web service --- src/controllers/ApiManageController.ts | 609 +++++++++++++++++++++ src/controllers/ApiWebServiceController.ts | 79 +++ src/entities/ApiAttribute.ts | 39 ++ src/entities/ApiName.ts | 52 ++ 4 files changed, 779 insertions(+) create mode 100644 src/controllers/ApiManageController.ts create mode 100644 src/controllers/ApiWebServiceController.ts create mode 100644 src/entities/ApiAttribute.ts diff --git a/src/controllers/ApiManageController.ts b/src/controllers/ApiManageController.ts new file mode 100644 index 00000000..d8ea2348 --- /dev/null +++ b/src/controllers/ApiManageController.ts @@ -0,0 +1,609 @@ +import { ApiAttribute } from "./../entities/ApiAttribute"; +import { CreateApi } from "./../entities/ApiName"; +import { PosMaster } from "../entities/PosMaster"; +import { OrgChild4 } from "../entities/OrgChild4"; +import { OrgChild3 } from "../entities/OrgChild3"; +import { OrgChild2 } from "../entities/OrgChild2"; +import { OrgChild1 } from "../entities/OrgChild1"; +import { OrgRoot } from "../entities/OrgRoot"; +import { ProfileEmployee } from "../entities/ProfileEmployee"; +import { ProfileSalary } from "../entities/ProfileSalary"; +import { ProfileOther } from "../entities/ProfileOther"; +import { ProfileNopaid } from "../entities/ProfileNopaid"; +import { ProfileLeave } from "../entities/ProfileLeave"; +import { ProfileInsignia } from "../entities/ProfileInsignia"; +import { ProfileHonor } from "../entities/ProfileHonor"; +import { ProfileGovernment } from "../entities/ProfileGovernment"; +import { ProfileFamilyMother } from "../entities/ProfileFamilyMother"; +import { ProfileFamilyFather } from "../entities/ProfileFamilyFather"; +import { ProfileFamilyCouple } from "../entities/ProfileFamilyCouple"; +import { ProfileEducation } from "../entities/ProfileEducation"; +import { ProfileDuty } from "../entities/ProfileDuty"; +import { ProfileDiscipline } from "../entities/ProfileDiscipline"; +import { ProfileDevelopment } from "../entities/ProfileDevelopment"; +import { ProfileChildren } from "../entities/ProfileChildren"; +import { ProfileChangeName } from "../entities/ProfileChangeName"; +import { ProfileCertificate } from "../entities/ProfileCertificate"; +import { ProfileAssessment } from "../entities/ProfileAssessment"; +import { ProfileAbility } from "../entities/ProfileAbility"; +import { + Controller, + Post, + Delete, + Route, + Security, + Tags, + Body, + Path, + Request, + Response, + Get, + Put, + 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 { RequestWithUser } from "../middlewares/user"; +import { ApiName } from "../entities/ApiName"; +import { Profile } from "../entities/Profile"; + +@Route("api/v1/org/api-manage") +@Tags("ApiKey") +@Security("bearerAuth") +@Response( + HttpStatusCode.INTERNAL_SERVER_ERROR, + "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง", +) +export class ApiManageController extends Controller { + // private apiNameRepository = AppDataSource.getRepository(ApiName); + private profileRepository = AppDataSource.getRepository(Profile); + private profileEmployeeRepository = AppDataSource.getRepository(ProfileEmployee); + private profileGovernmentRepository = AppDataSource.getRepository(ProfileGovernment); + private profileProfileSalaryRepository = AppDataSource.getRepository(ProfileSalary); + private profileAbilityRepository = AppDataSource.getRepository(ProfileAbility); + private profileAssessmentRepository = AppDataSource.getRepository(ProfileAssessment); + private profileCertificateRepository = AppDataSource.getRepository(ProfileCertificate); + private profileHonorRepository = AppDataSource.getRepository(ProfileHonor); + private profileInsigniaRepository = AppDataSource.getRepository(ProfileInsignia); + private profileLeaveRepository = AppDataSource.getRepository(ProfileLeave); + private profileChangeNameRepository = AppDataSource.getRepository(ProfileChangeName); + private profileDevelopmentRepository = AppDataSource.getRepository(ProfileDevelopment); + private profileDisciplineRepository = AppDataSource.getRepository(ProfileDiscipline); + private profileDutyRepository = AppDataSource.getRepository(ProfileDuty); + private profileEducationRepository = AppDataSource.getRepository(ProfileEducation); + private profileFamilyCoupleRepository = AppDataSource.getRepository(ProfileFamilyCouple); + private profileFamilyFatherRepository = AppDataSource.getRepository(ProfileFamilyFather); + private profileFamilyMotherRepository = AppDataSource.getRepository(ProfileFamilyMother); + private profileChildrenRepository = AppDataSource.getRepository(ProfileChildren); + private profileNopaidRepository = AppDataSource.getRepository(ProfileNopaid); + private profileOtherRepository = AppDataSource.getRepository(ProfileOther); + private orgRootRepository = AppDataSource.getRepository(OrgRoot); + private orgChild1Repository = AppDataSource.getRepository(OrgChild1); + private orgChild2Repository = AppDataSource.getRepository(OrgChild2); + private orgChild3Repository = AppDataSource.getRepository(OrgChild3); + private orgChild4Repository = AppDataSource.getRepository(OrgChild4); + private posMasterRepository = AppDataSource.getRepository(PosMaster); + + private systems = [ + { + code: "registry", + name: "ข้อมูลทะเบียนประวัติข้าราชการ", + }, + { + code: "registry_emp", + name: "ข้อมูลทะเบียนประวัติลูกจ้างประจำ", + }, + { + code: "registry_temp", + name: "ข้อมูลทะเบียนประวัติลูกจ้างชั่วคราว", + }, + { + code: "organization", + name: "ข้อมูลโครงสร้างและอัตรากำลัง", + }, + ]; + /** + * list systems + * @summary รายการ systems + */ + @Get("/systems") + async listSystems() { + return new HttpSuccess(this.systems); + } + + /** + * list fields by systems + * @summary รายการ fields ตาม systems + */ + @Get("/:system/fields") + async listAttribute( + @Request() req: RequestWithUser, + @Path("system") system: "registry" | "registry_emp" | "registry_temp" | "organization", + ): Promise { + try { + if (!req.user.role.includes("SUPER_ADMIN")) { + throw new HttpError(HttpStatusCode.FORBIDDEN, "คุณไม่มีสิทธิ์ในการเข้าถึงข้อมูลนี้"); + } + const entities = [ + { + name: "Profile", + repository: this.profileRepository, + description: "ข้อมูลหลัก", + system: ["registry"], + }, + { + name: "ProfileEmployee", + repository: this.profileEmployeeRepository, + description: "ข้อมูลหลัก", + system: ["registry_emp", "registry_temp"], + }, + { + name: "ProfileGovernment", + repository: this.profileGovernmentRepository, + description: "ข้อมูลราชการ", + system: ["registry", "registry_emp", "registry_temp"], + }, + { + name: "ProfileSalary", + repository: this.profileProfileSalaryRepository, + description: "ข้อมูลตำแหน่ง/เงินเดือน", + system: ["registry", "registry_emp", "registry_temp"], + }, + { + name: "ProfileAbility", + repository: this.profileAbilityRepository, + description: "ข้อมูลความสามารถ", + system: ["registry", "registry_emp", "registry_temp"], + }, + { + name: "ProfileAssessment", + repository: this.profileAssessmentRepository, + description: "ข้อมูลการประเมิน", + system: ["registry", "registry_emp", "registry_temp"], + }, + { + name: "ProfileCertificate", + repository: this.profileCertificateRepository, + description: "ข้อมูลใบรับรอง", + system: ["registry", "registry_emp", "registry_temp"], + }, + { + name: "ProfileHonor", + repository: this.profileHonorRepository, + description: "ข้อมูลเกียรติบัตร", + system: ["registry", "registry_emp", "registry_temp"], + }, + { + name: "ProfileInsignia", + repository: this.profileInsigniaRepository, + description: "ข้อมูลเครื่องหมาย", + system: ["registry", "registry_emp", "registry_temp"], + }, + { + name: "ProfileLeave", + repository: this.profileLeaveRepository, + description: "ข้อมูลการลา", + system: ["registry", "registry_emp", "registry_temp"], + }, + { + name: "ProfileChangeName", + repository: this.profileChangeNameRepository, + description: "ข้อมูลการเปลี่ยนชื่อ", + system: ["registry", "registry_emp", "registry_temp"], + }, + { + name: "ProfileDevelopment", + repository: this.profileDevelopmentRepository, + description: "ข้อมูลการพัฒนา", + system: ["registry", "registry_emp", "registry_temp"], + }, + { + name: "ProfileDiscipline", + repository: this.profileDisciplineRepository, + description: "ข้อมูลวินัย", + system: ["registry", "registry_emp", "registry_temp"], + }, + { + name: "ProfileDuty", + repository: this.profileDutyRepository, + description: "ข้อมูลหน้าที่ปฏิบัติราชการ", + system: ["registry", "registry_emp", "registry_temp"], + }, + { + name: "ProfileEducation", + repository: this.profileEducationRepository, + description: "ข้อมูลการศึกษา", + system: ["registry", "registry_emp", "registry_temp"], + }, + { + name: "ProfileFamilyCouple", + repository: this.profileFamilyCoupleRepository, + description: "ข้อมูลคู่สมรส", + system: ["registry", "registry_emp", "registry_temp"], + }, + { + name: "ProfileFamilyFather", + repository: this.profileFamilyFatherRepository, + description: "ข้อมูลบิดา", + system: ["registry", "registry_emp", "registry_temp"], + }, + { + name: "ProfileFamilyMother", + repository: this.profileFamilyMotherRepository, + description: "ข้อมูลมารดา", + system: ["registry", "registry_emp", "registry_temp"], + }, + { + name: "ProfileChildren", + repository: this.profileChildrenRepository, + description: "ข้อมูลบุตร", + system: ["registry", "registry_emp", "registry_temp"], + }, + { + name: "ProfileNopaid", + repository: this.profileNopaidRepository, + description: "ข้อมูลการไม่จ่ายเงินเดือน", + system: ["registry", "registry_emp", "registry_temp"], + }, + { + name: "ProfileOther", + repository: this.profileOtherRepository, + description: "ข้อมูลอื่นๆ", + system: ["registry", "registry_emp", "registry_temp"], + }, + { + name: "OrgRoot", + repository: this.orgRootRepository, + description: "ข้อมูลหน่วยงาน", + system: ["organization"], + }, + { + name: "OrgChild1", + repository: this.orgChild1Repository, + description: "ข้อมูลส่วนราชการ ระดับที่ 1", + system: ["organization"], + }, + { + name: "OrgChild2", + repository: this.orgChild2Repository, + description: "ข้อมูลส่วนราชการ ระดับที่ 2", + system: ["organization"], + }, + { + name: "OrgChild3", + repository: this.orgChild3Repository, + description: "ข้อมูลส่วนราชการ ระดับที่ 3", + system: ["organization"], + }, + { + name: "OrgChild4", + repository: this.orgChild4Repository, + description: "ข้อมูลส่วนราชการ ระดับที่ 4", + system: ["organization"], + }, + { + name: "PosMaster", + repository: this.posMasterRepository, + description: "ข้อมูลตำแหน่ง", + system: ["organization"], + }, + ]; + + const result = entities + .filter((s) => s.system.includes(system)) + .map(({ name, repository, description }) => ({ + tb: name, + description, + propertys: repository.metadata.columns + .filter( + (column) => + !column.isPrimary && + column.propertyName !== "createdUserId" && + column.propertyName !== "lastUpdateUserId", + ) + .map((column) => ({ + propertyName: column.propertyName, + type: column.type, + comment: column.comment, + key: `${name}.${column.propertyName}`, + })), + })); + + return new HttpSuccess(result); + } catch (error) { + throw new HttpError( + HttpStatusCode.INTERNAL_SERVER_ERROR, + (error instanceof Error ? error.message : String(error)) || + "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง", + ); + } + } + + /** + * list api + * @summary รายการ api + */ + @Get("/lists") + async listApi( + @Request() req: RequestWithUser, + @Query("page") page: number = 1, + @Query("pageSize") pageSize: number = 10, + @Query() searchKeyword: string = "", + ): Promise { + try { + if (!req.user.role.includes("SUPER_ADMIN")) { + throw new HttpError(HttpStatusCode.FORBIDDEN, "คุณไม่มีสิทธิ์ในการเข้าถึงข้อมูลนี้"); + } + const offset = (page - 1) * pageSize; + + const queryBuilder = AppDataSource.getRepository(ApiName) + .createQueryBuilder("apiName") + .select([ + "apiName.id", + "apiName.name", + "apiName.code", + "apiName.pathApi", + "apiName.methodApi", + "apiName.system", + "apiName.isActive", + "apiName.createdAt", + "apiName.lastUpdatedAt", + ]); + + if (searchKeyword?.trim()) { + queryBuilder.where( + "(apiName.name LIKE :keyword OR apiName.code LIKE :keyword OR apiName.pathApi LIKE :keyword)", + { keyword: `%${searchKeyword.trim()}%` }, + ); + } + + const [apiNames, total] = await queryBuilder + .skip(offset) + .take(pageSize) + .orderBy("apiName.lastUpdatedAt", "DESC") + .addOrderBy("apiName.createdAt", "ASC") + .getManyAndCount(); + + return new HttpSuccess({ + data: apiNames, + total, + }); + } catch (error) { + throw new HttpError( + HttpStatusCode.INTERNAL_SERVER_ERROR, + (error instanceof Error ? error.message : String(error)) || + "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง", + ); + } + } + + /** + * สร้าง api + * @summary สร้าง api + */ + @Post("") + async createApi( + @Request() req: RequestWithUser, + @Body() apiData: CreateApi, + ): Promise { + try { + const queryRunner = AppDataSource.createQueryRunner(); + await queryRunner.connect(); + await queryRunner.startTransaction(); + + try { + if (!req.user.role.includes("SUPER_ADMIN")) { + throw new HttpError(HttpStatusCode.FORBIDDEN, "คุณไม่มีสิทธิ์ในการเข้าถึงข้อมูลนี้"); + } + + const code = Math.random().toString(36).substring(2, 10).toUpperCase(); + const postData = { + name: apiData.name, + code, + pathApi: `/api/v2/org/api-service/${apiData.system}/${code}`, + methodApi: apiData.methodApi || "GET", + system: apiData.system || "registry", + isActive: apiData.isActive || false, + createdUserId: req.user?.sub || undefined, + createdFullName: req.user?.name || "", + }; + const apiName = await queryRunner.manager.getRepository(ApiName).save(postData); + + if (apiData.apiAttributes?.length) { + let orderingCounter = 0; + const attributesToSave = apiData.apiAttributes.flatMap((attr) => + attr.propertyKey.map((propertyKey) => ({ + apiNameId: apiName.id, + tbName: attr.tbName, + propertyKey, + ordering: orderingCounter++, + createdUserId: req.user?.sub || undefined, + createdFullName: req.user?.name || "", + })), + ); + + await queryRunner.manager.getRepository(ApiAttribute).save(attributesToSave); + } + + await queryRunner.commitTransaction(); + return new HttpSuccess(apiName.id); + } catch (transactionError) { + await queryRunner.rollbackTransaction(); + throw transactionError; + } finally { + await queryRunner.release(); + } + } catch (error) { + throw new HttpError( + HttpStatusCode.INTERNAL_SERVER_ERROR, + (error instanceof Error ? error.message : String(error)) || + "เกิดข้อผิดพลาด ไม่สามารถบันทึกข้อมูลได้ กรุณาลองใหม่ในภายหลัง", + ); + } + } + + /** + * รายละเอียด api ตามไอดี + * @summary รายละเอียด api ตามไอดี + */ + @Get("/{id}") + async getApiById( + @Request() req: RequestWithUser, + @Path("id") id: string, + ): Promise { + try { + if (!req.user.role.includes("SUPER_ADMIN")) { + throw new HttpError(HttpStatusCode.FORBIDDEN, "คุณไม่มีสิทธิ์ในการเข้าถึงข้อมูลนี้"); + } + + const apiName = await AppDataSource.getRepository(ApiName).findOne({ + select: { + id: true, + name: true, + code: true, + pathApi: true, + methodApi: true, + system: true, + isActive: true, + apiAttributes: true, + }, + where: { id }, + relations: ["apiAttributes"], + order: { + apiAttributes: { + ordering: "ASC", + }, + }, + }); + if (!apiName) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบ API ที่ต้องการแก้ไข"); + } + + const items = { + ...apiName, + apiAttributes: apiName.apiAttributes.map((attr) => ({ + tbName: attr.tbName, + propertyKey: attr.propertyKey, + })), + }; + return new HttpSuccess(items); + } catch (error) { + throw new HttpError( + HttpStatusCode.INTERNAL_SERVER_ERROR, + (error instanceof Error ? error.message : String(error)) || + "เกิดข้อผิดพลาด ไม่สามารถบันทึกข้อมูลได้ กรุณาลองใหม่ในภายหลัง", + ); + } + } + + /** + * แก้ไข api + * @summary แก้ไขข้อมูล api + */ + @Put("/{id}") + async editApi( + @Request() req: RequestWithUser, + @Path("id") id: string, + @Body() apiData: CreateApi, + ): Promise { + try { + const queryRunner = AppDataSource.createQueryRunner(); + await queryRunner.connect(); + await queryRunner.startTransaction(); + + try { + if (!req.user.role.includes("SUPER_ADMIN")) { + throw new HttpError(HttpStatusCode.FORBIDDEN, "คุณไม่มีสิทธิ์ในการเข้าถึงข้อมูลนี้"); + } + + const apiName = await queryRunner.manager.getRepository(ApiName).findOneBy({ id }); + if (!apiName) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบ API ที่ต้องการแก้ไข"); + } + + const updateData = { + name: apiData.name, + pathApi: `/api/v2/org/api-service/${apiData.system}/${apiName.code}`, + methodApi: apiData.methodApi || "GET", + system: apiData.system || "registry", + isActive: apiData.isActive || false, + lastUpdateUserId: req.user?.sub || undefined, + lastUpdateFullName: req.user?.name || "", + }; + await queryRunner.manager.getRepository(ApiName).update(id, updateData); + + await queryRunner.manager.getRepository(ApiAttribute).delete({ apiNameId: id }); + if (apiData.apiAttributes?.length) { + let orderingCounter = 0; + const attributesToSave = apiData.apiAttributes.flatMap((attr) => + attr.propertyKey.map((propertyKey) => ({ + apiNameId: apiName.id, + tbName: attr.tbName, + propertyKey, + ordering: orderingCounter++, + lastUpdateUserId: req.user?.sub || undefined, + lastUpdateFullName: req.user?.name || "", + })), + ); + + await queryRunner.manager.getRepository(ApiAttribute).save(attributesToSave); + } + + await queryRunner.commitTransaction(); + return new HttpSuccess(); + } catch (transactionError) { + await queryRunner.rollbackTransaction(); + throw transactionError; + } finally { + await queryRunner.release(); + } + } catch (error) { + throw new HttpError( + HttpStatusCode.INTERNAL_SERVER_ERROR, + (error instanceof Error ? error.message : String(error)) || + "เกิดข้อผิดพลาด ไม่สามารถบันทึกข้อมูลได้ กรุณาลองใหม่ในภายหลัง", + ); + } + } + + /** + * ลบ api + * @summary ลบข้อมูล api + */ + @Delete("/{id}") + async deleteApi( + @Request() req: RequestWithUser, + @Path("id") id: string, + ): Promise { + try { + const queryRunner = AppDataSource.createQueryRunner(); + await queryRunner.connect(); + await queryRunner.startTransaction(); + + try { + if (!req.user.role.includes("SUPER_ADMIN")) { + throw new HttpError(HttpStatusCode.FORBIDDEN, "คุณไม่มีสิทธิ์ในการเข้าถึงข้อมูลนี้"); + } + + await queryRunner.manager.getRepository(ApiName).delete({ id }); + await queryRunner.manager.getRepository(ApiAttribute).delete({ apiNameId: id }); + + await queryRunner.commitTransaction(); + return new HttpSuccess(); + } catch (transactionError) { + await queryRunner.rollbackTransaction(); + throw transactionError; + } finally { + await queryRunner.release(); + } + } catch (error) { + throw new HttpError( + HttpStatusCode.INTERNAL_SERVER_ERROR, + (error instanceof Error ? error.message : String(error)) || + "เกิดข้อผิดพลาด ไม่สามารถบันทึกข้อมูลได้ กรุณาลองใหม่ในภายหลัง", + ); + } + } +} diff --git a/src/controllers/ApiWebServiceController.ts b/src/controllers/ApiWebServiceController.ts new file mode 100644 index 00000000..77d8486f --- /dev/null +++ b/src/controllers/ApiWebServiceController.ts @@ -0,0 +1,79 @@ +import { + Controller, + Post, + Route, + Security, + Tags, + Body, + Path, + Request, + Response, + Get, + 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 { ApiName } from "../entities/ApiName"; +import { Profile } from "../entities/Profile"; +@Route("api/v2/org/api-service") +@Tags("ApiKey") +// @Security("bearerAuth") +@Response( + HttpStatusCode.INTERNAL_SERVER_ERROR, + "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง", +) +export class ApiWebServiceController extends Controller { + private apiNameRepository = AppDataSource.getRepository(ApiName); + + /** + * list fields by systems + * @summary รายการ fields ตาม systems + */ + @Get("/:system/:code") + async listAttribute( + @Path("system") system: "registry" | "registry_emp" | "registry_temp" | "organization", + @Path("code") code: string, + @Query("page") page: number = 1, + @Query("pageSize") pageSize: number = 100, + ): Promise { + try { + const apiName = await this.apiNameRepository.findOne({ + where: { code }, + select: ["id", "code", "methodApi", "system", "isActive"], + relations: ["apiAttributes"], + order: { + apiAttributes: { + ordering: "ASC", + }, + }, + }); + + if (!apiName || apiName.system != system || !apiName.isActive || apiName.methodApi != "GET") { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบ API ที่ระบุ"); + } + + const offset = (page - 1) * pageSize; + + const propertyKey = apiName.apiAttributes.map((attr) => `${attr.tbName}.${attr.propertyKey}`); + const queryBuilder = AppDataSource.getRepository(Profile) + .createQueryBuilder("Profile") + .select(propertyKey); + + const [items, total] = await queryBuilder + .skip(offset) + .take(pageSize) + .orderBy("Profile.createdAt", "DESC") + .getManyAndCount(); + + return new HttpSuccess({ items, total }); + } catch (error) { + throw new HttpError( + HttpStatusCode.INTERNAL_SERVER_ERROR, + (error instanceof Error ? error.message : String(error)) || + "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง", + ); + } + } +} diff --git a/src/entities/ApiAttribute.ts b/src/entities/ApiAttribute.ts new file mode 100644 index 00000000..3c6a21d5 --- /dev/null +++ b/src/entities/ApiAttribute.ts @@ -0,0 +1,39 @@ +import { ApiName } from "./ApiName"; +import { Entity, Column, ManyToOne, JoinColumn } from "typeorm"; +import { EntityBase } from "./base/Base"; + +@Entity("apiAttribute") +export class ApiAttribute extends EntityBase { + @Column({ + nullable: false, + comment: "ชื่อตาราง", + length: 50, + }) + tbName: string; + + @Column({ + nullable: false, + comment: "คีย์ของแอตทริบิวต์", + length: 255, + }) + propertyKey: string; + + @Column({ + nullable: false, + comment: "ลำดับการแสดงผล", + default: 0, + type: "int", + }) + ordering: number; + + @Column({ + nullable: false, + comment: "ไอดีของ API Name", + length: 36, // UUID length + }) + apiNameId: string; + + @ManyToOne(() => ApiName, (apiName) => apiName.apiAttributes) + @JoinColumn({ name: "apiNameId" }) + apiName: ApiName; +} diff --git a/src/entities/ApiName.ts b/src/entities/ApiName.ts index 510e51df..db9d5bf5 100644 --- a/src/entities/ApiName.ts +++ b/src/entities/ApiName.ts @@ -1,3 +1,4 @@ +import { ApiAttribute } from "./ApiAttribute"; import { Entity, Column, ManyToMany, JoinTable, OneToMany } from "typeorm"; import { EntityBase } from "./base/Base"; import { ApiKey } from "./ApiKey"; @@ -29,10 +30,61 @@ export class ApiName extends EntityBase { }) methodApi: string; + @Column({ + nullable: false, + comment: "code สำหรับการเรียก API", + length: 8, + }) + code: string; + + @Column({ + nullable: false, + comment: "code ระบบสำหรับการเรียก API", + length: 50, + default: "registry", + }) + system: string; + + @Column({ + nullable: false, + comment: "สถานะการใช้งาน", + type: "boolean", + default: false, + }) + isActive: boolean; + @ManyToMany(() => ApiKey, (apiKey) => apiKey.apiNames) @JoinTable() apiKeys: ApiKey[]; @OneToMany(() => ApiHistory, (v) => v.apiName) apiHistorys: ApiHistory[]; + + @OneToMany(() => ApiAttribute, (v) => v.apiName) + apiAttributes: ApiAttribute[]; +} + +export class CreateApi { + @Column() + name: string; + + @Column() + methodApi: "GET" | "POST" | "PUT"; + + @Column() + system: string; + + @Column() + isActive: boolean; + + @Column() + apiAttributes: CreateApiAttribute[]; +} + +export class CreateApiAttribute { + @Column() + tbName: string; + + @Column() + propertyKey: string[]; }