feat: Add table aggregation endpoint for data summarization
- Implemented a new endpoint to retrieve aggregated data (SUM/COUNT) for specified columns in a given table. - Added validation to ensure the presence of table name and valid aggregation columns in the request. - Integrated company code filtering to restrict data access based on user permissions. - Updated the table management routes to include the new aggregation functionality. - Enhanced the frontend order page to utilize the new aggregation endpoint for improved statistical reporting.
This commit is contained in:
@@ -907,6 +907,61 @@ export async function getTableData(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 테이블 집계 조회 (SUM/COUNT)
|
||||
* POST /api/table-management/tables/:tableName/aggregate
|
||||
*/
|
||||
export async function getTableAggregate(
|
||||
req: AuthenticatedRequest,
|
||||
res: Response
|
||||
): Promise<void> {
|
||||
try {
|
||||
const { tableName } = req.params;
|
||||
const { columns, autoFilter } = req.body;
|
||||
const companyCode = req.user?.companyCode;
|
||||
|
||||
if (!tableName || !columns || !Array.isArray(columns)) {
|
||||
res.status(400).json({ success: false, message: "tableName과 columns 배열이 필요합니다." });
|
||||
return;
|
||||
}
|
||||
|
||||
const validCols = columns.filter((c: any) =>
|
||||
c.column && c.func && /^[a-zA-Z0-9_]+$/.test(c.column) && ["sum", "count", "avg", "min", "max"].includes(c.func)
|
||||
);
|
||||
if (validCols.length === 0) {
|
||||
res.status(400).json({ success: false, message: "유효한 집계 컬럼이 없습니다." });
|
||||
return;
|
||||
}
|
||||
|
||||
const selectParts = validCols.map((c: any) => {
|
||||
const col = c.column.replace(/[^a-zA-Z0-9_]/g, "");
|
||||
return `${c.func}(COALESCE(CAST(NULLIF(${col}, '') AS numeric), 0)) AS "${c.func}_${col}"`;
|
||||
});
|
||||
|
||||
let whereClause = "";
|
||||
const params: any[] = [];
|
||||
let paramIdx = 1;
|
||||
|
||||
if (autoFilter !== false && companyCode && companyCode !== "*") {
|
||||
whereClause = `WHERE company_code = $${paramIdx}`;
|
||||
params.push(companyCode);
|
||||
paramIdx++;
|
||||
}
|
||||
|
||||
const pool = (await import("../database/db")).getPool();
|
||||
const safeTable = tableName.replace(/[^a-zA-Z0-9_]/g, "");
|
||||
const result = await pool.query(
|
||||
`SELECT ${selectParts.join(", ")} FROM ${safeTable} ${whereClause}`,
|
||||
params
|
||||
);
|
||||
|
||||
res.json({ success: true, data: result.rows[0] || {} });
|
||||
} catch (error: any) {
|
||||
logger.error("테이블 집계 조회 실패:", error);
|
||||
res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 테이블 데이터 추가
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user