import { Request, Response } from "express"; import { pool, queryOne } from "../database/db"; import logger from "../utils/logger"; import { PasswordEncryption } from "../utils/passwordEncryption"; import { DatabaseConnectorFactory } from "../database/DatabaseConnectorFactory"; // 외부 DB 커넥터를 가져오는 헬퍼 함수 export async function getExternalDbConnector(connectionId: number) { // 외부 DB 연결 정보 조회 const connection = await queryOne( `SELECT * FROM external_db_connections WHERE id = $1`, [connectionId] ); if (!connection) { throw new Error(`외부 DB 연결 정보를 찾을 수 없습니다. ID: ${connectionId}`); } // 패스워드 복호화 const decryptedPassword = PasswordEncryption.decrypt(connection.password); // DB 연결 설정 const config = { host: connection.host, port: connection.port, user: connection.username, password: decryptedPassword, database: connection.database_name, }; // DB 커넥터 생성 return await DatabaseConnectorFactory.createConnector( connection.db_type || "mariadb", config, connectionId ); } // 창고 목록 조회 (사용자 지정 테이블) export const getWarehouses = async (req: Request, res: Response): Promise => { try { const { externalDbConnectionId, tableName } = req.query; if (!externalDbConnectionId) { return res.status(400).json({ success: false, message: "외부 DB 연결 ID가 필요합니다.", }); } if (!tableName) { return res.status(400).json({ success: false, message: "테이블명이 필요합니다.", }); } const connector = await getExternalDbConnector(Number(externalDbConnectionId)); // 테이블명을 사용하여 모든 컬럼 조회 const query = `SELECT * FROM ${tableName} LIMIT 100`; const result = await connector.executeQuery(query); logger.info("창고 목록 조회", { externalDbConnectionId, tableName, count: result.rows.length, data: result.rows, // 실제 데이터 확인 }); return res.json({ success: true, data: result.rows, }); } catch (error: any) { logger.error("창고 목록 조회 실패", error); return res.status(500).json({ success: false, message: "창고 목록 조회 중 오류가 발생했습니다.", error: error.message, }); } }; // Area 목록 조회 (사용자 지정 테이블) export const getAreas = async (req: Request, res: Response): Promise => { try { const { externalDbConnectionId, tableName, warehouseKey } = req.query; if (!externalDbConnectionId || !tableName) { return res.status(400).json({ success: false, message: "외부 DB 연결 ID와 테이블명이 필요합니다.", }); } const connector = await getExternalDbConnector(Number(externalDbConnectionId)); // 테이블명을 사용하여 모든 컬럼 조회 let query = `SELECT * FROM ${tableName}`; if (warehouseKey) { query += ` WHERE WAREKEY = '${warehouseKey}'`; } query += ` LIMIT 1000`; const result = await connector.executeQuery(query); logger.info("Area 목록 조회", { externalDbConnectionId, tableName, warehouseKey, count: result.rows.length, }); return res.json({ success: true, data: result.rows, }); } catch (error: any) { logger.error("Area 목록 조회 실패", error); return res.status(500).json({ success: false, message: "Area 목록 조회 중 오류가 발생했습니다.", error: error.message, }); } }; // Location 목록 조회 (사용자 지정 테이블) export const getLocations = async (req: Request, res: Response): Promise => { try { const { externalDbConnectionId, tableName, areaKey } = req.query; if (!externalDbConnectionId || !tableName) { return res.status(400).json({ success: false, message: "외부 DB 연결 ID와 테이블명이 필요합니다.", }); } const connector = await getExternalDbConnector(Number(externalDbConnectionId)); // 테이블명을 사용하여 모든 컬럼 조회 let query = `SELECT * FROM ${tableName}`; if (areaKey) { query += ` WHERE AREAKEY = '${areaKey}'`; } query += ` LIMIT 1000`; const result = await connector.executeQuery(query); logger.info("Location 목록 조회", { externalDbConnectionId, tableName, areaKey, count: result.rows.length, }); return res.json({ success: true, data: result.rows, }); } catch (error: any) { logger.error("Location 목록 조회 실패", error); return res.status(500).json({ success: false, message: "Location 목록 조회 중 오류가 발생했습니다.", error: error.message, }); } }; // 자재 목록 조회 (사용자 지정 테이블) export const getMaterials = async (req: Request, res: Response): Promise => { try { const { externalDbConnectionId, tableName, locaKey } = req.query; if (!externalDbConnectionId || !tableName) { return res.status(400).json({ success: false, message: "외부 DB 연결 ID와 테이블명이 필요합니다.", }); } const connector = await getExternalDbConnector(Number(externalDbConnectionId)); // 테이블명을 사용하여 모든 컬럼 조회 let query = `SELECT * FROM ${tableName}`; if (locaKey) { query += ` WHERE LOCAKEY = '${locaKey}'`; } query += ` LIMIT 1000`; const result = await connector.executeQuery(query); logger.info("자재 목록 조회", { externalDbConnectionId, tableName, locaKey, count: result.rows.length, }); return res.json({ success: true, data: result.rows, }); } catch (error: any) { logger.error("자재 목록 조회 실패", error); return res.status(500).json({ success: false, message: "자재 목록 조회 중 오류가 발생했습니다.", error: error.message, }); } }; // Location별 자재 개수 조회 (배치 시 사용 - 사용자 지정 테이블) export const getMaterialCounts = async (req: Request, res: Response): Promise => { try { const { externalDbConnectionId, tableName, locaKeys } = req.query; if (!externalDbConnectionId || !tableName || !locaKeys) { return res.status(400).json({ success: false, message: "외부 DB 연결 ID, 테이블명, Location 키 목록이 필요합니다.", }); } const connector = await getExternalDbConnector(Number(externalDbConnectionId)); // locaKeys는 쉼표로 구분된 문자열 const locaKeyArray = (locaKeys as string).split(","); const quotedKeys = locaKeyArray.map((key) => `'${key}'`).join(","); const query = ` SELECT LOCAKEY, COUNT(*) as material_count, MAX(LOLAYER) as max_layer FROM ${tableName} WHERE LOCAKEY IN (${quotedKeys}) GROUP BY LOCAKEY `; const result = await connector.executeQuery(query); logger.info("자재 개수 조회", { externalDbConnectionId, tableName, locaKeyCount: locaKeyArray.length, }); return res.json({ success: true, data: result.rows, }); } catch (error: any) { logger.error("자재 개수 조회 실패", error); return res.status(500).json({ success: false, message: "자재 개수 조회 중 오류가 발생했습니다.", error: error.message, }); } };