All checks were successful
Build & Deploy on Dev / build (push) Successful in 1m1s
9189 lines
378 KiB
TypeScript
9189 lines
378 KiB
TypeScript
import { RoleKeycloak } from "./../entities/RoleKeycloak";
|
|
import { ProfileEmployee } from "./../entities/ProfileEmployee";
|
|
import { EmployeePosition } from "./../entities/EmployeePosition";
|
|
import { EmployeePosMaster } from "./../entities/EmployeePosMaster";
|
|
import { Position } from "./../entities/Position";
|
|
import { ProfileSalaryHistory } from "./../entities/ProfileSalaryHistory";
|
|
import { ProfileSalary } from "./../entities/ProfileSalary";
|
|
import {
|
|
Controller,
|
|
Get,
|
|
Post,
|
|
Put,
|
|
Route,
|
|
Security,
|
|
Tags,
|
|
Body,
|
|
Path,
|
|
Request,
|
|
Response,
|
|
} from "tsoa";
|
|
import { CreateOrgRevision, OrgRevision } from "../entities/OrgRevision";
|
|
import { AppDataSource } from "../database/data-source";
|
|
import HttpSuccess from "../interfaces/http-success";
|
|
import { OrgChild1 } from "../entities/OrgChild1";
|
|
import HttpError from "../interfaces/http-error";
|
|
import HttpStatusCode from "../interfaces/http-status";
|
|
import { In, IsNull, Not, Like } from "typeorm";
|
|
import { OrgRoot } from "../entities/OrgRoot";
|
|
import { OrgChild2 } from "../entities/OrgChild2";
|
|
import { OrgChild3 } from "../entities/OrgChild3";
|
|
import { OrgChild4 } from "../entities/OrgChild4";
|
|
import { PosMaster } from "../entities/PosMaster";
|
|
import { Profile } from "../entities/Profile";
|
|
import { RequestWithUser } from "../middlewares/user";
|
|
import permission from "../interfaces/permission";
|
|
import {
|
|
checkQueueInProgress,
|
|
resolveNodeId,
|
|
resolveNodeLevel,
|
|
setLogDataDiff,
|
|
} from "../interfaces/utils";
|
|
import { sendToQueueOrg, sendToQueueOrgDraft } from "../services/rabbitmq";
|
|
import { PosType } from "../entities/PosType";
|
|
import { PosLevel } from "../entities/PosLevel";
|
|
import { PermissionOrg } from "../entities/PermissionOrg";
|
|
import {
|
|
deleteUser,
|
|
getToken,
|
|
createUser,
|
|
getUserByUsername,
|
|
getRoles,
|
|
addUserRoles,
|
|
updateUserAttributes,
|
|
} from "../keycloak";
|
|
import {
|
|
getPositionCountsAggregated,
|
|
getPositionCount,
|
|
PositionCountsByNode,
|
|
} from "../services/OrganizationService";
|
|
import {
|
|
BatchSavePosMasterHistoryOfficer,
|
|
CreatePosMasterHistoryEmployee,
|
|
CreatePosMasterHistoryOfficer,
|
|
SavePosMasterHistoryOfficer,
|
|
} from "../services/PositionService";
|
|
import { orgStructureCache } from "../utils/OrgStructureCache";
|
|
import { OrgIdMapping, AllOrgMappings, SavePosMasterHistory } from "../interfaces/OrgMapping";
|
|
import { OrgPermissionData, NodeLevel } from "../interfaces/OrgTypes";
|
|
import { formatPosMaster, generateLabelName, filterPosMasters } from "../utils/org-formatting";
|
|
|
|
@Route("api/v1/org")
|
|
@Tags("Organization")
|
|
@Security("bearerAuth")
|
|
@Response(
|
|
HttpStatusCode.INTERNAL_SERVER_ERROR,
|
|
"เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง",
|
|
)
|
|
export class OrganizationController extends Controller {
|
|
private orgRevisionRepository = AppDataSource.getRepository(OrgRevision);
|
|
private orgRootRepository = AppDataSource.getRepository(OrgRoot);
|
|
private child1Repository = AppDataSource.getRepository(OrgChild1);
|
|
private child2Repository = AppDataSource.getRepository(OrgChild2);
|
|
private child3Repository = AppDataSource.getRepository(OrgChild3);
|
|
private child4Repository = AppDataSource.getRepository(OrgChild4);
|
|
private posMasterRepository = AppDataSource.getRepository(PosMaster);
|
|
private profileRepo = AppDataSource.getRepository(Profile);
|
|
private posTypeRepository = AppDataSource.getRepository(PosType);
|
|
private posLevelRepository = AppDataSource.getRepository(PosLevel);
|
|
private permissionOrgRepository = AppDataSource.getRepository(PermissionOrg);
|
|
private profileSalaryRepository = AppDataSource.getRepository(ProfileSalary);
|
|
private salaryHistoryRepo = AppDataSource.getRepository(ProfileSalaryHistory);
|
|
private positionRepository = AppDataSource.getRepository(Position);
|
|
|
|
private profileEmployeeRepo = AppDataSource.getRepository(ProfileEmployee);
|
|
private employeePosMasterRepository = AppDataSource.getRepository(EmployeePosMaster);
|
|
private employeePositionRepository = AppDataSource.getRepository(EmployeePosition);
|
|
private roleKeycloakRepo = AppDataSource.getRepository(RoleKeycloak);
|
|
|
|
/**
|
|
* API ล้างข้อมูล
|
|
*
|
|
* @summary ล้างข้อมูล
|
|
*
|
|
*/
|
|
@Get("clear-db")
|
|
async ClearDb() {
|
|
return new HttpSuccess();
|
|
}
|
|
|
|
/**
|
|
* API รายการประวัติโครงสร้าง
|
|
*
|
|
* @summary ORG_020 - รายการประวัติโครงสร้าง #21
|
|
*
|
|
*/
|
|
@Get("history")
|
|
async GetHistory() {
|
|
const orgRevision = await this.orgRevisionRepository.find({
|
|
select: ["id", "orgRevisionName", "orgRevisionIsCurrent", "createdAt", "orgRevisionIsDraft"],
|
|
order: { createdAt: "DESC" },
|
|
});
|
|
// if (!orgRevision) {
|
|
// return new HttpSuccess([]);
|
|
// }
|
|
const mapOrgRevisions = orgRevision.map((revision) => ({
|
|
orgRevisionId: revision.id,
|
|
orgRevisionName: revision.orgRevisionName,
|
|
orgRevisionIsCurrent: revision.orgRevisionIsCurrent,
|
|
orgRevisionCreatedAt: revision.createdAt,
|
|
orgRevisionIsDraft: revision.orgRevisionIsDraft,
|
|
}));
|
|
|
|
return new HttpSuccess(mapOrgRevisions);
|
|
}
|
|
|
|
/**
|
|
* API โครงสร้างปัจจุบันที่ใช้อยู่
|
|
*
|
|
* @summary ORG_021 - โครงสร้างปัจจุบันที่ใช้อยู่ #22
|
|
*
|
|
*/
|
|
@Get("active")
|
|
async GetActive() {
|
|
const orgRevisionActive = await this.orgRevisionRepository.findOne({
|
|
where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
|
|
});
|
|
const orgRevisionDraf = await this.orgRevisionRepository.findOne({
|
|
where: { orgRevisionIsCurrent: false, orgRevisionIsDraft: true },
|
|
});
|
|
const mapData = {
|
|
activeId: orgRevisionActive == null ? null : orgRevisionActive.id,
|
|
activeName: orgRevisionActive == null ? null : orgRevisionActive.orgRevisionName,
|
|
draftId: orgRevisionDraf == null ? null : orgRevisionDraf.id,
|
|
draftName: orgRevisionDraf == null ? null : orgRevisionDraf.orgRevisionName,
|
|
orgPublishDate: orgRevisionDraf == null ? null : orgRevisionDraf.orgPublishDate,
|
|
isPublic: orgRevisionDraf == null || orgRevisionDraf.orgRevisionName == null ? false : true,
|
|
};
|
|
return new HttpSuccess(mapData);
|
|
}
|
|
|
|
/**
|
|
* API สร้างแบบร่างโครงสร้าง
|
|
*
|
|
* @summary ORG_022 - สร้างโครงสร้างใหม่ #23
|
|
*
|
|
*/
|
|
@Post("draft")
|
|
async CreateOrgRevision(
|
|
@Body() requestBody: CreateOrgRevision,
|
|
@Request() request: RequestWithUser,
|
|
) {
|
|
try {
|
|
// CheckQueueInProgress
|
|
const [isBusyDraft, isBusyPublish] = await Promise.all([
|
|
checkQueueInProgress(`${process.env.AMQ_QUEUE_ORG_DRAFT}`),
|
|
checkQueueInProgress(`${process.env.AMQ_QUEUE_ORG}`),
|
|
]);
|
|
// console.log("✅ ตรวจสอบแล้ว Draft Busy:", isBusyDraft);
|
|
// console.log("✅ ตรวจสอบแล้ว Publish Busy:", isBusyPublish);
|
|
if (isBusyDraft || isBusyPublish) {
|
|
// console.log("🚫 พบว่ามีงานอยู่ในคิว — error")
|
|
throw new HttpError(
|
|
HttpStatusCode.CONFLICT,
|
|
"ไม่สามารถดำเนินการได้ หากกำลังเผยแพร่หรือสร้างแบบร่างโครงสร้างหน่วยงาน",
|
|
);
|
|
}
|
|
//new main revision
|
|
const before = null;
|
|
const revision = Object.assign(new OrgRevision(), requestBody) as OrgRevision;
|
|
revision.orgRevisionIsDraft = true;
|
|
revision.orgRevisionIsCurrent = false;
|
|
revision.createdUserId = request.user.sub;
|
|
revision.createdFullName = request.user.name;
|
|
revision.lastUpdateUserId = request.user.sub;
|
|
revision.lastUpdateFullName = request.user.name;
|
|
revision.createdAt = new Date();
|
|
revision.lastUpdatedAt = new Date();
|
|
await this.orgRevisionRepository.save(revision, { data: request });
|
|
|
|
setLogDataDiff(request, { before, after: revision });
|
|
const msg = {
|
|
data: {
|
|
requestBody: requestBody,
|
|
request: request.user,
|
|
revision: revision,
|
|
},
|
|
user: request.user,
|
|
};
|
|
await sendToQueueOrgDraft(msg);
|
|
return new HttpSuccess("Draft is being created... Processing in the background.");
|
|
} catch (error: any) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* API สร้างแบบร่างโครงสร้าง
|
|
*
|
|
* @summary ORG_022 - สร้างโครงสร้างใหม่ #23
|
|
*
|
|
*/
|
|
@Post("finddna")
|
|
async FindDnaOrg(
|
|
@Body()
|
|
requestBody: {
|
|
root: string[] | null;
|
|
child1: string[] | null;
|
|
child2: string[] | null;
|
|
child3: string[] | null;
|
|
child4: string[] | null;
|
|
privilege: string;
|
|
},
|
|
@Request() request: RequestWithUser,
|
|
) {
|
|
const _data = [];
|
|
if (requestBody.root != null && requestBody.root.length > 0) {
|
|
for (const x of requestBody.root) {
|
|
const data = await this.orgRootRepository.findOne({
|
|
where: { id: x },
|
|
});
|
|
if (data) {
|
|
_data.push(data.ancestorDNA);
|
|
}
|
|
}
|
|
requestBody.root = _data;
|
|
}
|
|
const _data1 = [];
|
|
if (requestBody.child1 != null && requestBody.child1.length > 0) {
|
|
for (const x of requestBody.child1) {
|
|
const data = await this.child1Repository.findOne({
|
|
where: { id: x },
|
|
});
|
|
if (data) {
|
|
_data1.push(data.ancestorDNA);
|
|
}
|
|
}
|
|
requestBody.child1 = _data1;
|
|
}
|
|
const _data2 = [];
|
|
if (requestBody.child2 != null && requestBody.child2.length > 0) {
|
|
for (const x of requestBody.child2) {
|
|
const data = await this.child2Repository.findOne({
|
|
where: { id: x },
|
|
});
|
|
if (data) {
|
|
_data2.push(data.ancestorDNA);
|
|
}
|
|
}
|
|
requestBody.child2 = _data2;
|
|
}
|
|
const _data3 = [];
|
|
if (requestBody.child3 != null && requestBody.child3.length > 0) {
|
|
for (const x of requestBody.child3) {
|
|
const data = await this.child3Repository.findOne({
|
|
where: { id: x },
|
|
});
|
|
if (data) {
|
|
_data3.push(data.ancestorDNA);
|
|
}
|
|
}
|
|
requestBody.child3 = _data3;
|
|
}
|
|
const _data4 = [];
|
|
if (requestBody.child4 != null && requestBody.child4.length > 0) {
|
|
for (const x of requestBody.child4) {
|
|
const data = await this.child4Repository.findOne({
|
|
where: { id: x },
|
|
});
|
|
if (data) {
|
|
_data4.push(data.ancestorDNA);
|
|
}
|
|
}
|
|
requestBody.child4 = _data4;
|
|
}
|
|
return new HttpSuccess(requestBody);
|
|
}
|
|
|
|
/**
|
|
* API หา ORG DNA ID
|
|
*
|
|
* @summary หา ORG DNA ID
|
|
*
|
|
*/
|
|
@Get("finddna-by-keycloak/{keycloakId}")
|
|
async FindDnaOrgByKeycloakId(@Path() keycloakId: string) {
|
|
let reply: any;
|
|
|
|
const profileByKeycloak: any = await this.profileRepo.findOne({
|
|
where: { keycloak: keycloakId },
|
|
select: ["id", "keycloak"],
|
|
});
|
|
|
|
const orgRevision = await this.orgRevisionRepository.findOne({
|
|
select: ["id"],
|
|
where: {
|
|
orgRevisionIsDraft: false,
|
|
orgRevisionIsCurrent: true,
|
|
},
|
|
});
|
|
|
|
const posMaster = await AppDataSource.getRepository(PosMaster)
|
|
.createQueryBuilder("pos")
|
|
.leftJoin("pos.orgRoot", "orgRoot")
|
|
.leftJoin("pos.orgChild1", "orgChild1")
|
|
.leftJoin("pos.orgChild2", "orgChild2")
|
|
.leftJoin("pos.orgChild3", "orgChild3")
|
|
.leftJoin("pos.orgChild4", "orgChild4")
|
|
.where("pos.current_holderId = :holderId", {
|
|
holderId: profileByKeycloak.id,
|
|
})
|
|
.andWhere("pos.orgRevisionId = :revId", {
|
|
revId: orgRevision?.id,
|
|
})
|
|
.select([
|
|
"pos.id",
|
|
"orgRoot.ancestorDNA as rootDnaId",
|
|
"orgChild1.ancestorDNA as child1DnaId",
|
|
"orgChild2.ancestorDNA as child2DnaId",
|
|
"orgChild3.ancestorDNA as child3DnaId",
|
|
"orgChild4.ancestorDNA as child4DnaId",
|
|
])
|
|
.getRawOne();
|
|
|
|
if (!posMaster) {
|
|
reply = {
|
|
rootDnaId: null,
|
|
child1DnaId: null,
|
|
child2DnaId: null,
|
|
child3DnaId: null,
|
|
child4DnaId: null,
|
|
};
|
|
} else {
|
|
reply = {
|
|
rootDnaId: posMaster.rootDnaId,
|
|
child1DnaId: posMaster.child1DnaId,
|
|
child2DnaId: posMaster.child2DnaId,
|
|
child3DnaId: posMaster.child3DnaId,
|
|
child4DnaId: posMaster.child4DnaId,
|
|
};
|
|
}
|
|
return new HttpSuccess(reply);
|
|
}
|
|
|
|
/**
|
|
* API เช็คสถานะโครงสร้างว่าส่งคนไปออกคำสั่งหรือไม่
|
|
*
|
|
* @summary API เช็คสถานะโครงสร้างว่าส่งคนไปออกคำสั่งหรือไม่
|
|
*
|
|
* @param {string} id Id OrgRevison
|
|
*/
|
|
@Get("lock/{id}")
|
|
async GetById(@Request() request: RequestWithUser, @Path() id: string) {
|
|
//add check permission
|
|
const orgRevision = await this.orgRevisionRepository.findOne({
|
|
where: { id: id },
|
|
});
|
|
if (!orgRevision) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลโครงสร้าง");
|
|
}
|
|
return new HttpSuccess(orgRevision.isLock);
|
|
}
|
|
|
|
/**
|
|
* API รายละเอียดโครงสร้าง
|
|
*
|
|
* @summary ORG_023 - รายละเอียดโครงสร้าง (ADMIN Menu) #25
|
|
*
|
|
*/
|
|
@Get("admin/{id}")
|
|
async detailForAdmin(@Path() id: string, @Request() request: RequestWithUser) {
|
|
// let _data: any = {
|
|
// root: null,
|
|
// child1: null,
|
|
// child2: null,
|
|
// child3: null,
|
|
// child4: null,
|
|
// };
|
|
|
|
const orgRevision = await this.orgRevisionRepository.findOne({ where: { id } });
|
|
if (!orgRevision) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูล");
|
|
}
|
|
// let attrOwnership = null;
|
|
if (
|
|
orgRevision.orgRevisionIsDraft == true &&
|
|
orgRevision.orgRevisionIsCurrent == false &&
|
|
request.user.role.includes("SUPER_ADMIN")
|
|
// attrOwnership == false
|
|
) {
|
|
const profile = await this.profileRepo.findOne({
|
|
where: { keycloak: request.user.sub },
|
|
// relations: ["permissionProfiles"],
|
|
});
|
|
if (!profile) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผู้ใช้งานในทะเบียนประวัติ");
|
|
}
|
|
// _data = {
|
|
// root: profile.permissionProfiles.map((x) => x.orgRootId),
|
|
// child1: null,
|
|
// child2: null,
|
|
// child3: null,
|
|
// child4: null,
|
|
// };
|
|
}
|
|
|
|
const orgRootData = await AppDataSource.getRepository(OrgRoot)
|
|
.createQueryBuilder("orgRoot")
|
|
.where("orgRoot.orgRevisionId = :id", { id })
|
|
// .andWhere(
|
|
// _data.root != undefined && _data.root != null
|
|
// ? _data.root[0] != null
|
|
// ? `orgRoot.id IN (:...node)`
|
|
// : `orgRoot.id is null`
|
|
// : "1=1",
|
|
// {
|
|
// node: _data.root,
|
|
// },
|
|
// )
|
|
.select([
|
|
"orgRoot.id",
|
|
"orgRoot.isDeputy",
|
|
"orgRoot.isCommission",
|
|
"orgRoot.orgRootName",
|
|
"orgRoot.orgRootShortName",
|
|
"orgRoot.orgRootCode",
|
|
"orgRoot.orgRootOrder",
|
|
"orgRoot.orgRootPhoneEx",
|
|
"orgRoot.orgRootPhoneIn",
|
|
"orgRoot.orgRootFax",
|
|
"orgRoot.orgRevisionId",
|
|
"orgRoot.orgRootRank",
|
|
"orgRoot.orgRootRankSub",
|
|
"orgRoot.DEPARTMENT_CODE",
|
|
"orgRoot.DIVISION_CODE",
|
|
"orgRoot.SECTION_CODE",
|
|
"orgRoot.JOB_CODE",
|
|
"orgRoot.responsibility",
|
|
])
|
|
.orderBy("orgRoot.orgRootOrder", "ASC")
|
|
.getMany();
|
|
const orgRootIds = orgRootData.map((orgRoot) => orgRoot.id) || null;
|
|
const orgChild1Data =
|
|
orgRootIds && orgRootIds.length > 0
|
|
? await AppDataSource.getRepository(OrgChild1)
|
|
.createQueryBuilder("orgChild1")
|
|
.where("orgChild1.orgRootId IN (:...ids)", { ids: orgRootIds })
|
|
// .andWhere(
|
|
// _data.child1 != undefined && _data.child1 != null
|
|
// ? _data.child1[0] != null
|
|
// ? `orgChild1.id IN (:...node)`
|
|
// : `orgChild1.id is null`
|
|
// : "1=1",
|
|
// {
|
|
// node: _data.child1,
|
|
// },
|
|
// )
|
|
.select([
|
|
"orgChild1.id",
|
|
"orgChild1.isOfficer",
|
|
"orgChild1.isInformation",
|
|
"orgChild1.orgChild1Name",
|
|
"orgChild1.orgChild1ShortName",
|
|
"orgChild1.orgChild1Code",
|
|
"orgChild1.orgChild1Order",
|
|
"orgChild1.orgChild1PhoneEx",
|
|
"orgChild1.orgChild1PhoneIn",
|
|
"orgChild1.orgChild1Fax",
|
|
"orgChild1.orgRootId",
|
|
"orgChild1.orgChild1Rank",
|
|
"orgChild1.orgChild1RankSub",
|
|
"orgChild1.DEPARTMENT_CODE",
|
|
"orgChild1.DIVISION_CODE",
|
|
"orgChild1.SECTION_CODE",
|
|
"orgChild1.JOB_CODE",
|
|
"orgChild1.responsibility",
|
|
])
|
|
.orderBy("orgChild1.orgChild1Order", "ASC")
|
|
.getMany()
|
|
: [];
|
|
|
|
const orgChild1Ids = orgChild1Data.map((orgChild1) => orgChild1.id) || null;
|
|
const orgChild2Data =
|
|
orgChild1Ids && orgChild1Ids.length > 0
|
|
? await AppDataSource.getRepository(OrgChild2)
|
|
.createQueryBuilder("orgChild2")
|
|
.where("orgChild2.orgChild1Id IN (:...ids)", { ids: orgChild1Ids })
|
|
// .andWhere(
|
|
// _data.child2 != undefined && _data.child2 != null
|
|
// ? _data.child2[0] != null
|
|
// ? `orgChild2.id IN (:...node)`
|
|
// : `orgChild2.id is null`
|
|
// : "1=1",
|
|
// {
|
|
// node: _data.child2,
|
|
// },
|
|
// )
|
|
.select([
|
|
"orgChild2.id",
|
|
"orgChild2.orgChild2Name",
|
|
"orgChild2.orgChild2ShortName",
|
|
"orgChild2.orgChild2Code",
|
|
"orgChild2.orgChild2Order",
|
|
"orgChild2.orgChild2PhoneEx",
|
|
"orgChild2.orgChild2PhoneIn",
|
|
"orgChild2.orgChild2Fax",
|
|
"orgChild2.orgRootId",
|
|
"orgChild2.orgChild2Rank",
|
|
"orgChild2.orgChild2RankSub",
|
|
"orgChild2.DEPARTMENT_CODE",
|
|
"orgChild2.DIVISION_CODE",
|
|
"orgChild2.SECTION_CODE",
|
|
"orgChild2.JOB_CODE",
|
|
"orgChild2.orgChild1Id",
|
|
"orgChild2.responsibility",
|
|
])
|
|
.orderBy("orgChild2.orgChild2Order", "ASC")
|
|
.getMany()
|
|
: [];
|
|
|
|
const orgChild2Ids = orgChild2Data.map((orgChild2) => orgChild2.id) || null;
|
|
const orgChild3Data =
|
|
orgChild2Ids && orgChild2Ids.length > 0
|
|
? await AppDataSource.getRepository(OrgChild3)
|
|
.createQueryBuilder("orgChild3")
|
|
.where("orgChild3.orgChild2Id IN (:...ids)", { ids: orgChild2Ids })
|
|
// .andWhere(
|
|
// _data.child3 != undefined && _data.child3 != null
|
|
// ? _data.child3[0] != null
|
|
// ? `orgChild3.id IN (:...node)`
|
|
// : `orgChild3.id is null`
|
|
// : "1=1",
|
|
// {
|
|
// node: _data.child3,
|
|
// },
|
|
// )
|
|
.select([
|
|
"orgChild3.id",
|
|
"orgChild3.orgChild3Name",
|
|
"orgChild3.orgChild3ShortName",
|
|
"orgChild3.orgChild3Code",
|
|
"orgChild3.orgChild3Order",
|
|
"orgChild3.orgChild3PhoneEx",
|
|
"orgChild3.orgChild3PhoneIn",
|
|
"orgChild3.orgChild3Fax",
|
|
"orgChild3.orgRootId",
|
|
"orgChild3.orgChild3Rank",
|
|
"orgChild3.orgChild3RankSub",
|
|
"orgChild3.DEPARTMENT_CODE",
|
|
"orgChild3.DIVISION_CODE",
|
|
"orgChild3.SECTION_CODE",
|
|
"orgChild3.JOB_CODE",
|
|
"orgChild3.orgChild2Id",
|
|
"orgChild3.responsibility",
|
|
])
|
|
.orderBy("orgChild3.orgChild3Order", "ASC")
|
|
.getMany()
|
|
: [];
|
|
|
|
const orgChild3Ids = orgChild3Data.map((orgChild3) => orgChild3.id) || null;
|
|
const orgChild4Data =
|
|
orgChild3Ids && orgChild3Ids.length > 0
|
|
? await AppDataSource.getRepository(OrgChild4)
|
|
.createQueryBuilder("orgChild4")
|
|
.where("orgChild4.orgChild3Id IN (:...ids)", { ids: orgChild3Ids })
|
|
// .andWhere(
|
|
// _data.child4 != undefined && _data.child4 != null
|
|
// ? _data.child4[0] != null
|
|
// ? `orgChild4.id IN (:...node)`
|
|
// : `orgChild4.id is null`
|
|
// : "1=1",
|
|
// {
|
|
// node: _data.child4,
|
|
// },
|
|
// )
|
|
.select([
|
|
"orgChild4.id",
|
|
"orgChild4.orgChild4Name",
|
|
"orgChild4.orgChild4ShortName",
|
|
"orgChild4.orgChild4Code",
|
|
"orgChild4.orgChild4Order",
|
|
"orgChild4.orgChild4PhoneEx",
|
|
"orgChild4.orgChild4PhoneIn",
|
|
"orgChild4.orgChild4Fax",
|
|
"orgChild4.orgRootId",
|
|
"orgChild4.orgChild4Rank",
|
|
"orgChild4.orgChild4RankSub",
|
|
"orgChild4.DEPARTMENT_CODE",
|
|
"orgChild4.DIVISION_CODE",
|
|
"orgChild4.SECTION_CODE",
|
|
"orgChild4.JOB_CODE",
|
|
"orgChild4.orgChild3Id",
|
|
"orgChild4.responsibility",
|
|
])
|
|
.orderBy("orgChild4.orgChild4Order", "ASC")
|
|
.getMany()
|
|
: [];
|
|
|
|
const formattedData = await Promise.all(
|
|
orgRootData.map(async (orgRoot) => {
|
|
return {
|
|
orgTreeId: orgRoot.id,
|
|
orgLevel: 0,
|
|
orgName: orgRoot.orgRootName,
|
|
orgTreeName: orgRoot.orgRootName,
|
|
orgTreeShortName: orgRoot.orgRootShortName,
|
|
orgTreeCode: orgRoot.orgRootCode,
|
|
orgCode: orgRoot.orgRootCode + "00",
|
|
orgTreeRank: orgRoot.orgRootRank,
|
|
orgTreeRankSub: orgRoot.orgRootRankSub,
|
|
DEPARTMENT_CODE: orgRoot.DEPARTMENT_CODE,
|
|
DIVISION_CODE: orgRoot.DIVISION_CODE,
|
|
SECTION_CODE: orgRoot.SECTION_CODE,
|
|
JOB_CODE: orgRoot.JOB_CODE,
|
|
orgTreeOrder: orgRoot.orgRootOrder,
|
|
orgTreePhoneEx: orgRoot.orgRootPhoneEx,
|
|
orgTreePhoneIn: orgRoot.orgRootPhoneIn,
|
|
orgTreeFax: orgRoot.orgRootFax,
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootName: orgRoot.orgRootName,
|
|
responsibility: orgRoot.responsibility,
|
|
isOfficer: false,
|
|
isDeputy: orgRoot.isDeputy,
|
|
isCommission: orgRoot.isCommission,
|
|
labelName:
|
|
orgRoot.orgRootName + " " + orgRoot.orgRootCode + "00" + " " + orgRoot.orgRootShortName,
|
|
totalPosition: await this.posMasterRepository.count({
|
|
where: { orgRevisionId: orgRoot.orgRevisionId, orgRootId: orgRoot.id },
|
|
}),
|
|
totalPositionCurrentUse: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
current_holderId: Not(IsNull()) || Not(""),
|
|
},
|
|
}),
|
|
totalPositionCurrentVacant: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
current_holderId: IsNull() || "",
|
|
},
|
|
}),
|
|
totalPositionNextUse: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
next_holderId: Not(IsNull()) || Not(""),
|
|
},
|
|
}),
|
|
totalPositionNextVacant: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
next_holderId: IsNull() || "",
|
|
},
|
|
}),
|
|
totalRootPosition: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: IsNull() || "",
|
|
orgChild2Id: IsNull() || "",
|
|
orgChild3Id: IsNull() || "",
|
|
orgChild4Id: IsNull() || "",
|
|
},
|
|
}),
|
|
totalRootPositionCurrentUse: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: IsNull() || "",
|
|
orgChild2Id: IsNull() || "",
|
|
orgChild3Id: IsNull() || "",
|
|
orgChild4Id: IsNull() || "",
|
|
current_holderId: Not(IsNull()) || Not(""),
|
|
},
|
|
}),
|
|
totalRootPositionCurrentVacant: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: IsNull() || "",
|
|
orgChild2Id: IsNull() || "",
|
|
orgChild3Id: IsNull() || "",
|
|
orgChild4Id: IsNull() || "",
|
|
current_holderId: IsNull() || "",
|
|
},
|
|
}),
|
|
totalRootPositionNextUse: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: IsNull() || "",
|
|
orgChild2Id: IsNull() || "",
|
|
orgChild3Id: IsNull() || "",
|
|
orgChild4Id: IsNull() || "",
|
|
next_holderId: Not(IsNull()) || Not(""),
|
|
},
|
|
}),
|
|
totalRootPositionNextVacant: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: IsNull() || "",
|
|
orgChild2Id: IsNull() || "",
|
|
orgChild3Id: IsNull() || "",
|
|
orgChild4Id: IsNull() || "",
|
|
next_holderId: IsNull() || "",
|
|
},
|
|
}),
|
|
|
|
children: await Promise.all(
|
|
orgChild1Data
|
|
.filter((orgChild1) => orgChild1.orgRootId === orgRoot.id)
|
|
.map(async (orgChild1) => ({
|
|
orgTreeId: orgChild1.id,
|
|
orgRootId: orgRoot.id,
|
|
orgLevel: 1,
|
|
orgName: `${orgChild1.orgChild1Name}/${orgRoot.orgRootName}`,
|
|
orgTreeName: orgChild1.orgChild1Name,
|
|
orgTreeShortName: orgChild1.orgChild1ShortName,
|
|
orgTreeCode: orgChild1.orgChild1Code,
|
|
orgCode: orgRoot.orgRootCode + orgChild1.orgChild1Code,
|
|
orgTreeRank: orgChild1.orgChild1Rank,
|
|
orgTreeRankSub: orgChild1.orgChild1RankSub,
|
|
DEPARTMENT_CODE: orgChild1.DEPARTMENT_CODE,
|
|
DIVISION_CODE: orgChild1.DIVISION_CODE,
|
|
SECTION_CODE: orgChild1.SECTION_CODE,
|
|
JOB_CODE: orgChild1.JOB_CODE,
|
|
orgTreeOrder: orgChild1.orgChild1Order,
|
|
orgRootCode: orgRoot.orgRootCode,
|
|
orgTreePhoneEx: orgChild1.orgChild1PhoneEx,
|
|
orgTreePhoneIn: orgChild1.orgChild1PhoneIn,
|
|
orgTreeFax: orgChild1.orgChild1Fax,
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootName: orgRoot.orgRootName,
|
|
responsibility: orgChild1.responsibility,
|
|
isOfficer: orgChild1.isOfficer,
|
|
isInformation: orgChild1.isInformation,
|
|
labelName:
|
|
orgChild1.orgChild1Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild1.orgChild1Code +
|
|
" " +
|
|
orgChild1.orgChild1ShortName,
|
|
totalPosition: await this.posMasterRepository.count({
|
|
where: { orgRevisionId: orgRoot.orgRevisionId, orgChild1Id: orgChild1.id },
|
|
}),
|
|
totalPositionCurrentUse: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgChild1Id: orgChild1.id,
|
|
current_holderId: Not(IsNull()) || Not(""),
|
|
},
|
|
}),
|
|
totalPositionCurrentVacant: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgChild1Id: orgChild1.id,
|
|
current_holderId: IsNull() || "",
|
|
},
|
|
}),
|
|
totalPositionNextUse: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgChild1Id: orgChild1.id,
|
|
next_holderId: Not(IsNull()) || Not(""),
|
|
},
|
|
}),
|
|
totalPositionNextVacant: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgChild1Id: orgChild1.id,
|
|
next_holderId: IsNull() || "",
|
|
},
|
|
}),
|
|
totalRootPosition: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: orgChild1.id,
|
|
orgChild2Id: IsNull() || "",
|
|
orgChild3Id: IsNull() || "",
|
|
orgChild4Id: IsNull() || "",
|
|
},
|
|
}),
|
|
totalRootPositionCurrentUse: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: orgChild1.id,
|
|
orgChild2Id: IsNull() || "",
|
|
orgChild3Id: IsNull() || "",
|
|
orgChild4Id: IsNull() || "",
|
|
current_holderId: Not(IsNull()) || Not(""),
|
|
},
|
|
}),
|
|
totalRootPositionCurrentVacant: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: orgChild1.id,
|
|
orgChild2Id: IsNull() || "",
|
|
orgChild3Id: IsNull() || "",
|
|
orgChild4Id: IsNull() || "",
|
|
current_holderId: IsNull() || "",
|
|
},
|
|
}),
|
|
totalRootPositionNextUse: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: orgChild1.id,
|
|
orgChild2Id: IsNull() || "",
|
|
orgChild3Id: IsNull() || "",
|
|
orgChild4Id: IsNull() || "",
|
|
next_holderId: Not(IsNull()) || Not(""),
|
|
},
|
|
}),
|
|
totalRootPositionNextVacant: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: orgChild1.id,
|
|
orgChild2Id: IsNull() || "",
|
|
orgChild3Id: IsNull() || "",
|
|
orgChild4Id: IsNull() || "",
|
|
next_holderId: IsNull() || "",
|
|
},
|
|
}),
|
|
|
|
children: await Promise.all(
|
|
orgChild2Data
|
|
.filter((orgChild2) => orgChild2.orgChild1Id === orgChild1.id)
|
|
.map(async (orgChild2) => ({
|
|
orgTreeId: orgChild2.id,
|
|
orgRootId: orgChild1.id,
|
|
orgLevel: 2,
|
|
orgName: `${orgChild2.orgChild2Name}/${orgChild1.orgChild1Name}/${orgRoot.orgRootName}`,
|
|
orgTreeName: orgChild2.orgChild2Name,
|
|
orgTreeShortName: orgChild2.orgChild2ShortName,
|
|
orgTreeCode: orgChild2.orgChild2Code,
|
|
orgCode: orgRoot.orgRootCode + orgChild2.orgChild2Code,
|
|
orgTreeRank: orgChild2.orgChild2Rank,
|
|
orgTreeRankSub: orgChild2.orgChild2RankSub,
|
|
DEPARTMENT_CODE: orgChild2.DEPARTMENT_CODE,
|
|
DIVISION_CODE: orgChild2.DIVISION_CODE,
|
|
SECTION_CODE: orgChild2.SECTION_CODE,
|
|
JOB_CODE: orgChild2.JOB_CODE,
|
|
orgTreeOrder: orgChild2.orgChild2Order,
|
|
orgRootCode: orgRoot.orgRootCode,
|
|
orgTreePhoneEx: orgChild2.orgChild2PhoneEx,
|
|
orgTreePhoneIn: orgChild2.orgChild2PhoneIn,
|
|
orgTreeFax: orgChild2.orgChild2Fax,
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootName: orgRoot.orgRootName,
|
|
responsibility: orgChild2.responsibility,
|
|
isOfficer: orgChild1.isOfficer,
|
|
labelName:
|
|
orgChild2.orgChild2Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild2.orgChild2Code +
|
|
" " +
|
|
orgChild2.orgChild2ShortName,
|
|
totalPosition: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgChild2Id: orgChild2.id,
|
|
},
|
|
}),
|
|
totalPositionCurrentUse: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgChild2Id: orgChild2.id,
|
|
current_holderId: Not(IsNull()) || Not(""),
|
|
},
|
|
}),
|
|
totalPositionCurrentVacant: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgChild2Id: orgChild2.id,
|
|
current_holderId: IsNull() || "",
|
|
},
|
|
}),
|
|
totalPositionNextUse: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgChild2Id: orgChild2.id,
|
|
next_holderId: Not(IsNull()) || Not(""),
|
|
},
|
|
}),
|
|
totalPositionNextVacant: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgChild2Id: orgChild2.id,
|
|
next_holderId: IsNull() || "",
|
|
},
|
|
}),
|
|
totalRootPosition: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: orgChild1.id,
|
|
orgChild2Id: orgChild2.id,
|
|
orgChild3Id: IsNull() || "",
|
|
orgChild4Id: IsNull() || "",
|
|
},
|
|
}),
|
|
totalRootPositionCurrentUse: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: orgChild1.id,
|
|
orgChild2Id: orgChild2.id,
|
|
orgChild3Id: IsNull() || "",
|
|
orgChild4Id: IsNull() || "",
|
|
current_holderId: Not(IsNull()) || Not(""),
|
|
},
|
|
}),
|
|
totalRootPositionCurrentVacant: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: orgChild1.id,
|
|
orgChild2Id: orgChild2.id,
|
|
orgChild3Id: IsNull() || "",
|
|
orgChild4Id: IsNull() || "",
|
|
current_holderId: IsNull() || "",
|
|
},
|
|
}),
|
|
totalRootPositionNextUse: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: orgChild1.id,
|
|
orgChild2Id: orgChild2.id,
|
|
orgChild3Id: IsNull() || "",
|
|
orgChild4Id: IsNull() || "",
|
|
next_holderId: Not(IsNull()) || Not(""),
|
|
},
|
|
}),
|
|
totalRootPositionNextVacant: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: orgChild1.id,
|
|
orgChild2Id: orgChild2.id,
|
|
orgChild3Id: IsNull() || "",
|
|
orgChild4Id: IsNull() || "",
|
|
next_holderId: IsNull() || "",
|
|
},
|
|
}),
|
|
|
|
children: await Promise.all(
|
|
orgChild3Data
|
|
.filter((orgChild3) => orgChild3.orgChild2Id === orgChild2.id)
|
|
.map(async (orgChild3) => ({
|
|
orgTreeId: orgChild3.id,
|
|
orgRootId: orgChild2.id,
|
|
orgLevel: 3,
|
|
orgName: `${orgChild3.orgChild3Name}/${orgChild2.orgChild2Name}/${orgChild1.orgChild1Name}/${orgRoot.orgRootName}`,
|
|
orgTreeName: orgChild3.orgChild3Name,
|
|
orgTreeShortName: orgChild3.orgChild3ShortName,
|
|
orgTreeCode: orgChild3.orgChild3Code,
|
|
orgCode: orgRoot.orgRootCode + orgChild3.orgChild3Code,
|
|
orgTreeRank: orgChild3.orgChild3Rank,
|
|
orgTreeRankSub: orgChild3.orgChild3RankSub,
|
|
DEPARTMENT_CODE: orgChild3.DEPARTMENT_CODE,
|
|
DIVISION_CODE: orgChild3.DIVISION_CODE,
|
|
SECTION_CODE: orgChild3.SECTION_CODE,
|
|
JOB_CODE: orgChild3.JOB_CODE,
|
|
orgTreeOrder: orgChild3.orgChild3Order,
|
|
orgRootCode: orgRoot.orgRootCode,
|
|
orgTreePhoneEx: orgChild3.orgChild3PhoneEx,
|
|
orgTreePhoneIn: orgChild3.orgChild3PhoneIn,
|
|
orgTreeFax: orgChild3.orgChild3Fax,
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootName: orgRoot.orgRootName,
|
|
responsibility: orgChild3.responsibility,
|
|
isOfficer: orgChild1.isOfficer,
|
|
labelName:
|
|
orgChild3.orgChild3Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild3.orgChild3Code +
|
|
" " +
|
|
orgChild3.orgChild3ShortName,
|
|
totalPosition: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgChild3Id: orgChild3.id,
|
|
},
|
|
}),
|
|
totalPositionCurrentUse: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgChild3Id: orgChild3.id,
|
|
current_holderId: Not(IsNull()) || Not(""),
|
|
},
|
|
}),
|
|
totalPositionCurrentVacant: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgChild3Id: orgChild3.id,
|
|
current_holderId: IsNull() || "",
|
|
},
|
|
}),
|
|
totalPositionNextUse: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgChild3Id: orgChild3.id,
|
|
next_holderId: Not(IsNull()) || Not(""),
|
|
},
|
|
}),
|
|
totalPositionNextVacant: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgChild3Id: orgChild3.id,
|
|
next_holderId: IsNull() || "",
|
|
},
|
|
}),
|
|
totalRootPosition: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: orgChild1.id,
|
|
orgChild2Id: orgChild2.id,
|
|
orgChild3Id: orgChild3.id,
|
|
orgChild4Id: IsNull() || "",
|
|
},
|
|
}),
|
|
totalRootPositionCurrentUse: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: orgChild1.id,
|
|
orgChild2Id: orgChild2.id,
|
|
orgChild3Id: orgChild3.id,
|
|
orgChild4Id: IsNull() || "",
|
|
current_holderId: Not(IsNull()) || Not(""),
|
|
},
|
|
}),
|
|
totalRootPositionCurrentVacant: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: orgChild1.id,
|
|
orgChild2Id: orgChild2.id,
|
|
orgChild3Id: orgChild3.id,
|
|
orgChild4Id: IsNull() || "",
|
|
current_holderId: IsNull() || "",
|
|
},
|
|
}),
|
|
totalRootPositionNextUse: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: orgChild1.id,
|
|
orgChild2Id: orgChild2.id,
|
|
orgChild3Id: orgChild3.id,
|
|
orgChild4Id: IsNull() || "",
|
|
next_holderId: Not(IsNull()) || Not(""),
|
|
},
|
|
}),
|
|
totalRootPositionNextVacant: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: orgChild1.id,
|
|
orgChild2Id: orgChild2.id,
|
|
orgChild3Id: orgChild3.id,
|
|
orgChild4Id: IsNull() || "",
|
|
next_holderId: IsNull() || "",
|
|
},
|
|
}),
|
|
|
|
children: await Promise.all(
|
|
orgChild4Data
|
|
.filter((orgChild4) => orgChild4.orgChild3Id === orgChild3.id)
|
|
.map(async (orgChild4) => ({
|
|
orgTreeId: orgChild4.id,
|
|
orgRootId: orgChild3.id,
|
|
orgLevel: 4,
|
|
orgName: `${orgChild4.orgChild4Name}/${orgChild3.orgChild3Name}/${orgChild2.orgChild2Name}/${orgChild1.orgChild1Name}/${orgRoot.orgRootName}`,
|
|
orgTreeName: orgChild4.orgChild4Name,
|
|
orgTreeShortName: orgChild4.orgChild4ShortName,
|
|
orgTreeCode: orgChild4.orgChild4Code,
|
|
orgCode: orgRoot.orgRootCode + orgChild4.orgChild4Code,
|
|
orgTreeRank: orgChild4.orgChild4Rank,
|
|
orgTreeRankSub: orgChild4.orgChild4RankSub,
|
|
DEPARTMENT_CODE: orgChild4.DEPARTMENT_CODE,
|
|
DIVISION_CODE: orgChild4.DIVISION_CODE,
|
|
SECTION_CODE: orgChild4.SECTION_CODE,
|
|
JOB_CODE: orgChild4.JOB_CODE,
|
|
orgTreeOrder: orgChild4.orgChild4Order,
|
|
orgRootCode: orgRoot.orgRootCode,
|
|
orgTreePhoneEx: orgChild4.orgChild4PhoneEx,
|
|
orgTreePhoneIn: orgChild4.orgChild4PhoneIn,
|
|
orgTreeFax: orgChild4.orgChild4Fax,
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootName: orgRoot.orgRootName,
|
|
responsibility: orgChild4.responsibility,
|
|
isOfficer: orgChild1.isOfficer,
|
|
labelName:
|
|
orgChild4.orgChild4Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild4.orgChild4Code +
|
|
" " +
|
|
orgChild4.orgChild4ShortName,
|
|
totalPosition: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgChild4Id: orgChild4.id,
|
|
},
|
|
}),
|
|
totalPositionCurrentUse: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgChild4Id: orgChild4.id,
|
|
current_holderId: Not(IsNull()) || Not(""),
|
|
},
|
|
}),
|
|
totalPositionCurrentVacant: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgChild4Id: orgChild4.id,
|
|
current_holderId: IsNull() || "",
|
|
},
|
|
}),
|
|
totalPositionNextUse: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgChild4Id: orgChild4.id,
|
|
next_holderId: Not(IsNull()) || Not(""),
|
|
},
|
|
}),
|
|
totalPositionNextVacant: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgChild4Id: orgChild4.id,
|
|
next_holderId: IsNull() || "",
|
|
},
|
|
}),
|
|
totalRootPosition: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: orgChild1.id,
|
|
orgChild2Id: orgChild2.id,
|
|
orgChild3Id: orgChild3.id,
|
|
orgChild4Id: orgChild4.id,
|
|
},
|
|
}),
|
|
totalRootPositionCurrentUse: await this.posMasterRepository.count(
|
|
{
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: orgChild1.id,
|
|
orgChild2Id: orgChild2.id,
|
|
orgChild3Id: orgChild3.id,
|
|
orgChild4Id: orgChild4.id,
|
|
current_holderId: Not(IsNull()) || Not(""),
|
|
},
|
|
},
|
|
),
|
|
totalRootPositionCurrentVacant:
|
|
await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: orgChild1.id,
|
|
orgChild2Id: orgChild2.id,
|
|
orgChild3Id: orgChild3.id,
|
|
orgChild4Id: orgChild4.id,
|
|
current_holderId: IsNull() || "",
|
|
},
|
|
}),
|
|
totalRootPositionNextUse: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: orgChild1.id,
|
|
orgChild2Id: orgChild2.id,
|
|
orgChild3Id: orgChild3.id,
|
|
orgChild4Id: orgChild4.id,
|
|
next_holderId: Not(IsNull()) || Not(""),
|
|
},
|
|
}),
|
|
totalRootPositionNextVacant: await this.posMasterRepository.count(
|
|
{
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: orgChild1.id,
|
|
orgChild2Id: orgChild2.id,
|
|
orgChild3Id: orgChild3.id,
|
|
orgChild4Id: orgChild4.id,
|
|
next_holderId: IsNull() || "",
|
|
},
|
|
},
|
|
),
|
|
})),
|
|
),
|
|
})),
|
|
),
|
|
})),
|
|
),
|
|
})),
|
|
),
|
|
};
|
|
}),
|
|
);
|
|
|
|
return new HttpSuccess(formattedData);
|
|
}
|
|
|
|
/**
|
|
* API รายละเอียดโครงสร้าง
|
|
*
|
|
* @summary ORG_023 - รายละเอียดโครงสร้าง (ADMIN) #25
|
|
*
|
|
*/
|
|
@Get("super-admin/{id}")
|
|
async detailSuperAdmin(@Path() id: string, @Request() request: RequestWithUser) {
|
|
const orgRevision = await this.orgRevisionRepository.findOne({
|
|
where: { id: id },
|
|
});
|
|
if (!orgRevision) return new HttpSuccess([]);
|
|
|
|
let rootId: any = null;
|
|
if (!request.user.role.includes("SUPER_ADMIN")) {
|
|
const profile = await this.profileRepo.findOne({
|
|
where: {
|
|
keycloak: request.user.sub,
|
|
},
|
|
select: ["id"],
|
|
});
|
|
if (profile == null) return new HttpSuccess([]);
|
|
|
|
const posMaster = await this.posMasterRepository.findOne({
|
|
where:
|
|
orgRevision.orgRevisionIsCurrent && !orgRevision.orgRevisionIsDraft
|
|
? {
|
|
orgRevisionId: id,
|
|
current_holderId: profile.id,
|
|
}
|
|
: {
|
|
orgRevisionId: id,
|
|
next_holderId: profile.id,
|
|
},
|
|
});
|
|
if (!posMaster) return new HttpSuccess([]);
|
|
|
|
rootId = posMaster.orgRootId;
|
|
}
|
|
|
|
// OPTIMIZED: Check cache first
|
|
const cachedResponse = await orgStructureCache.get(id, rootId);
|
|
if (cachedResponse) {
|
|
return new HttpSuccess(cachedResponse);
|
|
}
|
|
|
|
// OPTIMIZED: Get all position counts in ONE query (closed)
|
|
// const { orgRootMap, orgChild1Map, orgChild2Map, orgChild3Map, orgChild4Map, rootPosMap } =
|
|
// await getPositionCounts(id);
|
|
|
|
// OPTIMIZED: Fetch orgRoot first, then fetch all child levels in parallel
|
|
const orgRootData = await AppDataSource.getRepository(OrgRoot)
|
|
.createQueryBuilder("orgRoot")
|
|
.where("orgRoot.orgRevisionId = :id", { id })
|
|
.andWhere(rootId != null ? `orgRoot.id = :rootId` : "1=1", {
|
|
rootId: rootId,
|
|
})
|
|
.orderBy("orgRoot.orgRootOrder", "ASC")
|
|
.getMany();
|
|
|
|
const orgRootIds = orgRootData.map((orgRoot) => orgRoot.id);
|
|
|
|
// OPTIMIZED: Fetch all child levels in parallel using orgRevisionId
|
|
// This is faster than sequential queries that depend on parent IDs
|
|
const [orgChild1AllData, orgChild2AllData, orgChild3AllData, orgChild4AllData] =
|
|
await Promise.all([
|
|
AppDataSource.getRepository(OrgChild1)
|
|
.createQueryBuilder("orgChild1")
|
|
.where("orgChild1.orgRevisionId = :id", { id })
|
|
.orderBy("orgChild1.orgChild1Order", "ASC")
|
|
.getMany(),
|
|
|
|
AppDataSource.getRepository(OrgChild2)
|
|
.createQueryBuilder("orgChild2")
|
|
.where("orgChild2.orgRevisionId = :id", { id })
|
|
.orderBy("orgChild2.orgChild2Order", "ASC")
|
|
.getMany(),
|
|
|
|
AppDataSource.getRepository(OrgChild3)
|
|
.createQueryBuilder("orgChild3")
|
|
.where("orgChild3.orgRevisionId = :id", { id })
|
|
.orderBy("orgChild3.orgChild3Order", "ASC")
|
|
.getMany(),
|
|
|
|
AppDataSource.getRepository(OrgChild4)
|
|
.createQueryBuilder("orgChild4")
|
|
.where("orgChild4.orgRevisionId = :id", { id })
|
|
.orderBy("orgChild4.orgChild4Order", "ASC")
|
|
.getMany(),
|
|
]);
|
|
|
|
// Filter child1 data by orgRootIds (maintains backward compatibility)
|
|
const orgChild1Data =
|
|
orgRootIds && orgRootIds.length > 0
|
|
? orgChild1AllData.filter((orgChild1) => orgRootIds.includes(orgChild1.orgRootId))
|
|
: [];
|
|
|
|
// Build maps for efficient filtering of deeper levels
|
|
const orgChild1Ids = orgChild1Data.map((orgChild1) => orgChild1.id);
|
|
const orgChild2Data =
|
|
orgChild1Ids && orgChild1Ids.length > 0
|
|
? orgChild2AllData.filter((orgChild2) => orgChild1Ids.includes(orgChild2.orgChild1Id))
|
|
: [];
|
|
|
|
const orgChild2Ids = orgChild2Data.map((orgChild2) => orgChild2.id);
|
|
const orgChild3Data =
|
|
orgChild2Ids && orgChild2Ids.length > 0
|
|
? orgChild3AllData.filter((orgChild3) => orgChild2Ids.includes(orgChild3.orgChild2Id))
|
|
: [];
|
|
|
|
const orgChild3Ids = orgChild3Data.map((orgChild3) => orgChild3.id);
|
|
const orgChild4Data =
|
|
orgChild3Ids && orgChild3Ids.length > 0
|
|
? orgChild4AllData.filter((orgChild4) => orgChild3Ids.includes(orgChild4.orgChild3Id))
|
|
: [];
|
|
|
|
// OPTIMIZED: Build formatted data using pre-calculated counts (no nested queries!)
|
|
const formattedData = orgRootData.map((orgRoot) => {
|
|
// const rootCounts = getCounts(orgRootMap, orgRoot.id);
|
|
// const rootPosCounts = getRootCounts(rootPosMap, orgRoot.id);
|
|
|
|
return {
|
|
orgTreeId: orgRoot.id,
|
|
orgLevel: 0,
|
|
orgName: orgRoot.orgRootName,
|
|
orgTreeName: orgRoot.orgRootName,
|
|
orgTreeShortName: orgRoot.orgRootShortName,
|
|
orgTreeCode: orgRoot.orgRootCode,
|
|
orgCode: orgRoot.orgRootCode + "00",
|
|
orgTreeRank: orgRoot.orgRootRank,
|
|
orgTreeRankSub: orgRoot.orgRootRankSub,
|
|
orgRootDnaId: orgRoot.ancestorDNA,
|
|
DEPARTMENT_CODE: orgRoot.DEPARTMENT_CODE,
|
|
DIVISION_CODE: orgRoot.DIVISION_CODE,
|
|
SECTION_CODE: orgRoot.SECTION_CODE,
|
|
JOB_CODE: orgRoot.JOB_CODE,
|
|
orgTreeOrder: orgRoot.orgRootOrder,
|
|
orgTreePhoneEx: orgRoot.orgRootPhoneEx,
|
|
orgTreePhoneIn: orgRoot.orgRootPhoneIn,
|
|
orgTreeFax: orgRoot.orgRootFax,
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootName: orgRoot.orgRootName,
|
|
isDeputy: orgRoot.isDeputy,
|
|
isCommission: orgRoot.isCommission,
|
|
responsibility: orgRoot.responsibility,
|
|
labelName:
|
|
orgRoot.orgRootName + " " + orgRoot.orgRootCode + "00" + " " + orgRoot.orgRootShortName,
|
|
// totalPosition: rootCounts.totalPosition,
|
|
// totalPositionCurrentUse: rootCounts.totalPositionCurrentUse,
|
|
// totalPositionCurrentVacant: rootCounts.totalPositionCurrentVacant,
|
|
// totalPositionNextUse: rootCounts.totalPositionNextUse,
|
|
// totalPositionNextVacant: rootCounts.totalPositionNextVacant,
|
|
// totalRootPosition: rootPosCounts.totalRootPosition,
|
|
// totalRootPositionCurrentUse: rootPosCounts.totalRootPositionCurrentUse,
|
|
// totalRootPositionCurrentVacant: rootPosCounts.totalRootPositionCurrentVacant,
|
|
// totalRootPositionNextUse: rootPosCounts.totalRootPositionNextUse,
|
|
// totalRootPositionNextVacant: rootPosCounts.totalRootPositionNextVacant,
|
|
children: orgChild1Data
|
|
.filter((orgChild1) => orgChild1.orgRootId === orgRoot.id)
|
|
.map((orgChild1) => {
|
|
// const child1Counts = getCounts(orgChild1Map, orgChild1.id);
|
|
// const child1PosKey = `${orgRoot.id}-${orgChild1.id}`;
|
|
// const child1PosCounts = getRootCounts(rootPosMap, child1PosKey);
|
|
|
|
return {
|
|
orgTreeId: orgChild1.id,
|
|
orgRootId: orgRoot.id,
|
|
orgLevel: 1,
|
|
orgName: `${orgChild1.orgChild1Name}/${orgRoot.orgRootName}`,
|
|
orgTreeName: orgChild1.orgChild1Name,
|
|
orgTreeShortName: orgChild1.orgChild1ShortName,
|
|
orgTreeCode: orgChild1.orgChild1Code,
|
|
orgCode: orgRoot.orgRootCode + orgChild1.orgChild1Code,
|
|
orgTreeRank: orgChild1.orgChild1Rank,
|
|
orgTreeRankSub: orgChild1.orgChild1RankSub,
|
|
orgRootDnaId: orgRoot.ancestorDNA,
|
|
orgChild1DnaId: orgChild1.ancestorDNA,
|
|
DEPARTMENT_CODE: orgChild1.DEPARTMENT_CODE,
|
|
DIVISION_CODE: orgChild1.DIVISION_CODE,
|
|
SECTION_CODE: orgChild1.SECTION_CODE,
|
|
JOB_CODE: orgChild1.JOB_CODE,
|
|
orgTreeOrder: orgChild1.orgChild1Order,
|
|
orgRootCode: orgRoot.orgRootCode,
|
|
orgTreePhoneEx: orgChild1.orgChild1PhoneEx,
|
|
orgTreePhoneIn: orgChild1.orgChild1PhoneIn,
|
|
orgTreeFax: orgChild1.orgChild1Fax,
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootName: orgRoot.orgRootName,
|
|
responsibility: orgChild1.responsibility,
|
|
isOfficer: orgChild1.isOfficer,
|
|
isInformation: orgChild1.isInformation,
|
|
labelName:
|
|
orgChild1.orgChild1Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild1.orgChild1Code +
|
|
" " +
|
|
orgChild1.orgChild1ShortName,
|
|
// totalPosition: child1Counts.totalPosition,
|
|
// totalPositionCurrentUse: child1Counts.totalPositionCurrentUse,
|
|
// totalPositionCurrentVacant: child1Counts.totalPositionCurrentVacant,
|
|
// totalPositionNextUse: child1Counts.totalPositionNextUse,
|
|
// totalPositionNextVacant: child1Counts.totalPositionNextVacant,
|
|
// totalRootPosition: child1PosCounts.totalRootPosition,
|
|
// totalRootPositionCurrentUse: child1PosCounts.totalRootPositionCurrentUse,
|
|
// totalRootPositionCurrentVacant: child1PosCounts.totalRootPositionCurrentVacant,
|
|
// totalRootPositionNextUse: child1PosCounts.totalRootPositionNextUse,
|
|
// totalRootPositionNextVacant: child1PosCounts.totalRootPositionNextVacant,
|
|
children: orgChild2Data
|
|
.filter((orgChild2) => orgChild2.orgChild1Id === orgChild1.id)
|
|
.map((orgChild2) => {
|
|
// const child2Counts = getCounts(orgChild2Map, orgChild2.id);
|
|
// const child2PosKey = `${orgRoot.id}-${orgChild1.id}-${orgChild2.id}`;
|
|
// const child2PosCounts = getRootCounts(rootPosMap, child2PosKey);
|
|
|
|
return {
|
|
orgTreeId: orgChild2.id,
|
|
orgRootId: orgChild1.id,
|
|
orgLevel: 2,
|
|
orgName: `${orgChild2.orgChild2Name}/${orgChild1.orgChild1Name}/${orgRoot.orgRootName}`,
|
|
orgTreeName: orgChild2.orgChild2Name,
|
|
orgTreeShortName: orgChild2.orgChild2ShortName,
|
|
orgTreeCode: orgChild2.orgChild2Code,
|
|
orgCode: orgRoot.orgRootCode + orgChild2.orgChild2Code,
|
|
orgTreeRank: orgChild2.orgChild2Rank,
|
|
orgTreeRankSub: orgChild2.orgChild2RankSub,
|
|
orgRootDnaId: orgRoot.ancestorDNA,
|
|
orgChild1DnaId: orgChild1.ancestorDNA,
|
|
orgChild2DnaId: orgChild2.ancestorDNA,
|
|
DEPARTMENT_CODE: orgChild2.DEPARTMENT_CODE,
|
|
DIVISION_CODE: orgChild2.DIVISION_CODE,
|
|
SECTION_CODE: orgChild2.SECTION_CODE,
|
|
JOB_CODE: orgChild2.JOB_CODE,
|
|
orgTreeOrder: orgChild2.orgChild2Order,
|
|
orgRootCode: orgRoot.orgRootCode,
|
|
orgTreePhoneEx: orgChild2.orgChild2PhoneEx,
|
|
orgTreePhoneIn: orgChild2.orgChild2PhoneIn,
|
|
orgTreeFax: orgChild2.orgChild2Fax,
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootName: orgRoot.orgRootName,
|
|
responsibility: orgChild2.responsibility,
|
|
labelName:
|
|
orgChild2.orgChild2Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild2.orgChild2Code +
|
|
" " +
|
|
orgChild2.orgChild2ShortName,
|
|
// totalPosition: child2Counts.totalPosition,
|
|
// totalPositionCurrentUse: child2Counts.totalPositionCurrentUse,
|
|
// totalPositionCurrentVacant: child2Counts.totalPositionCurrentVacant,
|
|
// totalPositionNextUse: child2Counts.totalPositionNextUse,
|
|
// totalPositionNextVacant: child2Counts.totalPositionNextVacant,
|
|
// totalRootPosition: child2PosCounts.totalRootPosition,
|
|
// totalRootPositionCurrentUse: child2PosCounts.totalRootPositionCurrentUse,
|
|
// totalRootPositionCurrentVacant: child2PosCounts.totalRootPositionCurrentVacant,
|
|
// totalRootPositionNextUse: child2PosCounts.totalRootPositionNextUse,
|
|
// totalRootPositionNextVacant: child2PosCounts.totalRootPositionNextVacant,
|
|
children: orgChild3Data
|
|
.filter((orgChild3) => orgChild3.orgChild2Id === orgChild2.id)
|
|
.map((orgChild3) => {
|
|
// const child3Counts = getCounts(orgChild3Map, orgChild3.id);
|
|
// const child3PosKey = `${orgRoot.id}-${orgChild1.id}-${orgChild2.id}-${orgChild3.id}`;
|
|
// const child3PosCounts = getRootCounts(rootPosMap, child3PosKey);
|
|
|
|
return {
|
|
orgTreeId: orgChild3.id,
|
|
orgRootId: orgChild2.id,
|
|
orgLevel: 3,
|
|
orgName: `${orgChild3.orgChild3Name}/${orgChild2.orgChild2Name}/${orgChild1.orgChild1Name}/${orgRoot.orgRootName}`,
|
|
orgTreeName: orgChild3.orgChild3Name,
|
|
orgTreeShortName: orgChild3.orgChild3ShortName,
|
|
orgTreeCode: orgChild3.orgChild3Code,
|
|
orgCode: orgRoot.orgRootCode + orgChild3.orgChild3Code,
|
|
orgTreeRank: orgChild3.orgChild3Rank,
|
|
orgTreeRankSub: orgChild3.orgChild3RankSub,
|
|
orgRootDnaId: orgRoot.ancestorDNA,
|
|
orgChild1DnaId: orgChild1.ancestorDNA,
|
|
orgChild2DnaId: orgChild2.ancestorDNA,
|
|
orgChild3DnaId: orgChild3.ancestorDNA,
|
|
DEPARTMENT_CODE: orgChild3.DEPARTMENT_CODE,
|
|
DIVISION_CODE: orgChild3.DIVISION_CODE,
|
|
SECTION_CODE: orgChild3.SECTION_CODE,
|
|
JOB_CODE: orgChild3.JOB_CODE,
|
|
orgTreeOrder: orgChild3.orgChild3Order,
|
|
orgRootCode: orgRoot.orgRootCode,
|
|
orgTreePhoneEx: orgChild3.orgChild3PhoneEx,
|
|
orgTreePhoneIn: orgChild3.orgChild3PhoneIn,
|
|
orgTreeFax: orgChild3.orgChild3Fax,
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootName: orgRoot.orgRootName,
|
|
responsibility: orgChild3.responsibility,
|
|
labelName:
|
|
orgChild3.orgChild3Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild3.orgChild3Code +
|
|
" " +
|
|
orgChild3.orgChild3ShortName,
|
|
// totalPosition: child3Counts.totalPosition,
|
|
// totalPositionCurrentUse: child3Counts.totalPositionCurrentUse,
|
|
// totalPositionCurrentVacant: child3Counts.totalPositionCurrentVacant,
|
|
// totalPositionNextUse: child3Counts.totalPositionNextUse,
|
|
// totalPositionNextVacant: child3Counts.totalPositionNextVacant,
|
|
// totalRootPosition: child3PosCounts.totalRootPosition,
|
|
// totalRootPositionCurrentUse: child3PosCounts.totalRootPositionCurrentUse,
|
|
// totalRootPositionCurrentVacant:
|
|
// child3PosCounts.totalRootPositionCurrentVacant,
|
|
// totalRootPositionNextUse: child3PosCounts.totalRootPositionNextUse,
|
|
// totalRootPositionNextVacant: child3PosCounts.totalRootPositionNextVacant,
|
|
children: orgChild4Data
|
|
.filter((orgChild4) => orgChild4.orgChild3Id === orgChild3.id)
|
|
.map((orgChild4) => {
|
|
// const child4Counts = getCounts(orgChild4Map, orgChild4.id);
|
|
// const child4PosKey = `${orgRoot.id}-${orgChild1.id}-${orgChild2.id}-${orgChild3.id}-${orgChild4.id}`;
|
|
// const child4PosCounts = getRootCounts(rootPosMap, child4PosKey);
|
|
|
|
return {
|
|
orgTreeId: orgChild4.id,
|
|
orgRootId: orgChild3.id,
|
|
orgLevel: 4,
|
|
orgName: `${orgChild4.orgChild4Name}/${orgChild3.orgChild3Name}/${orgChild2.orgChild2Name}/${orgChild1.orgChild1Name}/${orgRoot.orgRootName}`,
|
|
orgTreeName: orgChild4.orgChild4Name,
|
|
orgTreeShortName: orgChild4.orgChild4ShortName,
|
|
orgTreeCode: orgChild4.orgChild4Code,
|
|
orgCode: orgRoot.orgRootCode + orgChild4.orgChild4Code,
|
|
orgTreeRank: orgChild4.orgChild4Rank,
|
|
orgTreeRankSub: orgChild4.orgChild4RankSub,
|
|
orgRootDnaId: orgRoot.ancestorDNA,
|
|
orgChild1DnaId: orgChild1.ancestorDNA,
|
|
orgChild2DnaId: orgChild2.ancestorDNA,
|
|
orgChild3DnaId: orgChild3.ancestorDNA,
|
|
orgChild4DnaId: orgChild4.ancestorDNA,
|
|
DEPARTMENT_CODE: orgChild4.DEPARTMENT_CODE,
|
|
DIVISION_CODE: orgChild4.DIVISION_CODE,
|
|
SECTION_CODE: orgChild4.SECTION_CODE,
|
|
JOB_CODE: orgChild4.JOB_CODE,
|
|
orgTreeOrder: orgChild4.orgChild4Order,
|
|
orgRootCode: orgRoot.orgRootCode,
|
|
orgTreePhoneEx: orgChild4.orgChild4PhoneEx,
|
|
orgTreePhoneIn: orgChild4.orgChild4PhoneIn,
|
|
orgTreeFax: orgChild4.orgChild4Fax,
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootName: orgRoot.orgRootName,
|
|
responsibility: orgChild4.responsibility,
|
|
labelName:
|
|
orgChild4.orgChild4Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild4.orgChild4Code +
|
|
" " +
|
|
orgChild4.orgChild4ShortName,
|
|
// totalPosition: child4Counts.totalPosition,
|
|
// totalPositionCurrentUse: child4Counts.totalPositionCurrentUse,
|
|
// totalPositionCurrentVacant: child4Counts.totalPositionCurrentVacant,
|
|
// totalPositionNextUse: child4Counts.totalPositionNextUse,
|
|
// totalPositionNextVacant: child4Counts.totalPositionNextVacant,
|
|
// totalRootPosition: child4PosCounts.totalRootPosition,
|
|
// totalRootPositionCurrentUse:
|
|
// child4PosCounts.totalRootPositionCurrentUse,
|
|
// totalRootPositionCurrentVacant:
|
|
// child4PosCounts.totalRootPositionCurrentVacant,
|
|
// totalRootPositionNextUse: child4PosCounts.totalRootPositionNextUse,
|
|
// totalRootPositionNextVacant:
|
|
// child4PosCounts.totalRootPositionNextVacant,
|
|
children: [],
|
|
};
|
|
}),
|
|
};
|
|
}),
|
|
};
|
|
}),
|
|
};
|
|
}),
|
|
};
|
|
});
|
|
|
|
// OPTIMIZED: Cache the result
|
|
await orgStructureCache.set(id, rootId, formattedData);
|
|
|
|
return new HttpSuccess(formattedData);
|
|
}
|
|
|
|
/**
|
|
* API รายละเอียดโครงสร้าง
|
|
*
|
|
* @summary ORG_023 - รายละเอียดโครงสร้าง (ADMIN) #25
|
|
*
|
|
*/
|
|
@Get("{id}")
|
|
async detail(@Path() id: string, @Request() request: RequestWithUser) {
|
|
let _data: any = {
|
|
root: null,
|
|
child1: null,
|
|
child2: null,
|
|
child3: null,
|
|
child4: null,
|
|
};
|
|
let _data1: any = {
|
|
root: null,
|
|
};
|
|
|
|
const orgRevision = await this.orgRevisionRepository.findOne({ where: { id } });
|
|
|
|
if (!orgRevision) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูล");
|
|
}
|
|
let _privilege = await new permission().PermissionOrgList(request, "SYS_ORG");
|
|
|
|
const attrOwnership = _privilege.root === null ? true : false;
|
|
|
|
const profile = await this.profileRepo.findOne({
|
|
where: { keycloak: request.user.sub },
|
|
relations: ["permissionProfiles", "current_holders", "current_holders.posMasterAssigns"],
|
|
});
|
|
if (!profile) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผู้ใช้งานในทะเบียนประวัติ");
|
|
}
|
|
let profileAssign = profile.current_holders
|
|
?.find((x) => x.orgRevisionId === id)
|
|
?.posMasterAssigns.find((x) => x.assignId === "SYS_ORG");
|
|
|
|
if (orgRevision.orgRevisionIsDraft && !orgRevision.orgRevisionIsCurrent && !attrOwnership) {
|
|
if (Array.isArray(profile.permissionProfiles) && profile.permissionProfiles.length > 0) {
|
|
_data.root = profile.permissionProfiles.map((x) => x.orgRootId);
|
|
} else {
|
|
return new HttpSuccess({ remark: "", data: [] });
|
|
}
|
|
}
|
|
// กำหนดการเข้าถึงข้อมูลตามสถานะและสิทธิ์
|
|
const isCurrentActive = !orgRevision.orgRevisionIsDraft && orgRevision.orgRevisionIsCurrent;
|
|
if (isCurrentActive) {
|
|
if (profileAssign && _privilege.privilege !== "OWNER" && _privilege.privilege !== "PARENT") {
|
|
if (_privilege.privilege == "NORMAL") {
|
|
const holder = profile.current_holders.find((x) => x.orgRevisionId === id);
|
|
if (!holder) return;
|
|
_data.root = [holder.orgRootId];
|
|
_data.child1 = [holder.orgChild1Id];
|
|
_data.child2 = [holder.orgChild2Id];
|
|
_data.child3 = [holder.orgChild3Id];
|
|
_data.child4 = [holder.orgChild4Id];
|
|
} else if (_privilege.privilege == "CHILD" || _privilege.privilege == "BROTHER") {
|
|
const holder = profile.current_holders.find((x) => x.orgRevisionId === id);
|
|
if (!holder) return;
|
|
_data.root = [holder.orgRootId];
|
|
if (_privilege.root && _privilege.child1 === null) {
|
|
} else if (_privilege.child1 && _privilege.child2 === null) {
|
|
_data.child1 = [holder.orgChild1Id];
|
|
} else if (_privilege.child2 && _privilege.child3 === null) {
|
|
_data.child1 = [holder.orgChild1Id];
|
|
_data.child2 = [holder.orgChild2Id];
|
|
} else if (_privilege.child3 && _privilege.child4 === null) {
|
|
_data.child1 = [holder.orgChild1Id];
|
|
_data.child2 = [holder.orgChild2Id];
|
|
_data.child3 = [holder.orgChild3Id];
|
|
_data.child4 = [holder.orgChild4Id];
|
|
}
|
|
} else {
|
|
_data.root = [profile.current_holders.find((x) => x.orgRevisionId === id)?.orgRootId];
|
|
}
|
|
} else {
|
|
if (!attrOwnership) _data = _privilege;
|
|
}
|
|
}
|
|
|
|
const _revision = await this.orgRevisionRepository.findOne({
|
|
where: { id: id },
|
|
});
|
|
if (!_revision) throw new HttpError(HttpStatusCode.NOT_FOUND, "not found.");
|
|
|
|
const orgRootData = await AppDataSource.getRepository(OrgRoot)
|
|
.createQueryBuilder("orgRoot")
|
|
.where("orgRoot.orgRevisionId = :id", { id })
|
|
.andWhere(
|
|
_data.root !== undefined && _data.root !== null
|
|
? _data.root[0] !== null
|
|
? `orgRoot.id IN (:...node)`
|
|
: `orgRoot.id is null`
|
|
: "1=1",
|
|
{
|
|
node: _data.root,
|
|
},
|
|
)
|
|
.select([
|
|
"orgRoot.ancestorDNA",
|
|
"orgRoot.id",
|
|
"orgRoot.misId",
|
|
"orgRoot.isDeputy",
|
|
"orgRoot.isCommission",
|
|
"orgRoot.orgRootName",
|
|
"orgRoot.orgRootShortName",
|
|
"orgRoot.orgRootCode",
|
|
"orgRoot.orgRootOrder",
|
|
"orgRoot.orgRootPhoneEx",
|
|
"orgRoot.orgRootPhoneIn",
|
|
"orgRoot.orgRootFax",
|
|
"orgRoot.orgRevisionId",
|
|
"orgRoot.orgRootRank",
|
|
"orgRoot.orgRootRankSub",
|
|
"orgRoot.DEPARTMENT_CODE",
|
|
"orgRoot.DIVISION_CODE",
|
|
"orgRoot.SECTION_CODE",
|
|
"orgRoot.JOB_CODE",
|
|
"orgRoot.responsibility",
|
|
])
|
|
.orderBy("orgRoot.orgRootOrder", "ASC")
|
|
.getMany();
|
|
const orgRootIds = orgRootData.map((orgRoot) => orgRoot.id) || null;
|
|
const orgChild1Data =
|
|
orgRootIds && orgRootIds.length > 0
|
|
? await AppDataSource.getRepository(OrgChild1)
|
|
.createQueryBuilder("orgChild1")
|
|
.where("orgChild1.orgRootId IN (:...ids)", { ids: orgRootIds })
|
|
.andWhere(
|
|
_data.child1 !== undefined && _data.child1 !== null
|
|
? _data.child1[0] !== null
|
|
? `orgChild1.id IN (:...node)`
|
|
: `orgChild1.id is null`
|
|
: "1=1",
|
|
{
|
|
node: _data.child1,
|
|
},
|
|
)
|
|
.select([
|
|
"orgChild1.id",
|
|
"orgChild1.misId",
|
|
"orgChild1.isOfficer",
|
|
"orgChild1.isInformation",
|
|
"orgChild1.orgChild1Name",
|
|
"orgChild1.orgChild1ShortName",
|
|
"orgChild1.orgChild1Code",
|
|
"orgChild1.orgChild1Order",
|
|
"orgChild1.orgChild1PhoneEx",
|
|
"orgChild1.orgChild1PhoneIn",
|
|
"orgChild1.orgChild1Fax",
|
|
"orgChild1.orgRootId",
|
|
"orgChild1.orgChild1Rank",
|
|
"orgChild1.orgChild1RankSub",
|
|
"orgChild1.DEPARTMENT_CODE",
|
|
"orgChild1.DIVISION_CODE",
|
|
"orgChild1.SECTION_CODE",
|
|
"orgChild1.JOB_CODE",
|
|
"orgChild1.responsibility",
|
|
])
|
|
.orderBy("orgChild1.orgChild1Order", "ASC")
|
|
.getMany()
|
|
: [];
|
|
|
|
const orgChild1Ids = orgChild1Data.map((orgChild1) => orgChild1.id) || null;
|
|
const orgChild2Data =
|
|
orgChild1Ids && orgChild1Ids.length > 0
|
|
? await AppDataSource.getRepository(OrgChild2)
|
|
.createQueryBuilder("orgChild2")
|
|
.where("orgChild2.orgChild1Id IN (:...ids)", { ids: orgChild1Ids })
|
|
.andWhere(
|
|
_data.child2 !== undefined && _data.child2 !== null
|
|
? _data.child2[0] !== null
|
|
? `orgChild2.id IN (:...node)`
|
|
: `orgChild2.id is null`
|
|
: "1=1",
|
|
{
|
|
node: _data.child2,
|
|
},
|
|
)
|
|
.select([
|
|
"orgChild2.id",
|
|
"orgChild2.misId",
|
|
"orgChild2.orgChild2Name",
|
|
"orgChild2.orgChild2ShortName",
|
|
"orgChild2.orgChild2Code",
|
|
"orgChild2.orgChild2Order",
|
|
"orgChild2.orgChild2PhoneEx",
|
|
"orgChild2.orgChild2PhoneIn",
|
|
"orgChild2.orgChild2Fax",
|
|
"orgChild2.orgRootId",
|
|
"orgChild2.orgChild2Rank",
|
|
"orgChild2.orgChild2RankSub",
|
|
"orgChild2.DEPARTMENT_CODE",
|
|
"orgChild2.DIVISION_CODE",
|
|
"orgChild2.SECTION_CODE",
|
|
"orgChild2.JOB_CODE",
|
|
"orgChild2.orgChild1Id",
|
|
"orgChild2.responsibility",
|
|
])
|
|
.orderBy("orgChild2.orgChild2Order", "ASC")
|
|
.getMany()
|
|
: [];
|
|
|
|
const orgChild2Ids = orgChild2Data.map((orgChild2) => orgChild2.id) || null;
|
|
const orgChild3Data =
|
|
orgChild2Ids && orgChild2Ids.length > 0
|
|
? await AppDataSource.getRepository(OrgChild3)
|
|
.createQueryBuilder("orgChild3")
|
|
.where("orgChild3.orgChild2Id IN (:...ids)", { ids: orgChild2Ids })
|
|
.andWhere(
|
|
_data.child3 !== undefined && _data.child3 !== null
|
|
? _data.child3[0] !== null
|
|
? `orgChild3.id IN (:...node)`
|
|
: `orgChild3.id is null`
|
|
: "1=1",
|
|
{
|
|
node: _data.child3,
|
|
},
|
|
)
|
|
.select([
|
|
"orgChild3.id",
|
|
"orgChild3.misId",
|
|
"orgChild3.orgChild3Name",
|
|
"orgChild3.orgChild3ShortName",
|
|
"orgChild3.orgChild3Code",
|
|
"orgChild3.orgChild3Order",
|
|
"orgChild3.orgChild3PhoneEx",
|
|
"orgChild3.orgChild3PhoneIn",
|
|
"orgChild3.orgChild3Fax",
|
|
"orgChild3.orgRootId",
|
|
"orgChild3.orgChild3Rank",
|
|
"orgChild3.orgChild3RankSub",
|
|
"orgChild3.DEPARTMENT_CODE",
|
|
"orgChild3.DIVISION_CODE",
|
|
"orgChild3.SECTION_CODE",
|
|
"orgChild3.JOB_CODE",
|
|
"orgChild3.orgChild2Id",
|
|
"orgChild3.responsibility",
|
|
])
|
|
.orderBy("orgChild3.orgChild3Order", "ASC")
|
|
.getMany()
|
|
: [];
|
|
|
|
const orgChild3Ids = orgChild3Data.map((orgChild3) => orgChild3.id) || null;
|
|
const orgChild4Data =
|
|
orgChild3Ids && orgChild3Ids.length > 0
|
|
? await AppDataSource.getRepository(OrgChild4)
|
|
.createQueryBuilder("orgChild4")
|
|
.where("orgChild4.orgChild3Id IN (:...ids)", { ids: orgChild3Ids })
|
|
.andWhere(
|
|
_data.child4 !== undefined && _data.child4 !== null
|
|
? _data.child4[0] !== null
|
|
? `orgChild4.id IN (:...node)`
|
|
: `orgChild4.id is null`
|
|
: "1=1",
|
|
{
|
|
node: _data.child4,
|
|
},
|
|
)
|
|
.select([
|
|
"orgChild4.id",
|
|
"orgChild4.misId",
|
|
"orgChild4.orgChild4Name",
|
|
"orgChild4.orgChild4ShortName",
|
|
"orgChild4.orgChild4Code",
|
|
"orgChild4.orgChild4Order",
|
|
"orgChild4.orgChild4PhoneEx",
|
|
"orgChild4.orgChild4PhoneIn",
|
|
"orgChild4.orgChild4Fax",
|
|
"orgChild4.orgRootId",
|
|
"orgChild4.orgChild4Rank",
|
|
"orgChild4.orgChild4RankSub",
|
|
"orgChild4.DEPARTMENT_CODE",
|
|
"orgChild4.DIVISION_CODE",
|
|
"orgChild4.SECTION_CODE",
|
|
"orgChild4.JOB_CODE",
|
|
"orgChild4.orgChild3Id",
|
|
"orgChild4.responsibility",
|
|
])
|
|
.orderBy("orgChild4.orgChild4Order", "ASC")
|
|
.getMany()
|
|
: [];
|
|
|
|
const formattedData = await Promise.all(
|
|
orgRootData.map(async (orgRoot) => {
|
|
return {
|
|
orgDnaId: orgRoot.ancestorDNA,
|
|
orgTreeId: orgRoot.id,
|
|
orgLevel: 0,
|
|
misId: orgRoot.misId,
|
|
orgName: orgRoot.orgRootName,
|
|
orgTreeName: orgRoot.orgRootName,
|
|
orgTreeShortName: orgRoot.orgRootShortName,
|
|
orgTreeCode: orgRoot.orgRootCode,
|
|
orgCode: orgRoot.orgRootCode + "00",
|
|
orgTreeRank: orgRoot.orgRootRank,
|
|
orgTreeRankSub: orgRoot.orgRootRankSub,
|
|
DEPARTMENT_CODE: orgRoot.DEPARTMENT_CODE,
|
|
DIVISION_CODE: orgRoot.DIVISION_CODE,
|
|
SECTION_CODE: orgRoot.SECTION_CODE,
|
|
JOB_CODE: orgRoot.JOB_CODE,
|
|
orgTreeOrder: orgRoot.orgRootOrder,
|
|
orgTreePhoneEx: orgRoot.orgRootPhoneEx,
|
|
orgTreePhoneIn: orgRoot.orgRootPhoneIn,
|
|
orgTreeFax: orgRoot.orgRootFax,
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootName: orgRoot.orgRootName,
|
|
isDeputy: orgRoot.isDeputy,
|
|
isCommission: orgRoot.isCommission,
|
|
responsibility: orgRoot.responsibility,
|
|
labelName:
|
|
orgRoot.orgRootName + " " + orgRoot.orgRootCode + "00" + " " + orgRoot.orgRootShortName,
|
|
|
|
children: await Promise.all(
|
|
orgChild1Data
|
|
.filter((orgChild1) => orgChild1.orgRootId === orgRoot.id)
|
|
.map(async (orgChild1) => ({
|
|
orgTreeId: orgChild1.id,
|
|
orgRootId: orgRoot.id,
|
|
orgLevel: 1,
|
|
misId: orgChild1.misId,
|
|
orgName: `${orgChild1.orgChild1Name}/${orgRoot.orgRootName}`,
|
|
orgTreeName: orgChild1.orgChild1Name,
|
|
orgTreeShortName: orgChild1.orgChild1ShortName,
|
|
orgTreeCode: orgChild1.orgChild1Code,
|
|
orgCode: orgRoot.orgRootCode + orgChild1.orgChild1Code,
|
|
orgTreeRank: orgChild1.orgChild1Rank,
|
|
orgTreeRankSub: orgChild1.orgChild1RankSub,
|
|
DEPARTMENT_CODE: orgChild1.DEPARTMENT_CODE,
|
|
DIVISION_CODE: orgChild1.DIVISION_CODE,
|
|
SECTION_CODE: orgChild1.SECTION_CODE,
|
|
JOB_CODE: orgChild1.JOB_CODE,
|
|
orgTreeOrder: orgChild1.orgChild1Order,
|
|
orgRootCode: orgRoot.orgRootCode,
|
|
orgTreePhoneEx: orgChild1.orgChild1PhoneEx,
|
|
orgTreePhoneIn: orgChild1.orgChild1PhoneIn,
|
|
orgTreeFax: orgChild1.orgChild1Fax,
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootName: orgRoot.orgRootName,
|
|
responsibility: orgChild1.responsibility,
|
|
isOfficer: orgChild1.isOfficer,
|
|
isInformation: orgChild1.isInformation,
|
|
labelName:
|
|
orgChild1.orgChild1Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild1.orgChild1Code +
|
|
" " +
|
|
orgChild1.orgChild1ShortName +
|
|
"/" +
|
|
orgRoot.orgRootName +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
"00" +
|
|
" " +
|
|
orgRoot.orgRootShortName,
|
|
|
|
children: await Promise.all(
|
|
orgChild2Data
|
|
.filter((orgChild2) => orgChild2.orgChild1Id === orgChild1.id)
|
|
.map(async (orgChild2) => ({
|
|
orgTreeId: orgChild2.id,
|
|
orgRootId: orgChild1.id,
|
|
orgLevel: 2,
|
|
misId: orgChild2.misId,
|
|
orgName: `${orgChild2.orgChild2Name}/${orgChild1.orgChild1Name}/${orgRoot.orgRootName}`,
|
|
orgTreeName: orgChild2.orgChild2Name,
|
|
orgTreeShortName: orgChild2.orgChild2ShortName,
|
|
orgTreeCode: orgChild2.orgChild2Code,
|
|
orgCode: orgRoot.orgRootCode + orgChild2.orgChild2Code,
|
|
orgTreeRank: orgChild2.orgChild2Rank,
|
|
orgTreeRankSub: orgChild2.orgChild2RankSub,
|
|
DEPARTMENT_CODE: orgChild2.DEPARTMENT_CODE,
|
|
DIVISION_CODE: orgChild2.DIVISION_CODE,
|
|
SECTION_CODE: orgChild2.SECTION_CODE,
|
|
JOB_CODE: orgChild2.JOB_CODE,
|
|
orgTreeOrder: orgChild2.orgChild2Order,
|
|
orgRootCode: orgRoot.orgRootCode,
|
|
orgTreePhoneEx: orgChild2.orgChild2PhoneEx,
|
|
orgTreePhoneIn: orgChild2.orgChild2PhoneIn,
|
|
orgTreeFax: orgChild2.orgChild2Fax,
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootName: orgRoot.orgRootName,
|
|
responsibility: orgChild2.responsibility,
|
|
labelName:
|
|
orgChild2.orgChild2Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild2.orgChild2Code +
|
|
" " +
|
|
orgChild2.orgChild2ShortName +
|
|
"/" +
|
|
orgChild1.orgChild1Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild1.orgChild1Code +
|
|
" " +
|
|
orgChild1.orgChild1ShortName +
|
|
"/" +
|
|
orgRoot.orgRootName +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
"00" +
|
|
" " +
|
|
orgRoot.orgRootShortName,
|
|
|
|
children: await Promise.all(
|
|
orgChild3Data
|
|
.filter((orgChild3) => orgChild3.orgChild2Id === orgChild2.id)
|
|
.map(async (orgChild3) => ({
|
|
orgTreeId: orgChild3.id,
|
|
orgRootId: orgChild2.id,
|
|
orgLevel: 3,
|
|
misId: orgChild3.misId,
|
|
orgName: `${orgChild3.orgChild3Name}/${orgChild2.orgChild2Name}/${orgChild1.orgChild1Name}/${orgRoot.orgRootName}`,
|
|
orgTreeName: orgChild3.orgChild3Name,
|
|
orgTreeShortName: orgChild3.orgChild3ShortName,
|
|
orgTreeCode: orgChild3.orgChild3Code,
|
|
orgCode: orgRoot.orgRootCode + orgChild3.orgChild3Code,
|
|
orgTreeRank: orgChild3.orgChild3Rank,
|
|
orgTreeRankSub: orgChild3.orgChild3RankSub,
|
|
DEPARTMENT_CODE: orgChild3.DEPARTMENT_CODE,
|
|
DIVISION_CODE: orgChild3.DIVISION_CODE,
|
|
SECTION_CODE: orgChild3.SECTION_CODE,
|
|
JOB_CODE: orgChild3.JOB_CODE,
|
|
orgTreeOrder: orgChild3.orgChild3Order,
|
|
orgRootCode: orgRoot.orgRootCode,
|
|
orgTreePhoneEx: orgChild3.orgChild3PhoneEx,
|
|
orgTreePhoneIn: orgChild3.orgChild3PhoneIn,
|
|
orgTreeFax: orgChild3.orgChild3Fax,
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootName: orgRoot.orgRootName,
|
|
responsibility: orgChild3.responsibility,
|
|
labelName:
|
|
orgChild3.orgChild3Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild3.orgChild3Code +
|
|
" " +
|
|
orgChild3.orgChild3ShortName +
|
|
"/" +
|
|
orgChild2.orgChild2Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild2.orgChild2Code +
|
|
" " +
|
|
orgChild2.orgChild2ShortName +
|
|
"/" +
|
|
orgChild1.orgChild1Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild1.orgChild1Code +
|
|
" " +
|
|
orgChild1.orgChild1ShortName +
|
|
"/" +
|
|
orgRoot.orgRootName +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
"00" +
|
|
" " +
|
|
orgRoot.orgRootShortName,
|
|
|
|
children: await Promise.all(
|
|
orgChild4Data
|
|
.filter((orgChild4) => orgChild4.orgChild3Id === orgChild3.id)
|
|
.map(async (orgChild4) => ({
|
|
orgTreeId: orgChild4.id,
|
|
orgRootId: orgChild3.id,
|
|
orgLevel: 4,
|
|
misId: orgChild4.misId,
|
|
orgName: `${orgChild4.orgChild4Name}/${orgChild3.orgChild3Name}/${orgChild2.orgChild2Name}/${orgChild1.orgChild1Name}/${orgRoot.orgRootName}`,
|
|
orgTreeName: orgChild4.orgChild4Name,
|
|
orgTreeShortName: orgChild4.orgChild4ShortName,
|
|
orgTreeCode: orgChild4.orgChild4Code,
|
|
orgCode: orgRoot.orgRootCode + orgChild4.orgChild4Code,
|
|
orgTreeRank: orgChild4.orgChild4Rank,
|
|
orgTreeRankSub: orgChild4.orgChild4RankSub,
|
|
DEPARTMENT_CODE: orgChild4.DEPARTMENT_CODE,
|
|
DIVISION_CODE: orgChild4.DIVISION_CODE,
|
|
SECTION_CODE: orgChild4.SECTION_CODE,
|
|
JOB_CODE: orgChild4.JOB_CODE,
|
|
orgTreeOrder: orgChild4.orgChild4Order,
|
|
orgRootCode: orgRoot.orgRootCode,
|
|
orgTreePhoneEx: orgChild4.orgChild4PhoneEx,
|
|
orgTreePhoneIn: orgChild4.orgChild4PhoneIn,
|
|
orgTreeFax: orgChild4.orgChild4Fax,
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootName: orgRoot.orgRootName,
|
|
responsibility: orgChild4.responsibility,
|
|
labelName:
|
|
orgChild4.orgChild4Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild4.orgChild4Code +
|
|
" " +
|
|
orgChild4.orgChild4ShortName +
|
|
"/" +
|
|
orgChild3.orgChild3Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild3.orgChild3Code +
|
|
" " +
|
|
orgChild3.orgChild3ShortName +
|
|
"/" +
|
|
orgChild2.orgChild2Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild2.orgChild2Code +
|
|
" " +
|
|
orgChild2.orgChild2ShortName +
|
|
"/" +
|
|
orgChild1.orgChild1Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild1.orgChild1Code +
|
|
" " +
|
|
orgChild1.orgChild1ShortName +
|
|
"/" +
|
|
orgRoot.orgRootName +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
"00" +
|
|
" " +
|
|
orgRoot.orgRootShortName,
|
|
})),
|
|
),
|
|
})),
|
|
),
|
|
})),
|
|
),
|
|
})),
|
|
),
|
|
};
|
|
}),
|
|
);
|
|
|
|
// return new HttpSuccess({ remark: _revision.remark, data: formattedData });
|
|
return new HttpSuccess({ remark: _revision.remark, data: formattedData });
|
|
}
|
|
|
|
/**
|
|
* API ตั้งเวลาเผยแพร่
|
|
*
|
|
* @summary ORG_025 - ตั้งเวลาเผยแพร่ (ADMIN) #27
|
|
*
|
|
* @param {string} id Id revison
|
|
*/
|
|
@Put("/set/publish/{id}")
|
|
async Edit(
|
|
@Path() id: string,
|
|
@Body() requestBody: { orgPublishDate: Date },
|
|
@Request() request: RequestWithUser,
|
|
) {
|
|
// await new permission().PermissionUpdate(request, "SYS_ORG");//ไม่แน่ใจOFFปิดไว้ก่อน
|
|
const orgRevision = await this.orgRevisionRepository.findOne({
|
|
where: {
|
|
id: id,
|
|
orgRevisionIsDraft: true,
|
|
orgRevisionIsCurrent: false,
|
|
},
|
|
});
|
|
if (!orgRevision) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found. RevisionId");
|
|
}
|
|
const before = structuredClone(orgRevision);
|
|
orgRevision.lastUpdateUserId = request.user.sub;
|
|
orgRevision.lastUpdateFullName = request.user.name;
|
|
orgRevision.lastUpdatedAt = new Date();
|
|
orgRevision.orgPublishDate = requestBody.orgPublishDate;
|
|
this.orgRevisionRepository.merge(orgRevision, requestBody);
|
|
await this.orgRevisionRepository.save(orgRevision, { data: request });
|
|
setLogDataDiff(request, { before, after: orgRevision });
|
|
return new HttpSuccess();
|
|
}
|
|
|
|
/**
|
|
* API ประวัติหน่วยงาน
|
|
*
|
|
* @summary ORG_039 - ประวัติหน่วยงาน (ADMIN) #42
|
|
*
|
|
*/
|
|
@Post("/history/publish")
|
|
async GetHistoryPublish(
|
|
@Body()
|
|
requestBody: {
|
|
id: string;
|
|
type: number;
|
|
},
|
|
@Request() request: RequestWithUser,
|
|
) {
|
|
if (requestBody.type == 1) {
|
|
const orgChild1 = await this.child1Repository.findOne({
|
|
where: { id: requestBody.id },
|
|
});
|
|
if (!orgChild1) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found. Child1");
|
|
}
|
|
const datas = await this.child1Repository
|
|
.createQueryBuilder("child1")
|
|
.where("child1.ancestorDNA = :ancestorDNA", { ancestorDNA: orgChild1.ancestorDNA })
|
|
.andWhere("child1.ancestorDNA <> :nullUUID", {
|
|
nullUUID: "00000000-0000-0000-0000-000000000000",
|
|
})
|
|
.andWhere("child1.ancestorDNA IS NOT NULL")
|
|
.leftJoinAndSelect("child1.orgRevision", "orgRevision")
|
|
.orderBy("child1.lastUpdatedAt", "DESC")
|
|
.getMany();
|
|
const _data = datas.map((item) => ({
|
|
id: item.id,
|
|
orgRevisionName: item.orgRevision == null ? null : item.orgRevision.orgRevisionName,
|
|
name: item.orgChild1Name,
|
|
lastUpdatedAt: item.lastUpdatedAt,
|
|
}));
|
|
return new HttpSuccess(_data);
|
|
} else if (requestBody.type == 2) {
|
|
const orgChild2 = await this.child2Repository.findOne({
|
|
where: { id: requestBody.id },
|
|
});
|
|
if (!orgChild2) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found. Child2");
|
|
}
|
|
const datas = await this.child2Repository
|
|
.createQueryBuilder("child2")
|
|
.where("child2.ancestorDNA = :ancestorDNA", { ancestorDNA: orgChild2.ancestorDNA })
|
|
.andWhere("child2.ancestorDNA <> :nullUUID", {
|
|
nullUUID: "00000000-0000-0000-0000-000000000000",
|
|
})
|
|
.andWhere("child2.ancestorDNA IS NOT NULL")
|
|
.leftJoinAndSelect("child2.orgRevision", "orgRevision")
|
|
.orderBy("child2.lastUpdatedAt", "DESC")
|
|
.getMany();
|
|
const _data = datas.map((item) => ({
|
|
id: item.id,
|
|
orgRevisionName: item.orgRevision == null ? null : item.orgRevision.orgRevisionName,
|
|
name: item.orgChild2Name,
|
|
lastUpdatedAt: item.lastUpdatedAt,
|
|
}));
|
|
return new HttpSuccess(_data);
|
|
} else if (requestBody.type == 3) {
|
|
const orgChild3 = await this.child3Repository.findOne({
|
|
where: { id: requestBody.id },
|
|
});
|
|
if (!orgChild3) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found. Child3");
|
|
}
|
|
const datas = await this.child3Repository
|
|
.createQueryBuilder("child3")
|
|
.where("child3.ancestorDNA = :ancestorDNA", { ancestorDNA: orgChild3.ancestorDNA })
|
|
.andWhere("child3.ancestorDNA <> :nullUUID", {
|
|
nullUUID: "00000000-0000-0000-0000-000000000000",
|
|
})
|
|
.andWhere("child3.ancestorDNA IS NOT NULL")
|
|
.leftJoinAndSelect("child3.orgRevision", "orgRevision")
|
|
.orderBy("child3.lastUpdatedAt", "DESC")
|
|
.getMany();
|
|
const _data = datas.map((item) => ({
|
|
id: item.id,
|
|
orgRevisionName: item.orgRevision == null ? null : item.orgRevision.orgRevisionName,
|
|
name: item.orgChild3Name,
|
|
lastUpdatedAt: item.lastUpdatedAt,
|
|
}));
|
|
return new HttpSuccess(_data);
|
|
} else if (requestBody.type == 4) {
|
|
const orgChild4 = await this.child4Repository.findOne({
|
|
where: { id: requestBody.id },
|
|
});
|
|
if (!orgChild4) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found. Child4");
|
|
}
|
|
const datas = await this.child4Repository
|
|
.createQueryBuilder("child4")
|
|
.where("child4.ancestorDNA = :ancestorDNA", { ancestorDNA: orgChild4.ancestorDNA })
|
|
.andWhere("child4.ancestorDNA <> :nullUUID", {
|
|
nullUUID: "00000000-0000-0000-0000-000000000000",
|
|
})
|
|
.andWhere("child4.ancestorDNA IS NOT NULL")
|
|
.leftJoinAndSelect("child4.orgRevision", "orgRevision")
|
|
.orderBy("child4.lastUpdatedAt", "DESC")
|
|
.getMany();
|
|
const _data = datas.map((item) => ({
|
|
id: item.id,
|
|
orgRevisionName: item.orgRevision == null ? null : item.orgRevision.orgRevisionName,
|
|
name: item.orgChild4Name,
|
|
lastUpdatedAt: item.lastUpdatedAt,
|
|
}));
|
|
return new HttpSuccess(_data);
|
|
} else {
|
|
const orgRoot = await this.orgRootRepository.findOne({
|
|
where: { id: requestBody.id },
|
|
});
|
|
if (!orgRoot) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found. Root");
|
|
}
|
|
const datas = await this.orgRootRepository
|
|
.createQueryBuilder("root")
|
|
.where("root.ancestorDNA = :ancestorDNA", { ancestorDNA: orgRoot.ancestorDNA })
|
|
.andWhere("root.ancestorDNA <> :nullUUID", {
|
|
nullUUID: "00000000-0000-0000-0000-000000000000",
|
|
})
|
|
.andWhere("root.ancestorDNA IS NOT NULL")
|
|
.leftJoinAndSelect("root.orgRevision", "orgRevision")
|
|
.orderBy("root.lastUpdatedAt", "DESC")
|
|
.getMany();
|
|
const _data = datas.map((item) => ({
|
|
id: item.id,
|
|
orgRevisionName: item.orgRevision == null ? null : item.orgRevision.orgRevisionName,
|
|
name: item.orgRootName,
|
|
lastUpdatedAt: item.lastUpdatedAt,
|
|
}));
|
|
return new HttpSuccess(_data);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* API จัดลำดับโครงสร้าง
|
|
*
|
|
* @summary ORG_038 - จัดลำดับโครงสร้าง (ADMIN) #41
|
|
*
|
|
*/
|
|
@Post("sort")
|
|
async Sort(
|
|
@Body() requestBody: { id: string; type: number; sortId: string[] },
|
|
@Request() request: RequestWithUser,
|
|
) {
|
|
await new permission().PermissionUpdate(request, "SYS_ORG");
|
|
const before = null;
|
|
switch (requestBody.type) {
|
|
case 0: {
|
|
const revisionId = await this.orgRevisionRepository.findOne({
|
|
where: { id: requestBody.id },
|
|
});
|
|
if (!revisionId?.id) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found revisionId: " + requestBody.id);
|
|
}
|
|
const listRootId = await this.orgRootRepository.find({
|
|
where: { orgRevisionId: requestBody.id },
|
|
select: ["id", "orgRootOrder"],
|
|
});
|
|
if (!listRootId) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found rootId.");
|
|
}
|
|
const sortData = listRootId.map((data) => ({
|
|
id: data.id,
|
|
orgRootOrder: requestBody.sortId.indexOf(data.id) + 1,
|
|
}));
|
|
await this.orgRootRepository.save(sortData, { data: request });
|
|
setLogDataDiff(request, { before, after: sortData });
|
|
break;
|
|
}
|
|
|
|
case 1: {
|
|
const rootId = await this.orgRootRepository.findOne({ where: { id: requestBody.id } });
|
|
if (!rootId?.id) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found rootId: " + requestBody.id);
|
|
}
|
|
const listChild1Id = await this.child1Repository.find({
|
|
where: { orgRootId: requestBody.id },
|
|
select: ["id", "orgChild1Order"],
|
|
});
|
|
if (!listChild1Id) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child1Id.");
|
|
}
|
|
const sortData = listChild1Id.map((data) => ({
|
|
id: data.id,
|
|
orgChild1Order: requestBody.sortId.indexOf(data.id) + 1,
|
|
}));
|
|
await this.child1Repository.save(sortData, { data: request });
|
|
setLogDataDiff(request, { before, after: sortData });
|
|
break;
|
|
}
|
|
|
|
case 2: {
|
|
const child1Id = await this.child1Repository.findOne({ where: { id: requestBody.id } });
|
|
if (!child1Id?.id) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child1Id: " + requestBody.id);
|
|
}
|
|
const listChild2Id = await this.child2Repository.find({
|
|
where: { orgChild1Id: requestBody.id },
|
|
select: ["id", "orgChild2Order"],
|
|
});
|
|
if (!listChild2Id) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child2Id.");
|
|
}
|
|
const sortData = listChild2Id.map((data) => ({
|
|
id: data.id,
|
|
orgChild2Order: requestBody.sortId.indexOf(data.id) + 1,
|
|
}));
|
|
await this.child2Repository.save(sortData, { data: request });
|
|
setLogDataDiff(request, { before, after: sortData });
|
|
break;
|
|
}
|
|
|
|
case 3: {
|
|
const child2Id = await this.child2Repository.findOne({ where: { id: requestBody.id } });
|
|
if (!child2Id?.id) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child2Id: " + requestBody.id);
|
|
}
|
|
const listChild3Id = await this.child3Repository.find({
|
|
where: { orgChild2Id: requestBody.id },
|
|
select: ["id", "orgChild3Order"],
|
|
});
|
|
if (!listChild3Id) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child3Id.");
|
|
}
|
|
const sortData = listChild3Id.map((data) => ({
|
|
id: data.id,
|
|
orgChild3Order: requestBody.sortId.indexOf(data.id) + 1,
|
|
}));
|
|
await this.child3Repository.save(sortData, { data: request });
|
|
setLogDataDiff(request, { before, after: sortData });
|
|
break;
|
|
}
|
|
|
|
case 4: {
|
|
const child3Id = await this.child3Repository.findOne({ where: { id: requestBody.id } });
|
|
if (!child3Id?.id) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child3Id: " + requestBody.id);
|
|
}
|
|
const listChild4Id = await this.child4Repository.find({
|
|
where: { orgChild3Id: requestBody.id },
|
|
select: ["id", "orgChild4Order"],
|
|
});
|
|
if (!listChild4Id) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child4Id.");
|
|
}
|
|
const sortData = listChild4Id.map((data) => ({
|
|
id: data.id,
|
|
orgChild4Order: requestBody.sortId.indexOf(data.id) + 1,
|
|
}));
|
|
await this.child4Repository.save(sortData, { data: request });
|
|
setLogDataDiff(request, { before, after: sortData });
|
|
break;
|
|
}
|
|
|
|
default:
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found type: " + requestBody.type);
|
|
}
|
|
return new HttpSuccess();
|
|
}
|
|
|
|
/**
|
|
* API เผยแพร่ข้อมูล
|
|
*
|
|
* @summary ORG_071 - เผยแพร่ข้อมูล (ADMIN) #57
|
|
*
|
|
* @param {string} id Id revison
|
|
*/
|
|
@Get("get/publish")
|
|
async runPublish(@Request() request: RequestWithUser) {
|
|
try {
|
|
// CheckQueueInProgress
|
|
// console.log("🚀 ตรวจสอบว่ามีงานอยู่ในคิว");
|
|
const [isBusyDraft, isBusyPublish] = await Promise.all([
|
|
checkQueueInProgress(`${process.env.AMQ_QUEUE_ORG_DRAFT}`),
|
|
checkQueueInProgress(`${process.env.AMQ_QUEUE_ORG}`),
|
|
]);
|
|
// console.log("✅ ตรวจสอบแล้ว Draft Busy:", isBusyDraft);
|
|
// console.log("✅ ตรวจสอบแล้ว Publish Busy:", isBusyPublish);
|
|
if (isBusyDraft || isBusyPublish) {
|
|
// console.log("🚫 พบว่ามีงานอยู่ในคิว — error")
|
|
throw new HttpError(
|
|
HttpStatusCode.CONFLICT,
|
|
"ไม่สามารถดำเนินการได้ หากกำลังเผยแพร่หรือสร้างแบบร่างโครงสร้างหน่วยงาน",
|
|
);
|
|
}
|
|
|
|
const today = new Date();
|
|
today.setHours(0, 0, 0, 0); // Set time to the beginning of the day
|
|
|
|
const orgRevisionDraft = await this.orgRevisionRepository
|
|
.createQueryBuilder("orgRevision")
|
|
.where("orgRevision.orgRevisionIsDraft = true")
|
|
.andWhere("orgRevision.orgRevisionIsCurrent = false")
|
|
// .andWhere("DATE(orgRevision.orgPublishDate) = :today", { today })
|
|
.getOne();
|
|
if (!orgRevisionDraft) {
|
|
return new HttpSuccess();
|
|
// throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่มีข้อมูลเผยแพร่");
|
|
}
|
|
// if (orgRevisionPublish) {
|
|
// orgRevisionPublish.orgRevisionIsDraft = false;
|
|
// orgRevisionPublish.orgRevisionIsCurrent = false;
|
|
// await this.orgRevisionRepository.save(orgRevisionPublish);
|
|
// }
|
|
// orgRevisionDraft.orgRevisionIsCurrent = true;
|
|
// orgRevisionDraft.orgRevisionIsDraft = false;
|
|
// await this.orgRevisionRepository.save(orgRevisionDraft);
|
|
const msg = {
|
|
data: {
|
|
id: orgRevisionDraft.id,
|
|
status: "NOW",
|
|
lastUpdateUserId: request.user.sub,
|
|
lastUpdateFullName: request.user.name,
|
|
lastUpdatedAt: new Date(),
|
|
},
|
|
user: request.user,
|
|
token: request.headers["authorization"],
|
|
};
|
|
await sendToQueueOrg(msg);
|
|
return new HttpSuccess();
|
|
} catch (error: any) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Cronjob
|
|
*/
|
|
async cronjobRevision() {
|
|
const today = new Date();
|
|
today.setUTCHours(0, 0, 0, 0); // Set time to the beginning of the day
|
|
const tomorrow = new Date(today);
|
|
tomorrow.setDate(tomorrow.getDate() + 1);
|
|
|
|
const orgRevisionDraft = await this.orgRevisionRepository
|
|
.createQueryBuilder("orgRevision")
|
|
.where("orgRevision.orgRevisionIsDraft = true")
|
|
.andWhere("orgRevision.orgRevisionIsCurrent = false")
|
|
.andWhere("orgRevision.orgPublishDate BETWEEN :today AND :tomorrow", { today, tomorrow })
|
|
.getOne();
|
|
|
|
if (!orgRevisionDraft) {
|
|
return new HttpSuccess();
|
|
}
|
|
// if (orgRevisionPublish) {
|
|
// orgRevisionPublish.orgRevisionIsDraft = false;
|
|
// orgRevisionPublish.orgRevisionIsCurrent = false;
|
|
// await this.orgRevisionRepository.save(orgRevisionPublish);
|
|
// }
|
|
// orgRevisionDraft.orgRevisionIsCurrent = true;
|
|
// orgRevisionDraft.orgRevisionIsDraft = false;
|
|
// await this.orgRevisionRepository.save(orgRevisionDraft);
|
|
|
|
// const posMaster = await this.posMasterRepository.find({
|
|
// where: { orgRevisionId: orgRevisionDraft.id },
|
|
// });
|
|
// posMaster.forEach(async (item) => {
|
|
// // if(item.next_holderId != null){
|
|
// item.current_holderId = item.next_holderId;
|
|
// item.next_holderId = null;
|
|
// await this.posMasterRepository.save(item);
|
|
// // }
|
|
// });
|
|
const msg = {
|
|
data: {
|
|
id: orgRevisionDraft.id,
|
|
status: "ON_SCHEDULE",
|
|
lastUpdateUserId: "system",
|
|
lastUpdateFullName: "system",
|
|
lastUpdatedAt: new Date(),
|
|
},
|
|
};
|
|
sendToQueueOrg(msg);
|
|
return new HttpSuccess();
|
|
}
|
|
|
|
/**
|
|
* API Organizational Chart
|
|
*
|
|
* @summary Organizational Chart
|
|
*
|
|
* @param {string} revisionId Id revison
|
|
*/
|
|
@Get("org-chart/{revisionId}")
|
|
async orgchart(@Path() revisionId: string) {
|
|
const data = await this.orgRevisionRepository.findOne({
|
|
where: { id: revisionId },
|
|
});
|
|
if (!data) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลโครงสร้าง");
|
|
}
|
|
let posMasterRoot: any;
|
|
let posMasterChild1: any;
|
|
let posMasterChild2: any;
|
|
let posMasterChild3: any;
|
|
let posMasterChild4: any;
|
|
if (data.orgRevisionIsCurrent == true && data.orgRevisionIsDraft == false) {
|
|
// ใช้ query เดียวแทน 5 queries แยก เพื่อความเร็วในการทำงาน
|
|
const allPosMasters = await this.posMasterRepository.find({
|
|
where: {
|
|
orgRevisionId: data.id,
|
|
},
|
|
relations: [
|
|
"current_holder",
|
|
"orgRoot",
|
|
"orgChild1",
|
|
"orgChild2",
|
|
"orgChild3",
|
|
"orgChild4",
|
|
],
|
|
order: {
|
|
orgRoot: {
|
|
orgRootOrder: "ASC",
|
|
},
|
|
posMasterOrder: "ASC",
|
|
posMasterNo: "ASC",
|
|
},
|
|
});
|
|
|
|
// แยกข้อมูลด้วย JavaScript แทนการใช้ database queries หลาย ๆ ครั้ง
|
|
posMasterRoot = allPosMasters.filter((item) => item.orgChild1Id === null);
|
|
posMasterChild1 = allPosMasters.filter(
|
|
(item) => item.orgChild2Id === null && item.orgChild1Id !== null,
|
|
);
|
|
posMasterChild2 = allPosMasters.filter(
|
|
(item) => item.orgChild3Id === null && item.orgChild2Id !== null,
|
|
);
|
|
posMasterChild3 = allPosMasters.filter(
|
|
(item) => item.orgChild4Id === null && item.orgChild3Id !== null,
|
|
);
|
|
posMasterChild4 = allPosMasters.filter((item) => item.orgChild4Id !== null);
|
|
|
|
// สร้าง Maps เพื่อ lookup ที่เร็วขึ้น แทนการใช้ filter หลายรอบ
|
|
const rootByOrgRootId = new Map<string, PosMaster[]>();
|
|
const child1ByOrgRootId = new Map<string, PosMaster[]>();
|
|
const child1ByOrgChild1Id = new Map<string, PosMaster[]>();
|
|
const child2ByOrgChild1Id = new Map<string, PosMaster[]>();
|
|
const child2ByOrgChild2Id = new Map<string, PosMaster[]>();
|
|
const child3ByOrgChild2Id = new Map<string, PosMaster[]>();
|
|
const child3ByOrgChild3Id = new Map<string, PosMaster[]>();
|
|
const child4ByOrgChild3Id = new Map<string, PosMaster[]>();
|
|
|
|
// Pre-compute all lookups เพื่อหลีกเลี่ยงการ filter ซ้ำๆ
|
|
posMasterRoot.forEach((item: PosMaster) => {
|
|
if (item.current_holderId) {
|
|
if (item.isDirector) {
|
|
// Root directors will be processed in main loop
|
|
} else {
|
|
// Group root non-directors by orgRootId
|
|
const key = item.orgRootId || "";
|
|
if (!rootByOrgRootId.has(key)) rootByOrgRootId.set(key, []);
|
|
rootByOrgRootId.get(key)!.push(item);
|
|
}
|
|
}
|
|
});
|
|
|
|
posMasterChild1.forEach((item: PosMaster) => {
|
|
if (item.isDirector) {
|
|
// Group child1 directors by orgRootId
|
|
const key = item.orgRootId || "";
|
|
if (!child1ByOrgRootId.has(key)) child1ByOrgRootId.set(key, []);
|
|
child1ByOrgRootId.get(key)!.push(item);
|
|
} else if (item.current_holderId) {
|
|
// Group child1 non-directors by orgChild1Id
|
|
const key = item.orgChild1Id || "";
|
|
if (!child1ByOrgChild1Id.has(key)) child1ByOrgChild1Id.set(key, []);
|
|
child1ByOrgChild1Id.get(key)!.push(item);
|
|
}
|
|
});
|
|
|
|
posMasterChild2.forEach((item: PosMaster) => {
|
|
if (item.isDirector) {
|
|
// Group child2 directors by orgChild1Id
|
|
const key = item.orgChild1Id || "";
|
|
if (!child2ByOrgChild1Id.has(key)) child2ByOrgChild1Id.set(key, []);
|
|
child2ByOrgChild1Id.get(key)!.push(item);
|
|
} else if (item.current_holderId) {
|
|
// Group child2 non-directors by orgChild2Id
|
|
const key = item.orgChild2Id || "";
|
|
if (!child2ByOrgChild2Id.has(key)) child2ByOrgChild2Id.set(key, []);
|
|
child2ByOrgChild2Id.get(key)!.push(item);
|
|
}
|
|
});
|
|
|
|
posMasterChild3.forEach((item: PosMaster) => {
|
|
if (item.isDirector) {
|
|
// Group child3 directors by orgChild2Id
|
|
const key = item.orgChild2Id || "";
|
|
if (!child3ByOrgChild2Id.has(key)) child3ByOrgChild2Id.set(key, []);
|
|
child3ByOrgChild2Id.get(key)!.push(item);
|
|
} else if (item.current_holderId) {
|
|
// Group child3 non-directors by orgChild3Id
|
|
const key = item.orgChild3Id || "";
|
|
if (!child3ByOrgChild3Id.has(key)) child3ByOrgChild3Id.set(key, []);
|
|
child3ByOrgChild3Id.get(key)!.push(item);
|
|
}
|
|
});
|
|
|
|
posMasterChild4.forEach((item: PosMaster) => {
|
|
if (item.isDirector) {
|
|
// Group child4 directors by orgChild3Id
|
|
const key = item.orgChild3Id || "";
|
|
if (!child4ByOrgChild3Id.has(key)) child4ByOrgChild3Id.set(key, []);
|
|
child4ByOrgChild3Id.get(key)!.push(item);
|
|
}
|
|
});
|
|
|
|
// Helper function เพื่อสร้าง node object
|
|
const createNode = (item: PosMaster, level: number, holder: any, orgInfo: any) => ({
|
|
level,
|
|
personID: holder?.id ?? "",
|
|
name: holder ? `${holder.firstName} ${holder.lastName}` : "ว่าง",
|
|
avatar:
|
|
holder?.avatar && holder?.avatarName ? `${holder.avatar}/${holder.avatarName}` : null,
|
|
positionName: holder?.position ?? "",
|
|
positionNum: `${orgInfo.shortName} ${item.posMasterNo}`,
|
|
positionNumInt: item.posMasterNo,
|
|
departmentName: orgInfo.name,
|
|
organizationId: orgInfo.id,
|
|
children: [] as any[],
|
|
});
|
|
|
|
let formattedData = posMasterRoot
|
|
.filter((x: any) => x.current_holderId != null && x.isDirector)
|
|
.map((x0: PosMaster) => {
|
|
const childLevel1: any[] = [];
|
|
|
|
// Add root non-directors (Level 2)
|
|
const rootNonDirectors = rootByOrgRootId.get(x0.orgRootId || "") || [];
|
|
rootNonDirectors.forEach((x00: PosMaster) => {
|
|
childLevel1.push(
|
|
createNode(x00, 2, x00.current_holder, {
|
|
shortName: x00.orgRoot.orgRootShortName,
|
|
name: x00.orgRoot.orgRootName,
|
|
id: x00.orgRoot.id,
|
|
}),
|
|
);
|
|
});
|
|
|
|
// Add child1 directors (Level 2)
|
|
const child1Directors = child1ByOrgRootId.get(x0.orgRootId || "") || [];
|
|
child1Directors.forEach((x1: PosMaster) => {
|
|
const childLevel2: any[] = [];
|
|
|
|
// Add child1 non-directors (Level 3)
|
|
const child1NonDirectors = child1ByOrgChild1Id.get(x1.orgChild1Id || "") || [];
|
|
child1NonDirectors.forEach((x11: PosMaster) => {
|
|
childLevel2.push(
|
|
createNode(x11, 3, x11.current_holder, {
|
|
shortName: x11.orgChild1.orgChild1ShortName,
|
|
name: x11.orgChild1.orgChild1Name,
|
|
id: x11.orgChild1.id,
|
|
}),
|
|
);
|
|
});
|
|
|
|
// Add child2 directors (Level 3)
|
|
const child2Directors = child2ByOrgChild1Id.get(x1.orgChild1Id || "") || [];
|
|
child2Directors.forEach((x2: PosMaster) => {
|
|
const childLevel3: any[] = [];
|
|
|
|
// Add child2 non-directors (Level 4)
|
|
const child2NonDirectors = child2ByOrgChild2Id.get(x2.orgChild2Id || "") || [];
|
|
child2NonDirectors.forEach((x22: PosMaster) => {
|
|
childLevel3.push(
|
|
createNode(x22, 4, x22.current_holder, {
|
|
shortName: x22.orgChild2.orgChild2ShortName,
|
|
name: x22.orgChild2.orgChild2Name,
|
|
id: x22.orgChild2.id,
|
|
}),
|
|
);
|
|
});
|
|
|
|
// Add child3 directors (Level 4)
|
|
const child3Directors = child3ByOrgChild2Id.get(x2.orgChild2Id || "") || [];
|
|
child3Directors.forEach((x3: PosMaster) => {
|
|
const childLevel4: any[] = [];
|
|
|
|
// Add child3 non-directors (Level 5)
|
|
const child3NonDirectors = child3ByOrgChild3Id.get(x3.orgChild3Id || "") || [];
|
|
child3NonDirectors.forEach((x33: PosMaster) => {
|
|
childLevel4.push(
|
|
createNode(x33, 5, x33.current_holder, {
|
|
shortName: x33.orgChild3.orgChild3ShortName,
|
|
name: x33.orgChild3.orgChild3Name,
|
|
id: x33.orgChild3.id,
|
|
}),
|
|
);
|
|
});
|
|
|
|
// Add child4 directors (Level 5)
|
|
const child4Directors = child4ByOrgChild3Id.get(x3.orgChild3Id || "") || [];
|
|
child4Directors.forEach((x4: PosMaster) => {
|
|
const childLevel5: any[] = [];
|
|
|
|
// Add child4 non-directors (Level 5)
|
|
posMasterChild4
|
|
.filter(
|
|
(x: PosMaster) =>
|
|
!x.isDirector && x.current_holderId && x.orgChild3Id === x4.orgChild3Id,
|
|
)
|
|
.forEach((x44: PosMaster) => {
|
|
childLevel5.push(
|
|
createNode(x44, 5, x44.current_holder, {
|
|
shortName: x44.orgChild4.orgChild4ShortName,
|
|
name: x44.orgChild4.orgChild4Name,
|
|
id: x44.orgChild4.id,
|
|
}),
|
|
);
|
|
});
|
|
|
|
const child4Node = createNode(x4, 4, x4.current_holder, {
|
|
shortName: x4.orgChild4.orgChild4ShortName,
|
|
name: x4.orgChild4.orgChild4Name,
|
|
id: x4.orgChild4.id,
|
|
});
|
|
child4Node.children = childLevel5;
|
|
childLevel4.push(child4Node);
|
|
});
|
|
|
|
const child3Node = createNode(x3, 4, x3.current_holder, {
|
|
shortName: x3.orgChild3.orgChild3ShortName,
|
|
name: x3.orgChild3.orgChild3Name,
|
|
id: x3.orgChild3.id,
|
|
});
|
|
child3Node.children = childLevel4;
|
|
childLevel3.push(child3Node);
|
|
});
|
|
|
|
const child2Node = createNode(x2, 3, x2.current_holder, {
|
|
shortName: x2.orgChild2.orgChild2ShortName,
|
|
name: x2.orgChild2.orgChild2Name,
|
|
id: x2.orgChild2.id,
|
|
});
|
|
child2Node.children = childLevel3;
|
|
childLevel2.push(child2Node);
|
|
});
|
|
|
|
const child1Node = createNode(x1, 2, x1.current_holder, {
|
|
shortName: x1.orgChild1.orgChild1ShortName,
|
|
name: x1.orgChild1.orgChild1Name,
|
|
id: x1.orgChild1.id,
|
|
});
|
|
child1Node.children = childLevel2;
|
|
childLevel1.push(child1Node);
|
|
});
|
|
|
|
// Root Level 1
|
|
const rootNode = createNode(x0, 1, x0.current_holder, {
|
|
shortName: x0.orgRoot.orgRootShortName,
|
|
name: x0.orgRoot.orgRootName,
|
|
id: x0.orgRoot.id,
|
|
});
|
|
rootNode.children = childLevel1;
|
|
return rootNode;
|
|
});
|
|
|
|
const formattedData_ = {
|
|
personID: "",
|
|
name: "",
|
|
avatar: "",
|
|
positionName: "",
|
|
positionNum: "",
|
|
positionNumInt: null,
|
|
departmentName: data.orgRevisionName,
|
|
organizationId: data.id,
|
|
children: formattedData,
|
|
};
|
|
return new HttpSuccess([formattedData_]);
|
|
} else if (data.orgRevisionIsCurrent == false && data.orgRevisionIsDraft == true) {
|
|
// ใช้ query เดียวแทน 5 queries แยก เพื่อความเร็วในการทำงาน
|
|
const allPosMasters = await this.posMasterRepository.find({
|
|
where: {
|
|
orgRevisionId: data.id,
|
|
// next_holderId: Not(IsNull()),
|
|
},
|
|
relations: ["next_holder", "orgRoot", "orgChild1", "orgChild2", "orgChild3", "orgChild4"],
|
|
});
|
|
|
|
// แยกข้อมูลด้วย JavaScript แทนการใช้ database queries หลาย ๆ ครั้ง
|
|
posMasterRoot = allPosMasters.filter((item) => item.orgChild1Id === null);
|
|
posMasterChild1 = allPosMasters.filter(
|
|
(item) => item.orgChild2Id === null && item.orgChild1Id !== null,
|
|
);
|
|
posMasterChild2 = allPosMasters.filter(
|
|
(item) => item.orgChild3Id === null && item.orgChild2Id !== null,
|
|
);
|
|
posMasterChild3 = allPosMasters.filter(
|
|
(item) => item.orgChild4Id === null && item.orgChild3Id !== null,
|
|
);
|
|
posMasterChild4 = allPosMasters.filter((item) => item.orgChild4Id !== null);
|
|
|
|
// สร้าง Maps เพื่อ lookup ที่เร็วขึ้น แทนการใช้ filter หลายรอบ สำหรับ draft version
|
|
const rootByOrgRootIdDraft = new Map<string, PosMaster[]>();
|
|
const child1ByOrgRootIdDraft = new Map<string, PosMaster[]>();
|
|
const child1ByOrgChild1IdDraft = new Map<string, PosMaster[]>();
|
|
const child2ByOrgChild1IdDraft = new Map<string, PosMaster[]>();
|
|
const child2ByOrgChild2IdDraft = new Map<string, PosMaster[]>();
|
|
const child3ByOrgChild2IdDraft = new Map<string, PosMaster[]>();
|
|
const child3ByOrgChild3IdDraft = new Map<string, PosMaster[]>();
|
|
const child4ByOrgChild3IdDraft = new Map<string, PosMaster[]>();
|
|
|
|
// Pre-compute all lookups เพื่อหลีกเลี่ยงการ filter ซ้ำๆ สำหรับ draft version
|
|
posMasterRoot.forEach((item: PosMaster) => {
|
|
if (item.next_holderId) {
|
|
if (item.isDirector) {
|
|
// Root directors will be processed in main loop
|
|
} else {
|
|
// Group root non-directors by orgRootId
|
|
const key = item.orgRootId || "";
|
|
if (!rootByOrgRootIdDraft.has(key)) rootByOrgRootIdDraft.set(key, []);
|
|
rootByOrgRootIdDraft.get(key)!.push(item);
|
|
}
|
|
}
|
|
});
|
|
|
|
posMasterChild1.forEach((item: PosMaster) => {
|
|
if (item.isDirector) {
|
|
// Group child1 directors by orgRootId
|
|
const key = item.orgRootId || "";
|
|
if (!child1ByOrgRootIdDraft.has(key)) child1ByOrgRootIdDraft.set(key, []);
|
|
child1ByOrgRootIdDraft.get(key)!.push(item);
|
|
} else if (item.next_holderId) {
|
|
// Group child1 non-directors by orgChild1Id
|
|
const key = item.orgChild1Id || "";
|
|
if (!child1ByOrgChild1IdDraft.has(key)) child1ByOrgChild1IdDraft.set(key, []);
|
|
child1ByOrgChild1IdDraft.get(key)!.push(item);
|
|
}
|
|
});
|
|
|
|
posMasterChild2.forEach((item: PosMaster) => {
|
|
if (item.isDirector) {
|
|
// Group child2 directors by orgChild1Id
|
|
const key = item.orgChild1Id || "";
|
|
if (!child2ByOrgChild1IdDraft.has(key)) child2ByOrgChild1IdDraft.set(key, []);
|
|
child2ByOrgChild1IdDraft.get(key)!.push(item);
|
|
} else if (item.next_holderId) {
|
|
// Group child2 non-directors by orgChild2Id
|
|
const key = item.orgChild2Id || "";
|
|
if (!child2ByOrgChild2IdDraft.has(key)) child2ByOrgChild2IdDraft.set(key, []);
|
|
child2ByOrgChild2IdDraft.get(key)!.push(item);
|
|
}
|
|
});
|
|
|
|
posMasterChild3.forEach((item: PosMaster) => {
|
|
if (item.isDirector) {
|
|
// Group child3 directors by orgChild2Id
|
|
const key = item.orgChild2Id || "";
|
|
if (!child3ByOrgChild2IdDraft.has(key)) child3ByOrgChild2IdDraft.set(key, []);
|
|
child3ByOrgChild2IdDraft.get(key)!.push(item);
|
|
} else if (item.next_holderId) {
|
|
// Group child3 non-directors by orgChild3Id
|
|
const key = item.orgChild3Id || "";
|
|
if (!child3ByOrgChild3IdDraft.has(key)) child3ByOrgChild3IdDraft.set(key, []);
|
|
child3ByOrgChild3IdDraft.get(key)!.push(item);
|
|
}
|
|
});
|
|
|
|
posMasterChild4.forEach((item: PosMaster) => {
|
|
if (item.isDirector) {
|
|
// Group child4 directors by orgChild3Id
|
|
const key = item.orgChild3Id || "";
|
|
if (!child4ByOrgChild3IdDraft.has(key)) child4ByOrgChild3IdDraft.set(key, []);
|
|
child4ByOrgChild3IdDraft.get(key)!.push(item);
|
|
}
|
|
});
|
|
|
|
// Helper function เพื่อสร้าง node object สำหรับ draft version
|
|
const createNodeDraft = (item: PosMaster, level: number, holder: any, orgInfo: any) => ({
|
|
level,
|
|
personID: holder?.id ?? "",
|
|
name: holder ? `${holder.firstName} ${holder.lastName}` : "ว่าง",
|
|
avatar:
|
|
holder?.avatar && holder?.avatarName ? `${holder.avatar}/${holder.avatarName}` : null,
|
|
positionName: holder?.position ?? "",
|
|
positionNum: `${orgInfo.shortName} ${item.posMasterNo}`,
|
|
positionNumInt: item.posMasterNo,
|
|
departmentName: orgInfo.name,
|
|
organizationId: orgInfo.id,
|
|
children: [] as any[],
|
|
});
|
|
|
|
let formattedData = posMasterRoot
|
|
.filter((x: any) => x.next_holderId != null && x.isDirector)
|
|
.map((x0: PosMaster) => {
|
|
const childLevel1: any[] = [];
|
|
|
|
// Add root non-directors (Level 2)
|
|
const rootNonDirectors = rootByOrgRootIdDraft.get(x0.orgRootId || "") || [];
|
|
rootNonDirectors.forEach((x00: PosMaster) => {
|
|
childLevel1.push(
|
|
createNodeDraft(x00, 2, x00.next_holder, {
|
|
shortName: x00.orgRoot.orgRootShortName,
|
|
name: x00.orgRoot.orgRootName,
|
|
id: x00.orgRoot.id,
|
|
}),
|
|
);
|
|
});
|
|
|
|
// Add child1 directors (Level 2)
|
|
const child1Directors = child1ByOrgRootIdDraft.get(x0.orgRootId || "") || [];
|
|
child1Directors.forEach((x1: PosMaster) => {
|
|
const childLevel2: any[] = [];
|
|
|
|
// Add child1 non-directors (Level 3)
|
|
const child1NonDirectors = child1ByOrgChild1IdDraft.get(x1.orgChild1Id || "") || [];
|
|
child1NonDirectors.forEach((x11: PosMaster) => {
|
|
childLevel2.push(
|
|
createNodeDraft(x11, 3, x11.next_holder, {
|
|
shortName: x11.orgChild1.orgChild1ShortName,
|
|
name: x11.orgChild1.orgChild1Name,
|
|
id: x11.orgChild1.id,
|
|
}),
|
|
);
|
|
});
|
|
|
|
// Add child2 directors (Level 3)
|
|
const child2Directors = child2ByOrgChild1IdDraft.get(x1.orgChild1Id || "") || [];
|
|
child2Directors.forEach((x2: PosMaster) => {
|
|
const childLevel3: any[] = [];
|
|
|
|
// Add child2 non-directors (Level 4)
|
|
const child2NonDirectors = child2ByOrgChild2IdDraft.get(x2.orgChild2Id || "") || [];
|
|
child2NonDirectors.forEach((x22: PosMaster) => {
|
|
childLevel3.push(
|
|
createNodeDraft(x22, 4, x22.next_holder, {
|
|
shortName: x22.orgChild2.orgChild2ShortName,
|
|
name: x22.orgChild2.orgChild2Name,
|
|
id: x22.orgChild2.id,
|
|
}),
|
|
);
|
|
});
|
|
|
|
// Add child3 directors (Level 4)
|
|
const child3Directors = child3ByOrgChild2IdDraft.get(x2.orgChild2Id || "") || [];
|
|
child3Directors.forEach((x3: PosMaster) => {
|
|
const childLevel4: any[] = [];
|
|
|
|
// Add child3 non-directors (Level 5)
|
|
const child3NonDirectors = child3ByOrgChild3IdDraft.get(x3.orgChild3Id || "") || [];
|
|
child3NonDirectors.forEach((x33: PosMaster) => {
|
|
childLevel4.push(
|
|
createNodeDraft(x33, 5, x33.next_holder, {
|
|
shortName: x33.orgChild3.orgChild3ShortName,
|
|
name: x33.orgChild3.orgChild3Name,
|
|
id: x33.orgChild3.id,
|
|
}),
|
|
);
|
|
});
|
|
|
|
// Add child4 directors (Level 5)
|
|
const child4Directors = child4ByOrgChild3IdDraft.get(x3.orgChild3Id || "") || [];
|
|
child4Directors.forEach((x4: PosMaster) => {
|
|
const childLevel5: any[] = [];
|
|
|
|
// Add child4 non-directors (Level 5)
|
|
posMasterChild4
|
|
.filter(
|
|
(x: PosMaster) =>
|
|
!x.isDirector && x.next_holderId && x.orgChild3Id === x4.orgChild3Id,
|
|
)
|
|
.forEach((x44: PosMaster) => {
|
|
childLevel5.push(
|
|
createNodeDraft(x44, 5, x44.next_holder, {
|
|
shortName: x44.orgChild4.orgChild4ShortName,
|
|
name: x44.orgChild4.orgChild4Name,
|
|
id: x44.orgChild4.id,
|
|
}),
|
|
);
|
|
});
|
|
|
|
const child4Node = createNodeDraft(x4, 4, x4.next_holder, {
|
|
shortName: x4.orgChild4.orgChild4ShortName,
|
|
name: x4.orgChild4.orgChild4Name,
|
|
id: x4.orgChild4.id,
|
|
});
|
|
child4Node.children = childLevel5;
|
|
childLevel4.push(child4Node);
|
|
});
|
|
|
|
const child3Node = createNodeDraft(x3, 4, x3.next_holder, {
|
|
shortName: x3.orgChild3.orgChild3ShortName,
|
|
name: x3.orgChild3.orgChild3Name,
|
|
id: x3.orgChild3.id,
|
|
});
|
|
child3Node.children = childLevel4;
|
|
childLevel3.push(child3Node);
|
|
});
|
|
|
|
const child2Node = createNodeDraft(x2, 3, x2.next_holder, {
|
|
shortName: x2.orgChild2.orgChild2ShortName,
|
|
name: x2.orgChild2.orgChild2Name,
|
|
id: x2.orgChild2.id,
|
|
});
|
|
child2Node.children = childLevel3;
|
|
childLevel2.push(child2Node);
|
|
});
|
|
|
|
const child1Node = createNodeDraft(x1, 2, x1.next_holder, {
|
|
shortName: x1.orgChild1.orgChild1ShortName,
|
|
name: x1.orgChild1.orgChild1Name,
|
|
id: x1.orgChild1.id,
|
|
});
|
|
child1Node.children = childLevel2;
|
|
childLevel1.push(child1Node);
|
|
});
|
|
|
|
// Root Level 1
|
|
const rootNode = createNodeDraft(x0, 1, x0.next_holder, {
|
|
shortName: x0.orgRoot.orgRootShortName,
|
|
name: x0.orgRoot.orgRootName,
|
|
id: x0.orgRoot.id,
|
|
});
|
|
rootNode.children = childLevel1;
|
|
return rootNode;
|
|
});
|
|
|
|
const formattedData_ = {
|
|
personID: "",
|
|
name: "",
|
|
avatar: "",
|
|
positionName: "",
|
|
positionNum: "",
|
|
positionNumInt: null,
|
|
departmentName: data.orgRevisionName,
|
|
organizationId: data.id,
|
|
children: formattedData,
|
|
};
|
|
return new HttpSuccess([formattedData_]);
|
|
} else {
|
|
return new HttpSuccess([
|
|
{
|
|
personID: "",
|
|
name: "",
|
|
avatar: "",
|
|
positionName: "",
|
|
positionNum: "",
|
|
positionNumInt: null,
|
|
departmentName: data.orgRevisionName,
|
|
organizationId: data.id,
|
|
children: [],
|
|
},
|
|
]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* API Organizational Chart
|
|
*
|
|
* @summary Organizational Chart
|
|
*
|
|
* @param {string} revisionId Id revison
|
|
*/
|
|
@Get("org-chart/{revisionId}/{rootId}")
|
|
async orgChartByRoot(@Path() revisionId: string, @Path() rootId: string) {
|
|
// get revision data
|
|
const data = await this.orgRevisionRepository.findOne({ where: { id: revisionId } });
|
|
if (!data) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลโครงสร้าง");
|
|
}
|
|
|
|
type OrgInfo = { shortName: string; name: string; id: string };
|
|
|
|
let fieldId: "current_holderId" | "next_holderId" = "current_holderId";
|
|
let relations: string[] =
|
|
rootId === "root"
|
|
? ["current_holder", "orgRoot"]
|
|
: ["current_holder", "orgRoot", "orgChild1", "orgChild2", "orgChild3", "orgChild4"];
|
|
if (data.orgRevisionIsCurrent === false && data.orgRevisionIsDraft === true) {
|
|
fieldId = "next_holderId";
|
|
relations =
|
|
rootId === "root"
|
|
? ["next_holder", "orgRoot"]
|
|
: ["next_holder", "orgRoot", "orgChild1", "orgChild2", "orgChild3", "orgChild4"];
|
|
}
|
|
|
|
const where =
|
|
rootId === "root"
|
|
? { orgRevisionId: data.id, posMasterNo: 1 }
|
|
: { orgRevisionId: data.id, orgRootId: rootId };
|
|
|
|
const allPosMasters = await this.posMasterRepository.find({
|
|
where,
|
|
relations,
|
|
order: {
|
|
orgRoot: { orgRootOrder: "ASC" },
|
|
posMasterOrder: "ASC",
|
|
posMasterNo: "ASC",
|
|
},
|
|
});
|
|
|
|
// Split positions by level
|
|
const posMasterRoot = allPosMasters.filter((item) => item.orgChild1Id === null);
|
|
const posMasterChild1 =
|
|
rootId !== "root"
|
|
? allPosMasters.filter((item) => item.orgChild2Id === null && item.orgChild1Id !== null)
|
|
: [];
|
|
const posMasterChild2 =
|
|
rootId !== "root"
|
|
? allPosMasters.filter((item) => item.orgChild3Id === null && item.orgChild2Id !== null)
|
|
: [];
|
|
const posMasterChild3 =
|
|
rootId !== "root"
|
|
? allPosMasters.filter((item) => item.orgChild4Id === null && item.orgChild3Id !== null)
|
|
: [];
|
|
const posMasterChild4 =
|
|
rootId !== "root" ? allPosMasters.filter((item) => item.orgChild4Id !== null) : [];
|
|
|
|
// Find the minimum posMasterNo for each orgRootId
|
|
const minPosMasterNoByOrgRootId = new Map<string, number>();
|
|
posMasterRoot.forEach((x) => {
|
|
const orgRootId = x.orgRootId ?? "";
|
|
const currentMin = minPosMasterNoByOrgRootId.get(orgRootId);
|
|
if (
|
|
(currentMin === undefined || x.posMasterNo < currentMin) &&
|
|
(x as any)[fieldId] != null &&
|
|
x.isDirector
|
|
) {
|
|
minPosMasterNoByOrgRootId.set(orgRootId, x.posMasterNo);
|
|
}
|
|
});
|
|
|
|
// Utility to group by key
|
|
function groupBy<T>(
|
|
arr: T[],
|
|
keyFn: (item: T) => string | number | undefined | null,
|
|
): Map<string, T[]> {
|
|
const map = new Map<string, T[]>();
|
|
for (const item of arr) {
|
|
let key = keyFn(item);
|
|
if (key === undefined || key === null) key = "";
|
|
key = String(key);
|
|
if (!map.has(key)) map.set(key, []);
|
|
map.get(key)!.push(item);
|
|
}
|
|
return map;
|
|
}
|
|
|
|
// Build lookup maps
|
|
const rootByOrgRootId = groupBy(
|
|
posMasterRoot.filter(
|
|
(item) =>
|
|
((item as any)[fieldId] && !item.isDirector) ||
|
|
(item.isDirector &&
|
|
minPosMasterNoByOrgRootId.get(item.orgRootId ?? "") !== item.posMasterNo),
|
|
),
|
|
(item) => item.orgRootId ?? "",
|
|
);
|
|
const child1ByOrgRootId = groupBy(
|
|
posMasterChild1.filter((item) => item.isDirector),
|
|
(item) => item.orgRootId ?? "",
|
|
);
|
|
const child1ByOrgChild1Id = groupBy(
|
|
posMasterChild1.filter((item) => (item as any)[fieldId] && !item.isDirector),
|
|
(item) => item.orgChild1Id ?? "",
|
|
);
|
|
const child2ByOrgChild1Id = groupBy(
|
|
posMasterChild2.filter((item) => item.isDirector),
|
|
(item) => item.orgChild1Id ?? "",
|
|
);
|
|
const child2ByOrgChild2Id = groupBy(
|
|
posMasterChild2.filter((item) => (item as any)[fieldId] && !item.isDirector),
|
|
(item) => item.orgChild2Id ?? "",
|
|
);
|
|
const child3ByOrgChild2Id = groupBy(
|
|
posMasterChild3.filter((item) => item.isDirector),
|
|
(item) => item.orgChild2Id ?? "",
|
|
);
|
|
const child3ByOrgChild3Id = groupBy(
|
|
posMasterChild3.filter((item) => (item as any)[fieldId] && !item.isDirector),
|
|
(item) => item.orgChild3Id ?? "",
|
|
);
|
|
const child4ByOrgChild3Id = groupBy(
|
|
posMasterChild4.filter((item) => item.isDirector),
|
|
(item) => item.orgChild3Id ?? "",
|
|
);
|
|
|
|
// Helper to create node
|
|
function createNode(item: any, level: number, orgInfo: OrgInfo): any {
|
|
const holder = fieldId === "current_holderId" ? item.current_holder : item.next_holder;
|
|
return {
|
|
level,
|
|
personID: holder?.id ?? "",
|
|
name: holder ? `${holder.firstName} ${holder.lastName}` : "ว่าง",
|
|
avatar:
|
|
holder?.avatar && holder?.avatarName ? `${holder.avatar}/${holder.avatarName}` : null,
|
|
positionName: holder?.position ?? "",
|
|
positionNum: `${orgInfo.shortName} ${item.posMasterNo}`,
|
|
positionNumInt: item.posMasterNo,
|
|
departmentName: orgInfo.name,
|
|
organizationId: orgInfo.id,
|
|
children: [],
|
|
};
|
|
}
|
|
|
|
// Recursive builder for children
|
|
function buildChildren(level: number, parent: any, orgInfo: OrgInfo): any[] {
|
|
if (level === 2) {
|
|
// Level 2: child1 non-directors and child2 directors
|
|
const children: any[] = [];
|
|
// Root non-directors
|
|
(
|
|
rootByOrgRootId
|
|
.get(parent.orgRootId)
|
|
?.filter(
|
|
(x00) =>
|
|
!x00.isDirector ||
|
|
(x00.isDirector &&
|
|
minPosMasterNoByOrgRootId.get(x00.orgRootId ?? "") !== x00.posMasterNo),
|
|
) || []
|
|
).forEach((x00) => {
|
|
children.push(
|
|
createNode(x00, 2, {
|
|
shortName: x00.orgRoot.orgRootShortName,
|
|
name: x00.orgRoot.orgRootName,
|
|
id: x00.orgRoot.id,
|
|
}),
|
|
);
|
|
});
|
|
if (rootId !== "root") {
|
|
// Child1 directors
|
|
(child1ByOrgRootId.get(parent.orgRootId) || []).forEach((x1) => {
|
|
const childLevel2 = buildChildren(3, x1, {
|
|
shortName: x1.orgChild1.orgChild1ShortName,
|
|
name: x1.orgChild1.orgChild1Name,
|
|
id: x1.orgChild1.id,
|
|
});
|
|
const node = createNode(x1, 2, {
|
|
shortName: x1.orgChild1.orgChild1ShortName,
|
|
name: x1.orgChild1.orgChild1Name,
|
|
id: x1.orgChild1.id,
|
|
});
|
|
node.children = childLevel2;
|
|
children.push(node);
|
|
});
|
|
}
|
|
return children;
|
|
} else if (level === 3) {
|
|
// Level 3: child1 non-directors and child2 directors
|
|
const children: any[] = [];
|
|
(child1ByOrgChild1Id.get(parent.orgChild1Id) || []).forEach((x11) => {
|
|
children.push(
|
|
createNode(x11, 3, {
|
|
shortName: x11.orgChild1.orgChild1ShortName,
|
|
name: x11.orgChild1.orgChild1Name,
|
|
id: x11.orgChild1.id,
|
|
}),
|
|
);
|
|
});
|
|
(child2ByOrgChild1Id.get(parent.orgChild1Id) || []).forEach((x2) => {
|
|
const childLevel3 = buildChildren(4, x2, {
|
|
shortName: x2.orgChild2.orgChild2ShortName,
|
|
name: x2.orgChild2.orgChild2Name,
|
|
id: x2.orgChild2.id,
|
|
});
|
|
const node = createNode(x2, 3, {
|
|
shortName: x2.orgChild2.orgChild2ShortName,
|
|
name: x2.orgChild2.orgChild2Name,
|
|
id: x2.orgChild2.id,
|
|
});
|
|
node.children = childLevel3;
|
|
children.push(node);
|
|
});
|
|
return children;
|
|
} else if (level === 4) {
|
|
// Level 4: child2 non-directors and child3 directors
|
|
const children: any[] = [];
|
|
(child2ByOrgChild2Id.get(parent.orgChild2Id) || []).forEach((x22) => {
|
|
children.push(
|
|
createNode(x22, 4, {
|
|
shortName: x22.orgChild2.orgChild2ShortName,
|
|
name: x22.orgChild2.orgChild2Name,
|
|
id: x22.orgChild2.id,
|
|
}),
|
|
);
|
|
});
|
|
(child3ByOrgChild2Id.get(parent.orgChild2Id) || []).forEach((x3) => {
|
|
const childLevel4 = buildChildren(5, x3, {
|
|
shortName: x3.orgChild3.orgChild3ShortName,
|
|
name: x3.orgChild3.orgChild3Name,
|
|
id: x3.orgChild3.id,
|
|
});
|
|
const node = createNode(x3, 4, {
|
|
shortName: x3.orgChild3.orgChild3ShortName,
|
|
name: x3.orgChild3.orgChild3Name,
|
|
id: x3.orgChild3.id,
|
|
});
|
|
node.children = childLevel4;
|
|
children.push(node);
|
|
});
|
|
return children;
|
|
} else if (level === 5) {
|
|
// Level 5: child3 non-directors and child4 directors
|
|
const children: any[] = [];
|
|
(child3ByOrgChild3Id.get(parent.orgChild3Id) || []).forEach((x33) => {
|
|
children.push(
|
|
createNode(x33, 5, {
|
|
shortName: x33.orgChild3.orgChild3ShortName,
|
|
name: x33.orgChild3.orgChild3Name,
|
|
id: x33.orgChild3.id,
|
|
}),
|
|
);
|
|
});
|
|
(child4ByOrgChild3Id.get(parent.orgChild3Id) || []).forEach((x4) => {
|
|
// Level 5: child4 directors and their non-directors
|
|
const childLevel5: any[] = [];
|
|
posMasterChild4
|
|
.filter((x) => !x.isDirector && (x as any)[fieldId] && x.orgChild3Id === x4.orgChild3Id)
|
|
.forEach((x44) => {
|
|
childLevel5.push(
|
|
createNode(x44, 5, {
|
|
shortName: x44.orgChild4.orgChild4ShortName,
|
|
name: x44.orgChild4.orgChild4Name,
|
|
id: x44.orgChild4.id,
|
|
}),
|
|
);
|
|
});
|
|
const node = createNode(x4, 4, {
|
|
shortName: x4.orgChild4.orgChild4ShortName,
|
|
name: x4.orgChild4.orgChild4Name,
|
|
id: x4.orgChild4.id,
|
|
});
|
|
node.children = childLevel5;
|
|
children.push(node);
|
|
});
|
|
return children;
|
|
}
|
|
return [];
|
|
}
|
|
|
|
// Build root nodes
|
|
const formattedData = posMasterRoot
|
|
.filter(
|
|
(x: any) =>
|
|
x.isDirector && minPosMasterNoByOrgRootId.get(x.orgRootId ?? "") === x.posMasterNo,
|
|
)
|
|
.map((x0) => {
|
|
const rootNode = createNode(x0, 1, {
|
|
shortName: x0.orgRoot.orgRootShortName,
|
|
name: x0.orgRoot.orgRootName,
|
|
id: x0.orgRoot.id,
|
|
});
|
|
rootNode.children = buildChildren(2, x0, {
|
|
shortName: x0.orgRoot.orgRootShortName,
|
|
name: x0.orgRoot.orgRootName,
|
|
id: x0.orgRoot.id,
|
|
});
|
|
return rootNode;
|
|
});
|
|
|
|
const formattedData_ =
|
|
rootId === "root"
|
|
? [
|
|
{
|
|
personID: "",
|
|
name: "",
|
|
avatar: "",
|
|
positionName: "",
|
|
positionNum: "",
|
|
positionNumInt: null,
|
|
departmentName: data.orgRevisionName,
|
|
organizationId: data.id,
|
|
children: formattedData,
|
|
},
|
|
]
|
|
: formattedData;
|
|
return new HttpSuccess(formattedData_);
|
|
}
|
|
|
|
// /**
|
|
// * API Organizational StructChart
|
|
// *
|
|
// * @summary Organizational StructChart
|
|
// *
|
|
// */
|
|
// @Get("struct-chart/{idNode}/{type}")
|
|
// async structchart(@Path() idNode: string, type: number) {
|
|
// switch (type) {
|
|
// case 0: {
|
|
// const data = await this.orgRevisionRepository.findOne({
|
|
// where: { id: idNode },
|
|
// relations: [
|
|
// "orgRoots",
|
|
// "orgRoots.orgChild1s",
|
|
// "orgRoots.orgChild1s.orgChild2s",
|
|
// "orgRoots.orgChild1s.orgChild2s.orgChild3s",
|
|
// "orgRoots.orgChild1s.orgChild2s.orgChild3s.orgChild4s",
|
|
// ],
|
|
// });
|
|
// if (!data) {
|
|
// throw new HttpError(HttpStatusCode.NOT_FOUND, "not found revision");
|
|
// }
|
|
|
|
// const formattedData = {
|
|
// departmentName: data.orgRevisionName,
|
|
// deptID: data.id,
|
|
// type: 0,
|
|
// // heads:
|
|
// totalPositionCount: await this.posMasterRepository.count({
|
|
// where: { orgRevisionId: data.id },
|
|
// }),
|
|
// totalPositionVacant:
|
|
// data.orgRevisionIsDraft == true
|
|
// ? await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRevisionId: data.id,
|
|
// next_holderId: IsNull() || "",
|
|
// },
|
|
// })
|
|
// : await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRevisionId: data.id,
|
|
// current_holderId: IsNull() || "",
|
|
// },
|
|
// }),
|
|
// // totalPositionCurrentVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgRevisionId: data.id,
|
|
// // current_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// // totalPositionNextVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgRevisionId: data.id,
|
|
// // next_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// children: await Promise.all(
|
|
// data.orgRoots
|
|
// .sort((a, b) => a.orgRootOrder - b.orgRootOrder)
|
|
// .map(async (orgRoot: OrgRoot) => {
|
|
// return {
|
|
// departmentName: orgRoot.orgRootName,
|
|
// deptID: orgRoot.id,
|
|
// type: 1,
|
|
// // heads:
|
|
// totalPositionCount: await this.posMasterRepository.count({
|
|
// where: { orgRevisionId: data.id, orgRootId: orgRoot.id },
|
|
// }),
|
|
// totalPositionVacant:
|
|
// data.orgRevisionIsDraft == true
|
|
// ? await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRevisionId: data.id,
|
|
// orgRootId: orgRoot.id,
|
|
// next_holderId: IsNull() || "",
|
|
// },
|
|
// })
|
|
// : await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRevisionId: data.id,
|
|
// orgRootId: orgRoot.id,
|
|
// current_holderId: IsNull() || "",
|
|
// },
|
|
// }),
|
|
// // totalPositionCurrentVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgRevisionId: data.id,
|
|
// // orgRootId: orgRoot.id,
|
|
// // current_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// // totalPositionNextVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgRevisionId: data.id,
|
|
// // orgRootId: orgRoot.id,
|
|
// // next_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// children: await Promise.all(
|
|
// orgRoot.orgChild1s
|
|
// .sort((a, b) => a.orgChild1Order - b.orgChild1Order)
|
|
// .map(async (orgChild1) => ({
|
|
// departmentName: orgChild1.orgChild1Name,
|
|
// deptID: orgChild1.id,
|
|
// type: 2,
|
|
// // heads:
|
|
// totalPositionCount: await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRevisionId: data.id,
|
|
// orgRootId: orgRoot.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// },
|
|
// }),
|
|
// totalPositionVacant:
|
|
// data.orgRevisionIsDraft == true
|
|
// ? await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRevisionId: data.id,
|
|
// orgRootId: orgRoot.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// next_holderId: IsNull() || "",
|
|
// },
|
|
// })
|
|
// : await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRevisionId: data.id,
|
|
// orgRootId: orgRoot.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// current_holderId: IsNull() || "",
|
|
// },
|
|
// }),
|
|
// // totalPositionCurrentVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgRevisionId: data.id,
|
|
// // orgRootId: orgRoot.id,
|
|
// // orgChild1Id: orgChild1.id,
|
|
// // current_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// // totalPositionNextVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgRevisionId: data.id,
|
|
// // orgRootId: orgRoot.id,
|
|
// // orgChild1Id: orgChild1.id,
|
|
// // next_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// children: await Promise.all(
|
|
// orgChild1.orgChild2s
|
|
// .sort((a, b) => a.orgChild2Order - b.orgChild2Order)
|
|
// .map(async (orgChild2) => ({
|
|
// departmentName: orgChild2.orgChild2Name,
|
|
// deptID: orgChild2.id,
|
|
// type: 3,
|
|
// // heads:
|
|
// totalPositionCount: await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRevisionId: data.id,
|
|
// orgRootId: orgRoot.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// },
|
|
// }),
|
|
// totalPositionVacant:
|
|
// data.orgRevisionIsDraft == true
|
|
// ? await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRevisionId: data.id,
|
|
// orgRootId: orgRoot.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// next_holderId: IsNull() || "",
|
|
// },
|
|
// })
|
|
// : await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRevisionId: data.id,
|
|
// orgRootId: orgRoot.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// current_holderId: IsNull() || "",
|
|
// },
|
|
// }),
|
|
// // totalPositionCurrentVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgRevisionId: data.id,
|
|
// // orgRootId: orgRoot.id,
|
|
// // orgChild1Id: orgChild1.id,
|
|
// // orgChild2Id: orgChild2.id,
|
|
// // current_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// // totalPositionNextVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgRevisionId: data.id,
|
|
// // orgRootId: orgRoot.id,
|
|
// // orgChild1Id: orgChild1.id,
|
|
// // orgChild2Id: orgChild2.id,
|
|
// // next_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// children: await Promise.all(
|
|
// orgChild2.orgChild3s
|
|
// .sort((a, b) => a.orgChild3Order - b.orgChild3Order)
|
|
// .map(async (orgChild3) => ({
|
|
// departmentName: orgChild3.orgChild3Name,
|
|
// deptID: orgChild3.id,
|
|
// type: 4,
|
|
// // heads:
|
|
// totalPositionCount: await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRevisionId: data.id,
|
|
// orgRootId: orgRoot.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// orgChild3Id: orgChild3.id,
|
|
// },
|
|
// }),
|
|
// totalPositionVacant:
|
|
// data.orgRevisionIsDraft == true
|
|
// ? await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRevisionId: data.id,
|
|
// orgRootId: orgRoot.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// orgChild3Id: orgChild3.id,
|
|
// next_holderId: IsNull() || "",
|
|
// },
|
|
// })
|
|
// : await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRevisionId: data.id,
|
|
// orgRootId: orgRoot.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// orgChild3Id: orgChild3.id,
|
|
// current_holderId: IsNull() || "",
|
|
// },
|
|
// }),
|
|
// // totalPositionCurrentVacant:
|
|
// // await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgRevisionId: data.id,
|
|
// // orgRootId: orgRoot.id,
|
|
// // orgChild1Id: orgChild1.id,
|
|
// // orgChild2Id: orgChild2.id,
|
|
// // orgChild3Id: orgChild3.id,
|
|
// // current_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// // totalPositionNextVacant: await this.posMasterRepository.count(
|
|
// // {
|
|
// // where: {
|
|
// // orgRevisionId: data.id,
|
|
// // orgRootId: orgRoot.id,
|
|
// // orgChild1Id: orgChild1.id,
|
|
// // orgChild2Id: orgChild2.id,
|
|
// // orgChild3Id: orgChild3.id,
|
|
// // next_holderId: IsNull() || "",
|
|
// // },
|
|
// // },
|
|
// // ),
|
|
// children: await Promise.all(
|
|
// orgChild3.orgChild4s
|
|
// .sort((a, b) => a.orgChild4Order - b.orgChild4Order)
|
|
// .map(async (orgChild4) => ({
|
|
// departmentName: orgChild4.orgChild4Name,
|
|
// deptID: orgChild4.id,
|
|
// type: 5,
|
|
// // heads:
|
|
// totalPositionCount: await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRevisionId: data.id,
|
|
// orgRootId: orgRoot.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// orgChild3Id: orgChild3.id,
|
|
// orgChild4Id: orgChild4.id,
|
|
// },
|
|
// }),
|
|
// totalPositionVacant:
|
|
// data.orgRevisionIsDraft == true
|
|
// ? await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRevisionId: data.id,
|
|
// orgRootId: orgRoot.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// orgChild3Id: orgChild3.id,
|
|
// orgChild4Id: orgChild4.id,
|
|
// next_holderId: IsNull() || "",
|
|
// },
|
|
// })
|
|
// : await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRevisionId: data.id,
|
|
// orgRootId: orgRoot.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// orgChild3Id: orgChild3.id,
|
|
// orgChild4Id: orgChild4.id,
|
|
// current_holderId: IsNull() || "",
|
|
// },
|
|
// }),
|
|
// // totalPositionCurrentVacant:
|
|
// // await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgRevisionId: data.id,
|
|
// // orgRootId: orgRoot.id,
|
|
// // orgChild1Id: orgChild1.id,
|
|
// // orgChild2Id: orgChild2.id,
|
|
// // orgChild3Id: orgChild3.id,
|
|
// // orgChild4Id: orgChild4.id,
|
|
// // current_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// // totalPositionNextVacant:
|
|
// // await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgRevisionId: data.id,
|
|
// // orgRootId: orgRoot.id,
|
|
// // orgChild1Id: orgChild1.id,
|
|
// // orgChild2Id: orgChild2.id,
|
|
// // orgChild3Id: orgChild3.id,
|
|
// // orgChild4Id: orgChild4.id,
|
|
// // next_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// })),
|
|
// ),
|
|
// })),
|
|
// ),
|
|
// })),
|
|
// ),
|
|
// })),
|
|
// ),
|
|
// };
|
|
// }),
|
|
// ),
|
|
// };
|
|
// return new HttpSuccess([formattedData]);
|
|
// }
|
|
// case 1: {
|
|
// const data = await this.orgRootRepository.findOne({
|
|
// where: { id: idNode },
|
|
// relations: [
|
|
// "orgRevision",
|
|
// "orgChild1s",
|
|
// "orgChild1s.orgChild2s",
|
|
// "orgChild1s.orgChild2s.orgChild3s",
|
|
// "orgChild1s.orgChild2s.orgChild3s.orgChild4s",
|
|
// ],
|
|
// });
|
|
// if (!data) {
|
|
// throw new HttpError(HttpStatusCode.NOT_FOUND, "not found rootId");
|
|
// }
|
|
|
|
// const formattedData = {
|
|
// departmentName: data.orgRootName,
|
|
// deptID: data.id,
|
|
// type: 1,
|
|
// // heads:
|
|
// totalPositionCount: await this.posMasterRepository.count({
|
|
// where: { orgRootId: data.id },
|
|
// }),
|
|
// totalPositionVacant:
|
|
// data.orgRevision.orgRevisionIsDraft == true
|
|
// ? await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRootId: data.id,
|
|
// next_holderId: IsNull() || "",
|
|
// },
|
|
// })
|
|
// : await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRootId: data.id,
|
|
// current_holderId: IsNull() || "",
|
|
// },
|
|
// }),
|
|
// // totalPositionCurrentVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgRootId: data.id,
|
|
// // current_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// // totalPositionNextVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgRootId: data.id,
|
|
// // next_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
|
|
// children: await Promise.all(
|
|
// data.orgChild1s
|
|
// .sort((a, b) => a.orgChild1Order - b.orgChild1Order)
|
|
// .map(async (orgChild1) => ({
|
|
// departmentName: orgChild1.orgChild1Name,
|
|
// deptID: orgChild1.id,
|
|
// type: 2,
|
|
// // heads:
|
|
// totalPositionCount: await this.posMasterRepository.count({
|
|
// where: { orgRootId: data.id, orgChild1Id: orgChild1.id },
|
|
// }),
|
|
// totalPositionVacant:
|
|
// data.orgRevision.orgRevisionIsDraft == true
|
|
// ? await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRootId: data.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// next_holderId: IsNull() || "",
|
|
// },
|
|
// })
|
|
// : await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRootId: data.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// current_holderId: IsNull() || "",
|
|
// },
|
|
// }),
|
|
// // totalPositionCurrentVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgRootId: data.id,
|
|
// // orgChild1Id: orgChild1.id,
|
|
// // current_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// // totalPositionNextVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgRootId: data.id,
|
|
// // orgChild1Id: orgChild1.id,
|
|
// // next_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// children: await Promise.all(
|
|
// orgChild1.orgChild2s
|
|
// .sort((a, b) => a.orgChild2Order - b.orgChild2Order)
|
|
// .map(async (orgChild2) => ({
|
|
// departmentName: orgChild2.orgChild2Name,
|
|
// deptID: orgChild2.id,
|
|
// type: 3,
|
|
// // heads:
|
|
// totalPositionCount: await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRootId: data.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// },
|
|
// }),
|
|
// totalPositionCurrentVacant:
|
|
// data.orgRevision.orgRevisionIsDraft == true
|
|
// ? await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRootId: data.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// next_holderId: IsNull() || "",
|
|
// },
|
|
// })
|
|
// : await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRootId: data.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// current_holderId: IsNull() || "",
|
|
// },
|
|
// }),
|
|
// // totalPositionCurrentVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgRootId: data.id,
|
|
// // orgChild1Id: orgChild1.id,
|
|
// // orgChild2Id: orgChild2.id,
|
|
// // current_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// // totalPositionNextVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgRootId: data.id,
|
|
// // orgChild1Id: orgChild1.id,
|
|
// // orgChild2Id: orgChild2.id,
|
|
// // next_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// children: await Promise.all(
|
|
// orgChild2.orgChild3s
|
|
// .sort((a, b) => a.orgChild3Order - b.orgChild3Order)
|
|
// .map(async (orgChild3) => ({
|
|
// departmentName: orgChild3.orgChild3Name,
|
|
// deptID: orgChild3.id,
|
|
// type: 4,
|
|
// // heads:
|
|
// totalPositionCount: await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRootId: data.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// orgChild3Id: orgChild3.id,
|
|
// },
|
|
// }),
|
|
// totalPositionVacant:
|
|
// data.orgRevision.orgRevisionIsDraft == true
|
|
// ? await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRootId: data.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// orgChild3Id: orgChild3.id,
|
|
// next_holderId: IsNull() || "",
|
|
// },
|
|
// })
|
|
// : await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRootId: data.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// orgChild3Id: orgChild3.id,
|
|
// current_holderId: IsNull() || "",
|
|
// },
|
|
// }),
|
|
// // totalPositionCurrentVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgRootId: data.id,
|
|
// // orgChild1Id: orgChild1.id,
|
|
// // orgChild2Id: orgChild2.id,
|
|
// // orgChild3Id: orgChild3.id,
|
|
// // current_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// // totalPositionNextVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgRootId: data.id,
|
|
// // orgChild1Id: orgChild1.id,
|
|
// // orgChild2Id: orgChild2.id,
|
|
// // orgChild3Id: orgChild3.id,
|
|
// // next_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// children: await Promise.all(
|
|
// orgChild3.orgChild4s
|
|
// .sort((a, b) => a.orgChild4Order - b.orgChild4Order)
|
|
// .map(async (orgChild4) => ({
|
|
// departmentName: orgChild4.orgChild4Name,
|
|
// deptID: orgChild4.id,
|
|
// type: 5,
|
|
// // heads:
|
|
// totalPositionCount: await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRootId: data.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// orgChild3Id: orgChild3.id,
|
|
// orgChild4Id: orgChild4.id,
|
|
// },
|
|
// }),
|
|
// totalPositionVacant:
|
|
// data.orgRevision.orgRevisionIsDraft == true
|
|
// ? await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRootId: data.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// orgChild3Id: orgChild3.id,
|
|
// orgChild4Id: orgChild4.id,
|
|
// next_holderId: IsNull() || "",
|
|
// },
|
|
// })
|
|
// : await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRootId: data.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// orgChild3Id: orgChild3.id,
|
|
// orgChild4Id: orgChild4.id,
|
|
// current_holderId: IsNull() || "",
|
|
// },
|
|
// }),
|
|
// // totalPositionCurrentVacant:
|
|
// // await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgRootId: data.id,
|
|
// // orgChild1Id: orgChild1.id,
|
|
// // orgChild2Id: orgChild2.id,
|
|
// // orgChild3Id: orgChild3.id,
|
|
// // orgChild4Id: orgChild4.id,
|
|
// // current_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// // totalPositionNextVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgRootId: data.id,
|
|
// // orgChild1Id: orgChild1.id,
|
|
// // orgChild2Id: orgChild2.id,
|
|
// // orgChild3Id: orgChild3.id,
|
|
// // orgChild4Id: orgChild4.id,
|
|
// // next_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// })),
|
|
// ),
|
|
// })),
|
|
// ),
|
|
// })),
|
|
// ),
|
|
// })),
|
|
// ),
|
|
// };
|
|
// return new HttpSuccess([formattedData]);
|
|
// }
|
|
// case 2: {
|
|
// const data = await this.child1Repository.findOne({
|
|
// where: { id: idNode },
|
|
// relations: [
|
|
// "orgRevision",
|
|
// "orgChild2s",
|
|
// "orgChild2s.orgChild3s",
|
|
// "orgChild2s.orgChild3s.orgChild4s",
|
|
// ],
|
|
// });
|
|
// if (!data) {
|
|
// throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child1Id");
|
|
// }
|
|
|
|
// const formattedData = {
|
|
// departmentName: data.orgChild1Name,
|
|
// deptID: data.id,
|
|
// type: 2,
|
|
// // heads:
|
|
// totalPositionCount: await this.posMasterRepository.count({
|
|
// where: { orgChild1Id: data.id },
|
|
// }),
|
|
// totalPositionVacant:
|
|
// data.orgRevision.orgRevisionIsDraft == true
|
|
// ? await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgChild1Id: data.id,
|
|
// next_holderId: IsNull() || "",
|
|
// },
|
|
// })
|
|
// : await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgChild1Id: data.id,
|
|
// current_holderId: IsNull() || "",
|
|
// },
|
|
// }),
|
|
// // totalPositionCurrentVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgChild1Id: data.id,
|
|
// // current_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// // totalPositionNextVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgChild1Id: data.id,
|
|
// // next_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
|
|
// children: await Promise.all(
|
|
// data.orgChild2s
|
|
// .sort((a, b) => a.orgChild2Order - b.orgChild2Order)
|
|
// .map(async (orgChild2) => ({
|
|
// departmentName: orgChild2.orgChild2Name,
|
|
// deptID: orgChild2.id,
|
|
// type: 3,
|
|
// // heads:
|
|
// totalPositionCount: await this.posMasterRepository.count({
|
|
// where: { orgChild1Id: data.id, orgChild2Id: orgChild2.id },
|
|
// }),
|
|
// totalPositionVacant:
|
|
// data.orgRevision.orgRevisionIsDraft == true
|
|
// ? await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgChild1Id: data.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// next_holderId: IsNull() || "",
|
|
// },
|
|
// })
|
|
// : await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgChild1Id: data.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// current_holderId: IsNull() || "",
|
|
// },
|
|
// }),
|
|
// // totalPositionCurrentVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgChild1Id: data.id,
|
|
// // orgChild2Id: orgChild2.id,
|
|
// // current_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// // totalPositionNextVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgChild1Id: data.id,
|
|
// // orgChild2Id: orgChild2.id,
|
|
// // next_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// children: await Promise.all(
|
|
// orgChild2.orgChild3s
|
|
// .sort((a, b) => a.orgChild3Order - b.orgChild3Order)
|
|
// .map(async (orgChild3) => ({
|
|
// departmentName: orgChild3.orgChild3Name,
|
|
// deptID: orgChild3.id,
|
|
// type: 4,
|
|
// // heads:
|
|
// totalPositionCount: await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRevisionId: data.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// orgChild3Id: orgChild3.id,
|
|
// },
|
|
// }),
|
|
// totalPositionVacant:
|
|
// data.orgRevision.orgRevisionIsDraft == true
|
|
// ? await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRevisionId: data.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// orgChild3Id: orgChild3.id,
|
|
// next_holderId: IsNull() || "",
|
|
// },
|
|
// })
|
|
// : await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRevisionId: data.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// orgChild3Id: orgChild3.id,
|
|
// current_holderId: IsNull() || "",
|
|
// },
|
|
// }),
|
|
// // totalPositionCurrentVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgRevisionId: data.id,
|
|
// // orgChild2Id: orgChild2.id,
|
|
// // orgChild3Id: orgChild3.id,
|
|
// // current_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// // totalPositionNextVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgRevisionId: data.id,
|
|
// // orgChild2Id: orgChild2.id,
|
|
// // orgChild3Id: orgChild3.id,
|
|
// // next_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// children: await Promise.all(
|
|
// orgChild3.orgChild4s
|
|
// .sort((a, b) => a.orgChild4Order - b.orgChild4Order)
|
|
// .map(async (orgChild4) => ({
|
|
// departmentName: orgChild4.orgChild4Name,
|
|
// deptID: orgChild4.id,
|
|
// type: 5,
|
|
// // heads:
|
|
// totalPositionCount: await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRevisionId: data.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// orgChild3Id: orgChild3.id,
|
|
// orgChild4Id: orgChild4.id,
|
|
// },
|
|
// }),
|
|
// totalPositionVacant:
|
|
// data.orgRevision.orgRevisionIsDraft == true
|
|
// ? await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRevisionId: data.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// orgChild3Id: orgChild3.id,
|
|
// orgChild4Id: orgChild4.id,
|
|
// next_holderId: IsNull() || "",
|
|
// },
|
|
// })
|
|
// : await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgRevisionId: data.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// orgChild3Id: orgChild3.id,
|
|
// orgChild4Id: orgChild4.id,
|
|
// current_holderId: IsNull() || "",
|
|
// },
|
|
// }),
|
|
// // totalPositionCurrentVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgRevisionId: data.id,
|
|
// // orgChild2Id: orgChild2.id,
|
|
// // orgChild3Id: orgChild3.id,
|
|
// // orgChild4Id: orgChild4.id,
|
|
// // current_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// // totalPositionNextVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgRevisionId: data.id,
|
|
// // orgChild2Id: orgChild2.id,
|
|
// // orgChild3Id: orgChild3.id,
|
|
// // orgChild4Id: orgChild4.id,
|
|
// // next_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// })),
|
|
// ),
|
|
// })),
|
|
// ),
|
|
// })),
|
|
// ),
|
|
// };
|
|
// return new HttpSuccess([formattedData]);
|
|
// }
|
|
// case 3: {
|
|
// const data = await this.child2Repository.findOne({
|
|
// where: { id: idNode },
|
|
// relations: ["orgRevision", "orgChild3s", "orgChild3s.orgChild4s"],
|
|
// });
|
|
// if (!data) {
|
|
// throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child2Id");
|
|
// }
|
|
|
|
// const formattedData = {
|
|
// departmentName: data.orgChild2Name,
|
|
// deptID: data.id,
|
|
// type: 3,
|
|
// // heads:
|
|
// totalPositionCount: await this.posMasterRepository.count({
|
|
// where: { orgChild2Id: data.id },
|
|
// }),
|
|
// totalPositionVacant:
|
|
// data.orgRevision.orgRevisionIsDraft == true
|
|
// ? await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgChild2Id: data.id,
|
|
// next_holderId: IsNull() || "",
|
|
// },
|
|
// })
|
|
// : await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgChild2Id: data.id,
|
|
// current_holderId: IsNull() || "",
|
|
// },
|
|
// }),
|
|
// // totalPositionCurrentVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgChild2Id: data.id,
|
|
// // current_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// // totalPositionNextVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgChild2Id: data.id,
|
|
// // next_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
|
|
// children: await Promise.all(
|
|
// data.orgChild3s
|
|
// .sort((a, b) => a.orgChild3Order - b.orgChild3Order)
|
|
// .map(async (orgChild3) => ({
|
|
// departmentName: orgChild3.orgChild3Name,
|
|
// deptID: orgChild3.id,
|
|
// type: 4,
|
|
// // heads:
|
|
// totalPositionCount: await this.posMasterRepository.count({
|
|
// where: { orgChild2Id: data.id, orgChild3Id: orgChild3.id },
|
|
// }),
|
|
// totalPositionVacant:
|
|
// data.orgRevision.orgRevisionIsDraft == true
|
|
// ? await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgChild2Id: data.id,
|
|
// orgChild3Id: orgChild3.id,
|
|
// next_holderId: IsNull() || "",
|
|
// },
|
|
// })
|
|
// : await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgChild2Id: data.id,
|
|
// orgChild3Id: orgChild3.id,
|
|
// current_holderId: IsNull() || "",
|
|
// },
|
|
// }),
|
|
// // totalPositionCurrentVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgChild2Id: data.id,
|
|
// // orgChild3Id: orgChild3.id,
|
|
// // current_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// // totalPositionNextVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgChild2Id: data.id,
|
|
// // orgChild3Id: orgChild3.id,
|
|
// // next_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// children: await Promise.all(
|
|
// orgChild3.orgChild4s
|
|
// .sort((a, b) => a.orgChild4Order - b.orgChild4Order)
|
|
// .map(async (orgChild4) => ({
|
|
// departmentName: orgChild4.orgChild4Name,
|
|
// deptID: orgChild4.id,
|
|
// type: 5,
|
|
// // heads:
|
|
// totalPositionCount: await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgChild2Id: data.id,
|
|
// orgChild3Id: orgChild3.id,
|
|
// orgChild4Id: orgChild4.id,
|
|
// },
|
|
// }),
|
|
// totalPositionVacant:
|
|
// data.orgRevision.orgRevisionIsDraft == true
|
|
// ? await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgChild2Id: data.id,
|
|
// orgChild3Id: orgChild3.id,
|
|
// orgChild4Id: orgChild4.id,
|
|
// next_holderId: IsNull() || "",
|
|
// },
|
|
// })
|
|
// : await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgChild2Id: data.id,
|
|
// orgChild3Id: orgChild3.id,
|
|
// orgChild4Id: orgChild4.id,
|
|
// current_holderId: IsNull() || "",
|
|
// },
|
|
// }),
|
|
// // totalPositionCurrentVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgChild2Id: data.id,
|
|
// // orgChild3Id: orgChild3.id,
|
|
// // orgChild4Id: orgChild4.id,
|
|
// // current_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// // totalPositionNextVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgChild2Id: data.id,
|
|
// // orgChild3Id: orgChild3.id,
|
|
// // orgChild4Id: orgChild4.id,
|
|
// // next_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// })),
|
|
// ),
|
|
// })),
|
|
// ),
|
|
// };
|
|
// return new HttpSuccess([formattedData]);
|
|
// }
|
|
// case 4: {
|
|
// const data = await this.child3Repository.findOne({
|
|
// where: { id: idNode },
|
|
// relations: ["orgRevision", "orgChild4s"],
|
|
// });
|
|
// if (!data) {
|
|
// throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child3Id");
|
|
// }
|
|
|
|
// const formattedData = {
|
|
// departmentName: data.orgChild3Name,
|
|
// deptID: data.id,
|
|
// type: 4,
|
|
// // heads:
|
|
// totalPositionCount: await this.posMasterRepository.count({
|
|
// where: { orgChild3Id: data.id },
|
|
// }),
|
|
// totalPositionVacant:
|
|
// data.orgRevision.orgRevisionIsDraft == true
|
|
// ? await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgChild3Id: data.id,
|
|
// next_holderId: IsNull() || "",
|
|
// },
|
|
// })
|
|
// : await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgChild3Id: data.id,
|
|
// current_holderId: IsNull() || "",
|
|
// },
|
|
// }),
|
|
// // totalPositionCurrentVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgChild3Id: data.id,
|
|
// // current_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// // totalPositionNextVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgChild3Id: data.id,
|
|
// // next_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
|
|
// children: await Promise.all(
|
|
// data.orgChild4s
|
|
// .sort((a, b) => a.orgChild4Order - b.orgChild4Order)
|
|
// .map(async (orgChild4) => ({
|
|
// departmentName: orgChild4.orgChild4Name,
|
|
// deptID: orgChild4.id,
|
|
// type: 5,
|
|
// // heads:
|
|
// totalPositionCount: await this.posMasterRepository.count({
|
|
// where: { orgChild3Id: data.id, orgChild4Id: orgChild4.id },
|
|
// }),
|
|
// totalPositionVacant:
|
|
// data.orgRevision.orgRevisionIsDraft == true
|
|
// ? await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgChild3Id: data.id,
|
|
// orgChild4Id: orgChild4.id,
|
|
// next_holderId: IsNull() || "",
|
|
// },
|
|
// })
|
|
// : await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgChild3Id: data.id,
|
|
// orgChild4Id: orgChild4.id,
|
|
// current_holderId: IsNull() || "",
|
|
// },
|
|
// }),
|
|
// // totalPositionCurrentVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgChild3Id: data.id,
|
|
// // orgChild4Id: orgChild4.id,
|
|
// // current_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// // totalPositionNextVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgChild3Id: data.id,
|
|
// // orgChild4Id: orgChild4.id,
|
|
// // next_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// })),
|
|
// ),
|
|
// };
|
|
// return new HttpSuccess([formattedData]);
|
|
// }
|
|
// case 5: {
|
|
// const data = await this.child4Repository.findOne({
|
|
// where: { id: idNode },
|
|
// relations: ["orgRevision"],
|
|
// });
|
|
// if (!data) {
|
|
// throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child4Id");
|
|
// }
|
|
|
|
// const formattedData = {
|
|
// departmentName: data.orgChild4Name,
|
|
// deptID: data.id,
|
|
// type: 5,
|
|
// // heads:
|
|
// totalPositionCount: await this.posMasterRepository.count({
|
|
// where: { orgChild4Id: data.id },
|
|
// }),
|
|
// totalPositionVacant:
|
|
// data.orgRevision.orgRevisionIsDraft == true
|
|
// ? await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgChild4Id: data.id,
|
|
// next_holderId: IsNull() || "",
|
|
// },
|
|
// })
|
|
// : await this.posMasterRepository.count({
|
|
// where: {
|
|
// orgChild4Id: data.id,
|
|
// current_holderId: IsNull() || "",
|
|
// },
|
|
// }),
|
|
// // totalPositionCurrentVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgChild4Id: data.id,
|
|
// // current_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// // totalPositionNextVacant: await this.posMasterRepository.count({
|
|
// // where: {
|
|
// // orgChild4Id: data.id,
|
|
// // next_holderId: IsNull() || "",
|
|
// // },
|
|
// // }),
|
|
// };
|
|
// return new HttpSuccess([formattedData]);
|
|
// }
|
|
// default:
|
|
// throw new HttpError(HttpStatusCode.NOT_FOUND, "not found type: ");
|
|
// }
|
|
// }
|
|
|
|
/**
|
|
* API Organizational StructChart V2 (Optimized)
|
|
*
|
|
* @summary Organizational StructChart - Optimized with batch queries to prevent N+1 problem
|
|
*
|
|
*/
|
|
@Get("struct-chart/{idNode}/{type}")
|
|
async structchartV2(@Path() idNode: string, type: number) {
|
|
// Fetch orgRevisionId and isDraft status first
|
|
let orgRevisionId: string | null = null;
|
|
let isDraft = false;
|
|
|
|
switch (type) {
|
|
case 0:
|
|
const revision = await this.orgRevisionRepository.findOne({ where: { id: idNode } });
|
|
orgRevisionId = revision?.id || null;
|
|
isDraft = revision?.orgRevisionIsDraft || false;
|
|
break;
|
|
case 1: {
|
|
const root = await this.orgRootRepository.findOne({
|
|
where: { id: idNode },
|
|
relations: ["orgRevision"],
|
|
});
|
|
orgRevisionId = root?.orgRevision?.id || null;
|
|
isDraft = root?.orgRevision?.orgRevisionIsDraft || false;
|
|
break;
|
|
}
|
|
case 2: {
|
|
const child1 = await this.child1Repository.findOne({
|
|
where: { id: idNode },
|
|
relations: ["orgRevision"],
|
|
});
|
|
orgRevisionId = child1?.orgRevision?.id || null;
|
|
isDraft = child1?.orgRevision?.orgRevisionIsDraft || false;
|
|
break;
|
|
}
|
|
case 3: {
|
|
const child2 = await this.child2Repository.findOne({
|
|
where: { id: idNode },
|
|
relations: ["orgRevision"],
|
|
});
|
|
orgRevisionId = child2?.orgRevision?.id || null;
|
|
isDraft = child2?.orgRevision?.orgRevisionIsDraft || false;
|
|
break;
|
|
}
|
|
case 4: {
|
|
const child3 = await this.child3Repository.findOne({
|
|
where: { id: idNode },
|
|
relations: ["orgRevision"],
|
|
});
|
|
orgRevisionId = child3?.orgRevision?.id || null;
|
|
isDraft = child3?.orgRevision?.orgRevisionIsDraft || false;
|
|
break;
|
|
}
|
|
case 5: {
|
|
const child4 = await this.child4Repository.findOne({
|
|
where: { id: idNode },
|
|
relations: ["orgRevision"],
|
|
});
|
|
orgRevisionId = child4?.orgRevision?.id || null;
|
|
isDraft = child4?.orgRevision?.orgRevisionIsDraft || false;
|
|
break;
|
|
}
|
|
default:
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found type: ");
|
|
}
|
|
|
|
if (!orgRevisionId) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found revision");
|
|
}
|
|
|
|
// Fetch all position counts in a single batch query (optimized)
|
|
const positionCounts = await getPositionCountsAggregated(orgRevisionId);
|
|
|
|
switch (type) {
|
|
case 0: {
|
|
const data = await this.orgRevisionRepository.findOne({
|
|
where: { id: idNode },
|
|
relations: [
|
|
"orgRoots",
|
|
"orgRoots.orgChild1s",
|
|
"orgRoots.orgChild1s.orgChild2s",
|
|
"orgRoots.orgChild1s.orgChild2s.orgChild3s",
|
|
"orgRoots.orgChild1s.orgChild2s.orgChild3s.orgChild4s",
|
|
],
|
|
});
|
|
if (!data) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found revision");
|
|
}
|
|
|
|
const formattedData = {
|
|
departmentName: data.orgRevisionName,
|
|
deptID: data.id,
|
|
type: 0,
|
|
totalPositionCount: this.sumAllCounts(positionCounts.orgRootMap),
|
|
totalPositionVacant: this.sumAllVacantCounts(positionCounts.orgRootMap, isDraft),
|
|
children: this.buildOrgRoots(data.orgRoots, positionCounts, isDraft),
|
|
};
|
|
return new HttpSuccess([formattedData]);
|
|
}
|
|
case 1: {
|
|
const data = await this.orgRootRepository.findOne({
|
|
where: { id: idNode },
|
|
relations: [
|
|
"orgRevision",
|
|
"orgChild1s",
|
|
"orgChild1s.orgChild2s",
|
|
"orgChild1s.orgChild2s.orgChild3s",
|
|
"orgChild1s.orgChild2s.orgChild3s.orgChild4s",
|
|
],
|
|
});
|
|
if (!data) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found rootId");
|
|
}
|
|
|
|
const rootCounts = getPositionCount(positionCounts.orgRootMap, data.id);
|
|
const formattedData = {
|
|
departmentName: data.orgRootName,
|
|
deptID: data.id,
|
|
type: 1,
|
|
totalPositionCount: rootCounts.totalCount,
|
|
totalPositionVacant: isDraft ? rootCounts.nextVacantCount : rootCounts.currentVacantCount,
|
|
children: this.buildOrgChild1s(data.orgChild1s, positionCounts, isDraft),
|
|
};
|
|
return new HttpSuccess([formattedData]);
|
|
}
|
|
case 2: {
|
|
const data = await this.child1Repository.findOne({
|
|
where: { id: idNode },
|
|
relations: [
|
|
"orgRevision",
|
|
"orgChild2s",
|
|
"orgChild2s.orgChild3s",
|
|
"orgChild2s.orgChild3s.orgChild4s",
|
|
],
|
|
});
|
|
if (!data) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child1Id");
|
|
}
|
|
|
|
const child1Counts = getPositionCount(positionCounts.orgChild1Map, data.id);
|
|
const formattedData = {
|
|
departmentName: data.orgChild1Name,
|
|
deptID: data.id,
|
|
type: 2,
|
|
totalPositionCount: child1Counts.totalCount,
|
|
totalPositionVacant: isDraft
|
|
? child1Counts.nextVacantCount
|
|
: child1Counts.currentVacantCount,
|
|
children: this.buildOrgChild2s(data.orgChild2s, positionCounts, isDraft),
|
|
};
|
|
return new HttpSuccess([formattedData]);
|
|
}
|
|
case 3: {
|
|
const data = await this.child2Repository.findOne({
|
|
where: { id: idNode },
|
|
relations: ["orgRevision", "orgChild3s", "orgChild3s.orgChild4s"],
|
|
});
|
|
if (!data) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child2Id");
|
|
}
|
|
|
|
const child2Counts = getPositionCount(positionCounts.orgChild2Map, data.id);
|
|
const formattedData = {
|
|
departmentName: data.orgChild2Name,
|
|
deptID: data.id,
|
|
type: 3,
|
|
totalPositionCount: child2Counts.totalCount,
|
|
totalPositionVacant: isDraft
|
|
? child2Counts.nextVacantCount
|
|
: child2Counts.currentVacantCount,
|
|
children: this.buildOrgChild3s(data.orgChild3s, positionCounts, isDraft),
|
|
};
|
|
return new HttpSuccess([formattedData]);
|
|
}
|
|
case 4: {
|
|
const data = await this.child3Repository.findOne({
|
|
where: { id: idNode },
|
|
relations: ["orgRevision", "orgChild4s"],
|
|
});
|
|
if (!data) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child3Id");
|
|
}
|
|
|
|
const child3Counts = getPositionCount(positionCounts.orgChild3Map, data.id);
|
|
const formattedData = {
|
|
departmentName: data.orgChild3Name,
|
|
deptID: data.id,
|
|
type: 4,
|
|
totalPositionCount: child3Counts.totalCount,
|
|
totalPositionVacant: isDraft
|
|
? child3Counts.nextVacantCount
|
|
: child3Counts.currentVacantCount,
|
|
children: this.buildOrgChild4s(data.orgChild4s, positionCounts, isDraft),
|
|
};
|
|
return new HttpSuccess([formattedData]);
|
|
}
|
|
case 5: {
|
|
const data = await this.child4Repository.findOne({
|
|
where: { id: idNode },
|
|
relations: ["orgRevision"],
|
|
});
|
|
if (!data) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child4Id");
|
|
}
|
|
|
|
const child4Counts = getPositionCount(positionCounts.orgChild4Map, data.id);
|
|
const formattedData = {
|
|
departmentName: data.orgChild4Name,
|
|
deptID: data.id,
|
|
type: 5,
|
|
totalPositionCount: child4Counts.totalCount,
|
|
totalPositionVacant: isDraft
|
|
? child4Counts.nextVacantCount
|
|
: child4Counts.currentVacantCount,
|
|
};
|
|
return new HttpSuccess([formattedData]);
|
|
}
|
|
default:
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found type: ");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* API เช็ค node
|
|
*
|
|
* @summary เช็ค node (ADMIN)
|
|
*
|
|
*/
|
|
@Post("find/node")
|
|
async findNodeAll(@Body() requestBody: { node: number; nodeId: string }) {
|
|
switch (requestBody.node) {
|
|
case 0: {
|
|
const data = await this.orgRootRepository.findOne({
|
|
where: { id: requestBody.nodeId },
|
|
});
|
|
if (data == null) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found rootId.");
|
|
}
|
|
return new HttpSuccess([data.id]);
|
|
}
|
|
case 1: {
|
|
const data = await this.child1Repository.findOne({
|
|
where: { id: requestBody.nodeId },
|
|
});
|
|
if (data == null) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child1.");
|
|
}
|
|
return new HttpSuccess([data.orgRootId, data.id]);
|
|
}
|
|
case 2: {
|
|
const data = await this.child2Repository.findOne({
|
|
where: { id: requestBody.nodeId },
|
|
});
|
|
if (data == null) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child2.");
|
|
}
|
|
return new HttpSuccess([data.orgRootId, data.orgChild1Id, data.id]);
|
|
}
|
|
case 3: {
|
|
const data = await this.child3Repository.findOne({
|
|
where: { id: requestBody.nodeId },
|
|
});
|
|
if (data == null) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child3.");
|
|
}
|
|
return new HttpSuccess([data.orgRootId, data.orgChild1Id, data.orgChild2Id, data.id]);
|
|
}
|
|
case 4: {
|
|
const data = await this.child4Repository.findOne({
|
|
where: { id: requestBody.nodeId },
|
|
});
|
|
if (data == null) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child4.");
|
|
}
|
|
return new HttpSuccess([
|
|
data.orgRootId,
|
|
data.orgChild1Id,
|
|
data.orgChild2Id,
|
|
data.orgChild3Id,
|
|
data.id,
|
|
]);
|
|
}
|
|
default:
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found type: " + requestBody.node);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* API เช็ค node
|
|
*
|
|
* @summary เช็ค node (ADMIN)
|
|
*
|
|
*/
|
|
@Post("find/node-all")
|
|
async findNodeAllOrg(@Body() requestBody: { node: number | null; nodeId: string | null }) {
|
|
let orgRootRankSub1 = ["BUREAU", "OFFICE"];
|
|
let orgRootRankSub2 = ["DISTRICT"];
|
|
let data1: any;
|
|
let data2: any;
|
|
switch (requestBody.node) {
|
|
case 0: {
|
|
const _data1 = await this.orgRootRepository.find({
|
|
where: {
|
|
id: requestBody.nodeId ?? "",
|
|
orgRootRankSub: In(orgRootRankSub1),
|
|
},
|
|
order: { orgRootOrder: "ASC" },
|
|
});
|
|
const _data2 = await this.orgRootRepository.find({
|
|
where: [
|
|
{
|
|
id: requestBody.nodeId ?? "",
|
|
orgRootRankSub: In(orgRootRankSub2),
|
|
},
|
|
{
|
|
id: requestBody.nodeId ?? "",
|
|
orgRootRankSub: IsNull(),
|
|
},
|
|
],
|
|
order: { orgRootOrder: "ASC" },
|
|
});
|
|
data1 = _data1.map((y) => ({
|
|
name: y.orgRootName,
|
|
rootId: y.id,
|
|
rootDnaId: y.ancestorDNA,
|
|
child1Id: null,
|
|
child1DnaId: null,
|
|
child2Id: null,
|
|
child2DnaId: null,
|
|
child3Id: null,
|
|
child3DnaId: null,
|
|
child4Id: null,
|
|
child4DnaId: null,
|
|
}));
|
|
data2 = _data2.map((y) => ({
|
|
name: y.orgRootName,
|
|
rootId: y.id,
|
|
rootDnaId: y.ancestorDNA,
|
|
child1Id: null,
|
|
child1DnaId: null,
|
|
child2Id: null,
|
|
child2DnaId: null,
|
|
child3Id: null,
|
|
child3DnaId: null,
|
|
child4Id: null,
|
|
child4DnaId: null,
|
|
}));
|
|
break;
|
|
}
|
|
case 1: {
|
|
const _data1 = await this.child1Repository.find({
|
|
where: {
|
|
id: requestBody.nodeId ?? "",
|
|
orgRoot: {
|
|
orgRootRankSub: In(orgRootRankSub1),
|
|
},
|
|
},
|
|
order: {
|
|
orgRoot: { orgRootOrder: "ASC" },
|
|
},
|
|
relations: ["orgRoot"],
|
|
});
|
|
const _data2 = await this.child1Repository.find({
|
|
where: [
|
|
{
|
|
id: requestBody.nodeId ?? "",
|
|
orgRoot: {
|
|
orgRootRankSub: In(orgRootRankSub2),
|
|
},
|
|
},
|
|
{
|
|
id: requestBody.nodeId ?? "",
|
|
orgRoot: {
|
|
orgRootRankSub: IsNull(),
|
|
},
|
|
},
|
|
],
|
|
order: {
|
|
orgRoot: { orgRootOrder: "ASC" },
|
|
},
|
|
relations: ["orgRoot"],
|
|
});
|
|
data1 = _data1.map((y) => ({
|
|
name: y.orgRoot.orgRootName,
|
|
rootId: y.orgRoot.id,
|
|
rootDnaId: y.orgRoot.ancestorDNA,
|
|
child1Id: y.id,
|
|
child1DnaId: y.ancestorDNA,
|
|
child2Id: null,
|
|
child2DnaId: null,
|
|
child3Id: null,
|
|
child3DnaId: null,
|
|
child4Id: null,
|
|
child4DnaId: null,
|
|
}));
|
|
data2 = _data2.map((y) => ({
|
|
name: y.orgRoot.orgRootName,
|
|
rootId: y.orgRoot.id,
|
|
rootDnaId: y.orgRoot.ancestorDNA,
|
|
child1Id: y.id,
|
|
child1DnaId: y.ancestorDNA,
|
|
child2Id: null,
|
|
child2DnaId: null,
|
|
child3Id: null,
|
|
child3DnaId: null,
|
|
child4Id: null,
|
|
child4DnaId: null,
|
|
}));
|
|
break;
|
|
}
|
|
case 2: {
|
|
const _data1 = await this.child2Repository.find({
|
|
where: {
|
|
id: requestBody.nodeId ?? "",
|
|
orgRoot: {
|
|
orgRootRankSub: In(orgRootRankSub1),
|
|
},
|
|
},
|
|
order: {
|
|
orgRoot: { orgRootOrder: "ASC" },
|
|
},
|
|
relations: ["orgRoot", "orgChild1"],
|
|
});
|
|
const _data2 = await this.child2Repository.find({
|
|
where: [
|
|
{
|
|
id: requestBody.nodeId ?? "",
|
|
orgRoot: {
|
|
orgRootRankSub: In(orgRootRankSub2),
|
|
},
|
|
},
|
|
{
|
|
id: requestBody.nodeId ?? "",
|
|
orgRoot: {
|
|
orgRootRankSub: IsNull(),
|
|
},
|
|
},
|
|
],
|
|
order: {
|
|
orgRoot: { orgRootOrder: "ASC" },
|
|
},
|
|
relations: ["orgRoot", "orgChild1"],
|
|
});
|
|
data1 = _data1.map((y) => ({
|
|
name: y.orgRoot.orgRootName,
|
|
rootId: y.orgRoot.id,
|
|
rootDnaId: y.orgRoot.ancestorDNA,
|
|
child1Id: y.orgChild1.id,
|
|
child1DnaId: y.orgChild1.ancestorDNA,
|
|
child2Id: y.id,
|
|
child2DnaId: y.ancestorDNA,
|
|
child3Id: null,
|
|
child3DnaId: null,
|
|
child4Id: null,
|
|
child4DnaId: null,
|
|
}));
|
|
data2 = _data2.map((y) => ({
|
|
name: y.orgRoot.orgRootName,
|
|
rootId: y.orgRoot.id,
|
|
rootDnaId: y.orgRoot.ancestorDNA,
|
|
child1Id: y.orgChild1.id,
|
|
child1DnaId: y.orgChild1.ancestorDNA,
|
|
child2Id: y.id,
|
|
child2DnaId: y.ancestorDNA,
|
|
child3Id: null,
|
|
child3DnaId: null,
|
|
child4Id: null,
|
|
child4DnaId: null,
|
|
}));
|
|
break;
|
|
}
|
|
case 3: {
|
|
const _data1 = await this.child3Repository.find({
|
|
where: {
|
|
id: requestBody.nodeId ?? "",
|
|
orgRoot: {
|
|
orgRootRankSub: In(orgRootRankSub1),
|
|
},
|
|
},
|
|
order: {
|
|
orgRoot: { orgRootOrder: "ASC" },
|
|
},
|
|
relations: ["orgRoot", "orgChild1", "orgChild2"],
|
|
});
|
|
const _data2 = await this.child3Repository.find({
|
|
where: [
|
|
{
|
|
id: requestBody.nodeId ?? "",
|
|
orgRoot: {
|
|
orgRootRankSub: In(orgRootRankSub2),
|
|
},
|
|
},
|
|
{
|
|
id: requestBody.nodeId ?? "",
|
|
orgRoot: {
|
|
orgRootRankSub: IsNull(),
|
|
},
|
|
},
|
|
],
|
|
order: {
|
|
orgRoot: { orgRootOrder: "ASC" },
|
|
},
|
|
relations: ["orgRoot", "orgChild1", "orgChild2"],
|
|
});
|
|
data1 = _data1.map((y) => ({
|
|
name: y.orgRoot.orgRootName,
|
|
rootId: y.orgRoot.id,
|
|
rootDnaId: y.orgRoot.ancestorDNA,
|
|
child1Id: y.orgChild1.id,
|
|
child1DnaId: y.orgChild1.ancestorDNA,
|
|
child2Id: y.orgChild2.id,
|
|
child2DnaId: y.orgChild2.ancestorDNA,
|
|
child3Id: y.id,
|
|
child3DnaId: y.ancestorDNA,
|
|
child4Id: null,
|
|
child4DnaId: null,
|
|
}));
|
|
data2 = _data2.map((y) => ({
|
|
name: y.orgRoot.orgRootName,
|
|
rootId: y.orgRoot.id,
|
|
rootDnaId: y.orgRoot.ancestorDNA,
|
|
child1Id: y.orgChild1.id,
|
|
child1DnaId: y.orgChild1.ancestorDNA,
|
|
child2Id: y.orgChild2.id,
|
|
child2DnaId: y.orgChild2.ancestorDNA,
|
|
child3Id: y.id,
|
|
child3DnaId: y.ancestorDNA,
|
|
child4Id: null,
|
|
child4DnaId: null,
|
|
}));
|
|
break;
|
|
}
|
|
case 4: {
|
|
const _data1 = await this.child4Repository.find({
|
|
where: {
|
|
id: requestBody.nodeId ?? "",
|
|
orgRoot: {
|
|
orgRootRankSub: In(orgRootRankSub1),
|
|
},
|
|
},
|
|
order: {
|
|
orgRoot: { orgRootOrder: "ASC" },
|
|
},
|
|
relations: ["orgRoot", "orgChild1", "orgChild2", "orgChild3"],
|
|
});
|
|
const _data2 = await this.child4Repository.find({
|
|
where: [
|
|
{
|
|
id: requestBody.nodeId ?? "",
|
|
orgRoot: {
|
|
orgRootRankSub: In(orgRootRankSub2),
|
|
},
|
|
},
|
|
{
|
|
id: requestBody.nodeId ?? "",
|
|
orgRoot: {
|
|
orgRootRankSub: IsNull(),
|
|
},
|
|
},
|
|
],
|
|
order: {
|
|
orgRoot: { orgRootOrder: "ASC" },
|
|
},
|
|
relations: ["orgRoot", "orgChild1", "orgChild2", "orgChild3"],
|
|
});
|
|
data1 = _data1.map((y) => ({
|
|
name: y.orgRoot.orgRootName,
|
|
rootId: y.orgRoot.id,
|
|
rootDnaId: y.orgRoot.ancestorDNA,
|
|
child1Id: y.orgChild1.id,
|
|
child1DnaId: y.orgChild1.ancestorDNA,
|
|
child2Id: y.orgChild2.id,
|
|
child2DnaId: y.orgChild2.ancestorDNA,
|
|
child3Id: y.orgChild3.id,
|
|
child3DnaId: y.orgChild3.ancestorDNA,
|
|
child4Id: y.id,
|
|
child4DnaId: y.ancestorDNA,
|
|
}));
|
|
data2 = _data2.map((y) => ({
|
|
name: y.orgRoot.orgRootName,
|
|
rootId: y.orgRoot.id,
|
|
rootDnaId: y.orgRoot.ancestorDNA,
|
|
child1Id: y.orgChild1.id,
|
|
child1DnaId: y.orgChild1.ancestorDNA,
|
|
child2Id: y.orgChild2.id,
|
|
child2DnaId: y.orgChild2.ancestorDNA,
|
|
child3Id: y.orgChild3.id,
|
|
child3DnaId: y.orgChild3.ancestorDNA,
|
|
child4Id: y.id,
|
|
child4DnaId: y.ancestorDNA,
|
|
}));
|
|
break;
|
|
}
|
|
default: {
|
|
const orgRevision = await this.orgRevisionRepository.findOne({
|
|
where: {
|
|
orgRevisionIsCurrent: true,
|
|
orgRevisionIsDraft: false,
|
|
},
|
|
});
|
|
const _data1 = await this.orgRootRepository.find({
|
|
where: {
|
|
orgRevisionId: orgRevision?.id,
|
|
orgRootRankSub: In(orgRootRankSub1),
|
|
},
|
|
order: { orgRootOrder: "ASC" },
|
|
});
|
|
const _data2 = await this.orgRootRepository.find({
|
|
where: [
|
|
{
|
|
orgRevisionId: orgRevision?.id,
|
|
orgRootRankSub: In(orgRootRankSub2),
|
|
},
|
|
{
|
|
orgRevisionId: orgRevision?.id,
|
|
orgRootRankSub: IsNull(),
|
|
},
|
|
],
|
|
order: { orgRootOrder: "ASC" },
|
|
});
|
|
data1 = _data1.map((y) => ({
|
|
name: y.orgRootName,
|
|
rootId: y.id,
|
|
rootDnaId: y.ancestorDNA,
|
|
child1Id: null,
|
|
child2Id: null,
|
|
child3Id: null,
|
|
child4Id: null,
|
|
}));
|
|
data2 = _data2.map((y) => ({
|
|
name: y.orgRootName,
|
|
rootId: y.id,
|
|
rootDnaId: y.ancestorDNA,
|
|
child1Id: null,
|
|
child2Id: null,
|
|
child3Id: null,
|
|
child4Id: null,
|
|
}));
|
|
}
|
|
}
|
|
return new HttpSuccess({ isRootTrue: data1, isRootFalse: data2 });
|
|
}
|
|
|
|
/**
|
|
* API เช็ค node detail
|
|
*
|
|
* @summary เช็ค node detail (ADMIN)
|
|
*
|
|
*/
|
|
@Post("find/all")
|
|
async findNodeAllDetail(@Body() requestBody: { node: number; nodeId: string }) {
|
|
switch (requestBody.node) {
|
|
case 0: {
|
|
const data = await this.orgRootRepository.findOne({
|
|
where: { id: requestBody.nodeId },
|
|
});
|
|
if (data == null) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found rootId.");
|
|
}
|
|
return new HttpSuccess({
|
|
rootId: data.id,
|
|
rootDnaId: data.ancestorDNA,
|
|
root: data.orgRootName,
|
|
rootShortName: data.orgRootShortName,
|
|
});
|
|
}
|
|
case 1: {
|
|
const data = await this.child1Repository.findOne({
|
|
where: { id: requestBody.nodeId },
|
|
relations: {
|
|
orgRoot: true,
|
|
},
|
|
});
|
|
if (data == null) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child1.");
|
|
}
|
|
return new HttpSuccess({
|
|
rootId: data.orgRootId,
|
|
rootDnaId: data.orgRoot == null ? null : data.orgRoot.ancestorDNA,
|
|
root: data.orgRoot == null ? null : data.orgRoot.orgRootName,
|
|
rootShortName: data.orgRoot == null ? null : data.orgRoot.orgRootShortName,
|
|
child1Id: data.id,
|
|
child1DnaId: data.ancestorDNA,
|
|
child1: data.orgChild1Name,
|
|
child1ShortName: data.orgChild1ShortName,
|
|
});
|
|
}
|
|
case 2: {
|
|
const data = await this.child2Repository.findOne({
|
|
where: { id: requestBody.nodeId },
|
|
relations: {
|
|
orgRoot: true,
|
|
orgChild1: true,
|
|
},
|
|
});
|
|
if (data == null) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child2.");
|
|
}
|
|
return new HttpSuccess({
|
|
rootId: data.orgRootId,
|
|
rootDnaId: data.orgRoot == null ? null : data.orgRoot.ancestorDNA,
|
|
root: data.orgRoot == null ? null : data.orgRoot.orgRootName,
|
|
rootShortName: data.orgRoot == null ? null : data.orgRoot.orgRootShortName,
|
|
child1Id: data.orgChild1Id,
|
|
child1DnaId: data.orgChild1 == null ? null : data.orgChild1.ancestorDNA,
|
|
child1: data.orgChild1 == null ? null : data.orgChild1.orgChild1Name,
|
|
child1ShortName: data.orgChild1 == null ? null : data.orgChild1.orgChild1ShortName,
|
|
child2Id: data.id,
|
|
child2DnaId: data.ancestorDNA,
|
|
child2: data.orgChild2Name,
|
|
child2ShortName: data.orgChild2ShortName,
|
|
});
|
|
}
|
|
case 3: {
|
|
const data = await this.child3Repository.findOne({
|
|
where: { id: requestBody.nodeId },
|
|
relations: {
|
|
orgRoot: true,
|
|
orgChild1: true,
|
|
orgChild2: true,
|
|
},
|
|
});
|
|
if (data == null) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child3.");
|
|
}
|
|
return new HttpSuccess({
|
|
rootId: data.orgRootId,
|
|
rootDnaId: data.orgRoot == null ? null : data.orgRoot.ancestorDNA,
|
|
root: data.orgRoot == null ? null : data.orgRoot.orgRootName,
|
|
rootShortName: data.orgRoot == null ? null : data.orgRoot.orgRootShortName,
|
|
child1Id: data.orgChild1Id,
|
|
child1DnaId: data.orgChild1 == null ? null : data.orgChild1.ancestorDNA,
|
|
child1: data.orgChild1 == null ? null : data.orgChild1.orgChild1Name,
|
|
child1ShortName: data.orgChild1 == null ? null : data.orgChild1.orgChild1ShortName,
|
|
child2Id: data.orgChild2Id,
|
|
child2DnaId: data.orgChild2 == null ? null : data.orgChild2.ancestorDNA,
|
|
child2: data.orgChild2 == null ? null : data.orgChild2.orgChild2Name,
|
|
child2ShortName: data.orgChild2 == null ? null : data.orgChild2.orgChild2ShortName,
|
|
child3Id: data.id,
|
|
child3DnaId: data.ancestorDNA,
|
|
child3: data.orgChild3Name,
|
|
child3ShortName: data.orgChild3ShortName,
|
|
});
|
|
}
|
|
case 4: {
|
|
const data = await this.child4Repository.findOne({
|
|
where: { id: requestBody.nodeId },
|
|
relations: {
|
|
orgRoot: true,
|
|
orgChild1: true,
|
|
orgChild2: true,
|
|
orgChild3: true,
|
|
},
|
|
});
|
|
if (data == null) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child4.");
|
|
}
|
|
return new HttpSuccess({
|
|
rootId: data.orgRootId,
|
|
rootDnaId: data.orgRoot == null ? null : data.orgRoot.ancestorDNA,
|
|
root: data.orgRoot == null ? null : data.orgRoot.orgRootName,
|
|
rootShortName: data.orgRoot == null ? null : data.orgRoot.orgRootShortName,
|
|
child1Id: data.orgChild1Id,
|
|
child1DnaId: data.orgChild1 == null ? null : data.orgChild1.ancestorDNA,
|
|
child1: data.orgChild1 == null ? null : data.orgChild1.orgChild1Name,
|
|
child1ShortName: data.orgChild1 == null ? null : data.orgChild1.orgChild1ShortName,
|
|
child2Id: data.orgChild2Id,
|
|
child2DnaId: data.orgChild2 == null ? null : data.orgChild2.ancestorDNA,
|
|
child2: data.orgChild2 == null ? null : data.orgChild2.orgChild2Name,
|
|
child2ShortName: data.orgChild2 == null ? null : data.orgChild2.orgChild2ShortName,
|
|
child3Id: data.orgChild3Id,
|
|
child3DnaId: data.orgChild3 == null ? null : data.orgChild3.ancestorDNA,
|
|
child3: data.orgChild3 == null ? null : data.orgChild3.orgChild3Name,
|
|
child3ShortName: data.orgChild3 == null ? null : data.orgChild3.orgChild3ShortName,
|
|
child4Id: data.id,
|
|
child4DnaId: data.ancestorDNA,
|
|
child4: data.orgChild4Name,
|
|
child4ShortName: data.orgChild4ShortName,
|
|
});
|
|
}
|
|
default:
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found type: " + requestBody.node);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* API เช็ค node detail
|
|
*
|
|
* @summary เช็ค node detail (ADMIN)
|
|
*
|
|
*/
|
|
@Post("find/allv2")
|
|
async findNodeAllDetailV2(@Body() requestBody: { node: number; nodeId: string }) {
|
|
switch (requestBody.node) {
|
|
case 0: {
|
|
const data = await this.orgRootRepository.findOne({
|
|
where: { ancestorDNA: requestBody.nodeId },
|
|
order: { createdAt: "DESC" },
|
|
});
|
|
if (data == null) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found rootId.");
|
|
}
|
|
return new HttpSuccess({
|
|
rootId: data.id,
|
|
rootDnaId: data.ancestorDNA,
|
|
root: data.orgRootName,
|
|
rootShortName: data.orgRootShortName,
|
|
});
|
|
}
|
|
case 1: {
|
|
const data = await this.child1Repository.findOne({
|
|
where: { ancestorDNA: requestBody.nodeId },
|
|
relations: {
|
|
orgRoot: true,
|
|
},
|
|
order: { createdAt: "DESC" },
|
|
});
|
|
if (data == null) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child1.");
|
|
}
|
|
return new HttpSuccess({
|
|
rootId: data.orgRootId,
|
|
rootDnaId: data.orgRoot == null ? null : data.orgRoot.ancestorDNA,
|
|
root: data.orgRoot == null ? null : data.orgRoot.orgRootName,
|
|
rootShortName: data.orgRoot == null ? null : data.orgRoot.orgRootShortName,
|
|
child1Id: data.id,
|
|
child1DnaId: data.ancestorDNA,
|
|
child1: data.orgChild1Name,
|
|
child1ShortName: data.orgChild1ShortName,
|
|
});
|
|
}
|
|
case 2: {
|
|
const data = await this.child2Repository.findOne({
|
|
where: { ancestorDNA: requestBody.nodeId },
|
|
relations: {
|
|
orgRoot: true,
|
|
orgChild1: true,
|
|
},
|
|
order: { createdAt: "DESC" },
|
|
});
|
|
if (data == null) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child2.");
|
|
}
|
|
return new HttpSuccess({
|
|
rootId: data.orgRootId,
|
|
rootDnaId: data.orgRoot == null ? null : data.orgRoot.ancestorDNA,
|
|
root: data.orgRoot == null ? null : data.orgRoot.orgRootName,
|
|
rootShortName: data.orgRoot == null ? null : data.orgRoot.orgRootShortName,
|
|
child1Id: data.orgChild1Id,
|
|
child1DnaId: data.orgChild1 == null ? null : data.orgChild1.ancestorDNA,
|
|
child1: data.orgChild1 == null ? null : data.orgChild1.orgChild1Name,
|
|
child1ShortName: data.orgChild1 == null ? null : data.orgChild1.orgChild1ShortName,
|
|
child2Id: data.id,
|
|
child2DnaId: data.ancestorDNA,
|
|
child2: data.orgChild2Name,
|
|
child2ShortName: data.orgChild2ShortName,
|
|
});
|
|
}
|
|
case 3: {
|
|
const data = await this.child3Repository.findOne({
|
|
where: { ancestorDNA: requestBody.nodeId },
|
|
relations: {
|
|
orgRoot: true,
|
|
orgChild1: true,
|
|
orgChild2: true,
|
|
},
|
|
order: { createdAt: "DESC" },
|
|
});
|
|
if (data == null) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child3.");
|
|
}
|
|
return new HttpSuccess({
|
|
rootId: data.orgRootId,
|
|
rootDnaId: data.orgRoot == null ? null : data.orgRoot.ancestorDNA,
|
|
root: data.orgRoot == null ? null : data.orgRoot.orgRootName,
|
|
rootShortName: data.orgRoot == null ? null : data.orgRoot.orgRootShortName,
|
|
child1Id: data.orgChild1Id,
|
|
child1DnaId: data.orgChild1 == null ? null : data.orgChild1.ancestorDNA,
|
|
child1: data.orgChild1 == null ? null : data.orgChild1.orgChild1Name,
|
|
child1ShortName: data.orgChild1 == null ? null : data.orgChild1.orgChild1ShortName,
|
|
child2Id: data.orgChild2Id,
|
|
child2DnaId: data.orgChild2 == null ? null : data.orgChild2.ancestorDNA,
|
|
child2: data.orgChild2 == null ? null : data.orgChild2.orgChild2Name,
|
|
child2ShortName: data.orgChild2 == null ? null : data.orgChild2.orgChild2ShortName,
|
|
child3Id: data.id,
|
|
child3DnaId: data.ancestorDNA,
|
|
child3: data.orgChild3Name,
|
|
child3ShortName: data.orgChild3ShortName,
|
|
});
|
|
}
|
|
case 4: {
|
|
const data = await this.child4Repository.findOne({
|
|
where: { ancestorDNA: requestBody.nodeId },
|
|
relations: {
|
|
orgRoot: true,
|
|
orgChild1: true,
|
|
orgChild2: true,
|
|
orgChild3: true,
|
|
},
|
|
order: { createdAt: "DESC" },
|
|
});
|
|
if (data == null) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found child4.");
|
|
}
|
|
return new HttpSuccess({
|
|
rootId: data.orgRootId,
|
|
rootDnaId: data.orgRoot == null ? null : data.orgRoot.ancestorDNA,
|
|
root: data.orgRoot == null ? null : data.orgRoot.orgRootName,
|
|
rootShortName: data.orgRoot == null ? null : data.orgRoot.orgRootShortName,
|
|
child1Id: data.orgChild1Id,
|
|
child1DnaId: data.orgChild1 == null ? null : data.orgChild1.ancestorDNA,
|
|
child1: data.orgChild1 == null ? null : data.orgChild1.orgChild1Name,
|
|
child1ShortName: data.orgChild1 == null ? null : data.orgChild1.orgChild1ShortName,
|
|
child2Id: data.orgChild2Id,
|
|
child2DnaId: data.orgChild2 == null ? null : data.orgChild2.ancestorDNA,
|
|
child2: data.orgChild2 == null ? null : data.orgChild2.orgChild2Name,
|
|
child2ShortName: data.orgChild2 == null ? null : data.orgChild2.orgChild2ShortName,
|
|
child3Id: data.orgChild3Id,
|
|
child3DnaId: data.orgChild3 == null ? null : data.orgChild3.ancestorDNA,
|
|
child3: data.orgChild3 == null ? null : data.orgChild3.orgChild3Name,
|
|
child3ShortName: data.orgChild3 == null ? null : data.orgChild3.orgChild3ShortName,
|
|
child4Id: data.id,
|
|
child4DnaId: data.ancestorDNA,
|
|
child4: data.orgChild4Name,
|
|
child4ShortName: data.orgChild4ShortName,
|
|
});
|
|
}
|
|
default:
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "not found type: " + requestBody.node);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* API หาสำนักทั้งหมด
|
|
*
|
|
* @summary หาสำนักทั้งหมด
|
|
*
|
|
*/
|
|
@Get("active/root")
|
|
async GetActiveRoot() {
|
|
const orgRevisionActive = await this.orgRevisionRepository.findOne({
|
|
where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
|
|
});
|
|
if (!orgRevisionActive) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบโครงสร้างที่เผยแพร่อยู่ตอนนี้");
|
|
}
|
|
|
|
const data = await this.orgRootRepository.find({
|
|
where: { orgRevisionId: orgRevisionActive.id },
|
|
relations: [
|
|
"orgRevision",
|
|
"orgChild1s",
|
|
"orgChild1s.orgChild2s",
|
|
"orgChild1s.orgChild2s.orgChild3s",
|
|
"orgChild1s.orgChild2s.orgChild3s.orgChild4s",
|
|
],
|
|
order: {
|
|
orgChild1s: {
|
|
orgChild1Order: "ASC",
|
|
orgChild2s: {
|
|
orgChild2Order: "ASC",
|
|
orgChild3s: {
|
|
orgChild3Order: "ASC",
|
|
orgChild4s: {
|
|
orgChild4Order: "ASC",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
return new HttpSuccess(data);
|
|
}
|
|
|
|
/**
|
|
* API หาสำนักทั้งหมด
|
|
*
|
|
* @summary หาสำนักทั้งหมด
|
|
*
|
|
*/
|
|
@Get("active/root/id")
|
|
async GetActiveRootId() {
|
|
const orgRevisionActive = await this.orgRevisionRepository.findOne({
|
|
where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
|
|
});
|
|
if (!orgRevisionActive) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบโครงสร้างที่เผยแพร่อยู่ตอนนี้");
|
|
}
|
|
|
|
const data = await this.orgRootRepository.find({
|
|
where: { orgRevisionId: orgRevisionActive.id },
|
|
order: {
|
|
orgRootOrder: "ASC",
|
|
},
|
|
});
|
|
return new HttpSuccess(data.map((x) => x.id));
|
|
}
|
|
|
|
/**
|
|
* API หาสำนักทั้งหมด
|
|
*
|
|
* @summary หาสำนักทั้งหมด
|
|
*
|
|
*/
|
|
@Get("active/root/all")
|
|
async GetActiveRootAll() {
|
|
const orgRevisionActive = await this.orgRevisionRepository.findOne({
|
|
where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
|
|
});
|
|
if (!orgRevisionActive) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบโครงสร้างที่เผยแพร่อยู่ตอนนี้");
|
|
}
|
|
|
|
const data = await this.orgRootRepository.find({
|
|
where: {
|
|
orgRevisionId: orgRevisionActive.id,
|
|
id: In([
|
|
"d7e98989-b5ce-47d6-93c3-ab63ed486348",
|
|
"6f9b30e1-757a-40d5-b053-61eb1b91c0f0",
|
|
"eaf65f33-25e9-4956-9dba-5d909f5eb595",
|
|
"87c5bc89-300c-4b6a-99e4-26371436caa2",
|
|
"982d33af-4eb5-4cc8-9c9f-b3ccadbb66d7",
|
|
"e0545eca-5d0a-4a1c-8bbd-e3e25c2521db",
|
|
]),
|
|
},
|
|
order: {
|
|
orgRootOrder: "ASC",
|
|
},
|
|
});
|
|
return new HttpSuccess(data);
|
|
}
|
|
|
|
/**
|
|
* API
|
|
*
|
|
* @summary
|
|
*
|
|
*/
|
|
@Get("active/root/latest")
|
|
async GetActiveRootIdLatest() {
|
|
const orgRevisionActive = await this.orgRevisionRepository.findOne({
|
|
where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
|
|
});
|
|
if (!orgRevisionActive) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบโครงสร้างที่เผยแพร่อยู่ตอนนี้");
|
|
}
|
|
return new HttpSuccess(orgRevisionActive.id);
|
|
}
|
|
|
|
/**
|
|
* API หาสำนักทั้งหมด by revision
|
|
*
|
|
* @summary หาสำนักทั้งหมด by revision
|
|
*
|
|
*/
|
|
@Get("active/root/{revisionId}")
|
|
async GetActiveRootByRevision(@Path() revisionId: string) {
|
|
const rawData = await this.orgRootRepository.find({
|
|
where: { orgRevisionId: revisionId },
|
|
relations: [
|
|
"orgRevision",
|
|
"orgChild1s",
|
|
"orgChild1s.orgChild2s",
|
|
"orgChild1s.orgChild2s.orgChild3s",
|
|
"orgChild1s.orgChild2s.orgChild3s.orgChild4s",
|
|
],
|
|
order: {
|
|
orgRootOrder: "ASC",
|
|
orgChild1s: {
|
|
orgChild1Order: "ASC",
|
|
orgChild2s: {
|
|
orgChild2Order: "ASC",
|
|
orgChild3s: {
|
|
orgChild3Order: "ASC",
|
|
orgChild4s: {
|
|
orgChild4Order: "ASC",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
const data = rawData.map((item) => ({
|
|
...item,
|
|
orgRootCode: item.orgRootCode + "00",
|
|
}));
|
|
return new HttpSuccess(data);
|
|
}
|
|
/**
|
|
* API หา revision ล่าสุด
|
|
*
|
|
* @summary หา revision ล่าสุด
|
|
*
|
|
*/
|
|
@Get("revision/latest")
|
|
async salaryGen() {
|
|
const findRevision = await this.orgRevisionRepository.findOne({
|
|
where: { orgRevisionIsCurrent: true },
|
|
});
|
|
if (!findRevision) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบโครงสร้างล่าสุด");
|
|
}
|
|
return new HttpSuccess(findRevision.id);
|
|
}
|
|
|
|
/**
|
|
* API รายละเอียดโครงสร้าง
|
|
*
|
|
* @summary รายละเอียดโครงสร้าง (ADMIN)
|
|
*
|
|
*/
|
|
@Get("act/{id}")
|
|
async detailAct(@Path() id: string, @Request() request: RequestWithUser) {
|
|
let _data: OrgPermissionData = {
|
|
root: null,
|
|
child1: null,
|
|
child2: null,
|
|
child3: null,
|
|
child4: null,
|
|
};
|
|
// if (!request.user.role.includes("SUPER_ADMIN")) {
|
|
// _data = await new permission().PermissionOrgList(request, "SYS_ACTING");
|
|
// }
|
|
const _privilege = await new permission().PermissionOrgList(request, "SYS_ACTING");
|
|
|
|
const orgRevision = await this.orgRevisionRepository.findOne({ where: { id } });
|
|
if (!orgRevision) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูล");
|
|
}
|
|
|
|
const attrOwnership = _privilege.root === null ? true : false;
|
|
|
|
const profile = await this.profileRepo.findOne({
|
|
where: { keycloak: request.user.sub },
|
|
relations: ["permissionProfiles", "current_holders", "current_holders.posMasterAssigns"],
|
|
});
|
|
if (!profile) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผู้ใช้งานในทะเบียนประวัติ");
|
|
}
|
|
let profileAssign = profile.current_holders
|
|
?.find((x) => x.orgRevisionId === id)
|
|
?.posMasterAssigns.find((x) => x.assignId === "SYS_ORG");
|
|
|
|
if (orgRevision.orgRevisionIsDraft && !orgRevision.orgRevisionIsCurrent && !attrOwnership) {
|
|
if (Array.isArray(profile.permissionProfiles) && profile.permissionProfiles.length > 0) {
|
|
_data.root = profile.permissionProfiles.map((x) => x.orgRootId);
|
|
} else {
|
|
return new HttpSuccess({ remark: "", data: [] });
|
|
}
|
|
}
|
|
// กำหนดการเข้าถึงข้อมูลตามสถานะและสิทธิ์
|
|
const isCurrentActive = !orgRevision.orgRevisionIsDraft && orgRevision.orgRevisionIsCurrent;
|
|
if (isCurrentActive) {
|
|
if (profileAssign && _privilege.privilege !== "OWNER" && _privilege.privilege !== "PARENT") {
|
|
if (_privilege.privilege == "NORMAL") {
|
|
const holder = profile.current_holders.find((x) => x.orgRevisionId === id);
|
|
if (!holder) return new HttpSuccess({ remark: "", data: [] });
|
|
_data.root = [holder.orgRootId];
|
|
_data.child1 = [holder.orgChild1Id];
|
|
_data.child2 = [holder.orgChild2Id];
|
|
_data.child3 = [holder.orgChild3Id];
|
|
_data.child4 = [holder.orgChild4Id];
|
|
} else if (_privilege.privilege == "CHILD" || _privilege.privilege == "BROTHER") {
|
|
const holder = profile.current_holders.find((x) => x.orgRevisionId === id);
|
|
if (!holder) return new HttpSuccess({ remark: "", data: [] });
|
|
_data.root = [holder.orgRootId];
|
|
if (_privilege.root && _privilege.child1 === null) {
|
|
} else if (_privilege.child1 && _privilege.child2 === null) {
|
|
_data.child1 = [holder.orgChild1Id];
|
|
} else if (_privilege.child2 && _privilege.child3 === null) {
|
|
_data.child1 = [holder.orgChild1Id];
|
|
_data.child2 = [holder.orgChild2Id];
|
|
} else if (_privilege.child3 && _privilege.child4 === null) {
|
|
_data.child1 = [holder.orgChild1Id];
|
|
_data.child2 = [holder.orgChild2Id];
|
|
_data.child3 = [holder.orgChild3Id];
|
|
_data.child4 = [holder.orgChild4Id];
|
|
}
|
|
} else {
|
|
_data.root = [profile.current_holders.find((x) => x.orgRevisionId === id)?.orgRootId];
|
|
}
|
|
} else {
|
|
if (!attrOwnership) _data = _privilege;
|
|
}
|
|
}
|
|
|
|
const orgDna = await new permission().checkDna(request, request.user.sub);
|
|
let level: NodeLevel = resolveNodeLevel(orgDna);
|
|
|
|
const orgRootData = await AppDataSource.getRepository(OrgRoot)
|
|
.createQueryBuilder("orgRoot")
|
|
.select([
|
|
"orgRoot.id",
|
|
"orgRoot.orgRootName",
|
|
"orgRoot.orgRootShortName",
|
|
"orgRoot.orgRootCode",
|
|
"orgRoot.orgRootOrder",
|
|
])
|
|
.addSelect([
|
|
"posMasters.id",
|
|
"posMasters.posMasterNo",
|
|
"posMasters.orgChild1Id",
|
|
"posMasters.isDirector",
|
|
])
|
|
.addSelect(["current_holder.prefix", "current_holder.firstName", "current_holder.lastName"])
|
|
.where("orgRoot.orgRevisionId = :id", { id })
|
|
.andWhere(
|
|
_data.root != undefined && _data.root != null
|
|
? _data.root[0] != null
|
|
? `orgRoot.id IN (:...node)`
|
|
: `orgRoot.id is null`
|
|
: "1=1",
|
|
{
|
|
node: _data.root,
|
|
},
|
|
)
|
|
.leftJoin("orgRoot.posMasters", "posMasters")
|
|
.leftJoin("posMasters.current_holder", "current_holder")
|
|
.orderBy("orgRoot.orgRootOrder", "ASC")
|
|
.getMany();
|
|
|
|
const orgRootIds = orgRootData.map((orgRoot) => orgRoot.id) || null;
|
|
const orgChild1Data =
|
|
orgRootIds && orgRootIds.length > 0
|
|
? await AppDataSource.getRepository(OrgChild1)
|
|
.createQueryBuilder("orgChild1")
|
|
.select([
|
|
"orgChild1.id",
|
|
"orgChild1.orgRootId",
|
|
"orgChild1.orgChild1Name",
|
|
"orgChild1.orgChild1ShortName",
|
|
"orgChild1.orgChild1Code",
|
|
"orgChild1.orgChild1Order",
|
|
])
|
|
.addSelect([
|
|
"posMasters.id",
|
|
"posMasters.posMasterNo",
|
|
"posMasters.orgChild2Id",
|
|
"posMasters.isDirector",
|
|
])
|
|
.addSelect([
|
|
"current_holder.prefix",
|
|
"current_holder.firstName",
|
|
"current_holder.lastName",
|
|
])
|
|
.where("orgChild1.orgRootId IN (:...ids)", { ids: orgRootIds })
|
|
.andWhere(
|
|
_data.child1 != undefined && _data.child1 != null
|
|
? _data.child1[0] != null
|
|
? `orgChild1.id IN (:...node)`
|
|
: `orgChild1.id is null`
|
|
: "1=1",
|
|
{
|
|
node: _data.child1,
|
|
},
|
|
)
|
|
.leftJoin("orgChild1.posMasters", "posMasters")
|
|
.leftJoin("posMasters.current_holder", "current_holder")
|
|
.orderBy("orgChild1.orgChild1Order", "ASC")
|
|
.getMany()
|
|
: [];
|
|
|
|
const orgChild1Ids = orgChild1Data.map((orgChild1) => orgChild1.id) || null;
|
|
const orgChild2Data =
|
|
orgChild1Ids && orgChild1Ids.length > 0
|
|
? await AppDataSource.getRepository(OrgChild2)
|
|
.createQueryBuilder("orgChild2")
|
|
.select([
|
|
"orgChild2.id",
|
|
"orgChild2.orgChild1Id",
|
|
"orgChild2.orgChild2Name",
|
|
"orgChild2.orgChild2ShortName",
|
|
"orgChild2.orgChild2Code",
|
|
"orgChild2.orgChild2Order",
|
|
])
|
|
.addSelect([
|
|
"posMasters.id",
|
|
"posMasters.posMasterNo",
|
|
"posMasters.orgChild3Id",
|
|
"posMasters.isDirector",
|
|
])
|
|
.addSelect([
|
|
"current_holder.prefix",
|
|
"current_holder.firstName",
|
|
"current_holder.lastName",
|
|
])
|
|
.where("orgChild2.orgChild1Id IN (:...ids)", { ids: orgChild1Ids })
|
|
.andWhere(
|
|
_data.child2 != undefined && _data.child2 != null
|
|
? _data.child2[0] != null
|
|
? `orgChild2.id IN (:...node)`
|
|
: `orgChild2.id is null`
|
|
: "1=1",
|
|
{
|
|
node: _data.child2,
|
|
},
|
|
)
|
|
.leftJoin("orgChild2.posMasters", "posMasters")
|
|
.leftJoin("posMasters.current_holder", "current_holder")
|
|
.orderBy("orgChild2.orgChild2Order", "ASC")
|
|
.getMany()
|
|
: [];
|
|
|
|
const orgChild2Ids = orgChild2Data.map((orgChild2) => orgChild2.id) || null;
|
|
const orgChild3Data =
|
|
orgChild2Ids && orgChild2Ids.length > 0
|
|
? await AppDataSource.getRepository(OrgChild3)
|
|
.createQueryBuilder("orgChild3")
|
|
.select([
|
|
"orgChild3.id",
|
|
"orgChild3.orgChild2Id",
|
|
"orgChild3.orgChild3Name",
|
|
"orgChild3.orgChild3ShortName",
|
|
"orgChild3.orgChild3Code",
|
|
"orgChild3.orgChild3Order",
|
|
])
|
|
.addSelect([
|
|
"posMasters.id",
|
|
"posMasters.posMasterNo",
|
|
"posMasters.orgChild4Id",
|
|
"posMasters.isDirector",
|
|
])
|
|
.addSelect([
|
|
"current_holder.prefix",
|
|
"current_holder.firstName",
|
|
"current_holder.lastName",
|
|
])
|
|
.where("orgChild3.orgChild2Id IN (:...ids)", { ids: orgChild2Ids })
|
|
.andWhere(
|
|
_data.child3 != undefined && _data.child3 != null
|
|
? _data.child3[0] != null
|
|
? `orgChild3.id IN (:...node)`
|
|
: `orgChild3.id is null`
|
|
: "1=1",
|
|
{
|
|
node: _data.child3,
|
|
},
|
|
)
|
|
.leftJoin("orgChild3.posMasters", "posMasters")
|
|
.leftJoin("posMasters.current_holder", "current_holder")
|
|
.orderBy("orgChild3.orgChild3Order", "ASC")
|
|
.getMany()
|
|
: [];
|
|
|
|
const orgChild3Ids = orgChild3Data.map((orgChild3) => orgChild3.id) || null;
|
|
const orgChild4Data =
|
|
orgChild3Ids && orgChild3Ids.length > 0
|
|
? await AppDataSource.getRepository(OrgChild4)
|
|
.createQueryBuilder("orgChild4")
|
|
.select([
|
|
"orgChild4.id",
|
|
"orgChild4.orgChild3Id",
|
|
"orgChild4.orgChild4Name",
|
|
"orgChild4.orgChild4ShortName",
|
|
"orgChild4.orgChild4Code",
|
|
"orgChild4.orgChild4Order",
|
|
])
|
|
.addSelect(["posMasters.id", "posMasters.posMasterNo", "posMasters.isDirector"])
|
|
.addSelect([
|
|
"current_holder.prefix",
|
|
"current_holder.firstName",
|
|
"current_holder.lastName",
|
|
])
|
|
.where("orgChild4.orgChild3Id IN (:...ids)", { ids: orgChild3Ids })
|
|
.andWhere(
|
|
_data.child4 != undefined && _data.child4 != null
|
|
? _data.child4[0] != null
|
|
? `orgChild4.id IN (:...node)`
|
|
: `orgChild4.id is null`
|
|
: "1=1",
|
|
{
|
|
node: _data.child4,
|
|
},
|
|
)
|
|
.leftJoin("orgChild4.posMasters", "posMasters")
|
|
.leftJoin("posMasters.current_holder", "current_holder")
|
|
.orderBy("orgChild4.orgChild4Order", "ASC")
|
|
.getMany()
|
|
: [];
|
|
|
|
const cannotViewRootPosMaster =
|
|
_privilege.privilege === "PARENT" ||
|
|
(_privilege.privilege === "BROTHER" && level !== null && level > 1) ||
|
|
(_privilege.privilege === "CHILD" && level !== null && level > 0) ||
|
|
(_privilege.privilege === "NORMAL" && level !== null && level !== 0);
|
|
|
|
const cannotViewChild1PosMaster =
|
|
(_privilege.privilege === "PARENT" && level !== null && level > 1) ||
|
|
(_privilege.privilege === "BROTHER" && level !== null && level > 2) ||
|
|
(_privilege.privilege === "CHILD" && level !== null && level > 1) ||
|
|
(_privilege.privilege === "NORMAL" && level !== 1);
|
|
|
|
const cannotViewChild2PosMaster =
|
|
(_privilege.privilege === "PARENT" && level !== null && level > 2) ||
|
|
(_privilege.privilege === "BROTHER" && level !== null && level > 3) ||
|
|
(_privilege.privilege === "CHILD" && level !== null && level > 2) ||
|
|
(_privilege.privilege === "NORMAL" && level !== 2);
|
|
|
|
const cannotViewChild3PosMaster =
|
|
(_privilege.privilege === "PARENT" && level !== null && level > 3) ||
|
|
(_privilege.privilege === "BROTHER" && level !== null && level > 4) ||
|
|
(_privilege.privilege === "CHILD" && level !== null && level > 3) ||
|
|
(_privilege.privilege === "NORMAL" && level !== 3);
|
|
|
|
const cannotViewChild4PosMaster =
|
|
(_privilege.privilege === "PARENT" && level !== null && level > 4) ||
|
|
(_privilege.privilege === "CHILD" && level !== null && level > 4) ||
|
|
(_privilege.privilege === "NORMAL" && level !== 4);
|
|
|
|
const formattedData = orgRootData.map((orgRoot) => ({
|
|
orgTreeId: orgRoot.id,
|
|
orgLevel: 0,
|
|
orgName: orgRoot.orgRootName,
|
|
orgTreeName: orgRoot.orgRootName,
|
|
orgTreeShortName: orgRoot.orgRootShortName,
|
|
orgTreeCode: orgRoot.orgRootCode,
|
|
orgCode: orgRoot.orgRootCode + "00",
|
|
orgRootName: orgRoot.orgRootName,
|
|
labelName: generateLabelName(
|
|
orgRoot.orgRootName,
|
|
orgRoot.orgRootCode + "00",
|
|
orgRoot.orgRootShortName,
|
|
orgRoot.orgRootName,
|
|
orgRoot.orgRootCode,
|
|
orgRoot.orgRootShortName,
|
|
),
|
|
posMaster: cannotViewRootPosMaster
|
|
? []
|
|
: filterPosMasters(orgRoot.posMasters, "orgChild1Id").map((x) =>
|
|
formatPosMaster(x, orgRoot.orgRootShortName, orgRoot.id, 0),
|
|
),
|
|
children: orgChild1Data
|
|
.filter((orgChild1) => orgChild1.orgRootId === orgRoot.id)
|
|
.map((orgChild1) => ({
|
|
orgTreeId: orgChild1.id,
|
|
orgRootId: orgRoot.id,
|
|
orgLevel: 1,
|
|
orgName: `${orgChild1.orgChild1Name}/${orgRoot.orgRootName}`,
|
|
orgTreeName: orgChild1.orgChild1Name,
|
|
orgTreeShortName: orgChild1.orgChild1ShortName,
|
|
orgTreeCode: orgChild1.orgChild1Code,
|
|
orgCode: orgRoot.orgRootCode + orgChild1.orgChild1Code,
|
|
orgRootName: orgRoot.orgRootName,
|
|
labelName: generateLabelName(
|
|
orgChild1.orgChild1Name,
|
|
orgChild1.orgChild1Code,
|
|
orgChild1.orgChild1ShortName,
|
|
orgRoot.orgRootName,
|
|
orgRoot.orgRootCode,
|
|
orgRoot.orgRootShortName,
|
|
),
|
|
posMaster: cannotViewChild1PosMaster
|
|
? []
|
|
: filterPosMasters(orgChild1.posMasters, "orgChild2Id").map((x) =>
|
|
formatPosMaster(x, orgChild1.orgChild1ShortName, orgChild1.id, 1),
|
|
),
|
|
children: orgChild2Data
|
|
.filter((orgChild2) => orgChild2.orgChild1Id === orgChild1.id)
|
|
.map((orgChild2) => ({
|
|
orgTreeId: orgChild2.id,
|
|
orgRootId: orgChild1.id,
|
|
orgLevel: 2,
|
|
orgName: `${orgChild2.orgChild2Name}/${orgChild1.orgChild1Name}/${orgRoot.orgRootName}`,
|
|
orgTreeName: orgChild2.orgChild2Name,
|
|
orgTreeShortName: orgChild2.orgChild2ShortName,
|
|
orgTreeCode: orgChild2.orgChild2Code,
|
|
orgCode: orgRoot.orgRootCode + orgChild2.orgChild2Code,
|
|
orgRootName: orgRoot.orgRootName,
|
|
labelName: generateLabelName(
|
|
orgChild2.orgChild2Name,
|
|
orgChild2.orgChild2Code,
|
|
orgChild2.orgChild2ShortName,
|
|
orgRoot.orgRootName,
|
|
orgRoot.orgRootCode,
|
|
orgRoot.orgRootShortName,
|
|
[orgChild1.orgChild1Name],
|
|
[orgChild1.orgChild1Code],
|
|
[orgChild1.orgChild1ShortName],
|
|
),
|
|
posMaster: cannotViewChild2PosMaster
|
|
? []
|
|
: filterPosMasters(orgChild2.posMasters, "orgChild3Id").map((x) =>
|
|
formatPosMaster(x, orgChild2.orgChild2ShortName, orgChild2.id, 2),
|
|
),
|
|
children: orgChild3Data
|
|
.filter((orgChild3) => orgChild3.orgChild2Id === orgChild2.id)
|
|
.map((orgChild3) => ({
|
|
orgTreeId: orgChild3.id,
|
|
orgRootId: orgChild2.id,
|
|
orgLevel: 3,
|
|
orgName: `${orgChild3.orgChild3Name}/${orgChild2.orgChild2Name}/${orgChild1.orgChild1Name}/${orgRoot.orgRootName}`,
|
|
orgTreeName: orgChild3.orgChild3Name,
|
|
orgTreeShortName: orgChild3.orgChild3ShortName,
|
|
orgTreeCode: orgChild3.orgChild3Code,
|
|
orgCode: orgRoot.orgRootCode + orgChild3.orgChild3Code,
|
|
orgRootName: orgRoot.orgRootName,
|
|
labelName: generateLabelName(
|
|
orgChild3.orgChild3Name,
|
|
orgChild3.orgChild3Code,
|
|
orgChild3.orgChild3ShortName,
|
|
orgRoot.orgRootName,
|
|
orgRoot.orgRootCode,
|
|
orgRoot.orgRootShortName,
|
|
[orgChild2.orgChild2Name, orgChild1.orgChild1Name],
|
|
[orgChild2.orgChild2Code, orgChild1.orgChild1Code],
|
|
[orgChild2.orgChild2ShortName, orgChild1.orgChild1ShortName],
|
|
),
|
|
posMaster: cannotViewChild3PosMaster
|
|
? []
|
|
: filterPosMasters(orgChild3.posMasters, "orgChild4Id").map((x) =>
|
|
formatPosMaster(x, orgChild3.orgChild3ShortName, orgChild3.id, 3),
|
|
),
|
|
children: orgChild4Data
|
|
.filter((orgChild4) => orgChild4.orgChild3Id === orgChild3.id)
|
|
.map((orgChild4) => ({
|
|
orgTreeId: orgChild4.id,
|
|
orgRootId: orgChild3.id,
|
|
orgLevel: 4,
|
|
orgName: `${orgChild4.orgChild4Name}/${orgChild3.orgChild3Name}/${orgChild2.orgChild2Name}/${orgChild1.orgChild1Name}/${orgRoot.orgRootName}`,
|
|
orgTreeName: orgChild4.orgChild4Name,
|
|
orgTreeShortName: orgChild4.orgChild4ShortName,
|
|
orgTreeCode: orgChild4.orgChild4Code,
|
|
orgCode: orgRoot.orgRootCode + orgChild4.orgChild4Code,
|
|
orgRootName: orgRoot.orgRootName,
|
|
labelName: generateLabelName(
|
|
orgChild4.orgChild4Name,
|
|
orgChild4.orgChild4Code,
|
|
orgChild4.orgChild4ShortName,
|
|
orgRoot.orgRootName,
|
|
orgRoot.orgRootCode,
|
|
orgRoot.orgRootShortName,
|
|
[orgChild3.orgChild3Name, orgChild2.orgChild2Name, orgChild1.orgChild1Name],
|
|
[orgChild3.orgChild3Code, orgChild2.orgChild2Code, orgChild1.orgChild1Code],
|
|
[
|
|
orgChild3.orgChild3ShortName,
|
|
orgChild2.orgChild2ShortName,
|
|
orgChild1.orgChild1ShortName,
|
|
],
|
|
),
|
|
posMaster: cannotViewChild4PosMaster
|
|
? []
|
|
: orgChild4.posMasters
|
|
.filter((x) => x.isDirector === true)
|
|
.map((x) =>
|
|
formatPosMaster(x, orgChild4.orgChild4ShortName, orgChild4.id, 4),
|
|
),
|
|
})),
|
|
})),
|
|
})),
|
|
})),
|
|
}));
|
|
|
|
return new HttpSuccess(formattedData);
|
|
}
|
|
|
|
/**
|
|
* API
|
|
*
|
|
* @summary (ADMIN)
|
|
*
|
|
* @param {string} id
|
|
*/
|
|
@Get("approver/{id}")
|
|
async getUserRootOrg(@Path() id: string, @Request() request: RequestWithUser) {
|
|
if (id == "00000000-0000-0000-0000-000000000000") {
|
|
const maps = {
|
|
id: "00000000-0000-0000-0000-000000000000",
|
|
name: "",
|
|
positionName: "ปลัดกรุงเทพมหานคร",
|
|
};
|
|
return new HttpSuccess(maps);
|
|
}
|
|
|
|
const root = await this.orgRootRepository.findOne({
|
|
where: { id: id },
|
|
});
|
|
if (!root) throw new HttpError(HttpStatusCode.NOT_FOUND, "not found. Root");
|
|
const posMaster = await this.posMasterRepository.find({
|
|
where: { orgRootId: root.id, orgChild1Id: IsNull(), current_holder: Not(IsNull()) },
|
|
relations: ["current_holder"],
|
|
});
|
|
if (!posMaster) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลตำแหน่ง");
|
|
|
|
const maps = posMaster.map((posMaster) => ({
|
|
id: posMaster?.current_holder?.id,
|
|
name: `${posMaster?.current_holder?.prefix}${posMaster?.current_holder?.firstName} ${posMaster?.current_holder?.lastName}`,
|
|
positionName: posMaster?.current_holder?.position,
|
|
}));
|
|
|
|
return new HttpSuccess(maps);
|
|
}
|
|
|
|
/**
|
|
* API รายละเอียดโครงสร้าง
|
|
*
|
|
* @summary ORG_023 - รายละเอียดโครงสร้าง (ADMIN) #25
|
|
*
|
|
*/
|
|
@Get("system/{id}/{system}")
|
|
async detailBySystem(
|
|
@Path() id: string,
|
|
@Path() system: string,
|
|
@Request() request: RequestWithUser,
|
|
) {
|
|
const orgRevision = await this.orgRevisionRepository.findOne({ where: { id } });
|
|
if (!orgRevision) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูล");
|
|
}
|
|
let _data: any = {
|
|
root: null,
|
|
child1: null,
|
|
child2: null,
|
|
child3: null,
|
|
child4: null,
|
|
};
|
|
if (
|
|
(orgRevision.orgRevisionIsDraft == true && orgRevision.orgRevisionIsCurrent == false) ||
|
|
system != "SYS_ORG"
|
|
) {
|
|
_data = await new permission().PermissionOrgList(request, system.trim().toUpperCase());
|
|
}
|
|
|
|
const profile = await this.profileRepo.findOne({
|
|
where: { keycloak: request.user.sub },
|
|
relations: ["permissionProfiles", "current_holders"],
|
|
});
|
|
|
|
if (!profile) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผู้ใช้งานในทะเบียนประวัติ");
|
|
}
|
|
|
|
let _privilege = await new permission().PermissionOrgList(request, system);
|
|
const attrOwnership = _privilege.root === null ? true : false;
|
|
|
|
if (orgRevision.orgRevisionIsDraft && !orgRevision.orgRevisionIsCurrent && !attrOwnership) {
|
|
if (Array.isArray(profile.permissionProfiles) && profile.permissionProfiles.length > 0) {
|
|
_data.root = profile.permissionProfiles.map((x) => x.orgRootId);
|
|
} else {
|
|
return new HttpSuccess({ remark: "", data: [] });
|
|
}
|
|
}
|
|
|
|
// กำหนดการเข้าถึงข้อมูลตามสถานะและสิทธิ์
|
|
const isCurrentActive = !orgRevision.orgRevisionIsDraft && orgRevision.orgRevisionIsCurrent;
|
|
if (isCurrentActive) {
|
|
if (_privilege.privilege !== "OWNER" && _privilege.privilege !== "PARENT") {
|
|
if (_privilege.privilege == "NORMAL") {
|
|
const holder = profile.current_holders.find((x) => x.orgRevisionId === id);
|
|
if (!holder) return;
|
|
_data.root = [holder.orgRootId];
|
|
_data.child1 = [holder.orgChild1Id];
|
|
_data.child2 = [holder.orgChild2Id];
|
|
_data.child3 = [holder.orgChild3Id];
|
|
_data.child4 = [holder.orgChild4Id];
|
|
} else if (_privilege.privilege == "CHILD" || _privilege.privilege == "BROTHER") {
|
|
const holder = profile.current_holders.find((x) => x.orgRevisionId === id);
|
|
if (!holder) return;
|
|
_data.root = [holder.orgRootId];
|
|
if (_privilege.root && _privilege.child1 === null) {
|
|
} else if (_privilege.child1 && _privilege.child2 === null) {
|
|
_data.child1 = [holder.orgChild1Id];
|
|
} else if (_privilege.child2 && _privilege.child3 === null) {
|
|
_data.child1 = [holder.orgChild1Id];
|
|
_data.child2 = [holder.orgChild2Id];
|
|
} else if (_privilege.child3 && _privilege.child4 === null) {
|
|
_data.child1 = [holder.orgChild1Id];
|
|
_data.child2 = [holder.orgChild2Id];
|
|
_data.child3 = [holder.orgChild3Id];
|
|
_data.child4 = [holder.orgChild4Id];
|
|
}
|
|
} else {
|
|
_data.root = [profile.current_holders.find((x) => x.orgRevisionId === id)?.orgRootId];
|
|
}
|
|
} else {
|
|
if (!attrOwnership) _data = _privilege;
|
|
}
|
|
}
|
|
|
|
const orgRootData = await AppDataSource.getRepository(OrgRoot)
|
|
.createQueryBuilder("orgRoot")
|
|
.where("orgRoot.orgRevisionId = :id", { id })
|
|
.andWhere(
|
|
_data.root != undefined && _data.root != null
|
|
? _data.root[0] != null
|
|
? `orgRoot.id IN (:...node)`
|
|
: `orgRoot.id is null`
|
|
: "1=1",
|
|
{
|
|
node: _data.root,
|
|
},
|
|
)
|
|
.select([
|
|
"orgRoot.id",
|
|
"orgRoot.ancestorDNA",
|
|
"orgRoot.orgRootName",
|
|
"orgRoot.orgRootShortName",
|
|
"orgRoot.orgRootCode",
|
|
"orgRoot.orgRootOrder",
|
|
"orgRoot.orgRootPhoneEx",
|
|
"orgRoot.orgRootPhoneIn",
|
|
"orgRoot.orgRootFax",
|
|
"orgRoot.orgRevisionId",
|
|
"orgRoot.orgRootRank",
|
|
"orgRoot.orgRootRankSub",
|
|
"orgRoot.DEPARTMENT_CODE",
|
|
"orgRoot.DIVISION_CODE",
|
|
"orgRoot.SECTION_CODE",
|
|
"orgRoot.JOB_CODE",
|
|
"orgRoot.responsibility",
|
|
])
|
|
.orderBy("orgRoot.orgRootOrder", "ASC")
|
|
.getMany();
|
|
const orgRootIds = orgRootData.map((orgRoot) => orgRoot.id) || null;
|
|
const orgChild1Data =
|
|
orgRootIds && orgRootIds.length > 0
|
|
? await AppDataSource.getRepository(OrgChild1)
|
|
.createQueryBuilder("orgChild1")
|
|
.where("orgChild1.orgRootId IN (:...ids)", { ids: orgRootIds })
|
|
.andWhere(
|
|
_data.child1 != undefined && _data.child1 != null
|
|
? _data.child1[0] != null
|
|
? `orgChild1.id IN (:...node)`
|
|
: `orgChild1.id is ${_data.privilege == "PARENT" ? "not null" : "null"}`
|
|
: "1=1",
|
|
{
|
|
node: _data.child1,
|
|
},
|
|
)
|
|
.select([
|
|
"orgChild1.id",
|
|
"orgChild1.ancestorDNA",
|
|
"orgChild1.orgChild1Name",
|
|
"orgChild1.orgChild1ShortName",
|
|
"orgChild1.orgChild1Code",
|
|
"orgChild1.orgChild1Order",
|
|
"orgChild1.orgChild1PhoneEx",
|
|
"orgChild1.orgChild1PhoneIn",
|
|
"orgChild1.orgChild1Fax",
|
|
"orgChild1.orgRootId",
|
|
"orgChild1.orgChild1Rank",
|
|
"orgChild1.orgChild1RankSub",
|
|
"orgChild1.DEPARTMENT_CODE",
|
|
"orgChild1.DIVISION_CODE",
|
|
"orgChild1.SECTION_CODE",
|
|
"orgChild1.JOB_CODE",
|
|
"orgChild1.responsibility",
|
|
])
|
|
.orderBy("orgChild1.orgChild1Order", "ASC")
|
|
.getMany()
|
|
: [];
|
|
|
|
const orgChild1Ids = orgChild1Data.map((orgChild1) => orgChild1.id) || null;
|
|
const orgChild2Data =
|
|
orgChild1Ids && orgChild1Ids.length > 0
|
|
? await AppDataSource.getRepository(OrgChild2)
|
|
.createQueryBuilder("orgChild2")
|
|
.where("orgChild2.orgChild1Id IN (:...ids)", { ids: orgChild1Ids })
|
|
.andWhere(
|
|
_data.child2 != undefined && _data.child2 != null
|
|
? _data.child2[0] != null
|
|
? `orgChild2.id IN (:...node)`
|
|
: `orgChild2.id is null`
|
|
: "1=1",
|
|
{
|
|
node: _data.child2,
|
|
},
|
|
)
|
|
.select([
|
|
"orgChild2.id",
|
|
"orgChild2.ancestorDNA",
|
|
"orgChild2.orgChild2Name",
|
|
"orgChild2.orgChild2ShortName",
|
|
"orgChild2.orgChild2Code",
|
|
"orgChild2.orgChild2Order",
|
|
"orgChild2.orgChild2PhoneEx",
|
|
"orgChild2.orgChild2PhoneIn",
|
|
"orgChild2.orgChild2Fax",
|
|
"orgChild2.orgRootId",
|
|
"orgChild2.orgChild2Rank",
|
|
"orgChild2.orgChild2RankSub",
|
|
"orgChild2.DEPARTMENT_CODE",
|
|
"orgChild2.DIVISION_CODE",
|
|
"orgChild2.SECTION_CODE",
|
|
"orgChild2.JOB_CODE",
|
|
"orgChild2.orgChild1Id",
|
|
"orgChild2.responsibility",
|
|
])
|
|
.orderBy("orgChild2.orgChild2Order", "ASC")
|
|
.getMany()
|
|
: [];
|
|
|
|
const orgChild2Ids = orgChild2Data.map((orgChild2) => orgChild2.id) || null;
|
|
const orgChild3Data =
|
|
orgChild2Ids && orgChild2Ids.length > 0
|
|
? await AppDataSource.getRepository(OrgChild3)
|
|
.createQueryBuilder("orgChild3")
|
|
.where("orgChild3.orgChild2Id IN (:...ids)", { ids: orgChild2Ids })
|
|
.andWhere(
|
|
_data.child3 != undefined && _data.child3 != null
|
|
? _data.child3[0] != null
|
|
? `orgChild3.id IN (:...node)`
|
|
: `orgChild3.id is null`
|
|
: "1=1",
|
|
{
|
|
node: _data.child3,
|
|
},
|
|
)
|
|
.select([
|
|
"orgChild3.id",
|
|
"orgChild3.ancestorDNA",
|
|
"orgChild3.orgChild3Name",
|
|
"orgChild3.orgChild3ShortName",
|
|
"orgChild3.orgChild3Code",
|
|
"orgChild3.orgChild3Order",
|
|
"orgChild3.orgChild3PhoneEx",
|
|
"orgChild3.orgChild3PhoneIn",
|
|
"orgChild3.orgChild3Fax",
|
|
"orgChild3.orgRootId",
|
|
"orgChild3.orgChild3Rank",
|
|
"orgChild3.orgChild3RankSub",
|
|
"orgChild3.DEPARTMENT_CODE",
|
|
"orgChild3.DIVISION_CODE",
|
|
"orgChild3.SECTION_CODE",
|
|
"orgChild3.JOB_CODE",
|
|
"orgChild3.orgChild2Id",
|
|
"orgChild3.responsibility",
|
|
])
|
|
.orderBy("orgChild3.orgChild3Order", "ASC")
|
|
.getMany()
|
|
: [];
|
|
|
|
const orgChild3Ids = orgChild3Data.map((orgChild3) => orgChild3.id) || null;
|
|
const orgChild4Data =
|
|
orgChild3Ids && orgChild3Ids.length > 0
|
|
? await AppDataSource.getRepository(OrgChild4)
|
|
.createQueryBuilder("orgChild4")
|
|
.where("orgChild4.orgChild3Id IN (:...ids)", { ids: orgChild3Ids })
|
|
.andWhere(
|
|
_data.child4 != undefined && _data.child4 != null
|
|
? _data.child4[0] != null
|
|
? `orgChild4.id IN (:...node)`
|
|
: `orgChild4.id is null`
|
|
: "1=1",
|
|
{
|
|
node: _data.child4,
|
|
},
|
|
)
|
|
.select([
|
|
"orgChild4.id",
|
|
"orgChild4.ancestorDNA",
|
|
"orgChild4.orgChild4Name",
|
|
"orgChild4.orgChild4ShortName",
|
|
"orgChild4.orgChild4Code",
|
|
"orgChild4.orgChild4Order",
|
|
"orgChild4.orgChild4PhoneEx",
|
|
"orgChild4.orgChild4PhoneIn",
|
|
"orgChild4.orgChild4Fax",
|
|
"orgChild4.orgRootId",
|
|
"orgChild4.orgChild4Rank",
|
|
"orgChild4.orgChild4RankSub",
|
|
"orgChild4.DEPARTMENT_CODE",
|
|
"orgChild4.DIVISION_CODE",
|
|
"orgChild4.SECTION_CODE",
|
|
"orgChild4.JOB_CODE",
|
|
"orgChild4.orgChild3Id",
|
|
"orgChild4.responsibility",
|
|
])
|
|
.orderBy("orgChild4.orgChild4Order", "ASC")
|
|
.getMany()
|
|
: [];
|
|
|
|
// const formattedData = orgRootData.map((orgRoot) => {
|
|
const formattedData = await Promise.all(
|
|
orgRootData.map(async (orgRoot) => {
|
|
// const sum0 = await this.posMasterRepository.find({
|
|
// where: { orgRevisionId: orgRoot.orgRevisionId, orgRootId: orgRoot.id },
|
|
// select: [
|
|
// "current_holderId",
|
|
// "next_holderId",
|
|
// "orgRootId",
|
|
// "orgChild1Id",
|
|
// "orgChild2Id",
|
|
// "orgChild3Id",
|
|
// "orgChild4Id",
|
|
// ],
|
|
// });
|
|
return {
|
|
orgTreeId: orgRoot.id,
|
|
orgTreeDnaId: orgRoot.ancestorDNA,
|
|
orgLevel: 0,
|
|
orgName: orgRoot.orgRootName,
|
|
orgTreeName: orgRoot.orgRootName,
|
|
orgTreeShortName: orgRoot.orgRootShortName,
|
|
orgTreeCode: orgRoot.orgRootCode,
|
|
orgCode: orgRoot.orgRootCode + "00",
|
|
orgTreeRank: orgRoot.orgRootRank,
|
|
orgTreeRankSub: orgRoot.orgRootRankSub,
|
|
DEPARTMENT_CODE: orgRoot.DEPARTMENT_CODE,
|
|
DIVISION_CODE: orgRoot.DIVISION_CODE,
|
|
SECTION_CODE: orgRoot.SECTION_CODE,
|
|
JOB_CODE: orgRoot.JOB_CODE,
|
|
orgTreeOrder: orgRoot.orgRootOrder,
|
|
orgTreePhoneEx: orgRoot.orgRootPhoneEx,
|
|
orgTreePhoneIn: orgRoot.orgRootPhoneIn,
|
|
orgTreeFax: orgRoot.orgRootFax,
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootName: orgRoot.orgRootName,
|
|
responsibility: orgRoot.responsibility,
|
|
labelName:
|
|
orgRoot.orgRootName + " " + orgRoot.orgRootCode + "00" + " " + orgRoot.orgRootShortName,
|
|
// totalPosition: sum0.length + 1,
|
|
// totalPositionCurrentUse:
|
|
// sum0.filter((x) => x.current_holderId != null && x.current_holderId != "").length + 1,
|
|
// totalPositionCurrentVacant:
|
|
// sum0.filter((x) => x.current_holderId == null || x.current_holderId == "").length + 1,
|
|
// totalPositionNextUse:
|
|
// sum0.filter((x) => x.next_holderId != null && x.next_holderId != "").length + 1,
|
|
// totalPositionNextVacant:
|
|
// sum0.filter((x) => x.next_holderId == null || x.next_holderId == "").length + 1,
|
|
// totalRootPosition:
|
|
// sum0.filter(
|
|
// (x) =>
|
|
// (x.orgChild1Id == null || x.orgChild1Id == "") &&
|
|
// (x.orgChild2Id == null || x.orgChild2Id == "") &&
|
|
// (x.orgChild3Id == null || x.orgChild3Id == "") &&
|
|
// (x.orgChild4Id == null || x.orgChild4Id == ""),
|
|
// ).length + 1,
|
|
// totalRootPositionCurrentUse:
|
|
// sum0.filter(
|
|
// (x) =>
|
|
// (x.orgChild1Id == null || x.orgChild1Id == "") &&
|
|
// (x.orgChild2Id == null || x.orgChild2Id == "") &&
|
|
// (x.orgChild3Id == null || x.orgChild3Id == "") &&
|
|
// (x.orgChild4Id == null || x.orgChild4Id == "") &&
|
|
// x.current_holderId != null &&
|
|
// x.current_holderId != "",
|
|
// ).length + 1,
|
|
// totalRootPositionCurrentVacant:
|
|
// sum0.filter(
|
|
// (x) =>
|
|
// (x.orgChild1Id == null || x.orgChild1Id == "") &&
|
|
// (x.orgChild2Id == null || x.orgChild2Id == "") &&
|
|
// (x.orgChild3Id == null || x.orgChild3Id == "") &&
|
|
// (x.orgChild4Id == null || x.orgChild4Id == "") &&
|
|
// (x.current_holderId == null || x.current_holderId == ""),
|
|
// ).length + 1,
|
|
// totalRootPositionNextUse:
|
|
// sum0.filter(
|
|
// (x) =>
|
|
// (x.orgChild1Id == null || x.orgChild1Id == "") &&
|
|
// (x.orgChild2Id == null || x.orgChild2Id == "") &&
|
|
// (x.orgChild3Id == null || x.orgChild3Id == "") &&
|
|
// (x.orgChild4Id == null || x.orgChild4Id == "") &&
|
|
// x.next_holderId != null &&
|
|
// x.next_holderId != "",
|
|
// ).length + 1,
|
|
// totalRootPositionNextVacant:
|
|
// sum0.filter(
|
|
// (x) =>
|
|
// (x.orgChild1Id == null || x.orgChild1Id == "") &&
|
|
// (x.orgChild2Id == null || x.orgChild2Id == "") &&
|
|
// (x.orgChild3Id == null || x.orgChild3Id == "") &&
|
|
// (x.orgChild4Id == null || x.orgChild4Id == "") &&
|
|
// (x.next_holderId == null || x.next_holderId == ""),
|
|
// ).length + 1,
|
|
|
|
children: await Promise.all(
|
|
orgChild1Data
|
|
.filter((orgChild1) => orgChild1.orgRootId === orgRoot.id)
|
|
.map(async (orgChild1) => {
|
|
// const sum1 = await this.posMasterRepository.find({
|
|
// where: {
|
|
// orgRevisionId: orgRoot.orgRevisionId,
|
|
// orgRootId: orgRoot.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// },
|
|
// select: [
|
|
// "current_holderId",
|
|
// "next_holderId",
|
|
// "orgRootId",
|
|
// "orgChild1Id",
|
|
// "orgChild2Id",
|
|
// "orgChild3Id",
|
|
// "orgChild4Id",
|
|
// ],
|
|
// });
|
|
return {
|
|
orgTreeId: orgChild1.id,
|
|
orgTreeDnaId: orgChild1.ancestorDNA,
|
|
orgRootId: orgRoot.id,
|
|
orgRootDnaId: orgRoot.ancestorDNA,
|
|
orgLevel: 1,
|
|
orgName: `${orgChild1.orgChild1Name} ${orgRoot.orgRootName}`,
|
|
orgTreeName: orgChild1.orgChild1Name,
|
|
orgTreeShortName: orgChild1.orgChild1ShortName,
|
|
orgTreeCode: orgChild1.orgChild1Code,
|
|
orgCode: orgRoot.orgRootCode + orgChild1.orgChild1Code,
|
|
orgTreeRank: orgChild1.orgChild1Rank,
|
|
orgTreeRankSub: orgChild1.orgChild1RankSub,
|
|
DEPARTMENT_CODE: orgChild1.DEPARTMENT_CODE,
|
|
DIVISION_CODE: orgChild1.DIVISION_CODE,
|
|
SECTION_CODE: orgChild1.SECTION_CODE,
|
|
JOB_CODE: orgChild1.JOB_CODE,
|
|
orgTreeOrder: orgChild1.orgChild1Order,
|
|
orgRootCode: orgRoot.orgRootCode,
|
|
orgTreePhoneEx: orgChild1.orgChild1PhoneEx,
|
|
orgTreePhoneIn: orgChild1.orgChild1PhoneIn,
|
|
orgTreeFax: orgChild1.orgChild1Fax,
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootName: orgRoot.orgRootName,
|
|
responsibility: orgChild1.responsibility,
|
|
labelName:
|
|
orgChild1.orgChild1Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild1.orgChild1Code +
|
|
" " +
|
|
orgChild1.orgChild1ShortName +
|
|
"/" +
|
|
orgRoot.orgRootName +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
"00" +
|
|
" " +
|
|
orgRoot.orgRootShortName,
|
|
// totalPosition: sum1.length + 1,
|
|
// totalPositionCurrentUse:
|
|
// sum1.filter((x) => x.current_holderId != null && x.current_holderId != "")
|
|
// .length + 1,
|
|
// totalPositionCurrentVacant:
|
|
// sum1.filter((x) => x.current_holderId == null || x.current_holderId == "")
|
|
// .length + 1,
|
|
// totalPositionNextUse:
|
|
// sum1.filter((x) => x.next_holderId != null && x.next_holderId != "").length + 1,
|
|
// totalPositionNextVacant:
|
|
// sum1.filter((x) => x.next_holderId == null || x.next_holderId == "").length + 1,
|
|
// totalRootPosition:
|
|
// sum1.filter(
|
|
// (x) =>
|
|
// (x.orgChild2Id == null || x.orgChild2Id == "") &&
|
|
// (x.orgChild3Id == null || x.orgChild3Id == "") &&
|
|
// (x.orgChild4Id == null || x.orgChild4Id == ""),
|
|
// ).length + 1,
|
|
// totalRootPositionCurrentUse:
|
|
// sum1.filter(
|
|
// (x) =>
|
|
// (x.orgChild2Id == null || x.orgChild2Id == "") &&
|
|
// (x.orgChild3Id == null || x.orgChild3Id == "") &&
|
|
// (x.orgChild4Id == null || x.orgChild4Id == "") &&
|
|
// x.current_holderId != null &&
|
|
// x.current_holderId != "",
|
|
// ).length + 1,
|
|
// totalRootPositionCurrentVacant:
|
|
// sum1.filter(
|
|
// (x) =>
|
|
// (x.orgChild2Id == null || x.orgChild2Id == "") &&
|
|
// (x.orgChild3Id == null || x.orgChild3Id == "") &&
|
|
// (x.orgChild4Id == null || x.orgChild4Id == "") &&
|
|
// (x.current_holderId == null || x.current_holderId == ""),
|
|
// ).length + 1,
|
|
// totalRootPositionNextUse:
|
|
// sum1.filter(
|
|
// (x) =>
|
|
// (x.orgChild2Id == null || x.orgChild2Id == "") &&
|
|
// (x.orgChild3Id == null || x.orgChild3Id == "") &&
|
|
// (x.orgChild4Id == null || x.orgChild4Id == "") &&
|
|
// x.next_holderId != null &&
|
|
// x.next_holderId != "",
|
|
// ).length + 1,
|
|
// totalRootPositionNextVacant:
|
|
// sum1.filter(
|
|
// (x) =>
|
|
// (x.orgChild2Id == null || x.orgChild2Id == "") &&
|
|
// (x.orgChild3Id == null || x.orgChild3Id == "") &&
|
|
// (x.orgChild4Id == null || x.orgChild4Id == "") &&
|
|
// (x.next_holderId == null || x.next_holderId == ""),
|
|
// ).length + 1,
|
|
|
|
children: await Promise.all(
|
|
orgChild2Data
|
|
.filter((orgChild2) => orgChild2.orgChild1Id === orgChild1.id)
|
|
.map(async (orgChild2) => {
|
|
// const sum2 = await this.posMasterRepository.find({
|
|
// where: {
|
|
// orgRevisionId: orgRoot.orgRevisionId,
|
|
// orgRootId: orgRoot.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// },
|
|
// select: [
|
|
// "current_holderId",
|
|
// "next_holderId",
|
|
// "orgRootId",
|
|
// "orgChild1Id",
|
|
// "orgChild2Id",
|
|
// "orgChild3Id",
|
|
// "orgChild4Id",
|
|
// ],
|
|
// });
|
|
return {
|
|
orgTreeId: orgChild2.id,
|
|
orgTreeDnaId: orgChild2.ancestorDNA,
|
|
orgRootId: orgChild1.id,
|
|
orgRootDnaId: orgChild1.ancestorDNA,
|
|
orgLevel: 2,
|
|
orgName: `${orgChild2.orgChild2Name} ${orgChild1.orgChild1Name} ${orgRoot.orgRootName}`,
|
|
orgTreeName: orgChild2.orgChild2Name,
|
|
orgTreeShortName: orgChild2.orgChild2ShortName,
|
|
orgTreeCode: orgChild2.orgChild2Code,
|
|
orgCode: orgRoot.orgRootCode + orgChild2.orgChild2Code,
|
|
orgTreeRank: orgChild2.orgChild2Rank,
|
|
orgTreeRankSub: orgChild2.orgChild2RankSub,
|
|
DEPARTMENT_CODE: orgChild2.DEPARTMENT_CODE,
|
|
DIVISION_CODE: orgChild2.DIVISION_CODE,
|
|
SECTION_CODE: orgChild2.SECTION_CODE,
|
|
JOB_CODE: orgChild2.JOB_CODE,
|
|
orgTreeOrder: orgChild2.orgChild2Order,
|
|
orgRootCode: orgRoot.orgRootCode,
|
|
orgTreePhoneEx: orgChild2.orgChild2PhoneEx,
|
|
orgTreePhoneIn: orgChild2.orgChild2PhoneIn,
|
|
orgTreeFax: orgChild2.orgChild2Fax,
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootName: orgRoot.orgRootName,
|
|
responsibility: orgChild2.responsibility,
|
|
labelName:
|
|
orgChild2.orgChild2Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild2.orgChild2Code +
|
|
" " +
|
|
orgChild2.orgChild2ShortName +
|
|
"/" +
|
|
orgChild1.orgChild1Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild1.orgChild1Code +
|
|
" " +
|
|
orgChild1.orgChild1ShortName +
|
|
"/" +
|
|
orgRoot.orgRootName +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
"00" +
|
|
" " +
|
|
orgRoot.orgRootShortName,
|
|
// totalPosition: sum2.length + 1,
|
|
// totalPositionCurrentUse:
|
|
// sum2.filter(
|
|
// (x) => x.current_holderId != null && x.current_holderId != "",
|
|
// ).length + 1,
|
|
// totalPositionCurrentVacant:
|
|
// sum2.filter(
|
|
// (x) => x.current_holderId == null || x.current_holderId == "",
|
|
// ).length + 1,
|
|
// totalPositionNextUse:
|
|
// sum2.filter((x) => x.next_holderId != null && x.next_holderId != "")
|
|
// .length + 1,
|
|
// totalPositionNextVacant:
|
|
// sum2.filter((x) => x.next_holderId == null || x.next_holderId == "")
|
|
// .length + 1,
|
|
// totalRootPosition:
|
|
// sum2.filter(
|
|
// (x) =>
|
|
// (x.orgChild3Id == null || x.orgChild3Id == "") &&
|
|
// (x.orgChild4Id == null || x.orgChild4Id == ""),
|
|
// ).length + 1,
|
|
// totalRootPositionCurrentUse:
|
|
// sum2.filter(
|
|
// (x) =>
|
|
// (x.orgChild3Id == null || x.orgChild3Id == "") &&
|
|
// (x.orgChild4Id == null || x.orgChild4Id == "") &&
|
|
// x.current_holderId != null &&
|
|
// x.current_holderId != "",
|
|
// ).length + 1,
|
|
// totalRootPositionCurrentVacant:
|
|
// sum2.filter(
|
|
// (x) =>
|
|
// (x.orgChild3Id == null || x.orgChild3Id == "") &&
|
|
// (x.orgChild4Id == null || x.orgChild4Id == "") &&
|
|
// (x.current_holderId == null || x.current_holderId == ""),
|
|
// ).length + 1,
|
|
// totalRootPositionNextUse:
|
|
// sum2.filter(
|
|
// (x) =>
|
|
// (x.orgChild3Id == null || x.orgChild3Id == "") &&
|
|
// (x.orgChild4Id == null || x.orgChild4Id == "") &&
|
|
// x.next_holderId != null &&
|
|
// x.next_holderId != "",
|
|
// ).length + 1,
|
|
// totalRootPositionNextVacant:
|
|
// sum2.filter(
|
|
// (x) =>
|
|
// (x.orgChild3Id == null || x.orgChild3Id == "") &&
|
|
// (x.orgChild4Id == null || x.orgChild4Id == "") &&
|
|
// (x.next_holderId == null || x.next_holderId == ""),
|
|
// ).length + 1,
|
|
|
|
children: await Promise.all(
|
|
orgChild3Data
|
|
.filter((orgChild3) => orgChild3.orgChild2Id === orgChild2.id)
|
|
.map(async (orgChild3) => {
|
|
// const sum3 = await this.posMasterRepository.find({
|
|
// where: {
|
|
// orgRevisionId: orgRoot.orgRevisionId,
|
|
// orgRootId: orgRoot.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// orgChild3Id: orgChild3.id,
|
|
// },
|
|
// select: [
|
|
// "current_holderId",
|
|
// "next_holderId",
|
|
// "orgRootId",
|
|
// "orgChild1Id",
|
|
// "orgChild2Id",
|
|
// "orgChild3Id",
|
|
// "orgChild4Id",
|
|
// ],
|
|
// });
|
|
return {
|
|
orgTreeId: orgChild3.id,
|
|
orgTreeDnaId: orgChild3.ancestorDNA,
|
|
orgRootId: orgChild2.id,
|
|
orgRootDnaId: orgChild2.ancestorDNA,
|
|
orgLevel: 3,
|
|
orgName: `${orgChild3.orgChild3Name} ${orgChild2.orgChild2Name} ${orgChild1.orgChild1Name} ${orgRoot.orgRootName}`,
|
|
orgTreeName: orgChild3.orgChild3Name,
|
|
orgTreeShortName: orgChild3.orgChild3ShortName,
|
|
orgTreeCode: orgChild3.orgChild3Code,
|
|
orgCode: orgRoot.orgRootCode + orgChild3.orgChild3Code,
|
|
orgTreeRank: orgChild3.orgChild3Rank,
|
|
orgTreeRankSub: orgChild3.orgChild3RankSub,
|
|
DEPARTMENT_CODE: orgChild3.DEPARTMENT_CODE,
|
|
DIVISION_CODE: orgChild3.DIVISION_CODE,
|
|
SECTION_CODE: orgChild3.SECTION_CODE,
|
|
JOB_CODE: orgChild3.JOB_CODE,
|
|
orgTreeOrder: orgChild3.orgChild3Order,
|
|
orgRootCode: orgRoot.orgRootCode,
|
|
orgTreePhoneEx: orgChild3.orgChild3PhoneEx,
|
|
orgTreePhoneIn: orgChild3.orgChild3PhoneIn,
|
|
orgTreeFax: orgChild3.orgChild3Fax,
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootName: orgRoot.orgRootName,
|
|
responsibility: orgChild3.responsibility,
|
|
labelName:
|
|
orgChild3.orgChild3Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild3.orgChild3Code +
|
|
" " +
|
|
orgChild3.orgChild3ShortName +
|
|
"/" +
|
|
orgChild2.orgChild2Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild2.orgChild2Code +
|
|
" " +
|
|
orgChild2.orgChild2ShortName +
|
|
"/" +
|
|
orgChild1.orgChild1Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild1.orgChild1Code +
|
|
" " +
|
|
orgChild1.orgChild1ShortName +
|
|
"/" +
|
|
orgRoot.orgRootName +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
"00" +
|
|
" " +
|
|
orgRoot.orgRootShortName,
|
|
// totalPosition: sum3.length + 1,
|
|
// totalPositionCurrentUse:
|
|
// sum3.filter(
|
|
// (x) => x.current_holderId != null && x.current_holderId != "",
|
|
// ).length + 1,
|
|
// totalPositionCurrentVacant:
|
|
// sum3.filter(
|
|
// (x) => x.current_holderId == null || x.current_holderId == "",
|
|
// ).length + 1,
|
|
// totalPositionNextUse:
|
|
// sum3.filter(
|
|
// (x) => x.next_holderId != null && x.next_holderId != "",
|
|
// ).length + 1,
|
|
// totalPositionNextVacant:
|
|
// sum3.filter(
|
|
// (x) => x.next_holderId == null || x.next_holderId == "",
|
|
// ).length + 1,
|
|
// totalRootPosition:
|
|
// sum3.filter((x) => x.orgChild4Id == null || x.orgChild4Id == "")
|
|
// .length + 1,
|
|
// totalRootPositionCurrentUse:
|
|
// sum3.filter(
|
|
// (x) =>
|
|
// (x.orgChild4Id == null || x.orgChild4Id == "") &&
|
|
// x.current_holderId != null &&
|
|
// x.current_holderId != "",
|
|
// ).length + 1,
|
|
// totalRootPositionCurrentVacant:
|
|
// sum3.filter(
|
|
// (x) =>
|
|
// (x.orgChild4Id == null || x.orgChild4Id == "") &&
|
|
// (x.current_holderId == null || x.current_holderId == ""),
|
|
// ).length + 1,
|
|
// totalRootPositionNextUse:
|
|
// sum3.filter(
|
|
// (x) =>
|
|
// (x.orgChild4Id == null || x.orgChild4Id == "") &&
|
|
// x.next_holderId != null &&
|
|
// x.next_holderId != "",
|
|
// ).length + 1,
|
|
// totalRootPositionNextVacant:
|
|
// sum3.filter(
|
|
// (x) =>
|
|
// (x.orgChild4Id == null || x.orgChild4Id == "") &&
|
|
// (x.next_holderId == null || x.next_holderId == ""),
|
|
// ).length + 1,
|
|
|
|
children: await Promise.all(
|
|
orgChild4Data
|
|
.filter((orgChild4) => orgChild4.orgChild3Id === orgChild3.id)
|
|
.map(async (orgChild4) => {
|
|
// const sum4 = await this.posMasterRepository.find({
|
|
// where: {
|
|
// orgRevisionId: orgRoot.orgRevisionId,
|
|
// orgRootId: orgRoot.id,
|
|
// orgChild1Id: orgChild1.id,
|
|
// orgChild2Id: orgChild2.id,
|
|
// orgChild3Id: orgChild3.id,
|
|
// orgChild4Id: orgChild4.id,
|
|
// },
|
|
// select: [
|
|
// "current_holderId",
|
|
// "next_holderId",
|
|
// "orgRootId",
|
|
// "orgChild1Id",
|
|
// "orgChild2Id",
|
|
// "orgChild3Id",
|
|
// "orgChild4Id",
|
|
// ],
|
|
// });
|
|
return {
|
|
orgTreeId: orgChild4.id,
|
|
orgTreeDnaId: orgChild4.ancestorDNA,
|
|
orgRootId: orgChild3.id,
|
|
orgRootDnaId: orgChild3.ancestorDNA,
|
|
orgLevel: 4,
|
|
orgName: `${orgChild4.orgChild4Name} ${orgChild3.orgChild3Name} ${orgChild2.orgChild2Name} ${orgChild1.orgChild1Name} ${orgRoot.orgRootName}`,
|
|
orgTreeName: orgChild4.orgChild4Name,
|
|
orgTreeShortName: orgChild4.orgChild4ShortName,
|
|
orgTreeCode: orgChild4.orgChild4Code,
|
|
orgCode: orgRoot.orgRootCode + orgChild4.orgChild4Code,
|
|
orgTreeRank: orgChild4.orgChild4Rank,
|
|
orgTreeRankSub: orgChild4.orgChild4RankSub,
|
|
DEPARTMENT_CODE: orgChild4.DEPARTMENT_CODE,
|
|
DIVISION_CODE: orgChild4.DIVISION_CODE,
|
|
SECTION_CODE: orgChild4.SECTION_CODE,
|
|
JOB_CODE: orgChild4.JOB_CODE,
|
|
orgTreeOrder: orgChild4.orgChild4Order,
|
|
orgRootCode: orgRoot.orgRootCode,
|
|
orgTreePhoneEx: orgChild4.orgChild4PhoneEx,
|
|
orgTreePhoneIn: orgChild4.orgChild4PhoneIn,
|
|
orgTreeFax: orgChild4.orgChild4Fax,
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootName: orgRoot.orgRootName,
|
|
responsibility: orgChild4.responsibility,
|
|
labelName:
|
|
orgChild4.orgChild4Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild4.orgChild4Code +
|
|
" " +
|
|
orgChild4.orgChild4ShortName +
|
|
"/" +
|
|
orgChild3.orgChild3Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild3.orgChild3Code +
|
|
" " +
|
|
orgChild3.orgChild3ShortName +
|
|
"/" +
|
|
orgChild2.orgChild2Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild2.orgChild2Code +
|
|
" " +
|
|
orgChild2.orgChild2ShortName +
|
|
"/" +
|
|
orgChild1.orgChild1Name +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
orgChild1.orgChild1Code +
|
|
" " +
|
|
orgChild1.orgChild1ShortName +
|
|
"/" +
|
|
orgRoot.orgRootName +
|
|
" " +
|
|
orgRoot.orgRootCode +
|
|
"00" +
|
|
" " +
|
|
orgRoot.orgRootShortName,
|
|
// totalPosition: sum4.length + 1,
|
|
// totalPositionCurrentUse:
|
|
// sum4.filter(
|
|
// (x) =>
|
|
// x.current_holderId != null &&
|
|
// x.current_holderId != "",
|
|
// ).length + 1,
|
|
// totalPositionCurrentVacant:
|
|
// sum4.filter(
|
|
// (x) =>
|
|
// x.current_holderId == null ||
|
|
// x.current_holderId == "",
|
|
// ).length + 1,
|
|
// totalPositionNextUse:
|
|
// sum4.filter(
|
|
// (x) =>
|
|
// x.next_holderId != null && x.next_holderId != "",
|
|
// ).length + 1,
|
|
// totalPositionNextVacant:
|
|
// sum4.filter(
|
|
// (x) =>
|
|
// x.next_holderId == null || x.next_holderId == "",
|
|
// ).length + 1,
|
|
// totalRootPosition: sum4.length + 1,
|
|
// totalRootPositionCurrentUse:
|
|
// sum4.filter(
|
|
// (x) =>
|
|
// x.current_holderId != null &&
|
|
// x.current_holderId != "",
|
|
// ).length + 1,
|
|
// totalRootPositionCurrentVacant:
|
|
// sum4.filter(
|
|
// (x) =>
|
|
// x.current_holderId == null ||
|
|
// x.current_holderId == "",
|
|
// ).length + 1,
|
|
// totalRootPositionNextUse:
|
|
// sum4.filter(
|
|
// (x) =>
|
|
// x.next_holderId != null && x.next_holderId != "",
|
|
// ).length + 1,
|
|
// totalRootPositionNextVacant:
|
|
// sum4.filter(
|
|
// (x) =>
|
|
// x.next_holderId == null || x.next_holderId == "",
|
|
// ).length + 1,
|
|
};
|
|
}),
|
|
),
|
|
};
|
|
}),
|
|
),
|
|
};
|
|
}),
|
|
),
|
|
};
|
|
}),
|
|
),
|
|
};
|
|
}),
|
|
);
|
|
|
|
return new HttpSuccess(formattedData);
|
|
}
|
|
/**
|
|
* API รายละเอียดโครงสร้าง
|
|
*
|
|
* @summary ORG_023 - รายละเอียดโครงสร้าง (ADMIN) #25
|
|
*
|
|
*/
|
|
@Get("system-root/{id}/{system}")
|
|
async detailBySystemRoot(
|
|
@Path() id: string,
|
|
@Path() system: string,
|
|
@Request() request: RequestWithUser,
|
|
) {
|
|
const orgRevision = await this.orgRevisionRepository.findOne({ where: { id } });
|
|
if (!orgRevision) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูล");
|
|
}
|
|
let _data = {
|
|
root: null,
|
|
child1: null,
|
|
child2: null,
|
|
child3: null,
|
|
child4: null,
|
|
};
|
|
if (orgRevision.orgRevisionIsDraft == true && orgRevision.orgRevisionIsCurrent == false) {
|
|
_data = await new permission().PermissionOrgList(request, system.trim().toUpperCase());
|
|
}
|
|
const orgRootData = await AppDataSource.getRepository(OrgRoot)
|
|
.createQueryBuilder("orgRoot")
|
|
.where("orgRoot.orgRevisionId = :id", { id })
|
|
.andWhere(
|
|
_data.root != undefined && _data.root != null
|
|
? _data.root[0] != null
|
|
? `orgRoot.id IN (:...node)`
|
|
: `orgRoot.id is null`
|
|
: "1=1",
|
|
{
|
|
node: _data.root,
|
|
},
|
|
)
|
|
.select([
|
|
"orgRoot.id",
|
|
"orgRoot.orgRootName",
|
|
"orgRoot.orgRootShortName",
|
|
"orgRoot.orgRootCode",
|
|
"orgRoot.orgRootOrder",
|
|
"orgRoot.orgRootPhoneEx",
|
|
"orgRoot.orgRootPhoneIn",
|
|
"orgRoot.orgRootFax",
|
|
"orgRoot.orgRevisionId",
|
|
"orgRoot.orgRootRank",
|
|
"orgRoot.orgRootRankSub",
|
|
"orgRoot.responsibility",
|
|
"orgRoot.isDeputy",
|
|
])
|
|
.orderBy("orgRoot.orgRootOrder", "ASC")
|
|
.getMany();
|
|
|
|
const formattedData = await Promise.all(
|
|
orgRootData.map(async (orgRoot) => {
|
|
return {
|
|
orgTreeId: orgRoot.id,
|
|
orgLevel: 0,
|
|
isDeputy: orgRoot.isDeputy,
|
|
orgName: orgRoot.orgRootName,
|
|
orgTreeName: orgRoot.orgRootName,
|
|
orgTreeShortName: orgRoot.orgRootShortName,
|
|
orgTreeCode: orgRoot.orgRootCode,
|
|
orgCode: orgRoot.orgRootCode + "00",
|
|
orgTreeRank: orgRoot.orgRootRank,
|
|
orgTreeRankSub: orgRoot.orgRootRankSub,
|
|
orgTreeOrder: orgRoot.orgRootOrder,
|
|
orgTreePhoneEx: orgRoot.orgRootPhoneEx,
|
|
orgTreePhoneIn: orgRoot.orgRootPhoneIn,
|
|
orgTreeFax: orgRoot.orgRootFax,
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootName: orgRoot.orgRootName,
|
|
responsibility: orgRoot.responsibility,
|
|
labelName:
|
|
orgRoot.orgRootName + " " + orgRoot.orgRootCode + "00" + " " + orgRoot.orgRootShortName,
|
|
totalPosition: await this.posMasterRepository.count({
|
|
where: { orgRevisionId: orgRoot.orgRevisionId, orgRootId: orgRoot.id },
|
|
}),
|
|
totalPositionCurrentUse: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
current_holderId: Not(IsNull()) || Not(""),
|
|
},
|
|
}),
|
|
totalPositionCurrentVacant: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
current_holderId: IsNull() || "",
|
|
},
|
|
}),
|
|
totalPositionNextUse: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
next_holderId: Not(IsNull()) || Not(""),
|
|
},
|
|
}),
|
|
totalPositionNextVacant: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
next_holderId: IsNull() || "",
|
|
},
|
|
}),
|
|
totalRootPosition: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: IsNull() || "",
|
|
orgChild2Id: IsNull() || "",
|
|
orgChild3Id: IsNull() || "",
|
|
orgChild4Id: IsNull() || "",
|
|
},
|
|
}),
|
|
totalRootPositionCurrentUse: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: IsNull() || "",
|
|
orgChild2Id: IsNull() || "",
|
|
orgChild3Id: IsNull() || "",
|
|
orgChild4Id: IsNull() || "",
|
|
current_holderId: Not(IsNull()) || Not(""),
|
|
},
|
|
}),
|
|
totalRootPositionCurrentVacant: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: IsNull() || "",
|
|
orgChild2Id: IsNull() || "",
|
|
orgChild3Id: IsNull() || "",
|
|
orgChild4Id: IsNull() || "",
|
|
current_holderId: IsNull() || "",
|
|
},
|
|
}),
|
|
totalRootPositionNextUse: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: IsNull() || "",
|
|
orgChild2Id: IsNull() || "",
|
|
orgChild3Id: IsNull() || "",
|
|
orgChild4Id: IsNull() || "",
|
|
next_holderId: Not(IsNull()) || Not(""),
|
|
},
|
|
}),
|
|
totalRootPositionNextVacant: await this.posMasterRepository.count({
|
|
where: {
|
|
orgRevisionId: orgRoot.orgRevisionId,
|
|
orgRootId: orgRoot.id,
|
|
orgChild1Id: IsNull() || "",
|
|
orgChild2Id: IsNull() || "",
|
|
orgChild3Id: IsNull() || "",
|
|
orgChild4Id: IsNull() || "",
|
|
next_holderId: IsNull() || "",
|
|
},
|
|
}),
|
|
};
|
|
}),
|
|
);
|
|
|
|
return new HttpSuccess(formattedData);
|
|
}
|
|
/**
|
|
* API เช็ค org ในระบบ
|
|
*
|
|
* @summary - เช็ค org ในระบบ (ADMIN)
|
|
*
|
|
*/
|
|
@Get("check/child1/{id}")
|
|
async findIsOfficerChild1(@Path() id: string, @Request() request: RequestWithUser) {
|
|
const orgRevision = await this.orgRevisionRepository.findOne({
|
|
where: { id },
|
|
relations: ["orgChild1s"],
|
|
});
|
|
if (!orgRevision) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูล");
|
|
}
|
|
const check = orgRevision.orgChild1s.find((x) => x.isOfficer == true);
|
|
return new HttpSuccess(check != null);
|
|
}
|
|
/**
|
|
* API เช็ค org ในระบบ
|
|
*
|
|
* @summary - เช็ค org ในระบบ (ADMIN)
|
|
*
|
|
*/
|
|
@Get("check/root/{id}")
|
|
async findIsDeputyRoot(@Path() id: string, @Request() request: RequestWithUser) {
|
|
const orgRevision = await this.orgRevisionRepository.findOne({
|
|
where: { id },
|
|
relations: ["orgRoots"],
|
|
});
|
|
if (!orgRevision) {
|
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูล");
|
|
}
|
|
const check = orgRevision.orgRoots.find((x) => x.isDeputy == true);
|
|
return new HttpSuccess(check != null);
|
|
}
|
|
|
|
/**
|
|
* API หา สกก1
|
|
*
|
|
* @summary - หา สกก1 (ADMIN)
|
|
*
|
|
*/
|
|
@Get("find/head/officer")
|
|
async findIsHeadOfficer(@Request() request: RequestWithUser) {
|
|
const posMaster = await this.posMasterRepository.find({
|
|
where: {
|
|
orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
|
|
orgRoot: { isCommission: true },
|
|
orgChild1Id: IsNull(),
|
|
isDirector: true,
|
|
current_holderId: Not(IsNull()),
|
|
// posMasterActs: { statusReport: "DONE" },
|
|
// posMasterActChilds: { statusReport: "DONE" },
|
|
},
|
|
order: { posMasterOrder: "ASC", posMasterActChilds: { posMasterOrder: "ASC" } },
|
|
relations: [
|
|
"current_holder",
|
|
// "posMasterActChilds",
|
|
// "posMasterActChilds.posMasterChild",
|
|
// "posMasterActChilds.posMasterChild.current_holder",
|
|
],
|
|
});
|
|
if (posMaster.length <= 0) {
|
|
return new HttpSuccess({
|
|
name: "......................................................",
|
|
position: "......................................................",
|
|
});
|
|
}
|
|
if (posMaster[0].current_holder == null) {
|
|
const posMaster = await this.posMasterRepository.find({
|
|
where: {
|
|
orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
|
|
orgRoot: { isCommission: true },
|
|
orgChild1Id: IsNull(),
|
|
isDirector: true,
|
|
posMasterActs: { statusReport: "DONE" },
|
|
posMasterActChilds: { statusReport: "DONE" },
|
|
},
|
|
order: { posMasterOrder: "ASC", posMasterActChilds: { posMasterOrder: "ASC" } },
|
|
relations: [
|
|
"current_holder",
|
|
"posMasterActChilds",
|
|
"posMasterActChilds.posMasterChild",
|
|
"posMasterActChilds.posMasterChild.current_holder",
|
|
],
|
|
});
|
|
if (
|
|
posMaster[0].posMasterActChilds.length <= 0 ||
|
|
posMaster[0].posMasterActChilds[0].posMasterChild == null ||
|
|
posMaster[0].posMasterActChilds[0].posMasterChild.current_holder == null
|
|
) {
|
|
return new HttpSuccess({
|
|
name: "......................................................",
|
|
position: "......................................................",
|
|
});
|
|
}
|
|
return new HttpSuccess({
|
|
name: `${posMaster[0].posMasterActChilds[0].posMasterChild.current_holder.prefix}${posMaster[0].posMasterActChilds[0].posMasterChild.current_holder.firstName} ${posMaster[0].posMasterActChilds[0].posMasterChild.current_holder.lastName}`,
|
|
position: posMaster[0].posMasterActChilds[0].posMasterChild.current_holder.position,
|
|
});
|
|
} else {
|
|
return new HttpSuccess({
|
|
name: `${posMaster[0].current_holder.prefix}${posMaster[0].current_holder.firstName} ${posMaster[0].current_holder.lastName}`,
|
|
position: posMaster[0].current_holder.position,
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* API ลำดับโครงสร้าง
|
|
*
|
|
* @summary - ลำดับโครงสร้าง (ADMIN)
|
|
*
|
|
*/
|
|
@Get("root/search/sort")
|
|
async searchSortRootLevelType(@Request() request: RequestWithUser) {
|
|
// const root1 = await this.orgRootRepository.find({
|
|
// where: {
|
|
// orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
|
|
// DEPARTMENT_CODE: Not("50"),
|
|
// },
|
|
// order: { isDeputy: "DESC", orgRootOrder: "ASC" },
|
|
// select: ["orgRootName"],
|
|
// });
|
|
// const root2 = await this.orgRootRepository.find({
|
|
// where: {
|
|
// orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
|
|
// DEPARTMENT_CODE: "50",
|
|
// },
|
|
// order: { orgRootName: "ASC" },
|
|
// select: ["orgRootName"],
|
|
// });
|
|
// const root = [...root1, ...root2];
|
|
|
|
// const child1 = await this.child1Repository.find({
|
|
// where: {
|
|
// orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
|
|
// },
|
|
// order: { orgChild1Order: "ASC" },
|
|
// select: ["orgChild1Name"],
|
|
// });
|
|
// const child2 = await this.child2Repository.find({
|
|
// where: {
|
|
// orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
|
|
// },
|
|
// order: { orgChild2Order: "ASC" },
|
|
// select: ["orgChild2Name"],
|
|
// });
|
|
// const child3 = await this.child3Repository.find({
|
|
// where: {
|
|
// orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
|
|
// },
|
|
// order: { orgChild3Order: "ASC" },
|
|
// select: ["orgChild3Name"],
|
|
// });
|
|
// const child4 = await this.child4Repository.find({
|
|
// where: {
|
|
// orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
|
|
// },
|
|
// order: { orgChild4Order: "ASC" },
|
|
// select: ["orgChild4Name"],
|
|
// });
|
|
// const hospital = await this.child1Repository.find({
|
|
// where: [
|
|
// {
|
|
// orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
|
|
// orgRoot: { isDeputy: true },
|
|
// },
|
|
// {
|
|
// orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
|
|
// orgChild1RankSub: "HOSPITAL",
|
|
// },
|
|
// ],
|
|
// select: ["orgChild1Name"],
|
|
// });
|
|
// const posType = await this.posTypeRepository.find({
|
|
// order: { posTypeRank: "DESC" },
|
|
// select: ["posTypeName"],
|
|
// });
|
|
// const posLevel = await this.posLevelRepository.find({
|
|
// order: { posLevelRank: "DESC" },
|
|
// select: ["posLevelName"],
|
|
// });
|
|
|
|
const [roots, child1, child2, child3, child4, hospital, posType, posLevel] = await Promise.all([
|
|
// ===== ROOT =====
|
|
this.orgRootRepository
|
|
.createQueryBuilder("root")
|
|
.innerJoin("root.orgRevision", "rev")
|
|
.select(["root.orgRootName AS orgRootName"])
|
|
.where("rev.orgRevisionIsDraft = false")
|
|
.andWhere("rev.orgRevisionIsCurrent = true")
|
|
.orderBy("CASE WHEN root.DEPARTMENT_CODE = '50' THEN 1 ELSE 0 END", "ASC")
|
|
.addOrderBy("root.isDeputy", "DESC")
|
|
.addOrderBy("root.orgRootOrder", "ASC")
|
|
.addOrderBy("root.orgRootName", "ASC")
|
|
.getRawMany(),
|
|
|
|
// ===== CHILD 1 =====
|
|
this.child1Repository
|
|
.createQueryBuilder("c1")
|
|
.innerJoin("c1.orgRevision", "rev")
|
|
.select("c1.orgChild1Name", "orgChild1Name")
|
|
.where("rev.orgRevisionIsDraft = false")
|
|
.andWhere("rev.orgRevisionIsCurrent = true")
|
|
.orderBy("c1.orgChild1Order", "ASC")
|
|
.getRawMany(),
|
|
|
|
// ===== CHILD 2 =====
|
|
this.child2Repository
|
|
.createQueryBuilder("c2")
|
|
.innerJoin("c2.orgRevision", "rev")
|
|
.select("c2.orgChild2Name", "orgChild2Name")
|
|
.where("rev.orgRevisionIsDraft = false")
|
|
.andWhere("rev.orgRevisionIsCurrent = true")
|
|
.orderBy("c2.orgChild2Order", "ASC")
|
|
.getRawMany(),
|
|
|
|
// ===== CHILD 3 =====
|
|
this.child3Repository
|
|
.createQueryBuilder("c3")
|
|
.innerJoin("c3.orgRevision", "rev")
|
|
.select("c3.orgChild3Name", "orgChild3Name")
|
|
.where("rev.orgRevisionIsDraft = false")
|
|
.andWhere("rev.orgRevisionIsCurrent = true")
|
|
.orderBy("c3.orgChild3Order", "ASC")
|
|
.getRawMany(),
|
|
|
|
// ===== CHILD 4 =====
|
|
this.child4Repository
|
|
.createQueryBuilder("c4")
|
|
.innerJoin("c4.orgRevision", "rev")
|
|
.select("c4.orgChild4Name", "orgChild4Name")
|
|
.where("rev.orgRevisionIsDraft = false")
|
|
.andWhere("rev.orgRevisionIsCurrent = true")
|
|
.orderBy("c4.orgChild4Order", "ASC")
|
|
.getRawMany(),
|
|
|
|
// ===== HOSPITAL =====
|
|
this.child1Repository
|
|
.createQueryBuilder("c1")
|
|
.innerJoin("c1.orgRevision", "rev")
|
|
.leftJoin("c1.orgRoot", "root")
|
|
.select("c1.orgChild1Name", "orgChild1Name")
|
|
.where("rev.orgRevisionIsDraft = false")
|
|
.andWhere("rev.orgRevisionIsCurrent = true")
|
|
.andWhere("(root.isDeputy = true OR c1.orgChild1RankSub = :rank)", { rank: "HOSPITAL" })
|
|
.getRawMany(),
|
|
|
|
// ===== POSITION TYPE =====
|
|
this.posTypeRepository
|
|
.createQueryBuilder("pt")
|
|
.select("pt.posTypeName", "posTypeName")
|
|
.orderBy("pt.posTypeRank", "DESC")
|
|
.getRawMany(),
|
|
|
|
// ===== POSITION LEVEL =====
|
|
this.posLevelRepository
|
|
.createQueryBuilder("pl")
|
|
.select("pl.posLevelName", "posLevelName")
|
|
.orderBy("pl.posLevelRank", "DESC")
|
|
.getRawMany(),
|
|
]);
|
|
|
|
return new HttpSuccess({
|
|
root: roots.map((x) => x.orgRootName),
|
|
child1: child1.map((x) => x.orgChild1Name),
|
|
child2: child2.map((x) => x.orgChild2Name),
|
|
child3: child3.map((x) => x.orgChild3Name),
|
|
child4: child4.map((x) => x.orgChild4Name),
|
|
hospital: hospital.map((x) => x.orgChild1Name),
|
|
posTypeNameOrder: posType.map((x) => x.posTypeName),
|
|
posLevelNameOrder: posLevel.map((x) => x.posLevelName),
|
|
});
|
|
}
|
|
|
|
/**
|
|
* API เพิ่มสิทธิ์โครงสร้าง
|
|
*
|
|
* @summary - เพิ่มสิทธิ์โครงสร้าง (ADMIN)
|
|
*
|
|
*/
|
|
@Get("root/add/permission/{child1Id}")
|
|
async addRootPermission(@Path() child1Id: string, @Request() request: RequestWithUser) {
|
|
const profiles = await this.profileRepo.find({
|
|
where: {
|
|
keycloak: Not(IsNull()),
|
|
current_holders: {
|
|
orgChild1Id: child1Id,
|
|
},
|
|
},
|
|
});
|
|
const orgRoots = await this.orgRootRepository.find({
|
|
where: {
|
|
orgRevision: {
|
|
orgRevisionIsDraft: true,
|
|
orgRevisionIsCurrent: false,
|
|
},
|
|
},
|
|
});
|
|
|
|
for await (const root of orgRoots) {
|
|
const _permissionOrg = profiles.map((profile) => {
|
|
const permission = new PermissionOrg();
|
|
permission.orgRootId = root.id;
|
|
permission.profileId = profile.id;
|
|
permission.createdUserId = request.user.sub;
|
|
permission.createdFullName = request.user.name;
|
|
permission.lastUpdateUserId = request.user.sub;
|
|
permission.lastUpdateFullName = request.user.name;
|
|
permission.createdAt = new Date();
|
|
permission.lastUpdatedAt = new Date();
|
|
return permission;
|
|
});
|
|
await this.permissionOrgRepository.save(_permissionOrg);
|
|
}
|
|
|
|
return new HttpSuccess();
|
|
}
|
|
|
|
/**
|
|
* API ลบข้าราชการในโครงสร้าง
|
|
*
|
|
* @summary - ลบข้าราชการในโครงสร้าง (ADMIN)
|
|
*
|
|
*/
|
|
@Get("delete/profile-officer/org/{orgRevisionId}")
|
|
async deleteOfficerRetireInOrg(
|
|
@Path() orgRevisionId: string,
|
|
@Request() request: RequestWithUser,
|
|
) {
|
|
const posMasters = await this.posMasterRepository.find({
|
|
where: {
|
|
orgRevisionId,
|
|
current_holderId: Not(IsNull()),
|
|
current_holder: {
|
|
isLeave: true,
|
|
isRetirement: true,
|
|
},
|
|
// positions: { positionIsSelected: true },
|
|
},
|
|
relations: ["positions"],
|
|
});
|
|
|
|
let checkOfficer = 0;
|
|
|
|
await Promise.all([
|
|
posMasters.map(async (posMaster) => {
|
|
posMaster.current_holderId = null;
|
|
posMaster.isSit = false;
|
|
if (posMaster.positions) {
|
|
for (const position of posMaster.positions) {
|
|
position.positionIsSelected = false;
|
|
await this.positionRepository.save(position);
|
|
checkOfficer += 1;
|
|
}
|
|
}
|
|
await this.posMasterRepository.save(posMaster);
|
|
await CreatePosMasterHistoryOfficer(posMaster.id, null);
|
|
}),
|
|
]);
|
|
|
|
return new HttpSuccess({
|
|
totalOfficer: posMasters.length,
|
|
officerSuccessAmount: checkOfficer,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* API ลบลูกจ้างในโครงสร้าง
|
|
*
|
|
* @summary - ลบลูกจ้างในโครงสร้าง (ADMIN)
|
|
*
|
|
*/
|
|
@Get("delete/profile-emp/org/{orgRevisionId}")
|
|
async deleteRetireEmpInOrg(@Path() orgRevisionId: string, @Request() request: RequestWithUser) {
|
|
const posMastersEmployee = await this.employeePosMasterRepository.find({
|
|
where: {
|
|
orgRevisionId,
|
|
current_holderId: Not(IsNull()),
|
|
current_holder: {
|
|
isLeave: true,
|
|
isRetirement: true,
|
|
},
|
|
// positions: { positionIsSelected: true },
|
|
},
|
|
relations: ["positions"],
|
|
});
|
|
|
|
let checkEmployee = 0;
|
|
|
|
await Promise.all(
|
|
posMastersEmployee.map(async (posMaster) => {
|
|
posMaster.current_holderId = null;
|
|
posMaster.isSit = false;
|
|
if (posMaster.positions) {
|
|
for (const position of posMaster.positions) {
|
|
position.positionIsSelected = false;
|
|
await this.employeePositionRepository.save(position);
|
|
checkEmployee += 1;
|
|
}
|
|
}
|
|
await this.employeePosMasterRepository.save(posMaster);
|
|
await CreatePosMasterHistoryEmployee(posMaster.id, null);
|
|
}),
|
|
);
|
|
|
|
return new HttpSuccess({
|
|
totalEmployee: posMastersEmployee.length,
|
|
employeeSuccessAmount: checkEmployee,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* API บันทึกลงประวัติตำแหน่ง
|
|
*
|
|
* @summary - บันทึกลงประวัติตำแหน่ง (ADMIN)
|
|
*
|
|
*/
|
|
@Get("save/profile/position-history")
|
|
async saveRetireToPositionHistory(@Request() request: RequestWithUser) {
|
|
const [profileLeave, profileEmployeeLeave] = await Promise.all([
|
|
this.profileRepo.find({
|
|
where: {
|
|
isLeave: true,
|
|
isRetirement: true,
|
|
leaveType: IsNull(),
|
|
},
|
|
}),
|
|
this.profileEmployeeRepo.find({
|
|
where: {
|
|
isLeave: true,
|
|
isRetirement: true,
|
|
leaveType: IsNull(),
|
|
},
|
|
}),
|
|
]);
|
|
|
|
let checkOfficer: number = 0;
|
|
await Promise.all(
|
|
profileLeave.map(async (profile: any) => {
|
|
const dest_item = await this.profileSalaryRepository.findOne({
|
|
where: { profileId: profile.id },
|
|
order: { order: "DESC" },
|
|
});
|
|
const data: any = {
|
|
order: dest_item == null ? 1 : dest_item.order + 1,
|
|
amount: null,
|
|
positionSalaryAmount: null,
|
|
mouthSalaryAmount: null,
|
|
profileId: profile.id,
|
|
posNo: null,
|
|
positionExecutive: null,
|
|
positionType: null,
|
|
positionLevel: null,
|
|
amountSpecial: null,
|
|
orgRoot: null,
|
|
orgChild1: null,
|
|
orgChild2: null,
|
|
orgChild3: null,
|
|
orgChild4: null,
|
|
commandYear: new Date().getFullYear() + 543,
|
|
commandDateAffect: profile.dateLeave,
|
|
commandCode: "16",
|
|
commandName: "พ้นจากราชการ",
|
|
posNoAbb: null,
|
|
isEntry: false,
|
|
positionName: "เกษียณอายุราชการ",
|
|
createdUserId: request.user.sub,
|
|
createdFullName: request.user.name,
|
|
lastUpdateUserId: request.user.sub,
|
|
lastUpdateFullName: request.user.name,
|
|
createdAt: new Date(),
|
|
lastUpdatedAt: new Date(),
|
|
remark: "ประกาศคณะอนุกรรมการสามัญข้าราชการกรุงเทพมหานครสามัญ ลว. 31 มี.ค. 68", // script เกษียณจริง ๆ ให้เอา “วันที่ประกาศเกษียณฉบับแรก” มาลงในเอกสารอ้างอิง
|
|
isGovernment: false,
|
|
};
|
|
|
|
const history = new ProfileSalaryHistory();
|
|
Object.assign(history, { ...data, id: undefined });
|
|
data.dateGovernment = profile.dateLeave;
|
|
const savedData = await this.profileSalaryRepository.save(data);
|
|
|
|
history.profileSalaryId = savedData.id;
|
|
await this.salaryHistoryRepo.save(history);
|
|
|
|
checkOfficer += 1;
|
|
}),
|
|
);
|
|
|
|
let checkEmployee: number = 0;
|
|
await Promise.all(
|
|
profileEmployeeLeave.map(async (profile: any) => {
|
|
const dest_item = await this.profileSalaryRepository.findOne({
|
|
where: { profileEmployeeId: profile.id },
|
|
order: { order: "DESC" },
|
|
});
|
|
const data: any = {
|
|
order: dest_item == null ? 1 : dest_item.order + 1,
|
|
amount: null,
|
|
positionSalaryAmount: null,
|
|
mouthSalaryAmount: null,
|
|
profileEmployeeId: profile.id,
|
|
posNo: null,
|
|
positionExecutive: null,
|
|
positionType: null,
|
|
positionLevel: null,
|
|
amountSpecial: null,
|
|
orgRoot: null,
|
|
orgChild1: null,
|
|
orgChild2: null,
|
|
orgChild3: null,
|
|
orgChild4: null,
|
|
commandYear: new Date().getFullYear() + 543,
|
|
commandDateAffect: profile.dateLeave,
|
|
commandCode: "16",
|
|
commandName: "พ้นจากราชการ",
|
|
posNoAbb: null,
|
|
isEntry: false,
|
|
positionName: "เกษียณอายุราชการ",
|
|
createdUserId: request.user.sub,
|
|
createdFullName: request.user.name,
|
|
lastUpdateUserId: request.user.sub,
|
|
lastUpdateFullName: request.user.name,
|
|
createdAt: new Date(),
|
|
lastUpdatedAt: new Date(),
|
|
remark: "ประกาศคณะอนุกรรมการสามัญข้าราชการกรุงเทพมหานครสามัญ ลว. 31 มี.ค. 68", // script เกษียณจริง ๆ ให้เอา “วันที่ประกาศเกษียณฉบับแรก” มาลงในเอกสารอ้างอิง
|
|
isGovernment: false,
|
|
};
|
|
|
|
const history = new ProfileSalaryHistory();
|
|
Object.assign(history, { ...data, id: undefined });
|
|
data.dateGovernment = profile.dateLeave;
|
|
const savedData = await this.profileSalaryRepository.save(data);
|
|
|
|
history.profileSalaryId = savedData.id;
|
|
await this.salaryHistoryRepo.save(history);
|
|
|
|
checkEmployee += 1;
|
|
}),
|
|
);
|
|
|
|
// จำนวนคนที่บันทึกลงประวัติตำแหน่ง
|
|
const totalOfficer = profileLeave.length;
|
|
const totalEmployee = profileEmployeeLeave.length;
|
|
// จำนวนคนที่ถูกบันทึกลงประวัติตำแหน่งสำเร็จ
|
|
return new HttpSuccess({
|
|
totalOfficer,
|
|
totalEmployee,
|
|
officerSuccessAmount: checkOfficer,
|
|
successEmployeeAmount: checkEmployee,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* API แก้ไขเหตุผลการลาออก และปลดจาก keycloak
|
|
*
|
|
* @summary - แก้ไขเหตุผลการลาออก และปลดจาก keycloak (ADMIN)
|
|
*
|
|
*/
|
|
@Get("update/profile/leave-reason")
|
|
async updateRetireReason() {
|
|
const [profileLeave, profileEmployeeLeave, token] = await Promise.all([
|
|
this.profileRepo.find({
|
|
where: {
|
|
isLeave: true,
|
|
isRetirement: true,
|
|
leaveType: IsNull(),
|
|
},
|
|
}),
|
|
this.profileEmployeeRepo.find({
|
|
where: {
|
|
isLeave: true,
|
|
isRetirement: true,
|
|
leaveType: IsNull(),
|
|
},
|
|
}),
|
|
getToken(),
|
|
]);
|
|
|
|
if (!token)
|
|
throw new HttpError(HttpStatusCode.INTERNAL_SERVER_ERROR, "ไม่สามารถเชื่อมต่อ Keycloak");
|
|
|
|
let checkOfficer: number = 0;
|
|
let notDeleteOfficer: string[] = [];
|
|
|
|
await Promise.all(
|
|
profileLeave.map(async (profile) => {
|
|
profile.leaveReason = "เกษียณอายุราชการ";
|
|
profile.leaveType = "RETIRE";
|
|
profile.isActive = false;
|
|
|
|
if (profile.keycloak != null && profile.keycloak != "" && profile.isDelete === false) {
|
|
const delUserKeycloak = await deleteUser(profile.keycloak, token);
|
|
if (delUserKeycloak) {
|
|
// profile.keycloak = "";
|
|
profile.isDelete = true;
|
|
profile.roleKeycloaks = [];
|
|
checkOfficer += 1;
|
|
} else {
|
|
// push array not delete
|
|
notDeleteOfficer.push(profile.keycloak);
|
|
}
|
|
}
|
|
|
|
await this.profileRepo.save(profile);
|
|
}),
|
|
);
|
|
|
|
let checkEmployee: number = 0;
|
|
let notDeleteEmployee: string[] = [];
|
|
|
|
await Promise.all(
|
|
profileEmployeeLeave.map(async (profileEmp) => {
|
|
profileEmp.leaveReason = "เกษียณอายุราชการ";
|
|
profileEmp.leaveType = "RETIRE";
|
|
profileEmp.leaveDate = new Date("2025-09-30");
|
|
profileEmp.dateLeave = new Date("2025-09-30");
|
|
profileEmp.lastUpdatedAt = new Date();
|
|
profileEmp.isActive = false;
|
|
|
|
if (profileEmp.keycloak != null && profileEmp.keycloak != "" && profileEmp.isDelete === false) {
|
|
const delUserKeycloak = await deleteUser(profileEmp.keycloak, token);
|
|
if (delUserKeycloak) {
|
|
// profileEmp.keycloak = "";
|
|
profileEmp.isDelete = true;
|
|
profileEmp.roleKeycloaks = [];
|
|
checkEmployee += 1;
|
|
} else {
|
|
// push array not delete
|
|
notDeleteEmployee.push(profileEmp.keycloak);
|
|
}
|
|
}
|
|
|
|
await this.profileEmployeeRepo.save(profileEmp);
|
|
}),
|
|
);
|
|
|
|
// loop batch at 50 profiles
|
|
// const chunkSize = 50;
|
|
// for (let i = 0; i < profileLeave.length; i += chunkSize) {
|
|
// const chunk = profileLeave.slice(i, i + chunkSize);
|
|
// await Promise.all(
|
|
// chunk.map(async (profile) => {
|
|
// profile.leaveReason = "เกษียณอายุราชการ";
|
|
// profile.isActive = false;
|
|
|
|
// if (profile.keycloak != null && profile.keycloak != "") {
|
|
// const delUserKeycloak = await deleteUser(profile.keycloak, token);
|
|
// if (delUserKeycloak) {
|
|
// profile.keycloak = "";
|
|
// profile.roleKeycloaks = [];
|
|
// check += 1;
|
|
// } else {
|
|
// // push array not delete
|
|
// notDelete.push(profile.keycloak);
|
|
// }
|
|
// }
|
|
|
|
// await this.profileEmployeeRepo.save(profile);
|
|
// }),
|
|
// );
|
|
// }
|
|
|
|
// จำนวนคนที่ถูกแก้ไขเหตุผลการลาออก
|
|
const total = profileLeave.length;
|
|
return new HttpSuccess({
|
|
total,
|
|
successOfficerAmount: checkOfficer,
|
|
notDeleteOfficer,
|
|
successEmployeeAmount: checkEmployee,
|
|
notDeleteEmployee,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* API สร้าง keycloak ใหม่สำหรับข้าราชการที่รันเกษียณผิด
|
|
*
|
|
* @summary - สร้าง keycloak ใหม่สำหรับข้าราชการที่รันเกษียณผิด (ADMIN)
|
|
*
|
|
*/
|
|
@Get("update/org/profile-officer/create-keycloak")
|
|
async createKeycloakForOfficer(@Request() request: RequestWithUser) {
|
|
const [profiles, token] = await Promise.all([
|
|
this.profileRepo.find({
|
|
where: {
|
|
keycloak: IsNull(),
|
|
isActive: true,
|
|
},
|
|
relations: ["roleKeycloaks"],
|
|
}),
|
|
getToken(),
|
|
]);
|
|
|
|
if (!token)
|
|
throw new HttpError(HttpStatusCode.INTERNAL_SERVER_ERROR, "ไม่สามารถเชื่อมต่อ Keycloak");
|
|
|
|
let check: number = 0;
|
|
for await (const _item of profiles) {
|
|
let password = _item.citizenId;
|
|
if (_item.birthDate != null) {
|
|
const _date = new Date(_item.birthDate.toDateString())
|
|
.getDate()
|
|
.toString()
|
|
.padStart(2, "0");
|
|
const _month = (new Date(_item.birthDate.toDateString()).getMonth() + 1)
|
|
.toString()
|
|
.padStart(2, "0");
|
|
const _year = new Date(_item.birthDate.toDateString()).getFullYear() + 543;
|
|
password = `${_date}${_month}${_year}`;
|
|
}
|
|
const checkUser = await getUserByUsername(_item.citizenId, token);
|
|
let userId: any = "";
|
|
if (checkUser.length == 0) {
|
|
userId = await createUser(
|
|
_item.citizenId,
|
|
password,
|
|
{
|
|
firstName: _item.firstName,
|
|
lastName: _item.lastName,
|
|
// email: _item.email,
|
|
},
|
|
token,
|
|
);
|
|
if (typeof userId !== "string") {
|
|
throw new Error(userId.errorMessage);
|
|
}
|
|
} else {
|
|
userId = checkUser[0].id;
|
|
}
|
|
|
|
const list = await getRoles("", token);
|
|
if (!Array.isArray(list)) throw new Error("Failed. Cannot get role(s) data from the server.");
|
|
const result = await addUserRoles(
|
|
userId,
|
|
list.filter((v) => v.id == "8a1a0dc9-304c-4e5b-a90a-65f841048212"),
|
|
token,
|
|
);
|
|
|
|
if (!result) {
|
|
throw new Error("Failed. Cannot set user's role.");
|
|
}
|
|
if (typeof userId === "string") {
|
|
_item.keycloak = userId;
|
|
}
|
|
const roleKeycloak = await this.roleKeycloakRepo.find({
|
|
where: { id: "8a1a0dc9-304c-4e5b-a90a-65f841048212" },
|
|
});
|
|
if (_item) {
|
|
_item.roleKeycloaks = Array.from(new Set([..._item.roleKeycloaks, ...roleKeycloak]));
|
|
this.profileRepo.save(_item);
|
|
check += 1;
|
|
}
|
|
}
|
|
|
|
const total = profiles.length;
|
|
|
|
return new HttpSuccess({ total, successAmount: check });
|
|
}
|
|
|
|
/**
|
|
* API สร้าง keycloak ใหม่สำหรับลูกจ้างที่รันเกษียณผิด
|
|
*
|
|
* @summary - สร้าง keycloak ใหม่สำหรับลูกจ้างที่รันเกษียณผิด (ADMIN)
|
|
*
|
|
*/
|
|
@Get("update/org/profile-employee/create-keycloak")
|
|
async createKeycloakForEmployee(@Request() request: RequestWithUser) {
|
|
let check: number = 0;
|
|
const profiles = await this.profileEmployeeRepo.find({
|
|
where: {
|
|
keycloak: IsNull(),
|
|
isLeave: false,
|
|
isRetirement: false,
|
|
},
|
|
order: { citizenId: "ASC" },
|
|
relations: ["roleKeycloaks"],
|
|
});
|
|
|
|
// ดึงข้อมูลที่ใช้บ่อยก่อน (cache)
|
|
const rolesList = await getRoles();
|
|
if (!Array.isArray(rolesList))
|
|
throw new Error("Failed. Cannot get role(s) data from the server.");
|
|
|
|
const roleKeycloak = await this.roleKeycloakRepo.find({
|
|
where: { id: "8a1a0dc9-304c-4e5b-a90a-65f841048212" },
|
|
});
|
|
|
|
// Process แบบ batch เพื่อลดการเรียก API ทีละตัว
|
|
const batchSize = 100;
|
|
const batches = [];
|
|
for (let i = 0; i < profiles.length; i += batchSize) {
|
|
batches.push(profiles.slice(i, i + batchSize));
|
|
}
|
|
for (const batch of batches) {
|
|
await Promise.all(
|
|
batch.map(async (_item) => {
|
|
let password = _item.citizenId;
|
|
if (_item.birthDate != null) {
|
|
const _date = new Date(_item.birthDate.toDateString())
|
|
.getDate()
|
|
.toString()
|
|
.padStart(2, "0");
|
|
const _month = (new Date(_item.birthDate.toDateString()).getMonth() + 1)
|
|
.toString()
|
|
.padStart(2, "0");
|
|
const _year = new Date(_item.birthDate.toDateString()).getFullYear() + 543;
|
|
password = `${_date}${_month}${_year}`;
|
|
}
|
|
|
|
try {
|
|
const checkUser = await getUserByUsername(_item.citizenId);
|
|
let userId: any = "";
|
|
if (checkUser.length == 0) {
|
|
userId = await createUser(_item.citizenId, password, {
|
|
firstName: _item.firstName,
|
|
lastName: _item.lastName,
|
|
});
|
|
if (typeof userId !== "string") {
|
|
console.error(`Failed to create user for ${_item.citizenId}:`, userId.errorMessage);
|
|
return;
|
|
}
|
|
} else {
|
|
userId = checkUser[0].id;
|
|
}
|
|
|
|
const result = await addUserRoles(
|
|
userId,
|
|
rolesList.filter((v) => v.id == "8a1a0dc9-304c-4e5b-a90a-65f841048212"),
|
|
);
|
|
|
|
if (!result) {
|
|
console.error(`Failed to set role for user ${_item.citizenId}`);
|
|
return;
|
|
}
|
|
|
|
if (typeof userId === "string") {
|
|
_item.keycloak = userId;
|
|
}
|
|
if (_item) {
|
|
_item.roleKeycloaks = Array.from(new Set([..._item.roleKeycloaks, ...roleKeycloak]));
|
|
check += 1;
|
|
_item = await this.profileEmployeeRepo.save(_item);
|
|
// update user attribute in keycloak
|
|
await updateUserAttributes(_item.keycloak, {
|
|
profileId: [_item.id],
|
|
prefix: [_item.prefix || ""],
|
|
});
|
|
}
|
|
} catch (error) {
|
|
console.error(`Error processing ${_item.citizenId}:`, error);
|
|
}
|
|
}),
|
|
);
|
|
}
|
|
const total = profiles.length;
|
|
return new HttpSuccess({ total, successAmount: check });
|
|
}
|
|
|
|
/**
|
|
* API ย้ายโครงสร้างแบบร่างไปโครงสร้างปัจจุบัน โดยอ้างอิงตาม rootId
|
|
*
|
|
* @summary - ย้ายโครงสร้างและตำแหน่งจากแบบร่างไปโครงสร้างปัจจุบัน โดยอ้างอิงตาม rootId
|
|
*
|
|
*/
|
|
@Post("move-draft-to-current/{rootDnaId}")
|
|
async moveDraftToCurrent(@Path() rootDnaId: string, @Request() request: RequestWithUser) {
|
|
const queryRunner = AppDataSource.createQueryRunner();
|
|
await queryRunner.connect();
|
|
await queryRunner.startTransaction();
|
|
|
|
try {
|
|
// permission owner only ??
|
|
// this code check...
|
|
|
|
// part 1 ข้อมูลโครงสร้าง
|
|
const [drafRevision, currentRevision] = await Promise.all([
|
|
this.orgRevisionRepository.findOne({
|
|
where: {
|
|
orgRevisionIsDraft: true,
|
|
orgRevisionIsCurrent: false,
|
|
},
|
|
select: ["id"],
|
|
}),
|
|
this.orgRevisionRepository.findOne({
|
|
where: {
|
|
orgRevisionIsDraft: false,
|
|
orgRevisionIsCurrent: true,
|
|
},
|
|
select: ["id"],
|
|
}),
|
|
]);
|
|
|
|
if (!drafRevision || !currentRevision)
|
|
return new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูล");
|
|
|
|
const drafRevisionId = drafRevision.id;
|
|
const currentRevisionId = currentRevision.id;
|
|
|
|
// ตรวจสอบว่ามี rootDnaId ในโครงสร้างร่าง และในโครงสร้างปัจจุบันหรือไม่
|
|
let [orgRootDraft, orgRootCurrent] = await Promise.all([
|
|
this.orgRootRepository.findOne({
|
|
where: {
|
|
ancestorDNA: rootDnaId,
|
|
orgRevisionId: drafRevisionId,
|
|
},
|
|
// select: ["id"],
|
|
}),
|
|
this.orgRootRepository.findOne({
|
|
where: {
|
|
ancestorDNA: rootDnaId,
|
|
orgRevisionId: currentRevisionId,
|
|
},
|
|
select: ["id"],
|
|
}),
|
|
]);
|
|
|
|
if (!orgRootDraft) return new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลโครงสร้างร่าง");
|
|
|
|
// if current record not found, create new one
|
|
if (!orgRootCurrent) {
|
|
// Create new current record using draft's ID
|
|
const newCurrentRoot = queryRunner.manager.create(OrgRoot, {
|
|
...orgRootDraft,
|
|
id: undefined, // Let database generate new ID
|
|
orgRevisionId: currentRevisionId, // Change to current revision
|
|
});
|
|
|
|
const savedRoot = await queryRunner.manager.save(OrgRoot, newCurrentRoot);
|
|
orgRootCurrent = savedRoot; // Use saved record for sync
|
|
}
|
|
|
|
// Part 1: Differential sync of organization structure (bottom-up)
|
|
// Build mapping incrementally as we process each level
|
|
|
|
const allMappings: AllOrgMappings = {
|
|
orgRoot: { byAncestorDNA: new Map(), byDraftId: new Map() },
|
|
orgChild1: { byAncestorDNA: new Map(), byDraftId: new Map() },
|
|
orgChild2: { byAncestorDNA: new Map(), byDraftId: new Map() },
|
|
orgChild3: { byAncestorDNA: new Map(), byDraftId: new Map() },
|
|
orgChild4: { byAncestorDNA: new Map(), byDraftId: new Map() },
|
|
};
|
|
|
|
// Track sync statistics for organization nodes
|
|
const orgSyncStats: Record<string, { deleted: number; updated: number; inserted: number }> =
|
|
{};
|
|
|
|
// Process from top (Root) to bottom (Child4) to handle foreign key constraints
|
|
// OrgRoot (sync first - no parent dependencies)
|
|
// If we manually created orgRootCurrent, skip syncOrgLevel and set up mapping directly
|
|
// to avoid double insert (syncOrgLevel would try to insert again because IDs don't match)
|
|
let orgRootResult: {
|
|
mapping: OrgIdMapping;
|
|
counts: { deleted: number; updated: number; inserted: number };
|
|
};
|
|
if (
|
|
orgRootCurrent &&
|
|
orgRootDraft &&
|
|
orgRootCurrent.ancestorDNA === orgRootDraft.ancestorDNA
|
|
) {
|
|
// Manually created - set up mapping directly
|
|
const rootMapping: OrgIdMapping = {
|
|
byAncestorDNA: new Map([[orgRootDraft.ancestorDNA, orgRootCurrent.id]]),
|
|
byDraftId: new Map([[orgRootDraft.id, orgRootCurrent.id]]),
|
|
};
|
|
orgRootResult = {
|
|
mapping: rootMapping,
|
|
counts: { deleted: 0, updated: 0, inserted: 1 }, // Count as insert since we created it
|
|
};
|
|
} else {
|
|
// Not manually created - use normal syncOrgLevel flow
|
|
orgRootResult = await this.syncOrgLevel(
|
|
queryRunner,
|
|
OrgRoot,
|
|
this.orgRootRepository,
|
|
drafRevisionId,
|
|
currentRevisionId,
|
|
allMappings,
|
|
orgRootDraft?.id,
|
|
orgRootCurrent?.id,
|
|
);
|
|
}
|
|
allMappings.orgRoot = orgRootResult.mapping;
|
|
orgSyncStats.orgRoot = orgRootResult.counts;
|
|
|
|
// Child1 (parent OrgRoot already synced)
|
|
const child1Result = await this.syncOrgLevel(
|
|
queryRunner,
|
|
OrgChild1,
|
|
this.child1Repository,
|
|
drafRevisionId,
|
|
currentRevisionId,
|
|
allMappings,
|
|
orgRootDraft?.id,
|
|
orgRootCurrent?.id,
|
|
);
|
|
allMappings.orgChild1 = child1Result.mapping;
|
|
orgSyncStats.orgChild1 = child1Result.counts;
|
|
|
|
// Child2 (parents OrgRoot and Child1 already synced)
|
|
const child2Result = await this.syncOrgLevel(
|
|
queryRunner,
|
|
OrgChild2,
|
|
this.child2Repository,
|
|
drafRevisionId,
|
|
currentRevisionId,
|
|
allMappings,
|
|
orgRootDraft?.id,
|
|
orgRootCurrent?.id,
|
|
);
|
|
allMappings.orgChild2 = child2Result.mapping;
|
|
orgSyncStats.orgChild2 = child2Result.counts;
|
|
|
|
// Child3 (parents OrgRoot, Child1, Child2 already synced)
|
|
const child3Result = await this.syncOrgLevel(
|
|
queryRunner,
|
|
OrgChild3,
|
|
this.child3Repository,
|
|
drafRevisionId,
|
|
currentRevisionId,
|
|
allMappings,
|
|
orgRootDraft?.id,
|
|
orgRootCurrent?.id,
|
|
);
|
|
allMappings.orgChild3 = child3Result.mapping;
|
|
orgSyncStats.orgChild3 = child3Result.counts;
|
|
|
|
// Child4 (parents OrgRoot, Child1, Child2, Child3 already synced)
|
|
const child4Result = await this.syncOrgLevel(
|
|
queryRunner,
|
|
OrgChild4,
|
|
this.child4Repository,
|
|
drafRevisionId,
|
|
currentRevisionId,
|
|
allMappings,
|
|
orgRootDraft?.id,
|
|
orgRootCurrent?.id,
|
|
);
|
|
allMappings.orgChild4 = child4Result.mapping;
|
|
orgSyncStats.orgChild4 = child4Result.counts;
|
|
|
|
// Part 2: Sync position data using new org IDs from Part 1
|
|
// 2.1 Clear current_holderId for affected positions (keep existing logic)
|
|
// Get draft organization IDs under the given rootDnaId to find positions to clear
|
|
const draftOrgIds = {
|
|
orgRoot: [...allMappings.orgRoot.byDraftId.keys()],
|
|
orgChild1: [...allMappings.orgChild1.byDraftId.keys()],
|
|
orgChild2: [...allMappings.orgChild2.byDraftId.keys()],
|
|
orgChild3: [...allMappings.orgChild3.byDraftId.keys()],
|
|
orgChild4: [...allMappings.orgChild4.byDraftId.keys()],
|
|
};
|
|
|
|
// Get current organization IDs from the mappings (moved up for reuse)
|
|
const currentOrgIds = {
|
|
orgRoot: [...allMappings.orgRoot.byDraftId.values()],
|
|
orgChild1: [...allMappings.orgChild1.byDraftId.values()],
|
|
orgChild2: [...allMappings.orgChild2.byDraftId.values()],
|
|
orgChild3: [...allMappings.orgChild3.byDraftId.values()],
|
|
orgChild4: [...allMappings.orgChild4.byDraftId.values()],
|
|
};
|
|
|
|
// Get draft positions that belong to any org under the rootDnaId
|
|
const posMasterDraft = await this.posMasterRepository.find({
|
|
where: [
|
|
{ orgRevisionId: drafRevisionId, orgRootId: In(draftOrgIds.orgRoot) },
|
|
{ orgRevisionId: drafRevisionId, orgChild1Id: In(draftOrgIds.orgChild1) },
|
|
{ orgRevisionId: drafRevisionId, orgChild2Id: In(draftOrgIds.orgChild2) },
|
|
{ orgRevisionId: drafRevisionId, orgChild3Id: In(draftOrgIds.orgChild3) },
|
|
{ orgRevisionId: drafRevisionId, orgChild4Id: In(draftOrgIds.orgChild4) },
|
|
],
|
|
});
|
|
|
|
// Special case: If draft has no positions, delete all current positions
|
|
if (posMasterDraft.length <= 0) {
|
|
// Fetch current positions
|
|
const posMasterCurrent = await this.posMasterRepository.find({
|
|
where: [
|
|
{ orgRevisionId: currentRevisionId, orgRootId: In(currentOrgIds.orgRoot) },
|
|
{ orgRevisionId: currentRevisionId, orgChild1Id: In(currentOrgIds.orgChild1) },
|
|
{ orgRevisionId: currentRevisionId, orgChild2Id: In(currentOrgIds.orgChild2) },
|
|
{ orgRevisionId: currentRevisionId, orgChild3Id: In(currentOrgIds.orgChild3) },
|
|
{ orgRevisionId: currentRevisionId, orgChild4Id: In(currentOrgIds.orgChild4) },
|
|
],
|
|
});
|
|
|
|
if (posMasterCurrent.length > 0) {
|
|
const toDeleteIds = posMasterCurrent.map((p) => p.id);
|
|
|
|
// Cascade delete positions first
|
|
await queryRunner.manager.delete(Position, { posMasterId: In(toDeleteIds) });
|
|
|
|
// Then delete posMaster records
|
|
await queryRunner.manager.delete(PosMaster, toDeleteIds);
|
|
|
|
// Save history
|
|
const deleteHistoryOps = posMasterCurrent.map((pos) => ({
|
|
posMasterDnaId: pos.ancestorDNA,
|
|
profileId: null,
|
|
pm: null,
|
|
}));
|
|
await BatchSavePosMasterHistoryOfficer(queryRunner, deleteHistoryOps);
|
|
}
|
|
|
|
// Build summary for this special case
|
|
const summary = {
|
|
message: "ย้ายโครงสร้างสำเร็จ",
|
|
organization: {
|
|
orgRoot: orgSyncStats.orgRoot,
|
|
orgChild1: orgSyncStats.orgChild1,
|
|
orgChild2: orgSyncStats.orgChild2,
|
|
orgChild3: orgSyncStats.orgChild3,
|
|
orgChild4: orgSyncStats.orgChild4,
|
|
},
|
|
positionMaster: {
|
|
deleted: posMasterCurrent.length,
|
|
updated: 0,
|
|
inserted: 0,
|
|
},
|
|
position: { deleted: 0, updated: 0, inserted: 0 },
|
|
};
|
|
|
|
await queryRunner.commitTransaction();
|
|
return new HttpSuccess(summary);
|
|
}
|
|
|
|
// Clear current_holderId for positions that will have new holders
|
|
const nextHolderIds = posMasterDraft
|
|
.filter((x) => x.next_holderId != null)
|
|
.map((x) => x.next_holderId) as string[];
|
|
|
|
if (nextHolderIds.length > 0) {
|
|
// FIX: Fetch positions first before updating (to avoid race condition)
|
|
const posMastersToUpdate = await queryRunner.manager.find(PosMaster, {
|
|
where: {
|
|
orgRevisionId: currentRevisionId,
|
|
current_holderId: In(nextHolderIds),
|
|
},
|
|
});
|
|
|
|
// Save history BEFORE clearing current_holderId
|
|
const historyOps = posMastersToUpdate
|
|
.filter((x) => x.orgRootId != orgRootCurrent?.id)
|
|
.map((pos) => ({
|
|
posMasterDnaId: pos.ancestorDNA,
|
|
profileId: null,
|
|
pm: null,
|
|
}));
|
|
await BatchSavePosMasterHistoryOfficer(queryRunner, historyOps);
|
|
|
|
// Now clear current_holderId
|
|
await queryRunner.manager.update(
|
|
PosMaster,
|
|
{
|
|
orgRevisionId: currentRevisionId,
|
|
current_holderId: In(nextHolderIds),
|
|
},
|
|
{ current_holderId: null, isSit: false },
|
|
);
|
|
}
|
|
|
|
// 2.2 Fetch current positions for comparison
|
|
const posMasterCurrent = await this.posMasterRepository.find({
|
|
where: [
|
|
{ orgRevisionId: currentRevisionId, orgRootId: In(currentOrgIds.orgRoot) },
|
|
{ orgRevisionId: currentRevisionId, orgChild1Id: In(currentOrgIds.orgChild1) },
|
|
{ orgRevisionId: currentRevisionId, orgChild2Id: In(currentOrgIds.orgChild2) },
|
|
{ orgRevisionId: currentRevisionId, orgChild3Id: In(currentOrgIds.orgChild3) },
|
|
{ orgRevisionId: currentRevisionId, orgChild4Id: In(currentOrgIds.orgChild4) },
|
|
],
|
|
});
|
|
|
|
// Build lookup map
|
|
const currentByDNA = new Map(posMasterCurrent.map((p) => [p.ancestorDNA, p]));
|
|
|
|
// 2.3 Batch DELETE: positions in current but not in draft
|
|
const toDelete = posMasterCurrent.filter(
|
|
(curr) => !posMasterDraft.some((d) => d.ancestorDNA === curr.ancestorDNA),
|
|
);
|
|
|
|
if (toDelete.length > 0) {
|
|
const toDeleteIds = toDelete.map((p) => p.id);
|
|
|
|
// Cascade delete positions first
|
|
await queryRunner.manager.delete(Position, { posMasterId: In(toDeleteIds) });
|
|
|
|
// Then delete posMaster records
|
|
await queryRunner.manager.delete(PosMaster, toDeleteIds);
|
|
|
|
const deleteHistoryOps = toDelete.map((pos) => ({
|
|
posMasterDnaId: pos.ancestorDNA,
|
|
profileId: null,
|
|
pm: null,
|
|
}));
|
|
await BatchSavePosMasterHistoryOfficer(queryRunner, deleteHistoryOps);
|
|
}
|
|
|
|
// 2.4 Process draft positions (UPDATE or INSERT)
|
|
const toUpdate: PosMaster[] = [];
|
|
const toInsert: any[] = [];
|
|
|
|
// Track draft PosMaster ID to current PosMaster ID mapping for position sync
|
|
// Type: Map<draftPosMasterId, [currentPosMasterId, nextHolderId]>
|
|
const posMasterMapping: Map<string, [string, string | null | undefined]> = new Map();
|
|
|
|
for (const draftPos of posMasterDraft) {
|
|
const current = currentByDNA.get(draftPos.ancestorDNA);
|
|
|
|
// Map organization IDs using new IDs from Part 1
|
|
const orgRootId = this.resolveOrgId(draftPos.orgRootId ?? null, allMappings.orgRoot);
|
|
const orgChild1Id = this.resolveOrgId(draftPos.orgChild1Id ?? null, allMappings.orgChild1);
|
|
const orgChild2Id = this.resolveOrgId(draftPos.orgChild2Id ?? null, allMappings.orgChild2);
|
|
const orgChild3Id = this.resolveOrgId(draftPos.orgChild3Id ?? null, allMappings.orgChild3);
|
|
const orgChild4Id = this.resolveOrgId(draftPos.orgChild4Id ?? null, allMappings.orgChild4);
|
|
|
|
if (current) {
|
|
// UPDATE existing position
|
|
Object.assign(current, {
|
|
createdAt: draftPos.createdAt,
|
|
createdUserId: draftPos.createdUserId,
|
|
createdFullName: draftPos.createdFullName,
|
|
lastUpdatedAt: new Date(),
|
|
lastUpdateUserId: request.user.sub,
|
|
lastUpdateFullName: request.user.name,
|
|
posMasterNoPrefix: draftPos.posMasterNoPrefix,
|
|
posMasterNoSuffix: draftPos.posMasterNoSuffix,
|
|
posMasterNo: draftPos.posMasterNo,
|
|
posMasterOrder: draftPos.posMasterOrder,
|
|
orgRootId,
|
|
orgChild1Id,
|
|
orgChild2Id,
|
|
orgChild3Id,
|
|
orgChild4Id,
|
|
current_holderId: draftPos.next_holderId,
|
|
isSit: draftPos.isSit,
|
|
reason: draftPos.reason,
|
|
isDirector: draftPos.isDirector,
|
|
isStaff: draftPos.isStaff,
|
|
positionSign: draftPos.positionSign,
|
|
statusReport: "DONE",
|
|
isCondition: draftPos.isCondition,
|
|
conditionReason: draftPos.conditionReason,
|
|
});
|
|
toUpdate.push(current);
|
|
|
|
if (draftPos.next_holderId === null) {
|
|
await SavePosMasterHistoryOfficer(queryRunner, draftPos.ancestorDNA, null, null);
|
|
}
|
|
|
|
// Track mapping for position sync
|
|
posMasterMapping.set(draftPos.id, [current.id, draftPos.next_holderId]);
|
|
} else {
|
|
// INSERT new position
|
|
const newPosMaster = queryRunner.manager.create(PosMaster, {
|
|
...draftPos,
|
|
id: undefined,
|
|
orgRevisionId: currentRevisionId,
|
|
orgRootId,
|
|
orgChild1Id,
|
|
orgChild2Id,
|
|
orgChild3Id,
|
|
orgChild4Id,
|
|
current_holderId: draftPos.next_holderId,
|
|
statusReport: "DONE",
|
|
});
|
|
|
|
toInsert.push(newPosMaster);
|
|
}
|
|
}
|
|
|
|
// Batch save updates and inserts
|
|
if (toUpdate.length > 0) {
|
|
await queryRunner.manager.save(toUpdate);
|
|
}
|
|
if (toInsert.length > 0) {
|
|
const saved = await queryRunner.manager.save(toInsert);
|
|
|
|
// Track mapping for newly inserted posMasters
|
|
// saved is an array, map each to its draft ID
|
|
if (Array.isArray(saved)) {
|
|
for (let i = 0; i < saved.length; i++) {
|
|
const draftPos = posMasterDraft.filter((d) => !currentByDNA.has(d.ancestorDNA))[i];
|
|
if (draftPos && saved[i]) {
|
|
posMasterMapping.set(draftPos.id, [saved[i].id, draftPos.next_holderId]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 2.5 Sync positions table for all affected posMasters (BATCH operation for performance)
|
|
const positionSyncStats = await this.syncAllPositionsBatch(
|
|
queryRunner,
|
|
posMasterMapping,
|
|
drafRevisionId,
|
|
currentRevisionId,
|
|
);
|
|
|
|
// Build comprehensive summary
|
|
const summary = {
|
|
message: "ย้ายโครงสร้างสำเร็จ",
|
|
organization: {
|
|
orgRoot: orgSyncStats.orgRoot,
|
|
orgChild1: orgSyncStats.orgChild1,
|
|
orgChild2: orgSyncStats.orgChild2,
|
|
orgChild3: orgSyncStats.orgChild3,
|
|
orgChild4: orgSyncStats.orgChild4,
|
|
},
|
|
positionMaster: {
|
|
deleted: toDelete.length,
|
|
updated: toUpdate.length,
|
|
inserted: toInsert.length,
|
|
},
|
|
position: positionSyncStats,
|
|
};
|
|
|
|
await queryRunner.commitTransaction();
|
|
return new HttpSuccess(summary);
|
|
} catch (error) {
|
|
console.error("Error moving draft to current:", error);
|
|
await queryRunner.rollbackTransaction();
|
|
throw new HttpError(HttpStatusCode.INTERNAL_SERVER_ERROR, "เกิดข้อผิดพลาดในการย้ายโครงสร้าง");
|
|
} finally {
|
|
if (queryRunner.isTransactionActive) {
|
|
await queryRunner.rollbackTransaction();
|
|
}
|
|
await queryRunner.release();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper function: Map draft ID to current ID using the mapping
|
|
*/
|
|
private resolveOrgId(draftId: string | null, mapping: OrgIdMapping): string | null {
|
|
if (!draftId) return null;
|
|
return mapping.byDraftId.get(draftId) ?? null;
|
|
}
|
|
|
|
/**
|
|
* Helper function: Cascade delete positions before deleting org node
|
|
*/
|
|
private async cascadeDeletePositions(
|
|
queryRunner: any,
|
|
node: any,
|
|
entityClass: any,
|
|
): Promise<void> {
|
|
const whereClause: any = {
|
|
orgRevisionId: node.orgRevisionId,
|
|
};
|
|
|
|
// Determine which FK field to use based on entity type
|
|
if (entityClass === OrgRoot) {
|
|
whereClause.orgRootId = node.id;
|
|
} else if (entityClass === OrgChild1) {
|
|
whereClause.orgChild1Id = node.id;
|
|
} else if (entityClass === OrgChild2) {
|
|
whereClause.orgChild2Id = node.id;
|
|
} else if (entityClass === OrgChild3) {
|
|
whereClause.orgChild3Id = node.id;
|
|
} else if (entityClass === OrgChild4) {
|
|
whereClause.orgChild4Id = node.id;
|
|
}
|
|
|
|
await queryRunner.manager.delete(PosMaster, whereClause);
|
|
}
|
|
|
|
/**
|
|
* Helper function: Generic differential sync for each org level
|
|
* Performs DELETE (nodes not in draft), UPDATE (existing nodes), INSERT (new nodes)
|
|
*/
|
|
private async syncOrgLevel<T extends OrgRoot | OrgChild1 | OrgChild2 | OrgChild3 | OrgChild4>(
|
|
queryRunner: any,
|
|
entityClass: any,
|
|
repository: any,
|
|
draftRevisionId: string,
|
|
currentRevisionId: string,
|
|
parentMappings?: AllOrgMappings,
|
|
draftOrgRootId?: string,
|
|
currentOrgRootId?: string,
|
|
): Promise<{
|
|
mapping: OrgIdMapping;
|
|
counts: { deleted: number; updated: number; inserted: number };
|
|
}> {
|
|
// 1. Fetch draft and current nodes under the given rootDnaId
|
|
// Build WHERE condition for draft nodes
|
|
const draftWhere: any = {
|
|
orgRevisionId: draftRevisionId,
|
|
};
|
|
if (
|
|
draftOrgRootId &&
|
|
(entityClass === OrgChild1 ||
|
|
entityClass === OrgChild2 ||
|
|
entityClass === OrgChild3 ||
|
|
entityClass === OrgChild4)
|
|
) {
|
|
draftWhere.orgRootId = draftOrgRootId;
|
|
} else if (entityClass === OrgRoot) {
|
|
draftWhere.id = draftOrgRootId;
|
|
}
|
|
|
|
// Build WHERE condition for current nodes
|
|
const currentWhere: any = {
|
|
orgRevisionId: currentRevisionId,
|
|
};
|
|
if (
|
|
currentOrgRootId &&
|
|
(entityClass === OrgChild1 ||
|
|
entityClass === OrgChild2 ||
|
|
entityClass === OrgChild3 ||
|
|
entityClass === OrgChild4)
|
|
) {
|
|
currentWhere.orgRootId = currentOrgRootId;
|
|
} else if (entityClass === OrgRoot) {
|
|
currentWhere.id = currentOrgRootId;
|
|
}
|
|
|
|
const [draftNodes, currentNodes] = await Promise.all([
|
|
repository.find({ where: draftWhere }),
|
|
repository.find({ where: currentWhere }),
|
|
]);
|
|
|
|
// 2. Build lookup maps for efficient matching by ancestorDNA
|
|
const draftByDNA = new Map(draftNodes.map((n: any) => [n.ancestorDNA, n]));
|
|
const currentByDNA = new Map(currentNodes.map((n: any) => [n.ancestorDNA, n]));
|
|
|
|
const mapping: OrgIdMapping = {
|
|
byAncestorDNA: new Map(),
|
|
byDraftId: new Map(),
|
|
};
|
|
|
|
// 3. DELETE: Current nodes not in draft (cascade delete positions first)
|
|
const toDelete = currentNodes.filter((curr: any) => !draftByDNA.has(curr.ancestorDNA));
|
|
for (const node of toDelete) {
|
|
// Cascade delete positions first
|
|
await this.cascadeDeletePositions(queryRunner, node, entityClass);
|
|
await queryRunner.manager.delete(entityClass, node.id);
|
|
}
|
|
|
|
// 4. UPDATE: Nodes that exist in both draft and current (matched by ancestorDNA)
|
|
const toUpdate = draftNodes.filter((draft: any) => currentByDNA.has(draft.ancestorDNA));
|
|
for (const draft of toUpdate) {
|
|
const current: any = currentByDNA.get(draft.ancestorDNA)!;
|
|
|
|
// Build update data with mapped parent IDs
|
|
const updateData: any = {
|
|
...draft,
|
|
id: current.id,
|
|
orgRevisionId: currentRevisionId,
|
|
};
|
|
|
|
// Map parent IDs based on entity level
|
|
if (entityClass === OrgChild1 && draft.orgRootId && parentMappings) {
|
|
updateData.orgRootId =
|
|
parentMappings.orgRoot.byDraftId.get(draft.orgRootId) ?? draft.orgRootId;
|
|
} else if (entityClass === OrgChild2) {
|
|
if (draft.orgRootId && parentMappings) {
|
|
updateData.orgRootId =
|
|
parentMappings.orgRoot.byDraftId.get(draft.orgRootId) ?? draft.orgRootId;
|
|
}
|
|
if (draft.orgChild1Id && parentMappings) {
|
|
updateData.orgChild1Id =
|
|
parentMappings.orgChild1.byDraftId.get(draft.orgChild1Id) ?? draft.orgChild1Id;
|
|
}
|
|
} else if (entityClass === OrgChild3) {
|
|
if (draft.orgRootId && parentMappings) {
|
|
updateData.orgRootId =
|
|
parentMappings.orgRoot.byDraftId.get(draft.orgRootId) ?? draft.orgRootId;
|
|
}
|
|
if (draft.orgChild1Id && parentMappings) {
|
|
updateData.orgChild1Id =
|
|
parentMappings.orgChild1.byDraftId.get(draft.orgChild1Id) ?? draft.orgChild1Id;
|
|
}
|
|
if (draft.orgChild2Id && parentMappings) {
|
|
updateData.orgChild2Id =
|
|
parentMappings.orgChild2.byDraftId.get(draft.orgChild2Id) ?? draft.orgChild2Id;
|
|
}
|
|
} else if (entityClass === OrgChild4) {
|
|
if (draft.orgRootId && parentMappings) {
|
|
updateData.orgRootId =
|
|
parentMappings.orgRoot.byDraftId.get(draft.orgRootId) ?? draft.orgRootId;
|
|
}
|
|
if (draft.orgChild1Id && parentMappings) {
|
|
updateData.orgChild1Id =
|
|
parentMappings.orgChild1.byDraftId.get(draft.orgChild1Id) ?? draft.orgChild1Id;
|
|
}
|
|
if (draft.orgChild2Id && parentMappings) {
|
|
updateData.orgChild2Id =
|
|
parentMappings.orgChild2.byDraftId.get(draft.orgChild2Id) ?? draft.orgChild2Id;
|
|
}
|
|
if (draft.orgChild3Id && parentMappings) {
|
|
updateData.orgChild3Id =
|
|
parentMappings.orgChild3.byDraftId.get(draft.orgChild3Id) ?? draft.orgChild3Id;
|
|
}
|
|
}
|
|
|
|
await queryRunner.manager.update(entityClass, current.id, updateData);
|
|
|
|
mapping.byAncestorDNA.set(draft.ancestorDNA, current.id);
|
|
mapping.byDraftId.set(draft.id, current.id);
|
|
}
|
|
|
|
// 5. INSERT: Draft nodes not in current
|
|
const toInsert = draftNodes.filter((draft: any) => !currentByDNA.has(draft.ancestorDNA));
|
|
for (const draft of toInsert) {
|
|
const newNode: any = queryRunner.manager.create(entityClass, {
|
|
...draft,
|
|
id: undefined,
|
|
orgRevisionId: currentRevisionId,
|
|
});
|
|
|
|
// Map parent IDs based on entity level
|
|
if (entityClass === OrgChild1 && draft.orgRootId) {
|
|
if (draft.orgRootId === draftOrgRootId) {
|
|
newNode.orgRootId = currentOrgRootId;
|
|
} else if (parentMappings) {
|
|
newNode.orgRootId = parentMappings.orgRoot.byDraftId.get(draft.orgRootId);
|
|
}
|
|
} else if (entityClass === OrgChild2) {
|
|
if (draft.orgRootId) {
|
|
if (draft.orgRootId === draftOrgRootId) {
|
|
newNode.orgRootId = currentOrgRootId;
|
|
} else if (parentMappings) {
|
|
newNode.orgRootId = parentMappings.orgRoot.byDraftId.get(draft.orgRootId);
|
|
}
|
|
}
|
|
if (draft.orgChild1Id && parentMappings) {
|
|
const mappedChild1Id = parentMappings.orgChild1.byDraftId.get(draft.orgChild1Id);
|
|
if (mappedChild1Id) {
|
|
newNode.orgChild1Id = mappedChild1Id;
|
|
}
|
|
}
|
|
} else if (entityClass === OrgChild3) {
|
|
if (draft.orgRootId) {
|
|
if (draft.orgRootId === draftOrgRootId) {
|
|
newNode.orgRootId = currentOrgRootId;
|
|
} else if (parentMappings) {
|
|
newNode.orgRootId = parentMappings.orgRoot.byDraftId.get(draft.orgRootId);
|
|
}
|
|
}
|
|
if (draft.orgChild1Id && parentMappings) {
|
|
const mappedChild1Id = parentMappings.orgChild1.byDraftId.get(draft.orgChild1Id);
|
|
if (mappedChild1Id) {
|
|
newNode.orgChild1Id = mappedChild1Id;
|
|
}
|
|
}
|
|
if (draft.orgChild2Id && parentMappings) {
|
|
const mappedChild2Id = parentMappings.orgChild2.byDraftId.get(draft.orgChild2Id);
|
|
if (mappedChild2Id) {
|
|
newNode.orgChild2Id = mappedChild2Id;
|
|
}
|
|
}
|
|
} else if (entityClass === OrgChild4) {
|
|
if (draft.orgRootId) {
|
|
if (draft.orgRootId === draftOrgRootId) {
|
|
newNode.orgRootId = currentOrgRootId;
|
|
} else if (parentMappings) {
|
|
newNode.orgRootId = parentMappings.orgRoot.byDraftId.get(draft.orgRootId);
|
|
}
|
|
}
|
|
if (draft.orgChild1Id && parentMappings) {
|
|
const mappedChild1Id = parentMappings.orgChild1.byDraftId.get(draft.orgChild1Id);
|
|
if (mappedChild1Id) {
|
|
newNode.orgChild1Id = mappedChild1Id;
|
|
}
|
|
}
|
|
if (draft.orgChild2Id && parentMappings) {
|
|
const mappedChild2Id = parentMappings.orgChild2.byDraftId.get(draft.orgChild2Id);
|
|
if (mappedChild2Id) {
|
|
newNode.orgChild2Id = mappedChild2Id;
|
|
}
|
|
}
|
|
if (draft.orgChild3Id && parentMappings) {
|
|
const mappedChild3Id = parentMappings.orgChild3.byDraftId.get(draft.orgChild3Id);
|
|
if (mappedChild3Id) {
|
|
newNode.orgChild3Id = mappedChild3Id;
|
|
}
|
|
}
|
|
}
|
|
|
|
const saved = await queryRunner.manager.save(newNode);
|
|
|
|
mapping.byAncestorDNA.set(draft.ancestorDNA, saved.id);
|
|
mapping.byDraftId.set(draft.id, saved.id);
|
|
}
|
|
|
|
return {
|
|
mapping,
|
|
counts: {
|
|
deleted: toDelete.length,
|
|
updated: toUpdate.length,
|
|
inserted: toInsert.length,
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Batch version: Sync positions for ALL posMasters in a single operation
|
|
* This significantly reduces database round trips for large organizations
|
|
*/
|
|
private async syncAllPositionsBatch(
|
|
queryRunner: any,
|
|
posMasterMapping: Map<string, [string, string | null | undefined]>,
|
|
_draftRevisionId: string,
|
|
_currentRevisionId: string,
|
|
): Promise<{ deleted: number; updated: number; inserted: number }> {
|
|
// Extract draft and current posMaster IDs
|
|
const draftPosMasterIds = Array.from(posMasterMapping.keys());
|
|
const currentPosMasterIds = Array.from(posMasterMapping.values()).map(
|
|
([currentId]) => currentId,
|
|
);
|
|
|
|
if (draftPosMasterIds.length === 0) {
|
|
return { deleted: 0, updated: 0, inserted: 0 };
|
|
}
|
|
|
|
// Fetch draft PosMasters with relations for history tracking
|
|
const draftPosMasters = await queryRunner.manager.find(PosMaster, {
|
|
where: { id: In(draftPosMasterIds) },
|
|
relations: ["orgRoot", "orgChild1", "orgChild2", "orgChild3", "orgChild4", "next_holder"],
|
|
});
|
|
|
|
// Fetch ALL positions for ALL posMasters in just 2 queries
|
|
const [allDraftPositions, allCurrentPositions] = await Promise.all([
|
|
queryRunner.manager.find(Position, {
|
|
where: {
|
|
posMasterId: In(draftPosMasterIds),
|
|
},
|
|
relations: ["posType", "posLevel", "posExecutive"],
|
|
order: { orderNo: "ASC" },
|
|
}),
|
|
queryRunner.manager.find(Position, {
|
|
where: {
|
|
posMasterId: In(currentPosMasterIds),
|
|
},
|
|
}),
|
|
]);
|
|
|
|
// Group positions by posMasterId for processing
|
|
const draftPositionsByMaster = new Map<string, any[]>();
|
|
for (const pos of allDraftPositions) {
|
|
if (!draftPositionsByMaster.has(pos.posMasterId)) {
|
|
draftPositionsByMaster.set(pos.posMasterId, []);
|
|
}
|
|
draftPositionsByMaster.get(pos.posMasterId)!.push(pos);
|
|
}
|
|
|
|
const currentPositionsByMaster = new Map<string, any[]>();
|
|
for (const pos of allCurrentPositions) {
|
|
if (!currentPositionsByMaster.has(pos.posMasterId)) {
|
|
currentPositionsByMaster.set(pos.posMasterId, []);
|
|
}
|
|
currentPositionsByMaster.get(pos.posMasterId)!.push(pos);
|
|
}
|
|
|
|
// Collect all operations
|
|
const allToDelete: string[] = [];
|
|
const allToDeleteHistory: string[] = [];
|
|
const allToUpdate: Array<{ id: string; data: any }> = [];
|
|
const allToInsert: Array<any> = [];
|
|
const profileUpdates: Map<string, any> = new Map();
|
|
|
|
// Create a map for quick lookup of draft PosMasters with relations
|
|
const draftPosMasterMap = new Map(draftPosMasters.map((pm: PosMaster) => [pm.id, pm]));
|
|
|
|
// Collect PosMasterHistory calls for selected positions
|
|
const historyCalls: Array<{
|
|
ancestorDNA: string;
|
|
profileId: string | null;
|
|
historyData: SavePosMasterHistory;
|
|
}> = [];
|
|
|
|
// Process each posMaster mapping
|
|
for (const [draftPosMasterId, [currentPosMasterId, nextHolderId]] of posMasterMapping) {
|
|
const draftPositions = draftPositionsByMaster.get(draftPosMasterId) || [];
|
|
const currentPositions = currentPositionsByMaster.get(currentPosMasterId) || [];
|
|
|
|
// If no draft positions, mark all current positions for deletion
|
|
if (draftPositions.length === 0) {
|
|
allToDelete.push(...currentPositions.map((p: any) => p.id));
|
|
allToDeleteHistory.push(...currentPositions.map((p: any) => p.ancestorDNA));
|
|
continue;
|
|
}
|
|
|
|
// Build map for tracking
|
|
const currentByOrderNo = new Map(currentPositions.map((p: any) => [p.orderNo, p]));
|
|
const draftOrderNos = new Set(draftPositions.map((p: any) => p.orderNo));
|
|
|
|
// Mark for deletion: current positions not in draft (by orderNo)
|
|
for (const currentPos of currentPositions) {
|
|
if (!draftOrderNos.has(currentPos.orderNo)) {
|
|
allToDelete.push(currentPos.id);
|
|
allToDeleteHistory.push(currentPos.ancestorDNA);
|
|
}
|
|
}
|
|
|
|
// Process UPDATE and INSERT
|
|
for (const draftPos of draftPositions) {
|
|
const current = currentByOrderNo.get(draftPos.orderNo);
|
|
|
|
if (current) {
|
|
// UPDATE existing position - collect for batch update
|
|
allToUpdate.push({
|
|
id: current.id,
|
|
data: {
|
|
positionName: draftPos.positionName,
|
|
positionField: draftPos.positionField,
|
|
posTypeId: draftPos.posTypeId,
|
|
posLevelId: draftPos.posLevelId,
|
|
posExecutiveId: draftPos.posExecutiveId,
|
|
positionExecutiveField: draftPos.positionExecutiveField,
|
|
positionArea: draftPos.positionArea,
|
|
isSpecial: draftPos.isSpecial,
|
|
orderNo: draftPos.orderNo,
|
|
positionIsSelected: draftPos.positionIsSelected,
|
|
lastUpdateFullName: draftPos.lastUpdateFullName,
|
|
lastUpdatedAt: new Date(),
|
|
},
|
|
});
|
|
} else {
|
|
// INSERT new position - collect for batch insert
|
|
allToInsert.push({
|
|
...draftPos,
|
|
id: undefined,
|
|
posMasterId: currentPosMasterId,
|
|
});
|
|
}
|
|
|
|
// Collect history data for the selected position
|
|
const draftPosMaster = draftPosMasterMap.get(draftPosMasterId) as any;
|
|
|
|
// Collect profile update for the selected position
|
|
// ถ้าไม่ใช่ตำแหน่งนั่งทับ (isSit = false) ถึงจะอัพเดทตำแหน่งในทะเบียนประวัติ
|
|
if (nextHolderId != null && draftPos.positionIsSelected && !draftPosMaster?.isSit) {
|
|
profileUpdates.set(nextHolderId, {
|
|
position: draftPos.positionName,
|
|
posTypeId: draftPos.posTypeId,
|
|
posLevelId: draftPos.posLevelId,
|
|
});
|
|
if (draftPosMaster && draftPosMaster.ancestorDNA) {
|
|
// Find the selected position from draft positions
|
|
const selectedPos =
|
|
draftPositions.find((p) => p.positionIsSelected === true) || draftPos;
|
|
historyCalls.push({
|
|
ancestorDNA: draftPosMaster.ancestorDNA,
|
|
profileId: nextHolderId,
|
|
historyData: {
|
|
prefix: draftPosMaster.next_holder?.prefix ?? null,
|
|
firstName: draftPosMaster.next_holder?.firstName ?? null,
|
|
lastName: draftPosMaster.next_holder?.lastName ?? null,
|
|
position: selectedPos.positionName ?? null,
|
|
posType: (selectedPos as any).posType?.posTypeName ?? null,
|
|
posLevel: (selectedPos as any).posLevel?.posLevelName ?? null,
|
|
posExecutive: (selectedPos as any).posExecutive?.posExecutiveName ?? null,
|
|
profileId: nextHolderId,
|
|
rootDnaId: draftPosMaster.orgRoot?.ancestorDNA ?? null,
|
|
child1DnaId: draftPosMaster.orgChild1?.ancestorDNA ?? null,
|
|
child2DnaId: draftPosMaster.orgChild2?.ancestorDNA ?? null,
|
|
child3DnaId: draftPosMaster.orgChild3?.ancestorDNA ?? null,
|
|
child4DnaId: draftPosMaster.orgChild4?.ancestorDNA ?? null,
|
|
shortName:
|
|
[
|
|
draftPosMaster.orgChild4?.orgChild4ShortName,
|
|
draftPosMaster.orgChild3?.orgChild3ShortName,
|
|
draftPosMaster.orgChild2?.orgChild2ShortName,
|
|
draftPosMaster.orgChild1?.orgChild1ShortName,
|
|
draftPosMaster.orgRoot?.orgRootShortName,
|
|
].find((s) => typeof s === "string" && s.trim().length > 0) ?? null,
|
|
posMasterNoPrefix: draftPosMaster.posMasterNoPrefix ?? null,
|
|
posMasterNo: draftPosMaster.posMasterNo ?? null,
|
|
posMasterNoSuffix: draftPosMaster.posMasterNoSuffix ?? null,
|
|
},
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Execute bulk operations
|
|
let deletedCount = 0;
|
|
let updatedCount = 0;
|
|
let insertedCount = 0;
|
|
|
|
// Bulk DELETE
|
|
if (allToDelete.length > 0) {
|
|
await queryRunner.manager.delete(Position, allToDelete);
|
|
const deleteOps = allToDeleteHistory.map((ancestorDNA) => ({
|
|
posMasterDnaId: ancestorDNA,
|
|
profileId: null,
|
|
pm: null,
|
|
}));
|
|
await BatchSavePosMasterHistoryOfficer(queryRunner, deleteOps);
|
|
deletedCount = allToDelete.length;
|
|
}
|
|
|
|
// Bulk UPDATE (batch by 100 to avoid query size limits)
|
|
if (allToUpdate.length > 0) {
|
|
const batchSize = 100;
|
|
for (let i = 0; i < allToUpdate.length; i += batchSize) {
|
|
const batch = allToUpdate.slice(i, i + batchSize);
|
|
await Promise.all(
|
|
batch.map(({ id, data }) => queryRunner.manager.update(Position, id, data)),
|
|
);
|
|
}
|
|
updatedCount = allToUpdate.length;
|
|
}
|
|
|
|
// Bulk INSERT
|
|
if (allToInsert.length > 0) {
|
|
const batchSize = 100;
|
|
for (let i = 0; i < allToInsert.length; i += batchSize) {
|
|
const batch = allToInsert.slice(i, i + batchSize);
|
|
await queryRunner.manager.save(Position, batch);
|
|
}
|
|
insertedCount = allToInsert.length;
|
|
}
|
|
|
|
// Bulk UPDATE profiles
|
|
if (profileUpdates.size > 0) {
|
|
const profileUpdateEntries = Array.from(profileUpdates.entries());
|
|
await Promise.all(
|
|
profileUpdateEntries.map(([profileId, data]) =>
|
|
queryRunner.manager.update(Profile, profileId, data),
|
|
),
|
|
);
|
|
}
|
|
|
|
// Save PosMasterHistory for updated positions
|
|
if (historyCalls.length > 0) {
|
|
await BatchSavePosMasterHistoryOfficer(
|
|
queryRunner,
|
|
historyCalls.map(({ ancestorDNA, profileId, historyData }) => ({
|
|
posMasterDnaId: ancestorDNA,
|
|
profileId,
|
|
pm: historyData,
|
|
})),
|
|
);
|
|
}
|
|
|
|
return { deleted: deletedCount, updated: updatedCount, inserted: insertedCount };
|
|
}
|
|
|
|
/**
|
|
* Helper: Sum all counts from a map (for root level total)
|
|
*/
|
|
private sumAllCounts(map: Map<string, { totalCount: number }>): number {
|
|
let sum = 0;
|
|
for (const value of map.values()) {
|
|
sum += value.totalCount;
|
|
}
|
|
return sum;
|
|
}
|
|
|
|
/**
|
|
* Helper: Sum all vacant counts from a map
|
|
*/
|
|
private sumAllVacantCounts(
|
|
map: Map<string, { currentVacantCount: number; nextVacantCount: number }>,
|
|
isDraft: boolean,
|
|
): number {
|
|
let sum = 0;
|
|
for (const value of map.values()) {
|
|
sum += isDraft ? value.nextVacantCount : value.currentVacantCount;
|
|
}
|
|
return sum;
|
|
}
|
|
|
|
/**
|
|
* Helper: Build orgRoots children array with pre-fetched counts
|
|
*/
|
|
private buildOrgRoots(
|
|
orgRoots: OrgRoot[],
|
|
positionCounts: PositionCountsByNode,
|
|
isDraft: boolean,
|
|
) {
|
|
if (!orgRoots) return [];
|
|
return orgRoots
|
|
.sort((a, b) => a.orgRootOrder - b.orgRootOrder)
|
|
.map((orgRoot) => {
|
|
const counts = getPositionCount(positionCounts.orgRootMap, orgRoot.id);
|
|
return {
|
|
departmentName: orgRoot.orgRootName,
|
|
deptID: orgRoot.id,
|
|
type: 1,
|
|
totalPositionCount: counts.totalCount,
|
|
totalPositionVacant: isDraft ? counts.nextVacantCount : counts.currentVacantCount,
|
|
children: this.buildOrgChild1s(orgRoot.orgChild1s, positionCounts, isDraft),
|
|
};
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Helper: Build orgChild1s children array with pre-fetched counts
|
|
*/
|
|
private buildOrgChild1s(
|
|
orgChild1s: OrgChild1[],
|
|
positionCounts: PositionCountsByNode,
|
|
isDraft: boolean,
|
|
) {
|
|
if (!orgChild1s) return [];
|
|
return orgChild1s
|
|
.sort((a, b) => a.orgChild1Order - b.orgChild1Order)
|
|
.map((orgChild1) => {
|
|
const counts = getPositionCount(positionCounts.orgChild1Map, orgChild1.id);
|
|
return {
|
|
departmentName: orgChild1.orgChild1Name,
|
|
deptID: orgChild1.id,
|
|
type: 2,
|
|
totalPositionCount: counts.totalCount,
|
|
totalPositionVacant: isDraft ? counts.nextVacantCount : counts.currentVacantCount,
|
|
children: this.buildOrgChild2s(orgChild1.orgChild2s, positionCounts, isDraft),
|
|
};
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Helper: Build orgChild2s children array with pre-fetched counts
|
|
*/
|
|
private buildOrgChild2s(
|
|
orgChild2s: OrgChild2[],
|
|
positionCounts: PositionCountsByNode,
|
|
isDraft: boolean,
|
|
) {
|
|
if (!orgChild2s) return [];
|
|
return orgChild2s
|
|
.sort((a, b) => a.orgChild2Order - b.orgChild2Order)
|
|
.map((orgChild2) => {
|
|
const counts = getPositionCount(positionCounts.orgChild2Map, orgChild2.id);
|
|
return {
|
|
departmentName: orgChild2.orgChild2Name,
|
|
deptID: orgChild2.id,
|
|
type: 3,
|
|
totalPositionCount: counts.totalCount,
|
|
totalPositionVacant: isDraft ? counts.nextVacantCount : counts.currentVacantCount,
|
|
children: this.buildOrgChild3s(orgChild2.orgChild3s, positionCounts, isDraft),
|
|
};
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Helper: Build orgChild3s children array with pre-fetched counts
|
|
*/
|
|
private buildOrgChild3s(
|
|
orgChild3s: OrgChild3[],
|
|
positionCounts: PositionCountsByNode,
|
|
isDraft: boolean,
|
|
) {
|
|
if (!orgChild3s) return [];
|
|
return orgChild3s
|
|
.sort((a, b) => a.orgChild3Order - b.orgChild3Order)
|
|
.map((orgChild3) => {
|
|
const counts = getPositionCount(positionCounts.orgChild3Map, orgChild3.id);
|
|
return {
|
|
departmentName: orgChild3.orgChild3Name,
|
|
deptID: orgChild3.id,
|
|
type: 4,
|
|
totalPositionCount: counts.totalCount,
|
|
totalPositionVacant: isDraft ? counts.nextVacantCount : counts.currentVacantCount,
|
|
children: this.buildOrgChild4s(orgChild3.orgChild4s, positionCounts, isDraft),
|
|
};
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Helper: Build orgChild4s children array with pre-fetched counts (leaf nodes)
|
|
*/
|
|
private buildOrgChild4s(
|
|
orgChild4s: OrgChild4[],
|
|
positionCounts: PositionCountsByNode,
|
|
isDraft: boolean,
|
|
) {
|
|
if (!orgChild4s) return [];
|
|
return orgChild4s
|
|
.sort((a, b) => a.orgChild4Order - b.orgChild4Order)
|
|
.map((orgChild4) => {
|
|
const counts = getPositionCount(positionCounts.orgChild4Map, orgChild4.id);
|
|
return {
|
|
departmentName: orgChild4.orgChild4Name,
|
|
deptID: orgChild4.id,
|
|
type: 5,
|
|
totalPositionCount: counts.totalCount,
|
|
totalPositionVacant: isDraft ? counts.nextVacantCount : counts.currentVacantCount,
|
|
};
|
|
});
|
|
}
|
|
}
|