feat: 카테고리 컴포넌트 메뉴 스코프 전환 완료
✅ 구현 내용: 1. 백엔드 API 추가 - GET /api/table-management/menu/:menuObjid/category-columns - 형제 메뉴들의 테이블에서 카테고리 타입 컬럼 조회 - menuService.getSiblingMenuObjids() 재사용 2. 프론트엔드 CategoryWidget 수정 - menuObjid를 props로 받아 CategoryColumnList에 전달 - effectiveMenuObjid로 props.menuObjid도 처리 - 선택된 컬럼에 tableName 포함하여 상태 관리 3. CategoryColumnList 수정 - menuObjid 기반으로 형제 메뉴의 모든 카테고리 컬럼 조회 - 테이블명+컬럼명 함께 표시 - onColumnSelect에 tableName 전달 4. 메뉴 네비게이션 수정 - AppLayout.tsx: 화면 이동 시 menuObjid를 URL 쿼리 파라미터로 전달 - useMenu.ts: 동일하게 menuObjid 전달 - page.tsx: 자식 컴포넌트에도 menuObjid 전달 🎯 효과: - 이제 형제 메뉴들이 서로 다른 테이블을 사용해도 카테고리 공유 가능 - 메뉴 클릭 → 화면 이동 시 자동으로 menuObjid 전달 - 카테고리 위젯이 형제 메뉴의 모든 카테고리 컬럼 표시
This commit is contained in:
@@ -1599,3 +1599,96 @@ export async function toggleLogTable(
|
||||
res.status(500).json(response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 메뉴의 형제 메뉴들이 사용하는 모든 테이블의 카테고리 타입 컬럼 조회
|
||||
*
|
||||
* @route GET /api/table-management/menu/:menuObjid/category-columns
|
||||
* @description 형제 메뉴들의 화면에서 사용하는 테이블의 input_type='category' 컬럼 조회
|
||||
*/
|
||||
export async function getCategoryColumnsByMenu(
|
||||
req: AuthenticatedRequest,
|
||||
res: Response
|
||||
): Promise<void> {
|
||||
try {
|
||||
const { menuObjid } = req.params;
|
||||
const companyCode = req.user?.companyCode;
|
||||
|
||||
logger.info("📥 메뉴별 카테고리 컬럼 조회 요청", { menuObjid, companyCode });
|
||||
|
||||
if (!menuObjid) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: "메뉴 OBJID가 필요합니다.",
|
||||
});
|
||||
}
|
||||
|
||||
// 1. 형제 메뉴 조회
|
||||
const { getSiblingMenuObjids } = await import("../services/menuService");
|
||||
const siblingObjids = await getSiblingMenuObjids(parseInt(menuObjid));
|
||||
|
||||
logger.info("✅ 형제 메뉴 조회 완료", { siblingObjids });
|
||||
|
||||
// 2. 형제 메뉴들이 사용하는 테이블 조회
|
||||
const { getPool } = await import("../database/db");
|
||||
const pool = getPool();
|
||||
|
||||
const tablesQuery = `
|
||||
SELECT DISTINCT table_name
|
||||
FROM screen_definitions
|
||||
WHERE menu_objid = ANY($1)
|
||||
AND company_code = $2
|
||||
AND table_name IS NOT NULL
|
||||
`;
|
||||
|
||||
const tablesResult = await pool.query(tablesQuery, [siblingObjids, companyCode]);
|
||||
const tableNames = tablesResult.rows.map((row: any) => row.table_name);
|
||||
|
||||
logger.info("✅ 형제 메뉴 테이블 조회 완료", { tableNames });
|
||||
|
||||
if (tableNames.length === 0) {
|
||||
return res.json({
|
||||
success: true,
|
||||
data: [],
|
||||
message: "형제 메뉴에 연결된 테이블이 없습니다.",
|
||||
});
|
||||
}
|
||||
|
||||
// 3. 테이블들의 카테고리 타입 컬럼 조회
|
||||
const columnsQuery = `
|
||||
SELECT
|
||||
table_name AS "tableName",
|
||||
column_name AS "columnName",
|
||||
column_label AS "columnLabel",
|
||||
input_type AS "inputType"
|
||||
FROM table_type_columns
|
||||
WHERE table_name = ANY($1)
|
||||
AND company_code = $2
|
||||
AND input_type = 'category'
|
||||
ORDER BY table_name, column_name
|
||||
`;
|
||||
|
||||
const columnsResult = await pool.query(columnsQuery, [tableNames, companyCode]);
|
||||
|
||||
logger.info("✅ 카테고리 컬럼 조회 완료", {
|
||||
columnCount: columnsResult.rows.length
|
||||
});
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: columnsResult.rows,
|
||||
message: "카테고리 컬럼 조회 성공",
|
||||
});
|
||||
} catch (error: any) {
|
||||
logger.error("❌ 메뉴별 카테고리 컬럼 조회 실패", {
|
||||
error: error.message,
|
||||
errorStack: error.stack,
|
||||
});
|
||||
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: "카테고리 컬럼 조회에 실패했습니다.",
|
||||
error: error.message,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user