Merge branch 'fix/org-chart' into develop
All checks were successful
Build & Deploy on Dev / build (push) Successful in 1m34s
All checks were successful
Build & Deploy on Dev / build (push) Successful in 1m34s
* fix/org-chart: fix: bug query
This commit is contained in:
commit
92e20966d0
2 changed files with 1461 additions and 978 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -1,7 +1,121 @@
|
||||||
import { AppDataSource } from "../database/data-source";
|
import { AppDataSource } from "../database/data-source";
|
||||||
import { PosMaster } from "../entities/PosMaster";
|
import { PosMaster } from "../entities/PosMaster";
|
||||||
|
|
||||||
// Helper function to get aggregated position counts
|
// Type definitions for position counts
|
||||||
|
export interface PositionCountData {
|
||||||
|
totalCount: number;
|
||||||
|
currentVacantCount: number;
|
||||||
|
nextVacantCount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PositionCountsByNode {
|
||||||
|
orgRootMap: Map<string, PositionCountData>;
|
||||||
|
orgChild1Map: Map<string, PositionCountData>;
|
||||||
|
orgChild2Map: Map<string, PositionCountData>;
|
||||||
|
orgChild3Map: Map<string, PositionCountData>;
|
||||||
|
orgChild4Map: Map<string, PositionCountData>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optimized function using SQL aggregation with GROUP BY
|
||||||
|
// This is much more efficient than loading all records into memory
|
||||||
|
export async function getPositionCountsAggregated(orgRevisionId: string): Promise<PositionCountsByNode> {
|
||||||
|
const posRepo = AppDataSource.getRepository(PosMaster);
|
||||||
|
|
||||||
|
// Helper to build map from query results
|
||||||
|
const buildMap = (results: any[]) => {
|
||||||
|
const map = new Map<string, PositionCountData>();
|
||||||
|
for (const row of results) {
|
||||||
|
if (row.nodeId) {
|
||||||
|
map.set(row.nodeId, {
|
||||||
|
totalCount: parseInt(row.totalCount) || 0,
|
||||||
|
currentVacantCount: parseInt(row.currentVacantCount) || 0,
|
||||||
|
nextVacantCount: parseInt(row.nextVacantCount) || 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Execute all aggregation queries in parallel
|
||||||
|
const [
|
||||||
|
orgRootResults,
|
||||||
|
orgChild1Results,
|
||||||
|
orgChild2Results,
|
||||||
|
orgChild3Results,
|
||||||
|
orgChild4Results,
|
||||||
|
] = await Promise.all([
|
||||||
|
// Level 0: orgRoot
|
||||||
|
posRepo
|
||||||
|
.createQueryBuilder("pos")
|
||||||
|
.select("pos.orgRootId", "nodeId")
|
||||||
|
.addSelect("COUNT(*)", "totalCount")
|
||||||
|
.addSelect("SUM(CASE WHEN pos.current_holderId IS NULL OR pos.current_holderId = '' THEN 1 ELSE 0 END)", "currentVacantCount")
|
||||||
|
.addSelect("SUM(CASE WHEN pos.next_holderId IS NULL OR pos.next_holderId = '' THEN 1 ELSE 0 END)", "nextVacantCount")
|
||||||
|
.where("pos.orgRevisionId = :orgRevisionId", { orgRevisionId })
|
||||||
|
.andWhere("pos.orgRootId IS NOT NULL")
|
||||||
|
.groupBy("pos.orgRootId")
|
||||||
|
.getRawMany(),
|
||||||
|
|
||||||
|
// Level 1: orgChild1
|
||||||
|
posRepo
|
||||||
|
.createQueryBuilder("pos")
|
||||||
|
.select("pos.orgChild1Id", "nodeId")
|
||||||
|
.addSelect("COUNT(*)", "totalCount")
|
||||||
|
.addSelect("SUM(CASE WHEN pos.current_holderId IS NULL OR pos.current_holderId = '' THEN 1 ELSE 0 END)", "currentVacantCount")
|
||||||
|
.addSelect("SUM(CASE WHEN pos.next_holderId IS NULL OR pos.next_holderId = '' THEN 1 ELSE 0 END)", "nextVacantCount")
|
||||||
|
.where("pos.orgRevisionId = :orgRevisionId", { orgRevisionId })
|
||||||
|
.andWhere("pos.orgChild1Id IS NOT NULL")
|
||||||
|
.groupBy("pos.orgChild1Id")
|
||||||
|
.getRawMany(),
|
||||||
|
|
||||||
|
// Level 2: orgChild2
|
||||||
|
posRepo
|
||||||
|
.createQueryBuilder("pos")
|
||||||
|
.select("pos.orgChild2Id", "nodeId")
|
||||||
|
.addSelect("COUNT(*)", "totalCount")
|
||||||
|
.addSelect("SUM(CASE WHEN pos.current_holderId IS NULL OR pos.current_holderId = '' THEN 1 ELSE 0 END)", "currentVacantCount")
|
||||||
|
.addSelect("SUM(CASE WHEN pos.next_holderId IS NULL OR pos.next_holderId = '' THEN 1 ELSE 0 END)", "nextVacantCount")
|
||||||
|
.where("pos.orgRevisionId = :orgRevisionId", { orgRevisionId })
|
||||||
|
.andWhere("pos.orgChild2Id IS NOT NULL")
|
||||||
|
.groupBy("pos.orgChild2Id")
|
||||||
|
.getRawMany(),
|
||||||
|
|
||||||
|
// Level 3: orgChild3
|
||||||
|
posRepo
|
||||||
|
.createQueryBuilder("pos")
|
||||||
|
.select("pos.orgChild3Id", "nodeId")
|
||||||
|
.addSelect("COUNT(*)", "totalCount")
|
||||||
|
.addSelect("SUM(CASE WHEN pos.current_holderId IS NULL OR pos.current_holderId = '' THEN 1 ELSE 0 END)", "currentVacantCount")
|
||||||
|
.addSelect("SUM(CASE WHEN pos.next_holderId IS NULL OR pos.next_holderId = '' THEN 1 ELSE 0 END)", "nextVacantCount")
|
||||||
|
.where("pos.orgRevisionId = :orgRevisionId", { orgRevisionId })
|
||||||
|
.andWhere("pos.orgChild3Id IS NOT NULL")
|
||||||
|
.groupBy("pos.orgChild3Id")
|
||||||
|
.getRawMany(),
|
||||||
|
|
||||||
|
// Level 4: orgChild4
|
||||||
|
posRepo
|
||||||
|
.createQueryBuilder("pos")
|
||||||
|
.select("pos.orgChild4Id", "nodeId")
|
||||||
|
.addSelect("COUNT(*)", "totalCount")
|
||||||
|
.addSelect("SUM(CASE WHEN pos.current_holderId IS NULL OR pos.current_holderId = '' THEN 1 ELSE 0 END)", "currentVacantCount")
|
||||||
|
.addSelect("SUM(CASE WHEN pos.next_holderId IS NULL OR pos.next_holderId = '' THEN 1 ELSE 0 END)", "nextVacantCount")
|
||||||
|
.where("pos.orgRevisionId = :orgRevisionId", { orgRevisionId })
|
||||||
|
.andWhere("pos.orgChild4Id IS NOT NULL")
|
||||||
|
.groupBy("pos.orgChild4Id")
|
||||||
|
.getRawMany(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
orgRootMap: buildMap(orgRootResults),
|
||||||
|
orgChild1Map: buildMap(orgChild1Results),
|
||||||
|
orgChild2Map: buildMap(orgChild2Results),
|
||||||
|
orgChild3Map: buildMap(orgChild3Results),
|
||||||
|
orgChild4Map: buildMap(orgChild4Results),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Legacy function - kept for backward compatibility
|
||||||
|
// DEPRECATED: Use getPositionCountsAggregated instead
|
||||||
export async function getPositionCounts(orgRevisionId: string) {
|
export async function getPositionCounts(orgRevisionId: string) {
|
||||||
// Query all posMaster data for this revision with aggregation
|
// Query all posMaster data for this revision with aggregation
|
||||||
const rawData = await AppDataSource.getRepository(PosMaster)
|
const rawData = await AppDataSource.getRepository(PosMaster)
|
||||||
|
|
@ -276,3 +390,18 @@ export function getRootCounts(map: Map<string, any>, key: string) {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper function to get position counts from aggregated maps with defaults
|
||||||
|
export function getPositionCount(
|
||||||
|
map: Map<string, PositionCountData>,
|
||||||
|
key: string | null | undefined
|
||||||
|
): PositionCountData {
|
||||||
|
if (!key) return { totalCount: 0, currentVacantCount: 0, nextVacantCount: 0 };
|
||||||
|
return (
|
||||||
|
map.get(key) || {
|
||||||
|
totalCount: 0,
|
||||||
|
currentVacantCount: 0,
|
||||||
|
nextVacantCount: 0,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue