연쇄관계 자식 라벨표시
This commit is contained in:
@@ -76,7 +76,9 @@ export const getCategoryValueCascadingGroups = async (
|
||||
data: result.rows,
|
||||
});
|
||||
} catch (error: any) {
|
||||
logger.error("카테고리 값 연쇄관계 그룹 목록 조회 실패", { error: error.message });
|
||||
logger.error("카테고리 값 연쇄관계 그룹 목록 조회 실패", {
|
||||
error: error.message,
|
||||
});
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
message: "카테고리 값 연쇄관계 그룹 목록 조회에 실패했습니다.",
|
||||
@@ -175,7 +177,9 @@ export const getCategoryValueCascadingGroupById = async (
|
||||
},
|
||||
});
|
||||
} catch (error: any) {
|
||||
logger.error("카테고리 값 연쇄관계 그룹 상세 조회 실패", { error: error.message });
|
||||
logger.error("카테고리 값 연쇄관계 그룹 상세 조회 실패", {
|
||||
error: error.message,
|
||||
});
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
message: "카테고리 값 연쇄관계 그룹 조회에 실패했습니다.",
|
||||
@@ -240,7 +244,9 @@ export const getCategoryValueCascadingByCode = async (
|
||||
data: result.rows[0],
|
||||
});
|
||||
} catch (error: any) {
|
||||
logger.error("카테고리 값 연쇄관계 코드 조회 실패", { error: error.message });
|
||||
logger.error("카테고리 값 연쇄관계 코드 조회 실패", {
|
||||
error: error.message,
|
||||
});
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
message: "카테고리 값 연쇄관계 조회에 실패했습니다.",
|
||||
@@ -277,7 +283,14 @@ export const createCategoryValueCascadingGroup = async (
|
||||
} = req.body;
|
||||
|
||||
// 필수 필드 검증
|
||||
if (!relationCode || !relationName || !parentTableName || !parentColumnName || !childTableName || !childColumnName) {
|
||||
if (
|
||||
!relationCode ||
|
||||
!relationName ||
|
||||
!parentTableName ||
|
||||
!parentColumnName ||
|
||||
!childTableName ||
|
||||
!childColumnName
|
||||
) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: "필수 필드가 누락되었습니다.",
|
||||
@@ -352,7 +365,9 @@ export const createCategoryValueCascadingGroup = async (
|
||||
message: "카테고리 값 연쇄관계 그룹이 생성되었습니다.",
|
||||
});
|
||||
} catch (error: any) {
|
||||
logger.error("카테고리 값 연쇄관계 그룹 생성 실패", { error: error.message });
|
||||
logger.error("카테고리 값 연쇄관계 그룹 생성 실패", {
|
||||
error: error.message,
|
||||
});
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
message: "카테고리 값 연쇄관계 그룹 생성에 실패했습니다.",
|
||||
@@ -403,7 +418,11 @@ export const updateCategoryValueCascadingGroup = async (
|
||||
}
|
||||
|
||||
const existingCompanyCode = existingCheck.rows[0].company_code;
|
||||
if (companyCode !== "*" && existingCompanyCode !== companyCode && existingCompanyCode !== "*") {
|
||||
if (
|
||||
companyCode !== "*" &&
|
||||
existingCompanyCode !== companyCode &&
|
||||
existingCompanyCode !== "*"
|
||||
) {
|
||||
return res.status(403).json({
|
||||
success: false,
|
||||
message: "수정 권한이 없습니다.",
|
||||
@@ -440,7 +459,11 @@ export const updateCategoryValueCascadingGroup = async (
|
||||
childTableName,
|
||||
childColumnName,
|
||||
childMenuObjid,
|
||||
clearOnParentChange !== undefined ? (clearOnParentChange ? "Y" : "N") : null,
|
||||
clearOnParentChange !== undefined
|
||||
? clearOnParentChange
|
||||
? "Y"
|
||||
: "N"
|
||||
: null,
|
||||
showGroupLabel !== undefined ? (showGroupLabel ? "Y" : "N") : null,
|
||||
emptyParentMessage,
|
||||
noOptionsMessage,
|
||||
@@ -461,7 +484,9 @@ export const updateCategoryValueCascadingGroup = async (
|
||||
message: "카테고리 값 연쇄관계 그룹이 수정되었습니다.",
|
||||
});
|
||||
} catch (error: any) {
|
||||
logger.error("카테고리 값 연쇄관계 그룹 수정 실패", { error: error.message });
|
||||
logger.error("카테고리 값 연쇄관계 그룹 수정 실패", {
|
||||
error: error.message,
|
||||
});
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
message: "카테고리 값 연쇄관계 그룹 수정에 실패했습니다.",
|
||||
@@ -496,7 +521,11 @@ export const deleteCategoryValueCascadingGroup = async (
|
||||
}
|
||||
|
||||
const existingCompanyCode = existingCheck.rows[0].company_code;
|
||||
if (companyCode !== "*" && existingCompanyCode !== companyCode && existingCompanyCode !== "*") {
|
||||
if (
|
||||
companyCode !== "*" &&
|
||||
existingCompanyCode !== companyCode &&
|
||||
existingCompanyCode !== "*"
|
||||
) {
|
||||
return res.status(403).json({
|
||||
success: false,
|
||||
message: "삭제 권한이 없습니다.",
|
||||
@@ -522,7 +551,9 @@ export const deleteCategoryValueCascadingGroup = async (
|
||||
message: "카테고리 값 연쇄관계 그룹이 삭제되었습니다.",
|
||||
});
|
||||
} catch (error: any) {
|
||||
logger.error("카테고리 값 연쇄관계 그룹 삭제 실패", { error: error.message });
|
||||
logger.error("카테고리 값 연쇄관계 그룹 삭제 실패", {
|
||||
error: error.message,
|
||||
});
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
message: "카테고리 값 연쇄관계 그룹 삭제에 실패했습니다.",
|
||||
@@ -620,7 +651,9 @@ export const saveCategoryValueCascadingMappings = async (
|
||||
client.release();
|
||||
}
|
||||
} catch (error: any) {
|
||||
logger.error("카테고리 값 연쇄관계 매핑 저장 실패", { error: error.message });
|
||||
logger.error("카테고리 값 연쇄관계 매핑 저장 실패", {
|
||||
error: error.message,
|
||||
});
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
message: "카테고리 값 연쇄관계 매핑 저장에 실패했습니다.",
|
||||
@@ -649,12 +682,15 @@ export const getCategoryValueCascadingOptions = async (
|
||||
|
||||
// 다중 부모값 파싱
|
||||
let parentValueArray: string[] = [];
|
||||
|
||||
|
||||
if (parentValues) {
|
||||
if (Array.isArray(parentValues)) {
|
||||
parentValueArray = parentValues.map(v => String(v));
|
||||
parentValueArray = parentValues.map((v) => String(v));
|
||||
} else {
|
||||
parentValueArray = String(parentValues).split(',').map(v => v.trim()).filter(v => v);
|
||||
parentValueArray = String(parentValues)
|
||||
.split(",")
|
||||
.map((v) => v.trim())
|
||||
.filter((v) => v);
|
||||
}
|
||||
} else if (parentValue) {
|
||||
parentValueArray = [String(parentValue)];
|
||||
@@ -696,8 +732,10 @@ export const getCategoryValueCascadingOptions = async (
|
||||
const group = groupResult.rows[0];
|
||||
|
||||
// 매핑된 자식 값 조회 (다중 부모값에 대해 IN 절 사용)
|
||||
const placeholders = parentValueArray.map((_, idx) => `$${idx + 2}`).join(', ');
|
||||
|
||||
const placeholders = parentValueArray
|
||||
.map((_, idx) => `$${idx + 2}`)
|
||||
.join(", ");
|
||||
|
||||
const optionsQuery = `
|
||||
SELECT DISTINCT
|
||||
child_value_code as value,
|
||||
@@ -712,7 +750,10 @@ export const getCategoryValueCascadingOptions = async (
|
||||
ORDER BY parent_value_code, display_order, child_value_label
|
||||
`;
|
||||
|
||||
const optionsResult = await pool.query(optionsQuery, [group.group_id, ...parentValueArray]);
|
||||
const optionsResult = await pool.query(optionsQuery, [
|
||||
group.group_id,
|
||||
...parentValueArray,
|
||||
]);
|
||||
|
||||
logger.info("카테고리 값 연쇄 옵션 조회", {
|
||||
relationCode: code,
|
||||
@@ -723,7 +764,7 @@ export const getCategoryValueCascadingOptions = async (
|
||||
return res.json({
|
||||
success: true,
|
||||
data: optionsResult.rows,
|
||||
showGroupLabel: group.show_group_label === 'Y',
|
||||
showGroupLabel: group.show_group_label === "Y",
|
||||
});
|
||||
} catch (error: any) {
|
||||
logger.error("카테고리 값 연쇄 옵션 조회 실패", { error: error.message });
|
||||
@@ -789,7 +830,10 @@ export const getCategoryValueCascadingParentOptions = async (
|
||||
AND is_active = true
|
||||
`;
|
||||
|
||||
const optionsParams: any[] = [group.parent_table_name, group.parent_column_name];
|
||||
const optionsParams: any[] = [
|
||||
group.parent_table_name,
|
||||
group.parent_column_name,
|
||||
];
|
||||
let paramIndex = 3;
|
||||
|
||||
// 메뉴 스코프 적용
|
||||
@@ -884,7 +928,10 @@ export const getCategoryValueCascadingChildOptions = async (
|
||||
AND is_active = true
|
||||
`;
|
||||
|
||||
const optionsParams: any[] = [group.child_table_name, group.child_column_name];
|
||||
const optionsParams: any[] = [
|
||||
group.child_table_name,
|
||||
group.child_column_name,
|
||||
];
|
||||
let paramIndex = 3;
|
||||
|
||||
// 메뉴 스코프 적용
|
||||
@@ -925,3 +972,91 @@ export const getCategoryValueCascadingChildOptions = async (
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 테이블명으로 해당 테이블의 모든 연쇄관계 매핑 조회
|
||||
* (테이블 목록에서 코드→라벨 변환에 사용)
|
||||
*/
|
||||
export const getCategoryValueCascadingMappingsByTable = async (
|
||||
req: AuthenticatedRequest,
|
||||
res: Response
|
||||
) => {
|
||||
try {
|
||||
const { tableName } = req.params;
|
||||
const companyCode = req.user?.companyCode || "*";
|
||||
|
||||
if (!tableName) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: "테이블명이 필요합니다.",
|
||||
});
|
||||
}
|
||||
|
||||
// 해당 테이블이 자식 테이블인 연쇄관계 그룹 찾기
|
||||
let groupQuery = `
|
||||
SELECT
|
||||
group_id,
|
||||
relation_code,
|
||||
child_column_name
|
||||
FROM category_value_cascading_group
|
||||
WHERE child_table_name = $1
|
||||
AND is_active = 'Y'
|
||||
`;
|
||||
const groupParams: any[] = [tableName];
|
||||
let paramIndex = 2;
|
||||
|
||||
// 멀티테넌시 적용
|
||||
if (companyCode !== "*") {
|
||||
groupQuery += ` AND (company_code = $${paramIndex} OR company_code = '*')`;
|
||||
groupParams.push(companyCode);
|
||||
}
|
||||
|
||||
const groupResult = await pool.query(groupQuery, groupParams);
|
||||
|
||||
if (groupResult.rowCount === 0) {
|
||||
// 연쇄관계가 없으면 빈 객체 반환
|
||||
return res.json({
|
||||
success: true,
|
||||
data: {},
|
||||
});
|
||||
}
|
||||
|
||||
// 각 그룹의 매핑 조회
|
||||
const mappings: Record<string, Array<{ code: string; label: string }>> = {};
|
||||
|
||||
for (const group of groupResult.rows) {
|
||||
const mappingQuery = `
|
||||
SELECT DISTINCT
|
||||
child_value_code as code,
|
||||
child_value_label as label
|
||||
FROM category_value_cascading_mapping
|
||||
WHERE group_id = $1
|
||||
AND is_active = 'Y'
|
||||
ORDER BY child_value_label
|
||||
`;
|
||||
|
||||
const mappingResult = await pool.query(mappingQuery, [group.group_id]);
|
||||
|
||||
if (mappingResult.rowCount && mappingResult.rowCount > 0) {
|
||||
mappings[group.child_column_name] = mappingResult.rows;
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("테이블별 연쇄관계 매핑 조회", {
|
||||
tableName,
|
||||
groupCount: groupResult.rowCount,
|
||||
columnMappings: Object.keys(mappings),
|
||||
});
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
data: mappings,
|
||||
});
|
||||
} catch (error: any) {
|
||||
logger.error("테이블별 연쇄관계 매핑 조회 실패", { error: error.message });
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
message: "연쇄관계 매핑 조회에 실패했습니다.",
|
||||
error: error.message,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
getCategoryValueCascadingOptions,
|
||||
getCategoryValueCascadingParentOptions,
|
||||
getCategoryValueCascadingChildOptions,
|
||||
getCategoryValueCascadingMappingsByTable,
|
||||
} from "../controllers/categoryValueCascadingController";
|
||||
import { authenticateToken } from "../middleware/authMiddleware";
|
||||
|
||||
@@ -60,5 +61,14 @@ router.get("/child-options/:code", getCategoryValueCascadingChildOptions);
|
||||
// 연쇄 옵션 조회 (부모 값 기반 자식 옵션)
|
||||
router.get("/options/:code", getCategoryValueCascadingOptions);
|
||||
|
||||
export default router;
|
||||
// ============================================
|
||||
// 테이블별 매핑 조회 (테이블 목록 표시용)
|
||||
// ============================================
|
||||
|
||||
// 테이블명으로 해당 테이블의 모든 연쇄관계 매핑 조회
|
||||
router.get(
|
||||
"/table/:tableName/mappings",
|
||||
getCategoryValueCascadingMappingsByTable
|
||||
);
|
||||
|
||||
export default router;
|
||||
|
||||
Reference in New Issue
Block a user