diff --git a/src/controllers/PortfolioController.ts b/src/controllers/PortfolioController.ts new file mode 100644 index 0000000..51f4eec --- /dev/null +++ b/src/controllers/PortfolioController.ts @@ -0,0 +1,162 @@ +import { + Controller, + Post, + Put, + Delete, + Route, + Security, + Tags, + Body, + Path, + Request, + SuccessResponse, + Response, + Get, +} 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 { Not } from "typeorm"; +import { CreatePortfolio, Portfolio } from "../entities/Portfolio"; +import { RequestWithUser } from "../middlewares/user"; + +@Route("api/v1/development/portfolio") +@Tags("Portfolio") +@Security("bearerAuth") +@Response( + HttpStatusCode.INTERNAL_SERVER_ERROR, + "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง", +) +@SuccessResponse(HttpStatusCode.OK, "สำเร็จ") +export class PortfolioController extends Controller { + private portfolioRepository = AppDataSource.getRepository(Portfolio); + + /** + * API list รายการผลงาน + * + * @summary ORG_058 - CRUD ผลงาน (ADMIN) #62 + * + */ + @Get() + async GetResult(@Request() request: RequestWithUser) { + const _portfolio = await this.portfolioRepository.find({ + where: { createdUserId: request.user.sub }, + select: [ + "id", + "name", + "detail", + "createdAt", + "lastUpdatedAt", + "createdFullName", + "lastUpdateFullName", + ], + order: { name: "ASC" }, + }); + return new HttpSuccess(_portfolio); + } + + /** + * API รายละเอียดรายการผลงาน + * + * @summary ORG_058 - CRUD ผลงาน (ADMIN) #62 + * + * @param {string} id Id ผลงาน + */ + @Get("{id}") + async GetById(@Path() id: string, @Request() request: RequestWithUser) { + const _portfolio = await this.portfolioRepository.findOne({ + where: { id: id, createdUserId: request.user.sub }, + select: ["id", "name", "detail"], + }); + if (!_portfolio) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผลงานนี้"); + } + + return new HttpSuccess(_portfolio); + } + + /** + * API สร้างรายการ body ผลงาน + * + * @summary ORG_058 - CRUD ผลงาน (ADMIN) #62 + * + */ + @Post() + async Post( + @Body() + requestBody: CreatePortfolio, + @Request() request: RequestWithUser, + ) { + const _portfolio = Object.assign(new Portfolio(), requestBody); + if (!_portfolio) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผลงานนี้"); + } + + const checkName = await this.portfolioRepository.findOne({ + where: { name: requestBody.name, createdUserId: request.user.sub }, + }); + + if (checkName) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ชื่อนี้มีอยู่ในระบบแล้ว"); + } + + _portfolio.createdUserId = request.user.sub; + _portfolio.createdFullName = request.user.name; + _portfolio.lastUpdateUserId = request.user.sub; + _portfolio.lastUpdateFullName = request.user.name; + await this.portfolioRepository.save(_portfolio); + return new HttpSuccess(_portfolio.id); + } + + /** + * API แก้ไขรายการ body ผลงาน + * + * @summary ORG_058 - CRUD ผลงาน (ADMIN) #62 + * + * @param {string} id Id ผลงาน + */ + @Put("{id}") + async Put( + @Path() id: string, + @Body() + requestBody: CreatePortfolio, + @Request() request: RequestWithUser, + ) { + const _portfolio = await this.portfolioRepository.findOne({ where: { id: id } }); + if (!_portfolio) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผลงานนี้"); + } + const checkName = await this.portfolioRepository.findOne({ + where: { id: Not(id), name: requestBody.name, createdUserId: request.user.sub }, + }); + if (checkName) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ชื่อนี้มีอยู่ในระบบแล้ว"); + } + + _portfolio.lastUpdateUserId = request.user.sub; + _portfolio.lastUpdateFullName = request.user.name; + Object.assign(_portfolio, requestBody); + await this.portfolioRepository.save(_portfolio); + return new HttpSuccess(_portfolio.id); + } + + /** + * API ลบรายการผลงาน + * + * @summary ORG_058 - CRUD ผลงาน (ADMIN) #62 + * + * @param {string} id Id ผลงาน + */ + @Delete("{id}") + async Delete(@Path() id: string, @Request() request: RequestWithUser) { + const _delPortfolio = await this.portfolioRepository.findOne({ + where: { id: id, createdUserId: request.user.sub }, + }); + if (!_delPortfolio) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผลงานนี้"); + } + await this.portfolioRepository.delete(_delPortfolio.id); + return new HttpSuccess(); + } +} diff --git a/src/entities/Portfolio.ts b/src/entities/Portfolio.ts new file mode 100644 index 0000000..acff01a --- /dev/null +++ b/src/entities/Portfolio.ts @@ -0,0 +1,25 @@ +import { Entity, Column } from "typeorm"; +import { EntityBase } from "./base/Base"; + +@Entity("portfolio") +export class Portfolio extends EntityBase { + @Column({ + nullable: true, + comment: "ชื่อเอกสาร/ผลงาน", + default: null, + }) + name: string; + + @Column({ + nullable: true, + comment: "รายละเอียดเอกสาร/ผลงาน", + default: null, + }) + detail: string; +} +export class CreatePortfolio { + @Column() + name: string; + @Column() + detail: string | null; +} diff --git a/src/middlewares/user.ts b/src/middlewares/user.ts new file mode 100644 index 0000000..a35cdc4 --- /dev/null +++ b/src/middlewares/user.ts @@ -0,0 +1,13 @@ +import type { Request } from "express"; + +export type RequestWithUser = Request & { + user: { + sub: string; + name: string; + given_name: string; + familiy_name: string; + preferred_username: string; + email: string; + role: string[]; + }; +}; diff --git a/src/migration/1719477296897-add_table_Portfolio.ts b/src/migration/1719477296897-add_table_Portfolio.ts new file mode 100644 index 0000000..e904ba2 --- /dev/null +++ b/src/migration/1719477296897-add_table_Portfolio.ts @@ -0,0 +1,14 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class AddTablePortfolio1719477296897 implements MigrationInterface { + name = 'AddTablePortfolio1719477296897' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`CREATE TABLE \`portfolio\` (\`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 'ชื่อเอกสาร/ผลงาน', \`detail\` varchar(255) NULL COMMENT 'รายละเอียดเอกสาร/ผลงาน', PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE \`portfolio\``); + } + +}