digramId를 사용해 제어 관계 그룹화
This commit is contained in:
@@ -5108,6 +5108,7 @@ model code_info {
|
||||
// 테이블 간 관계 정의
|
||||
model table_relationships {
|
||||
relationship_id Int @id @default(autoincrement())
|
||||
diagram_id Int // 관계도 그룹 식별자
|
||||
relationship_name String @db.VarChar(200)
|
||||
from_table_name String @db.VarChar(100)
|
||||
from_column_name String @db.VarChar(100)
|
||||
@@ -5127,8 +5128,10 @@ model table_relationships {
|
||||
bridges data_relationship_bridge[]
|
||||
|
||||
@@index([company_code], map: "idx_table_relationships_company_code")
|
||||
@@index([diagram_id], map: "idx_table_relationships_diagram_id")
|
||||
@@index([from_table_name], map: "idx_table_relationships_from_table")
|
||||
@@index([to_table_name], map: "idx_table_relationships_to_table")
|
||||
@@index([company_code, diagram_id], map: "idx_table_relationships_company_diagram")
|
||||
}
|
||||
|
||||
// 테이블 간 데이터 관계 중계 테이블 - 실제 데이터 연결 정보 저장
|
||||
|
||||
@@ -15,6 +15,7 @@ export async function createTableRelationship(
|
||||
logger.info("=== 테이블 관계 생성 시작 ===");
|
||||
|
||||
const {
|
||||
diagramId,
|
||||
relationshipName,
|
||||
fromTableName,
|
||||
fromColumnName,
|
||||
@@ -52,6 +53,7 @@ export async function createTableRelationship(
|
||||
|
||||
const dataflowService = new DataflowService();
|
||||
const relationship = await dataflowService.createTableRelationship({
|
||||
diagramId: diagramId ? parseInt(diagramId) : undefined,
|
||||
relationshipName,
|
||||
fromTableName,
|
||||
fromColumnName,
|
||||
@@ -828,7 +830,62 @@ export async function deleteDiagram(
|
||||
}
|
||||
|
||||
/**
|
||||
* relationship_id로 관계도 관계 조회
|
||||
* diagram_id로 관계도 관계 조회
|
||||
*/
|
||||
export async function getDiagramRelationshipsByDiagramId(
|
||||
req: AuthenticatedRequest,
|
||||
res: Response
|
||||
): Promise<void> {
|
||||
try {
|
||||
const { diagramId } = req.params;
|
||||
const companyCode = (req.user as any)?.company_code || "*";
|
||||
|
||||
if (!diagramId) {
|
||||
const response: ApiResponse<null> = {
|
||||
success: false,
|
||||
message: "관계도 ID가 필요합니다.",
|
||||
error: {
|
||||
code: "MISSING_DIAGRAM_ID",
|
||||
details: "diagramId 파라미터가 필요합니다.",
|
||||
},
|
||||
};
|
||||
res.status(400).json(response);
|
||||
return;
|
||||
}
|
||||
|
||||
const dataflowService = new DataflowService();
|
||||
const relationships =
|
||||
await dataflowService.getDiagramRelationshipsByDiagramId(
|
||||
companyCode,
|
||||
parseInt(diagramId)
|
||||
);
|
||||
|
||||
const response: ApiResponse<any[]> = {
|
||||
success: true,
|
||||
message: "관계도 관계 목록을 성공적으로 조회했습니다.",
|
||||
data: relationships,
|
||||
};
|
||||
|
||||
res.status(200).json(response);
|
||||
} catch (error) {
|
||||
logger.error("관계도 관계 조회 실패:", error);
|
||||
const response: ApiResponse<null> = {
|
||||
success: false,
|
||||
message: "관계도 관계 조회에 실패했습니다.",
|
||||
error: {
|
||||
code: "DIAGRAM_RELATIONSHIPS_FETCH_FAILED",
|
||||
details:
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "알 수 없는 오류가 발생했습니다.",
|
||||
},
|
||||
};
|
||||
res.status(500).json(response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* relationship_id로 관계도 관계 조회 (하위 호환성 유지)
|
||||
*/
|
||||
export async function getDiagramRelationshipsByRelationshipId(
|
||||
req: AuthenticatedRequest,
|
||||
@@ -852,10 +909,11 @@ export async function getDiagramRelationshipsByRelationshipId(
|
||||
}
|
||||
|
||||
const dataflowService = new DataflowService();
|
||||
const relationships = await dataflowService.getDiagramRelationshipsByRelationshipId(
|
||||
companyCode,
|
||||
parseInt(relationshipId)
|
||||
);
|
||||
const relationships =
|
||||
await dataflowService.getDiagramRelationshipsByRelationshipId(
|
||||
companyCode,
|
||||
parseInt(relationshipId)
|
||||
);
|
||||
|
||||
const response: ApiResponse<any[]> = {
|
||||
success: true,
|
||||
@@ -871,7 +929,10 @@ export async function getDiagramRelationshipsByRelationshipId(
|
||||
message: "관계도 관계 조회에 실패했습니다.",
|
||||
error: {
|
||||
code: "DIAGRAM_RELATIONSHIPS_FETCH_FAILED",
|
||||
details: error instanceof Error ? error.message : "알 수 없는 오류가 발생했습니다.",
|
||||
details:
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "알 수 없는 오류가 발생했습니다.",
|
||||
},
|
||||
};
|
||||
res.status(500).json(response);
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
getTableData,
|
||||
getDataFlowDiagrams,
|
||||
getDiagramRelationships,
|
||||
getDiagramRelationshipsByDiagramId,
|
||||
getDiagramRelationshipsByRelationshipId,
|
||||
copyDiagram,
|
||||
deleteDiagram,
|
||||
@@ -92,10 +93,22 @@ router.get("/table-data/:tableName", getTableData);
|
||||
router.get("/diagrams", getDataFlowDiagrams);
|
||||
|
||||
/**
|
||||
* 특정 관계도의 모든 관계 조회
|
||||
* GET /api/dataflow/diagrams/:diagramName/relationships
|
||||
* 특정 관계도의 모든 관계 조회 (diagram_id로)
|
||||
* GET /api/dataflow/diagrams/:diagramId/relationships
|
||||
*/
|
||||
router.get("/diagrams/:diagramName/relationships", getDiagramRelationships);
|
||||
router.get(
|
||||
"/diagrams/:diagramId/relationships",
|
||||
getDiagramRelationshipsByDiagramId
|
||||
);
|
||||
|
||||
/**
|
||||
* 특정 관계도의 모든 관계 조회 (diagramName으로 - 하위 호환성)
|
||||
* GET /api/dataflow/diagrams/name/:diagramName/relationships
|
||||
*/
|
||||
router.get(
|
||||
"/diagrams/name/:diagramName/relationships",
|
||||
getDiagramRelationships
|
||||
);
|
||||
|
||||
/**
|
||||
* 관계도 복사
|
||||
@@ -109,7 +122,7 @@ router.post("/diagrams/:diagramName/copy", copyDiagram);
|
||||
*/
|
||||
router.delete("/diagrams/:diagramName", deleteDiagram);
|
||||
|
||||
// relationship_id로 관계도 관계 조회
|
||||
// relationship_id로 관계도 관계 조회 (하위 호환성)
|
||||
router.get(
|
||||
"/relationships/:relationshipId/diagram",
|
||||
getDiagramRelationshipsByRelationshipId
|
||||
|
||||
@@ -5,6 +5,7 @@ const prisma = new PrismaClient();
|
||||
|
||||
// 테이블 관계 생성 데이터 타입
|
||||
interface CreateTableRelationshipData {
|
||||
diagramId?: number; // 기존 관계도에 추가하는 경우
|
||||
relationshipName: string;
|
||||
fromTableName: string;
|
||||
fromColumnName: string;
|
||||
@@ -38,9 +39,31 @@ export class DataflowService {
|
||||
try {
|
||||
logger.info("DataflowService: 테이블 관계 생성 시작", data);
|
||||
|
||||
// 중복 관계 확인
|
||||
// diagram_id 결정 로직
|
||||
let diagramId = data.diagramId;
|
||||
|
||||
if (!diagramId) {
|
||||
// 새로운 관계도인 경우, 새로운 diagram_id 생성
|
||||
// 현재 최대 diagram_id + 1
|
||||
const maxDiagramId = await prisma.table_relationships.findFirst({
|
||||
where: {
|
||||
company_code: data.companyCode,
|
||||
},
|
||||
orderBy: {
|
||||
diagram_id: "desc",
|
||||
},
|
||||
select: {
|
||||
diagram_id: true,
|
||||
},
|
||||
});
|
||||
|
||||
diagramId = (maxDiagramId?.diagram_id || 0) + 1;
|
||||
}
|
||||
|
||||
// 중복 관계 확인 (같은 diagram_id 내에서)
|
||||
const existingRelationship = await prisma.table_relationships.findFirst({
|
||||
where: {
|
||||
diagram_id: diagramId,
|
||||
from_table_name: data.fromTableName,
|
||||
from_column_name: data.fromColumnName,
|
||||
to_table_name: data.toTableName,
|
||||
@@ -56,9 +79,10 @@ export class DataflowService {
|
||||
);
|
||||
}
|
||||
|
||||
// 새 관계 생성 (중계 테이블은 별도로 생성하지 않음)
|
||||
// 새 관계 생성
|
||||
const relationship = await prisma.table_relationships.create({
|
||||
data: {
|
||||
diagram_id: diagramId,
|
||||
relationship_name: data.relationshipName,
|
||||
from_table_name: data.fromTableName,
|
||||
from_column_name: data.fromColumnName,
|
||||
@@ -74,7 +98,7 @@ export class DataflowService {
|
||||
});
|
||||
|
||||
logger.info(
|
||||
`DataflowService: 테이블 관계 생성 완료 - ID: ${relationship.relationship_id}`
|
||||
`DataflowService: 테이블 관계 생성 완료 - ID: ${relationship.relationship_id}, Diagram ID: ${relationship.diagram_id}`
|
||||
);
|
||||
return relationship;
|
||||
} catch (error) {
|
||||
@@ -731,7 +755,7 @@ export class DataflowService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 관계도 그룹 목록 조회 (관계도 이름별로 그룹화)
|
||||
* 관계도 그룹 목록 조회 (diagram_id별로 그룹화)
|
||||
*/
|
||||
async getDataFlowDiagrams(
|
||||
companyCode: string,
|
||||
@@ -744,7 +768,7 @@ export class DataflowService {
|
||||
`DataflowService: 관계도 목록 조회 시작 - ${companyCode}, page: ${page}, size: ${size}, search: ${searchTerm}`
|
||||
);
|
||||
|
||||
// 관계도 이름별로 그룹화하여 조회
|
||||
// diagram_id별로 그룹화하여 조회
|
||||
const whereCondition = {
|
||||
company_code: companyCode,
|
||||
is_active: "Y",
|
||||
@@ -772,11 +796,12 @@ export class DataflowService {
|
||||
}),
|
||||
};
|
||||
|
||||
// 관계도별로 그룹화된 데이터 조회 (관계도 이름을 기준으로)
|
||||
// diagram_id별로 그룹화된 데이터 조회
|
||||
const relationships = await prisma.table_relationships.findMany({
|
||||
where: whereCondition,
|
||||
select: {
|
||||
relationship_id: true,
|
||||
diagram_id: true,
|
||||
relationship_name: true,
|
||||
from_table_name: true,
|
||||
to_table_name: true,
|
||||
@@ -787,19 +812,19 @@ export class DataflowService {
|
||||
updated_date: true,
|
||||
updated_by: true,
|
||||
},
|
||||
orderBy: [{ relationship_name: "asc" }, { created_date: "desc" }],
|
||||
orderBy: [{ diagram_id: "asc" }, { created_date: "desc" }],
|
||||
});
|
||||
|
||||
// 관계도 이름별로 그룹화
|
||||
const diagramMap = new Map<string, any>();
|
||||
// diagram_id별로 그룹화
|
||||
const diagramMap = new Map<number, any>();
|
||||
|
||||
relationships.forEach((rel) => {
|
||||
const diagramName = rel.relationship_name;
|
||||
const diagramId = rel.diagram_id;
|
||||
|
||||
if (!diagramMap.has(diagramName)) {
|
||||
diagramMap.set(diagramName, {
|
||||
relationshipId: rel.relationship_id, // 첫 번째 관계의 ID를 대표 ID로 사용
|
||||
diagramName: diagramName,
|
||||
if (!diagramMap.has(diagramId)) {
|
||||
diagramMap.set(diagramId, {
|
||||
diagramId: diagramId,
|
||||
diagramName: rel.relationship_name, // 첫 번째 관계의 이름을 사용
|
||||
connectionType: rel.connection_type,
|
||||
relationshipType: rel.relationship_type,
|
||||
tableCount: new Set<string>(),
|
||||
@@ -812,7 +837,7 @@ export class DataflowService {
|
||||
});
|
||||
}
|
||||
|
||||
const diagram = diagramMap.get(diagramName);
|
||||
const diagram = diagramMap.get(diagramId);
|
||||
diagram.tableCount.add(rel.from_table_name);
|
||||
diagram.tableCount.add(rel.to_table_name);
|
||||
diagram.relationshipCount++;
|
||||
@@ -893,7 +918,7 @@ export class DataflowService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 관계도 복사
|
||||
* 관계도 복사 (diagram_id 기반)
|
||||
*/
|
||||
async copyDiagram(
|
||||
companyCode: string,
|
||||
@@ -936,11 +961,27 @@ export class DataflowService {
|
||||
newDiagramName = `${originalDiagramName} (${counter})`;
|
||||
}
|
||||
|
||||
// 새로운 diagram_id 생성
|
||||
const maxDiagramId = await prisma.table_relationships.findFirst({
|
||||
where: {
|
||||
company_code: companyCode,
|
||||
},
|
||||
orderBy: {
|
||||
diagram_id: "desc",
|
||||
},
|
||||
select: {
|
||||
diagram_id: true,
|
||||
},
|
||||
});
|
||||
|
||||
const newDiagramId = (maxDiagramId?.diagram_id || 0) + 1;
|
||||
|
||||
// 트랜잭션으로 모든 관계 복사
|
||||
const copiedRelationships = await prisma.$transaction(
|
||||
originalRelationships.map((rel) =>
|
||||
prisma.table_relationships.create({
|
||||
data: {
|
||||
diagram_id: newDiagramId,
|
||||
relationship_name: newDiagramName,
|
||||
from_table_name: rel.from_table_name,
|
||||
from_column_name: rel.from_column_name,
|
||||
@@ -959,7 +1000,7 @@ export class DataflowService {
|
||||
);
|
||||
|
||||
logger.info(
|
||||
`DataflowService: 관계도 복사 완료 - ${originalDiagramName} → ${newDiagramName}, ${copiedRelationships.length}개 관계 복사`
|
||||
`DataflowService: 관계도 복사 완료 - ${originalDiagramName} → ${newDiagramName} (diagram_id: ${newDiagramId}), ${copiedRelationships.length}개 관계 복사`
|
||||
);
|
||||
|
||||
return newDiagramName;
|
||||
@@ -1002,7 +1043,46 @@ export class DataflowService {
|
||||
}
|
||||
|
||||
/**
|
||||
* relationship_id로 해당 관계도의 모든 관계 조회
|
||||
* diagram_id로 해당 관계도의 모든 관계 조회
|
||||
*/
|
||||
async getDiagramRelationshipsByDiagramId(
|
||||
companyCode: string,
|
||||
diagramId: number
|
||||
) {
|
||||
try {
|
||||
logger.info(
|
||||
`DataflowService: diagram_id로 관계도 관계 조회 - ${diagramId}`
|
||||
);
|
||||
|
||||
// diagram_id로 모든 관계 조회
|
||||
const relationships = await prisma.table_relationships.findMany({
|
||||
where: {
|
||||
diagram_id: diagramId,
|
||||
company_code: companyCode,
|
||||
is_active: "Y",
|
||||
},
|
||||
orderBy: [{ relationship_id: "asc" }],
|
||||
});
|
||||
|
||||
logger.info(
|
||||
`DataflowService: diagram_id로 관계도 관계 조회 완료 - ${relationships.length}개 관계`
|
||||
);
|
||||
|
||||
return relationships.map((rel) => ({
|
||||
...rel,
|
||||
settings: rel.settings as any,
|
||||
}));
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`DataflowService: diagram_id로 관계도 관계 조회 실패 - ${diagramId}`,
|
||||
error
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* relationship_id로 해당 관계도의 모든 관계 조회 (하위 호환성 유지)
|
||||
*/
|
||||
async getDiagramRelationshipsByRelationshipId(
|
||||
companyCode: string,
|
||||
@@ -1013,7 +1093,7 @@ export class DataflowService {
|
||||
`DataflowService: relationship_id로 관계도 관계 조회 - ${relationshipId}`
|
||||
);
|
||||
|
||||
// 먼저 해당 relationship_id의 관계도명을 찾음
|
||||
// 먼저 해당 relationship_id의 diagram_id를 찾음
|
||||
const targetRelationship = await prisma.table_relationships.findFirst({
|
||||
where: {
|
||||
relationship_id: relationshipId,
|
||||
@@ -1021,7 +1101,7 @@ export class DataflowService {
|
||||
is_active: "Y",
|
||||
},
|
||||
select: {
|
||||
relationship_name: true,
|
||||
diagram_id: true,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1029,24 +1109,11 @@ export class DataflowService {
|
||||
throw new Error("해당 관계 ID를 찾을 수 없습니다.");
|
||||
}
|
||||
|
||||
// 같은 관계도명을 가진 모든 관계 조회
|
||||
const relationships = await prisma.table_relationships.findMany({
|
||||
where: {
|
||||
relationship_name: targetRelationship.relationship_name,
|
||||
company_code: companyCode,
|
||||
is_active: "Y",
|
||||
},
|
||||
orderBy: [{ relationship_id: "asc" }],
|
||||
});
|
||||
|
||||
logger.info(
|
||||
`DataflowService: relationship_id로 관계도 관계 조회 완료 - ${relationships.length}개 관계`
|
||||
// diagram_id로 모든 관계 조회
|
||||
return this.getDiagramRelationshipsByDiagramId(
|
||||
companyCode,
|
||||
targetRelationship.diagram_id
|
||||
);
|
||||
|
||||
return relationships.map((rel) => ({
|
||||
...rel,
|
||||
settings: rel.settings as any,
|
||||
}));
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`DataflowService: relationship_id로 관계도 관계 조회 실패 - ${relationshipId}`,
|
||||
|
||||
Reference in New Issue
Block a user