360 lines
10 KiB
TypeScript
360 lines
10 KiB
TypeScript
import { Request, Response } from "express";
|
|
import {
|
|
getDataflowDiagrams as getDataflowDiagramsService,
|
|
getDataflowDiagramById as getDataflowDiagramByIdService,
|
|
createDataflowDiagram as createDataflowDiagramService,
|
|
updateDataflowDiagram as updateDataflowDiagramService,
|
|
deleteDataflowDiagram as deleteDataflowDiagramService,
|
|
copyDataflowDiagram as copyDataflowDiagramService,
|
|
} from "../services/dataflowDiagramService";
|
|
import { logger } from "../utils/logger";
|
|
|
|
/**
|
|
* 관계도 목록 조회 (페이지네이션)
|
|
*/
|
|
export const getDataflowDiagrams = async (req: Request, res: Response) => {
|
|
try {
|
|
const page = parseInt(req.query.page as string) || 1;
|
|
const size = parseInt(req.query.size as string) || 20;
|
|
const searchTerm = req.query.searchTerm as string;
|
|
const companyCode =
|
|
(req.query.companyCode as string) ||
|
|
(req.headers["x-company-code"] as string) ||
|
|
"*";
|
|
|
|
const result = await getDataflowDiagramsService(
|
|
companyCode,
|
|
page,
|
|
size,
|
|
searchTerm
|
|
);
|
|
|
|
res.json({
|
|
success: true,
|
|
data: result,
|
|
});
|
|
} catch (error) {
|
|
logger.error("관계도 목록 조회 실패:", error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: "관계도 목록 조회 중 오류가 발생했습니다.",
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 특정 관계도 조회
|
|
*/
|
|
export const getDataflowDiagramById = async (req: Request, res: Response) => {
|
|
try {
|
|
const diagramId = parseInt(req.params.diagramId);
|
|
const companyCode =
|
|
(req.query.companyCode as string) ||
|
|
(req.headers["x-company-code"] as string) ||
|
|
"*";
|
|
|
|
if (isNaN(diagramId)) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: "유효하지 않은 관계도 ID입니다.",
|
|
});
|
|
}
|
|
|
|
const diagram = await getDataflowDiagramByIdService(diagramId, companyCode);
|
|
|
|
if (!diagram) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
message: "관계도를 찾을 수 없습니다.",
|
|
});
|
|
}
|
|
|
|
return res.json({
|
|
success: true,
|
|
data: diagram,
|
|
});
|
|
} catch (error) {
|
|
logger.error("관계도 조회 실패:", error);
|
|
return res.status(500).json({
|
|
success: false,
|
|
message: "관계도 조회 중 오류가 발생했습니다.",
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 새로운 관계도 생성
|
|
*/
|
|
export const createDataflowDiagram = async (req: Request, res: Response) => {
|
|
try {
|
|
const {
|
|
diagram_name,
|
|
relationships,
|
|
node_positions,
|
|
category,
|
|
control,
|
|
plan,
|
|
company_code,
|
|
created_by,
|
|
updated_by,
|
|
} = req.body;
|
|
|
|
logger.info(`새 관계도 생성 요청:`, { diagram_name, company_code });
|
|
logger.info(`node_positions:`, node_positions);
|
|
logger.info(`category:`, category);
|
|
logger.info(`control:`, control);
|
|
logger.info(`plan:`, plan);
|
|
logger.info(`전체 요청 Body:`, JSON.stringify(req.body, null, 2));
|
|
const companyCode =
|
|
company_code ||
|
|
(req.query.companyCode as string) ||
|
|
(req.headers["x-company-code"] as string) ||
|
|
"*";
|
|
const userId =
|
|
created_by ||
|
|
updated_by ||
|
|
(req.headers["x-user-id"] as string) ||
|
|
"SYSTEM";
|
|
|
|
if (!diagram_name || !relationships) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: "관계도 이름과 관계 정보는 필수입니다.",
|
|
});
|
|
}
|
|
|
|
const newDiagram = await createDataflowDiagramService({
|
|
diagram_name,
|
|
relationships,
|
|
node_positions,
|
|
category,
|
|
control,
|
|
plan,
|
|
company_code: companyCode,
|
|
created_by: userId,
|
|
updated_by: userId,
|
|
});
|
|
|
|
return res.status(201).json({
|
|
success: true,
|
|
data: newDiagram,
|
|
message: "관계도가 성공적으로 생성되었습니다.",
|
|
});
|
|
} catch (error) {
|
|
// 디버깅을 위한 에러 정보 출력
|
|
logger.error("에러 디버깅:", {
|
|
errorType: typeof error,
|
|
errorCode: (error as any)?.code,
|
|
errorMessage: error instanceof Error ? error.message : "Unknown error",
|
|
errorName: (error as any)?.name,
|
|
errorMeta: (error as any)?.meta,
|
|
});
|
|
|
|
// 중복 이름 에러인지 먼저 확인 (로그 출력 전에)
|
|
const isDuplicateError =
|
|
(error && typeof error === "object" && (error as any).code === "P2002") || // Prisma unique constraint error code
|
|
(error instanceof Error &&
|
|
(error.message.includes("unique constraint") ||
|
|
error.message.includes("Unique constraint") ||
|
|
error.message.includes("duplicate key") ||
|
|
error.message.includes("UNIQUE constraint failed") ||
|
|
error.message.includes("unique_diagram_name_per_company")));
|
|
|
|
if (isDuplicateError) {
|
|
// 중복 에러는 콘솔에 로그 출력하지 않음
|
|
return res.status(409).json({
|
|
success: false,
|
|
message: "중복된 이름입니다.",
|
|
});
|
|
}
|
|
|
|
// 다른 에러만 로그 출력
|
|
logger.error("관계도 생성 실패:", error);
|
|
|
|
return res.status(500).json({
|
|
success: false,
|
|
message: "관계도 생성 중 오류가 발생했습니다.",
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 관계도 수정
|
|
*/
|
|
export const updateDataflowDiagram = async (req: Request, res: Response) => {
|
|
try {
|
|
const diagramId = parseInt(req.params.diagramId);
|
|
const { updated_by } = req.body;
|
|
const companyCode =
|
|
(req.query.companyCode as string) ||
|
|
(req.headers["x-company-code"] as string) ||
|
|
"*";
|
|
const userId =
|
|
updated_by || (req.headers["x-user-id"] as string) || "SYSTEM";
|
|
|
|
logger.info(`관계도 수정 요청 - ID: ${diagramId}, Company: ${companyCode}`);
|
|
logger.info(`요청 Body:`, JSON.stringify(req.body, null, 2));
|
|
logger.info(`node_positions:`, req.body.node_positions);
|
|
logger.info(`요청 Body 키들:`, Object.keys(req.body));
|
|
logger.info(`요청 Body 타입:`, typeof req.body);
|
|
logger.info(`node_positions 타입:`, typeof req.body.node_positions);
|
|
logger.info(`node_positions 값:`, req.body.node_positions);
|
|
|
|
if (isNaN(diagramId)) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: "유효하지 않은 관계도 ID입니다.",
|
|
});
|
|
}
|
|
|
|
const updateData = {
|
|
...req.body,
|
|
updated_by: userId,
|
|
};
|
|
|
|
const updatedDiagram = await updateDataflowDiagramService(
|
|
diagramId,
|
|
updateData,
|
|
companyCode
|
|
);
|
|
|
|
if (!updatedDiagram) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
message: "관계도를 찾을 수 없습니다.",
|
|
});
|
|
}
|
|
|
|
return res.json({
|
|
success: true,
|
|
data: updatedDiagram,
|
|
message: "관계도가 성공적으로 수정되었습니다.",
|
|
});
|
|
} catch (error) {
|
|
// 중복 이름 에러인지 먼저 확인 (로그 출력 전에)
|
|
const isDuplicateError =
|
|
(error && typeof error === "object" && (error as any).code === "P2002") || // Prisma unique constraint error code
|
|
(error instanceof Error &&
|
|
(error.message.includes("unique constraint") ||
|
|
error.message.includes("Unique constraint") ||
|
|
error.message.includes("duplicate key") ||
|
|
error.message.includes("UNIQUE constraint failed") ||
|
|
error.message.includes("unique_diagram_name_per_company")));
|
|
|
|
if (isDuplicateError) {
|
|
// 중복 에러는 콘솔에 로그 출력하지 않음
|
|
return res.status(409).json({
|
|
success: false,
|
|
message: "중복된 이름입니다.",
|
|
});
|
|
}
|
|
|
|
// 다른 에러만 로그 출력
|
|
logger.error("관계도 수정 실패:", error);
|
|
return res.status(500).json({
|
|
success: false,
|
|
message: "관계도 수정 중 오류가 발생했습니다.",
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 관계도 삭제
|
|
*/
|
|
export const deleteDataflowDiagram = async (req: Request, res: Response) => {
|
|
try {
|
|
const diagramId = parseInt(req.params.diagramId);
|
|
const companyCode =
|
|
(req.query.companyCode as string) ||
|
|
(req.headers["x-company-code"] as string) ||
|
|
"*";
|
|
|
|
if (isNaN(diagramId)) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: "유효하지 않은 관계도 ID입니다.",
|
|
});
|
|
}
|
|
|
|
const deleted = await deleteDataflowDiagramService(diagramId, companyCode);
|
|
|
|
if (!deleted) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
message: "관계도를 찾을 수 없습니다.",
|
|
});
|
|
}
|
|
|
|
return res.json({
|
|
success: true,
|
|
message: "관계도가 성공적으로 삭제되었습니다.",
|
|
});
|
|
} catch (error) {
|
|
logger.error("관계도 삭제 실패:", error);
|
|
return res.status(500).json({
|
|
success: false,
|
|
message: "관계도 삭제 중 오류가 발생했습니다.",
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 관계도 복제
|
|
*/
|
|
export const copyDataflowDiagram = async (req: Request, res: Response) => {
|
|
try {
|
|
const diagramId = parseInt(req.params.diagramId);
|
|
const {
|
|
new_name,
|
|
companyCode: bodyCompanyCode,
|
|
userId: bodyUserId,
|
|
} = req.body;
|
|
const companyCode =
|
|
bodyCompanyCode ||
|
|
(req.query.companyCode as string) ||
|
|
(req.headers["x-company-code"] as string) ||
|
|
"*";
|
|
const userId =
|
|
bodyUserId || (req.headers["x-user-id"] as string) || "SYSTEM";
|
|
|
|
if (isNaN(diagramId)) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: "유효하지 않은 관계도 ID입니다.",
|
|
});
|
|
}
|
|
|
|
const copiedDiagram = await copyDataflowDiagramService(
|
|
diagramId,
|
|
companyCode,
|
|
new_name,
|
|
userId
|
|
);
|
|
|
|
if (!copiedDiagram) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
message: "복제할 관계도를 찾을 수 없습니다.",
|
|
});
|
|
}
|
|
|
|
return res.status(201).json({
|
|
success: true,
|
|
data: copiedDiagram,
|
|
message: "관계도가 성공적으로 복제되었습니다.",
|
|
});
|
|
} catch (error) {
|
|
logger.error("관계도 복제 실패:", error);
|
|
return res.status(500).json({
|
|
success: false,
|
|
message: "관계도 복제 중 오류가 발생했습니다.",
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
|
});
|
|
}
|
|
};
|