Merge branch 'develop' into dev
All checks were successful
Build & Deploy on Dev / build (push) Successful in 48s

* develop:
  Merge pull request #53 from Frappet/issue/#1883
  sort เงินเดือน/ค่าจ้าง
  sort
  update cronjob snapshot
This commit is contained in:
Warunee Tamkoo 2025-10-22 11:07:30 +07:00
commit 6479cbe331
7 changed files with 1575 additions and 425 deletions

View file

@ -306,9 +306,11 @@ export class SalaryController extends Controller {
@Query("page") page: number = 1, @Query("page") page: number = 1,
@Query("pageSize") pageSize: number = 10, @Query("pageSize") pageSize: number = 10,
@Query("keyword") keyword?: string, @Query("keyword") keyword?: string,
@Query("sortBy") sortBy?: string,
@Query("descending") descending?: boolean,
) { ) {
await new permission().PermissionList(request, "SYS_SALARY_CHART_OFFICER"); await new permission().PermissionList(request, "SYS_SALARY_CHART_OFFICER");
const [salary, total] = await AppDataSource.getRepository(Salarys) let query = await AppDataSource.getRepository(Salarys)
.createQueryBuilder("salary") .createQueryBuilder("salary")
.leftJoinAndSelect("salary.posType_", "posType_") .leftJoinAndSelect("salary.posType_", "posType_")
.leftJoinAndSelect("salary.posLevel_", "posLevel_") .leftJoinAndSelect("salary.posLevel_", "posLevel_")
@ -319,9 +321,31 @@ export class SalaryController extends Controller {
.orWhere("posLevel_.posLevelName LIKE :keyword", { keyword: `%${keyword}%` }); .orWhere("posLevel_.posLevelName LIKE :keyword", { keyword: `%${keyword}%` });
}), }),
) )
.orderBy("salary.isActive", "DESC")
.addOrderBy("posType_.posTypeRank", "DESC") if (sortBy) {
.addOrderBy("posLevel_.posLevelRank", "DESC") if(sortBy === "posType"){
query = query.orderBy(
`posType_.posTypeName`,
descending ? "DESC" : "ASC"
);
}else if(sortBy === "posLevel"){
query = query.orderBy(
`posLevel_.posLevelName`,
descending ? "DESC" : "ASC"
);
}else{
query = query.orderBy(
`salary.${sortBy}`,
descending ? "DESC" : "ASC"
);
}
}else{
query = query.orderBy("salary.isActive", "DESC")
.addOrderBy("posType_.posTypeRank", "DESC")
.addOrderBy("posLevel_.posLevelRank", "DESC")
}
const [salary, total] = await query
.skip((page - 1) * pageSize) .skip((page - 1) * pageSize)
.take(pageSize) .take(pageSize)
.getManyAndCount(); .getManyAndCount();

View file

@ -245,9 +245,11 @@ export class SalaryEmployeeController extends Controller {
@Query("page") page: number = 1, @Query("page") page: number = 1,
@Query("pageSize") pageSize: number = 10, @Query("pageSize") pageSize: number = 10,
@Query("keyword") keyword?: string, @Query("keyword") keyword?: string,
@Query("sortBy") sortBy?: string,
@Query("descending") descending?: boolean,
) { ) {
await new permission().PermissionList(request, "SYS_WAGE_CHART_EMP"); await new permission().PermissionList(request, "SYS_WAGE_CHART_EMP");
const [salaryEmployee, total] = await AppDataSource.getRepository(SalaryEmployee) let query = await AppDataSource.getRepository(SalaryEmployee)
.createQueryBuilder("salaryEmployee") .createQueryBuilder("salaryEmployee")
.andWhere( .andWhere(
new Brackets((qb) => { new Brackets((qb) => {
@ -257,12 +259,24 @@ export class SalaryEmployeeController extends Controller {
); );
}), }),
) )
.orderBy("salaryEmployee.isActive", "DESC")
.addOrderBy("salaryEmployee.group", "ASC") if (sortBy) {
query = query.orderBy(
`salaryEmployee.${sortBy}`,
descending ? "DESC" : "ASC"
);
}else{
query = query.orderBy("salaryEmployee.isActive", "DESC")
.addOrderBy("salaryEmployee.group", "ASC")
}
const [salaryEmployee, total] = await query
.skip((page - 1) * pageSize) .skip((page - 1) * pageSize)
.take(pageSize) .take(pageSize)
.getManyAndCount(); .getManyAndCount();
const _salaryEmployee = salaryEmployee.map((item) => ({ const _salaryEmployee = salaryEmployee.map((item) => ({
id: item.id, id: item.id,
name: item.name, name: item.name,

View file

@ -237,8 +237,10 @@ export class SalaryFormulaEmployeeController extends Controller {
@Query("pageSize") pageSize: number = 10, @Query("pageSize") pageSize: number = 10,
@Query("keyword") keyword?: string, @Query("keyword") keyword?: string,
@Query("posTypeId") posTypeId?: string, @Query("posTypeId") posTypeId?: string,
@Query("sortBy") sortBy?: string,
@Query("descending") descending?: boolean,
) { ) {
const [getFormula, total] = await AppDataSource.getRepository(SalaryFormulaEmployee) let query = await AppDataSource.getRepository(SalaryFormulaEmployee)
.createQueryBuilder("salaryFormulaEmployee") .createQueryBuilder("salaryFormulaEmployee")
.leftJoinAndSelect("salaryFormulaEmployee.salaryEmployee", "salaryEmployee") .leftJoinAndSelect("salaryFormulaEmployee.salaryEmployee", "salaryEmployee")
.leftJoinAndSelect("salaryFormulaEmployee.posType", "posType") .leftJoinAndSelect("salaryFormulaEmployee.posType", "posType")
@ -269,10 +271,42 @@ export class SalaryFormulaEmployeeController extends Controller {
) )
.andWhere(posTypeId == undefined ? "1=1" : { posTypeId: Like(`%${posTypeId}%`) }) .andWhere(posTypeId == undefined ? "1=1" : { posTypeId: Like(`%${posTypeId}%`) })
.orderBy("salaryFormulaEmployee.lastUpdatedAt", "DESC") .orderBy("salaryFormulaEmployee.lastUpdatedAt", "DESC")
if (sortBy) {
if(sortBy === "group"){
query = query.orderBy(
`salaryEmployee.group`,
descending ? "DESC" : "ASC"
);
}else if(sortBy === "posLevel"){
query = query.orderBy(
`posLevel.posLevelName`,
descending ? "DESC" : "ASC"
);
}else if(sortBy === "posType"){
query = query.orderBy(
`posType.posTypeName`,
descending ? "DESC" : "ASC"
);
// }else if(sortBy === "salaryEmployeeMin"){
// query = query.orderBy(
// `salaryEmployee.group`,
// descending ? "DESC" : "ASC"
// );
}else{
query = query.orderBy(
`salaryFormulaEmployee.${sortBy}`,
descending ? "DESC" : "ASC"
);
}
}
const [getFormula, total] = await query
.skip((page - 1) * pageSize) .skip((page - 1) * pageSize)
.take(pageSize) .take(pageSize)
.getManyAndCount(); .getManyAndCount();
const mapFormula = getFormula.map((item) => ({ const mapFormula = getFormula.map((item) => ({
id: item.id, id: item.id,
posLevel: posLevel:

File diff suppressed because it is too large Load diff

View file

@ -1080,6 +1080,8 @@ export class SalaryPeriodEmployeeController extends Controller {
keyword?: string; keyword?: string;
type?: any; type?: any;
isRetire?: string | null; isRetire?: string | null;
sortBy?: string,
descending?: boolean,
}, },
) { ) {
await new permission().PermissionList(request, "SYS_WAGE"); await new permission().PermissionList(request, "SYS_WAGE");
@ -1091,7 +1093,7 @@ export class SalaryPeriodEmployeeController extends Controller {
if (!salaryOrg) { if (!salaryOrg) {
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบรอบการขึ้นเงินเดือน"); throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบรอบการขึ้นเงินเดือน");
} }
const [salaryProfile, total] = await AppDataSource.getRepository(SalaryProfileEmployee) let query = await AppDataSource.getRepository(SalaryProfileEmployee)
.createQueryBuilder("profile") .createQueryBuilder("profile")
.andWhere( .andWhere(
new Brackets((qb) => { new Brackets((qb) => {
@ -1156,8 +1158,24 @@ export class SalaryPeriodEmployeeController extends Controller {
); );
}), }),
) )
.orderBy("profile.citizenId", "ASC")
.addOrderBy("profile.isReserve", "ASC") if (body.sortBy) {
if(body.sortBy === "posLevel"){
query = query
.orderBy( `profile.posTypeShort`,body.descending ? "DESC" : "ASC")
.addOrderBy( `profile.posLevel`,body.descending ? "DESC" : "ASC");
}else{
query = query.orderBy(
`profile.${body.sortBy}`,
body.descending ? "DESC" : "ASC"
);
}
}else{
query = query.orderBy("profile.citizenId", "ASC")
.addOrderBy("profile.isReserve", "ASC")
}
const [salaryProfile, total] = await query
.skip((body.page - 1) * body.pageSize) .skip((body.page - 1) * body.pageSize)
.take(body.pageSize) .take(body.pageSize)
.getManyAndCount(); .getManyAndCount();

View file

@ -55,7 +55,7 @@ class CallAPI {
} }
} }
//Post //Post
public async PostData(request: any, @Path() path: any, sendData: any) { public async PostData(request: any, @Path() path: any, sendData: any, log = true) {
const token = "Bearer " + request.headers.authorization.replace("Bearer ", ""); const token = "Bearer " + request.headers.authorization.replace("Bearer ", "");
const url = process.env.API_URL + path; const url = process.env.API_URL + path;
try { try {
@ -67,6 +67,7 @@ class CallAPI {
}, },
}); });
console.log("processing data..."); console.log("processing data...");
if (log)
addLogSequence(request, { addLogSequence(request, {
action: "request", action: "request",
status: "success", status: "success",
@ -80,6 +81,7 @@ class CallAPI {
}); });
return response.data.result; return response.data.result;
} catch (error) { } catch (error) {
if (log)
addLogSequence(request, { addLogSequence(request, {
action: "request", action: "request",
status: "error", status: "error",

View file

@ -184,61 +184,39 @@ class CheckAuth {
}); });
} }
public async checkOrg(token: any, keycloakId: string) { public async checkOrg(token: any, keycloakId: string) {
try { const redisClient = await this.redis.createClient({
// Validate required environment variables host: process.env.REDIS_HOST,
const REDIS_HOST = process.env.REDIS_HOST; port: process.env.REDIS_PORT,
const REDIS_PORT = process.env.REDIS_PORT ? Number(process.env.REDIS_PORT) : 6379; })
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) { const data = {
throw new Error("REDIS_HOST is not set in environment variables"); 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}`); return data
}
// Create Redis client } catch (error) {
const redisClient = this.redis.createClient({ console.error("Error calling API:", error)
socket: { throw error
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;
}
} }
public async PermissionCreate(req: RequestWithUser, system: string) { public async PermissionCreate(req: RequestWithUser, system: string) {
return await this.Permission(req, system, "CREATE"); return await this.Permission(req, system, "CREATE");