feat: 카테고리 값 삭제 기능 개선 및 하위 카테고리 수집 로직 추가

- 카테고리 값 삭제 시, 자기 자신과 모든 하위 카테고리 ID를 재귀적으로 수집하는 기능을 추가하였습니다.
- 삭제 대상 카테고리 값 수집 완료 후, 하위 카테고리부터 역순으로 삭제하는 로직을 구현하였습니다.
- 관련된 로그 메시지를 추가하여 삭제 과정과 결과를 기록하도록 하였습니다.
- 화면 관리 기능에서 하위 항목 개수를 계산하는 로직을 개선하여 사용자에게 더 정확한 정보를 제공하도록 하였습니다.
This commit is contained in:
kjs
2026-01-27 10:06:40 +09:00
parent 589f5b9222
commit 64cc5c6772
6 changed files with 248 additions and 82 deletions

View File

@@ -403,6 +403,33 @@ class CategoryTreeService {
}
}
/**
* 모든 하위 카테고리 값 ID 재귀 수집
*/
private async collectAllChildValueIds(
companyCode: string,
valueId: number
): Promise<number[]> {
const pool = getPool();
// 재귀 CTE를 사용하여 모든 하위 카테고리 수집
const query = `
WITH RECURSIVE category_tree AS (
SELECT value_id FROM category_values_test
WHERE parent_value_id = $1 AND (company_code = $2 OR company_code = '*')
UNION ALL
SELECT cv.value_id
FROM category_values_test cv
INNER JOIN category_tree ct ON cv.parent_value_id = ct.value_id
WHERE cv.company_code = $2 OR cv.company_code = '*'
)
SELECT value_id FROM category_tree
`;
const result = await pool.query(query, [valueId, companyCode]);
return result.rows.map(row => row.value_id);
}
/**
* 카테고리 값 삭제 (하위 항목도 함께 삭제)
*/
@@ -410,20 +437,33 @@ class CategoryTreeService {
const pool = getPool();
try {
const query = `
DELETE FROM category_values_test
WHERE (company_code = $1 OR company_code = '*') AND value_id = $2
RETURNING value_id
`;
// 1. 모든 하위 카테고리 ID 수집
const childValueIds = await this.collectAllChildValueIds(companyCode, valueId);
const allValueIds = [valueId, ...childValueIds];
logger.info("삭제 대상 카테고리 값 수집 완료", {
valueId,
childCount: childValueIds.length,
totalCount: allValueIds.length,
});
const result = await pool.query(query, [companyCode, valueId]);
if (result.rowCount && result.rowCount > 0) {
logger.info("카테고리 값 삭제 완료", { valueId });
return true;
// 2. 하위 카테고리부터 역순으로 삭제 (외래키 제약 회피)
const reversedIds = [...allValueIds].reverse();
for (const id of reversedIds) {
await pool.query(
`DELETE FROM category_values_test WHERE (company_code = $1 OR company_code = '*') AND value_id = $2`,
[companyCode, id]
);
}
return false;
logger.info("카테고리 값 삭제 완료", {
valueId,
deletedCount: allValueIds.length,
deletedChildCount: childValueIds.length,
});
return true;
} catch (error: unknown) {
const err = error as Error;
logger.error("카테고리 값 삭제 실패", { error: err.message, valueId });