ERP-node/backend-node/src/controllers/entitySearchController.ts

119 lines
3.3 KiB
TypeScript
Raw Normal View History

import { Request, Response } from "express";
import { getPool } from "../database/db";
import { logger } from "../utils/logger";
/**
* API
* GET /api/entity-search/:tableName
*/
export async function searchEntity(req: Request, res: Response) {
try {
const { tableName } = req.params;
const {
searchText = "",
searchFields = "",
filterCondition = "{}",
page = "1",
limit = "20",
} = req.query;
// tableName 유효성 검증
if (!tableName || tableName === "undefined" || tableName === "null") {
logger.warn("엔티티 검색 실패: 테이블명이 없음", { tableName });
return res.status(400).json({
success: false,
message: "테이블명이 지정되지 않았습니다. 컴포넌트 설정에서 sourceTable을 확인해주세요.",
});
}
// 멀티테넌시
const companyCode = req.user!.companyCode;
// 검색 필드 파싱
const fields = searchFields
? (searchFields as string).split(",").map((f) => f.trim())
: [];
// WHERE 조건 생성
const whereConditions: string[] = [];
const params: any[] = [];
let paramIndex = 1;
// 멀티테넌시 필터링
if (companyCode !== "*") {
whereConditions.push(`company_code = $${paramIndex}`);
params.push(companyCode);
paramIndex++;
}
// 검색 조건
if (searchText && fields.length > 0) {
const searchConditions = fields.map((field) => {
const condition = `${field}::text ILIKE $${paramIndex}`;
paramIndex++;
return condition;
});
whereConditions.push(`(${searchConditions.join(" OR ")})`);
// 검색어 파라미터 추가
fields.forEach(() => {
params.push(`%${searchText}%`);
});
}
// 추가 필터 조건
const additionalFilter = JSON.parse(filterCondition as string);
for (const [key, value] of Object.entries(additionalFilter)) {
whereConditions.push(`${key} = $${paramIndex}`);
params.push(value);
paramIndex++;
}
// 페이징
const offset = (parseInt(page as string) - 1) * parseInt(limit as string);
const whereClause =
whereConditions.length > 0
? `WHERE ${whereConditions.join(" AND ")}`
: "";
// 쿼리 실행
const pool = getPool();
const countQuery = `SELECT COUNT(*) FROM ${tableName} ${whereClause}`;
const dataQuery = `
SELECT * FROM ${tableName} ${whereClause}
ORDER BY id DESC
LIMIT $${paramIndex} OFFSET $${paramIndex + 1}
`;
params.push(parseInt(limit as string));
params.push(offset);
const countResult = await pool.query(
countQuery,
params.slice(0, params.length - 2)
);
const dataResult = await pool.query(dataQuery, params);
logger.info("엔티티 검색 성공", {
tableName,
searchText,
companyCode,
rowCount: dataResult.rowCount,
});
res.json({
success: true,
data: dataResult.rows,
pagination: {
total: parseInt(countResult.rows[0].count),
page: parseInt(page as string),
limit: parseInt(limit as string),
},
});
} catch (error: any) {
logger.error("엔티티 검색 오류", { error: error.message, stack: error.stack });
res.status(500).json({ success: false, message: error.message });
}
}