From 57114edac39264636857704597fa86cf272dc459 Mon Sep 17 00:00:00 2001 From: Adisak Date: Thu, 2 Oct 2025 17:31:37 +0700 Subject: [PATCH 1/7] =?UTF-8?q?sort=20=E0=B8=9E=E0=B8=B1=E0=B8=92=E0=B8=99?= =?UTF-8?q?=E0=B8=B2=E0=B8=9A=E0=B8=B8=E0=B8=84=E0=B8=A5=E0=B8=B2=E0=B8=81?= =?UTF-8?q?=E0=B8=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controllers/DevelopmentController.ts | 18 ++++++-- .../DevelopmentHistoryController.ts | 41 +++++++++++++++++-- .../DevelopmentScholarshipController.ts | 41 +++++++++++++++++-- 3 files changed, 91 insertions(+), 9 deletions(-) diff --git a/src/controllers/DevelopmentController.ts b/src/controllers/DevelopmentController.ts index 0642d60..c88ed1d 100644 --- a/src/controllers/DevelopmentController.ts +++ b/src/controllers/DevelopmentController.ts @@ -2022,6 +2022,8 @@ export class DevelopmentController extends Controller { @Query("nodeId") nodeId?: string | null, @Query("node") node?: number | null, @Query("keyword") keyword?: string, + @Query("sortBy") sortBy?: string, + @Query("descending") descending?: boolean, ) { let _data = await new permission().PermissionOrgList(request, "SYS_DEV_PROJECT"); await new CallAPI() @@ -2030,7 +2032,7 @@ export class DevelopmentController extends Controller { _data = x; }) .catch((x) => {}); - const [development, total] = await AppDataSource.getRepository(Development) + let query = await AppDataSource.getRepository(Development) .createQueryBuilder("development") .andWhere(year > 0 ? "development.year LIKE :year" : "1=1", { year: `${year.toString()}`, @@ -2129,8 +2131,18 @@ export class DevelopmentController extends Controller { "development.child3", "development.child4", ]) - .orderBy("development.year", "DESC") - .addOrderBy("development.createdAt", "DESC") + + if (sortBy) { + query = query.orderBy( + `development.${sortBy}`, + descending ? "DESC" : "ASC" + ); + }else{ + query = query.orderBy("development.year", "DESC") + .addOrderBy("development.createdAt", "DESC") + } + + const [development, total] = await query .skip((page - 1) * pageSize) .take(pageSize) .getManyAndCount(); diff --git a/src/controllers/DevelopmentHistoryController.ts b/src/controllers/DevelopmentHistoryController.ts index edb65eb..64c38ec 100644 --- a/src/controllers/DevelopmentHistoryController.ts +++ b/src/controllers/DevelopmentHistoryController.ts @@ -241,11 +241,13 @@ export class DevelopmentOfficerHistoryController extends Controller { keyword?: string; year?: number; root: string | null; + sortBy?: string; + descending?: boolean; }, ) { await new permission().PermissionList(request, "SYS_DEV_HISTORY_OFFICER"); const type = "OFFICER"; - const [development, total] = await AppDataSource.getRepository(DevelopmentHistory) + let query = await AppDataSource.getRepository(DevelopmentHistory) .createQueryBuilder("developmentHistory") .leftJoinAndSelect("developmentHistory.development", "development") .leftJoinAndSelect("developmentHistory.posLevel", "posLevel") @@ -314,11 +316,44 @@ export class DevelopmentOfficerHistoryController extends Controller { ); }), ) - .orderBy("development.year", "DESC") - .addOrderBy("developmentHistory.createdAt", "DESC") + + if (body.sortBy) { + if(body.sortBy === "year" || body.sortBy === "root" || body.sortBy === "projectName"){ + query = query.orderBy( + `development.${body.sortBy}`, + body.descending ? "DESC" : "ASC" + ); + }else if(body.sortBy === "posType"){ + query = query.orderBy( + `posType.posTypeName`, + body.descending ? "DESC" : "ASC" + ); + }else if(body.sortBy === "posLevel"){ + query = query.orderBy( + `posLevel.posLevelName`, + body.descending ? "DESC" : "ASC" + ); + }else if(body.sortBy === "fullName"){ + query = query + .orderBy(`developmentHistory.prefix`,body.descending ? "DESC" : "ASC") + .addOrderBy(`developmentHistory.firstName`,body.descending ? "DESC" : "ASC") + .addOrderBy(`developmentHistory.lastName`,body.descending ? "DESC" : "ASC") + }else{ + query = query.orderBy( + `developmentHistory.${body.sortBy}`, + body.descending ? "DESC" : "ASC" + ); + } + }else{ + query = query.orderBy("development.year", "DESC") + .addOrderBy("developmentHistory.createdAt", "DESC") + } + + const [development, total] = await query .skip((body.page - 1) * body.pageSize) .take(body.pageSize) .getManyAndCount(); + const formattedData = development.map((item) => ({ id: item.id, citizenId: item.citizenId, diff --git a/src/controllers/DevelopmentScholarshipController.ts b/src/controllers/DevelopmentScholarshipController.ts index af23f0a..2fd18d8 100644 --- a/src/controllers/DevelopmentScholarshipController.ts +++ b/src/controllers/DevelopmentScholarshipController.ts @@ -160,6 +160,8 @@ export class DevelopmentScholarshipController extends Controller { @Query("keyword") keyword?: string, @Query("year") year?: number, @Query("scholarshipType") scholarshipType?: string, + @Query("sortBy") sortBy?: string, + @Query("descending") descending?: boolean, ) { let _data = await new permission().PermissionOrgList(request, "SYS_DEV_SCHOLARSHIP"); await new CallAPI() @@ -168,7 +170,7 @@ export class DevelopmentScholarshipController extends Controller { _data = x; }) .catch((x) => {}); - const [development, total] = await AppDataSource.getRepository(DevelopmentScholarship) + let query = await AppDataSource.getRepository(DevelopmentScholarship) .createQueryBuilder("developmentScholarship") .leftJoinAndSelect("developmentScholarship.posLevel", "posLevel") .leftJoinAndSelect("developmentScholarship.posType", "posType") @@ -242,11 +244,44 @@ export class DevelopmentScholarshipController extends Controller { root: _data.root, }, ) - .orderBy("developmentScholarship.scholarshipYear", "DESC") - .addOrderBy("developmentScholarship.createdAt", "DESC") + + if (sortBy) { + if(sortBy === "posType"){ + query = query.orderBy( + `posType.posTypeName`, + descending ? "DESC" : "ASC" + ); + }else if(sortBy === "posLevel"){ + query = query.orderBy( + `posLevel.posLevelName`, + descending ? "DESC" : "ASC" + ); + }else if(sortBy === "year"){ + query = query.orderBy( + `developmentScholarship.scholarshipYear`, + descending ? "DESC" : "ASC" + ); + }else if(sortBy === "fullName"){ + query = query + .orderBy(`developmentScholarship.prefix`,descending ? "DESC" : "ASC") + .addOrderBy(`developmentScholarship.firstName`,descending ? "DESC" : "ASC") + .addOrderBy(`developmentScholarship.lastName`,descending ? "DESC" : "ASC") + }else{ + query = query.orderBy( + `developmentScholarship.${sortBy}`, + descending ? "DESC" : "ASC" + ); + } + }else{ + query = query.orderBy("developmentScholarship.scholarshipYear", "DESC") + .addOrderBy("developmentScholarship.createdAt", "DESC") + } + + const [development, total] = await query .skip((page - 1) * pageSize) .take(pageSize) .getManyAndCount(); + const formattedData = development.map((item) => ({ id: item.id, year: item.scholarshipYear, From 6fec2d906f60dab821d7e237ad3a39244c11fc48 Mon Sep 17 00:00:00 2001 From: Adisak Date: Thu, 2 Oct 2025 18:07:53 +0700 Subject: [PATCH 2/7] update sort --- .../DevelopmentEmployeeHistoryController.ts | 39 +++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/src/controllers/DevelopmentEmployeeHistoryController.ts b/src/controllers/DevelopmentEmployeeHistoryController.ts index 007d978..ba3827e 100644 --- a/src/controllers/DevelopmentEmployeeHistoryController.ts +++ b/src/controllers/DevelopmentEmployeeHistoryController.ts @@ -249,11 +249,13 @@ export class DevelopmentEmployeeHistoryController extends Controller { keyword?: string; year?: number; root: string | null; + sortBy?: string; + descending?: boolean; }, ) { await new permission().PermissionList(request, "SYS_DEV_HISTORY_EMP"); const type = "EMPLOYEE"; - const [development, total] = await AppDataSource.getRepository(DevelopmentHistory) + let query = await AppDataSource.getRepository(DevelopmentHistory) .createQueryBuilder("developmentHistory") .leftJoinAndSelect("developmentHistory.development", "development") .leftJoinAndSelect("developmentHistory.employeePosLevel", "employeePosLevel") @@ -326,8 +328,39 @@ export class DevelopmentEmployeeHistoryController extends Controller { ); }), ) - .orderBy("development.year", "DESC") - .addOrderBy("developmentHistory.createdAt", "DESC") + + if (body.sortBy) { + if(body.sortBy === "year" || body.sortBy === "projectName"){ + query = query.orderBy( + `development.${body.sortBy}`, + body.descending ? "DESC" : "ASC" + ); + }else if(body.sortBy === "posType"){ + query = query.orderBy( + `employeePosType.posTypeName`, + body.descending ? "DESC" : "ASC" + ); + }else if(body.sortBy === "posLevel"){ + query = query + .orderBy(`employeePosLevel.posTypeShortName`,body.descending ? "DESC" : "ASC") + .addOrderBy(`employeePosLevel.posLevelName`,body.descending ? "DESC" : "ASC") + }else if(body.sortBy === "fullName"){ + query = query + .orderBy(`developmentHistory.prefix`,body.descending ? "DESC" : "ASC") + .addOrderBy(`developmentHistory.firstName`,body.descending ? "DESC" : "ASC") + .addOrderBy(`developmentHistory.lastName`,body.descending ? "DESC" : "ASC") + }else{ + query = query.orderBy( + `developmentHistory.${body.sortBy}`, + body.descending ? "DESC" : "ASC" + ); + } + }else{ + query = query.orderBy("development.year", "DESC") + .addOrderBy("developmentHistory.createdAt", "DESC") + } + + const [development, total] = await query .skip((body.page - 1) * body.pageSize) .take(body.pageSize) .getManyAndCount(); From c629bed093557f9d7950d77a6dff0f8dff2e2c90 Mon Sep 17 00:00:00 2001 From: Adisak Date: Fri, 3 Oct 2025 10:13:48 +0700 Subject: [PATCH 3/7] fix --- src/controllers/DevelopmentEmployeeHistoryController.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/DevelopmentEmployeeHistoryController.ts b/src/controllers/DevelopmentEmployeeHistoryController.ts index ba3827e..aeae26e 100644 --- a/src/controllers/DevelopmentEmployeeHistoryController.ts +++ b/src/controllers/DevelopmentEmployeeHistoryController.ts @@ -342,7 +342,7 @@ export class DevelopmentEmployeeHistoryController extends Controller { ); }else if(body.sortBy === "posLevel"){ query = query - .orderBy(`employeePosLevel.posTypeShortName`,body.descending ? "DESC" : "ASC") + .orderBy(`employeePosType.posTypeShortName`,body.descending ? "DESC" : "ASC") .addOrderBy(`employeePosLevel.posLevelName`,body.descending ? "DESC" : "ASC") }else if(body.sortBy === "fullName"){ query = query From 97647bf230c9a703cadd81ee1d9887ad6c4909b5 Mon Sep 17 00:00:00 2001 From: Harid Promsri <52228846+Harid-999@users.noreply.github.com> Date: Mon, 6 Oct 2025 18:03:51 +0700 Subject: [PATCH 4/7] Merge pull request #20 from Frappet/task/#1839 discord-notify.yml --- .github/workflows/discord-notify.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .github/workflows/discord-notify.yml diff --git a/.github/workflows/discord-notify.yml b/.github/workflows/discord-notify.yml new file mode 100644 index 0000000..ce4ee51 --- /dev/null +++ b/.github/workflows/discord-notify.yml @@ -0,0 +1,22 @@ +name: Discord PR Notify + +on: + pull_request: + types: [opened] + +jobs: + discord: + runs-on: ubuntu-latest + steps: + - name: Send Discord + run: | + curl -X POST "${{ secrets.DISCORD_WEBHOOK_PULLREQUEST }}" \ + -H "Content-Type: application/json" \ + -d '{ + "embeds": [{ + "title": "🔔 **Service:** ${{ github.repository }}", + "description": "👤 **Author:** ${{ github.event.pull_request.user.login }}\n🌿 **Branch:** ${{ github.event.pull_request.head.ref }} → ${{ github.event.pull_request.base.ref }}\n📦 **Pull Request:** [#${{ github.event.pull_request.number }} - ${{ github.event.pull_request.title }}](${{ github.event.pull_request.html_url }})", + "color": 5814783, + "timestamp": "${{ github.event.pull_request.created_at }}" + }] + }' From 31b627789201f47ec5d62d943245c09e168576bc Mon Sep 17 00:00:00 2001 From: Adisak Date: Wed, 8 Oct 2025 17:26:09 +0700 Subject: [PATCH 5/7] add budgetSourceOther --- src/controllers/DevelopmentScholarshipController.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/controllers/DevelopmentScholarshipController.ts b/src/controllers/DevelopmentScholarshipController.ts index 2fd18d8..fa3c5e9 100644 --- a/src/controllers/DevelopmentScholarshipController.ts +++ b/src/controllers/DevelopmentScholarshipController.ts @@ -373,6 +373,7 @@ export class DevelopmentScholarshipController extends Controller { : null, scholarshipYear: getDevelopment.scholarshipYear ? getDevelopment.scholarshipYear : null, budgetSource: getDevelopment.budgetSource ? getDevelopment.budgetSource : null, + budgetSourceOther: getDevelopment.budgetSourceOther ? getDevelopment.budgetSourceOther : null, budgetApprove: getDevelopment.budgetApprove ? getDevelopment.budgetApprove : null, bookNo: getDevelopment.bookNo ? getDevelopment.bookNo : null, bookNoDate: getDevelopment.bookNoDate ? getDevelopment.bookNoDate : null, From b3c35e6441fd47626187ed1542aac46d2ee429e0 Mon Sep 17 00:00:00 2001 From: AdisakKanthawilang <153157069+AdisakKanthawilang@users.noreply.github.com> Date: Tue, 14 Oct 2025 17:59:46 +0700 Subject: [PATCH 6/7] update "place" insert (#21) --- src/controllers/DevelopmentController.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/controllers/DevelopmentController.ts b/src/controllers/DevelopmentController.ts index c88ed1d..334c9f2 100644 --- a/src/controllers/DevelopmentController.ts +++ b/src/controllers/DevelopmentController.ts @@ -2629,6 +2629,18 @@ export class DevelopmentController extends Controller { where: { developmentId: id, isDone: false }, relations: ["development"], }); + + const developmentAddresss = await this.developmentAddresssRepository.find({ + where: { developmentId: id} + }) + + const places = developmentAddresss + .map(addr => + `- ${addr.address}, ${addr.addressType === "IN_COUNTRY" ? addr.provinceName : addr.country} (${addr.addressType === "IN_COUNTRY" ? "ภายในประเทศ" : "ภายนอกประเทศ"})` + ) + .filter(Boolean) + .join("\n"); + await Promise.all( getDevelopment.map(async (x) => { const _data = Object.assign(new DevelopmentHistory(), x); @@ -2639,7 +2651,7 @@ export class DevelopmentController extends Controller { name: x.development == null ? null : x.development.projectName, topic: x.development == null ? null : x.development.topicAcademic, yearly: x.development == null ? null : x.development.year, - place: x.development == null ? null : x.development.addressAcademic, + place: places == null ? null : places, duration: x.trainingDays, department: x.development == null ? null : x.development.root, numberOrder: x.order, @@ -2662,7 +2674,7 @@ export class DevelopmentController extends Controller { name: x.development == null ? null : x.development.projectName, topic: x.development == null ? null : x.development.topicAcademic, yearly: x.development == null ? null : x.development.year, - place: x.development == null ? null : x.development.addressAcademic, + place: places == null ? null : places, duration: x.trainingDays, department: x.development == null ? null : x.development.root, numberOrder: x.order, From 16c026e7a47ba93da991cda0f2feb3d42006914d Mon Sep 17 00:00:00 2001 From: Harid Promsri <52228846+Harid-999@users.noreply.github.com> Date: Tue, 21 Oct 2025 14:51:24 +0700 Subject: [PATCH 7/7] fix log (#22) Co-authored-by: harid --- src/interfaces/permission.ts | 84 +++++++++++++----------------------- 1 file changed, 31 insertions(+), 53 deletions(-) diff --git a/src/interfaces/permission.ts b/src/interfaces/permission.ts index cfe76e6..6ff8977 100644 --- a/src/interfaces/permission.ts +++ b/src/interfaces/permission.ts @@ -184,61 +184,39 @@ class CheckAuth { }); } public async checkOrg(token: any, keycloakId: string) { - try { - // Validate required environment variables - const REDIS_HOST = process.env.REDIS_HOST; - const REDIS_PORT = process.env.REDIS_PORT ? Number(process.env.REDIS_PORT) : 6379; + const redisClient = await this.redis.createClient({ + host: process.env.REDIS_HOST, + port: process.env.REDIS_PORT, + }) + const getAsync = promisify(redisClient.get).bind(redisClient) + try { + let reply = await getAsync("org_" + keycloakId) + if (reply != null) { + reply = JSON.parse(reply) + } else { + if (!keycloakId) throw new Error("No KeycloakId provided") + const x = await new CallAPI().GetData( + { + headers: { authorization: token }, + }, + `/org/permission/checkOrg/${keycloakId}`, + false + ) - if (!REDIS_HOST) { - throw new Error("REDIS_HOST is not set in environment variables"); - } + const data = { + orgRootId: x.orgRootId, + orgChild1Id: x.orgChild1Id, + orgChild2Id: x.orgChild2Id, + orgChild3Id: x.orgChild3Id, + orgChild4Id: x.orgChild4Id, + } - console.log(`[REDIS] Connecting to Redis at ${REDIS_HOST}:${REDIS_PORT}`); - - // Create Redis client - const redisClient = this.redis.createClient({ - socket: { - host: REDIS_HOST, - port: REDIS_PORT, - }, - }); - - redisClient.on("error", (err: any) => { - console.error("[REDIS] Connection error:", err.message); - }); - - await redisClient.connect(); - console.log("[REDIS] Connected successfully!"); - - const getAsync = promisify(redisClient.get).bind(redisClient); - - let reply = await getAsync("org_" + keycloakId); - if (reply != null) { - reply = JSON.parse(reply); - } else { - if (!keycloakId) throw new Error("No KeycloakId provided"); - const x = await new CallAPI().GetData( - { - headers: { authorization: token }, - }, - `/org/permission/checkOrg/${keycloakId}`, - false, - ); - - const data = { - orgRootId: x.orgRootId, - orgChild1Id: x.orgChild1Id, - orgChild2Id: x.orgChild2Id, - orgChild3Id: x.orgChild3Id, - orgChild4Id: x.orgChild4Id, - }; - - return data; - } - } catch (error) { - console.error("Error calling API:", error); - throw error; - } + return data + } + } catch (error) { + console.error("Error calling API:", error) + throw error + } } public async PermissionCreate(req: RequestWithUser, system: string) { return await this.Permission(req, system, "CREATE");