import { Request, Response } from "express"; import { logger } from "../utils/logger"; import { AuthenticatedRequest } from "../types/auth"; import { MultiLangService } from "../services/multilangService"; import { Client } from "pg"; import { CreateLanguageRequest, UpdateLanguageRequest, CreateLangKeyRequest, UpdateLangKeyRequest, SaveLangTextsRequest, GetUserTextParams, BatchTranslationRequest, ApiResponse, } from "../types/multilang"; /** * GET /api/multilang/languages * 언어 목록 조회 API */ export const getLanguages = async ( req: AuthenticatedRequest, res: Response ): Promise => { try { logger.info("언어 목록 조회 요청", { user: req.user }); // PostgreSQL 클라이언트 생성 const client = new Client({ connectionString: process.env.DATABASE_URL || "postgresql://postgres:postgres@localhost:5432/ilshin", }); await client.connect(); try { const multiLangService = new MultiLangService(client); const languages = await multiLangService.getLanguages(); const response: ApiResponse = { success: true, message: "언어 목록 조회 성공", data: languages, }; res.status(200).json(response); } finally { await client.end(); } } catch (error) { logger.error("언어 목록 조회 실패:", error); res.status(500).json({ success: false, message: "언어 목록 조회 중 오류가 발생했습니다.", error: { code: "LANGUAGE_LIST_ERROR", details: error instanceof Error ? error.message : "Unknown error", }, }); } }; /** * POST /api/multilang/languages * 언어 생성 API */ export const createLanguage = async ( req: AuthenticatedRequest, res: Response ): Promise => { try { const languageData: CreateLanguageRequest = req.body; logger.info("언어 생성 요청", { languageData, user: req.user }); // 필수 입력값 검증 if ( !languageData.langCode || !languageData.langName || !languageData.langNative ) { res.status(400).json({ success: false, message: "언어 코드, 언어명, 원어명은 필수입니다.", error: { code: "MISSING_REQUIRED_FIELDS", details: "langCode, langName, langNative are required", }, }); return; } // PostgreSQL 클라이언트 생성 const client = new Client({ connectionString: process.env.DATABASE_URL || "postgresql://postgres:postgres@localhost:5432/ilshin", }); await client.connect(); try { const multiLangService = new MultiLangService(client); const createdLanguage = await multiLangService.createLanguage({ ...languageData, createdBy: req.user?.userId || "system", updatedBy: req.user?.userId || "system", }); const response: ApiResponse = { success: true, message: "언어가 성공적으로 생성되었습니다.", data: createdLanguage, }; res.status(201).json(response); } finally { await client.end(); } } catch (error) { logger.error("언어 생성 실패:", error); res.status(500).json({ success: false, message: "언어 생성 중 오류가 발생했습니다.", error: { code: "LANGUAGE_CREATE_ERROR", details: error instanceof Error ? error.message : "Unknown error", }, }); } }; /** * PUT /api/multilang/languages/:langCode * 언어 수정 API */ export const updateLanguage = async ( req: AuthenticatedRequest, res: Response ): Promise => { try { const { langCode } = req.params; const languageData: UpdateLanguageRequest = req.body; logger.info("언어 수정 요청", { langCode, languageData, user: req.user }); // PostgreSQL 클라이언트 생성 const client = new Client({ connectionString: process.env.DATABASE_URL || "postgresql://postgres:postgres@localhost:5432/ilshin", }); await client.connect(); try { const multiLangService = new MultiLangService(client); const updatedLanguage = await multiLangService.updateLanguage(langCode, { ...languageData, updatedBy: req.user?.userId || "system", }); const response: ApiResponse = { success: true, message: "언어가 성공적으로 수정되었습니다.", data: updatedLanguage, }; res.status(200).json(response); } finally { await client.end(); } } catch (error) { logger.error("언어 수정 실패:", error); res.status(500).json({ success: false, message: "언어 수정 중 오류가 발생했습니다.", error: { code: "LANGUAGE_UPDATE_ERROR", details: error instanceof Error ? error.message : "Unknown error", }, }); } }; /** * PUT /api/multilang/languages/:langCode/toggle * 언어 상태 토글 API */ export const toggleLanguage = async ( req: AuthenticatedRequest, res: Response ): Promise => { try { const { langCode } = req.params; logger.info("언어 상태 토글 요청", { langCode, user: req.user }); // PostgreSQL 클라이언트 생성 const client = new Client({ connectionString: process.env.DATABASE_URL || "postgresql://postgres:postgres@localhost:5432/ilshin", }); await client.connect(); try { const multiLangService = new MultiLangService(client); const result = await multiLangService.toggleLanguage(langCode); const response: ApiResponse = { success: true, message: `언어가 ${result}되었습니다.`, data: result, }; res.status(200).json(response); } finally { await client.end(); } } catch (error) { logger.error("언어 상태 토글 실패:", error); res.status(500).json({ success: false, message: "언어 상태 변경 중 오류가 발생했습니다.", error: { code: "LANGUAGE_TOGGLE_ERROR", details: error instanceof Error ? error.message : "Unknown error", }, }); } }; /** * GET /api/multilang/keys * 다국어 키 목록 조회 API */ export const getLangKeys = async ( req: AuthenticatedRequest, res: Response ): Promise => { try { const { companyCode, menuCode, keyType, searchText } = req.query; logger.info("다국어 키 목록 조회 요청", { query: req.query, user: req.user, }); // PostgreSQL 클라이언트 생성 const client = new Client({ connectionString: process.env.DATABASE_URL || "postgresql://postgres:postgres@localhost:5432/ilshin", }); await client.connect(); try { const multiLangService = new MultiLangService(client); const langKeys = await multiLangService.getLangKeys({ companyCode: companyCode as string, menuCode: menuCode as string, keyType: keyType as string, searchText: searchText as string, }); const response: ApiResponse = { success: true, message: "다국어 키 목록 조회 성공", data: langKeys, }; res.status(200).json(response); } finally { await client.end(); } } catch (error) { logger.error("다국어 키 목록 조회 실패:", error); res.status(500).json({ success: false, message: "다국어 키 목록 조회 중 오류가 발생했습니다.", error: { code: "LANG_KEYS_LIST_ERROR", details: error instanceof Error ? error.message : "Unknown error", }, }); } }; /** * GET /api/multilang/keys/:keyId/texts * 특정 키의 다국어 텍스트 조회 API */ export const getLangTexts = async ( req: AuthenticatedRequest, res: Response ): Promise => { try { const { keyId } = req.params; logger.info("다국어 텍스트 조회 요청", { keyId, user: req.user }); // PostgreSQL 클라이언트 생성 const client = new Client({ connectionString: process.env.DATABASE_URL || "postgresql://postgres:postgres@localhost:5432/ilshin", }); await client.connect(); try { const multiLangService = new MultiLangService(client); const langTexts = await multiLangService.getLangTexts(parseInt(keyId)); const response: ApiResponse = { success: true, message: "다국어 텍스트 조회 성공", data: langTexts, }; res.status(200).json(response); } finally { await client.end(); } } catch (error) { logger.error("다국어 텍스트 조회 실패:", error); res.status(500).json({ success: false, message: "다국어 텍스트 조회 중 오류가 발생했습니다.", error: { code: "LANG_TEXTS_LIST_ERROR", details: error instanceof Error ? error.message : "Unknown error", }, }); } }; /** * POST /api/multilang/keys * 다국어 키 생성 API */ export const createLangKey = async ( req: AuthenticatedRequest, res: Response ): Promise => { try { const keyData: CreateLangKeyRequest = req.body; logger.info("다국어 키 생성 요청", { keyData, user: req.user }); // 필수 입력값 검증 if (!keyData.companyCode || !keyData.langKey) { res.status(400).json({ success: false, message: "회사 코드와 언어 키는 필수입니다.", error: { code: "MISSING_REQUIRED_FIELDS", details: "companyCode and langKey are required", }, }); return; } // PostgreSQL 클라이언트 생성 const client = new Client({ connectionString: process.env.DATABASE_URL || "postgresql://postgres:postgres@localhost:5432/ilshin", }); await client.connect(); try { const multiLangService = new MultiLangService(client); const keyId = await multiLangService.createLangKey({ ...keyData, createdBy: req.user?.userId || "system", updatedBy: req.user?.userId || "system", }); const response: ApiResponse = { success: true, message: "다국어 키가 성공적으로 생성되었습니다.", data: keyId, }; res.status(201).json(response); } finally { await client.end(); } } catch (error) { logger.error("다국어 키 생성 실패:", error); res.status(500).json({ success: false, message: "다국어 키 생성 중 오류가 발생했습니다.", error: { code: "LANG_KEY_CREATE_ERROR", details: error instanceof Error ? error.message : "Unknown error", }, }); } }; /** * PUT /api/multilang/keys/:keyId * 다국어 키 수정 API */ export const updateLangKey = async ( req: AuthenticatedRequest, res: Response ): Promise => { try { const { keyId } = req.params; const keyData: UpdateLangKeyRequest = req.body; logger.info("다국어 키 수정 요청", { keyId, keyData, user: req.user }); // PostgreSQL 클라이언트 생성 const client = new Client({ connectionString: process.env.DATABASE_URL || "postgresql://postgres:postgres@localhost:5432/ilshin", }); await client.connect(); try { const multiLangService = new MultiLangService(client); await multiLangService.updateLangKey(parseInt(keyId), { ...keyData, updatedBy: req.user?.userId || "system", }); const response: ApiResponse = { success: true, message: "다국어 키가 성공적으로 수정되었습니다.", data: "수정 완료", }; res.status(200).json(response); } finally { await client.end(); } } catch (error) { logger.error("다국어 키 수정 실패:", error); res.status(500).json({ success: false, message: "다국어 키 수정 중 오류가 발생했습니다.", error: { code: "LANG_KEY_UPDATE_ERROR", details: error instanceof Error ? error.message : "Unknown error", }, }); } }; /** * DELETE /api/multilang/keys/:keyId * 다국어 키 삭제 API */ export const deleteLangKey = async ( req: AuthenticatedRequest, res: Response ): Promise => { try { const { keyId } = req.params; logger.info("다국어 키 삭제 요청", { keyId, user: req.user }); // PostgreSQL 클라이언트 생성 const client = new Client({ connectionString: process.env.DATABASE_URL || "postgresql://postgres:postgres@localhost:5432/ilshin", }); await client.connect(); try { const multiLangService = new MultiLangService(client); await multiLangService.deleteLangKey(parseInt(keyId)); const response: ApiResponse = { success: true, message: "다국어 키가 성공적으로 삭제되었습니다.", data: "삭제 완료", }; res.status(200).json(response); } finally { await client.end(); } } catch (error) { logger.error("다국어 키 삭제 실패:", error); res.status(500).json({ success: false, message: "다국어 키 삭제 중 오류가 발생했습니다.", error: { code: "LANG_KEY_DELETE_ERROR", details: error instanceof Error ? error.message : "Unknown error", }, }); } }; /** * PUT /api/multilang/keys/:keyId/toggle * 다국어 키 상태 토글 API */ export const toggleLangKey = async ( req: AuthenticatedRequest, res: Response ): Promise => { try { const { keyId } = req.params; logger.info("다국어 키 상태 토글 요청", { keyId, user: req.user }); // PostgreSQL 클라이언트 생성 const client = new Client({ connectionString: process.env.DATABASE_URL || "postgresql://postgres:postgres@localhost:5432/ilshin", }); await client.connect(); try { const multiLangService = new MultiLangService(client); const result = await multiLangService.toggleLangKey(parseInt(keyId)); const response: ApiResponse = { success: true, message: `다국어 키가 ${result}되었습니다.`, data: result, }; res.status(200).json(response); } finally { await client.end(); } } catch (error) { logger.error("다국어 키 상태 토글 실패:", error); res.status(500).json({ success: false, message: "다국어 키 상태 변경 중 오류가 발생했습니다.", error: { code: "LANG_KEY_TOGGLE_ERROR", details: error instanceof Error ? error.message : "Unknown error", }, }); } }; /** * POST /api/multilang/keys/:keyId/texts * 다국어 텍스트 저장/수정 API */ export const saveLangTexts = async ( req: AuthenticatedRequest, res: Response ): Promise => { try { const { keyId } = req.params; const textData: SaveLangTextsRequest = req.body; logger.info("다국어 텍스트 저장 요청", { keyId, textData, user: req.user }); // 필수 입력값 검증 if ( !textData.texts || !Array.isArray(textData.texts) || textData.texts.length === 0 ) { res.status(400).json({ success: false, message: "텍스트 데이터는 필수입니다.", error: { code: "MISSING_REQUIRED_FIELDS", details: "texts array is required", }, }); return; } // PostgreSQL 클라이언트 생성 const client = new Client({ connectionString: process.env.DATABASE_URL || "postgresql://postgres:postgres@localhost:5432/ilshin", }); await client.connect(); try { const multiLangService = new MultiLangService(client); await multiLangService.saveLangTexts(parseInt(keyId), { texts: textData.texts.map((text) => ({ ...text, createdBy: req.user?.userId || "system", updatedBy: req.user?.userId || "system", })), }); const response: ApiResponse = { success: true, message: "다국어 텍스트가 성공적으로 저장되었습니다.", data: "저장 완료", }; res.status(200).json(response); } finally { await client.end(); } } catch (error) { logger.error("다국어 텍스트 저장 실패:", error); res.status(500).json({ success: false, message: "다국어 텍스트 저장 중 오류가 발생했습니다.", error: { code: "LANG_TEXTS_SAVE_ERROR", details: error instanceof Error ? error.message : "Unknown error", }, }); } }; /** * GET /api/multilang/user-text/:companyCode/:menuCode/:langKey * 사용자별 다국어 텍스트 조회 API */ export const getUserText = async ( req: AuthenticatedRequest, res: Response ): Promise => { try { const { companyCode, menuCode, langKey } = req.params; const { userLang } = req.query; logger.info("사용자별 다국어 텍스트 조회 요청", { companyCode, menuCode, langKey, userLang, user: req.user, }); if (!userLang) { res.status(400).json({ success: false, message: "사용자 언어는 필수입니다.", error: { code: "MISSING_USER_LANG", details: "userLang query parameter is required", }, }); return; } // PostgreSQL 클라이언트 생성 const client = new Client({ connectionString: process.env.DATABASE_URL || "postgresql://postgres:postgres@localhost:5432/ilshin", }); await client.connect(); try { const multiLangService = new MultiLangService(client); const langText = await multiLangService.getUserText({ companyCode, menuCode, langKey, userLang: userLang as string, }); const response: ApiResponse = { success: true, message: "사용자별 다국어 텍스트 조회 성공", data: langText, }; res.status(200).json(response); } finally { await client.end(); } } catch (error) { logger.error("사용자별 다국어 텍스트 조회 실패:", error); res.status(500).json({ success: false, message: "사용자별 다국어 텍스트 조회 중 오류가 발생했습니다.", error: { code: "USER_TEXT_ERROR", details: error instanceof Error ? error.message : "Unknown error", }, }); } }; /** * GET /api/multilang/text/:companyCode/:langKey/:langCode * 특정 키의 다국어 텍스트 조회 API */ export const getLangText = async ( req: AuthenticatedRequest, res: Response ): Promise => { try { const { companyCode, langKey, langCode } = req.params; logger.info("특정 키의 다국어 텍스트 조회 요청", { companyCode, langKey, langCode, user: req.user, }); // PostgreSQL 클라이언트 생성 const client = new Client({ connectionString: process.env.DATABASE_URL || "postgresql://postgres:postgres@localhost:5432/ilshin", }); await client.connect(); try { const multiLangService = new MultiLangService(client); const langText = await multiLangService.getLangText( companyCode, langKey, langCode ); const response: ApiResponse = { success: true, message: "특정 키의 다국어 텍스트 조회 성공", data: langText, }; res.status(200).json(response); } finally { await client.end(); } } catch (error) { logger.error("특정 키의 다국어 텍스트 조회 실패:", error); res.status(500).json({ success: false, message: "특정 키의 다국어 텍스트 조회 중 오류가 발생했습니다.", error: { code: "LANG_TEXT_ERROR", details: error instanceof Error ? error.message : "Unknown error", }, }); } }; /** * POST /api/multilang/batch * 다국어 텍스트 배치 조회 API */ export const getBatchTranslations = async ( req: AuthenticatedRequest, res: Response ): Promise => { try { const { companyCode, menuCode, userLang } = req.query; const { langKeys } = req.body; logger.info("다국어 텍스트 배치 조회 요청", { companyCode, menuCode, userLang, keyCount: langKeys?.length || 0, user: req.user, }); if (!langKeys || !Array.isArray(langKeys) || langKeys.length === 0) { res.status(400).json({ success: false, message: "langKeys 배열이 필요합니다.", error: { code: "MISSING_LANG_KEYS", details: "langKeys array is required", }, }); return; } if (!companyCode || !userLang) { res.status(400).json({ success: false, message: "companyCode와 userLang은 필수입니다.", error: { code: "MISSING_REQUIRED_PARAMS", details: "companyCode and userLang are required", }, }); return; } // PostgreSQL 클라이언트 생성 const client = new Client({ connectionString: process.env.DATABASE_URL || "postgresql://postgres:postgres@localhost:5432/ilshin", }); await client.connect(); try { const multiLangService = new MultiLangService(client); const translations = await multiLangService.getBatchTranslations({ companyCode: companyCode as string, menuCode: menuCode as string, userLang: userLang as string, langKeys, }); const response: ApiResponse> = { success: true, message: "다국어 텍스트 배치 조회 성공", data: translations, }; res.status(200).json(response); } finally { await client.end(); } } catch (error) { logger.error("다국어 텍스트 배치 조회 실패:", error); res.status(500).json({ success: false, message: "다국어 텍스트 배치 조회 중 오류가 발생했습니다.", error: { code: "BATCH_TRANSLATION_ERROR", details: error instanceof Error ? error.message : "Unknown error", }, }); } };