회사관리, 메뉴관리 수정,삭제 기능
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import { Response } from "express";
|
||||
import { Request } from "express";
|
||||
import { AuthenticatedRequest } from "../types/auth";
|
||||
import { AdminService } from "../services/adminService";
|
||||
import { Request, Response } from "express";
|
||||
import { logger } from "../utils/logger";
|
||||
import { ApiResponse } from "../types/auth";
|
||||
import { AuthenticatedRequest } from "../types/auth";
|
||||
import { ApiResponse } from "../types/common";
|
||||
import { Client } from "pg";
|
||||
import { AdminService } from "../services/adminService";
|
||||
|
||||
/**
|
||||
* 관리자 메뉴 목록 조회
|
||||
@@ -250,15 +250,47 @@ export const getUserList = async (req: AuthenticatedRequest, res: Response) => {
|
||||
export const getUserLocale = async (
|
||||
req: AuthenticatedRequest,
|
||||
res: Response
|
||||
) => {
|
||||
): Promise<void> => {
|
||||
try {
|
||||
logger.info("사용자 로케일 조회 요청", {
|
||||
query: req.query,
|
||||
user: req.user,
|
||||
});
|
||||
|
||||
// 임시 더미 데이터 반환 (실제로는 데이터베이스에서 조회)
|
||||
const userLocale = "ko"; // 기본값
|
||||
if (!req.user?.userId) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
message: "사용자 정보가 없습니다.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 데이터베이스에서 사용자 로케일 조회
|
||||
const prisma = (await import("../config/database")).default;
|
||||
|
||||
const userInfo = await prisma.user_info.findFirst({
|
||||
where: {
|
||||
user_id: req.user.userId,
|
||||
},
|
||||
select: {
|
||||
locale: true,
|
||||
},
|
||||
});
|
||||
|
||||
let userLocale = "en"; // 기본값
|
||||
|
||||
if (userInfo?.locale) {
|
||||
userLocale = userInfo.locale;
|
||||
logger.info("데이터베이스에서 사용자 로케일 조회 성공", {
|
||||
userId: req.user.userId,
|
||||
locale: userLocale,
|
||||
});
|
||||
} else {
|
||||
logger.info("사용자 로케일이 설정되지 않음, 기본값 사용", {
|
||||
userId: req.user.userId,
|
||||
defaultLocale: userLocale,
|
||||
});
|
||||
}
|
||||
|
||||
const response = {
|
||||
success: true,
|
||||
@@ -268,6 +300,8 @@ export const getUserLocale = async (
|
||||
|
||||
logger.info("사용자 로케일 조회 성공", {
|
||||
userLocale,
|
||||
userId: req.user.userId,
|
||||
fromDatabase: !!userInfo?.locale,
|
||||
});
|
||||
|
||||
res.status(200).json(response);
|
||||
@@ -282,7 +316,76 @@ export const getUserLocale = async (
|
||||
};
|
||||
|
||||
/**
|
||||
* GET /api/admin/companies
|
||||
* 사용자 로케일 설정
|
||||
*/
|
||||
export const setUserLocale = async (
|
||||
req: AuthenticatedRequest,
|
||||
res: Response
|
||||
): Promise<void> => {
|
||||
try {
|
||||
logger.info("사용자 로케일 설정 요청", {
|
||||
body: req.body,
|
||||
user: req.user,
|
||||
});
|
||||
|
||||
if (!req.user?.userId) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
message: "사용자 정보가 없습니다.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const { locale } = req.body;
|
||||
|
||||
if (!locale || !["ko", "en", "ja", "zh"].includes(locale)) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
message: "유효하지 않은 로케일입니다. (ko, en, ja, zh 중 선택)",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 데이터베이스에 사용자 로케일 저장
|
||||
const prisma = (await import("../config/database")).default;
|
||||
|
||||
await prisma.user_info.update({
|
||||
where: {
|
||||
user_id: req.user.userId,
|
||||
},
|
||||
data: {
|
||||
locale: locale,
|
||||
},
|
||||
});
|
||||
|
||||
logger.info("사용자 로케일을 데이터베이스에 저장 완료", {
|
||||
locale,
|
||||
userId: req.user.userId,
|
||||
});
|
||||
|
||||
const response = {
|
||||
success: true,
|
||||
data: locale,
|
||||
message: "사용자 로케일 설정 성공",
|
||||
};
|
||||
|
||||
logger.info("사용자 로케일 설정 성공", {
|
||||
locale,
|
||||
userId: req.user.userId,
|
||||
});
|
||||
|
||||
res.status(200).json(response);
|
||||
} catch (error) {
|
||||
logger.error("사용자 로케일 설정 실패", { error });
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: "사용자 로케일 설정 중 오류가 발생했습니다.",
|
||||
error: error instanceof Error ? error.message : "Unknown error",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 회사 목록 조회 API
|
||||
*/
|
||||
export const getCompanyList = async (
|
||||
@@ -300,17 +403,27 @@ export const getCompanyList = async (
|
||||
{
|
||||
company_code: "ILSHIN",
|
||||
company_name: "일신제강",
|
||||
status: "active",
|
||||
writer: "admin",
|
||||
regdate: new Date().toISOString(),
|
||||
},
|
||||
{
|
||||
company_code: "HUTECH",
|
||||
company_name: "후테크",
|
||||
status: "active",
|
||||
writer: "admin",
|
||||
regdate: new Date().toISOString(),
|
||||
},
|
||||
{
|
||||
company_code: "DAIN",
|
||||
company_name: "다인",
|
||||
status: "active",
|
||||
writer: "admin",
|
||||
regdate: new Date().toISOString(),
|
||||
},
|
||||
];
|
||||
|
||||
// 프론트엔드에서 기대하는 응답 형식으로 변환
|
||||
const response = {
|
||||
success: true,
|
||||
data: dummyCompanies,
|
||||
@@ -319,6 +432,7 @@ export const getCompanyList = async (
|
||||
|
||||
logger.info("회사 목록 조회 성공", {
|
||||
totalCount: dummyCompanies.length,
|
||||
response: response,
|
||||
});
|
||||
|
||||
res.status(200).json(response);
|
||||
@@ -390,7 +504,10 @@ export async function getLangKeyList(
|
||||
res: Response
|
||||
): Promise<void> {
|
||||
try {
|
||||
logger.info("다국어 키 목록 조회 요청");
|
||||
logger.info("다국어 키 목록 조회 요청", {
|
||||
query: req.query,
|
||||
user: req.user,
|
||||
});
|
||||
|
||||
// 더미 데이터 반환
|
||||
const langKeys = [
|
||||
@@ -401,6 +518,10 @@ export async function getLangKeyList(
|
||||
langKey: "user.management.title",
|
||||
description: "사용자 관리 페이지 제목",
|
||||
isActive: "Y",
|
||||
createdDate: new Date().toISOString(),
|
||||
createdBy: "admin",
|
||||
updatedDate: new Date().toISOString(),
|
||||
updatedBy: "admin",
|
||||
},
|
||||
{
|
||||
keyId: 2,
|
||||
@@ -409,6 +530,10 @@ export async function getLangKeyList(
|
||||
langKey: "menu.management.title",
|
||||
description: "메뉴 관리 페이지 제목",
|
||||
isActive: "Y",
|
||||
createdDate: new Date().toISOString(),
|
||||
createdBy: "admin",
|
||||
updatedDate: new Date().toISOString(),
|
||||
updatedBy: "admin",
|
||||
},
|
||||
{
|
||||
keyId: 3,
|
||||
@@ -417,15 +542,25 @@ export async function getLangKeyList(
|
||||
langKey: "dashboard.title",
|
||||
description: "대시보드 페이지 제목",
|
||||
isActive: "Y",
|
||||
createdDate: new Date().toISOString(),
|
||||
createdBy: "admin",
|
||||
updatedDate: new Date().toISOString(),
|
||||
updatedBy: "admin",
|
||||
},
|
||||
];
|
||||
|
||||
// 프론트엔드에서 기대하는 응답 형식으로 변환
|
||||
const response: ApiResponse<any[]> = {
|
||||
success: true,
|
||||
message: "다국어 키 목록 조회 성공",
|
||||
data: langKeys,
|
||||
};
|
||||
|
||||
logger.info("다국어 키 목록 조회 성공", {
|
||||
totalCount: langKeys.length,
|
||||
response: response,
|
||||
});
|
||||
|
||||
res.status(200).json(response);
|
||||
} catch (error) {
|
||||
logger.error("다국어 키 목록 조회 실패:", error);
|
||||
@@ -724,3 +859,403 @@ export async function toggleLanguageStatus(
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 메뉴 저장 (추가/수정)
|
||||
*/
|
||||
export async function saveMenu(
|
||||
req: AuthenticatedRequest,
|
||||
res: Response
|
||||
): Promise<void> {
|
||||
try {
|
||||
const menuData = req.body;
|
||||
logger.info("메뉴 저장 요청", { menuData, user: req.user });
|
||||
|
||||
// PostgreSQL 클라이언트 생성
|
||||
const client = new Client({
|
||||
connectionString:
|
||||
process.env.DATABASE_URL ||
|
||||
"postgresql://postgres:postgres@localhost:5432/ilshin",
|
||||
});
|
||||
|
||||
await client.connect();
|
||||
|
||||
// 실제 데이터베이스에 저장
|
||||
const query = `
|
||||
INSERT INTO menu_info (
|
||||
objid, menu_type, parent_obj_id, menu_name_kor, menu_name_eng,
|
||||
seq, menu_url, menu_desc, writer, regdate, status,
|
||||
system_name, company_code, lang_key, lang_key_desc
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15
|
||||
) RETURNING *
|
||||
`;
|
||||
|
||||
const values = [
|
||||
Date.now(), // objid
|
||||
menuData.menuType || null, // menu_type
|
||||
menuData.parentObjId || null, // parent_obj_id
|
||||
menuData.menuNameKor, // menu_name_kor
|
||||
menuData.menuNameEng || null, // menu_name_eng
|
||||
menuData.seq || null, // seq
|
||||
menuData.menuUrl || null, // menu_url
|
||||
menuData.menuDesc || null, // menu_desc
|
||||
req.user?.userId || "admin", // writer
|
||||
new Date(), // regdate
|
||||
menuData.status || "active", // status
|
||||
menuData.systemName || "PLM", // system_name
|
||||
menuData.companyCode || "*", // company_code
|
||||
menuData.langKey || null, // lang_key
|
||||
menuData.langKeyDesc || null, // lang_key_desc
|
||||
];
|
||||
|
||||
const result = await client.query(query, values);
|
||||
const savedMenu = result.rows[0];
|
||||
|
||||
await client.end();
|
||||
|
||||
logger.info("메뉴 저장 성공", { savedMenu });
|
||||
|
||||
const response: ApiResponse<any> = {
|
||||
success: true,
|
||||
message: "메뉴가 성공적으로 저장되었습니다.",
|
||||
data: {
|
||||
objid: savedMenu.objid,
|
||||
menuNameKor: savedMenu.menu_name_kor,
|
||||
menuNameEng: savedMenu.menu_name_eng,
|
||||
menuUrl: savedMenu.menu_url,
|
||||
menuDesc: savedMenu.menu_desc,
|
||||
status: savedMenu.status,
|
||||
writer: savedMenu.writer,
|
||||
regdate: savedMenu.regdate,
|
||||
},
|
||||
};
|
||||
|
||||
res.status(200).json(response);
|
||||
} catch (error) {
|
||||
logger.error("메뉴 저장 실패:", error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: "메뉴 저장 중 오류가 발생했습니다.",
|
||||
error: error instanceof Error ? error.message : "Unknown error",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 메뉴 수정
|
||||
*/
|
||||
export async function updateMenu(
|
||||
req: AuthenticatedRequest,
|
||||
res: Response
|
||||
): Promise<void> {
|
||||
try {
|
||||
const { menuId } = req.params;
|
||||
const menuData = req.body;
|
||||
logger.info(`메뉴 수정 요청: menuId = ${menuId}`, {
|
||||
menuData,
|
||||
user: req.user,
|
||||
});
|
||||
|
||||
// PostgreSQL 클라이언트 생성
|
||||
const client = new Client({
|
||||
connectionString:
|
||||
process.env.DATABASE_URL ||
|
||||
"postgresql://postgres:postgres@localhost:5432/ilshin",
|
||||
});
|
||||
|
||||
await client.connect();
|
||||
|
||||
// 실제 데이터베이스에서 메뉴 수정
|
||||
const query = `
|
||||
UPDATE menu_info
|
||||
SET
|
||||
menu_type = $1,
|
||||
parent_obj_id = $2,
|
||||
menu_name_kor = $3,
|
||||
menu_name_eng = $4,
|
||||
seq = $5,
|
||||
menu_url = $6,
|
||||
menu_desc = $7,
|
||||
status = $8,
|
||||
system_name = $9,
|
||||
company_code = $10,
|
||||
lang_key = $11,
|
||||
lang_key_desc = $12
|
||||
WHERE objid = $13
|
||||
RETURNING *
|
||||
`;
|
||||
|
||||
const values = [
|
||||
menuData.menuType ? BigInt(menuData.menuType) : null, // menu_type
|
||||
menuData.parentObjId ? BigInt(menuData.parentObjId) : null, // parent_obj_id
|
||||
menuData.menuNameKor, // menu_name_kor
|
||||
menuData.menuNameEng || null, // menu_name_eng
|
||||
menuData.seq ? BigInt(menuData.seq) : null, // seq
|
||||
menuData.menuUrl || null, // menu_url
|
||||
menuData.menuDesc || null, // menu_desc
|
||||
menuData.status || "active", // status
|
||||
menuData.systemName || "PLM", // system_name
|
||||
menuData.companyCode || "*", // company_code
|
||||
menuData.langKey || null, // lang_key
|
||||
menuData.langKeyDesc || null, // lang_key_desc
|
||||
BigInt(menuId), // objid (WHERE 조건)
|
||||
];
|
||||
|
||||
const result = await client.query(query, values);
|
||||
|
||||
if (result.rowCount === 0) {
|
||||
await client.end();
|
||||
res.status(404).json({
|
||||
success: false,
|
||||
message: "수정할 메뉴를 찾을 수 없습니다.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const updatedMenu = result.rows[0];
|
||||
await client.end();
|
||||
|
||||
logger.info("메뉴 수정 성공", { updatedMenu });
|
||||
|
||||
const response: ApiResponse<any> = {
|
||||
success: true,
|
||||
message: "메뉴가 성공적으로 수정되었습니다.",
|
||||
data: {
|
||||
objid: updatedMenu.objid.toString(),
|
||||
menuNameKor: updatedMenu.menu_name_kor,
|
||||
menuNameEng: updatedMenu.menu_name_eng,
|
||||
menuUrl: updatedMenu.menu_url,
|
||||
menuDesc: updatedMenu.menu_desc,
|
||||
status: updatedMenu.status,
|
||||
writer: updatedMenu.writer,
|
||||
regdate: updatedMenu.regdate,
|
||||
},
|
||||
};
|
||||
|
||||
res.status(200).json(response);
|
||||
} catch (error) {
|
||||
logger.error("메뉴 수정 실패:", error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: "메뉴 수정 중 오류가 발생했습니다.",
|
||||
error: error instanceof Error ? error.message : "Unknown error",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 메뉴 삭제
|
||||
*/
|
||||
export async function deleteMenu(
|
||||
req: AuthenticatedRequest,
|
||||
res: Response
|
||||
): Promise<void> {
|
||||
try {
|
||||
const { menuId } = req.params;
|
||||
logger.info(`메뉴 삭제 요청: menuId = ${menuId}`, { user: req.user });
|
||||
|
||||
// PostgreSQL 클라이언트 생성
|
||||
const client = new Client({
|
||||
connectionString:
|
||||
process.env.DATABASE_URL ||
|
||||
"postgresql://postgres:postgres@localhost:5432/ilshin",
|
||||
});
|
||||
|
||||
await client.connect();
|
||||
|
||||
// 실제 데이터베이스에서 메뉴 삭제
|
||||
const query = `
|
||||
DELETE FROM menu_info
|
||||
WHERE objid = $1
|
||||
RETURNING *
|
||||
`;
|
||||
|
||||
const result = await client.query(query, [BigInt(menuId)]);
|
||||
|
||||
if (result.rowCount === 0) {
|
||||
await client.end();
|
||||
res.status(404).json({
|
||||
success: false,
|
||||
message: "삭제할 메뉴를 찾을 수 없습니다.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const deletedMenu = result.rows[0];
|
||||
await client.end();
|
||||
|
||||
logger.info("메뉴 삭제 성공", { deletedMenu });
|
||||
|
||||
const response: ApiResponse<any> = {
|
||||
success: true,
|
||||
message: "메뉴가 성공적으로 삭제되었습니다.",
|
||||
data: {
|
||||
objid: deletedMenu.objid.toString(),
|
||||
menuNameKor: deletedMenu.menu_name_kor,
|
||||
menuNameEng: deletedMenu.menu_name_eng,
|
||||
menuUrl: deletedMenu.menu_url,
|
||||
menuDesc: deletedMenu.menu_desc,
|
||||
status: deletedMenu.status,
|
||||
writer: deletedMenu.writer,
|
||||
regdate: deletedMenu.regdate,
|
||||
},
|
||||
};
|
||||
|
||||
res.status(200).json(response);
|
||||
} catch (error) {
|
||||
logger.error("메뉴 삭제 실패:", error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: "메뉴 삭제 중 오류가 발생했습니다.",
|
||||
error: error instanceof Error ? error.message : "Unknown error",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 메뉴 일괄 삭제
|
||||
*/
|
||||
export async function deleteMenusBatch(
|
||||
req: AuthenticatedRequest,
|
||||
res: Response
|
||||
): Promise<void> {
|
||||
try {
|
||||
const menuIds = req.body as string[];
|
||||
logger.info("메뉴 일괄 삭제 요청", { menuIds, user: req.user });
|
||||
|
||||
if (!Array.isArray(menuIds) || menuIds.length === 0) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
message: "삭제할 메뉴 ID 목록이 필요합니다.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// PostgreSQL 클라이언트 생성
|
||||
const client = new Client({
|
||||
connectionString:
|
||||
process.env.DATABASE_URL ||
|
||||
"postgresql://postgres:postgres@localhost:5432/ilshin",
|
||||
});
|
||||
|
||||
await client.connect();
|
||||
|
||||
let deletedCount = 0;
|
||||
let failedCount = 0;
|
||||
const deletedMenus: any[] = [];
|
||||
const failedMenuIds: string[] = [];
|
||||
|
||||
// 각 메뉴 ID에 대해 삭제 시도
|
||||
for (const menuId of menuIds) {
|
||||
try {
|
||||
const query = `
|
||||
DELETE FROM menu_info
|
||||
WHERE objid = $1
|
||||
RETURNING *
|
||||
`;
|
||||
|
||||
const result = await client.query(query, [BigInt(menuId)]);
|
||||
|
||||
if (result.rowCount && result.rowCount > 0) {
|
||||
deletedCount++;
|
||||
deletedMenus.push(result.rows[0]);
|
||||
} else {
|
||||
failedCount++;
|
||||
failedMenuIds.push(menuId);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`메뉴 삭제 실패 (ID: ${menuId}):`, error);
|
||||
failedCount++;
|
||||
failedMenuIds.push(menuId);
|
||||
}
|
||||
}
|
||||
|
||||
await client.end();
|
||||
|
||||
logger.info("메뉴 일괄 삭제 완료", {
|
||||
total: menuIds.length,
|
||||
deletedCount,
|
||||
failedCount,
|
||||
deletedMenus,
|
||||
failedMenuIds,
|
||||
});
|
||||
|
||||
const response: ApiResponse<any> = {
|
||||
success: true,
|
||||
message: `메뉴 일괄 삭제 완료: ${deletedCount}개 삭제, ${failedCount}개 실패`,
|
||||
data: {
|
||||
deletedCount,
|
||||
failedCount,
|
||||
total: menuIds.length,
|
||||
deletedMenus,
|
||||
failedMenuIds,
|
||||
},
|
||||
};
|
||||
|
||||
res.status(200).json(response);
|
||||
} catch (error) {
|
||||
logger.error("메뉴 일괄 삭제 실패:", error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: "메뉴 일괄 삭제 중 오류가 발생했습니다.",
|
||||
error: error instanceof Error ? error.message : "Unknown error",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 회사 목록 조회 (실제 데이터베이스에서)
|
||||
*/
|
||||
export async function getCompanyListFromDB(
|
||||
req: AuthenticatedRequest,
|
||||
res: Response
|
||||
): Promise<void> {
|
||||
try {
|
||||
logger.info("회사 목록 조회 요청 (DB)", { user: req.user });
|
||||
|
||||
// PostgreSQL 클라이언트 생성
|
||||
const client = new Client({
|
||||
connectionString:
|
||||
process.env.DATABASE_URL ||
|
||||
"postgresql://postgres:postgres@localhost:5432/ilshin",
|
||||
});
|
||||
|
||||
await client.connect();
|
||||
|
||||
// company_mng 테이블에서 회사 목록 조회
|
||||
const query = `
|
||||
SELECT
|
||||
company_code,
|
||||
company_name,
|
||||
writer,
|
||||
regdate,
|
||||
status
|
||||
FROM company_mng
|
||||
ORDER BY regdate DESC
|
||||
`;
|
||||
|
||||
const result = await client.query(query);
|
||||
const companies = result.rows;
|
||||
|
||||
await client.end();
|
||||
|
||||
logger.info("회사 목록 조회 성공 (DB)", { count: companies.length });
|
||||
|
||||
const response: ApiResponse<any> = {
|
||||
success: true,
|
||||
message: "회사 목록 조회 성공",
|
||||
data: companies,
|
||||
total: companies.length,
|
||||
};
|
||||
|
||||
res.status(200).json(response);
|
||||
} catch (error) {
|
||||
logger.error("회사 목록 조회 실패 (DB):", error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: "회사 목록 조회 중 오류가 발생했습니다.",
|
||||
error: error instanceof Error ? error.message : "Unknown error",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user