Merge remote-tracking branch 'upstream/main'

This commit is contained in:
kjs
2026-03-12 08:26:13 +09:00
56 changed files with 4880 additions and 500 deletions

View File

@@ -8,6 +8,7 @@ import { logger } from "../../utils/logger";
import { NodeFlowExecutionService } from "../../services/nodeFlowExecutionService";
import { AuthenticatedRequest } from "../../types/auth";
import { authenticateToken } from "../../middleware/authMiddleware";
import { auditLogService, getClientIp } from "../../services/auditLogService";
const router = Router();
@@ -124,6 +125,21 @@ router.post("/", async (req: AuthenticatedRequest, res: Response) => {
`플로우 저장 성공: ${result.flowId} (회사: ${userCompanyCode})`
);
auditLogService.log({
companyCode: userCompanyCode,
userId: req.user?.userId || "",
userName: req.user?.userName,
action: "CREATE",
resourceType: "NODE_FLOW",
resourceId: String(result.flowId),
resourceName: flowName,
tableName: "node_flows",
summary: `노드 플로우 "${flowName}" 생성`,
changes: { after: { flowName, flowDescription } },
ipAddress: getClientIp(req as any),
requestPath: req.originalUrl,
});
return res.json({
success: true,
message: "플로우가 저장되었습니다.",
@@ -143,7 +159,7 @@ router.post("/", async (req: AuthenticatedRequest, res: Response) => {
/**
* 플로우 수정
*/
router.put("/", async (req: Request, res: Response) => {
router.put("/", async (req: AuthenticatedRequest, res: Response) => {
try {
const { flowId, flowName, flowDescription, flowData } = req.body;
@@ -154,6 +170,11 @@ router.put("/", async (req: Request, res: Response) => {
});
}
const oldFlow = await queryOne(
`SELECT flow_name, flow_description FROM node_flows WHERE flow_id = $1`,
[flowId]
);
await query(
`
UPDATE node_flows
@@ -168,6 +189,25 @@ router.put("/", async (req: Request, res: Response) => {
logger.info(`플로우 수정 성공: ${flowId}`);
const userCompanyCode = req.user?.companyCode || "*";
auditLogService.log({
companyCode: userCompanyCode,
userId: req.user?.userId || "",
userName: req.user?.userName,
action: "UPDATE",
resourceType: "NODE_FLOW",
resourceId: String(flowId),
resourceName: flowName,
tableName: "node_flows",
summary: `노드 플로우 "${flowName}" 수정`,
changes: {
before: oldFlow ? { flowName: (oldFlow as any).flow_name, flowDescription: (oldFlow as any).flow_description } : undefined,
after: { flowName, flowDescription },
},
ipAddress: getClientIp(req as any),
requestPath: req.originalUrl,
});
return res.json({
success: true,
message: "플로우가 수정되었습니다.",
@@ -187,10 +227,15 @@ router.put("/", async (req: Request, res: Response) => {
/**
* 플로우 삭제
*/
router.delete("/:flowId", async (req: Request, res: Response) => {
router.delete("/:flowId", async (req: AuthenticatedRequest, res: Response) => {
try {
const { flowId } = req.params;
const oldFlow = await queryOne(
`SELECT flow_name, flow_description, company_code FROM node_flows WHERE flow_id = $1`,
[flowId]
);
await query(
`
DELETE FROM node_flows
@@ -201,6 +246,25 @@ router.delete("/:flowId", async (req: Request, res: Response) => {
logger.info(`플로우 삭제 성공: ${flowId}`);
const userCompanyCode = req.user?.companyCode || "*";
const flowName = (oldFlow as any)?.flow_name || `ID:${flowId}`;
auditLogService.log({
companyCode: userCompanyCode,
userId: req.user?.userId || "",
userName: req.user?.userName,
action: "DELETE",
resourceType: "NODE_FLOW",
resourceId: String(flowId),
resourceName: flowName,
tableName: "node_flows",
summary: `노드 플로우 "${flowName}" 삭제`,
changes: {
before: oldFlow ? { flowName: (oldFlow as any).flow_name, flowDescription: (oldFlow as any).flow_description } : undefined,
},
ipAddress: getClientIp(req as any),
requestPath: req.originalUrl,
});
return res.json({
success: true,
message: "플로우가 삭제되었습니다.",

View File

@@ -1,10 +1,36 @@
import { Router } from "express";
import { authenticateToken } from "../middleware/authMiddleware";
import {
getPkgUnits, createPkgUnit, updatePkgUnit, deletePkgUnit,
getPkgUnitItems, createPkgUnitItem, deletePkgUnitItem,
getLoadingUnits, createLoadingUnit, updateLoadingUnit, deleteLoadingUnit,
getLoadingUnitPkgs, createLoadingUnitPkg, deleteLoadingUnitPkg,
} from "../controllers/packagingController";
const router = Router();
router.use(authenticateToken);
// TODO: 포장/적재정보 관리 API 구현 예정
// 포장단위
router.get("/pkg-units", getPkgUnits);
router.post("/pkg-units", createPkgUnit);
router.put("/pkg-units/:id", updatePkgUnit);
router.delete("/pkg-units/:id", deletePkgUnit);
// 포장단위 매칭품목
router.get("/pkg-unit-items/:pkgCode", getPkgUnitItems);
router.post("/pkg-unit-items", createPkgUnitItem);
router.delete("/pkg-unit-items/:id", deletePkgUnitItem);
// 적재함
router.get("/loading-units", getLoadingUnits);
router.post("/loading-units", createLoadingUnit);
router.put("/loading-units/:id", updateLoadingUnit);
router.delete("/loading-units/:id", deleteLoadingUnit);
// 적재함 포장구성
router.get("/loading-unit-pkgs/:loadingCode", getLoadingUnitPkgs);
router.post("/loading-unit-pkgs", createLoadingUnitPkg);
router.delete("/loading-unit-pkgs/:id", deleteLoadingUnitPkg);
export default router;