From bde5f0884ac5ee6987c56bf820f6b4940a5f4fb7 Mon Sep 17 00:00:00 2001 From: hyeonsu Date: Mon, 1 Sep 2025 11:18:25 +0900 Subject: [PATCH] =?UTF-8?q?=EA=B0=84=EB=8B=A8=ED=95=9C=20crud=20=EB=B6=80?= =?UTF-8?q?=EB=B6=84=20prisma=20orm=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/controllers/adminController.ts | 464 +++++++----------- 1 file changed, 190 insertions(+), 274 deletions(-) diff --git a/backend-node/src/controllers/adminController.ts b/backend-node/src/controllers/adminController.ts index 4ca152ec..6b480304 100644 --- a/backend-node/src/controllers/adminController.ts +++ b/backend-node/src/controllers/adminController.ts @@ -547,61 +547,48 @@ export const getCompanyList = async ( user: req.user, }); - // PostgreSQL 클라이언트 생성 - const client = new Client({ - connectionString: - process.env.DATABASE_URL || - "postgresql://postgres:postgres@localhost:5432/ilshin", + // Prisma ORM을 사용한 회사 목록 조회 + const companies = await prisma.company_mng.findMany({ + where: { + OR: [{ status: "active" }, { status: null }], + }, + orderBy: { + company_name: "asc", + }, + select: { + company_code: true, + company_name: true, + status: true, + writer: true, + regdate: true, + }, }); - await client.connect(); + // 프론트엔드에서 기대하는 응답 형식으로 변환 + const response = { + success: true, + data: companies.map((company) => ({ + company_code: company.company_code, + company_name: company.company_name, + status: company.status || "active", + writer: company.writer, + regdate: company.regdate + ? company.regdate.toISOString() + : new Date().toISOString(), + data_type: "company", + })), + message: "회사 목록 조회 성공", + }; - try { - // 회사 목록 조회 쿼리 - const query = ` - SELECT - company_code, - company_name, - status, - writer, - regdate, - 'company' as data_type - FROM company_mng - WHERE status = 'active' OR status IS NULL - ORDER BY company_name - `; + logger.info("회사 목록 조회 성공", { + totalCount: companies.length, + companies: companies.map((c) => ({ + code: c.company_code, + name: c.company_name, + })), + }); - const result = await client.query(query); - const companies = result.rows; - - // 프론트엔드에서 기대하는 응답 형식으로 변환 - const response = { - success: true, - data: companies.map((company) => ({ - company_code: company.company_code, - company_name: company.company_name, - status: company.status || "active", - writer: company.writer, - regdate: company.regdate - ? company.regdate.toISOString() - : new Date().toISOString(), - data_type: company.data_type, - })), - message: "회사 목록 조회 성공", - }; - - logger.info("회사 목록 조회 성공", { - totalCount: companies.length, - companies: companies.map((c) => ({ - code: c.company_code, - name: c.company_name, - })), - }); - - res.status(200).json(response); - } finally { - await client.end(); - } + res.status(200).json(response); } catch (error) { logger.error("회사 목록 조회 실패", { error }); res.status(500).json({ @@ -1433,78 +1420,89 @@ export const getDepartmentList = async ( const { companyCode, status, search } = req.query; - // PostgreSQL 클라이언트 생성 - const client = new Client({ - connectionString: - process.env.DATABASE_URL || - "postgresql://postgres:postgres@localhost:5432/ilshin", + // Prisma ORM을 사용한 부서 목록 조회 + const whereConditions: any = {}; + + // 회사 코드 필터 + if (companyCode) { + whereConditions.company_name = companyCode; + } + + // 상태 필터 + if (status) { + whereConditions.status = status; + } + + // 검색 조건 + if (search) { + whereConditions.OR = [ + { dept_name: { contains: search as string, mode: "insensitive" } }, + { dept_code: { contains: search as string, mode: "insensitive" } }, + { location_name: { contains: search as string, mode: "insensitive" } }, + ]; + } + + const departments = await prisma.dept_info.findMany({ + where: whereConditions, + orderBy: [{ parent_dept_code: "asc" }, { dept_name: "asc" }], + select: { + dept_code: true, + parent_dept_code: true, + dept_name: true, + master_sabun: true, + master_user_id: true, + location: true, + location_name: true, + regdate: true, + data_type: true, + status: true, + sales_yn: true, + company_name: true, + }, }); - await client.connect(); + // 부서 트리 구조 생성 + const deptMap = new Map(); + const rootDepartments: any[] = []; - try { - // 부서 목록 조회 쿼리 - let query = ` - SELECT - dept_code, - parent_dept_code, - dept_name, - master_sabun, - master_user_id, - location, - location_name, - regdate, - data_type, - status, - sales_yn, - company_name - FROM dept_info - WHERE 1=1 - `; + // 모든 부서를 맵에 저장 + departments.forEach((dept) => { + deptMap.set(dept.dept_code, { + deptCode: dept.dept_code, + deptName: dept.dept_name, + parentDeptCode: dept.parent_dept_code, + masterSabun: dept.master_sabun, + masterUserId: dept.master_user_id, + location: dept.location, + locationName: dept.location_name, + regdate: dept.regdate ? dept.regdate.toISOString() : null, + dataType: dept.data_type, + status: dept.status || "active", + salesYn: dept.sales_yn, + companyName: dept.company_name, + children: [], + }); + }); - const queryParams: any[] = []; - let paramIndex = 1; + // 부서 트리 구조 생성 + departments.forEach((dept) => { + const deptNode = deptMap.get(dept.dept_code); - // 회사 코드 필터 - if (companyCode) { - query += ` AND company_name = $${paramIndex}`; - queryParams.push(companyCode); - paramIndex++; + if (dept.parent_dept_code && deptMap.has(dept.parent_dept_code)) { + // 상위 부서가 있으면 children에 추가 + const parentDept = deptMap.get(dept.parent_dept_code); + parentDept.children.push(deptNode); + } else { + // 상위 부서가 없으면 루트 부서로 추가 + rootDepartments.push(deptNode); } + }); - // 상태 필터 - if (status) { - query += ` AND status = $${paramIndex}`; - queryParams.push(status); - paramIndex++; - } - - // 검색 조건 - if (search) { - query += ` AND ( - dept_name ILIKE $${paramIndex} OR - dept_code ILIKE $${paramIndex} OR - location_name ILIKE $${paramIndex} - )`; - queryParams.push(`%${search}%`); - paramIndex++; - } - - // 정렬 (상위 부서 먼저, 그 다음 부서명 순) - query += ` ORDER BY - CASE WHEN parent_dept_code IS NULL OR parent_dept_code = '' THEN 0 ELSE 1 END, - dept_name`; - - const result = await client.query(query, queryParams); - const departments = result.rows; - - // 부서 트리 구조 생성 - const deptMap = new Map(); - const rootDepartments: any[] = []; - - // 모든 부서를 맵에 저장 - departments.forEach((dept) => { - deptMap.set(dept.dept_code, { + const response = { + success: true, + data: { + departments: rootDepartments, + flatList: departments.map((dept) => ({ deptCode: dept.dept_code, deptName: dept.dept_name, parentDeptCode: dept.parent_dept_code, @@ -1517,56 +1515,18 @@ export const getDepartmentList = async ( status: dept.status || "active", salesYn: dept.sales_yn, companyName: dept.company_name, - children: [], - }); - }); + })), + }, + message: "부서 목록 조회 성공", + total: departments.length, + }; - // 부서 트리 구조 생성 - departments.forEach((dept) => { - const deptNode = deptMap.get(dept.dept_code); + logger.info("부서 목록 조회 성공", { + totalCount: departments.length, + rootCount: rootDepartments.length, + }); - if (dept.parent_dept_code && deptMap.has(dept.parent_dept_code)) { - // 상위 부서가 있으면 children에 추가 - const parentDept = deptMap.get(dept.parent_dept_code); - parentDept.children.push(deptNode); - } else { - // 상위 부서가 없으면 루트 부서로 추가 - rootDepartments.push(deptNode); - } - }); - - const response = { - success: true, - data: { - departments: rootDepartments, - flatList: departments.map((dept) => ({ - deptCode: dept.dept_code, - deptName: dept.dept_name, - parentDeptCode: dept.parent_dept_code, - masterSabun: dept.master_sabun, - masterUserId: dept.master_user_id, - location: dept.location, - locationName: dept.location_name, - regdate: dept.regdate ? dept.regdate.toISOString() : null, - dataType: dept.data_type, - status: dept.status || "active", - salesYn: dept.sales_yn, - companyName: dept.company_name, - })), - }, - message: "부서 목록 조회 성공", - total: departments.length, - }; - - logger.info("부서 목록 조회 성공", { - totalCount: departments.length, - rootCount: rootDepartments.length, - }); - - res.status(200).json(response); - } finally { - await client.end(); - } + res.status(200).json(response); } catch (error) { logger.error("부서 목록 조회 실패", { error }); res.status(500).json({ @@ -2122,121 +2082,77 @@ export const saveUser = async (req: AuthenticatedRequest, res: Response) => { } } - // PostgreSQL 클라이언트 생성 - const client = new Client({ - connectionString: - process.env.DATABASE_URL || - "postgresql://postgres:postgres@localhost:5432/ilshin", + // 비밀번호 암호화 + const encryptedPassword = await EncryptUtil.encrypt(userData.userPassword); + + // Prisma ORM을 사용한 사용자 저장 (upsert) + const savedUser = await prisma.user_info.upsert({ + where: { + user_id: userData.userId, + }, + create: { + user_id: userData.userId, + user_name: userData.userName, + user_name_eng: userData.userNameEng || null, + user_password: encryptedPassword, + dept_code: userData.deptCode || null, + dept_name: userData.deptName || null, + position_code: userData.positionCode || null, + position_name: userData.positionName || null, + email: userData.email || null, + tel: userData.tel || null, + cell_phone: userData.cellPhone || null, + user_type: userData.userType || null, + user_type_name: userData.userTypeName || null, + sabun: userData.sabun || null, + company_code: userData.companyCode || null, + status: userData.status || "active", + locale: userData.locale || null, + regdate: new Date(), + }, + update: { + user_name: userData.userName, + user_name_eng: userData.userNameEng || null, + user_password: encryptedPassword, + dept_code: userData.deptCode || null, + dept_name: userData.deptName || null, + position_code: userData.positionCode || null, + position_name: userData.positionName || null, + email: userData.email || null, + tel: userData.tel || null, + cell_phone: userData.cellPhone || null, + user_type: userData.userType || null, + user_type_name: userData.userTypeName || null, + sabun: userData.sabun || null, + company_code: userData.companyCode || null, + status: userData.status || "active", + locale: userData.locale || null, + }, }); - await client.connect(); + // 기존 사용자인지 새 사용자인지 확인 + const isUpdate = + (await prisma.user_info.count({ + where: { user_id: userData.userId }, + })) > 0; - try { - // 기존 사용자 확인 - const checkQuery = ` - SELECT user_id FROM user_info WHERE user_id = $1 - `; - const checkResult = await client.query(checkQuery, [userData.userId]); - const isUpdate = checkResult.rows.length > 0; + logger.info(isUpdate ? "사용자 정보 수정 완료" : "새 사용자 등록 완료", { + userId: userData.userId, + }); - if (isUpdate) { - // 기존 사용자 수정 - const updateQuery = ` - UPDATE user_info SET - user_name = $1, - user_name_eng = $2, - user_password = $3, - dept_code = $4, - dept_name = $5, - position_code = $6, - position_name = $7, - email = $8, - tel = $9, - cell_phone = $10, - user_type = $11, - user_type_name = $12, - sabun = $13, - company_code = $14, - status = $15, - locale = $16 - WHERE user_id = $17 - `; + const response = { + success: true, + result: true, + message: isUpdate + ? "사용자 정보가 수정되었습니다." + : "사용자가 등록되었습니다.", + data: { + userId: userData.userId, + isUpdate, + }, + }; - const updateValues = [ - userData.userName, - userData.userNameEng || null, - await EncryptUtil.encrypt(userData.userPassword), // 비밀번호 암호화 - userData.deptCode || null, - userData.deptName || null, - userData.positionCode || null, - userData.positionName || null, - userData.email || null, - userData.tel || null, - userData.cellPhone || null, - userData.userType || null, - userData.userTypeName || null, - userData.sabun || null, - userData.companyCode || null, - userData.status || "active", - userData.locale || null, - userData.userId, - ]; - - await client.query(updateQuery, updateValues); - logger.info("사용자 정보 수정 완료", { userId: userData.userId }); - } else { - // 새 사용자 등록 - const insertQuery = ` - INSERT INTO user_info ( - user_id, user_name, user_name_eng, user_password, dept_code, dept_name, - position_code, position_name, email, tel, cell_phone, user_type, - user_type_name, sabun, company_code, status, locale, regdate - ) VALUES ( - $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18 - ) - `; - - const insertValues = [ - userData.userId, - userData.userName, - userData.userNameEng || null, - await EncryptUtil.encrypt(userData.userPassword), // 비밀번호 암호화 - userData.deptCode || null, - userData.deptName || null, - userData.positionCode || null, - userData.positionName || null, - userData.email || null, - userData.tel || null, - userData.cellPhone || null, - userData.userType || null, - userData.userTypeName || null, - userData.sabun || null, - userData.companyCode || null, - userData.status || "active", - userData.locale || null, - new Date(), - ]; - - await client.query(insertQuery, insertValues); - logger.info("새 사용자 등록 완료", { userId: userData.userId }); - } - - const response = { - success: true, - result: true, - message: isUpdate - ? "사용자 정보가 수정되었습니다." - : "사용자가 등록되었습니다.", - data: { - userId: userData.userId, - isUpdate, - }, - }; - - res.status(200).json(response); - } finally { - await client.end(); - } + res.status(200).json(response); } catch (error) { logger.error("사용자 저장 실패", { error, userData: req.body }); res.status(500).json({