우측 패널 항목 삭제 기능 구현

This commit is contained in:
dohyeons
2025-11-07 18:20:24 +09:00
parent 3009d1eecc
commit 68577a09f9
6 changed files with 246 additions and 17 deletions

View File

@@ -459,6 +459,58 @@ router.put(
* 레코드 삭제 API
* DELETE /api/data/{tableName}/{id}
*/
/**
* 복합키 레코드 삭제 API (POST)
* POST /api/data/:tableName/delete
* Body: { user_id: 'xxx', dept_code: 'yyy' }
*/
router.post(
"/:tableName/delete",
authenticateToken,
async (req: AuthenticatedRequest, res) => {
try {
const { tableName } = req.params;
const compositeKey = req.body;
// 입력값 검증
if (!tableName || typeof tableName !== "string") {
return res.status(400).json({
success: false,
message: "테이블명이 필요합니다.",
error: "INVALID_TABLE_NAME",
});
}
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(tableName)) {
return res.status(400).json({
success: false,
message: "유효하지 않은 테이블명입니다.",
error: "INVALID_TABLE_NAME",
});
}
console.log(`🗑️ 복합키 레코드 삭제: ${tableName}`, compositeKey);
// 레코드 삭제 (복합키 객체 전달)
const result = await dataService.deleteRecord(tableName, compositeKey);
if (!result.success) {
return res.status(400).json(result);
}
console.log(`✅ 레코드 삭제 성공: ${tableName}`);
return res.json(result);
} catch (error: any) {
console.error(`레코드 삭제 오류 (${req.params.tableName}):`, error);
return res.status(500).json({
success: false,
message: "레코드 삭제 중 오류가 발생했습니다.",
error: error.message,
});
}
}
);
router.delete(
"/:tableName/:id",
authenticateToken,

View File

@@ -652,7 +652,7 @@ class DataService {
*/
async deleteRecord(
tableName: string,
id: string | number
id: string | number | Record<string, any>
): Promise<ServiceResponse<void>> {
try {
// 테이블 접근 검증
@@ -661,28 +661,53 @@ class DataService {
return validation.error!;
}
// Primary Key 컬럼 찾기
// Primary Key 컬럼 찾기 (복합키 지원)
const pkResult = await query<{ attname: string }>(
`SELECT a.attname
FROM pg_index i
JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)
WHERE i.indrelid = $1::regclass AND i.indisprimary`,
WHERE i.indrelid = $1::regclass AND i.indisprimary
ORDER BY a.attnum`,
[tableName]
);
let pkColumn = "id";
if (pkResult.length > 0) {
pkColumn = pkResult[0].attname;
let whereClauses: string[] = [];
let params: any[] = [];
if (pkResult.length > 1) {
// 복합키인 경우: id가 객체여야 함
console.log(`🔑 복합키 테이블: ${tableName}, PK: [${pkResult.map(r => r.attname).join(', ')}]`);
if (typeof id === 'object' && !Array.isArray(id)) {
// id가 객체인 경우: { user_id: 'xxx', dept_code: 'yyy' }
pkResult.forEach((pk, index) => {
whereClauses.push(`"${pk.attname}" = $${index + 1}`);
params.push(id[pk.attname]);
});
} else {
// id가 문자열/숫자인 경우: 첫 번째 PK만 사용 (하위 호환성)
whereClauses.push(`"${pkResult[0].attname}" = $1`);
params.push(id);
}
} else {
// 단일키인 경우
const pkColumn = pkResult.length > 0 ? pkResult[0].attname : "id";
whereClauses.push(`"${pkColumn}" = $1`);
params.push(typeof id === 'object' ? id[pkColumn] : id);
}
const queryText = `DELETE FROM "${tableName}" WHERE "${pkColumn}" = $1`;
await query<any>(queryText, [id]);
const queryText = `DELETE FROM "${tableName}" WHERE ${whereClauses.join(' AND ')}`;
console.log(`🗑️ 삭제 쿼리:`, queryText, params);
const result = await query<any>(queryText, params);
console.log(`✅ 레코드 삭제 완료: ${tableName}, 영향받은 행: ${result.length}`);
return {
success: true,
};
} catch (error) {
console.error(`레코드 삭제 오류 (${tableName}/${id}):`, error);
console.error(`레코드 삭제 오류 (${tableName}):`, error);
return {
success: false,
message: "레코드 삭제 중 오류가 발생했습니다.",