feat: Integrate audit logging for various operations

- Added audit logging functionality across multiple controllers, including menu, user, department, flow, screen, and table management.
- Implemented logging for create, update, and delete actions, capturing relevant details such as company code, user information, and changes made.
- Enhanced the category tree service with a new endpoint to check if category values are in use, improving data integrity checks.
- Updated routes to include new functionalities and ensure proper logging for batch operations and individual record changes.
- This integration improves traceability and accountability for data modifications within the application.
This commit is contained in:
kjs
2026-03-04 13:49:08 +09:00
parent f04d224b09
commit b4d5367e2b
26 changed files with 2620 additions and 140 deletions

View File

@@ -3,6 +3,7 @@ import { logger } from "../utils/logger";
import { AuthenticatedRequest } from "../types/auth";
import { ApiResponse } from "../types/common";
import { query, queryOne } from "../database/db";
import { auditLogService } from "../services/auditLogService";
/**
* 부서 목록 조회 (회사별)
@@ -170,6 +171,21 @@ export async function createDepartment(req: AuthenticatedRequest, res: Response)
logger.info("부서 생성 성공", { deptCode, dept_name });
auditLogService.log({
companyCode: companyCode || req.user?.companyCode || "",
userId: req.user?.userId || "",
userName: req.user?.userName || "",
action: "CREATE",
resourceType: "DATA",
resourceId: deptCode,
resourceName: dept_name.trim(),
tableName: "dept_info",
summary: `부서 "${dept_name.trim()}" 생성`,
changes: { after: { deptCode, deptName: dept_name.trim(), parentDeptCode: parent_dept_code } },
ipAddress: (req as any).ip,
requestPath: req.originalUrl,
});
res.status(201).json({
success: true,
message: "부서가 생성되었습니다.",
@@ -219,6 +235,21 @@ export async function updateDepartment(req: AuthenticatedRequest, res: Response)
logger.info("부서 수정 성공", { deptCode });
auditLogService.log({
companyCode: req.user?.companyCode || "",
userId: req.user?.userId || "",
userName: req.user?.userName || "",
action: "UPDATE",
resourceType: "DATA",
resourceId: deptCode,
resourceName: dept_name.trim(),
tableName: "dept_info",
summary: `부서 "${dept_name.trim()}" 수정`,
changes: { after: { deptName: dept_name.trim(), parentDeptCode: parent_dept_code } },
ipAddress: (req as any).ip,
requestPath: req.originalUrl,
});
res.status(200).json({
success: true,
message: "부서가 수정되었습니다.",
@@ -285,6 +316,21 @@ export async function deleteDepartment(req: AuthenticatedRequest, res: Response)
deletedMemberCount: memberCount
});
auditLogService.log({
companyCode: req.user?.companyCode || "",
userId: req.user?.userId || "",
userName: req.user?.userName || "",
action: "DELETE",
resourceType: "DATA",
resourceId: deptCode,
resourceName: result[0].dept_name,
tableName: "dept_info",
summary: `부서 "${result[0].dept_name}" 삭제${memberCount > 0 ? ` (부서원 ${memberCount}명 제외)` : ""}`,
changes: { before: { deptCode, deptName: result[0].dept_name } },
ipAddress: (req as any).ip,
requestPath: req.originalUrl,
});
res.status(200).json({
success: true,
message: memberCount > 0