Merge branch 'develop'
This commit is contained in:
commit
4103863df3
22 changed files with 3085 additions and 224 deletions
780
src/controllers/ApiManageController.ts
Normal file
780
src/controllers/ApiManageController.ts
Normal file
|
|
@ -0,0 +1,780 @@
|
|||
import { Position } from "./../entities/Position";
|
||||
import { ApiKey } from "./../entities/ApiKey";
|
||||
import { ApiAttribute } from "./../entities/ApiAttribute";
|
||||
import { CreateApi } from "./../entities/ApiName";
|
||||
import { PosMaster } from "../entities/PosMaster";
|
||||
import { OrgChild4 } from "../entities/OrgChild4";
|
||||
import { OrgChild3 } from "../entities/OrgChild3";
|
||||
import { OrgChild2 } from "../entities/OrgChild2";
|
||||
import { OrgChild1 } from "../entities/OrgChild1";
|
||||
import { OrgRoot } from "../entities/OrgRoot";
|
||||
import { ProfileEmployee } from "../entities/ProfileEmployee";
|
||||
import { ProfileSalary } from "../entities/ProfileSalary";
|
||||
import { ProfileOther } from "../entities/ProfileOther";
|
||||
import { ProfileNopaid } from "../entities/ProfileNopaid";
|
||||
import { ProfileLeave } from "../entities/ProfileLeave";
|
||||
import { ProfileInsignia } from "../entities/ProfileInsignia";
|
||||
import { ProfileHonor } from "../entities/ProfileHonor";
|
||||
import { ProfileGovernment } from "../entities/ProfileGovernment";
|
||||
import { ProfileFamilyMother } from "../entities/ProfileFamilyMother";
|
||||
import { ProfileFamilyFather } from "../entities/ProfileFamilyFather";
|
||||
import { ProfileFamilyCouple } from "../entities/ProfileFamilyCouple";
|
||||
import { ProfileEducation } from "../entities/ProfileEducation";
|
||||
import { ProfileDuty } from "../entities/ProfileDuty";
|
||||
import { ProfileDiscipline } from "../entities/ProfileDiscipline";
|
||||
import { ProfileDevelopment } from "../entities/ProfileDevelopment";
|
||||
import { ProfileChildren } from "../entities/ProfileChildren";
|
||||
import { ProfileChangeName } from "../entities/ProfileChangeName";
|
||||
import { ProfileCertificate } from "../entities/ProfileCertificate";
|
||||
import { ProfileAssessment } from "../entities/ProfileAssessment";
|
||||
import { ProfileAbility } from "../entities/ProfileAbility";
|
||||
import {
|
||||
Controller,
|
||||
Post,
|
||||
Delete,
|
||||
Route,
|
||||
Security,
|
||||
Tags,
|
||||
Body,
|
||||
Path,
|
||||
Request,
|
||||
Response,
|
||||
Get,
|
||||
Put,
|
||||
Query,
|
||||
} 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 { RequestWithUser } from "../middlewares/user";
|
||||
import { ApiName } from "../entities/ApiName";
|
||||
import { Profile } from "../entities/Profile";
|
||||
import { SystemDefinition, EntityDefinition, SystemCode } from "./../interfaces/api-type";
|
||||
@Route("api/v1/org/api-manage")
|
||||
@Tags("ApiManage")
|
||||
@Security("bearerAuth")
|
||||
@Response(
|
||||
HttpStatusCode.INTERNAL_SERVER_ERROR,
|
||||
"เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง",
|
||||
)
|
||||
export class ApiManageController extends Controller {
|
||||
private readonly profileRepository = AppDataSource.getRepository(Profile);
|
||||
private readonly profileEmployeeRepository = AppDataSource.getRepository(ProfileEmployee);
|
||||
private readonly profileGovernmentRepository = AppDataSource.getRepository(ProfileGovernment);
|
||||
private readonly profileProfileSalaryRepository = AppDataSource.getRepository(ProfileSalary);
|
||||
private readonly profileAbilityRepository = AppDataSource.getRepository(ProfileAbility);
|
||||
private readonly profileAssessmentRepository = AppDataSource.getRepository(ProfileAssessment);
|
||||
private readonly profileCertificateRepository = AppDataSource.getRepository(ProfileCertificate);
|
||||
private readonly profileHonorRepository = AppDataSource.getRepository(ProfileHonor);
|
||||
private readonly profileInsigniaRepository = AppDataSource.getRepository(ProfileInsignia);
|
||||
private readonly profileLeaveRepository = AppDataSource.getRepository(ProfileLeave);
|
||||
private readonly profileChangeNameRepository = AppDataSource.getRepository(ProfileChangeName);
|
||||
private readonly profileDevelopmentRepository = AppDataSource.getRepository(ProfileDevelopment);
|
||||
private readonly profileDisciplineRepository = AppDataSource.getRepository(ProfileDiscipline);
|
||||
private readonly profileDutyRepository = AppDataSource.getRepository(ProfileDuty);
|
||||
private readonly profileEducationRepository = AppDataSource.getRepository(ProfileEducation);
|
||||
private readonly profileFamilyCoupleRepository = AppDataSource.getRepository(ProfileFamilyCouple);
|
||||
private readonly profileFamilyFatherRepository = AppDataSource.getRepository(ProfileFamilyFather);
|
||||
private readonly profileFamilyMotherRepository = AppDataSource.getRepository(ProfileFamilyMother);
|
||||
private readonly profileChildrenRepository = AppDataSource.getRepository(ProfileChildren);
|
||||
private readonly profileNopaidRepository = AppDataSource.getRepository(ProfileNopaid);
|
||||
private readonly profileOtherRepository = AppDataSource.getRepository(ProfileOther);
|
||||
private readonly orgRootRepository = AppDataSource.getRepository(OrgRoot);
|
||||
private readonly orgChild1Repository = AppDataSource.getRepository(OrgChild1);
|
||||
private readonly orgChild2Repository = AppDataSource.getRepository(OrgChild2);
|
||||
private readonly orgChild3Repository = AppDataSource.getRepository(OrgChild3);
|
||||
private readonly orgChild4Repository = AppDataSource.getRepository(OrgChild4);
|
||||
private readonly posMasterRepository = AppDataSource.getRepository(PosMaster);
|
||||
private readonly positionRepository = AppDataSource.getRepository(Position);
|
||||
|
||||
// รายการระบบ
|
||||
private readonly systems: SystemDefinition[] = [
|
||||
{
|
||||
code: "registry",
|
||||
name: "ข้อมูลทะเบียนประวัติข้าราชการ",
|
||||
},
|
||||
{
|
||||
code: "registry_emp",
|
||||
name: "ข้อมูลทะเบียนประวัติลูกจ้างประจำ",
|
||||
},
|
||||
{
|
||||
code: "registry_temp",
|
||||
name: "ข้อมูลทะเบียนประวัติลูกจ้างชั่วคราว",
|
||||
},
|
||||
{
|
||||
code: "organization",
|
||||
name: "ข้อมูลโครงสร้าง",
|
||||
},
|
||||
{
|
||||
code: "position",
|
||||
name: "ข้อมูลอัตรากำลัง",
|
||||
},
|
||||
];
|
||||
|
||||
// รายการเอนทิตีทั้งหมด
|
||||
private readonly entities: EntityDefinition[] = [
|
||||
{
|
||||
name: "Profile",
|
||||
repository: this.profileRepository,
|
||||
description: "ข้อมูลหลัก",
|
||||
isMain: true,
|
||||
system: ["registry"],
|
||||
},
|
||||
{
|
||||
name: "ProfileEmployee",
|
||||
repository: this.profileEmployeeRepository,
|
||||
description: "ข้อมูลหลัก",
|
||||
isMain: true,
|
||||
system: ["registry_emp", "registry_temp"],
|
||||
},
|
||||
{
|
||||
name: "ProfileGovernment",
|
||||
repository: this.profileGovernmentRepository,
|
||||
description: "ข้อมูลราชการ",
|
||||
system: ["registry", "registry_emp", "registry_temp"],
|
||||
},
|
||||
{
|
||||
name: "ProfileSalary",
|
||||
repository: this.profileProfileSalaryRepository,
|
||||
description: "ข้อมูลตำแหน่ง/เงินเดือน",
|
||||
system: ["registry", "registry_emp", "registry_temp"],
|
||||
},
|
||||
{
|
||||
name: "ProfileAbility",
|
||||
repository: this.profileAbilityRepository,
|
||||
description: "ข้อมูลความสามารถ",
|
||||
system: ["registry", "registry_emp", "registry_temp"],
|
||||
},
|
||||
{
|
||||
name: "ProfileAssessment",
|
||||
repository: this.profileAssessmentRepository,
|
||||
description: "ข้อมูลการประเมิน",
|
||||
system: ["registry", "registry_emp", "registry_temp"],
|
||||
},
|
||||
{
|
||||
name: "ProfileCertificate",
|
||||
repository: this.profileCertificateRepository,
|
||||
description: "ข้อมูลใบรับรอง",
|
||||
system: ["registry", "registry_emp", "registry_temp"],
|
||||
},
|
||||
{
|
||||
name: "ProfileHonor",
|
||||
repository: this.profileHonorRepository,
|
||||
description: "ข้อมูลเกียรติบัตร",
|
||||
system: ["registry", "registry_emp", "registry_temp"],
|
||||
},
|
||||
{
|
||||
name: "ProfileInsignia",
|
||||
repository: this.profileInsigniaRepository,
|
||||
description: "ข้อมูลเครื่องหมาย",
|
||||
system: ["registry", "registry_emp", "registry_temp"],
|
||||
},
|
||||
{
|
||||
name: "ProfileLeave",
|
||||
repository: this.profileLeaveRepository,
|
||||
description: "ข้อมูลการลา",
|
||||
system: ["registry", "registry_emp", "registry_temp"],
|
||||
},
|
||||
{
|
||||
name: "ProfileChangeName",
|
||||
repository: this.profileChangeNameRepository,
|
||||
description: "ข้อมูลการเปลี่ยนชื่อ",
|
||||
system: ["registry", "registry_emp", "registry_temp"],
|
||||
},
|
||||
{
|
||||
name: "ProfileDevelopment",
|
||||
repository: this.profileDevelopmentRepository,
|
||||
description: "ข้อมูลการพัฒนา",
|
||||
system: ["registry", "registry_emp", "registry_temp"],
|
||||
},
|
||||
{
|
||||
name: "ProfileDiscipline",
|
||||
repository: this.profileDisciplineRepository,
|
||||
description: "ข้อมูลวินัย",
|
||||
system: ["registry", "registry_emp", "registry_temp"],
|
||||
},
|
||||
{
|
||||
name: "ProfileDuty",
|
||||
repository: this.profileDutyRepository,
|
||||
description: "ข้อมูลหน้าที่ปฏิบัติราชการ",
|
||||
system: ["registry", "registry_emp", "registry_temp"],
|
||||
},
|
||||
{
|
||||
name: "ProfileEducation",
|
||||
repository: this.profileEducationRepository,
|
||||
description: "ข้อมูลการศึกษา",
|
||||
system: ["registry", "registry_emp", "registry_temp"],
|
||||
},
|
||||
{
|
||||
name: "ProfileFamilyCouple",
|
||||
repository: this.profileFamilyCoupleRepository,
|
||||
description: "ข้อมูลคู่สมรส",
|
||||
system: ["registry", "registry_emp", "registry_temp"],
|
||||
},
|
||||
{
|
||||
name: "ProfileFamilyFather",
|
||||
repository: this.profileFamilyFatherRepository,
|
||||
description: "ข้อมูลบิดา",
|
||||
system: ["registry", "registry_emp", "registry_temp"],
|
||||
},
|
||||
{
|
||||
name: "ProfileFamilyMother",
|
||||
repository: this.profileFamilyMotherRepository,
|
||||
description: "ข้อมูลมารดา",
|
||||
system: ["registry", "registry_emp", "registry_temp"],
|
||||
},
|
||||
{
|
||||
name: "ProfileChildren",
|
||||
repository: this.profileChildrenRepository,
|
||||
description: "ข้อมูลบุตร",
|
||||
system: ["registry", "registry_emp", "registry_temp"],
|
||||
},
|
||||
{
|
||||
name: "ProfileNopaid",
|
||||
repository: this.profileNopaidRepository,
|
||||
description: "ข้อมูลการไม่จ่ายเงินเดือน",
|
||||
system: ["registry", "registry_emp", "registry_temp"],
|
||||
},
|
||||
{
|
||||
name: "ProfileOther",
|
||||
repository: this.profileOtherRepository,
|
||||
description: "ข้อมูลอื่นๆ",
|
||||
system: ["registry", "registry_emp", "registry_temp"],
|
||||
},
|
||||
{
|
||||
name: "OrgRoot",
|
||||
repository: this.orgRootRepository,
|
||||
description: "ข้อมูลหน่วยงาน",
|
||||
isMain: true,
|
||||
system: ["organization"],
|
||||
},
|
||||
{
|
||||
name: "OrgChild1",
|
||||
repository: this.orgChild1Repository,
|
||||
description: "ข้อมูลส่วนราชการ ระดับที่ 1",
|
||||
system: ["organization"],
|
||||
},
|
||||
{
|
||||
name: "OrgChild2",
|
||||
repository: this.orgChild2Repository,
|
||||
description: "ข้อมูลส่วนราชการ ระดับที่ 2",
|
||||
system: ["organization"],
|
||||
},
|
||||
{
|
||||
name: "OrgChild3",
|
||||
repository: this.orgChild3Repository,
|
||||
description: "ข้อมูลส่วนราชการ ระดับที่ 3",
|
||||
system: ["organization"],
|
||||
},
|
||||
{
|
||||
name: "OrgChild4",
|
||||
repository: this.orgChild4Repository,
|
||||
description: "ข้อมูลส่วนราชการ ระดับที่ 4",
|
||||
system: ["organization"],
|
||||
},
|
||||
{
|
||||
name: "PosMaster",
|
||||
repository: this.posMasterRepository,
|
||||
description: "ข้อมูลอัตรากำลัง",
|
||||
isMain: true,
|
||||
system: ["position"],
|
||||
},
|
||||
{
|
||||
name: "Position",
|
||||
repository: this.positionRepository,
|
||||
description: "ข้อมูลตำแหน่ง",
|
||||
system: ["position"],
|
||||
},
|
||||
{
|
||||
name: "OrgRoot",
|
||||
repository: this.orgRootRepository,
|
||||
description: "ข้อมูลหน่วยงาน",
|
||||
system: ["position"],
|
||||
},
|
||||
{
|
||||
name: "OrgChild1",
|
||||
repository: this.orgChild1Repository,
|
||||
description: "ข้อมูลส่วนราชการ ระดับที่ 1",
|
||||
system: ["position"],
|
||||
},
|
||||
{
|
||||
name: "OrgChild2",
|
||||
repository: this.orgChild2Repository,
|
||||
description: "ข้อมูลส่วนราชการ ระดับที่ 2",
|
||||
system: ["position"],
|
||||
},
|
||||
{
|
||||
name: "OrgChild3",
|
||||
repository: this.orgChild3Repository,
|
||||
description: "ข้อมูลส่วนราชการ ระดับที่ 3",
|
||||
system: ["position"],
|
||||
},
|
||||
{
|
||||
name: "OrgChild4",
|
||||
repository: this.orgChild4Repository,
|
||||
description: "ข้อมูลส่วนราชการ ระดับที่ 4",
|
||||
system: ["position"],
|
||||
},
|
||||
{
|
||||
name: "Profile",
|
||||
repository: this.profileRepository,
|
||||
description: "ข้อมูลคนครอง",
|
||||
system: ["position"],
|
||||
},
|
||||
];
|
||||
|
||||
private readonly DEFAULT_PAGE_SIZE = 10; // ขนาดหน้าเริ่มต้น
|
||||
private readonly EXCLUDED_COLUMNS = ["createdUserId", "lastUpdateUserId"]; // ฟิลด์ที่ไม่ต้องการแสดงในผลลัพธ์
|
||||
|
||||
private validateSuperAdminRole(user: any): void {
|
||||
if (!user.role.includes("SUPER_ADMIN")) {
|
||||
throw new HttpError(HttpStatusCode.FORBIDDEN, "คุณไม่มีสิทธิ์ในการเข้าถึงข้อมูลนี้");
|
||||
}
|
||||
}
|
||||
|
||||
private generateApiCode(): string {
|
||||
return Math.random().toString(36).substring(2, 10).toUpperCase();
|
||||
}
|
||||
|
||||
private createApiPath(system: SystemCode = "registry", code: string): string {
|
||||
return `/api/v1/org/api-service/${system}/${code}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* list systems
|
||||
* @summary รายการ systems
|
||||
*/
|
||||
@Get("/systems")
|
||||
async listSystems(): Promise<HttpSuccess> {
|
||||
return new HttpSuccess(this.systems);
|
||||
}
|
||||
|
||||
/**
|
||||
* list fields by systems
|
||||
* @summary รายการ fields ตาม systems
|
||||
*/
|
||||
@Get("/:system/fields")
|
||||
async listAttribute(
|
||||
@Request() req: RequestWithUser,
|
||||
@Path("system") system: SystemCode,
|
||||
): Promise<HttpSuccess | HttpError> {
|
||||
try {
|
||||
this.validateSuperAdminRole(req.user);
|
||||
|
||||
const result = this.entities
|
||||
.filter((entity) => entity.system.includes(system))
|
||||
.map(({ name, repository, description, isMain }) => ({
|
||||
tb: name,
|
||||
description,
|
||||
isMain: isMain || false,
|
||||
propertys: repository.metadata.columns
|
||||
.filter(
|
||||
(column: any) =>
|
||||
!column.isPrimary && !this.EXCLUDED_COLUMNS.includes(column.propertyName),
|
||||
)
|
||||
.map((column: any) => ({
|
||||
propertyName: column.propertyName,
|
||||
type: typeof column.type === "string" ? column.type : "string",
|
||||
comment: column.comment,
|
||||
key: column.propertyName,
|
||||
})),
|
||||
}));
|
||||
|
||||
return new HttpSuccess(result);
|
||||
} catch (error) {
|
||||
throw new HttpError(
|
||||
HttpStatusCode.INTERNAL_SERVER_ERROR,
|
||||
(error instanceof Error ? error.message : String(error)) ||
|
||||
"เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* list api
|
||||
* @summary รายการ api
|
||||
*/
|
||||
@Get("/lists")
|
||||
async listApi(
|
||||
@Request() req: RequestWithUser,
|
||||
@Query("page") page: number = 1,
|
||||
@Query("pageSize") pageSize: number = this.DEFAULT_PAGE_SIZE,
|
||||
@Query("keyword") keyword: string = "",
|
||||
@Query("system") system: SystemCode | "" = "",
|
||||
@Query("isActive") isActive: boolean = true,
|
||||
): Promise<HttpSuccess | HttpError> {
|
||||
try {
|
||||
this.validateSuperAdminRole(req.user);
|
||||
|
||||
const offset = (page - 1) * pageSize;
|
||||
const queryBuilder = AppDataSource.getRepository(ApiName)
|
||||
.createQueryBuilder("apiName")
|
||||
.where("apiName.isActive = :isActive", { isActive })
|
||||
.select([
|
||||
"apiName.id",
|
||||
"apiName.name",
|
||||
"apiName.code",
|
||||
"apiName.pathApi",
|
||||
"apiName.methodApi",
|
||||
"apiName.system",
|
||||
"apiName.isActive",
|
||||
"apiName.createdAt",
|
||||
"apiName.lastUpdatedAt",
|
||||
]);
|
||||
|
||||
if (keyword?.trim()) {
|
||||
queryBuilder.andWhere(
|
||||
"(apiName.name LIKE :keyword OR apiName.code LIKE :keyword OR apiName.pathApi LIKE :keyword)",
|
||||
{ keyword: `%${keyword.trim()}%` },
|
||||
);
|
||||
}
|
||||
|
||||
if (system) {
|
||||
queryBuilder.andWhere("apiName.system = :system", { system });
|
||||
}
|
||||
|
||||
const [apiNames, total] = await queryBuilder
|
||||
.skip(offset)
|
||||
.take(pageSize)
|
||||
.orderBy("apiName.lastUpdatedAt", "DESC")
|
||||
.addOrderBy("apiName.createdAt", "ASC")
|
||||
.getManyAndCount();
|
||||
|
||||
return new HttpSuccess({
|
||||
data: apiNames.map((api) => ({
|
||||
...api,
|
||||
system: this.systems.find((s) => s.code === api.system)?.name || api.system,
|
||||
})),
|
||||
total,
|
||||
});
|
||||
} catch (error) {
|
||||
throw new HttpError(
|
||||
HttpStatusCode.INTERNAL_SERVER_ERROR,
|
||||
(error instanceof Error ? error.message : String(error)) ||
|
||||
"เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* สร้าง api
|
||||
* @summary สร้าง api
|
||||
*/
|
||||
@Post("")
|
||||
async createApi(
|
||||
@Request() req: RequestWithUser,
|
||||
@Body() apiData: CreateApi,
|
||||
): Promise<HttpSuccess | HttpError> {
|
||||
const queryRunner = AppDataSource.createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
|
||||
try {
|
||||
this.validateSuperAdminRole(req.user);
|
||||
|
||||
const code = this.generateApiCode();
|
||||
const postData = {
|
||||
name: apiData.name,
|
||||
code,
|
||||
pathApi: this.createApiPath(apiData.system as SystemCode, code),
|
||||
methodApi: apiData.methodApi || "GET",
|
||||
system: apiData.system || "registry",
|
||||
isActive: apiData.isActive || false,
|
||||
createdUserId: req.user?.sub,
|
||||
createdFullName: req.user?.name || "",
|
||||
};
|
||||
|
||||
const apiName = await queryRunner.manager.getRepository(ApiName).save(postData);
|
||||
|
||||
if (apiData.apiAttributes?.length) {
|
||||
let orderingCounter = 0;
|
||||
const attributesToSave = apiData.apiAttributes.flatMap((attr) =>
|
||||
attr.propertyKey.map((propertyKey) => ({
|
||||
apiNameId: apiName.id,
|
||||
tbName: attr.tbName,
|
||||
propertyKey,
|
||||
ordering: orderingCounter++,
|
||||
createdUserId: req.user?.sub,
|
||||
createdFullName: req.user?.name || "",
|
||||
})),
|
||||
);
|
||||
|
||||
await queryRunner.manager.getRepository(ApiAttribute).save(attributesToSave);
|
||||
}
|
||||
|
||||
await queryRunner.commitTransaction();
|
||||
return new HttpSuccess(apiName.id);
|
||||
} catch (error) {
|
||||
await queryRunner.rollbackTransaction();
|
||||
throw new HttpError(
|
||||
HttpStatusCode.INTERNAL_SERVER_ERROR,
|
||||
(error instanceof Error ? error.message : String(error)) ||
|
||||
"เกิดข้อผิดพลาด ไม่สามารถบันทึกข้อมูลได้ กรุณาลองใหม่ในภายหลัง",
|
||||
);
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* รายละเอียด api ตามไอดี
|
||||
* @summary รายละเอียด api ตามไอดี
|
||||
*/
|
||||
@Get("/{id}")
|
||||
async getApiById(
|
||||
@Request() req: RequestWithUser,
|
||||
@Path("id") id: string,
|
||||
): Promise<HttpSuccess | HttpError> {
|
||||
try {
|
||||
this.validateSuperAdminRole(req.user);
|
||||
|
||||
const apiName = await AppDataSource.getRepository(ApiName).findOne({
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
code: true,
|
||||
pathApi: true,
|
||||
methodApi: true,
|
||||
system: true,
|
||||
isActive: true,
|
||||
apiAttributes: true,
|
||||
},
|
||||
where: { id },
|
||||
relations: ["apiAttributes"],
|
||||
order: {
|
||||
apiAttributes: {
|
||||
ordering: "ASC",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!apiName) {
|
||||
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบ API ที่ต้องการแก้ไข");
|
||||
}
|
||||
|
||||
const items = {
|
||||
...apiName,
|
||||
apiAttributes: apiName.apiAttributes.map((attr) => ({
|
||||
tbName: attr.tbName,
|
||||
propertyKey: attr.propertyKey,
|
||||
})),
|
||||
};
|
||||
|
||||
return new HttpSuccess(items);
|
||||
} catch (error) {
|
||||
throw new HttpError(
|
||||
HttpStatusCode.INTERNAL_SERVER_ERROR,
|
||||
(error instanceof Error ? error.message : String(error)) ||
|
||||
"เกิดข้อผิดพลาด ไม่สามารถบันทึกข้อมูลได้ กรุณาลองใหม่ในภายหลัง",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* แก้ไข api
|
||||
* @summary แก้ไขข้อมูล api
|
||||
*/
|
||||
@Put("/{id}")
|
||||
async editApi(
|
||||
@Request() req: RequestWithUser,
|
||||
@Path("id") id: string,
|
||||
@Body() apiData: CreateApi,
|
||||
): Promise<HttpSuccess | HttpError> {
|
||||
const queryRunner = AppDataSource.createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
|
||||
try {
|
||||
this.validateSuperAdminRole(req.user);
|
||||
|
||||
const apiName = await queryRunner.manager.getRepository(ApiName).findOneBy({ id });
|
||||
if (!apiName) {
|
||||
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบ API ที่ต้องการแก้ไข");
|
||||
}
|
||||
|
||||
const updateData = {
|
||||
name: apiData.name,
|
||||
pathApi: this.createApiPath(apiData.system as SystemCode, apiName.code),
|
||||
methodApi: apiData.methodApi || "GET",
|
||||
system: apiData.system || "registry",
|
||||
isActive: apiData.isActive || false,
|
||||
lastUpdateUserId: req.user?.sub,
|
||||
lastUpdateFullName: req.user?.name || "",
|
||||
};
|
||||
|
||||
await queryRunner.manager.getRepository(ApiName).update(id, updateData);
|
||||
await queryRunner.manager.getRepository(ApiAttribute).delete({ apiNameId: id });
|
||||
|
||||
if (apiData.apiAttributes?.length) {
|
||||
let orderingCounter = 0;
|
||||
const attributesToSave = apiData.apiAttributes.flatMap((attr) =>
|
||||
attr.propertyKey.map((propertyKey) => ({
|
||||
apiNameId: apiName.id,
|
||||
tbName: attr.tbName,
|
||||
propertyKey,
|
||||
ordering: orderingCounter++,
|
||||
lastUpdateUserId: req.user?.sub,
|
||||
lastUpdateFullName: req.user?.name || "",
|
||||
})),
|
||||
);
|
||||
|
||||
await queryRunner.manager.getRepository(ApiAttribute).save(attributesToSave);
|
||||
}
|
||||
|
||||
await queryRunner.commitTransaction();
|
||||
return new HttpSuccess();
|
||||
} catch (error) {
|
||||
await queryRunner.rollbackTransaction();
|
||||
throw new HttpError(
|
||||
HttpStatusCode.INTERNAL_SERVER_ERROR,
|
||||
(error instanceof Error ? error.message : String(error)) ||
|
||||
"เกิดข้อผิดพลาด ไม่สามารถบันทึกข้อมูลได้ กรุณาลองใหม่ในภายหลัง",
|
||||
);
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ลบ api
|
||||
* @summary ลบข้อมูล api
|
||||
*/
|
||||
@Delete("/{id}")
|
||||
async deleteApi(
|
||||
@Request() req: RequestWithUser,
|
||||
@Path("id") id: string,
|
||||
): Promise<HttpSuccess | HttpError> {
|
||||
const queryRunner = AppDataSource.createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
|
||||
try {
|
||||
this.validateSuperAdminRole(req.user);
|
||||
|
||||
const checkUsed = await AppDataSource.getRepository(ApiKey)
|
||||
.createQueryBuilder("apiKey")
|
||||
.innerJoin("apiKey.apiNames", "apiName")
|
||||
.where("apiName.id = :id", { id })
|
||||
.getCount();
|
||||
|
||||
if (checkUsed > 0) {
|
||||
throw new HttpError(
|
||||
HttpStatusCode.BAD_REQUEST,
|
||||
"ไม่สามารถลบ API นี้ได้ เนื่องจากมีการใช้งานอยู่",
|
||||
);
|
||||
}
|
||||
|
||||
await queryRunner.manager.getRepository(ApiAttribute).delete({ apiNameId: id });
|
||||
await queryRunner.manager.getRepository(ApiName).delete({ id });
|
||||
|
||||
await queryRunner.commitTransaction();
|
||||
return new HttpSuccess();
|
||||
} catch (error) {
|
||||
await queryRunner.rollbackTransaction();
|
||||
throw new HttpError(
|
||||
HttpStatusCode.INTERNAL_SERVER_ERROR,
|
||||
(error instanceof Error ? error.message : String(error)) ||
|
||||
"เกิดข้อผิดพลาด ไม่สามารถบันทึกข้อมูลได้ กรุณาลองใหม่ในภายหลัง",
|
||||
);
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* list systems
|
||||
* @summary รายการ systems
|
||||
*/
|
||||
@Get("/manual/swagger")
|
||||
async getManualRequestWebService(): Promise<HttpSuccess> {
|
||||
const json = {
|
||||
openapi: "3.0.0",
|
||||
info: {
|
||||
title: "Request Web Service",
|
||||
version: "1.0.0",
|
||||
description: "This is a manual request web service.",
|
||||
},
|
||||
servers: [
|
||||
{
|
||||
url: process.env.API_URL?.replace("/api/v1", "") || "http://localhost:13009",
|
||||
},
|
||||
{
|
||||
url: "http://localhost:13009",
|
||||
description: "Local server",
|
||||
},
|
||||
],
|
||||
paths: {
|
||||
"/api/v1/org/api-service/{system}/{code}": {
|
||||
get: {
|
||||
summary: "Get Registry Data",
|
||||
parameters: [
|
||||
{
|
||||
name: "system",
|
||||
in: "path",
|
||||
required: true,
|
||||
schema: {
|
||||
type: "string",
|
||||
enum: ["registry", "registry_emp", "registry_temp", "organization", "position"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "code",
|
||||
in: "path",
|
||||
required: true,
|
||||
schema: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "page",
|
||||
in: "query",
|
||||
required: false,
|
||||
schema: {
|
||||
type: "integer",
|
||||
default: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "pageSize",
|
||||
in: "query",
|
||||
required: false,
|
||||
schema: {
|
||||
type: "integer",
|
||||
default: 100,
|
||||
},
|
||||
},
|
||||
],
|
||||
responses: {
|
||||
200: {
|
||||
description: "Successful response",
|
||||
},
|
||||
400: {
|
||||
description: "Bad request",
|
||||
},
|
||||
500: {
|
||||
description: "Internal server error",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
components: {
|
||||
securitySchemes: {
|
||||
ApiKeyAuth: {
|
||||
type: "apiKey",
|
||||
in: "header",
|
||||
name: "X-API-Key",
|
||||
},
|
||||
},
|
||||
},
|
||||
security: [
|
||||
{
|
||||
ApiKeyAuth: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
return new HttpSuccess(json);
|
||||
}
|
||||
}
|
||||
200
src/controllers/ApiWebServiceController.ts
Normal file
200
src/controllers/ApiWebServiceController.ts
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
import { Controller, Route, Security, Tags, Path, Request, Response, Get, Query } 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 { ApiName } from "../entities/ApiName";
|
||||
import { isPermissionRequest } from "../middlewares/authWebService";
|
||||
import { RequestWithUserWebService } from "../middlewares/user";
|
||||
import { OrgRevision } from "../entities/OrgRevision";
|
||||
import { ApiHistory } from "../entities/ApiHistory";
|
||||
import { SystemCode } from "./../interfaces/api-type";
|
||||
@Route("api/v1/org/api-service")
|
||||
@Tags("ApiKey")
|
||||
@Security("webServiceAuth")
|
||||
@Response(
|
||||
HttpStatusCode.INTERNAL_SERVER_ERROR,
|
||||
"เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง",
|
||||
)
|
||||
export class ApiWebServiceController extends Controller {
|
||||
private apiNameRepository = AppDataSource.getRepository(ApiName);
|
||||
private orgRevisionRepository = AppDataSource.getRepository(OrgRevision);
|
||||
private apiHistoryRepository = AppDataSource.getRepository(ApiHistory);
|
||||
|
||||
/**
|
||||
* list fields by systems
|
||||
* @summary รายการ fields ตาม systems
|
||||
*/
|
||||
@Get("/:system/:code")
|
||||
async listAttribute(
|
||||
@Request() request: RequestWithUserWebService,
|
||||
@Path("system")
|
||||
system: SystemCode,
|
||||
@Path("code") code: string,
|
||||
@Query("page") page: number = 1,
|
||||
@Query("pageSize") pageSize: number = 100,
|
||||
): Promise<HttpSuccess | HttpError> {
|
||||
const apiName = await this.apiNameRepository.findOne({
|
||||
where: { code },
|
||||
select: ["id", "code", "methodApi", "system", "isActive"],
|
||||
relations: ["apiAttributes"],
|
||||
order: {
|
||||
apiAttributes: {
|
||||
ordering: "ASC",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!apiName || apiName.system != system || !apiName.isActive || apiName.methodApi != "GET") {
|
||||
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบ API ที่ระบุ");
|
||||
}
|
||||
await isPermissionRequest(request, apiName.id);
|
||||
const offset = (page - 1) * pageSize;
|
||||
const propertyKey = apiName.apiAttributes.map((attr) => `${attr.tbName}.${attr.propertyKey}`);
|
||||
|
||||
let tbMain: string = "";
|
||||
let condition: string = "1=1";
|
||||
if (system == "registry") {
|
||||
tbMain = "Profile";
|
||||
} else if (system == "registry_emp") {
|
||||
tbMain = "ProfileEmployee";
|
||||
condition = `ProfileEmployee.employeeClass = "PERM"`;
|
||||
} else if (system == "registry_temp") {
|
||||
tbMain = "ProfileEmployee";
|
||||
condition = `ProfileEmployee.employeeClass = "TEMP"`;
|
||||
} else if (system == "organization") {
|
||||
tbMain = "OrgRoot";
|
||||
const revision = await this.orgRevisionRepository.findOne({
|
||||
select: ["id"],
|
||||
where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
|
||||
});
|
||||
condition = `OrgRoot.orgRevisionId = "${revision?.id}"`;
|
||||
} else if (system == "position") {
|
||||
tbMain = "PosMaster";
|
||||
const revision = await this.orgRevisionRepository.findOne({
|
||||
select: ["id"],
|
||||
where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
|
||||
});
|
||||
condition = `PosMaster.orgRevisionId = "${revision?.id}"`;
|
||||
}
|
||||
|
||||
const repo = AppDataSource.getRepository(tbMain);
|
||||
const metadata = repo.metadata;
|
||||
|
||||
const relationMap: Record<string, string> = {};
|
||||
metadata.relations.forEach((rel) => {
|
||||
relationMap[rel.inverseEntityMetadata.name] = rel.propertyName;
|
||||
});
|
||||
|
||||
// ดึงเฉพาะตารางรอง (ถ้าเลือกไว้)
|
||||
let propertyOtherKey: any[] = [];
|
||||
propertyOtherKey = [
|
||||
...new Set(propertyKey.map((x) => x.split(".")[0]).filter((tb) => tb !== tbMain)),
|
||||
];
|
||||
|
||||
const queryBuilder = repo.createQueryBuilder(tbMain);
|
||||
|
||||
// join กับตารารอง
|
||||
if (propertyOtherKey.length > 0) {
|
||||
propertyOtherKey.forEach((tb) => {
|
||||
const relationName = relationMap[tb];
|
||||
if (relationName) {
|
||||
queryBuilder.leftJoin(
|
||||
`${tbMain}.${relationName === "next_holder" ? "current_holder" : relationName}`, // เช็คว่าถ้าเป็น next_holder ให้ใช้ current_holder แทน
|
||||
tb,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// // เพิ่ม Main.id เพราะจะใช้ pk ในการแมบและนับจำนวน
|
||||
// if (!propertyKey.includes(`${Main}.id`)) {
|
||||
// propertyKey.push(`${Main}.id`);
|
||||
// }
|
||||
|
||||
// add FK
|
||||
let pk: string = "";
|
||||
const primaryColumns = metadata.primaryColumns;
|
||||
primaryColumns.forEach((col) => {
|
||||
pk = col.propertyName;
|
||||
if (!propertyKey.includes(`${tbMain}.${pk}`)) {
|
||||
propertyKey.push(`${tbMain}.${pk}`);
|
||||
}
|
||||
});
|
||||
|
||||
const [items, total] = await queryBuilder
|
||||
.select(propertyKey)
|
||||
.where(condition)
|
||||
.orderBy(propertyKey[0], "ASC")
|
||||
.skip(offset)
|
||||
.take(pageSize)
|
||||
.getManyAndCount();
|
||||
|
||||
// ลบ Main.id
|
||||
// const results = items.map(({ id, ...x }) => x);
|
||||
// const results = items.map(({ pk, ...x }) => x);
|
||||
|
||||
// const results = items.map(item => {
|
||||
// primaryColumns.forEach(col => delete item[col.propertyName]);
|
||||
// return item;
|
||||
// });
|
||||
|
||||
// split object id ออกก่อน return
|
||||
const data = items.map((item) => {
|
||||
const { [pk]: removedPk, ...x } = item;
|
||||
return x;
|
||||
});
|
||||
|
||||
// console.log("queryBuilder ===> ", queryBuilder.getQuery());
|
||||
|
||||
// save api history after query success
|
||||
const history = {
|
||||
headerApi: JSON.stringify({
|
||||
host: request.headers.host,
|
||||
"x-api-key": request.headers["x-api-key"],
|
||||
connection: request.headers.connection,
|
||||
accept: request.headers.accept,
|
||||
}),
|
||||
tokenApi: Array.isArray(request.headers["x-api-key"])
|
||||
? request.headers["x-api-key"][0] || ""
|
||||
: request.headers["x-api-key"] || "",
|
||||
requestApi: `${request.method} ${request.protocol}://${request.headers.host}${request.originalUrl || request.url}`,
|
||||
responseApi: "OK",
|
||||
ipApi: request.ip,
|
||||
codeApi: code,
|
||||
apiKeyId: request.user.id,
|
||||
apiNameId: apiName.id,
|
||||
createdFullName: request.user.name,
|
||||
lastUpdateFullName: request.user.name,
|
||||
};
|
||||
await this.apiHistoryRepository.save(history);
|
||||
|
||||
// const results = data.map((item) => {
|
||||
// const flattenedItem: any = {};
|
||||
|
||||
// // Extract nested object properties to top level
|
||||
// Object.keys(item).forEach((key) => {
|
||||
// const value = item[key];
|
||||
// if (value && typeof value === "object") {
|
||||
// // if (Array.isArray(value) && value.length === 1) {
|
||||
// // // If array has single item, extract it as object
|
||||
// // Object.assign(flattenedItem, value[0]);
|
||||
// // } else
|
||||
// if (!Array.isArray(value)) {
|
||||
// // Merge nested object properties to top level
|
||||
// Object.assign(flattenedItem, value);
|
||||
// } else {
|
||||
// // Keep arrays with multiple items or empty arrays as is
|
||||
// flattenedItem[key] = value;
|
||||
// }
|
||||
// } else {
|
||||
// // Keep primitive values as is
|
||||
// flattenedItem[key] = value;
|
||||
// }
|
||||
// });
|
||||
|
||||
// return flattenedItem;
|
||||
// });
|
||||
return new HttpSuccess({ data: data, total });
|
||||
}
|
||||
}
|
||||
|
|
@ -3120,7 +3120,10 @@ export class CommandController extends Controller {
|
|||
orgRevisionId: posMaster.orgRevisionId,
|
||||
},
|
||||
});
|
||||
if (posMasterOld != null) posMasterOld.current_holderId = null;
|
||||
if (posMasterOld != null) {
|
||||
posMasterOld.current_holderId = null;
|
||||
posMasterOld.lastUpdatedAt = new Date();
|
||||
}
|
||||
|
||||
const positionOld = await this.positionRepository.findOne({
|
||||
where: {
|
||||
|
|
@ -3148,6 +3151,7 @@ export class CommandController extends Controller {
|
|||
}
|
||||
|
||||
posMaster.current_holderId = item.profileId;
|
||||
posMaster.lastUpdatedAt = new Date();
|
||||
posMaster.conditionReason = _null;
|
||||
posMaster.isCondition = false;
|
||||
if (posMasterOld != null) await this.posMasterRepository.save(posMasterOld);
|
||||
|
|
@ -3304,7 +3308,10 @@ export class CommandController extends Controller {
|
|||
orgRevisionId: posMaster.orgRevisionId,
|
||||
},
|
||||
});
|
||||
if (posMasterOld != null) posMasterOld.current_holderId = null;
|
||||
if (posMasterOld != null) {
|
||||
posMasterOld.current_holderId = null;
|
||||
posMasterOld.lastUpdatedAt = new Date();
|
||||
}
|
||||
// if (posMasterOld != null) posMasterOld.next_holderId = null;
|
||||
|
||||
const positionOld = await this.employeePositionRepository.findOne({
|
||||
|
|
@ -3333,6 +3340,7 @@ export class CommandController extends Controller {
|
|||
}
|
||||
|
||||
posMaster.current_holderId = item.profileId;
|
||||
posMaster.lastUpdatedAt = new Date();
|
||||
posMaster.next_holderId = null;
|
||||
if (posMasterOld != null) await this.employeePosMasterRepository.save(posMasterOld);
|
||||
await this.employeePosMasterRepository.save(posMaster);
|
||||
|
|
@ -3561,6 +3569,7 @@ export class CommandController extends Controller {
|
|||
await this.positionRepository.save(clearPosition);
|
||||
}
|
||||
posMaster.current_holderId = profile.id;
|
||||
posMaster.lastUpdatedAt = new Date();
|
||||
posMaster.conditionReason = _null;
|
||||
posMaster.isCondition = false;
|
||||
await this.posMasterRepository.save(posMaster);
|
||||
|
|
@ -5987,7 +5996,10 @@ export class CommandController extends Controller {
|
|||
orgRevisionId: posMaster.orgRevisionId,
|
||||
},
|
||||
});
|
||||
if (posMasterOld != null) posMasterOld.current_holderId = null;
|
||||
if (posMasterOld != null) {
|
||||
posMasterOld.current_holderId = null;
|
||||
posMasterOld.lastUpdatedAt = new Date();
|
||||
}
|
||||
|
||||
const positionOld = await this.positionRepository.findOne({
|
||||
where: {
|
||||
|
|
@ -6015,6 +6027,7 @@ export class CommandController extends Controller {
|
|||
}
|
||||
|
||||
posMaster.current_holderId = profile.id;
|
||||
posMaster.lastUpdatedAt = new Date();
|
||||
posMaster.conditionReason = _null;
|
||||
posMaster.isCondition = false;
|
||||
if (posMasterOld != null) await this.posMasterRepository.save(posMasterOld);
|
||||
|
|
@ -6364,7 +6377,10 @@ export class CommandController extends Controller {
|
|||
orgRevisionId: posMaster.orgRevisionId,
|
||||
},
|
||||
});
|
||||
if (posMasterOld != null) posMasterOld.current_holderId = null;
|
||||
if (posMasterOld != null) {
|
||||
posMasterOld.current_holderId = null;
|
||||
posMasterOld.lastUpdatedAt = new Date();
|
||||
}
|
||||
// if (posMasterOld != null) posMasterOld.next_holderId = null;
|
||||
|
||||
const positionOld = await this.employeePositionRepository.findOne({
|
||||
|
|
@ -6393,6 +6409,7 @@ export class CommandController extends Controller {
|
|||
}
|
||||
|
||||
posMaster.current_holderId = profile.id;
|
||||
posMaster.lastUpdatedAt = new Date();
|
||||
posMaster.next_holderId = null;
|
||||
if (posMasterOld != null) await this.employeePosMasterRepository.save(posMasterOld);
|
||||
await this.employeePosMasterRepository.save(posMaster);
|
||||
|
|
@ -6673,23 +6690,11 @@ export class CommandController extends Controller {
|
|||
};
|
||||
|
||||
try {
|
||||
// 8. บันทึกข้อมูลใหม่
|
||||
const dataAct = new ProfileActposition();
|
||||
Object.assign(dataAct, metaAct);
|
||||
|
||||
const historyAct = new ProfileActpositionHistory();
|
||||
Object.assign(historyAct, { ...dataAct, id: undefined });
|
||||
|
||||
await this.actpositionRepository.save(dataAct);
|
||||
historyAct.profileActpositionId = dataAct.id;
|
||||
await this.actpositionHistoryRepository.save(historyAct);
|
||||
|
||||
// 9. ปิดสถานะรักษาการ
|
||||
// 8. ปิดสถานะรักษาการ
|
||||
const existingActPositions = await this.actpositionRepository.find({
|
||||
where: {
|
||||
profileId: item.posMasterChild.current_holderId,
|
||||
status: true,
|
||||
id: Not(dataAct.id),
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -6702,6 +6707,17 @@ export class CommandController extends Controller {
|
|||
|
||||
await this.actpositionRepository.save(updatedActPositions);
|
||||
}
|
||||
|
||||
// 9. บันทึกข้อมูลใหม่
|
||||
const dataAct = new ProfileActposition();
|
||||
Object.assign(dataAct, metaAct);
|
||||
|
||||
const historyAct = new ProfileActpositionHistory();
|
||||
Object.assign(historyAct, { ...dataAct, id: undefined });
|
||||
|
||||
await this.actpositionRepository.save(dataAct);
|
||||
historyAct.profileActpositionId = dataAct.id;
|
||||
await this.actpositionHistoryRepository.save(historyAct);
|
||||
} catch (error) {
|
||||
console.error(`Error processing item ${item.id}:`, error);
|
||||
throw new HttpError(
|
||||
|
|
|
|||
|
|
@ -372,18 +372,22 @@ export class EmployeePositionController extends Controller {
|
|||
// });
|
||||
// }
|
||||
findData = await this.employeePosDictRepository
|
||||
.createQueryBuilder("posDict")
|
||||
.leftJoinAndSelect("posDict.posType", "posType")
|
||||
.leftJoinAndSelect("posDict.posLevel", "posLevel")
|
||||
.where( keyword
|
||||
? "CONCAT(posType.posTypeShortName, ' ', posLevel.posLevelName) LIKE :keyword":"1=1", {keyword: `%${keyword}%`})
|
||||
.orderBy("posDict.posDictName", "ASC")
|
||||
.addOrderBy("posDict.createdAt", "DESC")
|
||||
.addOrderBy("posType.posTypeRank", "ASC")
|
||||
.addOrderBy("posType.createdAt", "DESC")
|
||||
.addOrderBy("posLevel.posLevelName", "ASC")
|
||||
.addOrderBy("posLevel.createdAt", "DESC")
|
||||
.getMany();
|
||||
.createQueryBuilder("posDict")
|
||||
.leftJoinAndSelect("posDict.posType", "posType")
|
||||
.leftJoinAndSelect("posDict.posLevel", "posLevel")
|
||||
.where(
|
||||
keyword
|
||||
? "CONCAT(posType.posTypeShortName, ' ', posLevel.posLevelName) LIKE :keyword"
|
||||
: "1=1",
|
||||
{ keyword: `%${keyword}%` },
|
||||
)
|
||||
.orderBy("posDict.posDictName", "ASC")
|
||||
.addOrderBy("posDict.createdAt", "DESC")
|
||||
.addOrderBy("posType.posTypeRank", "ASC")
|
||||
.addOrderBy("posType.createdAt", "DESC")
|
||||
.addOrderBy("posLevel.posLevelName", "ASC")
|
||||
.addOrderBy("posLevel.createdAt", "DESC")
|
||||
.getMany();
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -2258,6 +2262,7 @@ export class EmployeePositionController extends Controller {
|
|||
|
||||
dataMaster.isSit = requestBody.isSit;
|
||||
dataMaster.current_holderId = requestBody.profileId;
|
||||
dataMaster.lastUpdatedAt = new Date();
|
||||
// dataMaster.next_holderId = requestBody.profileId;
|
||||
await this.employeePosMasterRepository.save(dataMaster);
|
||||
|
||||
|
|
@ -2394,7 +2399,10 @@ export class EmployeePositionController extends Controller {
|
|||
orgRevisionId: posMaster.orgRevisionId,
|
||||
},
|
||||
});
|
||||
if (posMasterOld != null) posMasterOld.current_holderId = null;
|
||||
if (posMasterOld != null) {
|
||||
posMasterOld.current_holderId = null;
|
||||
posMasterOld.lastUpdatedAt = new Date();
|
||||
}
|
||||
// if (posMasterOld != null) posMasterOld.next_holderId = null;
|
||||
|
||||
const positionOld = await this.employeePositionRepository.findOne({
|
||||
|
|
@ -2429,6 +2437,7 @@ export class EmployeePositionController extends Controller {
|
|||
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลทะเบียนประวัตินี้");
|
||||
|
||||
posMaster.current_holderId = body.profileId;
|
||||
posMaster.lastUpdatedAt = new Date();
|
||||
// posMaster.next_holderId = body.profileId;
|
||||
if (posMasterOld != null) await this.employeePosMasterRepository.save(posMasterOld);
|
||||
await this.employeePosMasterRepository.save(posMaster);
|
||||
|
|
|
|||
|
|
@ -2001,6 +2001,7 @@ export class EmployeeTempPositionController extends Controller {
|
|||
|
||||
dataMaster.isSit = requestBody.isSit;
|
||||
dataMaster.current_holderId = requestBody.profileId;
|
||||
dataMaster.lastUpdatedAt = new Date();
|
||||
// dataMaster.next_holderId = requestBody.profileId;
|
||||
await this.employeeTempPosMasterRepository.save(dataMaster);
|
||||
|
||||
|
|
@ -2137,7 +2138,10 @@ export class EmployeeTempPositionController extends Controller {
|
|||
orgRevisionId: posMaster.orgRevisionId,
|
||||
},
|
||||
});
|
||||
if (posMasterOld != null) posMasterOld.current_holderId = null;
|
||||
if (posMasterOld != null) {
|
||||
posMasterOld.current_holderId = null;
|
||||
posMasterOld.lastUpdatedAt = new Date();
|
||||
}
|
||||
// if (posMasterOld != null) posMasterOld.next_holderId = null;
|
||||
|
||||
const positionOld = await this.employeePositionRepository.findOne({
|
||||
|
|
@ -2172,6 +2176,7 @@ export class EmployeeTempPositionController extends Controller {
|
|||
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลทะเบียนประวัตินี้");
|
||||
|
||||
posMaster.current_holderId = body.profileId;
|
||||
posMaster.lastUpdatedAt = new Date();
|
||||
// posMaster.next_holderId = body.profileId;
|
||||
if (posMasterOld != null) await this.employeeTempPosMasterRepository.save(posMasterOld);
|
||||
await this.employeeTempPosMasterRepository.save(posMaster);
|
||||
|
|
|
|||
|
|
@ -340,7 +340,7 @@ export class OrgRootController extends Controller {
|
|||
const before = structuredClone(orgRoot);
|
||||
orgRoot.lastUpdateUserId = request.user.sub;
|
||||
orgRoot.lastUpdateFullName = request.user.name;
|
||||
orgRoot.lastUpdatedAt = new Date();
|
||||
// orgRoot.lastUpdatedAt = new Date();
|
||||
this.orgRootRepository.merge(orgRoot, {
|
||||
...requestBody,
|
||||
DEPARTMENT_CODE: requestBody.DEPARTMENT_CODE != null ? requestBody.DEPARTMENT_CODE : _null,
|
||||
|
|
|
|||
|
|
@ -693,7 +693,11 @@ export class OrganizationDotnetController extends Controller {
|
|||
}
|
||||
}
|
||||
}
|
||||
let positionLeaveName = profile.posLevel?.posLevelName ?? null;
|
||||
let positionLeaveName =
|
||||
profile.posType == null && profile.posLevel == null
|
||||
? ""
|
||||
: `${profile.posType?.posTypeShortName ?? ""} ${profile.posLevel?.posLevelName ?? ""}`
|
||||
|
||||
const _profileCurrent = profile?.current_holders?.find(
|
||||
(x) =>
|
||||
x.orgRevision?.orgRevisionIsDraft === false &&
|
||||
|
|
|
|||
|
|
@ -1431,11 +1431,77 @@ export class PositionController extends Controller {
|
|||
@Get("position/{id}")
|
||||
async detailPosition(@Path() id: string) {
|
||||
const posMaster = await this.posMasterRepository.findOne({
|
||||
relations: ["orgRoot", "orgChild1", "orgChild2", "orgChild3", "orgChild4"],
|
||||
where: { id },
|
||||
});
|
||||
if (!posMaster) {
|
||||
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูล");
|
||||
}
|
||||
let orgLevel: any;
|
||||
|
||||
switch (true) {
|
||||
case !!posMaster.orgChild4Id:
|
||||
orgLevel = 4;
|
||||
break;
|
||||
case !!posMaster.orgChild3Id:
|
||||
orgLevel = 3;
|
||||
break;
|
||||
case !!posMaster.orgChild2Id:
|
||||
orgLevel = 2;
|
||||
break;
|
||||
case !!posMaster.orgChild1Id:
|
||||
orgLevel = 1;
|
||||
break;
|
||||
case !!posMaster.orgRootId:
|
||||
orgLevel = 0;
|
||||
break;
|
||||
default:
|
||||
orgLevel = null; // ถ้าไม่มีข้อมูลเลย
|
||||
break;
|
||||
}
|
||||
let shortName = "";
|
||||
let orgId: any;
|
||||
if (
|
||||
posMaster.orgRootId !== null &&
|
||||
posMaster.orgChild1Id == null &&
|
||||
posMaster.orgChild2Id == null &&
|
||||
posMaster.orgChild3Id == null
|
||||
) {
|
||||
shortName = posMaster.orgRoot.orgRootShortName;
|
||||
orgId = posMaster.orgRootId;
|
||||
} else if (
|
||||
posMaster.orgRootId !== null &&
|
||||
posMaster.orgChild1Id !== null &&
|
||||
posMaster.orgChild2Id == null &&
|
||||
posMaster.orgChild3Id == null
|
||||
) {
|
||||
shortName = posMaster.orgChild1.orgChild1ShortName;
|
||||
orgId = posMaster.orgChild1Id;
|
||||
} else if (
|
||||
posMaster.orgRootId !== null &&
|
||||
posMaster.orgChild1Id !== null &&
|
||||
posMaster.orgChild2Id !== null &&
|
||||
posMaster.orgChild3Id == null
|
||||
) {
|
||||
shortName = posMaster.orgChild2.orgChild2ShortName;
|
||||
orgId = posMaster.orgChild2Id;
|
||||
} else if (
|
||||
posMaster.orgRootId !== null &&
|
||||
posMaster.orgChild1Id !== null &&
|
||||
posMaster.orgChild2Id !== null &&
|
||||
posMaster.orgChild3Id !== null
|
||||
) {
|
||||
shortName = posMaster.orgChild3.orgChild3ShortName;
|
||||
orgId = posMaster.orgChild3Id;
|
||||
} else if (
|
||||
posMaster.orgRootId !== null &&
|
||||
posMaster.orgChild1Id !== null &&
|
||||
posMaster.orgChild2Id !== null &&
|
||||
posMaster.orgChild3Id !== null
|
||||
) {
|
||||
shortName = posMaster.orgChild4.orgChild4ShortName;
|
||||
orgId = posMaster.orgChild4Id;
|
||||
}
|
||||
const positions = await this.positionRepository.find({
|
||||
where: { posMasterId: posMaster.id },
|
||||
relations: ["posType", "posLevel", "posExecutive"],
|
||||
|
|
@ -1457,6 +1523,9 @@ export class PositionController extends Controller {
|
|||
reason: posMaster.reason,
|
||||
// isOfficer: posMaster.isOfficer,
|
||||
isStaff: posMaster.isStaff,
|
||||
orgLevel: orgLevel,
|
||||
orgShortname: shortName,
|
||||
orgId: orgId,
|
||||
isDirector: posMaster.isDirector,
|
||||
positionSign: posMaster.positionSign,
|
||||
positions: positions.map((position) => ({
|
||||
|
|
@ -2582,69 +2651,72 @@ export class PositionController extends Controller {
|
|||
async getHistoryPosMater(@Path() id: string, @Request() request: RequestWithUser) {
|
||||
let _workflow = await new permission().Workflow(request, id, "SYS_ORG");
|
||||
if (_workflow == false) await new permission().PermissionGet(request, "SYS_ORG");
|
||||
const posMaster = await this.posMasterRepository.findOne({
|
||||
where: { id },
|
||||
});
|
||||
|
||||
// ใช้ query builder สำหรับประสิทธิภาพที่ดีขึ้น
|
||||
const queryBuilder = this.posMasterRepository
|
||||
.createQueryBuilder("pm")
|
||||
.leftJoinAndSelect("pm.orgRevision", "orgRevision")
|
||||
.leftJoinAndSelect("pm.orgRoot", "orgRoot")
|
||||
.leftJoinAndSelect("pm.orgChild1", "orgChild1")
|
||||
.leftJoinAndSelect("pm.orgChild2", "orgChild2")
|
||||
.leftJoinAndSelect("pm.orgChild3", "orgChild3")
|
||||
.leftJoinAndSelect("pm.orgChild4", "orgChild4")
|
||||
.leftJoinAndSelect("pm.current_holder", "current_holder")
|
||||
.leftJoinAndSelect("pm.positions", "positions")
|
||||
.leftJoinAndSelect("positions.posLevel", "posLevel")
|
||||
.leftJoinAndSelect("positions.posType", "posType")
|
||||
.leftJoinAndSelect("positions.posExecutive", "posExecutive");
|
||||
|
||||
// หาข้อมูลหลัก
|
||||
const posMaster = await queryBuilder.where("pm.id = :id", { id }).getOne();
|
||||
|
||||
if (!posMaster) {
|
||||
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลตำแหน่งนี้");
|
||||
}
|
||||
const posMasters = await this.posMasterRepository.find({
|
||||
where: {
|
||||
ancestorDNA:
|
||||
posMaster.ancestorDNA == null || posMaster.ancestorDNA == ""
|
||||
? "123"
|
||||
: posMaster.ancestorDNA,
|
||||
},
|
||||
order: { lastUpdatedAt: "DESC" },
|
||||
relations: [
|
||||
"orgRoot",
|
||||
"orgChild1",
|
||||
"orgChild2",
|
||||
"orgChild3",
|
||||
"orgChild4",
|
||||
"current_holder",
|
||||
"positions",
|
||||
"positions.posLevel",
|
||||
"positions.posType",
|
||||
"positions.posExecutive",
|
||||
],
|
||||
});
|
||||
|
||||
// สร้าง conditions
|
||||
const ancestorDNA = posMaster.ancestorDNA || "123";
|
||||
let historyQuery = queryBuilder.where("pm.ancestorDNA = :ancestorDNA", { ancestorDNA });
|
||||
|
||||
// เพิ่มเงื่อนไข draft
|
||||
if (
|
||||
posMaster.orgRevision?.orgRevisionIsCurrent != false &&
|
||||
posMaster.orgRevision?.orgRevisionIsDraft != true
|
||||
) {
|
||||
historyQuery = historyQuery.andWhere("orgRevision.orgRevisionIsDraft != :isDraft", {
|
||||
isDraft: true,
|
||||
});
|
||||
}
|
||||
|
||||
const posMasters = await historyQuery.orderBy("pm.lastUpdatedAt", "DESC").getMany();
|
||||
|
||||
const _data = posMasters.map((item) => ({
|
||||
id: item.id,
|
||||
orgShortName:
|
||||
item.orgRoot == null
|
||||
? null
|
||||
: item.orgChild1 == null
|
||||
? item.orgRoot.orgRootShortName
|
||||
: item.orgChild2 == null
|
||||
? item.orgChild1.orgChild1ShortName
|
||||
: item.orgChild3 == null
|
||||
? item.orgChild2.orgChild2ShortName
|
||||
: item.orgChild4 == null
|
||||
? item.orgChild3.orgChild3ShortName
|
||||
: item.orgChild4.orgChild4ShortName,
|
||||
lastUpdatedAt: item.lastUpdatedAt ? item.lastUpdatedAt : null,
|
||||
posMasterNoPrefix: item.posMasterNoPrefix ? item.posMasterNoPrefix : null,
|
||||
posMasterNo: item.posMasterNo ? item.posMasterNo : null,
|
||||
posMasterNoSuffix: item.posMasterNoSuffix ? item.posMasterNoSuffix : null,
|
||||
reason: item.reason ? item.reason : null,
|
||||
item.orgChild4?.orgChild4ShortName ||
|
||||
item.orgChild3?.orgChild3ShortName ||
|
||||
item.orgChild2?.orgChild2ShortName ||
|
||||
item.orgChild1?.orgChild1ShortName ||
|
||||
item.orgRoot?.orgRootShortName ||
|
||||
null,
|
||||
lastUpdatedAt: item.lastUpdatedAt,
|
||||
posMasterNoPrefix: item.posMasterNoPrefix,
|
||||
posMasterNo: item.posMasterNo,
|
||||
posMasterNoSuffix: item.posMasterNoSuffix,
|
||||
reason: item.reason,
|
||||
position: item.positions.map((x) => x.positionName).join("/"),
|
||||
posExecutive: item.positions
|
||||
.filter((x) => x.posExecutive != null)
|
||||
.map((x) => x.posExecutive?.posExecutiveName ?? null)
|
||||
.filter((x) => x.posExecutive)
|
||||
.map((x) => x.posExecutive!.posExecutiveName)
|
||||
.join("/"),
|
||||
posLevel: item.positions.map((x) => x.posLevel.posLevelName).join("/"),
|
||||
posType: item.positions.map((x) => x.posType.posTypeName).join("/"),
|
||||
fullname:
|
||||
(item?.current_holder?.prefix ?? "") +
|
||||
"" +
|
||||
(item?.current_holder?.firstName ?? "") +
|
||||
" " +
|
||||
(item?.current_holder?.lastName ?? ""),
|
||||
`${item.current_holder?.prefix || ""}${item.current_holder?.firstName || ""} ${item.current_holder?.lastName || ""}`.trim(),
|
||||
}));
|
||||
|
||||
return new HttpSuccess(_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* API ย้ายอัตรากำลัง
|
||||
*
|
||||
|
|
@ -3518,6 +3590,7 @@ export class PositionController extends Controller {
|
|||
const before = null;
|
||||
dataMaster.isSit = requestBody.isSit;
|
||||
dataMaster.next_holderId = requestBody.profileId;
|
||||
dataMaster.lastUpdatedAt = new Date();
|
||||
//add on
|
||||
dataMaster.conditionReason = _null;
|
||||
dataMaster.isCondition = false;
|
||||
|
|
@ -4658,7 +4731,10 @@ export class PositionController extends Controller {
|
|||
orgRevisionId: posMaster.orgRevisionId,
|
||||
},
|
||||
});
|
||||
if (posMasterOld != null) posMasterOld.current_holderId = null;
|
||||
if (posMasterOld != null) {
|
||||
posMasterOld.current_holderId = null;
|
||||
posMasterOld.lastUpdatedAt = new Date();
|
||||
}
|
||||
|
||||
const positionOld = await this.positionRepository.findOne({
|
||||
where: {
|
||||
|
|
@ -4692,6 +4768,7 @@ export class PositionController extends Controller {
|
|||
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลทะเบียนประวัตินี้");
|
||||
|
||||
posMaster.current_holderId = body.profileId;
|
||||
posMaster.lastUpdatedAt = new Date();
|
||||
const _null: any = null;
|
||||
posMaster.conditionReason = _null;
|
||||
posMaster.isCondition = false;
|
||||
|
|
@ -5245,6 +5322,7 @@ export class PositionController extends Controller {
|
|||
if (!profile) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผู้ใช้งาน");
|
||||
|
||||
posMaster.next_holderId = requestBody.profileId;
|
||||
posMaster.lastUpdatedAt = new Date();
|
||||
posMaster.lastUpdateUserId = request.user.sub;
|
||||
posMaster.lastUpdateFullName = request.user.name;
|
||||
posMaster.lastUpdatedAt = new Date();
|
||||
|
|
|
|||
|
|
@ -1321,7 +1321,7 @@ export class ProfileController extends Controller {
|
|||
"profileLeave.dateLeaveEnd AS dateLeaveEnd",
|
||||
"profileLeave.leaveDays AS leaveDays",
|
||||
"profileLeave.reason AS reason",
|
||||
"leaveType.name as name"
|
||||
"leaveType.name as name",
|
||||
])
|
||||
.where("profileLeave.profileId = :profileId", { profileId: id })
|
||||
.andWhere("leaveType.code IN (:...codes)", { codes: ["LV-008", "LV-009", "LV-010"] })
|
||||
|
|
@ -1331,10 +1331,12 @@ export class ProfileController extends Controller {
|
|||
const leaves2 =
|
||||
leave2_raw.length > 0
|
||||
? leave2_raw.map((item) => ({
|
||||
date: item.dateLeaveStart && item.dateLeaveEnd
|
||||
? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateLeaveStart)) + " - "
|
||||
+ Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateLeaveEnd))
|
||||
: "-",
|
||||
date:
|
||||
item.dateLeaveStart && item.dateLeaveEnd
|
||||
? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateLeaveStart)) +
|
||||
" - " +
|
||||
Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateLeaveEnd))
|
||||
: "-",
|
||||
type: item.name || "-",
|
||||
leaveDays: item.leaveDays ? Extension.ToThaiNumber(item.leaveDays.toString()) : "-",
|
||||
reason: item.reason || "-",
|
||||
|
|
@ -1684,24 +1686,22 @@ export class ProfileController extends Controller {
|
|||
)
|
||||
: "";
|
||||
|
||||
let portfolios:any
|
||||
await new CallAPI()
|
||||
.GetData(req, `/development/portfolio/kk1/${profiles?.keycloak}`)
|
||||
.then((x) => {
|
||||
portfolios = x;
|
||||
})
|
||||
.catch(() => {});
|
||||
let portfolios: any;
|
||||
await new CallAPI()
|
||||
.GetData(req, `/development/portfolio/kk1/${profiles?.keycloak}`)
|
||||
.then((x) => {
|
||||
portfolios = x;
|
||||
})
|
||||
.catch(() => {});
|
||||
if (!portfolios) {
|
||||
portfolios = [{ name: "-", year: "-" }]
|
||||
portfolios = [{ name: "-", year: "-" }];
|
||||
} else {
|
||||
portfolios = portfolios.map((x: any) => ({
|
||||
name: x.name ? Extension.ToThaiNumber(x.name) : "-",
|
||||
year: x.year ? Extension.ToThaiNumber(x.year.toString()) : "-",
|
||||
}));
|
||||
}
|
||||
else {
|
||||
portfolios = portfolios.map((x:any) => ({
|
||||
name: x.name ? x.name : "-",
|
||||
year: x.year ? Extension.ToThaiNumber(x.year.toString()) : "-"
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
|
||||
const data = {
|
||||
fullName: `${profiles?.prefix}${profiles?.firstName} ${profiles?.lastName}`,
|
||||
prefix: profiles?.prefix != null ? profiles.prefix : "",
|
||||
|
|
@ -1855,7 +1855,7 @@ export class ProfileController extends Controller {
|
|||
assessments,
|
||||
profileAbility,
|
||||
otherIncome,
|
||||
portfolios
|
||||
portfolios,
|
||||
};
|
||||
|
||||
return new HttpSuccess({
|
||||
|
|
@ -2855,7 +2855,8 @@ export class ProfileController extends Controller {
|
|||
},
|
||||
});
|
||||
if (!posMaster) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลการครองตำแหน่ง");
|
||||
posMaster.current_holderId = "";
|
||||
posMaster.current_holderId = null;
|
||||
posMaster.lastUpdatedAt = new Date();
|
||||
// return new HttpSuccess({ data: [], total: 0 });
|
||||
} else if ((posMaster?.current_holder?.posLevel?.posLevelAuthority ?? null) == "GOVERNOR") {
|
||||
return new HttpSuccess({ data: [], total: 0 });
|
||||
|
|
@ -9616,6 +9617,46 @@ export class ProfileController extends Controller {
|
|||
keyword: `%${body.keyword}%`,
|
||||
},
|
||||
)
|
||||
.orWhere(
|
||||
body.keyword != null && body.keyword != ""
|
||||
? "CONCAT(orgRoot.orgRootShortName,' ',posMaster.posMasterNo) LIKE :keyword"
|
||||
: "1=1",
|
||||
{
|
||||
keyword: `%${body.keyword}%`,
|
||||
},
|
||||
)
|
||||
.orWhere(
|
||||
body.keyword != null && body.keyword != ""
|
||||
? "CONCAT(orgChild1.orgChild1ShortName,' ',posMaster.posMasterNo) LIKE :keyword"
|
||||
: "1=1",
|
||||
{
|
||||
keyword: `%${body.keyword}%`,
|
||||
},
|
||||
)
|
||||
.orWhere(
|
||||
body.keyword != null && body.keyword != ""
|
||||
? "CONCAT(orgChild2.orgChild2ShortName,' ',posMaster.posMasterNo) LIKE :keyword"
|
||||
: "1=1",
|
||||
{
|
||||
keyword: `%${body.keyword}%`,
|
||||
},
|
||||
)
|
||||
.orWhere(
|
||||
body.keyword != null && body.keyword != ""
|
||||
? "CONCAT(orgChild3.orgChild3ShortName,' ',posMaster.posMasterNo) LIKE :keyword"
|
||||
: "1=1",
|
||||
{
|
||||
keyword: `%${body.keyword}%`,
|
||||
},
|
||||
)
|
||||
.orWhere(
|
||||
body.keyword != null && body.keyword != ""
|
||||
? "CONCAT(orgChild4.orgChild4ShortName,' ',posMaster.posMasterNo) LIKE :keyword"
|
||||
: "1=1",
|
||||
{
|
||||
keyword: `%${body.keyword}%`,
|
||||
},
|
||||
)
|
||||
.orWhere(
|
||||
body.keyword != null && body.keyword != ""
|
||||
? "current_holder.position LIKE :keyword"
|
||||
|
|
|
|||
|
|
@ -5038,6 +5038,46 @@ export class ProfileEmployeeController extends Controller {
|
|||
keyword: `%${body.keyword}%`,
|
||||
},
|
||||
)
|
||||
.orWhere(
|
||||
body.keyword != null && body.keyword != ""
|
||||
? "CONCAT(orgRoot.orgRootShortName,' ',employeePosMaster.posMasterNo) LIKE :keyword"
|
||||
: "1=1",
|
||||
{
|
||||
keyword: `%${body.keyword}%`,
|
||||
},
|
||||
)
|
||||
.orWhere(
|
||||
body.keyword != null && body.keyword != ""
|
||||
? "CONCAT(orgChild1.orgChild1ShortName,' ',employeePosMaster.posMasterNo) LIKE :keyword"
|
||||
: "1=1",
|
||||
{
|
||||
keyword: `%${body.keyword}%`,
|
||||
},
|
||||
)
|
||||
.orWhere(
|
||||
body.keyword != null && body.keyword != ""
|
||||
? "CONCAT(orgChild2.orgChild2ShortName,' ',employeePosMaster.posMasterNo) LIKE :keyword"
|
||||
: "1=1",
|
||||
{
|
||||
keyword: `%${body.keyword}%`,
|
||||
},
|
||||
)
|
||||
.orWhere(
|
||||
body.keyword != null && body.keyword != ""
|
||||
? "CONCAT(orgChild3.orgChild3ShortName,' ',employeePosMaster.posMasterNo) LIKE :keyword"
|
||||
: "1=1",
|
||||
{
|
||||
keyword: `%${body.keyword}%`,
|
||||
},
|
||||
)
|
||||
.orWhere(
|
||||
body.keyword != null && body.keyword != ""
|
||||
? "CONCAT(orgChild4.orgChild4ShortName,' ',employeePosMaster.posMasterNo) LIKE :keyword"
|
||||
: "1=1",
|
||||
{
|
||||
keyword: `%${body.keyword}%`,
|
||||
},
|
||||
)
|
||||
.orWhere(
|
||||
body.keyword != null && body.keyword != ""
|
||||
? "current_holder.position LIKE :keyword"
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import {
|
|||
import permission from "../interfaces/permission";
|
||||
import { OrgRevision } from "../entities/OrgRevision";
|
||||
import { In } from "typeorm";
|
||||
import { ProfileSalary } from "../entities/ProfileSalary";
|
||||
@Route("api/v1/org/profile-employee/government")
|
||||
@Tags("ProfileEmployeeGovernment")
|
||||
@Security("bearerAuth")
|
||||
|
|
@ -26,6 +27,7 @@ export class ProfileGovernmentEmployeeController extends Controller {
|
|||
private positionRepo = AppDataSource.getRepository(EmployeePosition);
|
||||
private posMasterRepo = AppDataSource.getRepository(EmployeePosMaster);
|
||||
private orgRevisionRepository = AppDataSource.getRepository(OrgRevision);
|
||||
private salaryRepo = AppDataSource.getRepository(ProfileSalary);
|
||||
/**
|
||||
*
|
||||
* @summary ข้อมูลราชการ
|
||||
|
|
@ -150,32 +152,32 @@ export class ProfileGovernmentEmployeeController extends Controller {
|
|||
const record = await this.profileEmployeeRepo.findOne({
|
||||
where: {
|
||||
id: profileEmployeeId,
|
||||
profileSalary: {
|
||||
commandCode: In([
|
||||
"0",
|
||||
"9",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"8",
|
||||
"10",
|
||||
"11",
|
||||
"12",
|
||||
"13",
|
||||
"14",
|
||||
"15",
|
||||
"16",
|
||||
]),
|
||||
}
|
||||
// profileSalary: {
|
||||
// commandCode: In([
|
||||
// "0",
|
||||
// "9",
|
||||
// "1",
|
||||
// "2",
|
||||
// "3",
|
||||
// "4",
|
||||
// "8",
|
||||
// "10",
|
||||
// "11",
|
||||
// "12",
|
||||
// "13",
|
||||
// "14",
|
||||
// "15",
|
||||
// "16",
|
||||
// ]),
|
||||
// }
|
||||
},
|
||||
relations: ["posType", "posLevel", "profileSalary"],
|
||||
order: {
|
||||
profileSalary: {
|
||||
order: "DESC",
|
||||
createdAt: "DESC"
|
||||
}
|
||||
}
|
||||
relations: ["posType", "posLevel"/*, "profileSalary"*/],
|
||||
// order: {
|
||||
// profileSalary: {
|
||||
// order: "DESC",
|
||||
// createdAt: "DESC"
|
||||
// }
|
||||
// }
|
||||
});
|
||||
const posMaster = await this.posMasterRepo.findOne({
|
||||
where: {
|
||||
|
|
@ -216,16 +218,55 @@ export class ProfileGovernmentEmployeeController extends Controller {
|
|||
}
|
||||
}
|
||||
let _OrgLeave:any = []
|
||||
if (record?.isLeave && record?.profileSalary.length > 0) {
|
||||
let orgLeave:string = ""
|
||||
let posNoLeave:string = ""
|
||||
if (record?.isLeave /*&& record?.profileSalary.length > 0*/) {
|
||||
const profileSalary = await this.salaryRepo.find({
|
||||
select: [
|
||||
"orgRoot",
|
||||
"orgChild1",
|
||||
"orgChild2",
|
||||
"orgChild3",
|
||||
"orgChild4",
|
||||
"posNoAbb",
|
||||
"posNo"
|
||||
],
|
||||
where: {
|
||||
profileEmployeeId: profileEmployeeId,
|
||||
commandCode: In([
|
||||
"0",
|
||||
"9",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"8",
|
||||
"10",
|
||||
"11",
|
||||
"12",
|
||||
"13",
|
||||
"14",
|
||||
"15",
|
||||
"16",
|
||||
]),
|
||||
},
|
||||
order: {
|
||||
order: "DESC",
|
||||
createdAt: "DESC"
|
||||
}
|
||||
});
|
||||
_OrgLeave = [
|
||||
record?.profileSalary[0].orgChild4 ? record?.profileSalary[0].orgChild4 : null,
|
||||
record?.profileSalary[0].orgChild3 ? record?.profileSalary[0].orgChild3 : null,
|
||||
record?.profileSalary[0].orgChild2 ? record?.profileSalary[0].orgChild2 : null,
|
||||
record?.profileSalary[0].orgChild1 ? record?.profileSalary[0].orgChild1 : null,
|
||||
record?.profileSalary[0].orgRoot ? record?.profileSalary[0].orgRoot : null,
|
||||
profileSalary.length > 0 && profileSalary[0].orgChild4 ? profileSalary[0].orgChild4 : null,
|
||||
profileSalary.length > 0 && profileSalary[0].orgChild3 ? profileSalary[0].orgChild3 : null,
|
||||
profileSalary.length > 0 && profileSalary[0].orgChild2 ? profileSalary[0].orgChild2 : null,
|
||||
profileSalary.length > 0 && profileSalary[0].orgChild1 ? profileSalary[0].orgChild1 : null,
|
||||
profileSalary.length > 0 && profileSalary[0].orgRoot ? profileSalary[0].orgRoot : null,
|
||||
];
|
||||
orgLeave = _OrgLeave.filter((x:any) => x !== undefined && x !== null).join("\n");
|
||||
posNoLeave = profileSalary.length > 0
|
||||
? `${profileSalary[0].posNoAbb} ${profileSalary[0].posNo}`
|
||||
: ""
|
||||
}
|
||||
const orgLeave = _OrgLeave.filter((x:any) => x !== undefined && x !== null).join("\n");
|
||||
const data = {
|
||||
org: record?.isLeave == false ? org : orgLeave, //สังกัด
|
||||
position: record?.position, //ตำแหน่ง
|
||||
|
|
@ -235,9 +276,9 @@ export class ProfileGovernmentEmployeeController extends Controller {
|
|||
: `${record?.posType?.posTypeShortName ?? ""} ${record?.posLevel?.posLevelName ?? ""}`, //ระดับ
|
||||
posMasterNo: record?.isLeave == false
|
||||
? posMaster == null ? null : `${orgShortName} ${posMaster.posMasterNo}`
|
||||
: record && record?.profileSalary.length > 0
|
||||
: posNoLeave/*record && record?.profileSalary.length > 0
|
||||
? `${record?.profileSalary[0].posNoAbb} ${record?.profileSalary[0].posNo}`
|
||||
: null, //เลขที่ตำแหน่ง
|
||||
: null*/, //เลขที่ตำแหน่ง
|
||||
posType: record?.posType == null ? null : record?.posType.posTypeName, //ประเภท
|
||||
dateLeave: record?.birthDate == null ? null : calculateRetireDate(record?.birthDate), //วันเกษียณ
|
||||
dateAppoint: record?.dateAppoint, //วันที่สั่งบรรจุ
|
||||
|
|
@ -265,29 +306,29 @@ export class ProfileGovernmentEmployeeController extends Controller {
|
|||
const record = await this.profileEmployeeRepo.findOne({
|
||||
where: {
|
||||
id: profileEmployeeId,
|
||||
profileSalary:{
|
||||
commandCode: In([
|
||||
"0",
|
||||
"9",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"8",
|
||||
"10",
|
||||
"11",
|
||||
"12",
|
||||
"13",
|
||||
"14",
|
||||
"15",
|
||||
"16",
|
||||
]),
|
||||
}
|
||||
// profileSalary:{
|
||||
// commandCode: In([
|
||||
// "0",
|
||||
// "9",
|
||||
// "1",
|
||||
// "2",
|
||||
// "3",
|
||||
// "4",
|
||||
// "8",
|
||||
// "10",
|
||||
// "11",
|
||||
// "12",
|
||||
// "13",
|
||||
// "14",
|
||||
// "15",
|
||||
// "16",
|
||||
// ]),
|
||||
// }
|
||||
},
|
||||
relations: {
|
||||
posType: true,
|
||||
posLevel: true,
|
||||
profileSalary: true
|
||||
// profileSalary: true
|
||||
},
|
||||
});
|
||||
const posMaster = await this.posMasterRepo.findOne({
|
||||
|
|
@ -329,16 +370,55 @@ export class ProfileGovernmentEmployeeController extends Controller {
|
|||
}
|
||||
}
|
||||
let _OrgLeave:any = []
|
||||
if (record?.isLeave && record?.profileSalary.length > 0) {
|
||||
let orgLeave:string = ""
|
||||
let posNoLeave:string = ""
|
||||
if (record?.isLeave /*&& record?.profileSalary.length > 0*/) {
|
||||
const profileSalary = await this.salaryRepo.find({
|
||||
select: [
|
||||
"orgRoot",
|
||||
"orgChild1",
|
||||
"orgChild2",
|
||||
"orgChild3",
|
||||
"orgChild4",
|
||||
"posNoAbb",
|
||||
"posNo"
|
||||
],
|
||||
where: {
|
||||
profileEmployeeId: profileEmployeeId,
|
||||
commandCode: In([
|
||||
"0",
|
||||
"9",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"8",
|
||||
"10",
|
||||
"11",
|
||||
"12",
|
||||
"13",
|
||||
"14",
|
||||
"15",
|
||||
"16",
|
||||
]),
|
||||
},
|
||||
order: {
|
||||
order: "DESC",
|
||||
createdAt: "DESC"
|
||||
}
|
||||
});
|
||||
_OrgLeave = [
|
||||
record?.profileSalary[0].orgChild4 ? record?.profileSalary[0].orgChild4 : null,
|
||||
record?.profileSalary[0].orgChild3 ? record?.profileSalary[0].orgChild3 : null,
|
||||
record?.profileSalary[0].orgChild2 ? record?.profileSalary[0].orgChild2 : null,
|
||||
record?.profileSalary[0].orgChild1 ? record?.profileSalary[0].orgChild1 : null,
|
||||
record?.profileSalary[0].orgRoot ? record?.profileSalary[0].orgRoot : null,
|
||||
profileSalary.length > 0 && profileSalary[0].orgChild4 ? profileSalary[0].orgChild4 : null,
|
||||
profileSalary.length > 0 && profileSalary[0].orgChild3 ? profileSalary[0].orgChild3 : null,
|
||||
profileSalary.length > 0 && profileSalary[0].orgChild2 ? profileSalary[0].orgChild2 : null,
|
||||
profileSalary.length > 0 && profileSalary[0].orgChild1 ? profileSalary[0].orgChild1 : null,
|
||||
profileSalary.length > 0 && profileSalary[0].orgRoot ? profileSalary[0].orgRoot : null,
|
||||
];
|
||||
orgLeave = _OrgLeave.filter((x:any) => x !== undefined && x !== null).join("\n");
|
||||
posNoLeave = profileSalary.length > 0
|
||||
? `${profileSalary[0].posNoAbb} ${profileSalary[0].posNo}`
|
||||
: ""
|
||||
}
|
||||
const orgLeave = _OrgLeave.filter((x:any) => x !== undefined && x !== null).join("\n");
|
||||
const data = {
|
||||
org: record?.isLeave == false ? org : orgLeave, //สังกัด
|
||||
position: record?.position, //ตำแหน่ง
|
||||
|
|
@ -350,9 +430,9 @@ export class ProfileGovernmentEmployeeController extends Controller {
|
|||
? posMaster == null
|
||||
? null
|
||||
: `${orgShortName} ${posMaster.posMasterNo}`
|
||||
: record && record.profileSalary.length > 0
|
||||
: posNoLeave/*record && record.profileSalary.length > 0
|
||||
? `${record?.profileSalary[0].posNoAbb} ${record?.profileSalary[0].posNo}`
|
||||
: null, //เลขที่ตำแหน่ง
|
||||
: null*/, //เลขที่ตำแหน่ง
|
||||
posType: record?.posType == null ? null : record?.posType.posTypeName, //ประเภท
|
||||
dateLeave: record?.birthDate == null ? null : calculateRetireDate(record?.birthDate), //วันเกษียณ
|
||||
dateAppoint: record?.dateAppoint, //วันที่สั่งบรรจุ
|
||||
|
|
|
|||
|
|
@ -47,9 +47,13 @@ export const AppDataSource = new DataSource({
|
|||
logging: true,
|
||||
// timezone: "Z",
|
||||
entities:
|
||||
process.env.NODE_ENV !== "production" ? ["src/entities/**/*.ts"] : ["dist/entities/**/*{.ts,.js}"],
|
||||
process.env.NODE_ENV !== "production"
|
||||
? ["src/entities/**/*.ts"]
|
||||
: ["dist/entities/**/*{.ts,.js}"],
|
||||
migrations:
|
||||
process.env.NODE_ENV !== "production" ? ["src/entities/*.ts"] : ["dist/entities/*{.ts,.js}"],
|
||||
process.env.NODE_ENV !== "production"
|
||||
? ["src/migration/**/*.ts"]
|
||||
: ["dist/migration/**/*{.ts,.js}"],
|
||||
subscribers: [],
|
||||
logger: new MyCustomLogger(),
|
||||
});
|
||||
|
|
|
|||
39
src/entities/ApiAttribute.ts
Normal file
39
src/entities/ApiAttribute.ts
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import { ApiName } from "./ApiName";
|
||||
import { Entity, Column, ManyToOne, JoinColumn } from "typeorm";
|
||||
import { EntityBase } from "./base/Base";
|
||||
|
||||
@Entity("apiAttribute")
|
||||
export class ApiAttribute extends EntityBase {
|
||||
@Column({
|
||||
nullable: false,
|
||||
comment: "ชื่อตาราง",
|
||||
length: 50,
|
||||
})
|
||||
tbName: string;
|
||||
|
||||
@Column({
|
||||
nullable: false,
|
||||
comment: "คีย์ของแอตทริบิวต์",
|
||||
length: 255,
|
||||
})
|
||||
propertyKey: string;
|
||||
|
||||
@Column({
|
||||
nullable: false,
|
||||
comment: "ลำดับการแสดงผล",
|
||||
default: 0,
|
||||
type: "int",
|
||||
})
|
||||
ordering: number;
|
||||
|
||||
@Column({
|
||||
nullable: false,
|
||||
comment: "ไอดีของ API Name",
|
||||
length: 36, // UUID length
|
||||
})
|
||||
apiNameId: string;
|
||||
|
||||
@ManyToOne(() => ApiName, (apiName) => apiName.apiAttributes)
|
||||
@JoinColumn({ name: "apiNameId" })
|
||||
apiName: ApiName;
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import { ApiAttribute } from "./ApiAttribute";
|
||||
import { Entity, Column, ManyToMany, JoinTable, OneToMany } from "typeorm";
|
||||
import { EntityBase } from "./base/Base";
|
||||
import { ApiKey } from "./ApiKey";
|
||||
|
|
@ -29,10 +30,61 @@ export class ApiName extends EntityBase {
|
|||
})
|
||||
methodApi: string;
|
||||
|
||||
@Column({
|
||||
nullable: false,
|
||||
comment: "code สำหรับการเรียก API",
|
||||
length: 8,
|
||||
})
|
||||
code: string;
|
||||
|
||||
@Column({
|
||||
nullable: false,
|
||||
comment: "code ระบบสำหรับการเรียก API",
|
||||
length: 50,
|
||||
default: "registry",
|
||||
})
|
||||
system: string;
|
||||
|
||||
@Column({
|
||||
nullable: false,
|
||||
comment: "สถานะการใช้งาน",
|
||||
type: "boolean",
|
||||
default: false,
|
||||
})
|
||||
isActive: boolean;
|
||||
|
||||
@ManyToMany(() => ApiKey, (apiKey) => apiKey.apiNames)
|
||||
@JoinTable()
|
||||
apiKeys: ApiKey[];
|
||||
|
||||
@OneToMany(() => ApiHistory, (v) => v.apiName)
|
||||
apiHistorys: ApiHistory[];
|
||||
|
||||
@OneToMany(() => ApiAttribute, (v) => v.apiName)
|
||||
apiAttributes: ApiAttribute[];
|
||||
}
|
||||
|
||||
export class CreateApi {
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@Column()
|
||||
methodApi: "GET" | "POST" | "PUT";
|
||||
|
||||
@Column()
|
||||
system: string;
|
||||
|
||||
@Column()
|
||||
isActive: boolean;
|
||||
|
||||
@Column()
|
||||
apiAttributes: CreateApiAttribute[];
|
||||
}
|
||||
|
||||
export class CreateApiAttribute {
|
||||
@Column()
|
||||
tbName: string;
|
||||
|
||||
@Column()
|
||||
propertyKey: string[];
|
||||
}
|
||||
|
|
|
|||
16
src/interfaces/api-type.ts
Normal file
16
src/interfaces/api-type.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
type SystemCode = "registry" | "registry_emp" | "registry_temp" | "organization" | "position";
|
||||
|
||||
interface SystemDefinition {
|
||||
code: SystemCode;
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface EntityDefinition {
|
||||
name: string;
|
||||
repository: any;
|
||||
description: string;
|
||||
isMain?: boolean;
|
||||
system: SystemCode[];
|
||||
}
|
||||
|
||||
export { SystemCode, SystemDefinition, EntityDefinition };
|
||||
|
|
@ -553,6 +553,14 @@ export async function checkQueueInProgress(queueName: string) {
|
|||
// return false;
|
||||
}
|
||||
|
||||
export function chunkArray(array: any, size: number) {
|
||||
const result = [];
|
||||
for (let i = 0; i < array.length; i += size) {
|
||||
result.push(array.slice(i, i + size));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function commandTypePath(commandCode: string): string | null {
|
||||
switch (commandCode) {
|
||||
case "C-PM-01":
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { createDecoder, createVerifier } from "fast-jwt";
|
|||
|
||||
import HttpError from "../interfaces/http-error";
|
||||
import HttpStatus from "../interfaces/http-status";
|
||||
import { handleWebServiceAuth } from "./authWebService";
|
||||
|
||||
if (!process.env.AUTH_PUBLIC_KEY && !process.env.AUTH_REALM_URL) {
|
||||
throw new Error("Require keycloak AUTH_PUBLIC_KEY or AUTH_REALM_URL.");
|
||||
|
|
@ -30,6 +31,11 @@ export async function expressAuthentication(
|
|||
return { preferred_username: "bypassed" };
|
||||
}
|
||||
|
||||
// เพิ่มการจัดการสำหรับ Web Service Authentication
|
||||
if (securityName === "webServiceAuth") {
|
||||
return await handleWebServiceAuth(request);
|
||||
}
|
||||
|
||||
if (securityName !== "bearerAuth") throw new Error("ไม่ทราบวิธีการยืนยันตัวตน");
|
||||
|
||||
const token = request.headers["authorization"]?.includes("Bearer ")
|
||||
|
|
|
|||
56
src/middlewares/authWebService.ts
Normal file
56
src/middlewares/authWebService.ts
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import { RequestWithUserWebService } from "./user";
|
||||
import { AppDataSource } from "../database/data-source";
|
||||
import { ApiKey } from "../entities/ApiKey";
|
||||
import * as express from "express";
|
||||
|
||||
import HttpError from "../interfaces/http-error";
|
||||
import HttpStatus from "../interfaces/http-status";
|
||||
|
||||
// เพิ่มฟังก์ชันสำหรับจัดการ Web Service Authentication
|
||||
export async function handleWebServiceAuth(request: express.Request) {
|
||||
// ตัวอย่างการใช้ API Key
|
||||
const apiKey = request.headers["x-api-key"] as string;
|
||||
|
||||
if (!apiKey) {
|
||||
throw new HttpError(HttpStatus.UNAUTHORIZED, "ไม่พบข้อมูลสำหรับยืนยันตัวตน");
|
||||
}
|
||||
|
||||
// ตรวจสอบ API Key กับฐานข้อมูล
|
||||
const apiKeyData = await AppDataSource.getRepository(ApiKey).findOne({
|
||||
select: { id: true, name: true, keyApi: true },
|
||||
where: { keyApi: apiKey },
|
||||
relations: ["apiNames"],
|
||||
});
|
||||
if (!apiKeyData) {
|
||||
throw new HttpError(HttpStatus.UNAUTHORIZED, "ไม่สามารถยืนยันตัวตนได้");
|
||||
}
|
||||
|
||||
// บันทึก log data สำหรับ web service
|
||||
if (!request.app.locals.logData) {
|
||||
request.app.locals.logData = {};
|
||||
}
|
||||
|
||||
request.app.locals.logData.id = apiKeyData.id;
|
||||
request.app.locals.logData.name = apiKeyData.name;
|
||||
request.app.locals.logData.accessApi = apiKeyData.apiNames.map((x) => x.id) ?? [];
|
||||
|
||||
// ส่งคืนข้อมูลผู้ใช้ที่ยืนยันตัวตน
|
||||
return {
|
||||
id: apiKeyData.id,
|
||||
name: apiKeyData.name,
|
||||
type: "web-service",
|
||||
accessApi: apiKeyData.apiNames.map((x) => x.id) ?? [],
|
||||
};
|
||||
}
|
||||
|
||||
export function isPermissionRequest(
|
||||
request: RequestWithUserWebService,
|
||||
apiId: string,
|
||||
): Promise<boolean> {
|
||||
// ฟังก์ชันนี้ใช้เพื่อตรวจสอบสิทธิ์ของผู้ใช้ที่ร้องขอ API โดยตรวจสอบว่า user มีสิทธิ์เข้าถึง API ที่ร้องขอหรือไม่
|
||||
const hasPermission = request.user.accessApi.includes(apiId);
|
||||
if (!hasPermission) {
|
||||
throw new HttpError(HttpStatus.FORBIDDEN, "คุณไม่มีสิทธิ์เข้าถึง API นี้");
|
||||
}
|
||||
return Promise.resolve(hasPermission);
|
||||
}
|
||||
|
|
@ -11,3 +11,11 @@ export type RequestWithUser = Request & {
|
|||
role: string[];
|
||||
};
|
||||
};
|
||||
|
||||
export type RequestWithUserWebService = Request & {
|
||||
user: {
|
||||
id: string;
|
||||
name: string;
|
||||
accessApi: string[];
|
||||
};
|
||||
};
|
||||
|
|
|
|||
1316
src/migration/1754549669635-update_api_name.ts
Normal file
1316
src/migration/1754549669635-update_api_name.ts
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -1,7 +1,7 @@
|
|||
import amqp from "amqplib";
|
||||
import { AppDataSource } from "../database/data-source";
|
||||
import { Command } from "../entities/Command";
|
||||
import { commandTypePath } from "../interfaces/utils";
|
||||
import { chunkArray, commandTypePath } from "../interfaces/utils";
|
||||
import CallAPI from "../interfaces/call-api";
|
||||
import HttpError from "../interfaces/http-error";
|
||||
import HttpStatusCode from "../interfaces/http-status";
|
||||
|
|
@ -115,46 +115,139 @@ function createConsumer( //----> consumer
|
|||
|
||||
async function handler(msg: amqp.ConsumeMessage): Promise<boolean> {
|
||||
//----> condition before process consumer
|
||||
// const repo = AppDataSource.getRepository(Command);
|
||||
// const { data, token, user } = JSON.parse(msg.content.toString());
|
||||
// const { id, status, lastUpdateUserId, lastUpdateFullName, lastUpdatedAt } = data;
|
||||
// const command = await repo.findOne({
|
||||
// where: { id: id },
|
||||
// relations: ["commandType", "commandRecives"],
|
||||
// });
|
||||
// if (!command) return true;
|
||||
// let waiting_message = `ระบบทำการออกคำสั่งเลขที่ ${command.commandNo}/${command.commandYear + 543}`;
|
||||
// let success_message = `ระบบออกคำสั่งเลขที่ ${command.commandNo}/${command.commandYear + 543} เสร็จสิ้น`;
|
||||
// let error_message = `ระบบออกคำสั่งเลขที่ ${command.commandNo}/${command.commandYear + 543} ผิดพลาด`
|
||||
// if(command.commandType?.code == "C-PM-47"){
|
||||
// waiting_message = `ระบบทำการออกคำสั่งเลขที่ ${command.commandNo}`;
|
||||
// success_message = `ระบบออกคำสั่งเลขที่ ${command.commandNo} เสร็จสิ้น`;
|
||||
// error_message = `ระบบออกคำสั่งเลขที่ ${command.commandNo} ผิดพลาด`;
|
||||
// }
|
||||
// if (user) {
|
||||
// sendWebSocket(
|
||||
// "send-command-notification",
|
||||
// {
|
||||
// success: true,
|
||||
// message: waiting_message,
|
||||
// payload: command,
|
||||
// },
|
||||
// { userId: user?.sub },
|
||||
// ).catch(console.error);
|
||||
// }
|
||||
// const path = commandTypePath(command.commandType.code);
|
||||
// if (path == null) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบประเภทคำสั่งนี้ในระบบ");
|
||||
// return await new CallAPI()
|
||||
// //chunk 50
|
||||
// .PostData(
|
||||
// {
|
||||
// headers: { authorization: token },
|
||||
// },
|
||||
// path + "/excecute",
|
||||
// {
|
||||
// refIds: command.commandRecives //chunk
|
||||
// .filter((x) => x.refId != null)
|
||||
// .map((x) => ({
|
||||
// refId: x.refId,
|
||||
// commandNo: command.commandNo,
|
||||
// commandYear: command.commandYear,
|
||||
// commandId: command.id,
|
||||
// remark: command.positionDetail,
|
||||
// amount: x.amount,
|
||||
// amountSpecial: x.amountSpecial,
|
||||
// positionSalaryAmount: x.positionSalaryAmount,
|
||||
// mouthSalaryAmount: x.mouthSalaryAmount,
|
||||
// commandCode: command.commandType.commandCode,
|
||||
// commandName: command.commandType.name,
|
||||
// commandDateAffect: command.commandExcecuteDate,
|
||||
// commandDateSign: command.commandAffectDate,
|
||||
// })),
|
||||
// },
|
||||
// false,
|
||||
// )
|
||||
// .then(async (res) => {
|
||||
// console.log("[AMQ] Excecute Command Success");
|
||||
// Object.assign(command, { status, lastUpdateUserId, lastUpdateFullName, lastUpdatedAt });
|
||||
// const result = await repo.save(command).catch((e) => console.log(e));
|
||||
// if (user) {
|
||||
// sendWebSocket(
|
||||
// "send-command-notification",
|
||||
// {
|
||||
// success: true,
|
||||
// message: success_message,
|
||||
// payload: command,
|
||||
// },
|
||||
// { userId: user?.sub },
|
||||
// ).catch(console.error);
|
||||
// }
|
||||
// return !!result;
|
||||
// })
|
||||
// .catch((e) => {
|
||||
// console.error(e);
|
||||
// if (user) {
|
||||
// sendWebSocket(
|
||||
// "send-command-notification",
|
||||
// {
|
||||
// success: false,
|
||||
// message: error_message,
|
||||
// payload: command,
|
||||
// },
|
||||
// { userId: user?.sub },
|
||||
// ).catch(console.error);
|
||||
// }
|
||||
// return false;
|
||||
// });
|
||||
const repo = AppDataSource.getRepository(Command);
|
||||
const { data, token, user } = JSON.parse(msg.content.toString());
|
||||
const { id, status, lastUpdateUserId, lastUpdateFullName, lastUpdatedAt } = data;
|
||||
|
||||
const command = await repo.findOne({
|
||||
where: { id: id },
|
||||
relations: ["commandType", "commandRecives"],
|
||||
});
|
||||
if (!command) return true;
|
||||
|
||||
let waiting_message = `ระบบทำการออกคำสั่งเลขที่ ${command.commandNo}/${command.commandYear + 543}`;
|
||||
let success_message = `ระบบออกคำสั่งเลขที่ ${command.commandNo}/${command.commandYear + 543} เสร็จสิ้น`;
|
||||
let error_message = `ระบบออกคำสั่งเลขที่ ${command.commandNo}/${command.commandYear + 543} ผิดพลาด`
|
||||
if(command.commandType?.code == "C-PM-47"){
|
||||
let error_message = `ระบบออกคำสั่งเลขที่ ${command.commandNo}/${command.commandYear + 543} ผิดพลาด`;
|
||||
|
||||
if (command.commandType?.code == "C-PM-47") {
|
||||
waiting_message = `ระบบทำการออกคำสั่งเลขที่ ${command.commandNo}`;
|
||||
success_message = `ระบบออกคำสั่งเลขที่ ${command.commandNo} เสร็จสิ้น`;
|
||||
error_message = `ระบบออกคำสั่งเลขที่ ${command.commandNo} ผิดพลาด`;
|
||||
}
|
||||
|
||||
if (user) {
|
||||
sendWebSocket(
|
||||
"send-command-notification",
|
||||
{
|
||||
success: true,
|
||||
message: waiting_message,
|
||||
payload: command,
|
||||
},
|
||||
{ success: true, message: waiting_message, payload: command },
|
||||
{ userId: user?.sub },
|
||||
).catch(console.error);
|
||||
}
|
||||
|
||||
const path = commandTypePath(command.commandType.code);
|
||||
if (path == null) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบประเภทคำสั่งนี้ในระบบ");
|
||||
return await new CallAPI()
|
||||
|
||||
.PostData(
|
||||
{
|
||||
headers: { authorization: token },
|
||||
},
|
||||
path + "/excecute",
|
||||
{
|
||||
refIds: command.commandRecives
|
||||
.filter((x) => x.refId != null)
|
||||
.map((x) => ({
|
||||
|
||||
try {
|
||||
const allRefIds = new Set<string>();
|
||||
const chunks = chunkArray(
|
||||
command.commandRecives
|
||||
.filter((x) => x.refId != null)
|
||||
.map((x) => {
|
||||
const key = `${x.refId}-${command.id}`;
|
||||
if (allRefIds.has(key)) {
|
||||
return null;
|
||||
}
|
||||
allRefIds.add(key);
|
||||
|
||||
return {
|
||||
refId: x.refId,
|
||||
commandNo: command.commandNo,
|
||||
commandYear: command.commandYear,
|
||||
|
|
@ -168,42 +261,46 @@ async function handler(msg: amqp.ConsumeMessage): Promise<boolean> {
|
|||
commandName: command.commandType.name,
|
||||
commandDateAffect: command.commandExcecuteDate,
|
||||
commandDateSign: command.commandAffectDate,
|
||||
})),
|
||||
},
|
||||
false,
|
||||
)
|
||||
.then(async (res) => {
|
||||
console.log("[AMQ] Excecute Command Success");
|
||||
Object.assign(command, { status, lastUpdateUserId, lastUpdateFullName, lastUpdatedAt });
|
||||
const result = await repo.save(command).catch((e) => console.log(e));
|
||||
if (user) {
|
||||
sendWebSocket(
|
||||
"send-command-notification",
|
||||
{
|
||||
success: true,
|
||||
message: success_message,
|
||||
payload: command,
|
||||
},
|
||||
{ userId: user?.sub },
|
||||
).catch(console.error);
|
||||
}
|
||||
return !!result;
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
if (user) {
|
||||
sendWebSocket(
|
||||
"send-command-notification",
|
||||
{
|
||||
success: false,
|
||||
message: error_message,
|
||||
payload: command,
|
||||
},
|
||||
{ userId: user?.sub },
|
||||
).catch(console.error);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
};
|
||||
})
|
||||
.filter(Boolean),
|
||||
20
|
||||
);
|
||||
|
||||
for (const chunk of chunks) {
|
||||
await new CallAPI().PostData(
|
||||
{ headers: { authorization: token } },
|
||||
path + "/excecute",
|
||||
{ refIds: chunk },
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
Object.assign(command, { status, lastUpdateUserId, lastUpdateFullName, lastUpdatedAt });
|
||||
const result = await repo.save(command);
|
||||
|
||||
if (user) {
|
||||
sendWebSocket(
|
||||
"send-command-notification",
|
||||
{ success: true, message: success_message, payload: command },
|
||||
{ userId: user?.sub },
|
||||
).catch(console.error);
|
||||
}
|
||||
|
||||
console.log("[AMQ] Excecute Command Success");
|
||||
return !!result;
|
||||
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
if (user) {
|
||||
sendWebSocket(
|
||||
"send-command-notification",
|
||||
{ success: false, message: error_message, payload: command },
|
||||
{ userId: user?.sub },
|
||||
).catch(console.error);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// async function handler(msg: amqp.ConsumeMessage): Promise<boolean> {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,12 @@
|
|||
"name": "Authorization",
|
||||
"description": "Keycloak Bearer Token",
|
||||
"in": "header"
|
||||
},
|
||||
"webServiceAuth": {
|
||||
"type": "apiKey",
|
||||
"name": "X-API-Key",
|
||||
"description": "API KEY สำหรับ Web Service",
|
||||
"in": "header"
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue