사용자 변경 이력 조회 구현

This commit is contained in:
dohyeons
2025-08-25 18:30:07 +09:00
parent 3027f2c817
commit b43a88a045
6 changed files with 207 additions and 38 deletions

View File

@@ -1832,6 +1832,158 @@ export const checkDuplicateUserId = async (
* 사용자 등록/수정 API
* 기존 Java AdminController의 saveUserInfo 기능 포팅
*/
/**
* GET /api/admin/users/:userId/history
* 사용자 변경이력 조회 API
* 기존 Java AdminController.getUserHistory() 포팅
*/
export const getUserHistory = async (
req: AuthenticatedRequest,
res: Response
) => {
try {
const { userId } = req.params;
const { page = 1, countPerPage = 10 } = req.query;
logger.info(`사용자 변경이력 조회 요청 - userId: ${userId}`, {
page,
countPerPage,
user: req.user,
});
if (!userId) {
res.status(400).json({
success: false,
message: "사용자 ID가 필요합니다.",
error: {
code: "USER_ID_REQUIRED",
details: "userId 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 currentPage = Number(page);
const pageSize = Number(countPerPage);
const pageStart = (currentPage - 1) * pageSize + 1;
const pageEnd = currentPage * pageSize;
// 전체 건수 조회 쿼리 (기존 backend와 동일한 로직)
const countQuery = `
SELECT
CEIL(TOTAL_CNT::float / $1)::integer AS MAX_PAGE_SIZE,
TOTAL_CNT
FROM (
SELECT
COUNT(1) AS TOTAL_CNT
FROM user_info_history
WHERE user_id = $2
) A
`;
const countResult = await client.query(countQuery, [pageSize, userId]);
const countData = countResult.rows[0] || {
total_cnt: 0,
max_page_size: 1,
};
// 변경이력 목록 조회 쿼리 (기존 backend와 동일한 로직)
const historyQuery = `
SELECT
A.*
FROM (
SELECT
A.*,
ROW_NUMBER() OVER (ORDER BY RM DESC) AS RNUM
FROM (
SELECT
T.*,
ROW_NUMBER() OVER (ORDER BY regdate) AS RM,
(SELECT user_name FROM user_info UI WHERE T.writer = UI.user_id) AS writer_name,
TO_CHAR(T.regdate, 'YYYY-MM-DD HH24:MI:SS') AS reg_date_title
FROM
user_info_history T
WHERE user_id = $1
) A
WHERE 1=1
) A
WHERE 1=1
AND RNUM::integer <= $2
AND RNUM::integer >= $3
ORDER BY RM DESC
`;
const historyResult = await client.query(historyQuery, [
userId,
pageEnd,
pageStart,
]);
// 응답 데이터 가공
const historyList = historyResult.rows.map((row) => ({
sabun: row.sabun || "",
userId: row.user_id || "",
userName: row.user_name || "",
deptCode: row.dept_code || "",
deptName: row.dept_name || "",
userTypeName: row.user_type_name || "",
historyType: row.history_type || "",
writer: row.writer || "",
writerName: row.writer_name || "",
regDate: row.regdate,
regDateTitle: row.reg_date_title || "",
status: row.status || "",
rowNum: row.rnum,
}));
logger.info(
`사용자 변경이력 조회 완료 - userId: ${userId}, 조회건수: ${historyList.length}, 전체: ${countData.total_cnt}`
);
const response: ApiResponse<any[]> = {
success: true,
data: historyList,
total: Number(countData.total_cnt),
pagination: {
page: currentPage,
limit: pageSize,
total: Number(countData.total_cnt),
totalPages: Number(countData.max_page_size),
},
};
res.status(200).json(response);
} finally {
await client.end();
}
} catch (error) {
logger.error("사용자 변경이력 조회 중 오류 발생", error);
const response: ApiResponse<null> = {
success: false,
message: "사용자 변경이력 조회 중 오류가 발생했습니다.",
error: {
code: "USER_HISTORY_FETCH_ERROR",
details: error instanceof Error ? error.message : "Unknown error",
},
};
res.status(500).json(response);
}
};
export const saveUser = async (req: AuthenticatedRequest, res: Response) => {
try {
const userData = req.body;