/** * 카테고리 트리 컨트롤러 (테스트용) */ import { Router, Request, Response } from "express"; import { categoryTreeService, CreateCategoryValueInput, UpdateCategoryValueInput } from "../services/categoryTreeService"; import { logger } from "../utils/logger"; const router = Router(); // 인증된 사용자 타입 interface AuthenticatedRequest extends Request { user?: { userId: string; companyCode: string; }; } /** * 전체 카테고리 키 목록 조회 (모든 테이블.컬럼 조합) * GET /api/category-tree/test/all-category-keys * 주의: 이 라우트는 /test/:tableName/:columnName 보다 먼저 정의되어야 함 */ router.get("/test/all-category-keys", async (req: AuthenticatedRequest, res: Response) => { try { const companyCode = req.user?.companyCode || "*"; const keys = await categoryTreeService.getAllCategoryKeys(companyCode); res.json({ success: true, data: keys, }); } catch (error: unknown) { const err = error as Error; logger.error("전체 카테고리 키 목록 조회 API 오류", { error: err.message }); res.status(500).json({ success: false, error: err.message, }); } }); /** * 카테고리 트리 조회 * GET /api/category-tree/test/:tableName/:columnName */ router.get("/test/:tableName/:columnName", async (req: AuthenticatedRequest, res: Response) => { try { const { tableName, columnName } = req.params; const companyCode = req.user?.companyCode || "*"; const tree = await categoryTreeService.getCategoryTree(companyCode, tableName, columnName); res.json({ success: true, data: tree, }); } catch (error: unknown) { const err = error as Error; logger.error("카테고리 트리 조회 API 오류", { error: err.message }); res.status(500).json({ success: false, error: err.message, }); } }); /** * 카테고리 목록 조회 (플랫 리스트) * GET /api/category-tree/test/:tableName/:columnName/flat */ router.get("/test/:tableName/:columnName/flat", async (req: AuthenticatedRequest, res: Response) => { try { const { tableName, columnName } = req.params; const companyCode = req.user?.companyCode || "*"; const list = await categoryTreeService.getCategoryList(companyCode, tableName, columnName); res.json({ success: true, data: list, }); } catch (error: unknown) { const err = error as Error; logger.error("카테고리 목록 조회 API 오류", { error: err.message }); res.status(500).json({ success: false, error: err.message, }); } }); /** * 카테고리 값 단일 조회 * GET /api/category-tree/test/value/:valueId */ router.get("/test/value/:valueId", async (req: AuthenticatedRequest, res: Response) => { try { const { valueId } = req.params; const companyCode = req.user?.companyCode || "*"; const value = await categoryTreeService.getCategoryValue(companyCode, Number(valueId)); if (!value) { return res.status(404).json({ success: false, error: "카테고리 값을 찾을 수 없습니다", }); } res.json({ success: true, data: value, }); } catch (error: unknown) { const err = error as Error; logger.error("카테고리 값 조회 API 오류", { error: err.message }); res.status(500).json({ success: false, error: err.message, }); } }); /** * 카테고리 값 생성 * POST /api/category-tree/test/value */ router.post("/test/value", async (req: AuthenticatedRequest, res: Response) => { try { const input: CreateCategoryValueInput = req.body; const userCompanyCode = req.user?.companyCode || "*"; const createdBy = req.user?.userId; // 🔧 최고 관리자가 특정 회사를 선택한 경우, targetCompanyCode 우선 사용 // 단, 최고 관리자(companyCode = '*')만 다른 회사 코드 사용 가능 let companyCode = userCompanyCode; if (input.targetCompanyCode && userCompanyCode === "*") { companyCode = input.targetCompanyCode; logger.info("🔓 최고 관리자 회사 코드 오버라이드 (카테고리 값 생성)", { originalCompanyCode: userCompanyCode, targetCompanyCode: input.targetCompanyCode, }); } if (!input.tableName || !input.columnName || !input.valueCode || !input.valueLabel) { return res.status(400).json({ success: false, error: "tableName, columnName, valueCode, valueLabel은 필수입니다", }); } const value = await categoryTreeService.createCategoryValue(companyCode, input, createdBy); res.json({ success: true, data: value, }); } catch (error: unknown) { const err = error as Error; logger.error("카테고리 값 생성 API 오류", { error: err.message }); res.status(500).json({ success: false, error: err.message, }); } }); /** * 카테고리 값 수정 * PUT /api/category-tree/test/value/:valueId */ router.put("/test/value/:valueId", async (req: AuthenticatedRequest, res: Response) => { try { const { valueId } = req.params; const input: UpdateCategoryValueInput = req.body; const companyCode = req.user?.companyCode || "*"; const updatedBy = req.user?.userId; const value = await categoryTreeService.updateCategoryValue(companyCode, Number(valueId), input, updatedBy); if (!value) { return res.status(404).json({ success: false, error: "카테고리 값을 찾을 수 없습니다", }); } res.json({ success: true, data: value, }); } catch (error: unknown) { const err = error as Error; logger.error("카테고리 값 수정 API 오류", { error: err.message }); res.status(500).json({ success: false, error: err.message, }); } }); /** * 카테고리 값 삭제 * DELETE /api/category-tree/test/value/:valueId */ router.delete("/test/value/:valueId", async (req: AuthenticatedRequest, res: Response) => { try { const { valueId } = req.params; const companyCode = req.user?.companyCode || "*"; const success = await categoryTreeService.deleteCategoryValue(companyCode, Number(valueId)); if (!success) { return res.status(404).json({ success: false, error: "카테고리 값을 찾을 수 없습니다", }); } res.json({ success: true, message: "삭제되었습니다", }); } catch (error: unknown) { const err = error as Error; logger.error("카테고리 값 삭제 API 오류", { error: err.message }); res.status(500).json({ success: false, error: err.message, }); } }); /** * 테이블의 카테고리 컬럼 목록 조회 * GET /api/category-tree/test/columns/:tableName */ router.get("/test/columns/:tableName", async (req: AuthenticatedRequest, res: Response) => { try { const { tableName } = req.params; const companyCode = req.user?.companyCode || "*"; const columns = await categoryTreeService.getCategoryColumns(companyCode, tableName); res.json({ success: true, data: columns, }); } catch (error: unknown) { const err = error as Error; logger.error("카테고리 컬럼 목록 조회 API 오류", { error: err.message }); res.status(500).json({ success: false, error: err.message, }); } }); export default router;