hrms-api-org/src/controllers/ExRetirementController.ts
harid e7a973b764
All checks were successful
Build & Deploy on Dev / build (push) Successful in 1m5s
fix issues #2428 #2383
2026-04-16 15:59:36 +07:00

254 lines
7.9 KiB
TypeScript

import axios from "axios";
import {
Controller,
Post,
Delete,
Route,
Security,
Tags,
Body,
Path,
Request,
Response,
Get,
} from "tsoa";
import HttpError from "../interfaces/http-error";
import HttpStatusCode from "../interfaces/http-status";
import { addLogSequence } from "../interfaces/utils";
import HttpSuccess from "../interfaces/http-success";
interface CachedToken {
token: string;
expiry: Date;
}
const API_URL_BANGKOK = "https://exprofile.bangkok.go.th/API";
const clientId = "e5f6ad6ce374177eef023bf5d0c018b6";
const clientSecret = "5EhOvN5DwHOKakupqT9FmCk7MOwpT3zLqLPkPh4ZhJpxBN2nMG@2022";
class TokenCache {
private static cache: Map<string, CachedToken> = new Map();
static get(key: string): string | null {
const cached = this.cache.get(key);
if (!cached) return null;
return cached.token;
}
static set(key: string, token: string): void {
this.cache.set(key, { token, expiry: new Date(Date.now() + 50 * 60 * 1000) });
}
static delete(key: string): void {
this.cache.delete(key);
}
}
@Route("api/v1/org/ex/retirement")
@Tags("ExRetirement")
@Security("bearerAuth")
export class ExRetirementController extends Controller {
@Post()
async getExRetirement(
@Body()
requestBody: {
type: string; //ประเภท
retireYear: string; //ปีที่เกษียณ
citizenID: string; //เลขบัตรประชาชน
firstNameTH: string; //ชื่อ
lastNameTH: string; //นามสกุล
page: number; //หน้า
},
) {
let retryCount = 0;
const maxRetries = 2;
while (retryCount < maxRetries) {
try {
const token = await getToken(clientId, clientSecret);
if (!token) {
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่สามารถขอ Token ได้");
}
// const scope = requestBody.type === "officer" ? "getOfficerRetireData" : "";
const scope = "getOfficerRetireData";
const startRecord = requestBody.page !== 1 ? (requestBody.page - 1) * 25 : 0;
const formData = new FormData();
formData.append("scope", scope);
formData.append("startRecord", startRecord.toString());
formData.append("retireYear", requestBody.retireYear);
formData.append("citizenID", requestBody.citizenID);
formData.append("firstNameTH", requestBody.firstNameTH);
formData.append("lastNameTH", requestBody.lastNameTH);
formData.append("officerTypeID", requestBody.type === "officer" ? "1" : "2");
const res = await axios.post(API_URL_BANGKOK + "/getData", formData, {
headers: {
Authorization: `Bearer ${token}`,
},
});
// return res.data;
return new HttpSuccess(res.data.data);
} catch (error: any) {
if (error.response?.status === 500 && retryCount < maxRetries - 1) {
TokenCache.delete(`${clientId}:${clientSecret}`);
retryCount++;
continue;
}
throw new HttpError(HttpStatusCode.INTERNAL_SERVER_ERROR, "ไม่สามารถติดต่อ API ได้");
}
}
}
@Get("/document/{documentId}")
async getDocument(@Path("documentId") officerDocumentID: string, @Request() req: any) {
let retryCount = 0;
const maxRetries = 2;
while (retryCount < maxRetries) {
try {
const token = await getToken(clientId, clientSecret);
if (!token) {
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่สามารถขอ Token ได้");
}
const formData = new FormData();
formData.append("scope", "getOfficerRetireFile");
formData.append("officerDocumentID", officerDocumentID);
const res = await axios.post(API_URL_BANGKOK + "/getData", formData, {
headers: {
Authorization: `Bearer ${token}`,
},
responseType: "arraybuffer",
});
if (!req.res.headersSent && !req.res.destroyed) {
// Set response headers
req.res.setHeader("Content-Type", "application/pdf");
req.res.setHeader("Content-Disposition", `inline; filename="${officerDocumentID}.pdf"`);
req.res.setHeader("Content-Length", res.data.byteLength.toString());
req.res.end(Buffer.from(res.data));
return;
}
} catch (error: any) {
if (error.response?.status === 500 && retryCount < maxRetries - 1) {
TokenCache.delete(`${clientId}:${clientSecret}`);
retryCount++;
continue;
}
throw new HttpError(HttpStatusCode.INTERNAL_SERVER_ERROR, "ไม่สามารถติดต่อ API ได้");
}
}
}
}
async function getToken(ClientID: string, ClientSecret: string): Promise<string> {
const cacheKey = `${ClientID}:${ClientSecret}`;
// ลองหา token ใน cache ก่อน
const cachedToken = TokenCache.get(cacheKey);
if (cachedToken) {
return cachedToken;
}
// ถ้าไม่มีใน cache ให้ขอใหม่
try {
const formData = new FormData();
formData.append("ClientID", ClientID);
formData.append("ClientSecret", ClientSecret);
const res = await axios.post(API_URL_BANGKOK + "/authorize", formData, {
headers: {
"Content-Type": "application/json",
},
});
const token = res.data.token;
TokenCache.set(cacheKey, token);
return token;
} catch (error) {
return Promise.reject({ message: "Error occurred", error });
}
}
// function post retire data to exprofile system
export async function PostRetireToExprofile(
request: any,
citizenID: string,
prefix: string,
firstName: string,
lastName: string,
retireYear: string,
positionName: string,
positionTypeName: string,
positionLevelName: string,
retireDate: Date,
organizeName: string, // child4Name child3Name child2Name child1Name rootName
retireTypeName: string, // เช่น เกษียณ, ขอโอนออก, ลาออก, ปลดออก, ไล่ออก, ...
) {
// check NODE_ENV ถ้าเป็น production ถึงจะทำการส่งข้อมูลไปยัง exprofile
const NODE_ENV = process.env.NODE_ENV || "development";
if (NODE_ENV !== "production") {
return;
}
let retryCount = 0;
const maxRetries = 2;
while (retryCount < maxRetries) {
try {
const token = await getToken(clientId, clientSecret);
if (!token) {
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่สามารถขอ Token ได้");
}
const scope = "importOfficerRetireData";
const body = {
scope: scope,
data: {
citizenID: citizenID,
prenameTH: prefix,
firstNameTH: firstName,
lastNameTH: lastName,
retireYear,
positionNameTH: positionName,
positionTypeNameTH: positionTypeName,
positionLevelNameTH: positionLevelName,
retireDate,
organizeNameTH: organizeName,
retireTypeNameTH: retireTypeName,
},
};
const res = await axios.post(API_URL_BANGKOK + "/importData", body, {
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
});
return res.data;
} catch (error: any) {
if (error.response?.status === 500 && retryCount < maxRetries - 1) {
TokenCache.delete(`${clientId}:${clientSecret}`);
retryCount++;
continue;
}
addLogSequence(request, {
action: "request",
status: "error",
description: "unconnected to exprofile api",
request: {
method: "POST",
url: API_URL_BANGKOK + "/importData",
response: JSON.stringify(error),
},
});
throw new HttpError(HttpStatusCode.INTERNAL_SERVER_ERROR, "ไม่สามารถติดต่อ API ได้");
}
}
}