연쇄관계 관리
This commit is contained in:
719
backend-node/src/controllers/cascadingRelationController.ts
Normal file
719
backend-node/src/controllers/cascadingRelationController.ts
Normal file
@@ -0,0 +1,719 @@
|
||||
import { Request, Response } from "express";
|
||||
import { getPool } from "../database/db";
|
||||
import { logger } from "../utils/logger";
|
||||
|
||||
const pool = getPool();
|
||||
|
||||
/**
|
||||
* 연쇄 관계 목록 조회
|
||||
*/
|
||||
export const getCascadingRelations = async (req: Request, res: Response) => {
|
||||
try {
|
||||
const companyCode = req.user?.companyCode || "*";
|
||||
const { isActive } = req.query;
|
||||
|
||||
let query = `
|
||||
SELECT
|
||||
relation_id,
|
||||
relation_code,
|
||||
relation_name,
|
||||
description,
|
||||
parent_table,
|
||||
parent_value_column,
|
||||
parent_label_column,
|
||||
child_table,
|
||||
child_filter_column,
|
||||
child_value_column,
|
||||
child_label_column,
|
||||
child_order_column,
|
||||
child_order_direction,
|
||||
empty_parent_message,
|
||||
no_options_message,
|
||||
loading_message,
|
||||
clear_on_parent_change,
|
||||
company_code,
|
||||
is_active,
|
||||
created_by,
|
||||
created_date,
|
||||
updated_by,
|
||||
updated_date
|
||||
FROM cascading_relation
|
||||
WHERE 1=1
|
||||
`;
|
||||
|
||||
const params: any[] = [];
|
||||
let paramIndex = 1;
|
||||
|
||||
// 멀티테넌시 필터링
|
||||
if (companyCode !== "*") {
|
||||
query += ` AND (company_code = $${paramIndex} OR company_code = '*')`;
|
||||
params.push(companyCode);
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
// 활성 상태 필터링
|
||||
if (isActive !== undefined) {
|
||||
query += ` AND is_active = $${paramIndex}`;
|
||||
params.push(isActive);
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
query += ` ORDER BY relation_name ASC`;
|
||||
|
||||
const result = await pool.query(query, params);
|
||||
|
||||
logger.info("연쇄 관계 목록 조회", {
|
||||
companyCode,
|
||||
count: result.rowCount,
|
||||
});
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
data: result.rows,
|
||||
});
|
||||
} catch (error: any) {
|
||||
logger.error("연쇄 관계 목록 조회 실패", { error: error.message });
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
message: "연쇄 관계 목록 조회에 실패했습니다.",
|
||||
error: error.message,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 연쇄 관계 상세 조회
|
||||
*/
|
||||
export const getCascadingRelationById = async (req: Request, res: Response) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const companyCode = req.user?.companyCode || "*";
|
||||
|
||||
let query = `
|
||||
SELECT
|
||||
relation_id,
|
||||
relation_code,
|
||||
relation_name,
|
||||
description,
|
||||
parent_table,
|
||||
parent_value_column,
|
||||
parent_label_column,
|
||||
child_table,
|
||||
child_filter_column,
|
||||
child_value_column,
|
||||
child_label_column,
|
||||
child_order_column,
|
||||
child_order_direction,
|
||||
empty_parent_message,
|
||||
no_options_message,
|
||||
loading_message,
|
||||
clear_on_parent_change,
|
||||
company_code,
|
||||
is_active,
|
||||
created_by,
|
||||
created_date,
|
||||
updated_by,
|
||||
updated_date
|
||||
FROM cascading_relation
|
||||
WHERE relation_id = $1
|
||||
`;
|
||||
|
||||
const params: any[] = [id];
|
||||
|
||||
// 멀티테넌시 필터링
|
||||
if (companyCode !== "*") {
|
||||
query += ` AND (company_code = $2 OR company_code = '*')`;
|
||||
params.push(companyCode);
|
||||
}
|
||||
|
||||
const result = await pool.query(query, params);
|
||||
|
||||
if (result.rowCount === 0) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: "연쇄 관계를 찾을 수 없습니다.",
|
||||
});
|
||||
}
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
data: result.rows[0],
|
||||
});
|
||||
} catch (error: any) {
|
||||
logger.error("연쇄 관계 상세 조회 실패", { error: error.message });
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
message: "연쇄 관계 조회에 실패했습니다.",
|
||||
error: error.message,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 연쇄 관계 코드로 조회
|
||||
*/
|
||||
export const getCascadingRelationByCode = async (req: Request, res: Response) => {
|
||||
try {
|
||||
const { code } = req.params;
|
||||
const companyCode = req.user?.companyCode || "*";
|
||||
|
||||
let query = `
|
||||
SELECT
|
||||
relation_id,
|
||||
relation_code,
|
||||
relation_name,
|
||||
description,
|
||||
parent_table,
|
||||
parent_value_column,
|
||||
parent_label_column,
|
||||
child_table,
|
||||
child_filter_column,
|
||||
child_value_column,
|
||||
child_label_column,
|
||||
child_order_column,
|
||||
child_order_direction,
|
||||
empty_parent_message,
|
||||
no_options_message,
|
||||
loading_message,
|
||||
clear_on_parent_change,
|
||||
company_code,
|
||||
is_active
|
||||
FROM cascading_relation
|
||||
WHERE relation_code = $1
|
||||
AND is_active = 'Y'
|
||||
`;
|
||||
|
||||
const params: any[] = [code];
|
||||
|
||||
// 멀티테넌시 필터링 (회사 전용 관계 우선, 없으면 공통 관계)
|
||||
if (companyCode !== "*") {
|
||||
query += ` AND (company_code = $2 OR company_code = '*')`;
|
||||
params.push(companyCode);
|
||||
query += ` ORDER BY CASE WHEN company_code = $2 THEN 0 ELSE 1 END LIMIT 1`;
|
||||
} else {
|
||||
query += ` LIMIT 1`;
|
||||
}
|
||||
|
||||
const result = await pool.query(query, params);
|
||||
|
||||
if (result.rowCount === 0) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: "연쇄 관계를 찾을 수 없습니다.",
|
||||
});
|
||||
}
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
data: result.rows[0],
|
||||
});
|
||||
} catch (error: any) {
|
||||
logger.error("연쇄 관계 코드 조회 실패", { error: error.message });
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
message: "연쇄 관계 조회에 실패했습니다.",
|
||||
error: error.message,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 연쇄 관계 생성
|
||||
*/
|
||||
export const createCascadingRelation = async (req: Request, res: Response) => {
|
||||
try {
|
||||
const companyCode = req.user?.companyCode || "*";
|
||||
const userId = req.user?.userId || "system";
|
||||
|
||||
const {
|
||||
relationCode,
|
||||
relationName,
|
||||
description,
|
||||
parentTable,
|
||||
parentValueColumn,
|
||||
parentLabelColumn,
|
||||
childTable,
|
||||
childFilterColumn,
|
||||
childValueColumn,
|
||||
childLabelColumn,
|
||||
childOrderColumn,
|
||||
childOrderDirection,
|
||||
emptyParentMessage,
|
||||
noOptionsMessage,
|
||||
loadingMessage,
|
||||
clearOnParentChange,
|
||||
} = req.body;
|
||||
|
||||
// 필수 필드 검증
|
||||
if (!relationCode || !relationName || !parentTable || !parentValueColumn ||
|
||||
!childTable || !childFilterColumn || !childValueColumn || !childLabelColumn) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: "필수 필드가 누락되었습니다.",
|
||||
});
|
||||
}
|
||||
|
||||
// 중복 코드 체크
|
||||
const duplicateCheck = await pool.query(
|
||||
`SELECT relation_id FROM cascading_relation
|
||||
WHERE relation_code = $1 AND company_code = $2`,
|
||||
[relationCode, companyCode]
|
||||
);
|
||||
|
||||
if (duplicateCheck.rowCount && duplicateCheck.rowCount > 0) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: "이미 존재하는 관계 코드입니다.",
|
||||
});
|
||||
}
|
||||
|
||||
const query = `
|
||||
INSERT INTO cascading_relation (
|
||||
relation_code,
|
||||
relation_name,
|
||||
description,
|
||||
parent_table,
|
||||
parent_value_column,
|
||||
parent_label_column,
|
||||
child_table,
|
||||
child_filter_column,
|
||||
child_value_column,
|
||||
child_label_column,
|
||||
child_order_column,
|
||||
child_order_direction,
|
||||
empty_parent_message,
|
||||
no_options_message,
|
||||
loading_message,
|
||||
clear_on_parent_change,
|
||||
company_code,
|
||||
is_active,
|
||||
created_by,
|
||||
created_date
|
||||
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, 'Y', $18, CURRENT_TIMESTAMP)
|
||||
RETURNING *
|
||||
`;
|
||||
|
||||
const result = await pool.query(query, [
|
||||
relationCode,
|
||||
relationName,
|
||||
description || null,
|
||||
parentTable,
|
||||
parentValueColumn,
|
||||
parentLabelColumn || null,
|
||||
childTable,
|
||||
childFilterColumn,
|
||||
childValueColumn,
|
||||
childLabelColumn,
|
||||
childOrderColumn || null,
|
||||
childOrderDirection || "ASC",
|
||||
emptyParentMessage || "상위 항목을 먼저 선택하세요",
|
||||
noOptionsMessage || "선택 가능한 항목이 없습니다",
|
||||
loadingMessage || "로딩 중...",
|
||||
clearOnParentChange !== false ? "Y" : "N",
|
||||
companyCode,
|
||||
userId,
|
||||
]);
|
||||
|
||||
logger.info("연쇄 관계 생성", {
|
||||
relationId: result.rows[0].relation_id,
|
||||
relationCode,
|
||||
companyCode,
|
||||
userId,
|
||||
});
|
||||
|
||||
return res.status(201).json({
|
||||
success: true,
|
||||
data: result.rows[0],
|
||||
message: "연쇄 관계가 생성되었습니다.",
|
||||
});
|
||||
} catch (error: any) {
|
||||
logger.error("연쇄 관계 생성 실패", { error: error.message });
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
message: "연쇄 관계 생성에 실패했습니다.",
|
||||
error: error.message,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 연쇄 관계 수정
|
||||
*/
|
||||
export const updateCascadingRelation = async (req: Request, res: Response) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const companyCode = req.user?.companyCode || "*";
|
||||
const userId = req.user?.userId || "system";
|
||||
|
||||
const {
|
||||
relationName,
|
||||
description,
|
||||
parentTable,
|
||||
parentValueColumn,
|
||||
parentLabelColumn,
|
||||
childTable,
|
||||
childFilterColumn,
|
||||
childValueColumn,
|
||||
childLabelColumn,
|
||||
childOrderColumn,
|
||||
childOrderDirection,
|
||||
emptyParentMessage,
|
||||
noOptionsMessage,
|
||||
loadingMessage,
|
||||
clearOnParentChange,
|
||||
isActive,
|
||||
} = req.body;
|
||||
|
||||
// 권한 체크
|
||||
const existingCheck = await pool.query(
|
||||
`SELECT relation_id, company_code FROM cascading_relation WHERE relation_id = $1`,
|
||||
[id]
|
||||
);
|
||||
|
||||
if (existingCheck.rowCount === 0) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: "연쇄 관계를 찾을 수 없습니다.",
|
||||
});
|
||||
}
|
||||
|
||||
// 다른 회사의 데이터는 수정 불가 (최고 관리자 제외)
|
||||
const existingCompanyCode = existingCheck.rows[0].company_code;
|
||||
if (companyCode !== "*" && existingCompanyCode !== companyCode && existingCompanyCode !== "*") {
|
||||
return res.status(403).json({
|
||||
success: false,
|
||||
message: "수정 권한이 없습니다.",
|
||||
});
|
||||
}
|
||||
|
||||
const query = `
|
||||
UPDATE cascading_relation SET
|
||||
relation_name = COALESCE($1, relation_name),
|
||||
description = COALESCE($2, description),
|
||||
parent_table = COALESCE($3, parent_table),
|
||||
parent_value_column = COALESCE($4, parent_value_column),
|
||||
parent_label_column = COALESCE($5, parent_label_column),
|
||||
child_table = COALESCE($6, child_table),
|
||||
child_filter_column = COALESCE($7, child_filter_column),
|
||||
child_value_column = COALESCE($8, child_value_column),
|
||||
child_label_column = COALESCE($9, child_label_column),
|
||||
child_order_column = COALESCE($10, child_order_column),
|
||||
child_order_direction = COALESCE($11, child_order_direction),
|
||||
empty_parent_message = COALESCE($12, empty_parent_message),
|
||||
no_options_message = COALESCE($13, no_options_message),
|
||||
loading_message = COALESCE($14, loading_message),
|
||||
clear_on_parent_change = COALESCE($15, clear_on_parent_change),
|
||||
is_active = COALESCE($16, is_active),
|
||||
updated_by = $17,
|
||||
updated_date = CURRENT_TIMESTAMP
|
||||
WHERE relation_id = $18
|
||||
RETURNING *
|
||||
`;
|
||||
|
||||
const result = await pool.query(query, [
|
||||
relationName,
|
||||
description,
|
||||
parentTable,
|
||||
parentValueColumn,
|
||||
parentLabelColumn,
|
||||
childTable,
|
||||
childFilterColumn,
|
||||
childValueColumn,
|
||||
childLabelColumn,
|
||||
childOrderColumn,
|
||||
childOrderDirection,
|
||||
emptyParentMessage,
|
||||
noOptionsMessage,
|
||||
loadingMessage,
|
||||
clearOnParentChange !== undefined ? (clearOnParentChange ? "Y" : "N") : null,
|
||||
isActive !== undefined ? (isActive ? "Y" : "N") : null,
|
||||
userId,
|
||||
id,
|
||||
]);
|
||||
|
||||
logger.info("연쇄 관계 수정", {
|
||||
relationId: id,
|
||||
companyCode,
|
||||
userId,
|
||||
});
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
data: result.rows[0],
|
||||
message: "연쇄 관계가 수정되었습니다.",
|
||||
});
|
||||
} catch (error: any) {
|
||||
logger.error("연쇄 관계 수정 실패", { error: error.message });
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
message: "연쇄 관계 수정에 실패했습니다.",
|
||||
error: error.message,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 연쇄 관계 삭제
|
||||
*/
|
||||
export const deleteCascadingRelation = async (req: Request, res: Response) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const companyCode = req.user?.companyCode || "*";
|
||||
const userId = req.user?.userId || "system";
|
||||
|
||||
// 권한 체크
|
||||
const existingCheck = await pool.query(
|
||||
`SELECT relation_id, company_code FROM cascading_relation WHERE relation_id = $1`,
|
||||
[id]
|
||||
);
|
||||
|
||||
if (existingCheck.rowCount === 0) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: "연쇄 관계를 찾을 수 없습니다.",
|
||||
});
|
||||
}
|
||||
|
||||
// 다른 회사의 데이터는 삭제 불가 (최고 관리자 제외)
|
||||
const existingCompanyCode = existingCheck.rows[0].company_code;
|
||||
if (companyCode !== "*" && existingCompanyCode !== companyCode && existingCompanyCode !== "*") {
|
||||
return res.status(403).json({
|
||||
success: false,
|
||||
message: "삭제 권한이 없습니다.",
|
||||
});
|
||||
}
|
||||
|
||||
// 소프트 삭제 (is_active = 'N')
|
||||
await pool.query(
|
||||
`UPDATE cascading_relation SET is_active = 'N', updated_by = $1, updated_date = CURRENT_TIMESTAMP WHERE relation_id = $2`,
|
||||
[userId, id]
|
||||
);
|
||||
|
||||
logger.info("연쇄 관계 삭제", {
|
||||
relationId: id,
|
||||
companyCode,
|
||||
userId,
|
||||
});
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
message: "연쇄 관계가 삭제되었습니다.",
|
||||
});
|
||||
} catch (error: any) {
|
||||
logger.error("연쇄 관계 삭제 실패", { error: error.message });
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
message: "연쇄 관계 삭제에 실패했습니다.",
|
||||
error: error.message,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 🆕 연쇄 관계로 부모 옵션 조회 (상위 선택 역할용)
|
||||
* parent_table에서 전체 옵션을 조회합니다.
|
||||
*/
|
||||
export const getParentOptions = async (req: Request, res: Response) => {
|
||||
try {
|
||||
const { code } = req.params;
|
||||
const companyCode = req.user?.companyCode || "*";
|
||||
|
||||
// 관계 정보 조회
|
||||
let relationQuery = `
|
||||
SELECT
|
||||
parent_table,
|
||||
parent_value_column,
|
||||
parent_label_column
|
||||
FROM cascading_relation
|
||||
WHERE relation_code = $1
|
||||
AND is_active = 'Y'
|
||||
`;
|
||||
|
||||
const relationParams: any[] = [code];
|
||||
|
||||
if (companyCode !== "*") {
|
||||
relationQuery += ` AND (company_code = $2 OR company_code = '*')`;
|
||||
relationParams.push(companyCode);
|
||||
relationQuery += ` ORDER BY CASE WHEN company_code = $2 THEN 0 ELSE 1 END LIMIT 1`;
|
||||
} else {
|
||||
relationQuery += ` LIMIT 1`;
|
||||
}
|
||||
|
||||
const relationResult = await pool.query(relationQuery, relationParams);
|
||||
|
||||
if (relationResult.rowCount === 0) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: "연쇄 관계를 찾을 수 없습니다.",
|
||||
});
|
||||
}
|
||||
|
||||
const relation = relationResult.rows[0];
|
||||
|
||||
// 라벨 컬럼이 없으면 값 컬럼 사용
|
||||
const labelColumn = relation.parent_label_column || relation.parent_value_column;
|
||||
|
||||
// 부모 옵션 조회
|
||||
let optionsQuery = `
|
||||
SELECT
|
||||
${relation.parent_value_column} as value,
|
||||
${labelColumn} as label
|
||||
FROM ${relation.parent_table}
|
||||
WHERE 1=1
|
||||
`;
|
||||
|
||||
// 멀티테넌시 적용 (테이블에 company_code가 있는 경우)
|
||||
const tableInfoResult = await pool.query(
|
||||
`SELECT column_name FROM information_schema.columns
|
||||
WHERE table_name = $1 AND column_name = 'company_code'`,
|
||||
[relation.parent_table]
|
||||
);
|
||||
|
||||
const optionsParams: any[] = [];
|
||||
|
||||
if (tableInfoResult.rowCount && tableInfoResult.rowCount > 0 && companyCode !== "*") {
|
||||
optionsQuery += ` AND (company_code = $1 OR company_code = '*')`;
|
||||
optionsParams.push(companyCode);
|
||||
}
|
||||
|
||||
// status 컬럼이 있으면 활성 상태만 조회
|
||||
const statusInfoResult = await pool.query(
|
||||
`SELECT column_name FROM information_schema.columns
|
||||
WHERE table_name = $1 AND column_name = 'status'`,
|
||||
[relation.parent_table]
|
||||
);
|
||||
|
||||
if (statusInfoResult.rowCount && statusInfoResult.rowCount > 0) {
|
||||
optionsQuery += ` AND (status IS NULL OR status != 'N')`;
|
||||
}
|
||||
|
||||
// 정렬
|
||||
optionsQuery += ` ORDER BY ${labelColumn} ASC`;
|
||||
|
||||
const optionsResult = await pool.query(optionsQuery, optionsParams);
|
||||
|
||||
logger.info("부모 옵션 조회", {
|
||||
relationCode: code,
|
||||
parentTable: relation.parent_table,
|
||||
optionsCount: optionsResult.rowCount,
|
||||
});
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
data: optionsResult.rows,
|
||||
});
|
||||
} catch (error: any) {
|
||||
logger.error("부모 옵션 조회 실패", { error: error.message });
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
message: "부모 옵션 조회에 실패했습니다.",
|
||||
error: error.message,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 연쇄 관계로 자식 옵션 조회
|
||||
* 실제 연쇄 드롭다운에서 사용하는 API
|
||||
*/
|
||||
export const getCascadingOptions = async (req: Request, res: Response) => {
|
||||
try {
|
||||
const { code } = req.params;
|
||||
const { parentValue } = req.query;
|
||||
const companyCode = req.user?.companyCode || "*";
|
||||
|
||||
if (!parentValue) {
|
||||
return res.json({
|
||||
success: true,
|
||||
data: [],
|
||||
message: "부모 값이 없습니다.",
|
||||
});
|
||||
}
|
||||
|
||||
// 관계 정보 조회
|
||||
let relationQuery = `
|
||||
SELECT
|
||||
child_table,
|
||||
child_filter_column,
|
||||
child_value_column,
|
||||
child_label_column,
|
||||
child_order_column,
|
||||
child_order_direction
|
||||
FROM cascading_relation
|
||||
WHERE relation_code = $1
|
||||
AND is_active = 'Y'
|
||||
`;
|
||||
|
||||
const relationParams: any[] = [code];
|
||||
|
||||
if (companyCode !== "*") {
|
||||
relationQuery += ` AND (company_code = $2 OR company_code = '*')`;
|
||||
relationParams.push(companyCode);
|
||||
relationQuery += ` ORDER BY CASE WHEN company_code = $2 THEN 0 ELSE 1 END LIMIT 1`;
|
||||
} else {
|
||||
relationQuery += ` LIMIT 1`;
|
||||
}
|
||||
|
||||
const relationResult = await pool.query(relationQuery, relationParams);
|
||||
|
||||
if (relationResult.rowCount === 0) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: "연쇄 관계를 찾을 수 없습니다.",
|
||||
});
|
||||
}
|
||||
|
||||
const relation = relationResult.rows[0];
|
||||
|
||||
// 자식 옵션 조회
|
||||
let optionsQuery = `
|
||||
SELECT
|
||||
${relation.child_value_column} as value,
|
||||
${relation.child_label_column} as label
|
||||
FROM ${relation.child_table}
|
||||
WHERE ${relation.child_filter_column} = $1
|
||||
`;
|
||||
|
||||
// 멀티테넌시 적용 (테이블에 company_code가 있는 경우)
|
||||
const tableInfoResult = await pool.query(
|
||||
`SELECT column_name FROM information_schema.columns
|
||||
WHERE table_name = $1 AND column_name = 'company_code'`,
|
||||
[relation.child_table]
|
||||
);
|
||||
|
||||
const optionsParams: any[] = [parentValue];
|
||||
|
||||
if (tableInfoResult.rowCount && tableInfoResult.rowCount > 0 && companyCode !== "*") {
|
||||
optionsQuery += ` AND (company_code = $2 OR company_code = '*')`;
|
||||
optionsParams.push(companyCode);
|
||||
}
|
||||
|
||||
// 정렬
|
||||
if (relation.child_order_column) {
|
||||
optionsQuery += ` ORDER BY ${relation.child_order_column} ${relation.child_order_direction || "ASC"}`;
|
||||
} else {
|
||||
optionsQuery += ` ORDER BY ${relation.child_label_column} ASC`;
|
||||
}
|
||||
|
||||
const optionsResult = await pool.query(optionsQuery, optionsParams);
|
||||
|
||||
logger.info("연쇄 옵션 조회", {
|
||||
relationCode: code,
|
||||
parentValue,
|
||||
optionsCount: optionsResult.rowCount,
|
||||
});
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
data: optionsResult.rows,
|
||||
});
|
||||
} catch (error: any) {
|
||||
logger.error("연쇄 옵션 조회 실패", { error: error.message });
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
message: "연쇄 옵션 조회에 실패했습니다.",
|
||||
error: error.message,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user