node-nonquery #10
File diff suppressed because it is too large
Load Diff
|
|
@ -662,61 +662,53 @@ export async function getLangKeyList(
|
|||
user: req.user,
|
||||
});
|
||||
|
||||
// 실제 데이터베이스에서 데이터 조회
|
||||
const client = new Client({
|
||||
host: process.env.DB_HOST || "localhost",
|
||||
port: parseInt(process.env.DB_PORT || "5432"),
|
||||
database: process.env.DB_NAME || "ilshin",
|
||||
user: process.env.DB_USER || "postgres",
|
||||
password: process.env.DB_PASSWORD || "postgres",
|
||||
// Prisma ORM을 사용한 다국어 키 목록 조회
|
||||
const result = await prisma.multi_lang_key_master.findMany({
|
||||
orderBy: [
|
||||
{ company_code: "asc" },
|
||||
{ menu_name: "asc" },
|
||||
{ lang_key: "asc" },
|
||||
],
|
||||
select: {
|
||||
key_id: true,
|
||||
company_code: true,
|
||||
menu_name: true,
|
||||
lang_key: true,
|
||||
description: true,
|
||||
is_active: true,
|
||||
created_date: true,
|
||||
created_by: true,
|
||||
updated_date: true,
|
||||
updated_by: true,
|
||||
},
|
||||
});
|
||||
|
||||
await client.connect();
|
||||
const langKeys = result.map((row) => ({
|
||||
keyId: row.key_id,
|
||||
companyCode: row.company_code,
|
||||
menuName: row.menu_name,
|
||||
langKey: row.lang_key,
|
||||
description: row.description,
|
||||
isActive: row.is_active,
|
||||
createdDate: row.created_date?.toISOString(),
|
||||
createdBy: row.created_by,
|
||||
updatedDate: row.updated_date?.toISOString(),
|
||||
updatedBy: row.updated_by,
|
||||
}));
|
||||
|
||||
try {
|
||||
const query = `
|
||||
SELECT
|
||||
key_id as "keyId",
|
||||
company_code as "companyCode",
|
||||
menu_name as "menuName",
|
||||
lang_key as "langKey",
|
||||
description,
|
||||
is_active as "isActive",
|
||||
created_date as "createdDate",
|
||||
created_by as "createdBy",
|
||||
updated_date as "updatedDate",
|
||||
updated_by as "updatedBy"
|
||||
FROM multi_lang_key_master
|
||||
ORDER BY company_code, menu_name, lang_key
|
||||
`;
|
||||
// 프론트엔드에서 기대하는 응답 형식으로 변환
|
||||
const response: ApiResponse<any[]> = {
|
||||
success: true,
|
||||
message: "다국어 키 목록 조회 성공",
|
||||
data: langKeys,
|
||||
};
|
||||
|
||||
const result = await client.query(query);
|
||||
const langKeys = result.rows.map((row) => ({
|
||||
...row,
|
||||
createdDate: row.createdDate
|
||||
? new Date(row.createdDate).toISOString()
|
||||
: undefined,
|
||||
updatedDate: row.updatedDate
|
||||
? new Date(row.updatedDate).toISOString()
|
||||
: undefined,
|
||||
}));
|
||||
logger.info("다국어 키 목록 조회 성공", {
|
||||
totalCount: langKeys.length,
|
||||
response: response,
|
||||
});
|
||||
|
||||
// 프론트엔드에서 기대하는 응답 형식으로 변환
|
||||
const response: ApiResponse<any[]> = {
|
||||
success: true,
|
||||
message: "다국어 키 목록 조회 성공",
|
||||
data: langKeys,
|
||||
};
|
||||
|
||||
logger.info("다국어 키 목록 조회 성공", {
|
||||
totalCount: langKeys.length,
|
||||
response: response,
|
||||
});
|
||||
|
||||
res.status(200).json(response);
|
||||
} finally {
|
||||
await client.end();
|
||||
}
|
||||
res.status(200).json(response);
|
||||
} catch (error) {
|
||||
logger.error("다국어 키 목록 조회 실패:", error);
|
||||
res.status(500).json({
|
||||
|
|
@ -1026,56 +1018,36 @@ export async function saveMenu(
|
|||
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",
|
||||
// Prisma ORM을 사용한 메뉴 저장
|
||||
const savedMenu = await prisma.menu_info.create({
|
||||
data: {
|
||||
objid: Date.now(), // 고유 ID 생성
|
||||
menu_type: menuData.menuType ? Number(menuData.menuType) : null,
|
||||
parent_obj_id: menuData.parentObjId
|
||||
? Number(menuData.parentObjId)
|
||||
: null,
|
||||
menu_name_kor: menuData.menuNameKor,
|
||||
menu_name_eng: menuData.menuNameEng || null,
|
||||
seq: menuData.seq ? Number(menuData.seq) : null,
|
||||
menu_url: menuData.menuUrl || null,
|
||||
menu_desc: menuData.menuDesc || null,
|
||||
writer: req.user?.userId || "admin",
|
||||
regdate: new Date(),
|
||||
status: menuData.status || "active",
|
||||
system_name: menuData.systemName || "PLM",
|
||||
company_code: menuData.companyCode || "*",
|
||||
lang_key: menuData.langKey || null,
|
||||
lang_key_desc: menuData.langKeyDesc || null,
|
||||
},
|
||||
});
|
||||
|
||||
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,
|
||||
objid: savedMenu.objid.toString(), // BigInt를 문자열로 변환
|
||||
menuNameKor: savedMenu.menu_name_kor,
|
||||
menuNameEng: savedMenu.menu_name_eng,
|
||||
menuUrl: savedMenu.menu_url,
|
||||
|
|
@ -1112,65 +1084,29 @@ export async function updateMenu(
|
|||
user: req.user,
|
||||
});
|
||||
|
||||
// PostgreSQL 클라이언트 생성
|
||||
const client = new Client({
|
||||
connectionString:
|
||||
process.env.DATABASE_URL ||
|
||||
"postgresql://postgres:postgres@localhost:5432/ilshin",
|
||||
// Prisma ORM을 사용한 메뉴 수정
|
||||
const updatedMenu = await prisma.menu_info.update({
|
||||
where: {
|
||||
objid: Number(menuId),
|
||||
},
|
||||
data: {
|
||||
menu_type: menuData.menuType ? Number(menuData.menuType) : null,
|
||||
parent_obj_id: menuData.parentObjId
|
||||
? Number(menuData.parentObjId)
|
||||
: null,
|
||||
menu_name_kor: menuData.menuNameKor,
|
||||
menu_name_eng: menuData.menuNameEng || null,
|
||||
seq: menuData.seq ? Number(menuData.seq) : null,
|
||||
menu_url: menuData.menuUrl || null,
|
||||
menu_desc: menuData.menuDesc || null,
|
||||
status: menuData.status || "active",
|
||||
system_name: menuData.systemName || "PLM",
|
||||
company_code: menuData.companyCode || "*",
|
||||
lang_key: menuData.langKey || null,
|
||||
lang_key_desc: menuData.langKeyDesc || null,
|
||||
},
|
||||
});
|
||||
|
||||
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> = {
|
||||
|
|
@ -1210,36 +1146,13 @@ export async function deleteMenu(
|
|||
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",
|
||||
// Prisma ORM을 사용한 메뉴 삭제
|
||||
const deletedMenu = await prisma.menu_info.delete({
|
||||
where: {
|
||||
objid: Number(menuId),
|
||||
},
|
||||
});
|
||||
|
||||
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> = {
|
||||
|
|
@ -1287,15 +1200,7 @@ export async function deleteMenusBatch(
|
|||
return;
|
||||
}
|
||||
|
||||
// PostgreSQL 클라이언트 생성
|
||||
const client = new Client({
|
||||
connectionString:
|
||||
process.env.DATABASE_URL ||
|
||||
"postgresql://postgres:postgres@localhost:5432/ilshin",
|
||||
});
|
||||
|
||||
await client.connect();
|
||||
|
||||
// Prisma ORM을 사용한 메뉴 일괄 삭제
|
||||
let deletedCount = 0;
|
||||
let failedCount = 0;
|
||||
const deletedMenus: any[] = [];
|
||||
|
|
@ -1304,17 +1209,18 @@ export async function deleteMenusBatch(
|
|||
// 각 메뉴 ID에 대해 삭제 시도
|
||||
for (const menuId of menuIds) {
|
||||
try {
|
||||
const query = `
|
||||
DELETE FROM menu_info
|
||||
WHERE objid = $1
|
||||
RETURNING *
|
||||
`;
|
||||
const deletedMenu = await prisma.menu_info.delete({
|
||||
where: {
|
||||
objid: Number(menuId),
|
||||
},
|
||||
});
|
||||
|
||||
const result = await client.query(query, [BigInt(menuId)]);
|
||||
|
||||
if (result.rowCount && result.rowCount > 0) {
|
||||
if (deletedMenu) {
|
||||
deletedCount++;
|
||||
deletedMenus.push(result.rows[0]);
|
||||
deletedMenus.push({
|
||||
...deletedMenu,
|
||||
objid: deletedMenu.objid.toString(),
|
||||
});
|
||||
} else {
|
||||
failedCount++;
|
||||
failedMenuIds.push(menuId);
|
||||
|
|
@ -1326,8 +1232,6 @@ export async function deleteMenusBatch(
|
|||
}
|
||||
}
|
||||
|
||||
await client.end();
|
||||
|
||||
logger.info("메뉴 일괄 삭제 완료", {
|
||||
total: menuIds.length,
|
||||
deletedCount,
|
||||
|
|
@ -1561,125 +1465,94 @@ export const getUserInfo = async (req: AuthenticatedRequest, res: Response) => {
|
|||
return;
|
||||
}
|
||||
|
||||
// PostgreSQL 클라이언트 생성
|
||||
const client = new Client({
|
||||
connectionString:
|
||||
process.env.DATABASE_URL ||
|
||||
"postgresql://postgres:postgres@localhost:5432/ilshin",
|
||||
// Prisma ORM을 사용한 사용자 상세 정보 조회
|
||||
const user = await prisma.user_info.findUnique({
|
||||
where: {
|
||||
user_id: userId,
|
||||
},
|
||||
});
|
||||
|
||||
await client.connect();
|
||||
|
||||
try {
|
||||
// 사용자 상세 정보 조회 쿼리
|
||||
const query = `
|
||||
SELECT
|
||||
u.sabun,
|
||||
u.user_id,
|
||||
u.user_name,
|
||||
u.user_name_eng,
|
||||
u.user_name_cn,
|
||||
u.dept_code,
|
||||
u.dept_name,
|
||||
u.position_code,
|
||||
u.position_name,
|
||||
u.email,
|
||||
u.tel,
|
||||
u.cell_phone,
|
||||
u.user_type,
|
||||
u.user_type_name,
|
||||
u.regdate,
|
||||
u.status,
|
||||
u.end_date,
|
||||
u.fax_no,
|
||||
u.partner_objid,
|
||||
u.rank,
|
||||
u.photo,
|
||||
u.locale,
|
||||
u.company_code,
|
||||
u.data_type,
|
||||
d.dept_name as dept_name_full,
|
||||
d.parent_dept_code,
|
||||
d.location,
|
||||
d.location_name,
|
||||
d.sales_yn,
|
||||
d.company_name as dept_company_name
|
||||
FROM user_info u
|
||||
LEFT JOIN dept_info d ON u.dept_code = d.dept_code
|
||||
WHERE u.user_id = $1
|
||||
`;
|
||||
|
||||
const result = await client.query(query, [userId]);
|
||||
|
||||
if (result.rows.length === 0) {
|
||||
res.status(404).json({
|
||||
success: false,
|
||||
message: "사용자를 찾을 수 없습니다.",
|
||||
error: {
|
||||
code: "USER_NOT_FOUND",
|
||||
details: `User ID: ${userId}`,
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const user = result.rows[0];
|
||||
|
||||
// 응답 데이터 가공
|
||||
const userInfo = {
|
||||
sabun: user.sabun,
|
||||
userId: user.user_id,
|
||||
userName: user.user_name,
|
||||
userNameEng: user.user_name_eng,
|
||||
userNameCn: user.user_name_cn,
|
||||
deptCode: user.dept_code,
|
||||
deptName: user.dept_name || user.dept_name_full,
|
||||
positionCode: user.position_code,
|
||||
positionName: user.position_name,
|
||||
email: user.email,
|
||||
tel: user.tel,
|
||||
cellPhone: user.cell_phone,
|
||||
userType: user.user_type,
|
||||
userTypeName: user.user_type_name,
|
||||
regdate: user.regdate ? user.regdate.toISOString() : null,
|
||||
status: user.status || "active",
|
||||
endDate: user.end_date ? user.end_date.toISOString() : null,
|
||||
faxNo: user.fax_no,
|
||||
partnerObjid: user.partner_objid,
|
||||
rank: user.rank,
|
||||
photo: user.photo
|
||||
? `data:image/jpeg;base64,${user.photo.toString("base64")}`
|
||||
: null,
|
||||
locale: user.locale,
|
||||
companyCode: user.company_code,
|
||||
dataType: user.data_type,
|
||||
// 부서 정보
|
||||
deptInfo: {
|
||||
deptCode: user.dept_code,
|
||||
deptName: user.dept_name || user.dept_name_full,
|
||||
parentDeptCode: user.parent_dept_code,
|
||||
location: user.location,
|
||||
locationName: user.location_name,
|
||||
salesYn: user.sales_yn,
|
||||
companyName: user.dept_company_name,
|
||||
if (!user) {
|
||||
res.status(404).json({
|
||||
success: false,
|
||||
message: "사용자를 찾을 수 없습니다.",
|
||||
error: {
|
||||
code: "USER_NOT_FOUND",
|
||||
details: `User ID: ${userId}`,
|
||||
},
|
||||
};
|
||||
|
||||
const response = {
|
||||
success: true,
|
||||
data: userInfo,
|
||||
message: "사용자 상세 정보 조회 성공",
|
||||
};
|
||||
|
||||
logger.info("사용자 상세 정보 조회 성공", {
|
||||
userId,
|
||||
userName: user.user_name,
|
||||
});
|
||||
|
||||
res.status(200).json(response);
|
||||
} finally {
|
||||
await client.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// 부서 정보 별도 조회
|
||||
const deptInfo = user.dept_code
|
||||
? await prisma.dept_info.findUnique({
|
||||
where: {
|
||||
dept_code: user.dept_code,
|
||||
},
|
||||
select: {
|
||||
dept_name: true,
|
||||
parent_dept_code: true,
|
||||
location: true,
|
||||
location_name: true,
|
||||
sales_yn: true,
|
||||
company_name: true,
|
||||
},
|
||||
})
|
||||
: null;
|
||||
|
||||
// 응답 데이터 가공
|
||||
const userInfo = {
|
||||
sabun: user.sabun,
|
||||
userId: user.user_id,
|
||||
userName: user.user_name,
|
||||
userNameEng: user.user_name_eng,
|
||||
userNameCn: user.user_name_cn,
|
||||
deptCode: user.dept_code,
|
||||
deptName: user.dept_name,
|
||||
positionCode: user.position_code,
|
||||
positionName: user.position_name,
|
||||
email: user.email,
|
||||
tel: user.tel,
|
||||
cellPhone: user.cell_phone,
|
||||
userType: user.user_type,
|
||||
userTypeName: user.user_type_name,
|
||||
regdate: user.regdate ? user.regdate.toISOString() : null,
|
||||
status: user.status || "active",
|
||||
endDate: user.end_date ? user.end_date.toISOString() : null,
|
||||
faxNo: user.fax_no,
|
||||
partnerObjid: user.partner_objid,
|
||||
rank: user.rank,
|
||||
photo: user.photo
|
||||
? `data:image/jpeg;base64,${user.photo.toString("base64")}`
|
||||
: null,
|
||||
locale: user.locale,
|
||||
companyCode: user.company_code,
|
||||
dataType: user.data_type,
|
||||
// 부서 정보
|
||||
deptInfo: {
|
||||
deptCode: user.dept_code,
|
||||
deptName: deptInfo?.dept_name,
|
||||
parentDeptCode: deptInfo?.parent_dept_code,
|
||||
location: deptInfo?.location,
|
||||
locationName: deptInfo?.location_name,
|
||||
salesYn: deptInfo?.sales_yn,
|
||||
companyName: deptInfo?.company_name,
|
||||
},
|
||||
};
|
||||
|
||||
const response = {
|
||||
success: true,
|
||||
data: userInfo,
|
||||
message: "사용자 상세 정보 조회 성공",
|
||||
};
|
||||
|
||||
logger.info("사용자 상세 정보 조회 성공", {
|
||||
userId,
|
||||
userName: user.user_name,
|
||||
});
|
||||
|
||||
res.status(200).json(response);
|
||||
} catch (error) {
|
||||
logger.error("사용자 상세 정보 조회 실패", {
|
||||
error,
|
||||
|
|
@ -1955,98 +1828,66 @@ export const changeUserStatus = async (
|
|||
return;
|
||||
}
|
||||
|
||||
// 복잡한 상태 변경은 직접 쿼리 사용
|
||||
const client = new Client({
|
||||
connectionString: config.databaseUrl,
|
||||
// Prisma ORM을 사용한 사용자 상태 변경
|
||||
// 1. 사용자 존재 여부 확인
|
||||
const currentUser = await prisma.user_info.findUnique({
|
||||
where: {
|
||||
user_id: userId,
|
||||
},
|
||||
select: {
|
||||
user_id: true,
|
||||
user_name: true,
|
||||
status: true,
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
// 1. Prisma ORM으로 사용자 존재 여부 확인
|
||||
const currentUser = await prisma.user_info.findUnique({
|
||||
where: {
|
||||
user_id: userId,
|
||||
},
|
||||
select: {
|
||||
user_id: true,
|
||||
user_name: true,
|
||||
status: true,
|
||||
},
|
||||
if (!currentUser) {
|
||||
res.status(404).json({
|
||||
result: false,
|
||||
msg: "사용자를 찾을 수 없습니다.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 상태 변경 데이터 준비
|
||||
let updateData: any = {
|
||||
status: status,
|
||||
};
|
||||
|
||||
// active/inactive에 따른 END_DATE 처리
|
||||
if (status === "inactive") {
|
||||
updateData.end_date = new Date();
|
||||
} else if (status === "active") {
|
||||
updateData.end_date = null;
|
||||
}
|
||||
|
||||
// 3. Prisma ORM으로 상태 변경 실행
|
||||
const updateResult = await prisma.user_info.update({
|
||||
where: {
|
||||
user_id: userId,
|
||||
},
|
||||
data: updateData,
|
||||
});
|
||||
|
||||
if (updateResult) {
|
||||
// 사용자 이력 저장은 user_info_history 테이블이 @@ignore 상태이므로 생략
|
||||
|
||||
logger.info("사용자 상태 변경 성공", {
|
||||
userId,
|
||||
oldStatus: currentUser.status,
|
||||
newStatus: status,
|
||||
updatedBy: req.user?.userId,
|
||||
});
|
||||
|
||||
if (!currentUser) {
|
||||
res.status(404).json({
|
||||
result: false,
|
||||
msg: "사용자를 찾을 수 없습니다.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
await client.connect();
|
||||
|
||||
// 2. 상태 변경 쿼리 실행
|
||||
let updateQuery = `
|
||||
UPDATE user_info
|
||||
SET status = $1
|
||||
`;
|
||||
|
||||
const queryParams = [status];
|
||||
|
||||
// active/inactive에 따른 END_DATE 처리
|
||||
if (status === "inactive") {
|
||||
updateQuery += `, end_date = NOW()`;
|
||||
} else if (status === "active") {
|
||||
updateQuery += `, end_date = NULL`;
|
||||
}
|
||||
|
||||
updateQuery += ` WHERE user_id = $2`;
|
||||
queryParams.push(userId);
|
||||
|
||||
const updateResult = await client.query(updateQuery, queryParams);
|
||||
|
||||
if (updateResult.rowCount && updateResult.rowCount > 0) {
|
||||
// 3. 사용자 이력 저장 (선택적)
|
||||
try {
|
||||
await client.query(
|
||||
`
|
||||
INSERT INTO user_info_history
|
||||
(user_id, user_name, dept_code, dept_name, user_type_name, history_type, writer, reg_date, status, sabun)
|
||||
VALUES ($1, $2, '', '', '', '사용자 상태 변경', $3, NOW(), $4, '')
|
||||
`,
|
||||
[
|
||||
userId,
|
||||
currentUser.user_name || userId,
|
||||
req.user?.userId || "system",
|
||||
status,
|
||||
]
|
||||
);
|
||||
} catch (historyError) {
|
||||
logger.warn("사용자 이력 저장 실패", {
|
||||
error: historyError,
|
||||
userId,
|
||||
status,
|
||||
});
|
||||
// 이력 저장 실패는 치명적이지 않으므로 계속 진행
|
||||
}
|
||||
|
||||
logger.info("사용자 상태 변경 성공", {
|
||||
userId,
|
||||
oldStatus: currentUser.status,
|
||||
newStatus: status,
|
||||
updatedBy: req.user?.userId,
|
||||
});
|
||||
|
||||
res.json({
|
||||
result: true,
|
||||
msg: `사용자 상태가 ${status === "active" ? "활성" : "비활성"}으로 변경되었습니다.`,
|
||||
});
|
||||
} else {
|
||||
res.status(400).json({
|
||||
result: false,
|
||||
msg: "사용자 상태 변경에 실패했습니다.",
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
await client.end();
|
||||
res.json({
|
||||
result: true,
|
||||
msg: `사용자 상태가 ${status === "active" ? "활성" : "비활성"}으로 변경되었습니다.`,
|
||||
});
|
||||
} else {
|
||||
res.status(400).json({
|
||||
result: false,
|
||||
msg: "사용자 상태 변경에 실패했습니다.",
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error("사용자 상태 변경 중 오류 발생", {
|
||||
|
|
@ -2315,63 +2156,36 @@ export const updateCompany = async (
|
|||
return;
|
||||
}
|
||||
|
||||
// PostgreSQL 클라이언트 생성
|
||||
const client = new Client({
|
||||
connectionString:
|
||||
process.env.DATABASE_URL ||
|
||||
"postgresql://postgres:postgres@localhost:5432/ilshin",
|
||||
// Prisma ORM으로 회사명 중복 체크 (자기 자신 제외)
|
||||
const duplicateCompany = await prisma.company_mng.findFirst({
|
||||
where: {
|
||||
company_name: company_name.trim(),
|
||||
company_code: {
|
||||
not: companyCode,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await client.connect();
|
||||
if (duplicateCompany) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
message: "이미 등록된 회사명입니다.",
|
||||
errorCode: "COMPANY_NAME_DUPLICATE",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Prisma ORM으로 회사 정보 수정
|
||||
try {
|
||||
// 회사명 중복 체크 (자기 자신 제외)
|
||||
const duplicateCheckQuery = `
|
||||
SELECT COUNT(*) as count
|
||||
FROM company_mng
|
||||
WHERE company_name = $1 AND company_code != $2
|
||||
`;
|
||||
|
||||
const duplicateResult = await client.query(duplicateCheckQuery, [
|
||||
company_name.trim(),
|
||||
companyCode,
|
||||
]);
|
||||
|
||||
if (parseInt(duplicateResult.rows[0].count) > 0) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
message: "이미 등록된 회사명입니다.",
|
||||
errorCode: "COMPANY_NAME_DUPLICATE",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 회사 정보 수정
|
||||
const updateQuery = `
|
||||
UPDATE company_mng
|
||||
SET company_name = $1, status = $2
|
||||
WHERE company_code = $3
|
||||
RETURNING *
|
||||
`;
|
||||
|
||||
const updateValues = [
|
||||
company_name.trim(),
|
||||
status || "active",
|
||||
companyCode,
|
||||
];
|
||||
|
||||
const updateResult = await client.query(updateQuery, updateValues);
|
||||
|
||||
if (updateResult.rows.length === 0) {
|
||||
res.status(404).json({
|
||||
success: false,
|
||||
message: "해당 회사를 찾을 수 없습니다.",
|
||||
errorCode: "COMPANY_NOT_FOUND",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const updatedCompany = updateResult.rows[0];
|
||||
const updatedCompany = await prisma.company_mng.update({
|
||||
where: {
|
||||
company_code: companyCode,
|
||||
},
|
||||
data: {
|
||||
company_name: company_name.trim(),
|
||||
status: status || "active",
|
||||
},
|
||||
});
|
||||
|
||||
logger.info("회사 정보 수정 성공", {
|
||||
companyCode: updatedCompany.company_code,
|
||||
|
|
@ -2392,8 +2206,17 @@ export const updateCompany = async (
|
|||
};
|
||||
|
||||
res.status(200).json(response);
|
||||
} finally {
|
||||
await client.end();
|
||||
} catch (updateError: any) {
|
||||
if (updateError.code === "P2025") {
|
||||
// Prisma error code for "Record to update not found"
|
||||
res.status(404).json({
|
||||
success: false,
|
||||
message: "해당 회사를 찾을 수 없습니다.",
|
||||
errorCode: "COMPANY_NOT_FOUND",
|
||||
});
|
||||
return;
|
||||
}
|
||||
throw updateError;
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error("회사 정보 수정 실패", { error, body: req.body });
|
||||
|
|
@ -2639,9 +2462,6 @@ export const resetUserPassword = async (
|
|||
return;
|
||||
}
|
||||
|
||||
// 복잡한 암호화 로직은 직접 쿼리 사용
|
||||
const client = new Client({ connectionString: config.databaseUrl });
|
||||
|
||||
try {
|
||||
// 1. Prisma ORM으로 사용자 존재 여부 확인
|
||||
const currentUser = await prisma.user_info.findUnique({
|
||||
|
|
@ -2664,8 +2484,6 @@ export const resetUserPassword = async (
|
|||
return;
|
||||
}
|
||||
|
||||
await client.connect();
|
||||
|
||||
// 2. 비밀번호 암호화 (기존 Java 로직과 동일)
|
||||
let encryptedPassword: string;
|
||||
try {
|
||||
|
|
@ -2693,31 +2511,18 @@ export const resetUserPassword = async (
|
|||
return;
|
||||
}
|
||||
|
||||
// 3. 비밀번호 업데이트 실행
|
||||
const updateResult = await client.query(
|
||||
"UPDATE user_info SET user_password = $1 WHERE user_id = $2",
|
||||
[encryptedPassword, userId]
|
||||
);
|
||||
// 3. Prisma ORM으로 비밀번호 업데이트 실행
|
||||
const updateResult = await prisma.user_info.update({
|
||||
where: {
|
||||
user_id: userId,
|
||||
},
|
||||
data: {
|
||||
user_password: encryptedPassword,
|
||||
},
|
||||
});
|
||||
|
||||
if (updateResult.rowCount && updateResult.rowCount > 0) {
|
||||
// 4. 이력 저장 (선택적)
|
||||
try {
|
||||
const writer = req.user?.userId || "system";
|
||||
await client.query(
|
||||
`
|
||||
INSERT INTO user_info_history
|
||||
(sabun, user_id, user_name, dept_code, dept_name, user_type_name, history_type, writer, regdate, status)
|
||||
VALUES ('', $1, $2, '', '', '', '비밀번호 초기화', $3, NOW(), '')
|
||||
`,
|
||||
[userId, currentUser.user_name || userId, writer]
|
||||
);
|
||||
} catch (historyError) {
|
||||
logger.warn("비밀번호 초기화 이력 저장 실패", {
|
||||
error: historyError,
|
||||
userId,
|
||||
});
|
||||
// 이력 저장 실패해도 비밀번호 초기화는 성공으로 처리
|
||||
}
|
||||
if (updateResult) {
|
||||
// 이력 저장은 user_info_history 테이블이 @@ignore 상태이므로 생략
|
||||
|
||||
logger.info("비밀번호 초기화 성공", {
|
||||
userId,
|
||||
|
|
@ -2749,7 +2554,5 @@ export const resetUserPassword = async (
|
|||
message: "비밀번호 초기화 중 시스템 오류가 발생했습니다.",
|
||||
msg: "비밀번호 초기화 중 시스템 오류가 발생했습니다.",
|
||||
});
|
||||
} finally {
|
||||
await client.end();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -333,23 +333,36 @@ export class AdminService {
|
|||
try {
|
||||
logger.info(`AdminService.getMenuInfo 시작 - menuId: ${menuId}`);
|
||||
|
||||
// menu_info 모델이 @@ignore로 설정되어 있으므로 $queryRaw 사용
|
||||
const menuInfo = await prisma.$queryRaw<any[]>`
|
||||
SELECT
|
||||
MI.*,
|
||||
COALESCE(CM.COMPANY_NAME, '미지정') AS COMPANY_NAME
|
||||
FROM MENU_INFO MI
|
||||
LEFT JOIN COMPANY_MNG CM ON MI.COMPANY_CODE = CM.COMPANY_CODE
|
||||
WHERE MI.OBJID = ${parseInt(menuId)}::numeric
|
||||
LIMIT 1
|
||||
`;
|
||||
// Prisma ORM을 사용한 메뉴 정보 조회 (회사 정보 포함)
|
||||
const menuInfo = await prisma.menu_info.findUnique({
|
||||
where: {
|
||||
objid: Number(menuId),
|
||||
},
|
||||
include: {
|
||||
company: {
|
||||
select: {
|
||||
company_name: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!menuInfo || menuInfo.length === 0) {
|
||||
if (!menuInfo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
logger.info("메뉴 정보 조회 결과:", menuInfo[0]);
|
||||
return menuInfo[0];
|
||||
// 응답 형식 조정 (기존 형식과 호환성 유지)
|
||||
const result = {
|
||||
...menuInfo,
|
||||
objid: menuInfo.objid.toString(), // BigInt를 문자열로 변환
|
||||
menu_type: menuInfo.menu_type?.toString(),
|
||||
parent_obj_id: menuInfo.parent_obj_id?.toString(),
|
||||
seq: menuInfo.seq?.toString(),
|
||||
company_name: menuInfo.company?.company_name || "미지정",
|
||||
};
|
||||
|
||||
logger.info("메뉴 정보 조회 결과:", result);
|
||||
return result;
|
||||
} catch (error) {
|
||||
logger.error("AdminService.getMenuInfo 오류:", error);
|
||||
throw error;
|
||||
|
|
|
|||
|
|
@ -155,23 +155,35 @@ export class AuthService {
|
|||
return null;
|
||||
}
|
||||
|
||||
// 권한 정보 조회 (기존 Java 로직과 동일)
|
||||
const authInfo = await prisma.$queryRaw<Array<{ auth_name: string }>>`
|
||||
SELECT ARRAY_TO_STRING(ARRAY_AGG(AM.AUTH_NAME), ',') AS AUTH_NAME
|
||||
FROM AUTHORITY_MASTER AM, AUTHORITY_SUB_USER ASU
|
||||
WHERE AM.OBJID = ASU.MASTER_OBJID
|
||||
AND ASU.USER_ID = ${userId}
|
||||
GROUP BY ASU.USER_ID
|
||||
`;
|
||||
// 권한 정보 조회 (Prisma ORM 사용)
|
||||
const authInfo = await prisma.authority_sub_user.findMany({
|
||||
where: {
|
||||
user_id: userId,
|
||||
},
|
||||
include: {
|
||||
authority_master: {
|
||||
select: {
|
||||
auth_name: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// 회사 정보 조회 (기존 Java 로직과 동일)
|
||||
const companyInfo = await prisma.$queryRaw<
|
||||
Array<{ company_name: string }>
|
||||
>`
|
||||
SELECT COALESCE(CM.COMPANY_NAME, '미지정') AS COMPANY_NAME
|
||||
FROM COMPANY_MNG CM
|
||||
WHERE CM.COMPANY_CODE = ${userInfo.company_code || "ILSHIN"}
|
||||
`;
|
||||
// 권한명들을 쉼표로 연결
|
||||
const authNames = authInfo
|
||||
.filter((auth) => auth.authority_master?.auth_name)
|
||||
.map((auth) => auth.authority_master!.auth_name!)
|
||||
.join(",");
|
||||
|
||||
// 회사 정보 조회 (Prisma ORM 사용으로 변경)
|
||||
const companyInfo = await prisma.company_mng.findFirst({
|
||||
where: {
|
||||
company_code: userInfo.company_code || "ILSHIN",
|
||||
},
|
||||
select: {
|
||||
company_name: true,
|
||||
},
|
||||
});
|
||||
|
||||
// PersonBean 형태로 변환 (null 값을 undefined로 변환)
|
||||
const personBean: PersonBean = {
|
||||
|
|
@ -189,9 +201,11 @@ export class AuthService {
|
|||
userType: userInfo.user_type || undefined,
|
||||
userTypeName: userInfo.user_type_name || undefined,
|
||||
partnerObjid: userInfo.partner_objid || undefined,
|
||||
authName: authInfo.length > 0 ? authInfo[0].auth_name : undefined,
|
||||
authName: authNames || undefined,
|
||||
companyCode: userInfo.company_code || "ILSHIN",
|
||||
photo: userInfo.photo ? `data:image/jpeg;base64,${userInfo.photo.toString('base64')}` : undefined,
|
||||
photo: userInfo.photo
|
||||
? `data:image/jpeg;base64,${userInfo.photo.toString("base64")}`
|
||||
: undefined,
|
||||
locale: userInfo.locale || "KR",
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue