From 869bb093a38909947af501e170c41d346ff0a3ae Mon Sep 17 00:00:00 2001 From: waruneeauy Date: Tue, 5 May 2026 12:08:37 +0700 Subject: [PATCH 1/6] refactor code function handler_org --- src/services/rabbitmq.ts | 1311 +++++++++++++++++++------------------- 1 file changed, 649 insertions(+), 662 deletions(-) diff --git a/src/services/rabbitmq.ts b/src/services/rabbitmq.ts index 31a4269d..00b1f27a 100644 --- a/src/services/rabbitmq.ts +++ b/src/services/rabbitmq.ts @@ -92,13 +92,12 @@ export async function init() { // createConsumer(queue2, channel, handler2); } -let retries = 0; - function createConsumer( //----> consumer queue: string, channel: amqp.Channel, handler: (msg: amqp.ConsumeMessage) => Promise | boolean, ) { + let retries = 0; channel.consume( queue, async (msg) => { @@ -405,7 +404,7 @@ async function handler_command_noti(msg: amqp.ConsumeMessage): Promise try { let profilesNotiRequest: Promise | undefined; - if (!(["C-PM-10"].includes(command.commandType.code))) { + if (!["C-PM-10"].includes(command.commandType.code)) { profilesNotiRequest = new CallAPI() .PostData( { headers: { authorization: token } }, @@ -441,14 +440,14 @@ async function handler_command_noti(msg: amqp.ConsumeMessage): Promise let profilesSend = command && command.commandSends.length > 0 ? command.commandSends - .filter((x: any) => x.profileId != null) - .map((x: any) => ({ - receiverUserId: x.profileId, - notiLink: "", - isSendMail: x.commandSendCCs.map((x: any) => x.name == "EMAIL").length > 0, - isSendInbox: x.commandSendCCs.map((x: any) => x.name == "INBOX").length > 0, - isSendNotification: true, - })) + .filter((x: any) => x.profileId != null) + .map((x: any) => ({ + receiverUserId: x.profileId, + notiLink: "", + isSendMail: x.commandSendCCs.map((x: any) => x.name == "EMAIL").length > 0, + isSendInbox: x.commandSendCCs.map((x: any) => x.name == "INBOX").length > 0, + isSendNotification: true, + })) : []; const payloadStr = await PayloadSendNoti(command.id); const profilesSendRequest = new CallAPI() @@ -482,8 +481,7 @@ async function handler_command_noti(msg: amqp.ConsumeMessage): Promise /*เฉพาะคำสั่ง C-PM-10 ให้ตัด profilesNotiRequest ที่ส่ง noti ครั้งแรกออก*/ if (["C-PM-10"].includes(command.commandType.code)) { await Promise.all([profilesSendRequest]); - } - else { + } else { await Promise.all([profilesNotiRequest!, profilesSendRequest]); } @@ -497,7 +495,7 @@ async function handler_command_noti(msg: amqp.ConsumeMessage): Promise async function handler_org(msg: amqp.ConsumeMessage): Promise { //----> condition before process consume - console.time('[AMQ] handler_org_total'); + console.time("[AMQ] handler_org_total"); const startTime = Date.now(); console.log(`[AMQ] handler_org START at ${new Date(startTime).toISOString()}`); @@ -520,6 +518,30 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { const { id, status, lastUpdateUserId, lastUpdateFullName, lastUpdatedAt } = data; console.log(`[AMQ] Received message - revisionId: ${id}, status: ${status}`); + const targetOrgRevision = await repoOrgRevision.findOne({ + where: { id }, + }); + + if (!targetOrgRevision) { + console.error(`[AMQ] Skip publish: revision ${id} not found`); + console.timeEnd("[AMQ] handler_org_total"); + return true; + } + + if (targetOrgRevision.orgRevisionIsCurrent && !targetOrgRevision.orgRevisionIsDraft) { + console.log(`[AMQ] Skip publish: revision ${id} is already current`); + console.timeEnd("[AMQ] handler_org_total"); + return true; + } + + if (!targetOrgRevision.orgRevisionIsDraft || targetOrgRevision.orgRevisionIsCurrent) { + console.log( + `[AMQ] Skip publish: revision ${id} is no longer publishable (isDraft=${targetOrgRevision.orgRevisionIsDraft}, isCurrent=${targetOrgRevision.orgRevisionIsCurrent})`, + ); + console.timeEnd("[AMQ] handler_org_total"); + return true; + } + if (user) { sendWebSocket( "send-publish-org", @@ -531,25 +553,30 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { ).catch(console.error); } - console.time('[AMQ] query_revisions'); - const orgRevisionPublish = await repoOrgRevision - .createQueryBuilder("orgRevision") - .where("orgRevision.orgRevisionIsDraft = false") - .andWhere("orgRevision.orgRevisionIsCurrent = true") - .getOne(); - - const orgRevisionDraft = await repoOrgRevision - .createQueryBuilder("orgRevision") - .where("orgRevision.orgRevisionIsDraft = true") - .andWhere("orgRevision.orgRevisionIsCurrent = false") - .getOne(); - console.timeEnd('[AMQ] query_revisions'); - console.log(`[AMQ] orgRevisionPublish found: ${orgRevisionPublish ? orgRevisionPublish.id : 'null'}`); - console.log(`[AMQ] orgRevisionDraft found: ${orgRevisionDraft ? orgRevisionDraft.id : 'null'}`); + console.time("[AMQ] query_revisions"); + const [orgRevisionPublish, orgRevisionDraft] = await Promise.all([ + repoOrgRevision + .createQueryBuilder("orgRevision") + .where("orgRevision.orgRevisionIsDraft = false") + .andWhere("orgRevision.orgRevisionIsCurrent = true") + .getOne(), + repoOrgRevision + .createQueryBuilder("orgRevision") + .where("orgRevision.orgRevisionIsDraft = true") + .andWhere("orgRevision.orgRevisionIsCurrent = false") + .getOne(), + ]); + console.timeEnd("[AMQ] query_revisions"); + console.log( + `[AMQ] orgRevisionPublish found: ${orgRevisionPublish ? orgRevisionPublish.id : "null"}`, + ); + console.log(`[AMQ] orgRevisionDraft found: ${orgRevisionDraft ? orgRevisionDraft.id : "null"}`); // Validate: ต้องมี orgRevisionPublish เสมอสำหรับการเผยแพร่ if (!orgRevisionPublish) { - console.error('[AMQ] Cannot publish: No current org revision found (isDraft=false, isCurrent=true)'); + console.error( + "[AMQ] Cannot publish: No current org revision found (isDraft=false, isCurrent=true)", + ); if (user) { sendWebSocket( "send-publish-org", @@ -565,7 +592,9 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { // Validate: ต้องมี orgRevisionDraft ที่จะเผยแพร่ if (!orgRevisionDraft) { - console.error('[AMQ] Cannot publish: No draft org revision found (isDraft=true, isCurrent=false)'); + console.error( + "[AMQ] Cannot publish: No draft org revision found (isDraft=true, isCurrent=false)", + ); if (user) { sendWebSocket( "send-publish-org", @@ -579,11 +608,19 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { return false; } + if (orgRevisionDraft.id !== targetOrgRevision.id) { + console.log( + `[AMQ] Skip publish: revision ${id} is stale because draft ${orgRevisionDraft.id} is now the active publish candidate`, + ); + console.timeEnd("[AMQ] handler_org_total"); + return true; + } + // NOTE: ย้ายการอัปเดตสถานะไปไว้หลังจากทำงานเสร็จทั้งหมด // เพื่อป้องกันกรณี timeout/retry ทำให้สถานะเพี้ยน (ทุก row เป็น false,false) try { - console.time('[AMQ] query_posMaster'); + console.time("[AMQ] query_posMaster"); const posMaster = await repoPosmaster.find({ where: { orgRevisionId: id }, relations: [ @@ -598,15 +635,15 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { "positions.posExecutive", ], }); - console.timeEnd('[AMQ] query_posMaster'); + console.timeEnd("[AMQ] query_posMaster"); console.log(`[AMQ] posMaster count: ${posMaster.length}`); - console.time('[AMQ] query_old_data'); + console.time("[AMQ] query_old_data"); const oldPosMasters = await repoPosmaster.find({ where: { orgRevisionId: orgRevisionPublish.id, }, - select: ['id', 'current_holderId', 'ancestorDNA'] + select: ["id", "current_holderId", "ancestorDNA"], }); // Task #2160 ดึง posMasterAssign ของ revision เดิม @@ -618,11 +655,11 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { }, }, }); - console.timeEnd('[AMQ] query_old_data'); + console.timeEnd("[AMQ] query_old_data"); console.log(`[AMQ] oldPosMasters count: ${oldPosMasters.length}`); console.log(`[AMQ] oldposMasterAssigns count: ${oldposMasterAssigns.length}`); - console.time('[AMQ] build_assignMap'); + console.time("[AMQ] build_assignMap"); // สร้าง assignMap เอาไว้เก็บ posMasterAssign.ancestorDNA ของ revision เดิม const assignMap = new Map(); for (const posmasterAssign of oldposMasterAssigns) { @@ -633,12 +670,12 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { assignMap.get(dna)!.push({ id: posmasterAssign.id, posMasterId: posmasterAssign.posMasterId, - assignId: posmasterAssign.assignId + assignId: posmasterAssign.assignId, }); } - console.timeEnd('[AMQ] build_assignMap'); + console.timeEnd("[AMQ] build_assignMap"); - console.time('[AMQ] query_oldposMasterAct'); + console.time("[AMQ] query_oldposMasterAct"); // ดึง posMasterAct ของ revision เดิม xxx const oldposMasterAct = await posMasterActRepository.find({ relations: ["posMaster", "posMasterChild"], @@ -648,16 +685,16 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { }, }, }); - console.timeEnd('[AMQ] query_oldposMasterAct'); + console.timeEnd("[AMQ] query_oldposMasterAct"); console.log(`[AMQ] oldposMasterAct count: ${oldposMasterAct.length}`); type ActKey = string; // `${parentDNA}|${childDNA}` - console.time('[AMQ] build_maps'); + console.time("[AMQ] build_maps"); const posMasterActMap = new Map(); for (const act of oldposMasterAct) { - const parentDNA = act.posMaster?.ancestorDNA?.trim() ?? ''; - const childDNA = act.posMasterChild?.ancestorDNA?.trim() ?? ''; + const parentDNA = act.posMaster?.ancestorDNA?.trim() ?? ""; + const childDNA = act.posMasterChild?.ancestorDNA?.trim() ?? ""; const key = `${parentDNA}|${childDNA}`; if (!posMasterActMap.has(key)) { @@ -668,7 +705,7 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { const posMasterIdMap = new Map(); for (const pm of posMaster) { - posMasterIdMap.set(pm.ancestorDNA?.trim() ?? '', pm.id); + posMasterIdMap.set(pm.ancestorDNA?.trim() ?? "", pm.id); } const oldPosMasterMap = new Map(); @@ -678,25 +715,25 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { oldPosMasterMap.set(dna, oldPm); } } - console.timeEnd('[AMQ] build_maps'); + console.timeEnd("[AMQ] build_maps"); const _null: any = null; // ===== BATCH PROCESSING: เตรียมข้อมูลก่อน loop ===== - console.time('[AMQ] prepare_batch_data'); + console.time("[AMQ] prepare_batch_data"); // 1. รวบรวม profileIds ทั้งหมดที่ต้องอัพเดท const profileIds = posMaster - .filter(item => item.next_holderId != null) - .map(item => item.next_holderId!) - .filter(id => id != null && id !== ""); + .filter((item) => item.next_holderId != null) + .map((item) => item.next_holderId!) + .filter((id) => id != null && id !== ""); // 2. Batch load profiles ทั้งหมดในครั้งเดียว (แก้ปัญหา N+1 Query) const profilesMap = new Map(); if (profileIds.length > 0) { const profiles = await repoProfile.findBy({ - id: In(profileIds) + id: In(profileIds), }); - profiles.forEach(p => profilesMap.set(p.id, p)); + profiles.forEach((p) => profilesMap.set(p.id, p)); } console.log(`[AMQ] profiles to update: ${profilesMap.size}`); @@ -724,7 +761,7 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { lastUpdatedAt: lastUpdatedAt, lastUpdateFullName: lastUpdateFullName, lastUpdateUserId: lastUpdateUserId, - }) + }), ); posMasterAssignsToSave.push(...newAssigns); } @@ -775,33 +812,35 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { historyCreateIds.push(item.id); } } - console.timeEnd('[AMQ] prepare_batch_data'); - console.log(`[AMQ] Prepared - posMasterAssignsToSave: ${posMasterAssignsToSave.length}, profilesToSave: ${profilesToSave.length}, posMasterUpdates: ${posMasterUpdates.length}, historyCreateIds: ${historyCreateIds.length}`); + console.timeEnd("[AMQ] prepare_batch_data"); + console.log( + `[AMQ] Prepared - posMasterAssignsToSave: ${posMasterAssignsToSave.length}, profilesToSave: ${profilesToSave.length}, posMasterUpdates: ${posMasterUpdates.length}, historyCreateIds: ${historyCreateIds.length}`, + ); // ===== BATCH EXECUTION: save ทีละ batch ===== // 4. Batch save posMasterAssign (chunk 500) - console.time('[AMQ] batch_save_posMasterAssign'); + console.time("[AMQ] batch_save_posMasterAssign"); if (posMasterAssignsToSave.length > 0) { const chunks = chunkArray(posMasterAssignsToSave, 500); for (const chunk of chunks) { await posMasterAssignRepository.save(chunk); } } - console.timeEnd('[AMQ] batch_save_posMasterAssign'); + console.timeEnd("[AMQ] batch_save_posMasterAssign"); // 5. Batch save profiles (chunk 200) - console.time('[AMQ] batch_save_profiles'); + console.time("[AMQ] batch_save_profiles"); if (profilesToSave.length > 0) { const chunks = chunkArray(profilesToSave, 200); for (const chunk of chunks) { await repoProfile.save(chunk); } } - console.timeEnd('[AMQ] batch_save_profiles'); + console.timeEnd("[AMQ] batch_save_profiles"); // 6. Batch update posMasters - console.time('[AMQ] batch_update_posMasters'); + console.time("[AMQ] batch_update_posMasters"); for (const update of posMasterUpdates) { await repoPosmaster.update(update.id, { current_holderId: update.current_holderId, @@ -811,20 +850,20 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { lastUpdatedAt, }); } - console.timeEnd('[AMQ] batch_update_posMasters'); + console.timeEnd("[AMQ] batch_update_posMasters"); // 7. Batch create history - console.time('[AMQ] batch_create_history'); + console.time("[AMQ] batch_create_history"); for (const id of historyCreateIds) { await CreatePosMasterHistoryOfficer(id, null); } - console.timeEnd('[AMQ] batch_create_history'); + console.timeEnd("[AMQ] batch_create_history"); // Clone oldposMasterAct - console.time('[AMQ] clone_oldposMasterAct'); + console.time("[AMQ] clone_oldposMasterAct"); for (const act of oldposMasterAct) { - const parentDNA = act.posMaster?.ancestorDNA?.trim()?.toLowerCase() ?? ''; - const childDNA = act.posMasterChild?.ancestorDNA?.trim()?.toLowerCase() ?? ''; + const parentDNA = act.posMaster?.ancestorDNA?.trim()?.toLowerCase() ?? ""; + const childDNA = act.posMasterChild?.ancestorDNA?.trim()?.toLowerCase() ?? ""; const newParentId = posMasterIdMap.get(parentDNA); const newChildId = posMasterIdMap.get(childDNA); @@ -847,16 +886,16 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { await posMasterActRepository.save(newAct); } - console.timeEnd('[AMQ] clone_oldposMasterAct'); + console.timeEnd("[AMQ] clone_oldposMasterAct"); if (orgRevisionPublish != null && orgRevisionDraft != null) { - console.time('[AMQ] clone_org_structure'); + console.time("[AMQ] clone_org_structure"); //new main revision const before = null; //ทุก orgRoot และ orgChild ข้างล่างนี้จะเป็นตัวเก่าที่ไม่ได้เป็น current revision //cone tree - console.time('[AMQ] query_old_org_structure'); + console.time("[AMQ] query_old_org_structure"); //หา dna tree const orgRoot = await orgRootRepository.find({ where: { orgRevisionId: orgRevisionPublish.id }, @@ -877,27 +916,55 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { const orgChild4 = await child4Repository.find({ where: { orgRevisionId: orgRevisionPublish.id }, }); - console.timeEnd('[AMQ] query_old_org_structure'); - console.log(`[AMQ] Old structure - orgRoot: ${orgRoot.length}, orgChild1: ${orgChild1.length}, orgChild2: ${orgChild2.length}, orgChild3: ${orgChild3.length}, orgChild4: ${orgChild4.length}`); + console.timeEnd("[AMQ] query_old_org_structure"); + console.log( + `[AMQ] Old structure - orgRoot: ${orgRoot.length}, orgChild1: ${orgChild1.length}, orgChild2: ${orgChild2.length}, orgChild3: ${orgChild3.length}, orgChild4: ${orgChild4.length}`, + ); // Task #2172 ดึง orgRoot ของ revision ใหม่ const newRoots = await orgRootRepository.find({ where: { orgRevisionId: orgRevisionDraft.id }, }); // สร้าง newRootMap เอาไว้เก็บ orgRoot.ancestorDNA ของ revision ใหม่ - const newRootMap = new Map( - newRoots.map(r => [r.ancestorDNA, r.id]) - ); + const newRootMap = new Map(newRoots.map((r) => [r.ancestorDNA, r.id])); + const emptyAncestorDNA = "00000000-0000-0000-0000-000000000000"; + const hasEmptyAncestorDNA = (ancestorDNA?: string | null) => + ancestorDNA == null || ancestorDNA === emptyAncestorDNA; + const hasSelfOrEmptyAncestorDNA = (node: { id: string; ancestorDNA: string | null }) => + node.ancestorDNA === node.id || hasEmptyAncestorDNA(node.ancestorDNA); + const findMatchedNodeByAncestorDNA = ( + nodes: T[], + node: T, + ) => + nodes.find((item) => { + if (hasSelfOrEmptyAncestorDNA(node)) { + return hasEmptyAncestorDNA(item.ancestorDNA); + } + return item.ancestorDNA === node.ancestorDNA; + }); + const [ + orgRootCurrent, + orgChild1Current, + orgChild2Current, + orgChild3Current, + orgChild4Current, + ] = await Promise.all([ + orgRootRepository.find({ where: { orgRevisionId: orgRevisionDraft.id } }), + child1Repository.find({ where: { orgRevisionId: orgRevisionDraft.id } }), + child2Repository.find({ where: { orgRevisionId: orgRevisionDraft.id } }), + child3Repository.find({ where: { orgRevisionId: orgRevisionDraft.id } }), + child4Repository.find({ where: { orgRevisionId: orgRevisionDraft.id } }), + ]); - console.time('[AMQ] clone_permissionProfiles'); + console.time("[AMQ] clone_permissionProfiles"); // ดึง permissionProfiles ของ revision เดิม const oldPermissionProfiles = await permissionProfilesRepository.find({ relations: ["orgRootTree"], where: { orgRootTree: { orgRevisionId: orgRevisionPublish.id, - } - } + }, + }, }); const inserts: any[] = []; for (const permiss of oldPermissionProfiles) { @@ -922,15 +989,15 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { if (inserts.length > 0) { await permissionProfilesRepository.insert(inserts); } - console.timeEnd('[AMQ] clone_permissionProfiles'); + console.timeEnd("[AMQ] clone_permissionProfiles"); //หา dna posmaster ถ้าไม่มีให้เอาตัวเองเป็น dna - console.time('[AMQ] query_employeePosMaster'); + console.time("[AMQ] query_employeePosMaster"); const orgemployeePosMaster = await repoEmployeePosmaster.find({ where: { orgRevisionId: orgRevisionPublish.id }, relations: ["positions"], }); - console.timeEnd('[AMQ] query_employeePosMaster'); + console.timeEnd("[AMQ] query_employeePosMaster"); console.log(`[AMQ] orgemployeePosMaster count: ${orgemployeePosMaster.length}`); let _orgemployeePosMaster: EmployeePosMaster[]; @@ -962,7 +1029,7 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { : x.ancestorDNA, })); - console.time('[AMQ] insert_employeePosMaster'); + console.time("[AMQ] insert_employeePosMaster"); await repoEmployeePosmaster .createQueryBuilder() .insert() @@ -973,16 +1040,16 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { overwrite: ["ancestorDNA"], }) .execute(); - console.timeEnd('[AMQ] insert_employeePosMaster'); + console.timeEnd("[AMQ] insert_employeePosMaster"); // } //หา dna posmaster ถ้าไม่มีให้เอาตัวเองเป็น dna - console.time('[AMQ] query_employeeTempPosMaster'); + console.time("[AMQ] query_employeeTempPosMaster"); const orgemployeeTempPosMaster = await repoEmployeeTempPosmaster.find({ where: { orgRevisionId: orgRevisionPublish.id }, relations: ["positions"], }); - console.timeEnd('[AMQ] query_employeeTempPosMaster'); + console.timeEnd("[AMQ] query_employeeTempPosMaster"); console.log(`[AMQ] orgemployeeTempPosMaster count: ${orgemployeeTempPosMaster.length}`); let _orgemployeeTempPosMaster: EmployeeTempPosMaster[]; @@ -1012,30 +1079,12 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { .execute(); // } - //create org - forEach orgRoot (WARNING: async forEach without await) - console.time('[AMQ] forEach_orgRoot'); + //create org + console.time("[AMQ] forEach_orgRoot"); console.log(`[AMQ] Starting forEach orgRoot loop (${orgRoot.length} items)`); - let processedOrgRoot = 0; - orgRoot.forEach(async (x: any) => { - const itemStartTime = Date.now(); - var dataId = x.id; - - const orgRootCurrent = await orgRootRepository.find({ - where: { orgRevisionId: orgRevisionDraft.id }, - }); - - const matchedOrgRoot = orgRootCurrent.find((i: OrgRoot) => { - if ( - x.ancestorDNA === x.id || // ถ้า ancestorDNA ถูกตั้งเป็น id ตัวเอง - x.ancestorDNA === null || - x.ancestorDNA === "00000000-0000-0000-0000-000000000000" - ) { - return ( - i.ancestorDNA === null || i.ancestorDNA === "00000000-0000-0000-0000-000000000000" - ); - } - return i.ancestorDNA === x.ancestorDNA; - }); + for (const x of orgRoot) { + const dataId = x.id; + const matchedOrgRoot = findMatchedNodeByAncestorDNA(orgRootCurrent, x); // if ( // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || @@ -1044,44 +1093,45 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" // ) { //create employeePosmaster - const filteredEmployeePosMaster = _orgemployeePosMaster - .filter((x: EmployeePosMaster) => x.orgRootId == dataId && x.orgChild1Id == null); + const filteredEmployeePosMaster = _orgemployeePosMaster.filter( + (x: EmployeePosMaster) => x.orgRootId == dataId && x.orgChild1Id == null, + ); await Promise.all( - filteredEmployeePosMaster - .map(async (item: any) => { - delete item.id; - const employeePosMaster = Object.assign(new EmployeePosMaster(), item); - employeePosMaster.positions = []; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeePosMaster.current_holderId = item.current_holderId; - // } else { - // // employeePosMaster.next_holderId = null; - // employeePosMaster.isSit = false; - // } - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeePosMaster.authRoleId = item.authRoleId; - // } else { - // employeePosMaster.authRoleId = null; - // } - // employeePosMaster.current_holderId = null; - employeePosMaster.orgRevisionId = orgRevisionDraft.id; - employeePosMaster.orgRootId = matchedOrgRoot?.id ?? null; - employeePosMaster.createdUserId = ""; - employeePosMaster.createdFullName = "System Administrator"; - employeePosMaster.createdAt = new Date(); - employeePosMaster.lastUpdateUserId = ""; - employeePosMaster.lastUpdateFullName = "System Administrator"; - employeePosMaster.lastUpdatedAt = new Date(); - await repoEmployeePosmaster.save(employeePosMaster); + filteredEmployeePosMaster.map(async (item: any) => { + delete item.id; + const employeePosMaster = Object.assign(new EmployeePosMaster(), item); + employeePosMaster.positions = []; + // if ( + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" + // ) { + // employeePosMaster.current_holderId = item.current_holderId; + // } else { + // // employeePosMaster.next_holderId = null; + // employeePosMaster.isSit = false; + // } + // if ( + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" + // ) { + // employeePosMaster.authRoleId = item.authRoleId; + // } else { + // employeePosMaster.authRoleId = null; + // } + // employeePosMaster.current_holderId = null; + employeePosMaster.orgRevisionId = orgRevisionDraft.id; + employeePosMaster.orgRootId = matchedOrgRoot?.id ?? null; + employeePosMaster.createdUserId = ""; + employeePosMaster.createdFullName = "System Administrator"; + employeePosMaster.createdAt = new Date(); + employeePosMaster.lastUpdateUserId = ""; + employeePosMaster.lastUpdateFullName = "System Administrator"; + employeePosMaster.lastUpdatedAt = new Date(); + await repoEmployeePosmaster.save(employeePosMaster); - //create employeePosition + //create employeePosition + await Promise.all( item.positions.map(async (pos: any) => { delete pos.id; const employeePosition: EmployeePosition = Object.assign( @@ -1102,8 +1152,9 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { employeePosition.lastUpdateFullName = "System Administrator"; employeePosition.lastUpdatedAt = new Date(); await employeePositionRepository.save(employeePosition); - }); - }), + }), + ); + }), ); //create employeeTempPosmaster await Promise.all( @@ -1142,53 +1193,180 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { await repoEmployeeTempPosmaster.save(employeeTempPosMaster); //create employeePosition - item.positions.map(async (pos: any) => { - delete pos.id; - const employeePosition: EmployeePosition = Object.assign( - new EmployeePosition(), - pos, - ); - employeePosition.posMasterTempId = employeeTempPosMaster.id; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" - // ) { - // employeePosition.positionIsSelected = false; - // } - employeePosition.createdUserId = ""; - employeePosition.createdFullName = "System Administrator"; - employeePosition.createdAt = new Date(); - employeePosition.lastUpdateUserId = ""; - employeePosition.lastUpdateFullName = "System Administrator"; - employeePosition.lastUpdatedAt = new Date(); - await employeePositionRepository.save(employeePosition); - }); + await Promise.all( + item.positions.map(async (pos: any) => { + delete pos.id; + const employeePosition: EmployeePosition = Object.assign( + new EmployeePosition(), + pos, + ); + employeePosition.posMasterTempId = employeeTempPosMaster.id; + // if ( + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" + // ) { + // employeePosition.positionIsSelected = false; + // } + employeePosition.createdUserId = ""; + employeePosition.createdFullName = "System Administrator"; + employeePosition.createdAt = new Date(); + employeePosition.lastUpdateUserId = ""; + employeePosition.lastUpdateFullName = "System Administrator"; + employeePosition.lastUpdatedAt = new Date(); + await employeePositionRepository.save(employeePosition); + }), + ); }), ); // } //create org - orgChild1 - .filter((x: OrgChild1) => x.orgRootId == dataId) - .forEach(async (x: any) => { - var data1Id = x.id; - const orgChild1Current = await child1Repository.find({ - where: { orgRevisionId: orgRevisionDraft.id }, - }); + for (const x of orgChild1.filter((item: OrgChild1) => item.orgRootId == dataId)) { + const data1Id = x.id; + const matchedOrgChild1 = findMatchedNodeByAncestorDNA(orgChild1Current, x); + // ("[in case Child1] ancestorDNA", `${x.orgChild1Id == matchedOrgChild1?.id}`); + // if ( + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" + // ) { + //create employeePosmaster + await Promise.all( + _orgemployeePosMaster + .filter((x: EmployeePosMaster) => x.orgChild1Id == data1Id && x.orgChild2Id == null) + .map(async (item: any) => { + delete item.id; + // console.log("[in case Child1] orgChild1Id == data1Id"); + const employeePosMaster = Object.assign(new EmployeePosMaster(), item); + employeePosMaster.positions = []; + // if ( + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" + // ) { + // employeePosMaster.current_holderId = item.current_holderId; + // } else { + // // employeePosMaster.next_holderId = null; + // employeePosMaster.isSit = false; + // } + // if ( + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" + // ) { + // employeePosMaster.authRoleId = item.authRoleId; + // } else { + // employeePosMaster.authRoleId = null; + // } + // employeePosMaster.current_holderId = null; + employeePosMaster.orgRevisionId = orgRevisionDraft.id; + employeePosMaster.orgRootId = matchedOrgRoot?.id ?? null; + employeePosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; + employeePosMaster.createdUserId = ""; + employeePosMaster.createdFullName = "System Administrator"; + employeePosMaster.createdAt = new Date(); + employeePosMaster.lastUpdateUserId = ""; + employeePosMaster.lastUpdateFullName = "System Administrator"; + employeePosMaster.lastUpdatedAt = new Date(); + await repoEmployeePosmaster.save(employeePosMaster); - const matchedOrgChild1 = orgChild1Current.find((i: OrgChild1) => { - if ( - x.ancestorDNA === x.id || // ถ้า ancestorDNA ถูกตั้งเป็น id ตัวเอง - x.ancestorDNA === null || - x.ancestorDNA === "00000000-0000-0000-0000-000000000000" - ) { - return ( - i.ancestorDNA === null || i.ancestorDNA === "00000000-0000-0000-0000-000000000000" + //create employeePosition + await Promise.all( + item.positions.map(async (pos: any) => { + delete pos.id; + const employeePosition: EmployeePosition = Object.assign( + new EmployeePosition(), + pos, + ); + employeePosition.posMasterId = employeePosMaster.id; + // if ( + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" + // ) { + // employeePosition.positionIsSelected = false; + // } + employeePosition.createdUserId = ""; + employeePosition.createdFullName = "System Administrator"; + employeePosition.createdAt = new Date(); + employeePosition.lastUpdateUserId = ""; + employeePosition.lastUpdateFullName = "System Administrator"; + employeePosition.lastUpdatedAt = new Date(); + await employeePositionRepository.save(employeePosition); + }), ); - } - return i.ancestorDNA === x.ancestorDNA; - }); - // ("[in case Child1] ancestorDNA", `${x.orgChild1Id == matchedOrgChild1?.id}`); + }), + ); + // create employeeTempPosmaster + await Promise.all( + _orgemployeeTempPosMaster + .filter( + (x: EmployeeTempPosMaster) => x.orgChild1Id == data1Id && x.orgChild2Id == null, + ) + .map(async (item: any) => { + delete item.id; + const employeeTempPosMaster = Object.assign(new EmployeeTempPosMaster(), item); + employeeTempPosMaster.positions = []; + // if ( + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" + // ) { + // employeeTempPosMaster.current_holderId = item.current_holderId; + // } else { + // // employeeTempPosMaster.next_holderId = null; + // employeeTempPosMaster.isSit = false; + // } + // if ( + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" + // ) { + // employeeTempPosMaster.authRoleId = item.authRoleId; + // } else { + // employeeTempPosMaster.authRoleId = null; + // } + // employeeTempPosMaster.current_holderId = null; + employeeTempPosMaster.orgRevisionId = orgRevisionDraft.id; + employeeTempPosMaster.orgRootId = matchedOrgRoot?.id ?? null; + employeeTempPosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; + employeeTempPosMaster.createdUserId = ""; + employeeTempPosMaster.createdFullName = "System Administrator"; + employeeTempPosMaster.createdAt = new Date(); + employeeTempPosMaster.lastUpdateUserId = ""; + employeeTempPosMaster.lastUpdateFullName = "System Administrator"; + employeeTempPosMaster.lastUpdatedAt = new Date(); + await repoEmployeeTempPosmaster.save(employeeTempPosMaster); + + //create employeePosition + await Promise.all( + item.positions.map(async (pos: any) => { + delete pos.id; + const employeePosition: EmployeePosition = Object.assign( + new EmployeePosition(), + pos, + ); + employeePosition.posMasterTempId = employeeTempPosMaster.id; + // if ( + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" + // ) { + // employeePosition.positionIsSelected = false; + // } + employeePosition.createdUserId = ""; + employeePosition.createdFullName = "System Administrator"; + employeePosition.createdAt = new Date(); + employeePosition.lastUpdateUserId = ""; + employeePosition.lastUpdateFullName = "System Administrator"; + employeePosition.lastUpdatedAt = new Date(); + await employeePositionRepository.save(employeePosition); + }), + ); + }), + ); + // } + + //create org + for (const x of orgChild2.filter((item: OrgChild2) => item.orgChild1Id == data1Id)) { + const data2Id = x.id; + const matchedOrgChild2 = findMatchedNodeByAncestorDNA(orgChild2Current, x); + // console.log("[in case Child2] ancestorDNA", `${x.orgChild2Id == matchedOrgChild2?.id}`); // if ( // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || @@ -1198,10 +1376,10 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { //create employeePosmaster await Promise.all( _orgemployeePosMaster - .filter((x: EmployeePosMaster) => x.orgChild1Id == data1Id && x.orgChild2Id == null) + .filter((x: EmployeePosMaster) => x.orgChild2Id == data2Id && x.orgChild3Id == null) .map(async (item: any) => { delete item.id; - // console.log("[in case Child1] orgChild1Id == data1Id"); + // console.log("[in case Child2] orgChild2Id == data2Id"); const employeePosMaster = Object.assign(new EmployeePosMaster(), item); employeePosMaster.positions = []; // if ( @@ -1225,6 +1403,7 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { employeePosMaster.orgRevisionId = orgRevisionDraft.id; employeePosMaster.orgRootId = matchedOrgRoot?.id ?? null; employeePosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; + employeePosMaster.orgChild2Id = matchedOrgChild2?.id ?? null; employeePosMaster.createdUserId = ""; employeePosMaster.createdFullName = "System Administrator"; employeePosMaster.createdAt = new Date(); @@ -1234,34 +1413,36 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { await repoEmployeePosmaster.save(employeePosMaster); //create employeePosition - item.positions.map(async (pos: any) => { - delete pos.id; - const employeePosition: EmployeePosition = Object.assign( - new EmployeePosition(), - pos, - ); - employeePosition.posMasterId = employeePosMaster.id; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" - // ) { - // employeePosition.positionIsSelected = false; - // } - employeePosition.createdUserId = ""; - employeePosition.createdFullName = "System Administrator"; - employeePosition.createdAt = new Date(); - employeePosition.lastUpdateUserId = ""; - employeePosition.lastUpdateFullName = "System Administrator"; - employeePosition.lastUpdatedAt = new Date(); - await employeePositionRepository.save(employeePosition); - }); + await Promise.all( + item.positions.map(async (pos: any) => { + delete pos.id; + const employeePosition: EmployeePosition = Object.assign( + new EmployeePosition(), + pos, + ); + employeePosition.posMasterId = employeePosMaster.id; + // if ( + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" + // ) { + // employeePosition.positionIsSelected = false; + // } + employeePosition.createdUserId = ""; + employeePosition.createdFullName = "System Administrator"; + employeePosition.createdAt = new Date(); + employeePosition.lastUpdateUserId = ""; + employeePosition.lastUpdateFullName = "System Administrator"; + employeePosition.lastUpdatedAt = new Date(); + await employeePositionRepository.save(employeePosition); + }), + ); }), ); // create employeeTempPosmaster await Promise.all( _orgemployeeTempPosMaster .filter( - (x: EmployeeTempPosMaster) => x.orgChild1Id == data1Id && x.orgChild2Id == null, + (x: EmployeeTempPosMaster) => x.orgChild2Id == data2Id && x.orgChild3Id == null, ) .map(async (item: any) => { delete item.id; @@ -1286,8 +1467,9 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { // } // employeeTempPosMaster.current_holderId = null; employeeTempPosMaster.orgRevisionId = orgRevisionDraft.id; - employeeTempPosMaster.orgRootId = matchedOrgRoot?.id ?? null; - employeeTempPosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; + employeeTempPosMaster.orgRootId = dataId; + employeeTempPosMaster.orgChild1Id = data1Id; + employeeTempPosMaster.orgChild2Id = data2Id; employeeTempPosMaster.createdUserId = ""; employeeTempPosMaster.createdFullName = "System Administrator"; employeeTempPosMaster.createdAt = new Date(); @@ -1297,54 +1479,186 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { await repoEmployeeTempPosmaster.save(employeeTempPosMaster); //create employeePosition - item.positions.map(async (pos: any) => { - delete pos.id; - const employeePosition: EmployeePosition = Object.assign( - new EmployeePosition(), - pos, - ); - employeePosition.posMasterTempId = employeeTempPosMaster.id; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" - // ) { - // employeePosition.positionIsSelected = false; - // } - employeePosition.createdUserId = ""; - employeePosition.createdFullName = "System Administrator"; - employeePosition.createdAt = new Date(); - employeePosition.lastUpdateUserId = ""; - employeePosition.lastUpdateFullName = "System Administrator"; - employeePosition.lastUpdatedAt = new Date(); - await employeePositionRepository.save(employeePosition); - }); + await Promise.all( + item.positions.map(async (pos: any) => { + delete pos.id; + const employeePosition: EmployeePosition = Object.assign( + new EmployeePosition(), + pos, + ); + employeePosition.posMasterTempId = employeeTempPosMaster.id; + // if ( + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" + // ) { + // employeePosition.positionIsSelected = false; + // } + employeePosition.createdUserId = ""; + employeePosition.createdFullName = "System Administrator"; + employeePosition.createdAt = new Date(); + employeePosition.lastUpdateUserId = ""; + employeePosition.lastUpdateFullName = "System Administrator"; + employeePosition.lastUpdatedAt = new Date(); + await employeePositionRepository.save(employeePosition); + }), + ); }), ); // } //create org - orgChild2 - .filter((x: OrgChild2) => x.orgChild1Id == data1Id) - .forEach(async (x: any) => { - var data2Id = x.id; - const orgChild2Current = await child2Repository.find({ - where: { orgRevisionId: orgRevisionDraft.id }, - }); + for (const x of orgChild3.filter((item: OrgChild3) => item.orgChild2Id == data2Id)) { + const data3Id = x.id; + const matchedOrgChild3 = findMatchedNodeByAncestorDNA(orgChild3Current, x); + // console.log("[in case Child3] ancestorDNA", `${x.orgChild3Id == matchedOrgChild3?.id}`); + // if ( + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" + // ) { + //create employeePosmaster + await Promise.all( + _orgemployeePosMaster + .filter( + (x: EmployeePosMaster) => x.orgChild3Id == data3Id && x.orgChild4Id == null, + ) + .map(async (item: any) => { + delete item.id; + // console.log("[in case Child3] orgChild3Id == data3Id"); + const employeePosMaster = Object.assign(new EmployeePosMaster(), item); + employeePosMaster.positions = []; + // if ( + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" + // ) { + // employeePosMaster.current_holderId = item.current_holderId; + // } else { + // // employeePosMaster.next_holderId = null; + // employeePosMaster.isSit = false; + // } + // if ( + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" + // ) { + // employeePosMaster.authRoleId = item.authRoleId; + // } else { + // employeePosMaster.authRoleId = null; + // } + // employeePosMaster.current_holderId = null; + employeePosMaster.orgRevisionId = orgRevisionDraft.id; + employeePosMaster.orgRootId = matchedOrgRoot?.id ?? null; + employeePosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; + employeePosMaster.orgChild2Id = matchedOrgChild2?.id ?? null; + employeePosMaster.orgChild3Id = matchedOrgChild3?.id ?? null; + employeePosMaster.createdUserId = ""; + employeePosMaster.createdFullName = "System Administrator"; + employeePosMaster.createdAt = new Date(); + employeePosMaster.lastUpdateUserId = ""; + employeePosMaster.lastUpdateFullName = "System Administrator"; + employeePosMaster.lastUpdatedAt = new Date(); + await repoEmployeePosmaster.save(employeePosMaster); - const matchedOrgChild2 = orgChild2Current.find((i: OrgChild2) => { - if ( - x.ancestorDNA === x.id || // ถ้า ancestorDNA ถูกตั้งเป็น id ตัวเอง - x.ancestorDNA === null || - x.ancestorDNA === "00000000-0000-0000-0000-000000000000" - ) { - return ( - i.ancestorDNA === null || - i.ancestorDNA === "00000000-0000-0000-0000-000000000000" + //create employeePosition + await Promise.all( + item.positions.map(async (pos: any) => { + delete pos.id; + const employeePosition: EmployeePosition = Object.assign( + new EmployeePosition(), + pos, + ); + employeePosition.posMasterId = employeePosMaster.id; + // if ( + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" + // ) { + // employeePosition.positionIsSelected = false; + // } + employeePosition.createdUserId = ""; + employeePosition.createdFullName = "System Administrator"; + employeePosition.createdAt = new Date(); + employeePosition.lastUpdateUserId = ""; + employeePosition.lastUpdateFullName = "System Administrator"; + employeePosition.lastUpdatedAt = new Date(); + await employeePositionRepository.save(employeePosition); + }), ); - } - return i.ancestorDNA === x.ancestorDNA; - }); - // console.log("[in case Child2] ancestorDNA", `${x.orgChild2Id == matchedOrgChild2?.id}`); + }), + ); + // create employeeTempPosmaster + await Promise.all( + _orgemployeeTempPosMaster + .filter( + (x: EmployeeTempPosMaster) => x.orgChild3Id == data3Id && x.orgChild4Id == null, + ) + .map(async (item: any) => { + delete item.id; + const employeeTempPosMaster = Object.assign(new EmployeeTempPosMaster(), item); + employeeTempPosMaster.positions = []; + // if ( + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" + // ) { + // employeeTempPosMaster.current_holderId = item.current_holderId; + // } else { + // // employeeTempPosMaster.next_holderId = null; + // employeeTempPosMaster.isSit = false; + // } + // if ( + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" + // ) { + // employeeTempPosMaster.authRoleId = item.authRoleId; + // } else { + // employeeTempPosMaster.authRoleId = null; + // } + // employeeTempPosMaster.current_holderId = null; + employeeTempPosMaster.orgRevisionId = orgRevisionDraft.id; + employeeTempPosMaster.orgRootId = matchedOrgRoot?.id ?? null; + employeeTempPosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; + employeeTempPosMaster.orgChild2Id = matchedOrgChild2?.id ?? null; + employeeTempPosMaster.orgChild3Id = matchedOrgChild3?.id ?? null; + employeeTempPosMaster.createdUserId = ""; + employeeTempPosMaster.createdFullName = "System Administrator"; + employeeTempPosMaster.createdAt = new Date(); + employeeTempPosMaster.lastUpdateUserId = ""; + employeeTempPosMaster.lastUpdateFullName = "System Administrator"; + employeeTempPosMaster.lastUpdatedAt = new Date(); + await repoEmployeeTempPosmaster.save(employeeTempPosMaster); + + //create employeePosition + await Promise.all( + item.positions.map(async (pos: any) => { + delete pos.id; + const employeePosition: EmployeePosition = Object.assign( + new EmployeePosition(), + pos, + ); + employeePosition.posMasterTempId = employeeTempPosMaster.id; + // if ( + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" + // ) { + // employeePosition.positionIsSelected = false; + // } + employeePosition.createdUserId = ""; + employeePosition.createdFullName = "System Administrator"; + employeePosition.createdAt = new Date(); + employeePosition.lastUpdateUserId = ""; + employeePosition.lastUpdateFullName = "System Administrator"; + employeePosition.lastUpdatedAt = new Date(); + await employeePositionRepository.save(employeePosition); + }), + ); + }), + ); + // } + + //create org + for (const x of orgChild4.filter((item: OrgChild4) => item.orgChild3Id == data3Id)) { + const data4Id = x.id; + const matchedOrgChild4 = findMatchedNodeByAncestorDNA(orgChild4Current, x); + // console.log("[in case Child4] ancestorDNA", `${x.orgChild4Id == matchedOrgChild4?.id}`); // if ( // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || @@ -1354,12 +1668,10 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { //create employeePosmaster await Promise.all( _orgemployeePosMaster - .filter( - (x: EmployeePosMaster) => x.orgChild2Id == data2Id && x.orgChild3Id == null, - ) + .filter((x: EmployeePosMaster) => x.orgChild4Id == data4Id) .map(async (item: any) => { delete item.id; - // console.log("[in case Child2] orgChild2Id == data2Id"); + // console.log("[in case Child4] orgChild4Id == data4Id"); const employeePosMaster = Object.assign(new EmployeePosMaster(), item); employeePosMaster.positions = []; // if ( @@ -1384,6 +1696,8 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { employeePosMaster.orgRootId = matchedOrgRoot?.id ?? null; employeePosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; employeePosMaster.orgChild2Id = matchedOrgChild2?.id ?? null; + employeePosMaster.orgChild3Id = matchedOrgChild3?.id ?? null; + employeePosMaster.orgChild4Id = matchedOrgChild4?.id ?? null; employeePosMaster.createdUserId = ""; employeePosMaster.createdFullName = "System Administrator"; employeePosMaster.createdAt = new Date(); @@ -1393,36 +1707,35 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { await repoEmployeePosmaster.save(employeePosMaster); //create employeePosition - item.positions.map(async (pos: any) => { - delete pos.id; - const employeePosition: EmployeePosition = Object.assign( - new EmployeePosition(), - pos, - ); - employeePosition.posMasterId = employeePosMaster.id; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" - // ) { - // employeePosition.positionIsSelected = false; - // } - employeePosition.createdUserId = ""; - employeePosition.createdFullName = "System Administrator"; - employeePosition.createdAt = new Date(); - employeePosition.lastUpdateUserId = ""; - employeePosition.lastUpdateFullName = "System Administrator"; - employeePosition.lastUpdatedAt = new Date(); - await employeePositionRepository.save(employeePosition); - }); + await Promise.all( + item.positions.map(async (pos: any) => { + delete pos.id; + const employeePosition: EmployeePosition = Object.assign( + new EmployeePosition(), + pos, + ); + employeePosition.posMasterId = employeePosMaster.id; + // if ( + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" + // ) { + // employeePosition.positionIsSelected = false; + // } + employeePosition.createdUserId = ""; + employeePosition.createdFullName = "System Administrator"; + employeePosition.createdAt = new Date(); + employeePosition.lastUpdateUserId = ""; + employeePosition.lastUpdateFullName = "System Administrator"; + employeePosition.lastUpdatedAt = new Date(); + await employeePositionRepository.save(employeePosition); + }), + ); }), ); - // create employeeTempPosmaster + //create employeeTempPosmaster await Promise.all( _orgemployeeTempPosMaster - .filter( - (x: EmployeeTempPosMaster) => - x.orgChild2Id == data2Id && x.orgChild3Id == null, - ) + .filter((x: EmployeeTempPosMaster) => x.orgChild4Id == data4Id) .map(async (item: any) => { delete item.id; const employeeTempPosMaster = Object.assign( @@ -1449,9 +1762,11 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { // } // employeeTempPosMaster.current_holderId = null; employeeTempPosMaster.orgRevisionId = orgRevisionDraft.id; - employeeTempPosMaster.orgRootId = dataId; - employeeTempPosMaster.orgChild1Id = data1Id; - employeeTempPosMaster.orgChild2Id = data2Id; + employeeTempPosMaster.orgRootId = matchedOrgRoot?.id ?? null; + employeeTempPosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; + employeeTempPosMaster.orgChild2Id = matchedOrgChild2?.id ?? null; + employeeTempPosMaster.orgChild3Id = matchedOrgChild3?.id ?? null; + employeeTempPosMaster.orgChild4Id = matchedOrgChild4?.id ?? null; employeeTempPosMaster.createdUserId = ""; employeeTempPosMaster.createdFullName = "System Administrator"; employeeTempPosMaster.createdAt = new Date(); @@ -1461,368 +1776,37 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { await repoEmployeeTempPosmaster.save(employeeTempPosMaster); //create employeePosition - item.positions.map(async (pos: any) => { - delete pos.id; - const employeePosition: EmployeePosition = Object.assign( - new EmployeePosition(), - pos, - ); - employeePosition.posMasterTempId = employeeTempPosMaster.id; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" - // ) { - // employeePosition.positionIsSelected = false; - // } - employeePosition.createdUserId = ""; - employeePosition.createdFullName = "System Administrator"; - employeePosition.createdAt = new Date(); - employeePosition.lastUpdateUserId = ""; - employeePosition.lastUpdateFullName = "System Administrator"; - employeePosition.lastUpdatedAt = new Date(); - await employeePositionRepository.save(employeePosition); - }); + await Promise.all( + item.positions.map(async (pos: any) => { + delete pos.id; + const employeePosition: EmployeePosition = Object.assign( + new EmployeePosition(), + pos, + ); + employeePosition.posMasterTempId = employeeTempPosMaster.id; + // if ( + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || + // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" + // ) { + // employeePosition.positionIsSelected = false; + // } + employeePosition.createdUserId = ""; + employeePosition.createdFullName = "System Administrator"; + employeePosition.createdAt = new Date(); + employeePosition.lastUpdateUserId = ""; + employeePosition.lastUpdateFullName = "System Administrator"; + employeePosition.lastUpdatedAt = new Date(); + await employeePositionRepository.save(employeePosition); + }), + ); }), ); // } - - //create org - orgChild3 - .filter((x: OrgChild3) => x.orgChild2Id == data2Id) - .forEach(async (x: any) => { - var data3Id = x.id; - const orgChild3Current = await child3Repository.find({ - where: { orgRevisionId: orgRevisionDraft.id }, - }); - - const matchedOrgChild3 = orgChild3Current.find((i: OrgChild3) => { - if ( - x.ancestorDNA === x.id || // ถ้า ancestorDNA ถูกตั้งเป็น id ตัวเอง - x.ancestorDNA === null || - x.ancestorDNA === "00000000-0000-0000-0000-000000000000" - ) { - return ( - i.ancestorDNA === null || - i.ancestorDNA === "00000000-0000-0000-0000-000000000000" - ); - } - return i.ancestorDNA === x.ancestorDNA; - }); - // console.log("[in case Child3] ancestorDNA", `${x.orgChild3Id == matchedOrgChild3?.id}`); - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - //create employeePosmaster - await Promise.all( - _orgemployeePosMaster - .filter( - (x: EmployeePosMaster) => - x.orgChild3Id == data3Id && x.orgChild4Id == null, - ) - .map(async (item: any) => { - delete item.id; - // console.log("[in case Child3] orgChild3Id == data3Id"); - const employeePosMaster = Object.assign(new EmployeePosMaster(), item); - employeePosMaster.positions = []; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeePosMaster.current_holderId = item.current_holderId; - // } else { - // // employeePosMaster.next_holderId = null; - // employeePosMaster.isSit = false; - // } - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeePosMaster.authRoleId = item.authRoleId; - // } else { - // employeePosMaster.authRoleId = null; - // } - // employeePosMaster.current_holderId = null; - employeePosMaster.orgRevisionId = orgRevisionDraft.id; - employeePosMaster.orgRootId = matchedOrgRoot?.id ?? null; - employeePosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; - employeePosMaster.orgChild2Id = matchedOrgChild2?.id ?? null; - employeePosMaster.orgChild3Id = matchedOrgChild3?.id ?? null; - employeePosMaster.createdUserId = ""; - employeePosMaster.createdFullName = "System Administrator"; - employeePosMaster.createdAt = new Date(); - employeePosMaster.lastUpdateUserId = ""; - employeePosMaster.lastUpdateFullName = "System Administrator"; - employeePosMaster.lastUpdatedAt = new Date(); - await repoEmployeePosmaster.save(employeePosMaster); - - //create employeePosition - item.positions.map(async (pos: any) => { - delete pos.id; - const employeePosition: EmployeePosition = Object.assign( - new EmployeePosition(), - pos, - ); - employeePosition.posMasterId = employeePosMaster.id; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" - // ) { - // employeePosition.positionIsSelected = false; - // } - employeePosition.createdUserId = ""; - employeePosition.createdFullName = "System Administrator"; - employeePosition.createdAt = new Date(); - employeePosition.lastUpdateUserId = ""; - employeePosition.lastUpdateFullName = "System Administrator"; - employeePosition.lastUpdatedAt = new Date(); - await employeePositionRepository.save(employeePosition); - }); - }), - ); - // create employeeTempPosmaster - await Promise.all( - _orgemployeeTempPosMaster - .filter( - (x: EmployeeTempPosMaster) => - x.orgChild3Id == data3Id && x.orgChild4Id == null, - ) - .map(async (item: any) => { - delete item.id; - const employeeTempPosMaster = Object.assign( - new EmployeeTempPosMaster(), - item, - ); - employeeTempPosMaster.positions = []; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeeTempPosMaster.current_holderId = item.current_holderId; - // } else { - // // employeeTempPosMaster.next_holderId = null; - // employeeTempPosMaster.isSit = false; - // } - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeeTempPosMaster.authRoleId = item.authRoleId; - // } else { - // employeeTempPosMaster.authRoleId = null; - // } - // employeeTempPosMaster.current_holderId = null; - employeeTempPosMaster.orgRevisionId = orgRevisionDraft.id; - employeeTempPosMaster.orgRootId = matchedOrgRoot?.id ?? null; - employeeTempPosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; - employeeTempPosMaster.orgChild2Id = matchedOrgChild2?.id ?? null; - employeeTempPosMaster.orgChild3Id = matchedOrgChild3?.id ?? null; - employeeTempPosMaster.createdUserId = ""; - employeeTempPosMaster.createdFullName = "System Administrator"; - employeeTempPosMaster.createdAt = new Date(); - employeeTempPosMaster.lastUpdateUserId = ""; - employeeTempPosMaster.lastUpdateFullName = "System Administrator"; - employeeTempPosMaster.lastUpdatedAt = new Date(); - await repoEmployeeTempPosmaster.save(employeeTempPosMaster); - - //create employeePosition - item.positions.map(async (pos: any) => { - delete pos.id; - const employeePosition: EmployeePosition = Object.assign( - new EmployeePosition(), - pos, - ); - employeePosition.posMasterTempId = employeeTempPosMaster.id; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" - // ) { - // employeePosition.positionIsSelected = false; - // } - employeePosition.createdUserId = ""; - employeePosition.createdFullName = "System Administrator"; - employeePosition.createdAt = new Date(); - employeePosition.lastUpdateUserId = ""; - employeePosition.lastUpdateFullName = "System Administrator"; - employeePosition.lastUpdatedAt = new Date(); - await employeePositionRepository.save(employeePosition); - }); - }), - ); - // } - - //create org - orgChild4 - .filter((x: OrgChild4) => x.orgChild3Id == data3Id) - .forEach(async (x: any) => { - var data4Id = x.id; - const orgChild4Current = await child4Repository.find({ - where: { orgRevisionId: orgRevisionDraft.id }, - }); - - const matchedOrgChild4 = orgChild4Current.find((i: OrgChild4) => { - if ( - x.ancestorDNA === x.id || // ถ้า ancestorDNA ถูกตั้งเป็น id ตัวเอง - x.ancestorDNA === null || - x.ancestorDNA === "00000000-0000-0000-0000-000000000000" - ) { - return ( - i.ancestorDNA === null || - i.ancestorDNA === "00000000-0000-0000-0000-000000000000" - ); - } - return i.ancestorDNA === x.ancestorDNA; - }); - // console.log("[in case Child4] ancestorDNA", `${x.orgChild4Id == matchedOrgChild4?.id}`); - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - //create employeePosmaster - await Promise.all( - _orgemployeePosMaster - .filter((x: EmployeePosMaster) => x.orgChild4Id == data4Id) - .map(async (item: any) => { - delete item.id; - // console.log("[in case Child4] orgChild4Id == data4Id"); - const employeePosMaster = Object.assign( - new EmployeePosMaster(), - item, - ); - employeePosMaster.positions = []; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeePosMaster.current_holderId = item.current_holderId; - // } else { - // // employeePosMaster.next_holderId = null; - // employeePosMaster.isSit = false; - // } - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeePosMaster.authRoleId = item.authRoleId; - // } else { - // employeePosMaster.authRoleId = null; - // } - // employeePosMaster.current_holderId = null; - employeePosMaster.orgRevisionId = orgRevisionDraft.id; - employeePosMaster.orgRootId = matchedOrgRoot?.id ?? null; - employeePosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; - employeePosMaster.orgChild2Id = matchedOrgChild2?.id ?? null; - employeePosMaster.orgChild3Id = matchedOrgChild3?.id ?? null; - employeePosMaster.orgChild4Id = matchedOrgChild4?.id ?? null; - employeePosMaster.createdUserId = ""; - employeePosMaster.createdFullName = "System Administrator"; - employeePosMaster.createdAt = new Date(); - employeePosMaster.lastUpdateUserId = ""; - employeePosMaster.lastUpdateFullName = "System Administrator"; - employeePosMaster.lastUpdatedAt = new Date(); - await repoEmployeePosmaster.save(employeePosMaster); - - //create employeePosition - item.positions.map(async (pos: any) => { - delete pos.id; - const employeePosition: EmployeePosition = Object.assign( - new EmployeePosition(), - pos, - ); - employeePosition.posMasterId = employeePosMaster.id; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" - // ) { - // employeePosition.positionIsSelected = false; - // } - employeePosition.createdUserId = ""; - employeePosition.createdFullName = "System Administrator"; - employeePosition.createdAt = new Date(); - employeePosition.lastUpdateUserId = ""; - employeePosition.lastUpdateFullName = "System Administrator"; - employeePosition.lastUpdatedAt = new Date(); - await employeePositionRepository.save(employeePosition); - }); - }), - ); - //create employeeTempPosmaster - await Promise.all( - _orgemployeeTempPosMaster - .filter((x: EmployeeTempPosMaster) => x.orgChild4Id == data4Id) - .map(async (item: any) => { - delete item.id; - const employeeTempPosMaster = Object.assign( - new EmployeeTempPosMaster(), - item, - ); - employeeTempPosMaster.positions = []; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeeTempPosMaster.current_holderId = item.current_holderId; - // } else { - // // employeeTempPosMaster.next_holderId = null; - // employeeTempPosMaster.isSit = false; - // } - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeeTempPosMaster.authRoleId = item.authRoleId; - // } else { - // employeeTempPosMaster.authRoleId = null; - // } - // employeeTempPosMaster.current_holderId = null; - employeeTempPosMaster.orgRevisionId = orgRevisionDraft.id; - employeeTempPosMaster.orgRootId = matchedOrgRoot?.id ?? null; - employeeTempPosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; - employeeTempPosMaster.orgChild2Id = matchedOrgChild2?.id ?? null; - employeeTempPosMaster.orgChild3Id = matchedOrgChild3?.id ?? null; - employeeTempPosMaster.orgChild4Id = matchedOrgChild4?.id ?? null; - employeeTempPosMaster.createdUserId = ""; - employeeTempPosMaster.createdFullName = "System Administrator"; - employeeTempPosMaster.createdAt = new Date(); - employeeTempPosMaster.lastUpdateUserId = ""; - employeeTempPosMaster.lastUpdateFullName = "System Administrator"; - employeeTempPosMaster.lastUpdatedAt = new Date(); - await repoEmployeeTempPosmaster.save(employeeTempPosMaster); - - //create employeePosition - item.positions.map(async (pos: any) => { - delete pos.id; - const employeePosition: EmployeePosition = Object.assign( - new EmployeePosition(), - pos, - ); - employeePosition.posMasterTempId = employeeTempPosMaster.id; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" - // ) { - // employeePosition.positionIsSelected = false; - // } - employeePosition.createdUserId = ""; - employeePosition.createdFullName = "System Administrator"; - employeePosition.createdAt = new Date(); - employeePosition.lastUpdateUserId = ""; - employeePosition.lastUpdateFullName = "System Administrator"; - employeePosition.lastUpdatedAt = new Date(); - await employeePositionRepository.save(employeePosition); - }); - }), - ); - // } - }); - }); - }); - }); - }); + } + } + } + } + } // } const employeePosMaster = await repoEmployeePosmaster.find({ @@ -1848,7 +1832,7 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { item.lastUpdateUserId = lastUpdateUserId; item.lastUpdateFullName = lastUpdateFullName; item.lastUpdatedAt = lastUpdatedAt; - await repoEmployeePosmaster.save(item).catch((e) => console.log(e)); + await repoEmployeePosmaster.save(item); } const employeeTempPosMaster = await repoEmployeeTempPosmaster.find({ where: { orgRevisionId: orgRevisionDraft.id }, @@ -1873,7 +1857,7 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { item.lastUpdateUserId = lastUpdateUserId; item.lastUpdateFullName = lastUpdateFullName; item.lastUpdatedAt = lastUpdatedAt; - await repoEmployeeTempPosmaster.save(item).catch((e) => console.log(e)); + await repoEmployeeTempPosmaster.save(item); } } console.log("[AMQ] Excecute Organization Success"); @@ -1887,10 +1871,10 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { { userId: user?.sub }, ).catch(console.error); } - console.timeEnd('[AMQ] clone_org_structure'); + console.timeEnd("[AMQ] clone_org_structure"); // อัปเดตสถานะ orgRevision หลังจากทำงานเสร็จทั้งหมด - console.time('[AMQ] save_revision_status'); + console.time("[AMQ] save_revision_status"); orgRevisionPublish.orgRevisionIsDraft = false; orgRevisionPublish.orgRevisionIsCurrent = false; await repoOrgRevision.save(orgRevisionPublish); @@ -1898,10 +1882,10 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { orgRevisionDraft.orgRevisionIsCurrent = true; orgRevisionDraft.orgRevisionIsDraft = false; await repoOrgRevision.save(orgRevisionDraft); - console.timeEnd('[AMQ] save_revision_status'); + console.timeEnd("[AMQ] save_revision_status"); console.log(`[AMQ] handler_org SUCCESS - Total time: ${Date.now() - startTime}ms`); - console.timeEnd('[AMQ] handler_org_total'); + console.timeEnd("[AMQ] handler_org_total"); return true; } catch (error) { const totalTime = Date.now() - startTime; @@ -1916,7 +1900,7 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { { userId: user?.sub }, ).catch(console.error); } - console.timeEnd('[AMQ] handler_org_total'); + console.timeEnd("[AMQ] handler_org_total"); return false; } } @@ -2591,7 +2575,8 @@ async function handler_org_draft(msg: amqp.ConsumeMessage): Promise { }); await posMasterAssignRepository.delete({ posMasterId: In(_posMasters.map((x) => x.id)) }); await posMasterActRepository.delete({ posMasterId: In(_posMasters.map((x) => x.id)) }); //ใช้ posMasterId ของ revision: draft *แต่ยังไม่เจอช็อดไหนที่ใช้โครงสร้างแบบร่างในรักษาการแทน - await posMasterActRepository.delete({ //ใช้ posMasterId ของ revision: draft *แต่ยังไม่เจอช็อดไหนที่ใช้โครงสร้างแบบร่างในรักษาการแทน + await posMasterActRepository.delete({ + //ใช้ posMasterId ของ revision: draft *แต่ยังไม่เจอช็อดไหนที่ใช้โครงสร้างแบบร่างในรักษาการแทน posMasterChildId: In(_posMasters.map((x) => x.id)), }); // await posMasterRepository.remove(_posMasters); @@ -2619,24 +2604,26 @@ async function handler_org_draft(msg: amqp.ConsumeMessage): Promise { await child2Repository.delete({ orgRevisionId: In(_orgRevisions.map((x) => x.id)) }); await child1Repository.delete({ orgRevisionId: In(_orgRevisions.map((x) => x.id)) }); // Task #2160 อัพเดทหน้าที่จัดการโครงสร้างแบบร่าง - if (["ORG", "ORG_POSITION", "ORG_POSITION_PERSON", "ORG_POSITION_ROLE", "ORG_POSITION_PERSON_ROLE"].includes(requestBody.typeDraft?.toUpperCase())) { + if ( + [ + "ORG", + "ORG_POSITION", + "ORG_POSITION_PERSON", + "ORG_POSITION_ROLE", + "ORG_POSITION_PERSON_ROLE", + ].includes(requestBody.typeDraft?.toUpperCase()) + ) { const _newRoots = await orgRootRepository.find({ - where: { orgRevisionId: revision.id } + where: { orgRevisionId: revision.id }, }); - const newRootMap = new Map( - _newRoots.map(r => [r.ancestorDNA, r.id]) - ); + const newRootMap = new Map(_newRoots.map((r) => [r.ancestorDNA, r.id])); for (const oldRoot of _roots) { const newRootId = newRootMap.get(oldRoot.ancestorDNA); if (!newRootId) continue; // อัพเดท orgRootId ที่อยู่ภายใต้ orgRevision แบบร่างเดิมเป็นของ orgRevision แบบร่างใหม่ - await permissionOrgRepository.update( - { orgRootId: oldRoot.id }, - { orgRootId: newRootId } - ); + await permissionOrgRepository.update({ orgRootId: oldRoot.id }, { orgRootId: newRootId }); } - } - else { + } else { await permissionOrgRepository.delete({ orgRootId: In(_roots.map((x) => x.id)), }); From 3335c4f44cb1b4899fba281ce31d66508df40136 Mon Sep 17 00:00:00 2001 From: waruneeauy Date: Tue, 5 May 2026 12:32:21 +0700 Subject: [PATCH 2/6] refactor transaction --- src/services/PositionService.ts | 201 ++++++------ src/services/rabbitmq.ts | 549 +++++++++----------------------- 2 files changed, 251 insertions(+), 499 deletions(-) diff --git a/src/services/PositionService.ts b/src/services/PositionService.ts index 44916aee..357ec2af 100644 --- a/src/services/PositionService.ts +++ b/src/services/PositionService.ts @@ -1,4 +1,4 @@ -import { In } from "typeorm"; +import { EntityManager, In } from "typeorm"; import { SavePosMasterHistory } from "./../interfaces/OrgMapping"; import { AppDataSource } from "../database/data-source"; import { EmployeePosMaster } from "../entities/EmployeePosMaster"; @@ -17,105 +17,118 @@ export async function CreatePosMasterHistoryOfficer( request: RequestWithUser | null, type?: string | null, positionData?: { positionId?: string } | null, + manager?: EntityManager, ): Promise { - try { - await AppDataSource.transaction(async (manager) => { - const repoPosmaster = manager.getRepository(PosMaster); - const repoHistory = manager.getRepository(PosMasterHistory); - const repoOrgRevision = manager.getRepository(OrgRevision); - const repoPosition = manager.getRepository(Position); + const execute = async (transactionManager: EntityManager) => { + const repoPosmaster = transactionManager.getRepository(PosMaster); + const repoHistory = transactionManager.getRepository(PosMasterHistory); + const repoOrgRevision = transactionManager.getRepository(OrgRevision); + const repoPosition = transactionManager.getRepository(Position); - const pm = await repoPosmaster.findOne({ - where: { id: posMasterId }, - relations: [ - "positions", - "positions.posLevel", - "positions.posType", - "positions.posExecutive", - "orgRoot", - "orgChild1", - "orgChild2", - "orgChild3", - "orgChild4", - "current_holder", - "next_holder", - ], - }); - - if (!pm) return false; - if (!pm.ancestorDNA) return false; - - const checkCurrentRevision = await repoOrgRevision.findOne({ - where: { - id: pm.orgRevisionId, - orgRevisionIsCurrent: true, - orgRevisionIsDraft: false, - }, - }); - const _null: any = null; - const h = new PosMasterHistory(); - - // query position โดยตรงจาก positionRepository - let selectedPosition: Position | null = null; - if (positionData?.positionId) { - selectedPosition = await repoPosition.findOne({ - where: { id: positionData.positionId }, - relations: { posLevel: true, posType: true, posExecutive: true }, - }); - } else { - // ใช้ logic เดิม หาจาก pm.positions ที่ positionIsSelected = true - selectedPosition = - pm.positions.length > 0 - ? pm.positions.find((p) => p.positionIsSelected === true) ?? null - : null; - } - - h.ancestorDNA = pm.ancestorDNA ? pm.ancestorDNA : _null; - if (!type || type != "DELETE") { - if (checkCurrentRevision) { - h.prefix = pm.current_holder?.prefix || _null; - h.firstName = pm.current_holder?.firstName || _null; - h.lastName = pm.current_holder?.lastName || _null; - h.profileId = pm.current_holder?.id || _null; - } else { - h.prefix = pm.next_holder?.prefix || _null; - h.firstName = pm.next_holder?.firstName || _null; - h.lastName = pm.next_holder?.lastName || _null; - } - h.position = selectedPosition?.positionName ?? _null; - h.posType = selectedPosition?.posType?.posTypeName ?? _null; - h.posLevel = selectedPosition?.posLevel?.posLevelName ?? _null; - } - h.rootDnaId = pm.orgRoot?.ancestorDNA || _null; - h.child1DnaId = pm.orgChild1?.ancestorDNA || _null; - h.child2DnaId = pm.orgChild2?.ancestorDNA || _null; - h.child3DnaId = pm.orgChild3?.ancestorDNA || _null; - h.child4DnaId = pm.orgChild4?.ancestorDNA || _null; - h.posMasterNoPrefix = pm.posMasterNoPrefix ?? _null; - h.posMasterNo = pm.posMasterNo ?? _null; - h.posMasterNoSuffix = pm.posMasterNoSuffix ?? _null; - h.posExecutive = selectedPosition?.posExecutive?.posExecutiveName ?? _null; - h.shortName = - [ - pm.orgChild4?.orgChild4ShortName, - pm.orgChild3?.orgChild3ShortName, - pm.orgChild2?.orgChild2ShortName, - pm.orgChild1?.orgChild1ShortName, - pm.orgRoot?.orgRootShortName, - ].find((s) => typeof s === "string" && s.trim().length > 0) ?? _null; - const userId = request?.user?.sub ?? ""; - const userName = request?.user?.name ?? "system"; - h.createdUserId = userId; - h.createdFullName = userName; - h.lastUpdateUserId = userId; - h.lastUpdateFullName = userName; - h.createdAt = new Date(); - h.lastUpdatedAt = new Date(); - await repoHistory.save(h); + const pm = await repoPosmaster.findOne({ + where: { id: posMasterId }, + relations: [ + "positions", + "positions.posLevel", + "positions.posType", + "positions.posExecutive", + "orgRoot", + "orgChild1", + "orgChild2", + "orgChild3", + "orgChild4", + "current_holder", + "next_holder", + ], }); + if (!pm || !pm.ancestorDNA) { + return; + } + + const checkCurrentRevision = await repoOrgRevision.findOne({ + where: { + id: pm.orgRevisionId, + orgRevisionIsCurrent: true, + orgRevisionIsDraft: false, + }, + }); + const _null: any = null; + const h = new PosMasterHistory(); + + // query position โดยตรงจาก positionRepository + let selectedPosition: Position | null = null; + if (positionData?.positionId) { + selectedPosition = await repoPosition.findOne({ + where: { id: positionData.positionId }, + relations: { posLevel: true, posType: true, posExecutive: true }, + }); + } else { + // ใช้ logic เดิม หาจาก pm.positions ที่ positionIsSelected = true + selectedPosition = + pm.positions.length > 0 + ? pm.positions.find((p) => p.positionIsSelected === true) ?? null + : null; + } + + h.ancestorDNA = pm.ancestorDNA ? pm.ancestorDNA : _null; + if (!type || type != "DELETE") { + if (checkCurrentRevision) { + h.prefix = pm.current_holder?.prefix || _null; + h.firstName = pm.current_holder?.firstName || _null; + h.lastName = pm.current_holder?.lastName || _null; + h.profileId = pm.current_holder?.id || _null; + } else { + h.prefix = pm.next_holder?.prefix || _null; + h.firstName = pm.next_holder?.firstName || _null; + h.lastName = pm.next_holder?.lastName || _null; + } + h.position = selectedPosition?.positionName ?? _null; + h.posType = selectedPosition?.posType?.posTypeName ?? _null; + h.posLevel = selectedPosition?.posLevel?.posLevelName ?? _null; + } + h.rootDnaId = pm.orgRoot?.ancestorDNA || _null; + h.child1DnaId = pm.orgChild1?.ancestorDNA || _null; + h.child2DnaId = pm.orgChild2?.ancestorDNA || _null; + h.child3DnaId = pm.orgChild3?.ancestorDNA || _null; + h.child4DnaId = pm.orgChild4?.ancestorDNA || _null; + h.posMasterNoPrefix = pm.posMasterNoPrefix ?? _null; + h.posMasterNo = pm.posMasterNo ?? _null; + h.posMasterNoSuffix = pm.posMasterNoSuffix ?? _null; + h.posExecutive = selectedPosition?.posExecutive?.posExecutiveName ?? _null; + h.shortName = + [ + pm.orgChild4?.orgChild4ShortName, + pm.orgChild3?.orgChild3ShortName, + pm.orgChild2?.orgChild2ShortName, + pm.orgChild1?.orgChild1ShortName, + pm.orgRoot?.orgRootShortName, + ].find((s) => typeof s === "string" && s.trim().length > 0) ?? _null; + const userId = request?.user?.sub ?? ""; + const userName = request?.user?.name ?? "system"; + h.createdUserId = userId; + h.createdFullName = userName; + h.lastUpdateUserId = userId; + h.lastUpdateFullName = userName; + h.createdAt = new Date(); + h.lastUpdatedAt = new Date(); + await repoHistory.save(h); + }; + + try { + if (manager) { + await execute(manager); + return true; + } + + await AppDataSource.transaction(async (transactionManager) => { + await execute(transactionManager); + }); return true; } catch (err) { + if (manager) { + throw err; + } console.error("CreatePosMasterHistoryOfficer transaction error:", err); return false; } diff --git a/src/services/rabbitmq.ts b/src/services/rabbitmq.ts index 00b1f27a..42c386e0 100644 --- a/src/services/rabbitmq.ts +++ b/src/services/rabbitmq.ts @@ -818,77 +818,138 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { ); // ===== BATCH EXECUTION: save ทีละ batch ===== + let shouldSkipPublishInTransaction = false; + await AppDataSource.transaction(async (manager) => { + const repoPosmaster = manager.getRepository(PosMaster); + const posMasterAssignRepository = manager.getRepository(PosMasterAssign); + const posMasterActRepository = manager.getRepository(PosMasterAct); + const permissionProfilesRepository = manager.getRepository(PermissionProfile); + const repoEmployeePosmaster = manager.getRepository(EmployeePosMaster); + const repoEmployeeTempPosmaster = manager.getRepository(EmployeeTempPosMaster); + const repoProfile = manager.getRepository(Profile); + const repoProfileEmployee = manager.getRepository(ProfileEmployee); + const employeePositionRepository = manager.getRepository(EmployeePosition); + const repoOrgRevision = manager.getRepository(OrgRevision); + const orgRootRepository = manager.getRepository(OrgRoot); + const child1Repository = manager.getRepository(OrgChild1); + const child2Repository = manager.getRepository(OrgChild2); + const child3Repository = manager.getRepository(OrgChild3); + const child4Repository = manager.getRepository(OrgChild4); - // 4. Batch save posMasterAssign (chunk 500) - console.time("[AMQ] batch_save_posMasterAssign"); - if (posMasterAssignsToSave.length > 0) { - const chunks = chunkArray(posMasterAssignsToSave, 500); - for (const chunk of chunks) { - await posMasterAssignRepository.save(chunk); + const targetOrgRevision = await repoOrgRevision + .createQueryBuilder("orgRevision") + .setLock("pessimistic_write") + .where("orgRevision.id = :id", { id }) + .getOne(); + + if (!targetOrgRevision) { + shouldSkipPublishInTransaction = true; + return; } - } - console.timeEnd("[AMQ] batch_save_posMasterAssign"); - // 5. Batch save profiles (chunk 200) - console.time("[AMQ] batch_save_profiles"); - if (profilesToSave.length > 0) { - const chunks = chunkArray(profilesToSave, 200); - for (const chunk of chunks) { - await repoProfile.save(chunk); + if (targetOrgRevision.orgRevisionIsCurrent && !targetOrgRevision.orgRevisionIsDraft) { + shouldSkipPublishInTransaction = true; + return; } - } - console.timeEnd("[AMQ] batch_save_profiles"); - // 6. Batch update posMasters - console.time("[AMQ] batch_update_posMasters"); - for (const update of posMasterUpdates) { - await repoPosmaster.update(update.id, { - current_holderId: update.current_holderId, - next_holderId: null, - lastUpdateUserId, - lastUpdateFullName, - lastUpdatedAt, - }); - } - console.timeEnd("[AMQ] batch_update_posMasters"); + if (!targetOrgRevision.orgRevisionIsDraft || targetOrgRevision.orgRevisionIsCurrent) { + shouldSkipPublishInTransaction = true; + return; + } - // 7. Batch create history - console.time("[AMQ] batch_create_history"); - for (const id of historyCreateIds) { - await CreatePosMasterHistoryOfficer(id, null); - } - console.timeEnd("[AMQ] batch_create_history"); + const orgRevisionPublish = await repoOrgRevision + .createQueryBuilder("orgRevision") + .setLock("pessimistic_write") + .where("orgRevision.orgRevisionIsDraft = false") + .andWhere("orgRevision.orgRevisionIsCurrent = true") + .getOne(); - // Clone oldposMasterAct - console.time("[AMQ] clone_oldposMasterAct"); - for (const act of oldposMasterAct) { - const parentDNA = act.posMaster?.ancestorDNA?.trim()?.toLowerCase() ?? ""; - const childDNA = act.posMasterChild?.ancestorDNA?.trim()?.toLowerCase() ?? ""; + if (!orgRevisionPublish) { + throw new Error("[AMQ] Cannot publish in transaction: no current org revision found"); + } - const newParentId = posMasterIdMap.get(parentDNA); - const newChildId = posMasterIdMap.get(childDNA); + const orgRevisionDraft = await repoOrgRevision + .createQueryBuilder("orgRevision") + .setLock("pessimistic_write") + .where("orgRevision.id = :id", { id }) + .andWhere("orgRevision.orgRevisionIsDraft = true") + .andWhere("orgRevision.orgRevisionIsCurrent = false") + .getOne(); - if (!newParentId || !newChildId) continue; + if (!orgRevisionDraft) { + shouldSkipPublishInTransaction = true; + return; + } - const { id, posMaster, posMasterChild, ...fields } = act; + // 4. Batch save posMasterAssign (chunk 500) + console.time("[AMQ] batch_save_posMasterAssign"); + if (posMasterAssignsToSave.length > 0) { + const chunks = chunkArray(posMasterAssignsToSave, 500); + for (const chunk of chunks) { + await posMasterAssignRepository.save(chunk); + } + } + console.timeEnd("[AMQ] batch_save_posMasterAssign"); - const newAct = { - ...fields, - posMasterId: newParentId, - posMasterChildId: newChildId, - createdAt: new Date(), - createdFullName: user ? user.name : "system", - createdUserId: user ? user.sub : "system", - lastUpdatedAt: new Date(), - lastUpdateFullName: user ? user.name : "system", - lastUpdateUserId: user ? user.sub : "system", - }; + // 5. Batch save profiles (chunk 200) + console.time("[AMQ] batch_save_profiles"); + if (profilesToSave.length > 0) { + const chunks = chunkArray(profilesToSave, 200); + for (const chunk of chunks) { + await repoProfile.save(chunk); + } + } + console.timeEnd("[AMQ] batch_save_profiles"); - await posMasterActRepository.save(newAct); - } - console.timeEnd("[AMQ] clone_oldposMasterAct"); + // 6. Batch update posMasters + console.time("[AMQ] batch_update_posMasters"); + for (const update of posMasterUpdates) { + await repoPosmaster.update(update.id, { + current_holderId: update.current_holderId, + next_holderId: null, + lastUpdateUserId, + lastUpdateFullName, + lastUpdatedAt, + }); + } + console.timeEnd("[AMQ] batch_update_posMasters"); + + // 7. Batch create history + console.time("[AMQ] batch_create_history"); + for (const id of historyCreateIds) { + await CreatePosMasterHistoryOfficer(id, null, undefined, undefined, manager); + } + console.timeEnd("[AMQ] batch_create_history"); + + // Clone oldposMasterAct + console.time("[AMQ] clone_oldposMasterAct"); + for (const act of oldposMasterAct) { + const parentDNA = act.posMaster?.ancestorDNA?.trim()?.toLowerCase() ?? ""; + const childDNA = act.posMasterChild?.ancestorDNA?.trim()?.toLowerCase() ?? ""; + + const newParentId = posMasterIdMap.get(parentDNA); + const newChildId = posMasterIdMap.get(childDNA); + + if (!newParentId || !newChildId) continue; + + const { id, posMaster, posMasterChild, ...fields } = act; + + const newAct = { + ...fields, + posMasterId: newParentId, + posMasterChildId: newChildId, + createdAt: new Date(), + createdFullName: user ? user.name : "system", + createdUserId: user ? user.sub : "system", + lastUpdatedAt: new Date(), + lastUpdateFullName: user ? user.name : "system", + lastUpdateUserId: user ? user.sub : "system", + }; + + await posMasterActRepository.save(newAct); + } + console.timeEnd("[AMQ] clone_oldposMasterAct"); - if (orgRevisionPublish != null && orgRevisionDraft != null) { console.time("[AMQ] clone_org_structure"); //new main revision const before = null; @@ -1001,20 +1062,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { console.log(`[AMQ] orgemployeePosMaster count: ${orgemployeePosMaster.length}`); let _orgemployeePosMaster: EmployeePosMaster[]; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // _orgemployeePosMaster = orgemployeePosMaster.map((x) => ({ - // ...x, - // ancestorDNA: - // x.ancestorDNA == null || x.ancestorDNA == "00000000-0000-0000-0000-000000000000" - // ? x.id - // : x.ancestorDNA, - // })); - // await repoEmployeePosmaster.save(_orgemployeePosMaster); const validProfileIds = new Set( (await repoProfileEmployee.find({ select: ["id"] })).map((p) => p.id), ); @@ -1042,7 +1089,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { .execute(); console.timeEnd("[AMQ] insert_employeePosMaster"); - // } //หา dna posmaster ถ้าไม่มีให้เอาตัวเองเป็น dna console.time("[AMQ] query_employeeTempPosMaster"); const orgemployeeTempPosMaster = await repoEmployeeTempPosmaster.find({ @@ -1053,12 +1099,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { console.log(`[AMQ] orgemployeeTempPosMaster count: ${orgemployeeTempPosMaster.length}`); let _orgemployeeTempPosMaster: EmployeeTempPosMaster[]; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { _orgemployeeTempPosMaster = orgemployeeTempPosMaster.map((x) => ({ ...x, ancestorDNA: @@ -1066,7 +1106,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { ? x.id : x.ancestorDNA, })); - // await repoEmployeeTempPosmaster.save(_orgemployeeTempPosMaster); await repoEmployeeTempPosmaster .createQueryBuilder() .insert() @@ -1077,7 +1116,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { overwrite: ["ancestorDNA"], }) .execute(); - // } //create org console.time("[AMQ] forEach_orgRoot"); @@ -1086,13 +1124,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { const dataId = x.id; const matchedOrgRoot = findMatchedNodeByAncestorDNA(orgRootCurrent, x); - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - //create employeePosmaster const filteredEmployeePosMaster = _orgemployeePosMaster.filter( (x: EmployeePosMaster) => x.orgRootId == dataId && x.orgChild1Id == null, ); @@ -1102,24 +1133,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { delete item.id; const employeePosMaster = Object.assign(new EmployeePosMaster(), item); employeePosMaster.positions = []; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeePosMaster.current_holderId = item.current_holderId; - // } else { - // // employeePosMaster.next_holderId = null; - // employeePosMaster.isSit = false; - // } - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeePosMaster.authRoleId = item.authRoleId; - // } else { - // employeePosMaster.authRoleId = null; - // } - // employeePosMaster.current_holderId = null; employeePosMaster.orgRevisionId = orgRevisionDraft.id; employeePosMaster.orgRootId = matchedOrgRoot?.id ?? null; employeePosMaster.createdUserId = ""; @@ -1130,7 +1143,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { employeePosMaster.lastUpdatedAt = new Date(); await repoEmployeePosmaster.save(employeePosMaster); - //create employeePosition await Promise.all( item.positions.map(async (pos: any) => { delete pos.id; @@ -1139,12 +1151,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { pos, ); employeePosition.posMasterId = employeePosMaster.id; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" - // ) { - // employeePosition.positionIsSelected = false; - // } employeePosition.createdUserId = ""; employeePosition.createdFullName = "System Administrator"; employeePosition.createdAt = new Date(); @@ -1156,7 +1162,7 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { ); }), ); - //create employeeTempPosmaster + await Promise.all( _orgemployeeTempPosMaster .filter((x: EmployeeTempPosMaster) => x.orgRootId == dataId && x.orgChild1Id == null) @@ -1164,24 +1170,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { delete item.id; const employeeTempPosMaster = Object.assign(new EmployeeTempPosMaster(), item); employeeTempPosMaster.positions = []; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeeTempPosMaster.current_holderId = item.current_holderId; - // } else { - // // employeeTempPosMaster.next_holderId = null; - // employeeTempPosMaster.isSit = false; - // } - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeeTempPosMaster.authRoleId = item.authRoleId; - // } else { - // employeeTempPosMaster.authRoleId = null; - // } - // employeeTempPosMaster.current_holderId = null; employeeTempPosMaster.orgRevisionId = orgRevisionDraft.id; employeeTempPosMaster.orgRootId = matchedOrgRoot?.id ?? null; employeeTempPosMaster.createdUserId = ""; @@ -1192,7 +1180,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { employeeTempPosMaster.lastUpdatedAt = new Date(); await repoEmployeeTempPosmaster.save(employeeTempPosMaster); - //create employeePosition await Promise.all( item.positions.map(async (pos: any) => { delete pos.id; @@ -1201,12 +1188,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { pos, ); employeePosition.posMasterTempId = employeeTempPosMaster.id; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" - // ) { - // employeePosition.positionIsSelected = false; - // } employeePosition.createdUserId = ""; employeePosition.createdFullName = "System Administrator"; employeePosition.createdAt = new Date(); @@ -1218,46 +1199,17 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { ); }), ); - // } - //create org for (const x of orgChild1.filter((item: OrgChild1) => item.orgRootId == dataId)) { const data1Id = x.id; const matchedOrgChild1 = findMatchedNodeByAncestorDNA(orgChild1Current, x); - // ("[in case Child1] ancestorDNA", `${x.orgChild1Id == matchedOrgChild1?.id}`); - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - //create employeePosmaster await Promise.all( _orgemployeePosMaster .filter((x: EmployeePosMaster) => x.orgChild1Id == data1Id && x.orgChild2Id == null) .map(async (item: any) => { delete item.id; - // console.log("[in case Child1] orgChild1Id == data1Id"); const employeePosMaster = Object.assign(new EmployeePosMaster(), item); employeePosMaster.positions = []; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeePosMaster.current_holderId = item.current_holderId; - // } else { - // // employeePosMaster.next_holderId = null; - // employeePosMaster.isSit = false; - // } - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeePosMaster.authRoleId = item.authRoleId; - // } else { - // employeePosMaster.authRoleId = null; - // } - // employeePosMaster.current_holderId = null; employeePosMaster.orgRevisionId = orgRevisionDraft.id; employeePosMaster.orgRootId = matchedOrgRoot?.id ?? null; employeePosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; @@ -1269,7 +1221,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { employeePosMaster.lastUpdatedAt = new Date(); await repoEmployeePosmaster.save(employeePosMaster); - //create employeePosition await Promise.all( item.positions.map(async (pos: any) => { delete pos.id; @@ -1278,12 +1229,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { pos, ); employeePosition.posMasterId = employeePosMaster.id; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" - // ) { - // employeePosition.positionIsSelected = false; - // } employeePosition.createdUserId = ""; employeePosition.createdFullName = "System Administrator"; employeePosition.createdAt = new Date(); @@ -1295,7 +1240,7 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { ); }), ); - // create employeeTempPosmaster + await Promise.all( _orgemployeeTempPosMaster .filter( @@ -1305,24 +1250,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { delete item.id; const employeeTempPosMaster = Object.assign(new EmployeeTempPosMaster(), item); employeeTempPosMaster.positions = []; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeeTempPosMaster.current_holderId = item.current_holderId; - // } else { - // // employeeTempPosMaster.next_holderId = null; - // employeeTempPosMaster.isSit = false; - // } - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeeTempPosMaster.authRoleId = item.authRoleId; - // } else { - // employeeTempPosMaster.authRoleId = null; - // } - // employeeTempPosMaster.current_holderId = null; employeeTempPosMaster.orgRevisionId = orgRevisionDraft.id; employeeTempPosMaster.orgRootId = matchedOrgRoot?.id ?? null; employeeTempPosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; @@ -1334,7 +1261,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { employeeTempPosMaster.lastUpdatedAt = new Date(); await repoEmployeeTempPosmaster.save(employeeTempPosMaster); - //create employeePosition await Promise.all( item.positions.map(async (pos: any) => { delete pos.id; @@ -1343,12 +1269,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { pos, ); employeePosition.posMasterTempId = employeeTempPosMaster.id; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" - // ) { - // employeePosition.positionIsSelected = false; - // } employeePosition.createdUserId = ""; employeePosition.createdFullName = "System Administrator"; employeePosition.createdAt = new Date(); @@ -1360,46 +1280,17 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { ); }), ); - // } - //create org for (const x of orgChild2.filter((item: OrgChild2) => item.orgChild1Id == data1Id)) { const data2Id = x.id; const matchedOrgChild2 = findMatchedNodeByAncestorDNA(orgChild2Current, x); - // console.log("[in case Child2] ancestorDNA", `${x.orgChild2Id == matchedOrgChild2?.id}`); - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - //create employeePosmaster await Promise.all( _orgemployeePosMaster .filter((x: EmployeePosMaster) => x.orgChild2Id == data2Id && x.orgChild3Id == null) .map(async (item: any) => { delete item.id; - // console.log("[in case Child2] orgChild2Id == data2Id"); const employeePosMaster = Object.assign(new EmployeePosMaster(), item); employeePosMaster.positions = []; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeePosMaster.current_holderId = item.current_holderId; - // } else { - // // employeePosMaster.next_holderId = null; - // employeePosMaster.isSit = false; - // } - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeePosMaster.authRoleId = item.authRoleId; - // } else { - // employeePosMaster.authRoleId = null; - // } - // employeePosMaster.current_holderId = null; employeePosMaster.orgRevisionId = orgRevisionDraft.id; employeePosMaster.orgRootId = matchedOrgRoot?.id ?? null; employeePosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; @@ -1412,7 +1303,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { employeePosMaster.lastUpdatedAt = new Date(); await repoEmployeePosmaster.save(employeePosMaster); - //create employeePosition await Promise.all( item.positions.map(async (pos: any) => { delete pos.id; @@ -1421,12 +1311,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { pos, ); employeePosition.posMasterId = employeePosMaster.id; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" - // ) { - // employeePosition.positionIsSelected = false; - // } employeePosition.createdUserId = ""; employeePosition.createdFullName = "System Administrator"; employeePosition.createdAt = new Date(); @@ -1438,7 +1322,7 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { ); }), ); - // create employeeTempPosmaster + await Promise.all( _orgemployeeTempPosMaster .filter( @@ -1448,24 +1332,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { delete item.id; const employeeTempPosMaster = Object.assign(new EmployeeTempPosMaster(), item); employeeTempPosMaster.positions = []; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeeTempPosMaster.current_holderId = item.current_holderId; - // } else { - // // employeeTempPosMaster.next_holderId = null; - // employeeTempPosMaster.isSit = false; - // } - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeeTempPosMaster.authRoleId = item.authRoleId; - // } else { - // employeeTempPosMaster.authRoleId = null; - // } - // employeeTempPosMaster.current_holderId = null; employeeTempPosMaster.orgRevisionId = orgRevisionDraft.id; employeeTempPosMaster.orgRootId = dataId; employeeTempPosMaster.orgChild1Id = data1Id; @@ -1478,7 +1344,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { employeeTempPosMaster.lastUpdatedAt = new Date(); await repoEmployeeTempPosmaster.save(employeeTempPosMaster); - //create employeePosition await Promise.all( item.positions.map(async (pos: any) => { delete pos.id; @@ -1487,12 +1352,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { pos, ); employeePosition.posMasterTempId = employeeTempPosMaster.id; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" - // ) { - // employeePosition.positionIsSelected = false; - // } employeePosition.createdUserId = ""; employeePosition.createdFullName = "System Administrator"; employeePosition.createdAt = new Date(); @@ -1504,20 +1363,10 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { ); }), ); - // } - //create org for (const x of orgChild3.filter((item: OrgChild3) => item.orgChild2Id == data2Id)) { const data3Id = x.id; const matchedOrgChild3 = findMatchedNodeByAncestorDNA(orgChild3Current, x); - // console.log("[in case Child3] ancestorDNA", `${x.orgChild3Id == matchedOrgChild3?.id}`); - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - //create employeePosmaster await Promise.all( _orgemployeePosMaster .filter( @@ -1525,27 +1374,8 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { ) .map(async (item: any) => { delete item.id; - // console.log("[in case Child3] orgChild3Id == data3Id"); const employeePosMaster = Object.assign(new EmployeePosMaster(), item); employeePosMaster.positions = []; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeePosMaster.current_holderId = item.current_holderId; - // } else { - // // employeePosMaster.next_holderId = null; - // employeePosMaster.isSit = false; - // } - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeePosMaster.authRoleId = item.authRoleId; - // } else { - // employeePosMaster.authRoleId = null; - // } - // employeePosMaster.current_holderId = null; employeePosMaster.orgRevisionId = orgRevisionDraft.id; employeePosMaster.orgRootId = matchedOrgRoot?.id ?? null; employeePosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; @@ -1559,7 +1389,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { employeePosMaster.lastUpdatedAt = new Date(); await repoEmployeePosmaster.save(employeePosMaster); - //create employeePosition await Promise.all( item.positions.map(async (pos: any) => { delete pos.id; @@ -1568,12 +1397,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { pos, ); employeePosition.posMasterId = employeePosMaster.id; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" - // ) { - // employeePosition.positionIsSelected = false; - // } employeePosition.createdUserId = ""; employeePosition.createdFullName = "System Administrator"; employeePosition.createdAt = new Date(); @@ -1585,7 +1408,7 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { ); }), ); - // create employeeTempPosmaster + await Promise.all( _orgemployeeTempPosMaster .filter( @@ -1595,24 +1418,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { delete item.id; const employeeTempPosMaster = Object.assign(new EmployeeTempPosMaster(), item); employeeTempPosMaster.positions = []; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeeTempPosMaster.current_holderId = item.current_holderId; - // } else { - // // employeeTempPosMaster.next_holderId = null; - // employeeTempPosMaster.isSit = false; - // } - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeeTempPosMaster.authRoleId = item.authRoleId; - // } else { - // employeeTempPosMaster.authRoleId = null; - // } - // employeeTempPosMaster.current_holderId = null; employeeTempPosMaster.orgRevisionId = orgRevisionDraft.id; employeeTempPosMaster.orgRootId = matchedOrgRoot?.id ?? null; employeeTempPosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; @@ -1626,7 +1431,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { employeeTempPosMaster.lastUpdatedAt = new Date(); await repoEmployeeTempPosmaster.save(employeeTempPosMaster); - //create employeePosition await Promise.all( item.positions.map(async (pos: any) => { delete pos.id; @@ -1635,12 +1439,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { pos, ); employeePosition.posMasterTempId = employeeTempPosMaster.id; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" - // ) { - // employeePosition.positionIsSelected = false; - // } employeePosition.createdUserId = ""; employeePosition.createdFullName = "System Administrator"; employeePosition.createdAt = new Date(); @@ -1652,46 +1450,17 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { ); }), ); - // } - //create org for (const x of orgChild4.filter((item: OrgChild4) => item.orgChild3Id == data3Id)) { const data4Id = x.id; const matchedOrgChild4 = findMatchedNodeByAncestorDNA(orgChild4Current, x); - // console.log("[in case Child4] ancestorDNA", `${x.orgChild4Id == matchedOrgChild4?.id}`); - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - //create employeePosmaster await Promise.all( _orgemployeePosMaster .filter((x: EmployeePosMaster) => x.orgChild4Id == data4Id) .map(async (item: any) => { delete item.id; - // console.log("[in case Child4] orgChild4Id == data4Id"); const employeePosMaster = Object.assign(new EmployeePosMaster(), item); employeePosMaster.positions = []; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeePosMaster.current_holderId = item.current_holderId; - // } else { - // // employeePosMaster.next_holderId = null; - // employeePosMaster.isSit = false; - // } - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeePosMaster.authRoleId = item.authRoleId; - // } else { - // employeePosMaster.authRoleId = null; - // } - // employeePosMaster.current_holderId = null; employeePosMaster.orgRevisionId = orgRevisionDraft.id; employeePosMaster.orgRootId = matchedOrgRoot?.id ?? null; employeePosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; @@ -1706,7 +1475,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { employeePosMaster.lastUpdatedAt = new Date(); await repoEmployeePosmaster.save(employeePosMaster); - //create employeePosition await Promise.all( item.positions.map(async (pos: any) => { delete pos.id; @@ -1715,12 +1483,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { pos, ); employeePosition.posMasterId = employeePosMaster.id; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" - // ) { - // employeePosition.positionIsSelected = false; - // } employeePosition.createdUserId = ""; employeePosition.createdFullName = "System Administrator"; employeePosition.createdAt = new Date(); @@ -1732,7 +1494,7 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { ); }), ); - //create employeeTempPosmaster + await Promise.all( _orgemployeeTempPosMaster .filter((x: EmployeeTempPosMaster) => x.orgChild4Id == data4Id) @@ -1743,24 +1505,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { item, ); employeeTempPosMaster.positions = []; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeeTempPosMaster.current_holderId = item.current_holderId; - // } else { - // // employeeTempPosMaster.next_holderId = null; - // employeeTempPosMaster.isSit = false; - // } - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE" - // ) { - // employeeTempPosMaster.authRoleId = item.authRoleId; - // } else { - // employeeTempPosMaster.authRoleId = null; - // } - // employeeTempPosMaster.current_holderId = null; employeeTempPosMaster.orgRevisionId = orgRevisionDraft.id; employeeTempPosMaster.orgRootId = matchedOrgRoot?.id ?? null; employeeTempPosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; @@ -1775,7 +1519,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { employeeTempPosMaster.lastUpdatedAt = new Date(); await repoEmployeeTempPosmaster.save(employeeTempPosMaster); - //create employeePosition await Promise.all( item.positions.map(async (pos: any) => { delete pos.id; @@ -1784,12 +1527,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { pos, ); employeePosition.posMasterTempId = employeeTempPosMaster.id; - // if ( - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION" || - // requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" - // ) { - // employeePosition.positionIsSelected = false; - // } employeePosition.createdUserId = ""; employeePosition.createdFullName = "System Administrator"; employeePosition.createdAt = new Date(); @@ -1801,13 +1538,11 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { ); }), ); - // } } } } } } - // } const employeePosMaster = await repoEmployeePosmaster.find({ where: { orgRevisionId: orgRevisionDraft.id }, @@ -1827,8 +1562,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { await repoProfileEmployee.save(profile); } } - // item.current_holderId = item.next_holderId; - // item.next_holderId = null; item.lastUpdateUserId = lastUpdateUserId; item.lastUpdateFullName = lastUpdateFullName; item.lastUpdatedAt = lastUpdatedAt; @@ -1852,14 +1585,32 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { await repoProfileEmployee.save(profile); } } - // item.current_holderId = item.next_holderId; - // item.next_holderId = null; item.lastUpdateUserId = lastUpdateUserId; item.lastUpdateFullName = lastUpdateFullName; item.lastUpdatedAt = lastUpdatedAt; await repoEmployeeTempPosmaster.save(item); } + console.timeEnd("[AMQ] clone_org_structure"); + + console.time("[AMQ] save_revision_status"); + orgRevisionPublish.orgRevisionIsDraft = false; + orgRevisionPublish.orgRevisionIsCurrent = false; + await repoOrgRevision.save(orgRevisionPublish); + + orgRevisionDraft.orgRevisionIsCurrent = true; + orgRevisionDraft.orgRevisionIsDraft = false; + await repoOrgRevision.save(orgRevisionDraft); + console.timeEnd("[AMQ] save_revision_status"); + }); + + if (shouldSkipPublishInTransaction) { + console.log( + `[AMQ] Skip publish in transaction: revision ${id} state changed before write phase`, + ); + console.timeEnd("[AMQ] handler_org_total"); + return true; } + console.log("[AMQ] Excecute Organization Success"); if (user) { sendWebSocket( @@ -1871,18 +1622,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { { userId: user?.sub }, ).catch(console.error); } - console.timeEnd("[AMQ] clone_org_structure"); - - // อัปเดตสถานะ orgRevision หลังจากทำงานเสร็จทั้งหมด - console.time("[AMQ] save_revision_status"); - orgRevisionPublish.orgRevisionIsDraft = false; - orgRevisionPublish.orgRevisionIsCurrent = false; - await repoOrgRevision.save(orgRevisionPublish); - - orgRevisionDraft.orgRevisionIsCurrent = true; - orgRevisionDraft.orgRevisionIsDraft = false; - await repoOrgRevision.save(orgRevisionDraft); - console.timeEnd("[AMQ] save_revision_status"); console.log(`[AMQ] handler_org SUCCESS - Total time: ${Date.now() - startTime}ms`); console.timeEnd("[AMQ] handler_org_total"); From b5c75379ffd44ffe6ce6002e5a9a1337bb3600ce Mon Sep 17 00:00:00 2001 From: waruneeauy Date: Tue, 5 May 2026 15:59:39 +0700 Subject: [PATCH 3/6] fixed error and not retry --- src/services/rabbitmq.ts | 361 +++++++++++++++++++++++++++++---------- 1 file changed, 273 insertions(+), 88 deletions(-) diff --git a/src/services/rabbitmq.ts b/src/services/rabbitmq.ts index 42c386e0..097473f8 100644 --- a/src/services/rabbitmq.ts +++ b/src/services/rabbitmq.ts @@ -24,9 +24,27 @@ import { In, Not } from "typeorm"; import { PosMasterAct } from "../entities/PosMasterAct"; import { PermissionOrg } from "../entities/PermissionOrg"; import { sendWebSocket } from "./webSocket"; -import { CreatePosMasterHistoryOfficer } from "./PositionService"; import { PayloadSendNoti } from "../interfaces/utils"; import { PermissionProfile } from "../entities/PermissionProfile"; +import { PosMasterHistory } from "../entities/PosMasterHistory"; + +let reconnectTimer: ReturnType | null = null; + +function scheduleReconnect() { + if (reconnectTimer) { + return; + } + + reconnectTimer = setTimeout(async () => { + reconnectTimer = null; + try { + await init(); + } catch (error) { + console.error("[AMQ] Reconnect failed:", error); + scheduleReconnect(); + } + }, 1000); +} export let sendToQueue: (payload: any) => void; export let sendToQueueOrg: (payload: any) => void; @@ -55,10 +73,28 @@ export async function init() { console.log(connection ? "[AMQ] Connection success" : "[AMQ] Connection failed"); + connection.on("error", (error) => { + console.error("[AMQ] Connection error:", error); + }); + + connection.on("close", () => { + console.error("[AMQ] Connection closed. Scheduling reconnect..."); + scheduleReconnect(); + }); + const channel = await connection.createChannel(); //----> (1.4) create Channel console.log(channel ? "[AMQ] Create channel success" : "[AMQ] Create channel failed"); + channel.on("error", (error) => { + console.error("[AMQ] Channel error:", error); + }); + + channel.on("close", () => { + console.error("[AMQ] Channel closed. Scheduling reconnect..."); + scheduleReconnect(); + }); + channel.assertQueue(queue, { durable: true }), //----> (1.5) assert queue and set durable (if "true" save to disk on RabbitMQ) channel.assertQueue(queue_org, { durable: true }), channel.assertQueue(queue_org_draft, { durable: true }), @@ -97,18 +133,26 @@ function createConsumer( //----> consumer channel: amqp.Channel, handler: (msg: amqp.ConsumeMessage) => Promise | boolean, ) { - let retries = 0; channel.consume( queue, async (msg) => { if (!msg) return; - if ((await handler(msg)) || retries++ >= 3) { - retries = 0; - console.log("[AMQ] Process Consumer success"); + try { + if (await handler(msg)) { + console.log("[AMQ] Process Consumer success"); + return channel.ack(msg); + } + console.error(`[AMQ] Process Consumer failed on queue ${queue}, acknowledging without retry`); return channel.ack(msg); + } catch (error) { + console.error(`[AMQ] Consumer processing error on queue ${queue}:`, error); + try { + console.error(`[AMQ] Acknowledging failed message on queue ${queue} without retry`); + channel.ack(msg); + } catch (channelError) { + console.error(`[AMQ] Failed to ack/nack message on queue ${queue}:`, channelError); + } } - console.log("[AMQ] Process Consumer failed"); - return await new Promise((resolve) => setTimeout(() => resolve(channel.nack(msg)), 3000)); }, { noAck: false }, ); @@ -740,7 +784,7 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { // 3. เตรียม arrays สำหรับ batch operations const profilesToSave: Profile[] = []; const posMasterAssignsToSave: PosMasterAssign[] = []; - const historyCreateIds: string[] = []; + const historyRowsToSave: Partial[] = []; const posMasterUpdates: { id: string; current_holderId: string | null | undefined }[] = []; // ===== LOOP: เก็บข้อมูลทั้งหมด ===== @@ -809,12 +853,54 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { const isHolderChanged = oldHolderId !== newHolderId; if (isHolderChanged) { - historyCreateIds.push(item.id); + const nextHolderProfile = + item.next_holderId != null && item.next_holderId !== "" + ? profilesMap.get(item.next_holderId) + : null; + const selectedPosition = + item.positions.length > 0 + ? item.positions.find((position) => position.positionIsSelected === true) ?? null + : null; + const shortName = + [ + item.orgChild4?.orgChild4ShortName, + item.orgChild3?.orgChild3ShortName, + item.orgChild2?.orgChild2ShortName, + item.orgChild1?.orgChild1ShortName, + item.orgRoot?.orgRootShortName, + ].find((name) => typeof name === "string" && name.trim().length > 0) ?? _null; + + historyRowsToSave.push({ + ancestorDNA: item.ancestorDNA ? item.ancestorDNA : _null, + prefix: nextHolderProfile?.prefix || _null, + firstName: nextHolderProfile?.firstName || _null, + lastName: nextHolderProfile?.lastName || _null, + shortName, + posMasterNoPrefix: item.posMasterNoPrefix ?? _null, + posMasterNo: item.posMasterNo ?? _null, + posMasterNoSuffix: item.posMasterNoSuffix ?? _null, + position: selectedPosition?.positionName ?? _null, + posType: selectedPosition?.posType?.posTypeName ?? _null, + posLevel: selectedPosition?.posLevel?.posLevelName ?? _null, + posExecutive: selectedPosition?.posExecutive?.posExecutiveName ?? _null, + profileId: _null, + rootDnaId: item.orgRoot?.ancestorDNA || _null, + child1DnaId: item.orgChild1?.ancestorDNA || _null, + child2DnaId: item.orgChild2?.ancestorDNA || _null, + child3DnaId: item.orgChild3?.ancestorDNA || _null, + child4DnaId: item.orgChild4?.ancestorDNA || _null, + createdUserId: "", + createdFullName: "system", + lastUpdateUserId: "", + lastUpdateFullName: "system", + createdAt: new Date(), + lastUpdatedAt: new Date(), + }); } } console.timeEnd("[AMQ] prepare_batch_data"); console.log( - `[AMQ] Prepared - posMasterAssignsToSave: ${posMasterAssignsToSave.length}, profilesToSave: ${profilesToSave.length}, posMasterUpdates: ${posMasterUpdates.length}, historyCreateIds: ${historyCreateIds.length}`, + `[AMQ] Prepared - posMasterAssignsToSave: ${posMasterAssignsToSave.length}, profilesToSave: ${profilesToSave.length}, posMasterUpdates: ${posMasterUpdates.length}, historyCreateIds: ${historyRowsToSave.length}`, ); // ===== BATCH EXECUTION: save ทีละ batch ===== @@ -835,6 +921,7 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { const child2Repository = manager.getRepository(OrgChild2); const child3Repository = manager.getRepository(OrgChild3); const child4Repository = manager.getRepository(OrgChild4); + const posMasterHistoryRepository = manager.getRepository(PosMasterHistory); const targetOrgRevision = await repoOrgRevision .createQueryBuilder("orgRevision") @@ -903,21 +990,45 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { // 6. Batch update posMasters console.time("[AMQ] batch_update_posMasters"); - for (const update of posMasterUpdates) { - await repoPosmaster.update(update.id, { - current_holderId: update.current_holderId, - next_holderId: null, - lastUpdateUserId, - lastUpdateFullName, - lastUpdatedAt, - }); + if (posMasterUpdates.length > 0) { + const chunks = chunkArray(posMasterUpdates, 500); + const posMasterTableName = repoPosmaster.metadata.tableName; + for (const chunk of chunks as typeof posMasterUpdates[]) { + const caseClauses = chunk.map(() => "WHEN ? THEN ?").join(" "); + const wherePlaceholders = chunk.map(() => "?").join(", "); + const params = chunk.flatMap((update: (typeof posMasterUpdates)[number]) => [ + update.id, + update.current_holderId ?? null, + ]); + + params.push( + lastUpdateUserId, + lastUpdateFullName, + lastUpdatedAt, + ...chunk.map((update: (typeof posMasterUpdates)[number]) => update.id), + ); + + await manager.query( + `UPDATE \`${posMasterTableName}\` + SET current_holderId = CASE id ${caseClauses} END, + next_holderId = NULL, + lastUpdateUserId = ?, + lastUpdateFullName = ?, + lastUpdatedAt = ? + WHERE id IN (${wherePlaceholders})`, + params, + ); + } } console.timeEnd("[AMQ] batch_update_posMasters"); // 7. Batch create history console.time("[AMQ] batch_create_history"); - for (const id of historyCreateIds) { - await CreatePosMasterHistoryOfficer(id, null, undefined, undefined, manager); + if (historyRowsToSave.length > 0) { + const chunks = chunkArray(historyRowsToSave, 500); + for (const chunk of chunks) { + await posMasterHistoryRepository.save(posMasterHistoryRepository.create(chunk)); + } } console.timeEnd("[AMQ] batch_create_history"); @@ -958,25 +1069,23 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { //cone tree console.time("[AMQ] query_old_org_structure"); //หา dna tree - const orgRoot = await orgRootRepository.find({ - where: { orgRevisionId: orgRevisionPublish.id }, - }); - - const orgChild1 = await child1Repository.find({ - where: { orgRevisionId: orgRevisionPublish.id }, - }); - - const orgChild2 = await child2Repository.find({ - where: { orgRevisionId: orgRevisionPublish.id }, - }); - - const orgChild3 = await child3Repository.find({ - where: { orgRevisionId: orgRevisionPublish.id }, - }); - - const orgChild4 = await child4Repository.find({ - where: { orgRevisionId: orgRevisionPublish.id }, - }); + const [orgRoot, orgChild1, orgChild2, orgChild3, orgChild4] = await Promise.all([ + orgRootRepository.find({ + where: { orgRevisionId: orgRevisionPublish.id }, + }), + child1Repository.find({ + where: { orgRevisionId: orgRevisionPublish.id }, + }), + child2Repository.find({ + where: { orgRevisionId: orgRevisionPublish.id }, + }), + child3Repository.find({ + where: { orgRevisionId: orgRevisionPublish.id }, + }), + child4Repository.find({ + where: { orgRevisionId: orgRevisionPublish.id }, + }), + ]); console.timeEnd("[AMQ] query_old_org_structure"); console.log( `[AMQ] Old structure - orgRoot: ${orgRoot.length}, orgChild1: ${orgChild1.length}, orgChild2: ${orgChild2.length}, orgChild3: ${orgChild3.length}, orgChild4: ${orgChild4.length}`, @@ -1106,6 +1215,78 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { ? x.id : x.ancestorDNA, })); + + const groupByParentId = ( + items: T[], + getParentId: (item: T) => string | null | undefined, + ) => { + const grouped = new Map(); + for (const item of items) { + const parentId = getParentId(item); + if (!parentId) { + continue; + } + const current = grouped.get(parentId); + if (current) { + current.push(item); + } else { + grouped.set(parentId, [item]); + } + } + return grouped; + }; + + const buildEmployeeNodeKey = (item: { + orgRootId?: string | null; + orgChild1Id?: string | null; + orgChild2Id?: string | null; + orgChild3Id?: string | null; + orgChild4Id?: string | null; + }) => { + if (item.orgChild4Id) return `child4:${item.orgChild4Id}`; + if (item.orgChild3Id && item.orgChild4Id == null) return `child3:${item.orgChild3Id}`; + if (item.orgChild2Id && item.orgChild3Id == null) return `child2:${item.orgChild2Id}`; + if (item.orgChild1Id && item.orgChild2Id == null) return `child1:${item.orgChild1Id}`; + if (item.orgRootId && item.orgChild1Id == null) return `root:${item.orgRootId}`; + return null; + }; + + const groupByEmployeeNode = < + T extends { + orgRootId?: string | null; + orgChild1Id?: string | null; + orgChild2Id?: string | null; + orgChild3Id?: string | null; + orgChild4Id?: string | null; + }, + >( + items: T[], + ) => { + const grouped = new Map(); + for (const item of items) { + const key = buildEmployeeNodeKey(item); + if (!key) { + continue; + } + const current = grouped.get(key); + if (current) { + current.push(item); + } else { + grouped.set(key, [item]); + } + } + return grouped; + }; + + const employeePosMasterByNode = groupByEmployeeNode(_orgemployeePosMaster); + const employeeTempPosMasterByNode = groupByEmployeeNode(_orgemployeeTempPosMaster); + const getNodeKey = (level: "root" | "child1" | "child2" | "child3" | "child4", id: string) => + `${level}:${id}`; + const orgChild1ByRoot = groupByParentId(orgChild1, (item) => item.orgRootId); + const orgChild2ByChild1 = groupByParentId(orgChild2, (item) => item.orgChild1Id); + const orgChild3ByChild2 = groupByParentId(orgChild3, (item) => item.orgChild2Id); + const orgChild4ByChild3 = groupByParentId(orgChild4, (item) => item.orgChild3Id); + await repoEmployeeTempPosmaster .createQueryBuilder() .insert() @@ -1124,9 +1305,7 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { const dataId = x.id; const matchedOrgRoot = findMatchedNodeByAncestorDNA(orgRootCurrent, x); - const filteredEmployeePosMaster = _orgemployeePosMaster.filter( - (x: EmployeePosMaster) => x.orgRootId == dataId && x.orgChild1Id == null, - ); + const filteredEmployeePosMaster = employeePosMasterByNode.get(getNodeKey("root", dataId)) ?? []; await Promise.all( filteredEmployeePosMaster.map(async (item: any) => { @@ -1164,8 +1343,7 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { ); await Promise.all( - _orgemployeeTempPosMaster - .filter((x: EmployeeTempPosMaster) => x.orgRootId == dataId && x.orgChild1Id == null) + (employeeTempPosMasterByNode.get(getNodeKey("root", dataId)) ?? []) .map(async (item: any) => { delete item.id; const employeeTempPosMaster = Object.assign(new EmployeeTempPosMaster(), item); @@ -1200,12 +1378,11 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { }), ); - for (const x of orgChild1.filter((item: OrgChild1) => item.orgRootId == dataId)) { + for (const x of orgChild1ByRoot.get(dataId) ?? []) { const data1Id = x.id; const matchedOrgChild1 = findMatchedNodeByAncestorDNA(orgChild1Current, x); await Promise.all( - _orgemployeePosMaster - .filter((x: EmployeePosMaster) => x.orgChild1Id == data1Id && x.orgChild2Id == null) + (employeePosMasterByNode.get(getNodeKey("child1", data1Id)) ?? []) .map(async (item: any) => { delete item.id; const employeePosMaster = Object.assign(new EmployeePosMaster(), item); @@ -1242,10 +1419,7 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { ); await Promise.all( - _orgemployeeTempPosMaster - .filter( - (x: EmployeeTempPosMaster) => x.orgChild1Id == data1Id && x.orgChild2Id == null, - ) + (employeeTempPosMasterByNode.get(getNodeKey("child1", data1Id)) ?? []) .map(async (item: any) => { delete item.id; const employeeTempPosMaster = Object.assign(new EmployeeTempPosMaster(), item); @@ -1281,12 +1455,11 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { }), ); - for (const x of orgChild2.filter((item: OrgChild2) => item.orgChild1Id == data1Id)) { + for (const x of orgChild2ByChild1.get(data1Id) ?? []) { const data2Id = x.id; const matchedOrgChild2 = findMatchedNodeByAncestorDNA(orgChild2Current, x); await Promise.all( - _orgemployeePosMaster - .filter((x: EmployeePosMaster) => x.orgChild2Id == data2Id && x.orgChild3Id == null) + (employeePosMasterByNode.get(getNodeKey("child2", data2Id)) ?? []) .map(async (item: any) => { delete item.id; const employeePosMaster = Object.assign(new EmployeePosMaster(), item); @@ -1324,10 +1497,7 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { ); await Promise.all( - _orgemployeeTempPosMaster - .filter( - (x: EmployeeTempPosMaster) => x.orgChild2Id == data2Id && x.orgChild3Id == null, - ) + (employeeTempPosMasterByNode.get(getNodeKey("child2", data2Id)) ?? []) .map(async (item: any) => { delete item.id; const employeeTempPosMaster = Object.assign(new EmployeeTempPosMaster(), item); @@ -1364,14 +1534,11 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { }), ); - for (const x of orgChild3.filter((item: OrgChild3) => item.orgChild2Id == data2Id)) { + for (const x of orgChild3ByChild2.get(data2Id) ?? []) { const data3Id = x.id; const matchedOrgChild3 = findMatchedNodeByAncestorDNA(orgChild3Current, x); await Promise.all( - _orgemployeePosMaster - .filter( - (x: EmployeePosMaster) => x.orgChild3Id == data3Id && x.orgChild4Id == null, - ) + (employeePosMasterByNode.get(getNodeKey("child3", data3Id)) ?? []) .map(async (item: any) => { delete item.id; const employeePosMaster = Object.assign(new EmployeePosMaster(), item); @@ -1410,10 +1577,7 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { ); await Promise.all( - _orgemployeeTempPosMaster - .filter( - (x: EmployeeTempPosMaster) => x.orgChild3Id == data3Id && x.orgChild4Id == null, - ) + (employeeTempPosMasterByNode.get(getNodeKey("child3", data3Id)) ?? []) .map(async (item: any) => { delete item.id; const employeeTempPosMaster = Object.assign(new EmployeeTempPosMaster(), item); @@ -1451,12 +1615,11 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { }), ); - for (const x of orgChild4.filter((item: OrgChild4) => item.orgChild3Id == data3Id)) { + for (const x of orgChild4ByChild3.get(data3Id) ?? []) { const data4Id = x.id; const matchedOrgChild4 = findMatchedNodeByAncestorDNA(orgChild4Current, x); await Promise.all( - _orgemployeePosMaster - .filter((x: EmployeePosMaster) => x.orgChild4Id == data4Id) + (employeePosMasterByNode.get(getNodeKey("child4", data4Id)) ?? []) .map(async (item: any) => { delete item.id; const employeePosMaster = Object.assign(new EmployeePosMaster(), item); @@ -1496,8 +1659,7 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { ); await Promise.all( - _orgemployeeTempPosMaster - .filter((x: EmployeeTempPosMaster) => x.orgChild4Id == data4Id) + (employeeTempPosMasterByNode.get(getNodeKey("child4", data4Id)) ?? []) .map(async (item: any) => { delete item.id; const employeeTempPosMaster = Object.assign( @@ -1544,22 +1706,42 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { } } - const employeePosMaster = await repoEmployeePosmaster.find({ - where: { orgRevisionId: orgRevisionDraft.id }, - relations: ["positions", "positions.posLevel", "positions.posType"], - }); + const [employeePosMaster, employeeTempPosMaster] = await Promise.all([ + repoEmployeePosmaster.find({ + where: { orgRevisionId: orgRevisionDraft.id }, + relations: ["positions", "positions.posLevel", "positions.posType"], + }), + repoEmployeeTempPosmaster.find({ + where: { orgRevisionId: orgRevisionDraft.id }, + relations: ["positions", "positions.posLevel", "positions.posType"], + }), + ]); + const profileEmployeeIds = Array.from( + new Set( + [...employeePosMaster, ...employeeTempPosMaster] + .map((item) => item.next_holderId) + .filter((profileId): profileId is string => !!profileId), + ), + ); + const profileEmployeeMap = new Map(); + if (profileEmployeeIds.length > 0) { + const profiles = await repoProfileEmployee.findBy({ + id: In(profileEmployeeIds), + }); + profiles.forEach((profile) => profileEmployeeMap.set(profile.id, profile)); + } + const updatedProfileEmployeeIds = new Set(); + for (const item of employeePosMaster) { if (item.next_holderId != null) { - const profile = await repoProfileEmployee.findOne({ - where: { id: item.next_holderId == null ? "" : item.next_holderId }, - }); + const profile = profileEmployeeMap.get(item.next_holderId); const position = await item.positions.find((x) => x.positionIsSelected == true); const _null: any = null; if (profile != null) { profile.posLevelId = position?.posLevelId ?? _null; profile.posTypeId = position?.posTypeId ?? _null; profile.position = position?.positionName ?? _null; - await repoProfileEmployee.save(profile); + updatedProfileEmployeeIds.add(profile.id); } } item.lastUpdateUserId = lastUpdateUserId; @@ -1567,22 +1749,16 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { item.lastUpdatedAt = lastUpdatedAt; await repoEmployeePosmaster.save(item); } - const employeeTempPosMaster = await repoEmployeeTempPosmaster.find({ - where: { orgRevisionId: orgRevisionDraft.id }, - relations: ["positions", "positions.posLevel", "positions.posType"], - }); for (const item of employeeTempPosMaster) { if (item.next_holderId != null) { - const profile = await repoProfileEmployee.findOne({ - where: { id: item.next_holderId == null ? "" : item.next_holderId }, - }); + const profile = profileEmployeeMap.get(item.next_holderId); const position = await item.positions.find((x) => x.positionIsSelected == true); const _null: any = null; if (profile != null) { profile.posLevelId = position?.posLevelId ?? _null; profile.posTypeId = position?.posTypeId ?? _null; profile.position = position?.positionName ?? _null; - await repoProfileEmployee.save(profile); + updatedProfileEmployeeIds.add(profile.id); } } item.lastUpdateUserId = lastUpdateUserId; @@ -1590,6 +1766,15 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { item.lastUpdatedAt = lastUpdatedAt; await repoEmployeeTempPosmaster.save(item); } + if (updatedProfileEmployeeIds.size > 0) { + const profilesToSave = Array.from(updatedProfileEmployeeIds) + .map((profileId) => profileEmployeeMap.get(profileId)) + .filter((profile): profile is ProfileEmployee => !!profile); + const chunks = chunkArray(profilesToSave, 200); + for (const chunk of chunks) { + await repoProfileEmployee.save(chunk); + } + } console.timeEnd("[AMQ] clone_org_structure"); console.time("[AMQ] save_revision_status"); From e7e4e2075b71d7b65f271605b2b35456ee23c6b1 Mon Sep 17 00:00:00 2001 From: waruneeauy Date: Tue, 5 May 2026 16:25:06 +0700 Subject: [PATCH 4/6] =?UTF-8?q?1.=20=E0=B8=A3=E0=B8=A7=E0=B8=A1=20query=5F?= =?UTF-8?q?employeePosMaster=20=E0=B8=81=E0=B8=B1=E0=B8=9A=20query=5Femplo?= =?UTF-8?q?yeeTempPosMaster=20=E0=B9=83=E0=B8=AB=E0=B9=89=E0=B8=94?= =?UTF-8?q?=E0=B8=B6=E0=B8=87=E0=B9=81=E0=B8=9A=E0=B8=9A=E0=B8=82=E0=B8=99?= =?UTF-8?q?=E0=B8=B2=E0=B8=99=E0=B8=94=E0=B9=89=E0=B8=A7=E0=B8=A2=20Promis?= =?UTF-8?q?e.all=202.=20=E0=B8=95=E0=B8=B1=E0=B8=94=20full-table=20scan=20?= =?UTF-8?q?=E0=B8=82=E0=B8=AD=E0=B8=87=20ProfileEmployee=20=E0=B8=AD?= =?UTF-8?q?=E0=B8=AD=E0=B8=81=20=E0=B9=82=E0=B8=94=E0=B8=A2=E0=B9=80?= =?UTF-8?q?=E0=B8=9B=E0=B8=A5=E0=B8=B5=E0=B9=88=E0=B8=A2=E0=B8=99=E0=B8=88?= =?UTF-8?q?=E0=B8=B2=E0=B8=81=20find({=20select:=20["id"]=20})=20=E0=B8=97?= =?UTF-8?q?=E0=B8=B1=E0=B9=89=E0=B8=87=E0=B8=95=E0=B8=B2=E0=B8=A3=E0=B8=B2?= =?UTF-8?q?=E0=B8=87=20=E0=B8=A1=E0=B8=B2=E0=B9=80=E0=B8=9B=E0=B9=87?= =?UTF-8?q?=E0=B8=99=20query=20=E0=B9=80=E0=B8=89=E0=B8=9E=E0=B8=B2?= =?UTF-8?q?=E0=B8=B0=20current=5FholderId=20=E0=B8=97=E0=B8=B5=E0=B9=88?= =?UTF-8?q?=E0=B8=AD=E0=B9=89=E0=B8=B2=E0=B8=87=E0=B8=96=E0=B8=B6=E0=B8=87?= =?UTF-8?q?=E0=B8=88=E0=B8=A3=E0=B8=B4=E0=B8=87=E0=B9=83=E0=B8=99=E0=B8=8A?= =?UTF-8?q?=E0=B8=B8=E0=B8=94=E0=B8=82=E0=B9=89=E0=B8=AD=E0=B8=A1=E0=B8=B9?= =?UTF-8?q?=E0=B8=A5=20publish=203.=20=E0=B9=80=E0=B8=81=E0=B9=87=E0=B8=9A?= =?UTF-8?q?=20normalization=20=E0=B8=82=E0=B8=AD=E0=B8=87=20=5Forgemployee?= =?UTF-8?q?PosMaster=20=E0=B9=81=E0=B8=A5=E0=B8=B0=20=5ForgemployeeTempPos?= =?UTF-8?q?Master=20=E0=B9=84=E0=B8=A7=E0=B9=89=E0=B8=AB=E0=B8=A5=E0=B8=B1?= =?UTF-8?q?=E0=B8=87=20query=20=E0=B8=8A=E0=B8=B8=E0=B8=94=E0=B9=80?= =?UTF-8?q?=E0=B8=94=E0=B8=B5=E0=B8=A2=E0=B8=A7=E0=B8=81=E0=B8=B1=E0=B8=99?= =?UTF-8?q?=20=E0=B8=97=E0=B8=B3=E0=B9=83=E0=B8=AB=E0=B9=89=20block=20?= =?UTF-8?q?=E0=B8=99=E0=B8=B5=E0=B9=89=E0=B8=81=E0=B8=A3=E0=B8=B0=E0=B8=8A?= =?UTF-8?q?=E0=B8=B1=E0=B8=9A=E0=B8=82=E0=B8=B6=E0=B9=89=E0=B8=99=E0=B9=81?= =?UTF-8?q?=E0=B8=A5=E0=B8=B0=E0=B8=A5=E0=B8=94=20read=20cost=20=E0=B8=97?= =?UTF-8?q?=E0=B8=B5=E0=B9=88=E0=B9=84=E0=B8=A1=E0=B9=88=E0=B8=88=E0=B8=B3?= =?UTF-8?q?=E0=B9=80=E0=B8=9B=E0=B9=87=E0=B8=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/services/rabbitmq.ts | 64 ++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/src/services/rabbitmq.ts b/src/services/rabbitmq.ts index 097473f8..da93d32f 100644 --- a/src/services/rabbitmq.ts +++ b/src/services/rabbitmq.ts @@ -1161,21 +1161,38 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { } console.timeEnd("[AMQ] clone_permissionProfiles"); - //หา dna posmaster ถ้าไม่มีให้เอาตัวเองเป็น dna - console.time("[AMQ] query_employeePosMaster"); - const orgemployeePosMaster = await repoEmployeePosmaster.find({ - where: { orgRevisionId: orgRevisionPublish.id }, - relations: ["positions"], - }); - console.timeEnd("[AMQ] query_employeePosMaster"); + console.time("[AMQ] query_employee_org_structures"); + const [orgemployeePosMaster, orgemployeeTempPosMaster] = await Promise.all([ + repoEmployeePosmaster.find({ + where: { orgRevisionId: orgRevisionPublish.id }, + relations: ["positions"], + }), + repoEmployeeTempPosmaster.find({ + where: { orgRevisionId: orgRevisionPublish.id }, + relations: ["positions"], + }), + ]); + console.timeEnd("[AMQ] query_employee_org_structures"); console.log(`[AMQ] orgemployeePosMaster count: ${orgemployeePosMaster.length}`); + console.log(`[AMQ] orgemployeeTempPosMaster count: ${orgemployeeTempPosMaster.length}`); - let _orgemployeePosMaster: EmployeePosMaster[]; - const validProfileIds = new Set( - (await repoProfileEmployee.find({ select: ["id"] })).map((p) => p.id), + const currentHolderIds = Array.from( + new Set( + orgemployeePosMaster + .map((item) => item.current_holderId) + .filter((holderId): holderId is string => !!holderId), + ), ); + const validProfileIds = new Set(); + if (currentHolderIds.length > 0) { + const profiles = await repoProfileEmployee.find({ + select: ["id"], + where: { id: In(currentHolderIds) }, + }); + profiles.forEach((profile) => validProfileIds.add(profile.id)); + } - _orgemployeePosMaster = orgemployeePosMaster.map((x) => ({ + const _orgemployeePosMaster: EmployeePosMaster[] = orgemployeePosMaster.map((x) => ({ ...x, current_holderId: x.current_holderId && validProfileIds.has(x.current_holderId) ? x.current_holderId : null, @@ -1184,6 +1201,13 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { ? x.id : x.ancestorDNA, })); + const _orgemployeeTempPosMaster: EmployeeTempPosMaster[] = orgemployeeTempPosMaster.map((x) => ({ + ...x, + ancestorDNA: + x.ancestorDNA == null || x.ancestorDNA == "00000000-0000-0000-0000-000000000000" + ? x.id + : x.ancestorDNA, + })); console.time("[AMQ] insert_employeePosMaster"); await repoEmployeePosmaster @@ -1198,24 +1222,6 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { .execute(); console.timeEnd("[AMQ] insert_employeePosMaster"); - //หา dna posmaster ถ้าไม่มีให้เอาตัวเองเป็น dna - console.time("[AMQ] query_employeeTempPosMaster"); - const orgemployeeTempPosMaster = await repoEmployeeTempPosmaster.find({ - where: { orgRevisionId: orgRevisionPublish.id }, - relations: ["positions"], - }); - console.timeEnd("[AMQ] query_employeeTempPosMaster"); - console.log(`[AMQ] orgemployeeTempPosMaster count: ${orgemployeeTempPosMaster.length}`); - - let _orgemployeeTempPosMaster: EmployeeTempPosMaster[]; - _orgemployeeTempPosMaster = orgemployeeTempPosMaster.map((x) => ({ - ...x, - ancestorDNA: - x.ancestorDNA == null || x.ancestorDNA == "00000000-0000-0000-0000-000000000000" - ? x.id - : x.ancestorDNA, - })); - const groupByParentId = ( items: T[], getParentId: (item: T) => string | null | undefined, From 750947f34fb6cb62f8e98f7207e1682c8027f1d0 Mon Sep 17 00:00:00 2001 From: waruneeauy Date: Tue, 5 May 2026 16:38:54 +0700 Subject: [PATCH 5/6] =?UTF-8?q?1.=20=E0=B9=80=E0=B8=9E=E0=B8=B4=E0=B9=88?= =?UTF-8?q?=E0=B8=A1=20helper=20=E0=B8=AA=E0=B8=B3=E0=B8=AB=E0=B8=A3?= =?UTF-8?q?=E0=B8=B1=E0=B8=9A=20build=20clone=20rows=20=E0=B8=88=E0=B8=B2?= =?UTF-8?q?=E0=B8=81=20metadata=20=E0=B8=82=E0=B8=AD=E0=B8=87=20repository?= =?UTF-8?q?=20=E0=B9=81=E0=B8=A5=E0=B9=89=E0=B8=A7=20pre-generate=20UUID?= =?UTF-8?q?=20=E0=B9=83=E0=B8=AB=E0=B9=89=20parent=20=E0=B9=81=E0=B8=A5?= =?UTF-8?q?=E0=B8=B0=20child=20=E0=B8=A5=E0=B9=88=E0=B8=A7=E0=B8=87?= =?UTF-8?q?=E0=B8=AB=E0=B8=99=E0=B9=89=E0=B8=B2=202.=20=E0=B9=80=E0=B8=9B?= =?UTF-8?q?=E0=B8=A5=E0=B8=B5=E0=B9=88=E0=B8=A2=E0=B8=99=20inner=20clone?= =?UTF-8?q?=20flow=20=E0=B9=80=E0=B8=9B=E0=B9=87=E0=B8=99=20cloneEmployeeN?= =?UTF-8?q?odeBatch(...)=20=E0=B8=97=E0=B8=B5=E0=B9=88=E0=B8=97=E0=B8=B3?= =?UTF-8?q?=E0=B8=87=E0=B8=B2=E0=B8=99=E0=B9=80=E0=B8=9B=E0=B9=87=E0=B8=99?= =?UTF-8?q?=E0=B8=8A=E0=B8=B8=E0=B8=94=20=E0=B9=81=E0=B8=97=E0=B8=99?= =?UTF-8?q?=E0=B8=81=E0=B8=B2=E0=B8=A3=20save()=20parent=20=E0=B9=81?= =?UTF-8?q?=E0=B8=A5=E0=B9=89=E0=B8=A7=20save()=20children=20=E0=B8=97?= =?UTF-8?q?=E0=B8=B5=E0=B8=A5=E0=B8=B0=E0=B8=A3=E0=B8=B2=E0=B8=A2=E0=B8=81?= =?UTF-8?q?=E0=B8=B2=E0=B8=A3=203.=20=E0=B9=83=E0=B8=8A=E0=B9=89=20insertI?= =?UTF-8?q?nChunks(...)=20=E0=B8=AA=E0=B8=B3=E0=B8=AB=E0=B8=A3=E0=B8=B1?= =?UTF-8?q?=E0=B8=9A=20batch=20insert=20=E0=B8=82=E0=B8=AD=E0=B8=87=20pare?= =?UTF-8?q?nt=20rows=20=E0=B9=81=E0=B8=A5=E0=B8=B0=20EmployeePosition=20ro?= =?UTF-8?q?ws=204.=20=E0=B9=83=E0=B8=8A=E0=B9=89=20helper=20=E0=B9=80?= =?UTF-8?q?=E0=B8=94=E0=B8=B5=E0=B8=A2=E0=B8=A7=E0=B8=81=E0=B8=B1=E0=B8=99?= =?UTF-8?q?=E0=B8=8B=E0=B9=89=E0=B8=B3=E0=B8=97=E0=B8=B8=E0=B8=81=E0=B8=A3?= =?UTF-8?q?=E0=B8=B0=E0=B8=94=E0=B8=B1=E0=B8=9A=E0=B8=82=E0=B8=AD=E0=B8=87?= =?UTF-8?q?=20tree=20(root,=20child1,=20child2,=20child3,=20child4)=20?= =?UTF-8?q?=E0=B9=80=E0=B8=9E=E0=B8=B7=E0=B9=88=E0=B8=AD=E0=B8=A5=E0=B8=94?= =?UTF-8?q?=20code=20duplication=20=E0=B9=81=E0=B8=A5=E0=B8=B0=E0=B8=84?= =?UTF-8?q?=E0=B8=87=20mapping=20=E0=B8=82=E0=B8=AD=E0=B8=87=20destination?= =?UTF-8?q?=20org=20ids=20=E0=B8=95=E0=B8=B2=E0=B8=A1=20logic=20=E0=B9=80?= =?UTF-8?q?=E0=B8=94=E0=B8=B4=E0=B8=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/services/rabbitmq.ts | 543 +++++++++++++-------------------------- 1 file changed, 180 insertions(+), 363 deletions(-) diff --git a/src/services/rabbitmq.ts b/src/services/rabbitmq.ts index da93d32f..073042c9 100644 --- a/src/services/rabbitmq.ts +++ b/src/services/rabbitmq.ts @@ -1,3 +1,4 @@ +import { randomUUID } from "crypto"; import amqp from "amqplib"; import { AppDataSource } from "../database/data-source"; import { Command } from "../entities/Command"; @@ -20,7 +21,7 @@ import { OrgChild4 } from "../entities/OrgChild4"; import { OrgRoot } from "../entities/OrgRoot"; import { PosMasterAssign, PosMasterAssignDTO } from "../entities/PosMasterAssign"; import { Position } from "../entities/Position"; -import { In, Not } from "typeorm"; +import { In, Not, Repository } from "typeorm"; import { PosMasterAct } from "../entities/PosMasterAct"; import { PermissionOrg } from "../entities/PermissionOrg"; import { sendWebSocket } from "./webSocket"; @@ -1292,6 +1293,98 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { const orgChild2ByChild1 = groupByParentId(orgChild2, (item) => item.orgChild1Id); const orgChild3ByChild2 = groupByParentId(orgChild3, (item) => item.orgChild2Id); const orgChild4ByChild3 = groupByParentId(orgChild4, (item) => item.orgChild3Id); + type OrgDestinationIds = { + orgRootId?: string | null; + orgChild1Id?: string | null; + orgChild2Id?: string | null; + orgChild3Id?: string | null; + orgChild4Id?: string | null; + }; + type CloneEmployeeSource = { + positions: EmployeePosition[]; + } & (EmployeePosMaster | EmployeeTempPosMaster); + const buildAuditFields = (timestamp: Date) => ({ + createdUserId: "", + createdFullName: "System Administrator", + createdAt: timestamp, + lastUpdateUserId: "", + lastUpdateFullName: "System Administrator", + lastUpdatedAt: timestamp, + }); + const buildColumnData = (repository: Repository, source: T): Partial => { + const row = {} as Partial; + const target = row as Record; + const sourceRecord = source as Record; + for (const column of repository.metadata.columns) { + target[column.propertyName] = sourceRecord[column.propertyName]; + } + return row; + }; + const insertInChunks = async ( + repository: Repository, + rows: Partial[], + chunkSize: number, + ) => { + if (rows.length === 0) { + return; + } + for (const chunk of chunkArray(rows, chunkSize) as Partial[][]) { + await repository.insert(chunk as Parameters["insert"]>[0]); + } + }; + const buildEmployeeCloneBatch = ( + items: T[], + parentRepository: Repository, + positionParentKey: "posMasterId" | "posMasterTempId", + targetIds: OrgDestinationIds, + ) => { + const parentRows: Partial[] = []; + const positionRows: Partial[] = []; + + for (const item of items) { + const parentId = randomUUID(); + const parentTimestamp = new Date(); + parentRows.push({ + ...buildColumnData(parentRepository, item), + id: parentId, + orgRevisionId: orgRevisionDraft.id, + ...targetIds, + ...buildAuditFields(parentTimestamp), + }); + + for (const position of item.positions ?? []) { + const positionTimestamp = new Date(); + positionRows.push({ + ...buildColumnData(employeePositionRepository, position), + id: randomUUID(), + posMasterId: positionParentKey === "posMasterId" ? parentId : undefined, + posMasterTempId: + positionParentKey === "posMasterTempId" ? parentId : undefined, + ...buildAuditFields(positionTimestamp), + }); + } + } + + return { parentRows, positionRows }; + }; + const cloneEmployeeNodeBatch = async ( + items: T[], + parentRepository: Repository, + positionParentKey: "posMasterId" | "posMasterTempId", + targetIds: OrgDestinationIds, + ) => { + if (items.length === 0) { + return; + } + const { parentRows, positionRows } = buildEmployeeCloneBatch( + items, + parentRepository, + positionParentKey, + targetIds, + ); + await insertInChunks(parentRepository, parentRows, 200); + await insertInChunks(employeePositionRepository, positionRows, 500); + }; await repoEmployeeTempPosmaster .createQueryBuilder() @@ -1313,398 +1406,122 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { const filteredEmployeePosMaster = employeePosMasterByNode.get(getNodeKey("root", dataId)) ?? []; - await Promise.all( - filteredEmployeePosMaster.map(async (item: any) => { - delete item.id; - const employeePosMaster = Object.assign(new EmployeePosMaster(), item); - employeePosMaster.positions = []; - employeePosMaster.orgRevisionId = orgRevisionDraft.id; - employeePosMaster.orgRootId = matchedOrgRoot?.id ?? null; - employeePosMaster.createdUserId = ""; - employeePosMaster.createdFullName = "System Administrator"; - employeePosMaster.createdAt = new Date(); - employeePosMaster.lastUpdateUserId = ""; - employeePosMaster.lastUpdateFullName = "System Administrator"; - employeePosMaster.lastUpdatedAt = new Date(); - await repoEmployeePosmaster.save(employeePosMaster); - - await Promise.all( - item.positions.map(async (pos: any) => { - delete pos.id; - const employeePosition: EmployeePosition = Object.assign( - new EmployeePosition(), - pos, - ); - employeePosition.posMasterId = employeePosMaster.id; - employeePosition.createdUserId = ""; - employeePosition.createdFullName = "System Administrator"; - employeePosition.createdAt = new Date(); - employeePosition.lastUpdateUserId = ""; - employeePosition.lastUpdateFullName = "System Administrator"; - employeePosition.lastUpdatedAt = new Date(); - await employeePositionRepository.save(employeePosition); - }), - ); - }), + await cloneEmployeeNodeBatch( + filteredEmployeePosMaster, + repoEmployeePosmaster, + "posMasterId", + { orgRootId: matchedOrgRoot?.id ?? null }, ); - await Promise.all( - (employeeTempPosMasterByNode.get(getNodeKey("root", dataId)) ?? []) - .map(async (item: any) => { - delete item.id; - const employeeTempPosMaster = Object.assign(new EmployeeTempPosMaster(), item); - employeeTempPosMaster.positions = []; - employeeTempPosMaster.orgRevisionId = orgRevisionDraft.id; - employeeTempPosMaster.orgRootId = matchedOrgRoot?.id ?? null; - employeeTempPosMaster.createdUserId = ""; - employeeTempPosMaster.createdFullName = "System Administrator"; - employeeTempPosMaster.createdAt = new Date(); - employeeTempPosMaster.lastUpdateUserId = ""; - employeeTempPosMaster.lastUpdateFullName = "System Administrator"; - employeeTempPosMaster.lastUpdatedAt = new Date(); - await repoEmployeeTempPosmaster.save(employeeTempPosMaster); - - await Promise.all( - item.positions.map(async (pos: any) => { - delete pos.id; - const employeePosition: EmployeePosition = Object.assign( - new EmployeePosition(), - pos, - ); - employeePosition.posMasterTempId = employeeTempPosMaster.id; - employeePosition.createdUserId = ""; - employeePosition.createdFullName = "System Administrator"; - employeePosition.createdAt = new Date(); - employeePosition.lastUpdateUserId = ""; - employeePosition.lastUpdateFullName = "System Administrator"; - employeePosition.lastUpdatedAt = new Date(); - await employeePositionRepository.save(employeePosition); - }), - ); - }), + await cloneEmployeeNodeBatch( + employeeTempPosMasterByNode.get(getNodeKey("root", dataId)) ?? [], + repoEmployeeTempPosmaster, + "posMasterTempId", + { orgRootId: matchedOrgRoot?.id ?? null }, ); for (const x of orgChild1ByRoot.get(dataId) ?? []) { const data1Id = x.id; const matchedOrgChild1 = findMatchedNodeByAncestorDNA(orgChild1Current, x); - await Promise.all( - (employeePosMasterByNode.get(getNodeKey("child1", data1Id)) ?? []) - .map(async (item: any) => { - delete item.id; - const employeePosMaster = Object.assign(new EmployeePosMaster(), item); - employeePosMaster.positions = []; - employeePosMaster.orgRevisionId = orgRevisionDraft.id; - employeePosMaster.orgRootId = matchedOrgRoot?.id ?? null; - employeePosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; - employeePosMaster.createdUserId = ""; - employeePosMaster.createdFullName = "System Administrator"; - employeePosMaster.createdAt = new Date(); - employeePosMaster.lastUpdateUserId = ""; - employeePosMaster.lastUpdateFullName = "System Administrator"; - employeePosMaster.lastUpdatedAt = new Date(); - await repoEmployeePosmaster.save(employeePosMaster); - - await Promise.all( - item.positions.map(async (pos: any) => { - delete pos.id; - const employeePosition: EmployeePosition = Object.assign( - new EmployeePosition(), - pos, - ); - employeePosition.posMasterId = employeePosMaster.id; - employeePosition.createdUserId = ""; - employeePosition.createdFullName = "System Administrator"; - employeePosition.createdAt = new Date(); - employeePosition.lastUpdateUserId = ""; - employeePosition.lastUpdateFullName = "System Administrator"; - employeePosition.lastUpdatedAt = new Date(); - await employeePositionRepository.save(employeePosition); - }), - ); - }), + await cloneEmployeeNodeBatch( + employeePosMasterByNode.get(getNodeKey("child1", data1Id)) ?? [], + repoEmployeePosmaster, + "posMasterId", + { + orgRootId: matchedOrgRoot?.id ?? null, + orgChild1Id: matchedOrgChild1?.id ?? null, + }, ); - await Promise.all( - (employeeTempPosMasterByNode.get(getNodeKey("child1", data1Id)) ?? []) - .map(async (item: any) => { - delete item.id; - const employeeTempPosMaster = Object.assign(new EmployeeTempPosMaster(), item); - employeeTempPosMaster.positions = []; - employeeTempPosMaster.orgRevisionId = orgRevisionDraft.id; - employeeTempPosMaster.orgRootId = matchedOrgRoot?.id ?? null; - employeeTempPosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; - employeeTempPosMaster.createdUserId = ""; - employeeTempPosMaster.createdFullName = "System Administrator"; - employeeTempPosMaster.createdAt = new Date(); - employeeTempPosMaster.lastUpdateUserId = ""; - employeeTempPosMaster.lastUpdateFullName = "System Administrator"; - employeeTempPosMaster.lastUpdatedAt = new Date(); - await repoEmployeeTempPosmaster.save(employeeTempPosMaster); - - await Promise.all( - item.positions.map(async (pos: any) => { - delete pos.id; - const employeePosition: EmployeePosition = Object.assign( - new EmployeePosition(), - pos, - ); - employeePosition.posMasterTempId = employeeTempPosMaster.id; - employeePosition.createdUserId = ""; - employeePosition.createdFullName = "System Administrator"; - employeePosition.createdAt = new Date(); - employeePosition.lastUpdateUserId = ""; - employeePosition.lastUpdateFullName = "System Administrator"; - employeePosition.lastUpdatedAt = new Date(); - await employeePositionRepository.save(employeePosition); - }), - ); - }), + await cloneEmployeeNodeBatch( + employeeTempPosMasterByNode.get(getNodeKey("child1", data1Id)) ?? [], + repoEmployeeTempPosmaster, + "posMasterTempId", + { + orgRootId: matchedOrgRoot?.id ?? null, + orgChild1Id: matchedOrgChild1?.id ?? null, + }, ); for (const x of orgChild2ByChild1.get(data1Id) ?? []) { const data2Id = x.id; const matchedOrgChild2 = findMatchedNodeByAncestorDNA(orgChild2Current, x); - await Promise.all( - (employeePosMasterByNode.get(getNodeKey("child2", data2Id)) ?? []) - .map(async (item: any) => { - delete item.id; - const employeePosMaster = Object.assign(new EmployeePosMaster(), item); - employeePosMaster.positions = []; - employeePosMaster.orgRevisionId = orgRevisionDraft.id; - employeePosMaster.orgRootId = matchedOrgRoot?.id ?? null; - employeePosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; - employeePosMaster.orgChild2Id = matchedOrgChild2?.id ?? null; - employeePosMaster.createdUserId = ""; - employeePosMaster.createdFullName = "System Administrator"; - employeePosMaster.createdAt = new Date(); - employeePosMaster.lastUpdateUserId = ""; - employeePosMaster.lastUpdateFullName = "System Administrator"; - employeePosMaster.lastUpdatedAt = new Date(); - await repoEmployeePosmaster.save(employeePosMaster); - - await Promise.all( - item.positions.map(async (pos: any) => { - delete pos.id; - const employeePosition: EmployeePosition = Object.assign( - new EmployeePosition(), - pos, - ); - employeePosition.posMasterId = employeePosMaster.id; - employeePosition.createdUserId = ""; - employeePosition.createdFullName = "System Administrator"; - employeePosition.createdAt = new Date(); - employeePosition.lastUpdateUserId = ""; - employeePosition.lastUpdateFullName = "System Administrator"; - employeePosition.lastUpdatedAt = new Date(); - await employeePositionRepository.save(employeePosition); - }), - ); - }), + await cloneEmployeeNodeBatch( + employeePosMasterByNode.get(getNodeKey("child2", data2Id)) ?? [], + repoEmployeePosmaster, + "posMasterId", + { + orgRootId: matchedOrgRoot?.id ?? null, + orgChild1Id: matchedOrgChild1?.id ?? null, + orgChild2Id: matchedOrgChild2?.id ?? null, + }, ); - await Promise.all( - (employeeTempPosMasterByNode.get(getNodeKey("child2", data2Id)) ?? []) - .map(async (item: any) => { - delete item.id; - const employeeTempPosMaster = Object.assign(new EmployeeTempPosMaster(), item); - employeeTempPosMaster.positions = []; - employeeTempPosMaster.orgRevisionId = orgRevisionDraft.id; - employeeTempPosMaster.orgRootId = dataId; - employeeTempPosMaster.orgChild1Id = data1Id; - employeeTempPosMaster.orgChild2Id = data2Id; - employeeTempPosMaster.createdUserId = ""; - employeeTempPosMaster.createdFullName = "System Administrator"; - employeeTempPosMaster.createdAt = new Date(); - employeeTempPosMaster.lastUpdateUserId = ""; - employeeTempPosMaster.lastUpdateFullName = "System Administrator"; - employeeTempPosMaster.lastUpdatedAt = new Date(); - await repoEmployeeTempPosmaster.save(employeeTempPosMaster); - - await Promise.all( - item.positions.map(async (pos: any) => { - delete pos.id; - const employeePosition: EmployeePosition = Object.assign( - new EmployeePosition(), - pos, - ); - employeePosition.posMasterTempId = employeeTempPosMaster.id; - employeePosition.createdUserId = ""; - employeePosition.createdFullName = "System Administrator"; - employeePosition.createdAt = new Date(); - employeePosition.lastUpdateUserId = ""; - employeePosition.lastUpdateFullName = "System Administrator"; - employeePosition.lastUpdatedAt = new Date(); - await employeePositionRepository.save(employeePosition); - }), - ); - }), + await cloneEmployeeNodeBatch( + employeeTempPosMasterByNode.get(getNodeKey("child2", data2Id)) ?? [], + repoEmployeeTempPosmaster, + "posMasterTempId", + { + orgRootId: dataId, + orgChild1Id: data1Id, + orgChild2Id: data2Id, + }, ); for (const x of orgChild3ByChild2.get(data2Id) ?? []) { const data3Id = x.id; const matchedOrgChild3 = findMatchedNodeByAncestorDNA(orgChild3Current, x); - await Promise.all( - (employeePosMasterByNode.get(getNodeKey("child3", data3Id)) ?? []) - .map(async (item: any) => { - delete item.id; - const employeePosMaster = Object.assign(new EmployeePosMaster(), item); - employeePosMaster.positions = []; - employeePosMaster.orgRevisionId = orgRevisionDraft.id; - employeePosMaster.orgRootId = matchedOrgRoot?.id ?? null; - employeePosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; - employeePosMaster.orgChild2Id = matchedOrgChild2?.id ?? null; - employeePosMaster.orgChild3Id = matchedOrgChild3?.id ?? null; - employeePosMaster.createdUserId = ""; - employeePosMaster.createdFullName = "System Administrator"; - employeePosMaster.createdAt = new Date(); - employeePosMaster.lastUpdateUserId = ""; - employeePosMaster.lastUpdateFullName = "System Administrator"; - employeePosMaster.lastUpdatedAt = new Date(); - await repoEmployeePosmaster.save(employeePosMaster); - - await Promise.all( - item.positions.map(async (pos: any) => { - delete pos.id; - const employeePosition: EmployeePosition = Object.assign( - new EmployeePosition(), - pos, - ); - employeePosition.posMasterId = employeePosMaster.id; - employeePosition.createdUserId = ""; - employeePosition.createdFullName = "System Administrator"; - employeePosition.createdAt = new Date(); - employeePosition.lastUpdateUserId = ""; - employeePosition.lastUpdateFullName = "System Administrator"; - employeePosition.lastUpdatedAt = new Date(); - await employeePositionRepository.save(employeePosition); - }), - ); - }), + await cloneEmployeeNodeBatch( + employeePosMasterByNode.get(getNodeKey("child3", data3Id)) ?? [], + repoEmployeePosmaster, + "posMasterId", + { + orgRootId: matchedOrgRoot?.id ?? null, + orgChild1Id: matchedOrgChild1?.id ?? null, + orgChild2Id: matchedOrgChild2?.id ?? null, + orgChild3Id: matchedOrgChild3?.id ?? null, + }, ); - await Promise.all( - (employeeTempPosMasterByNode.get(getNodeKey("child3", data3Id)) ?? []) - .map(async (item: any) => { - delete item.id; - const employeeTempPosMaster = Object.assign(new EmployeeTempPosMaster(), item); - employeeTempPosMaster.positions = []; - employeeTempPosMaster.orgRevisionId = orgRevisionDraft.id; - employeeTempPosMaster.orgRootId = matchedOrgRoot?.id ?? null; - employeeTempPosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; - employeeTempPosMaster.orgChild2Id = matchedOrgChild2?.id ?? null; - employeeTempPosMaster.orgChild3Id = matchedOrgChild3?.id ?? null; - employeeTempPosMaster.createdUserId = ""; - employeeTempPosMaster.createdFullName = "System Administrator"; - employeeTempPosMaster.createdAt = new Date(); - employeeTempPosMaster.lastUpdateUserId = ""; - employeeTempPosMaster.lastUpdateFullName = "System Administrator"; - employeeTempPosMaster.lastUpdatedAt = new Date(); - await repoEmployeeTempPosmaster.save(employeeTempPosMaster); - - await Promise.all( - item.positions.map(async (pos: any) => { - delete pos.id; - const employeePosition: EmployeePosition = Object.assign( - new EmployeePosition(), - pos, - ); - employeePosition.posMasterTempId = employeeTempPosMaster.id; - employeePosition.createdUserId = ""; - employeePosition.createdFullName = "System Administrator"; - employeePosition.createdAt = new Date(); - employeePosition.lastUpdateUserId = ""; - employeePosition.lastUpdateFullName = "System Administrator"; - employeePosition.lastUpdatedAt = new Date(); - await employeePositionRepository.save(employeePosition); - }), - ); - }), + await cloneEmployeeNodeBatch( + employeeTempPosMasterByNode.get(getNodeKey("child3", data3Id)) ?? [], + repoEmployeeTempPosmaster, + "posMasterTempId", + { + orgRootId: matchedOrgRoot?.id ?? null, + orgChild1Id: matchedOrgChild1?.id ?? null, + orgChild2Id: matchedOrgChild2?.id ?? null, + orgChild3Id: matchedOrgChild3?.id ?? null, + }, ); for (const x of orgChild4ByChild3.get(data3Id) ?? []) { const data4Id = x.id; const matchedOrgChild4 = findMatchedNodeByAncestorDNA(orgChild4Current, x); - await Promise.all( - (employeePosMasterByNode.get(getNodeKey("child4", data4Id)) ?? []) - .map(async (item: any) => { - delete item.id; - const employeePosMaster = Object.assign(new EmployeePosMaster(), item); - employeePosMaster.positions = []; - employeePosMaster.orgRevisionId = orgRevisionDraft.id; - employeePosMaster.orgRootId = matchedOrgRoot?.id ?? null; - employeePosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; - employeePosMaster.orgChild2Id = matchedOrgChild2?.id ?? null; - employeePosMaster.orgChild3Id = matchedOrgChild3?.id ?? null; - employeePosMaster.orgChild4Id = matchedOrgChild4?.id ?? null; - employeePosMaster.createdUserId = ""; - employeePosMaster.createdFullName = "System Administrator"; - employeePosMaster.createdAt = new Date(); - employeePosMaster.lastUpdateUserId = ""; - employeePosMaster.lastUpdateFullName = "System Administrator"; - employeePosMaster.lastUpdatedAt = new Date(); - await repoEmployeePosmaster.save(employeePosMaster); - - await Promise.all( - item.positions.map(async (pos: any) => { - delete pos.id; - const employeePosition: EmployeePosition = Object.assign( - new EmployeePosition(), - pos, - ); - employeePosition.posMasterId = employeePosMaster.id; - employeePosition.createdUserId = ""; - employeePosition.createdFullName = "System Administrator"; - employeePosition.createdAt = new Date(); - employeePosition.lastUpdateUserId = ""; - employeePosition.lastUpdateFullName = "System Administrator"; - employeePosition.lastUpdatedAt = new Date(); - await employeePositionRepository.save(employeePosition); - }), - ); - }), + await cloneEmployeeNodeBatch( + employeePosMasterByNode.get(getNodeKey("child4", data4Id)) ?? [], + repoEmployeePosmaster, + "posMasterId", + { + orgRootId: matchedOrgRoot?.id ?? null, + orgChild1Id: matchedOrgChild1?.id ?? null, + orgChild2Id: matchedOrgChild2?.id ?? null, + orgChild3Id: matchedOrgChild3?.id ?? null, + orgChild4Id: matchedOrgChild4?.id ?? null, + }, ); - await Promise.all( - (employeeTempPosMasterByNode.get(getNodeKey("child4", data4Id)) ?? []) - .map(async (item: any) => { - delete item.id; - const employeeTempPosMaster = Object.assign( - new EmployeeTempPosMaster(), - item, - ); - employeeTempPosMaster.positions = []; - employeeTempPosMaster.orgRevisionId = orgRevisionDraft.id; - employeeTempPosMaster.orgRootId = matchedOrgRoot?.id ?? null; - employeeTempPosMaster.orgChild1Id = matchedOrgChild1?.id ?? null; - employeeTempPosMaster.orgChild2Id = matchedOrgChild2?.id ?? null; - employeeTempPosMaster.orgChild3Id = matchedOrgChild3?.id ?? null; - employeeTempPosMaster.orgChild4Id = matchedOrgChild4?.id ?? null; - employeeTempPosMaster.createdUserId = ""; - employeeTempPosMaster.createdFullName = "System Administrator"; - employeeTempPosMaster.createdAt = new Date(); - employeeTempPosMaster.lastUpdateUserId = ""; - employeeTempPosMaster.lastUpdateFullName = "System Administrator"; - employeeTempPosMaster.lastUpdatedAt = new Date(); - await repoEmployeeTempPosmaster.save(employeeTempPosMaster); - - await Promise.all( - item.positions.map(async (pos: any) => { - delete pos.id; - const employeePosition: EmployeePosition = Object.assign( - new EmployeePosition(), - pos, - ); - employeePosition.posMasterTempId = employeeTempPosMaster.id; - employeePosition.createdUserId = ""; - employeePosition.createdFullName = "System Administrator"; - employeePosition.createdAt = new Date(); - employeePosition.lastUpdateUserId = ""; - employeePosition.lastUpdateFullName = "System Administrator"; - employeePosition.lastUpdatedAt = new Date(); - await employeePositionRepository.save(employeePosition); - }), - ); - }), + await cloneEmployeeNodeBatch( + employeeTempPosMasterByNode.get(getNodeKey("child4", data4Id)) ?? [], + repoEmployeeTempPosmaster, + "posMasterTempId", + { + orgRootId: matchedOrgRoot?.id ?? null, + orgChild1Id: matchedOrgChild1?.id ?? null, + orgChild2Id: matchedOrgChild2?.id ?? null, + orgChild3Id: matchedOrgChild3?.id ?? null, + orgChild4Id: matchedOrgChild4?.id ?? null, + }, ); } } From 6c1e4a1e427a82d908cc14c8d17d83eb72688f4c Mon Sep 17 00:00:00 2001 From: waruneeauy Date: Tue, 5 May 2026 18:11:55 +0700 Subject: [PATCH 6/6] Optimize handler_org batch writes Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/services/rabbitmq.ts | 59 ++++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/src/services/rabbitmq.ts b/src/services/rabbitmq.ts index 073042c9..990cd5fb 100644 --- a/src/services/rabbitmq.ts +++ b/src/services/rabbitmq.ts @@ -1035,6 +1035,7 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { // Clone oldposMasterAct console.time("[AMQ] clone_oldposMasterAct"); + const posMasterActRowsToInsert: Partial[] = []; for (const act of oldposMasterAct) { const parentDNA = act.posMaster?.ancestorDNA?.trim()?.toLowerCase() ?? ""; const childDNA = act.posMasterChild?.ancestorDNA?.trim()?.toLowerCase() ?? ""; @@ -1046,7 +1047,7 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { const { id, posMaster, posMasterChild, ...fields } = act; - const newAct = { + posMasterActRowsToInsert.push({ ...fields, posMasterId: newParentId, posMasterChildId: newChildId, @@ -1056,9 +1057,13 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { lastUpdatedAt: new Date(), lastUpdateFullName: user ? user.name : "system", lastUpdateUserId: user ? user.sub : "system", - }; - - await posMasterActRepository.save(newAct); + }); + } + if (posMasterActRowsToInsert.length > 0) { + const chunks = chunkArray(posMasterActRowsToInsert, 500); + for (const chunk of chunks) { + await posMasterActRepository.insert(chunk); + } } console.timeEnd("[AMQ] clone_oldposMasterAct"); @@ -1554,11 +1559,13 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { profiles.forEach((profile) => profileEmployeeMap.set(profile.id, profile)); } const updatedProfileEmployeeIds = new Set(); + const employeePosMasterIdsToTouch: string[] = []; + const employeeTempPosMasterIdsToTouch: string[] = []; for (const item of employeePosMaster) { if (item.next_holderId != null) { const profile = profileEmployeeMap.get(item.next_holderId); - const position = await item.positions.find((x) => x.positionIsSelected == true); + const position = item.positions.find((x) => x.positionIsSelected == true); const _null: any = null; if (profile != null) { profile.posLevelId = position?.posLevelId ?? _null; @@ -1567,15 +1574,12 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { updatedProfileEmployeeIds.add(profile.id); } } - item.lastUpdateUserId = lastUpdateUserId; - item.lastUpdateFullName = lastUpdateFullName; - item.lastUpdatedAt = lastUpdatedAt; - await repoEmployeePosmaster.save(item); + employeePosMasterIdsToTouch.push(item.id); } for (const item of employeeTempPosMaster) { if (item.next_holderId != null) { const profile = profileEmployeeMap.get(item.next_holderId); - const position = await item.positions.find((x) => x.positionIsSelected == true); + const position = item.positions.find((x) => x.positionIsSelected == true); const _null: any = null; if (profile != null) { profile.posLevelId = position?.posLevelId ?? _null; @@ -1584,10 +1588,37 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise { updatedProfileEmployeeIds.add(profile.id); } } - item.lastUpdateUserId = lastUpdateUserId; - item.lastUpdateFullName = lastUpdateFullName; - item.lastUpdatedAt = lastUpdatedAt; - await repoEmployeeTempPosmaster.save(item); + employeeTempPosMasterIdsToTouch.push(item.id); + } + if (employeePosMasterIdsToTouch.length > 0) { + const chunks = chunkArray(employeePosMasterIdsToTouch, 500); + const employeePosMasterTableName = repoEmployeePosmaster.metadata.tableName; + for (const chunk of chunks) { + const wherePlaceholders = chunk.map(() => "?").join(", "); + await manager.query( + `UPDATE \`${employeePosMasterTableName}\` + SET lastUpdateUserId = ?, + lastUpdateFullName = ?, + lastUpdatedAt = ? + WHERE id IN (${wherePlaceholders})`, + [lastUpdateUserId, lastUpdateFullName, lastUpdatedAt, ...chunk], + ); + } + } + if (employeeTempPosMasterIdsToTouch.length > 0) { + const chunks = chunkArray(employeeTempPosMasterIdsToTouch, 500); + const employeeTempPosMasterTableName = repoEmployeeTempPosmaster.metadata.tableName; + for (const chunk of chunks) { + const wherePlaceholders = chunk.map(() => "?").join(", "); + await manager.query( + `UPDATE \`${employeeTempPosMasterTableName}\` + SET lastUpdateUserId = ?, + lastUpdateFullName = ?, + lastUpdatedAt = ? + WHERE id IN (${wherePlaceholders})`, + [lastUpdateUserId, lastUpdateFullName, lastUpdatedAt, ...chunk], + ); + } } if (updatedProfileEmployeeIds.size > 0) { const profilesToSave = Array.from(updatedProfileEmployeeIds)