컴포넌트 리뉴얼 1.0
This commit is contained in:
@@ -3,6 +3,101 @@ import { AuthenticatedRequest } from "../types/auth";
|
||||
import { getPool } from "../database/db";
|
||||
import { logger } from "../utils/logger";
|
||||
|
||||
/**
|
||||
* 엔티티 옵션 조회 API (UnifiedSelect용)
|
||||
* GET /api/entity/:tableName/options
|
||||
*
|
||||
* Query Params:
|
||||
* - value: 값 컬럼 (기본: id)
|
||||
* - label: 표시 컬럼 (기본: name)
|
||||
*/
|
||||
export async function getEntityOptions(req: AuthenticatedRequest, res: Response) {
|
||||
try {
|
||||
const { tableName } = req.params;
|
||||
const { value = "id", label = "name" } = req.query;
|
||||
|
||||
// tableName 유효성 검증
|
||||
if (!tableName || tableName === "undefined" || tableName === "null") {
|
||||
logger.warn("엔티티 옵션 조회 실패: 테이블명이 없음", { tableName });
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: "테이블명이 지정되지 않았습니다.",
|
||||
});
|
||||
}
|
||||
|
||||
const companyCode = req.user!.companyCode;
|
||||
const pool = getPool();
|
||||
|
||||
// 테이블의 실제 컬럼 목록 조회
|
||||
const columnsResult = await pool.query(
|
||||
`SELECT column_name FROM information_schema.columns
|
||||
WHERE table_schema = 'public' AND table_name = $1`,
|
||||
[tableName]
|
||||
);
|
||||
const existingColumns = new Set(columnsResult.rows.map((r: any) => r.column_name));
|
||||
|
||||
// 요청된 컬럼 검증
|
||||
const valueColumn = existingColumns.has(value as string) ? value : "id";
|
||||
const labelColumn = existingColumns.has(label as string) ? label : "name";
|
||||
|
||||
// 둘 다 없으면 에러
|
||||
if (!existingColumns.has(valueColumn as string)) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: `테이블 "${tableName}"에 값 컬럼 "${value}"이 존재하지 않습니다.`,
|
||||
});
|
||||
}
|
||||
|
||||
// label 컬럼이 없으면 value 컬럼을 label로도 사용
|
||||
const effectiveLabelColumn = existingColumns.has(labelColumn as string) ? labelColumn : valueColumn;
|
||||
|
||||
// WHERE 조건 (멀티테넌시)
|
||||
const whereConditions: string[] = [];
|
||||
const params: any[] = [];
|
||||
let paramIndex = 1;
|
||||
|
||||
if (companyCode !== "*" && existingColumns.has("company_code")) {
|
||||
whereConditions.push(`company_code = $${paramIndex}`);
|
||||
params.push(companyCode);
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
const whereClause = whereConditions.length > 0
|
||||
? `WHERE ${whereConditions.join(" AND ")}`
|
||||
: "";
|
||||
|
||||
// 쿼리 실행 (최대 500개)
|
||||
const query = `
|
||||
SELECT ${valueColumn} as value, ${effectiveLabelColumn} as label
|
||||
FROM ${tableName}
|
||||
${whereClause}
|
||||
ORDER BY ${effectiveLabelColumn} ASC
|
||||
LIMIT 500
|
||||
`;
|
||||
|
||||
const result = await pool.query(query, params);
|
||||
|
||||
logger.info("엔티티 옵션 조회 성공", {
|
||||
tableName,
|
||||
valueColumn,
|
||||
labelColumn: effectiveLabelColumn,
|
||||
companyCode,
|
||||
rowCount: result.rowCount,
|
||||
});
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: result.rows,
|
||||
});
|
||||
} catch (error: any) {
|
||||
logger.error("엔티티 옵션 조회 오류", {
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
});
|
||||
res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 엔티티 검색 API
|
||||
* GET /api/entity-search/:tableName
|
||||
|
||||
Reference in New Issue
Block a user