diff --git a/src/controllers/DevelopmentController.ts b/src/controllers/DevelopmentController.ts new file mode 100644 index 0000000..baaada6 --- /dev/null +++ b/src/controllers/DevelopmentController.ts @@ -0,0 +1,171 @@ +import { + Controller, + Get, + Post, + Put, + Delete, + Route, + Security, + Tags, + Body, + Path, + Request, + Query, + Example +} from "tsoa"; +import { AppDataSource } from "../database/data-source"; +import { In, Not, MoreThan, Brackets, Like, MoreThanOrEqual, } from "typeorm"; +import HttpSuccess from "../interfaces/http-success"; +import HttpError from "../interfaces/http-error"; +import HttpStatusCode from "../interfaces/http-status"; +import { Development, CreateDevelopment, UpdateDevelopment } from "../entities/Development"; + +@Route("api/v1/development/main") +@Tags("Development") +@Security("bearerAuth") +export class DevelopmentController extends Controller { + private developmentRepository = AppDataSource.getRepository(Development); + + /** + * API เพิ่มโครงการ/หลักสูตรการฝึกอบรม + * + * @summary DEV_001 - เพิ่มโครงการ/หลักสูตรการฝึกอบรม#1 + * + */ + @Post() + @Example({ + name: "", + year: 2024, + }) + async CreateDevelopment( + @Body() requestBody: CreateDevelopment, + @Request() request: { user: Record }, + ) { + const development = Object.assign(new Development(), requestBody); + if (!development) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูล"); + } + const chk_name = await this.developmentRepository.find({ + where: { + name: requestBody.name, + year: requestBody.year + }, + }); + if (chk_name.length > 0) { + throw new HttpError( + HttpStatusCode.NOT_FOUND, + "โครงการ/หลักสูตรการฝึกอบรม: " + requestBody.name + " ปีงบประมาณ: " + requestBody.year + " มีอยู่ในระบบแล้ว", + ); + } + development.createdUserId = request.user.sub; + development.createdFullName = request.user.name; + development.lastUpdateUserId = request.user.sub; + development.lastUpdateFullName = request.user.name; + await this.developmentRepository.save(development); + return new HttpSuccess(development.id); + } + + /** + * API แก้ไขโครงการ/หลักสูตรการฝึกอบรม + * + * @summary DEV_002 - แก้ไขโครงการ/หลักสูตรการฝึกอบรม #2 + * + * @param {string} id Id โครงการ + */ + @Put("{id}") + async UpdateDevelopment( + @Path() id: string, + @Body() requestBody: UpdateDevelopment, + @Request() request: { user: Record }, + ) { + const development = await this.developmentRepository.findOne({ where: { id } }); + if (!development) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลโครงการ/หลักสูตรการฝึกอบรมนี้"); + } + const chk_name = await this.developmentRepository.find({ + where: { + name: requestBody.name, + year: requestBody.year, + id: Not(id) + }, + }); + if (chk_name.length > 0) { + throw new HttpError( + HttpStatusCode.NOT_FOUND, + "โครงการ/หลักสูตรการฝึกอบรม: " + requestBody.name + " ปีงบประมาณ: " + requestBody.year + " มีอยู่ในระบบแล้ว", + ); + } + development.lastUpdateUserId = request.user.sub; + development.lastUpdateFullName = request.user.name; + this.developmentRepository.merge(development, requestBody); + await this.developmentRepository.save(development); + return new HttpSuccess(development.id); + } + + /** + * API ลบโครงการ/หลักสูตรการฝึกอบรม + * + * @summary DEV_003 - ลบโครงการ/หลักสูตรการฝึกอบรม #3 + * + * @param {string} id Id โครงการ + */ + @Delete("{id}") + async DeleteDevelopment(@Path() id: string) { + const delDevelopment = await this.developmentRepository.findOne({ where: { id } }); + if (!delDevelopment) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลโครงการ/หลักสูตรการฝึกอบรมนี้"); + } + await this.developmentRepository.remove(delDevelopment); + return new HttpSuccess(); + } + + /** + * API รายการโครงการ/หลักสูตรการฝึกอบรม + * + * @summary DEV_004 - รายการโครงการ/หลักสูตรการฝึกอบรม #4 + * + */ + @Get() + async GetDevelopmentLists( + @Query("page") page: number = 1, + @Query("pageSize") pageSize: number = 10, + @Query("keyword") keyword?: string, + @Query("year") year: number = 2024, + ) { + const [development, total] = await AppDataSource.getRepository(Development) + .createQueryBuilder("development") + .andWhere(year != 0 ? "development.year LIKE :year" : "1=1", { year: `${year}` }) + .orWhere("development.name LIKE :keyword", { keyword: `${keyword}` }) + .select([ + "development.id", + "development.name", + "development.year", + ]) + .orderBy("development.year", "DESC") + .skip((page - 1) * pageSize) + .take(pageSize) + .getManyAndCount(); + + return new HttpSuccess({ data: development, total }); + } + + /** + * API รายละเอียดโครงการ/หลักสูตรการฝึกอบรม + * + * @summary DEV_005 - รายละเอียดโครงการ/หลักสูตรการฝึกอบรม #5 + * + * @param {string} id Id โครงการ + */ + @Get("{id}") + async GetDevelopemtById(@Path() id: string) { + const getDevelopment = await this.developmentRepository.findOne({ + select: ["id", "name", "year"], + where: { id: id }, + }); + if (!getDevelopment) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลโครงการ/หลักสูตรการฝึกอบรมนี้"); + } + return new HttpSuccess(getDevelopment); + } + +} diff --git a/src/entities/Development.ts b/src/entities/Development.ts new file mode 100644 index 0000000..ca5c2b9 --- /dev/null +++ b/src/entities/Development.ts @@ -0,0 +1,34 @@ +import { Entity, Column, ManyToOne, JoinColumn, OneToOne, OneToMany } from "typeorm"; +import { EntityBase } from "./base/Base"; + +@Entity("development") +export class Development extends EntityBase { + @Column({ + comment: "ชื่อโครงการ/กิจกรรม/หลักสูตร", + length: 255, + }) + name: string; + + @Column({ + nullable: true, + comment: "ปีงบประมาณ", + }) + year: number; + +} + +export class CreateDevelopment { + @Column() + name: string; + + @Column() + year: number; +} + +export class UpdateDevelopment { + @Column() + name: string; + + @Column() + year: number; +} diff --git a/src/interfaces/call-api.ts b/src/interfaces/call-api.ts new file mode 100644 index 0000000..8608230 --- /dev/null +++ b/src/interfaces/call-api.ts @@ -0,0 +1,51 @@ +import { + Controller, + Request, + Get, + Post, + Put, + Delete, + Patch, + Route, + Security, + Tags, + Path, +} from "tsoa"; +import axios from "axios"; + +class CallAPI { + //Get + public async GetData(request: any, @Path() path: any) { + const token = request.headers.authorization; + const url = process.env.API + path; + try { + const response = await axios.get(url, { + headers: { + Authorization: `Bearer ${token}`, + "Content-Type": "application/json", + }, + }); + return response.data.result; + } catch (error) { + throw error; + } + } + //Post + public async PostData(request: any, @Path() path: any, sendData: any) { + const token = request.headers.authorization; + const url = process.env.API + path; + try { + const response = await axios.post(url, sendData, { + headers: { + Authorization: `Bearer ${token}`, + "Content-Type": "application/json", + }, + }); + return response.data.result; + } catch (error) { + throw error; + } + } +} + +export default CallAPI; diff --git a/src/interfaces/extension.ts b/src/interfaces/extension.ts new file mode 100644 index 0000000..1355587 --- /dev/null +++ b/src/interfaces/extension.ts @@ -0,0 +1,81 @@ +class Extension { + public static ToThaiMonth(value: number) { + switch (value) { + case 1: + return "มกราคม"; + case 2: + return "กุมภาพันธ์"; + case 3: + return "มีนาคม"; + case 4: + return "เมษายน"; + case 5: + return "พฤษภาคม"; + case 6: + return "มิถุนายน"; + case 7: + return "กรกฎาคม"; + case 8: + return "สิงหาคม"; + case 9: + return "กันยายน"; + case 10: + return "ตุลาคม"; + case 11: + return "พฤศจิกายน"; + case 12: + return "ธันวาคม"; + default: + return ""; + } + } + + public static ToThaiYear(value: number) { + if (value < 2400) return value + 543; + else return value; + } + + public static ToCeYear(value: number) { + if (value >= 2400) return value - 543; + else return value; + } + + public static ToThaiNumber(value: string) { + let arabicNumbers = "0123456789"; + let thaiNumbers = "๐๑๒๓๔๕๖๗๘๙"; + let result = ""; + for (let digit of value) { + let index = arabicNumbers.indexOf(digit); + if (index >= 0) { + result += thaiNumbers[index]; + } else { + result += digit; + } + } + return result; + } + + public static ToThaiFullDate(value: Date) { + let yy = value.getFullYear() < 2400 ? value.getFullYear() + 543 : value.getFullYear(); + return ( + "วันที่ " + + value.getDate() + + " เดือน " + + Extension.ToThaiMonth(value.getMonth() + 1) + + " พ.ศ. " + + yy + ); + } + + public static sumObjectValues(array: any, propertyName: any) { + let sum = 0; + for (let i = 0; i < array.length; i++) { + if (array[i][propertyName] !== undefined) { + sum += array[i][propertyName]; + } + } + return sum; + } +} + +export default Extension; diff --git a/src/interfaces/storage-fs.ts b/src/interfaces/storage-fs.ts new file mode 100644 index 0000000..63d0769 --- /dev/null +++ b/src/interfaces/storage-fs.ts @@ -0,0 +1,39 @@ +export interface StorageFolder { + /** + * @prop Full path to this folder. It is used as key as there are no files or directories at the same location. + */ + pathname: string; + /** + * @prop Directory / Folder name. + */ + name: string; + + createdAt: string | Date; + createdBy: string | Date; +} + +export interface StorageFile { + /** + * @prop Full path to this folder. It is used as key as there are no files or directories at the same location. + */ + pathname: string; + + fileName: string; + fileSize: number; + fileType: string; + + title: string; + description: string; + author: string; + category: string[]; + keyword: string[]; + metadata: Record; + + path: string; + upload: boolean; + + updatedAt: string | Date; + updatedBy: string; + createdAt: string | Date; + createdBy: string; +} diff --git a/src/migration/1712050402784-add_table_development.ts b/src/migration/1712050402784-add_table_development.ts new file mode 100644 index 0000000..35b2cf5 --- /dev/null +++ b/src/migration/1712050402784-add_table_development.ts @@ -0,0 +1,14 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class AddTableDevelopment1712050402784 implements MigrationInterface { + name = 'AddTableDevelopment1712050402784' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`CREATE TABLE \`development\` (\`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) NOT NULL COMMENT 'ชื่อโครงการ/กิจกรรม/หลักสูตร', \`year\` int NULL COMMENT 'ปีงบประมาณ', PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE \`development\``); + } + +} diff --git a/tsoa.json b/tsoa.json index 5bbc1e5..ff48c69 100644 --- a/tsoa.json +++ b/tsoa.json @@ -28,6 +28,9 @@ "tags": [ { "name": "Test", "description": "สำหรับทดสอบ" + }, + { + "name": "Development", "description": "ชื่อโครงการ/กิจกรรม/หลักสูตร" } ] },