Compare commits
No commits in common. "f0cae99c8def467aae1d398059f81a185794a1f5" and "c0f2fbbd885d0f2f78020827ccf301f8744eccea" have entirely different histories.
f0cae99c8d
...
c0f2fbbd88
|
|
@ -0,0 +1,554 @@
|
||||||
|
import { query } from "../database/db";
|
||||||
|
import { logger } from "../utils/logger";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 권한 그룹 인터페이스
|
||||||
|
*/
|
||||||
|
export interface RoleGroup {
|
||||||
|
objid: number;
|
||||||
|
authName: string;
|
||||||
|
authCode: string;
|
||||||
|
companyCode: string;
|
||||||
|
status: string;
|
||||||
|
writer: string;
|
||||||
|
regdate: Date;
|
||||||
|
memberCount?: number;
|
||||||
|
menuCount?: number;
|
||||||
|
memberNames?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 권한 그룹 멤버 인터페이스
|
||||||
|
*/
|
||||||
|
export interface RoleMember {
|
||||||
|
objid: number;
|
||||||
|
masterObjid: number;
|
||||||
|
userId: string;
|
||||||
|
userName?: string;
|
||||||
|
deptName?: string;
|
||||||
|
positionName?: string;
|
||||||
|
writer: string;
|
||||||
|
regdate: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 메뉴 권한 인터페이스
|
||||||
|
*/
|
||||||
|
export interface MenuPermission {
|
||||||
|
objid: number;
|
||||||
|
menuObjid: number;
|
||||||
|
authObjid: number;
|
||||||
|
menuName?: string;
|
||||||
|
createYn: string;
|
||||||
|
readYn: string;
|
||||||
|
updateYn: string;
|
||||||
|
deleteYn: string;
|
||||||
|
writer: string;
|
||||||
|
regdate: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 권한 그룹 서비스
|
||||||
|
*/
|
||||||
|
export class RoleService {
|
||||||
|
/**
|
||||||
|
* 회사별 권한 그룹 목록 조회
|
||||||
|
* @param companyCode - 회사 코드 (undefined 시 전체 조회)
|
||||||
|
* @param search - 검색어
|
||||||
|
*/
|
||||||
|
static async getRoleGroups(
|
||||||
|
companyCode?: string,
|
||||||
|
search?: string
|
||||||
|
): Promise<RoleGroup[]> {
|
||||||
|
try {
|
||||||
|
let sql = `
|
||||||
|
SELECT
|
||||||
|
objid,
|
||||||
|
auth_name AS "authName",
|
||||||
|
auth_code AS "authCode",
|
||||||
|
company_code AS "companyCode",
|
||||||
|
status,
|
||||||
|
writer,
|
||||||
|
regdate,
|
||||||
|
(SELECT COUNT(*) FROM authority_sub_user asu WHERE asu.master_objid = am.objid) AS "memberCount",
|
||||||
|
(SELECT COUNT(*) FROM rel_menu_auth rma WHERE rma.auth_objid = am.objid) AS "menuCount",
|
||||||
|
(SELECT STRING_AGG(ui.user_name, ', ' ORDER BY ui.user_name)
|
||||||
|
FROM authority_sub_user asu
|
||||||
|
JOIN user_info ui ON asu.user_id = ui.user_id
|
||||||
|
WHERE asu.master_objid = am.objid) AS "memberNames"
|
||||||
|
FROM authority_master am
|
||||||
|
WHERE 1=1
|
||||||
|
`;
|
||||||
|
|
||||||
|
const params: any[] = [];
|
||||||
|
let paramIndex = 1;
|
||||||
|
|
||||||
|
// 회사 코드 필터 (companyCode가 undefined면 전체 조회)
|
||||||
|
if (companyCode) {
|
||||||
|
sql += ` AND company_code = $${paramIndex}`;
|
||||||
|
params.push(companyCode);
|
||||||
|
paramIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 검색어 필터
|
||||||
|
if (search && search.trim()) {
|
||||||
|
sql += ` AND (auth_name ILIKE $${paramIndex} OR auth_code ILIKE $${paramIndex})`;
|
||||||
|
params.push(`%${search.trim()}%`);
|
||||||
|
paramIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
sql += ` ORDER BY regdate DESC`;
|
||||||
|
|
||||||
|
logger.info("권한 그룹 조회 SQL", { sql, params });
|
||||||
|
const result = await query<RoleGroup>(sql, params);
|
||||||
|
logger.info("권한 그룹 조회 결과", { count: result.length });
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error("권한 그룹 목록 조회 실패", { error, companyCode, search });
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 권한 그룹 상세 조회
|
||||||
|
*/
|
||||||
|
static async getRoleGroupById(objid: number): Promise<RoleGroup | null> {
|
||||||
|
try {
|
||||||
|
const sql = `
|
||||||
|
SELECT
|
||||||
|
objid,
|
||||||
|
auth_name AS "authName",
|
||||||
|
auth_code AS "authCode",
|
||||||
|
company_code AS "companyCode",
|
||||||
|
status,
|
||||||
|
writer,
|
||||||
|
regdate
|
||||||
|
FROM authority_master
|
||||||
|
WHERE objid = $1
|
||||||
|
`;
|
||||||
|
|
||||||
|
const result = await query<RoleGroup>(sql, [objid]);
|
||||||
|
return result.length > 0 ? result[0] : null;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error("권한 그룹 상세 조회 실패", { error, objid });
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 권한 그룹 생성
|
||||||
|
*/
|
||||||
|
static async createRoleGroup(data: {
|
||||||
|
authName: string;
|
||||||
|
authCode: string;
|
||||||
|
companyCode: string;
|
||||||
|
writer: string;
|
||||||
|
}): Promise<RoleGroup> {
|
||||||
|
try {
|
||||||
|
const sql = `
|
||||||
|
INSERT INTO authority_master (objid, auth_name, auth_code, company_code, status, writer, regdate)
|
||||||
|
VALUES (nextval('seq_authority_master'), $1, $2, $3, 'active', $4, NOW())
|
||||||
|
RETURNING objid, auth_name AS "authName", auth_code AS "authCode",
|
||||||
|
company_code AS "companyCode", status, writer, regdate
|
||||||
|
`;
|
||||||
|
|
||||||
|
const result = await query<RoleGroup>(sql, [
|
||||||
|
data.authName,
|
||||||
|
data.authCode,
|
||||||
|
data.companyCode,
|
||||||
|
data.writer,
|
||||||
|
]);
|
||||||
|
|
||||||
|
logger.info("권한 그룹 생성 성공", {
|
||||||
|
objid: result[0].objid,
|
||||||
|
authName: data.authName,
|
||||||
|
});
|
||||||
|
return result[0];
|
||||||
|
} catch (error) {
|
||||||
|
logger.error("권한 그룹 생성 실패", { error, data });
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 권한 그룹 수정
|
||||||
|
*/
|
||||||
|
static async updateRoleGroup(
|
||||||
|
objid: number,
|
||||||
|
data: {
|
||||||
|
authName?: string;
|
||||||
|
authCode?: string;
|
||||||
|
status?: string;
|
||||||
|
}
|
||||||
|
): Promise<RoleGroup> {
|
||||||
|
try {
|
||||||
|
const updates: string[] = [];
|
||||||
|
const params: any[] = [];
|
||||||
|
let paramIndex = 1;
|
||||||
|
|
||||||
|
if (data.authName !== undefined) {
|
||||||
|
updates.push(`auth_name = $${paramIndex}`);
|
||||||
|
params.push(data.authName);
|
||||||
|
paramIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.authCode !== undefined) {
|
||||||
|
updates.push(`auth_code = $${paramIndex}`);
|
||||||
|
params.push(data.authCode);
|
||||||
|
paramIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.status !== undefined) {
|
||||||
|
updates.push(`status = $${paramIndex}`);
|
||||||
|
params.push(data.status);
|
||||||
|
paramIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updates.length === 0) {
|
||||||
|
throw new Error("수정할 데이터가 없습니다");
|
||||||
|
}
|
||||||
|
|
||||||
|
params.push(objid);
|
||||||
|
|
||||||
|
const sql = `
|
||||||
|
UPDATE authority_master
|
||||||
|
SET ${updates.join(", ")}
|
||||||
|
WHERE objid = $${paramIndex}
|
||||||
|
RETURNING objid, auth_name AS "authName", auth_code AS "authCode",
|
||||||
|
company_code AS "companyCode", status, writer, regdate
|
||||||
|
`;
|
||||||
|
|
||||||
|
const result = await query<RoleGroup>(sql, params);
|
||||||
|
|
||||||
|
if (result.length === 0) {
|
||||||
|
throw new Error("권한 그룹을 찾을 수 없습니다");
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("권한 그룹 수정 성공", { objid, updates });
|
||||||
|
return result[0];
|
||||||
|
} catch (error) {
|
||||||
|
logger.error("권한 그룹 수정 실패", { error, objid, data });
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 권한 그룹 삭제
|
||||||
|
*/
|
||||||
|
static async deleteRoleGroup(objid: number): Promise<void> {
|
||||||
|
try {
|
||||||
|
// CASCADE로 연결된 데이터도 함께 삭제됨 (authority_sub_user, rel_menu_auth)
|
||||||
|
await query("DELETE FROM authority_master WHERE objid = $1", [objid]);
|
||||||
|
logger.info("권한 그룹 삭제 성공", { objid });
|
||||||
|
} catch (error) {
|
||||||
|
logger.error("권한 그룹 삭제 실패", { error, objid });
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 권한 그룹 멤버 목록 조회
|
||||||
|
*/
|
||||||
|
static async getRoleMembers(masterObjid: number): Promise<RoleMember[]> {
|
||||||
|
try {
|
||||||
|
const sql = `
|
||||||
|
SELECT
|
||||||
|
asu.objid,
|
||||||
|
asu.master_objid AS "masterObjid",
|
||||||
|
asu.user_id AS "userId",
|
||||||
|
ui.user_name AS "userName",
|
||||||
|
ui.dept_name AS "deptName",
|
||||||
|
ui.position_name AS "positionName",
|
||||||
|
asu.writer,
|
||||||
|
asu.regdate
|
||||||
|
FROM authority_sub_user asu
|
||||||
|
JOIN user_info ui ON asu.user_id = ui.user_id
|
||||||
|
WHERE asu.master_objid = $1
|
||||||
|
ORDER BY ui.user_name
|
||||||
|
`;
|
||||||
|
|
||||||
|
const result = await query<RoleMember>(sql, [masterObjid]);
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error("권한 그룹 멤버 조회 실패", { error, masterObjid });
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 권한 그룹 멤버 추가 (여러 명)
|
||||||
|
*/
|
||||||
|
static async addRoleMembers(
|
||||||
|
masterObjid: number,
|
||||||
|
userIds: string[],
|
||||||
|
writer: string
|
||||||
|
): Promise<void> {
|
||||||
|
try {
|
||||||
|
// 이미 존재하는 멤버 제외
|
||||||
|
const existingSql = `
|
||||||
|
SELECT user_id
|
||||||
|
FROM authority_sub_user
|
||||||
|
WHERE master_objid = $1 AND user_id = ANY($2)
|
||||||
|
`;
|
||||||
|
const existing = await query<{ user_id: string }>(existingSql, [
|
||||||
|
masterObjid,
|
||||||
|
userIds,
|
||||||
|
]);
|
||||||
|
const existingIds = new Set(
|
||||||
|
existing.map((row: { user_id: string }) => row.user_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
const newUserIds = userIds.filter((userId) => !existingIds.has(userId));
|
||||||
|
|
||||||
|
if (newUserIds.length === 0) {
|
||||||
|
logger.info("추가할 신규 멤버가 없습니다", { masterObjid, userIds });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 배치 삽입
|
||||||
|
const values = newUserIds
|
||||||
|
.map(
|
||||||
|
(_, index) =>
|
||||||
|
`(nextval('seq_authority_sub_user'), $1, $${index + 2}, $${newUserIds.length + 2}, NOW())`
|
||||||
|
)
|
||||||
|
.join(", ");
|
||||||
|
|
||||||
|
const sql = `
|
||||||
|
INSERT INTO authority_sub_user (objid, master_objid, user_id, writer, regdate)
|
||||||
|
VALUES ${values}
|
||||||
|
`;
|
||||||
|
|
||||||
|
await query(sql, [masterObjid, ...newUserIds, writer]);
|
||||||
|
|
||||||
|
// 히스토리 기록
|
||||||
|
for (const userId of newUserIds) {
|
||||||
|
await this.insertAuthorityHistory(masterObjid, userId, "ADD", writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("권한 그룹 멤버 추가 성공", {
|
||||||
|
masterObjid,
|
||||||
|
count: newUserIds.length,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
logger.error("권한 그룹 멤버 추가 실패", { error, masterObjid, userIds });
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 권한 그룹 멤버 제거 (여러 명)
|
||||||
|
*/
|
||||||
|
static async removeRoleMembers(
|
||||||
|
masterObjid: number,
|
||||||
|
userIds: string[],
|
||||||
|
writer: string
|
||||||
|
): Promise<void> {
|
||||||
|
try {
|
||||||
|
await query(
|
||||||
|
"DELETE FROM authority_sub_user WHERE master_objid = $1 AND user_id = ANY($2)",
|
||||||
|
[masterObjid, userIds]
|
||||||
|
);
|
||||||
|
|
||||||
|
// 히스토리 기록
|
||||||
|
for (const userId of userIds) {
|
||||||
|
await this.insertAuthorityHistory(
|
||||||
|
masterObjid,
|
||||||
|
userId,
|
||||||
|
"REMOVE",
|
||||||
|
writer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("권한 그룹 멤버 제거 성공", {
|
||||||
|
masterObjid,
|
||||||
|
count: userIds.length,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
logger.error("권한 그룹 멤버 제거 실패", { error, masterObjid, userIds });
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 권한 히스토리 기록
|
||||||
|
*/
|
||||||
|
private static async insertAuthorityHistory(
|
||||||
|
masterObjid: number,
|
||||||
|
userId: string,
|
||||||
|
historyType: "ADD" | "REMOVE",
|
||||||
|
writer: string
|
||||||
|
): Promise<void> {
|
||||||
|
try {
|
||||||
|
const sql = `
|
||||||
|
INSERT INTO authority_master_history
|
||||||
|
(objid, parent_objid, parent_name, parent_code, user_id, active, history_type, writer, reg_date)
|
||||||
|
SELECT
|
||||||
|
nextval('seq_authority_master'),
|
||||||
|
$1,
|
||||||
|
am.auth_name,
|
||||||
|
am.auth_code,
|
||||||
|
$2,
|
||||||
|
am.status,
|
||||||
|
$3,
|
||||||
|
$4,
|
||||||
|
NOW()
|
||||||
|
FROM authority_master am
|
||||||
|
WHERE am.objid = $1
|
||||||
|
`;
|
||||||
|
|
||||||
|
await query(sql, [masterObjid, userId, historyType, writer]);
|
||||||
|
} catch (error) {
|
||||||
|
logger.error("권한 히스토리 기록 실패", {
|
||||||
|
error,
|
||||||
|
masterObjid,
|
||||||
|
userId,
|
||||||
|
historyType,
|
||||||
|
});
|
||||||
|
// 히스토리 기록 실패는 메인 작업을 중단하지 않음
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 메뉴 권한 목록 조회
|
||||||
|
*/
|
||||||
|
static async getMenuPermissions(
|
||||||
|
authObjid: number
|
||||||
|
): Promise<MenuPermission[]> {
|
||||||
|
try {
|
||||||
|
const sql = `
|
||||||
|
SELECT
|
||||||
|
rma.objid,
|
||||||
|
rma.menu_objid AS "menuObjid",
|
||||||
|
rma.auth_objid AS "authObjid",
|
||||||
|
mi.menu_name_kor AS "menuName",
|
||||||
|
mi.menu_code AS "menuCode",
|
||||||
|
mi.menu_url AS "menuUrl",
|
||||||
|
rma.create_yn AS "createYn",
|
||||||
|
rma.read_yn AS "readYn",
|
||||||
|
rma.update_yn AS "updateYn",
|
||||||
|
rma.delete_yn AS "deleteYn",
|
||||||
|
rma.execute_yn AS "executeYn",
|
||||||
|
rma.export_yn AS "exportYn",
|
||||||
|
rma.writer,
|
||||||
|
rma.regdate
|
||||||
|
FROM rel_menu_auth rma
|
||||||
|
LEFT JOIN menu_info mi ON rma.menu_objid = mi.objid
|
||||||
|
WHERE rma.auth_objid = $1
|
||||||
|
ORDER BY mi.menu_name_kor
|
||||||
|
`;
|
||||||
|
|
||||||
|
const result = await query<MenuPermission>(sql, [authObjid]);
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error("메뉴 권한 조회 실패", { error, authObjid });
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 메뉴 권한 설정 (여러 메뉴)
|
||||||
|
*/
|
||||||
|
static async setMenuPermissions(
|
||||||
|
authObjid: number,
|
||||||
|
permissions: Array<{
|
||||||
|
menuObjid: number;
|
||||||
|
createYn: string;
|
||||||
|
readYn: string;
|
||||||
|
updateYn: string;
|
||||||
|
deleteYn: string;
|
||||||
|
}>,
|
||||||
|
writer: string
|
||||||
|
): Promise<void> {
|
||||||
|
try {
|
||||||
|
// 기존 권한 삭제
|
||||||
|
await query("DELETE FROM rel_menu_auth WHERE auth_objid = $1", [
|
||||||
|
authObjid,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 새로운 권한 삽입
|
||||||
|
if (permissions.length > 0) {
|
||||||
|
const values = permissions
|
||||||
|
.map(
|
||||||
|
(_, index) =>
|
||||||
|
`(nextval('seq_rel_menu_auth'), $${index * 5 + 2}, $1, $${index * 5 + 3}, $${index * 5 + 4}, $${index * 5 + 5}, $${index * 5 + 6}, $${permissions.length * 5 + 2}, NOW())`
|
||||||
|
)
|
||||||
|
.join(", ");
|
||||||
|
|
||||||
|
const params = permissions.flatMap((p) => [
|
||||||
|
p.menuObjid,
|
||||||
|
p.createYn,
|
||||||
|
p.readYn,
|
||||||
|
p.updateYn,
|
||||||
|
p.deleteYn,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const sql = `
|
||||||
|
INSERT INTO rel_menu_auth (objid, menu_objid, auth_objid, create_yn, read_yn, update_yn, delete_yn, writer, regdate)
|
||||||
|
VALUES ${values}
|
||||||
|
`;
|
||||||
|
|
||||||
|
await query(sql, [authObjid, ...params, writer]);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("메뉴 권한 설정 성공", {
|
||||||
|
authObjid,
|
||||||
|
count: permissions.length,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
logger.error("메뉴 권한 설정 실패", { error, authObjid, permissions });
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 사용자가 속한 권한 그룹 목록 조회
|
||||||
|
*/
|
||||||
|
static async getUserRoleGroups(
|
||||||
|
userId: string,
|
||||||
|
companyCode: string
|
||||||
|
): Promise<RoleGroup[]> {
|
||||||
|
try {
|
||||||
|
const sql = `
|
||||||
|
SELECT
|
||||||
|
am.objid,
|
||||||
|
am.auth_name AS "authName",
|
||||||
|
am.auth_code AS "authCode",
|
||||||
|
am.company_code AS "companyCode",
|
||||||
|
am.status,
|
||||||
|
am.writer,
|
||||||
|
am.regdate
|
||||||
|
FROM authority_master am
|
||||||
|
JOIN authority_sub_user asu ON am.objid = asu.master_objid
|
||||||
|
WHERE asu.user_id = $1
|
||||||
|
AND am.company_code = $2
|
||||||
|
AND am.status = 'active'
|
||||||
|
ORDER BY am.auth_name
|
||||||
|
`;
|
||||||
|
|
||||||
|
const result = await query<RoleGroup>(sql, [userId, companyCode]);
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error("사용자 권한 그룹 조회 실패", {
|
||||||
|
error,
|
||||||
|
userId,
|
||||||
|
companyCode,
|
||||||
|
});
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 전체 메뉴 목록 조회 (권한 설정용)
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* 전체 메뉴 목록 조회 (권한 설정용)
|
||||||
|
*/
|
||||||
|
static async getAllMenus(companyCode?: string): Promise<any[]> {
|
||||||
|
try {
|
||||||
|
logger.info("🔍 전체 메뉴 목록 조회 시작", { companyCode });
|
||||||
|
|
||||||
|
let whereConditions: string[] = ["status = 'active'"];
|
||||||
|
const params: any[] = [];
|
||||||
|
let paramIndex = 1;
|
||||||
|
|
||||||
|
// 회사 코드 필터 (선택적)
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
/**
|
||||||
|
* 전체 메뉴 목록 조회 (권한 설정용)
|
||||||
|
*/
|
||||||
|
static async getAllMenus(companyCode?: string): Promise<any[]> {
|
||||||
|
try {
|
||||||
|
logger.info("🔍 전체 메뉴 목록 조회 시작", { companyCode });
|
||||||
|
|
||||||
|
let whereConditions: string[] = ["status = 'active'"];
|
||||||
|
const params: any[] = [];
|
||||||
|
let paramIndex = 1;
|
||||||
|
|
||||||
|
// 회사 코드 필터 (선택적)
|
||||||
|
// 공통 메뉴(*)와 특정 회사 메뉴를 모두 조회
|
||||||
|
if (companyCode) {
|
||||||
|
whereConditions.push(`(company_code = \$${paramIndex} OR company_code = '*')`);
|
||||||
|
params.push(companyCode);
|
||||||
|
paramIndex++;
|
||||||
|
logger.info("📋 회사 코드 필터 적용", { companyCode });
|
||||||
|
} else {
|
||||||
|
logger.info("📋 회사 코드 필터 없음 (전체 조회)");
|
||||||
|
}
|
||||||
|
|
||||||
|
const whereClause = whereConditions.join(" AND ");
|
||||||
|
|
||||||
|
const sql = `
|
||||||
|
SELECT
|
||||||
|
objid,
|
||||||
|
menu_name_kor AS "menuName",
|
||||||
|
menu_name_eng AS "menuNameEng",
|
||||||
|
menu_code AS "menuCode",
|
||||||
|
menu_url AS "menuUrl",
|
||||||
|
menu_type AS "menuType",
|
||||||
|
parent_obj_id AS "parentObjid",
|
||||||
|
seq AS "sortOrder",
|
||||||
|
company_code AS "companyCode"
|
||||||
|
FROM menu_info
|
||||||
|
WHERE ${whereClause}
|
||||||
|
ORDER BY seq, menu_name_kor
|
||||||
|
`;
|
||||||
|
|
||||||
|
logger.info("🔍 SQL 쿼리 실행", {
|
||||||
|
whereClause,
|
||||||
|
params,
|
||||||
|
sql: sql.substring(0, 200) + "...",
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await query<any>(sql, params);
|
||||||
|
|
||||||
|
logger.info("✅ 메뉴 목록 조회 성공", {
|
||||||
|
count: result.length,
|
||||||
|
companyCode,
|
||||||
|
menus: result.map((m) => ({
|
||||||
|
objid: m.objid,
|
||||||
|
name: m.menuName,
|
||||||
|
code: m.menuCode,
|
||||||
|
companyCode: m.companyCode,
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error("❌ 메뉴 목록 조회 실패", { error, companyCode });
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue