Files
DDD1542 2348800e68
Build & Deploy to K8s / build-and-deploy (push) Successful in 9m22s
refactor(common-code): 마스터-디테일 재설계 — code_info(그룹) + code_detail(재귀 트리)
카테고리/캐스케이딩 시스템 (B/C/D) 전부 폐기:
- BE: mapper/Service/Controller 9세트 삭제 (cascading*, categoryTree, tableCategoryValue, categoryValueCascading, codeMerge)
- FE: 페이지 3 + API 8 + hooks 2 + 폐기 컴포넌트 6 삭제, 14곳 의존성 정리
- DB: 12 테이블 DROP, TABLE_TYPE_COLUMNS.CODE_CATEGORY → CODE_INFO rename

신설 commonCode 마스터-디테일:
- code_info: 1레벨 그룹 마스터
- code_detail: 2~∞ depth 재귀 트리 (parent_detail_id self-FK, depth 자동 계산)
- API: /api/common-codes/{info,detail}
- CodeCategoryFormModal/Panel → CodeInfoFormModal/Panel rename
- code_category 컬럼명 전부 code_info 로 치환 (mapper/Java/FE)
- 옛 commonCode API URL (/categories/...) → getCodeOptions 어댑터 + /detail?code_info=... 전환

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 16:50:50 +09:00

98 lines
3.1 KiB
TypeScript

/**
* 코드 관리 API (호환 레이어)
*
* 2026-05-15: 옛 카테고리 API 가 폐기되고 마스터-디테일(code_info/code_detail) 로 재작성됨.
* 이 파일은 화면관리/플로우 등에서 호출하는 기존 헬퍼 시그니처를 유지하기 위한 얇은 어댑터.
*
* 새 코드는 `lib/api/commonCode.ts` 의 `getCodeDetailTree` 등을 직접 사용 권장.
*/
import { getCodeDetailTree, getCodeInfoList } from "./commonCode";
export interface CodeItem {
code: string;
name: string;
description?: string;
orderNo?: number;
useYn: string;
}
export interface CodeInfo {
categoryCode: string;
categoryName: string;
description?: string;
useYn: string;
}
/** 그룹 목록 조회 — 옛 시그니처 유지 */
export const getCodeCategories = async (): Promise<CodeInfo[]> => {
try {
const response = await getCodeInfoList({ is_active: true });
const rows = response.data || [];
return rows.map((row: any) => ({
categoryCode: row.code_info,
categoryName: row.code_name || row.code_info,
description: row.description,
useYn: row.is_active === "Y" ? "Y" : "N",
}));
} catch (error) {
console.error("코드 그룹 조회 실패:", error);
return [];
}
};
/** 그룹의 디테일 목록 조회 — 옛 시그니처 유지 (활성만) */
export const getCodesByCategory = async (categoryCode: string): Promise<CodeItem[]> => {
if (!categoryCode || categoryCode === "none") return [];
try {
const response = await getCodeDetailTree({ code_info: categoryCode, is_active: true });
const rows = response.data || [];
return rows.map((row: any) => ({
code: row.code_value,
name: row.code_name || row.code_value,
description: row.description || undefined,
orderNo: row.sort_order ?? undefined,
useYn: row.is_active === "Y" ? "Y" : "N",
}));
} catch (error: any) {
console.error(`코드 그룹 '${categoryCode}' 디테일 조회 실패:`, error?.message || error);
return [];
}
};
/**
* 컬럼 메타(webType / codeInfo) 기반으로 코드 조회
*/
export const getCodesForColumn = async (
columnName: string,
webType?: string,
codeInfo?: string,
): Promise<CodeItem[]> => {
if (webType !== "code" && !codeInfo) return [];
if (codeInfo) return getCodesByCategory(codeInfo);
const inferred = inferCodeInfoFromColumnName(columnName);
return inferred ? getCodesByCategory(inferred) : [];
};
/**
* 컬럼명에서 그룹 코드를 추론 (legacy fallback)
*/
const inferCodeInfoFromColumnName = (columnName: string): string | null => {
const lower = columnName.toLowerCase();
const patterns: Array<{ pattern: RegExp; category: string }> = [
{ pattern: /status/i, category: "STATUS" },
{ pattern: /state/i, category: "STATE" },
{ pattern: /type/i, category: "TYPE" },
{ pattern: /category/i, category: "CATEGORY" },
{ pattern: /grade/i, category: "GRADE" },
{ pattern: /level/i, category: "LEVEL" },
{ pattern: /priority/i, category: "PRIORITY" },
{ pattern: /role/i, category: "ROLE" },
];
for (const { pattern, category } of patterns) {
if (pattern.test(lower)) return category;
}
return null;
};