테이블 리스트 오류수정

This commit is contained in:
kjs 2025-10-01 17:18:48 +09:00
parent 767c031629
commit b84f35d514
1 changed files with 50 additions and 45 deletions

View File

@ -250,13 +250,13 @@ export class ImprovedButtonActionExecutor {
throw new Error(`관계 정보를 찾을 수 없습니다: ${config.relationshipId}`);
}
console.log(`📋 관계 데이터 로드 완료:`, relationshipData);
console.log("📋 관계 데이터 로드 완료:", relationshipData);
// 2. 관계 타입에 따른 실행
const relationships = relationshipData.relationships;
const connectionType = relationships.connectionType;
console.log(`🔍 관계 상세 정보:`, {
console.log("🔍 관계 상세 정보:", {
connectionType,
hasExternalCallConfig: !!relationships.externalCallConfig,
externalCallConfig: relationships.externalCallConfig,
@ -308,7 +308,7 @@ export class ImprovedButtonActionExecutor {
const response = await apiClient.get(`/dataflow-diagrams/${relationshipId}`);
console.log(`✅ 관계 데이터 조회 성공:`, response.data);
console.log("✅ 관계 데이터 조회 성공:", response.data);
if (!response.data.success) {
throw new Error(response.data.message || "관계 데이터 조회 실패");
@ -330,10 +330,10 @@ export class ImprovedButtonActionExecutor {
context: ButtonExecutionContext,
): Promise<ExecutionResult> {
try {
console.log(`🔍 외부 호출 실행 시작 - relationships 구조:`, relationships);
console.log("🔍 외부 호출 실행 시작 - relationships 구조:", relationships);
const externalCallConfig = relationships.externalCallConfig;
console.log(`🔍 externalCallConfig:`, externalCallConfig);
console.log("🔍 externalCallConfig:", externalCallConfig);
if (!externalCallConfig) {
console.error("❌ 외부 호출 설정이 없습니다. relationships 구조:", relationships);
@ -368,7 +368,7 @@ export class ImprovedButtonActionExecutor {
}
// 백엔드 프록시를 통한 외부 API 호출 (CORS 문제 해결)
console.log(`🌐 백엔드 프록시를 통한 외부 API 호출 준비:`, {
console.log("🌐 백엔드 프록시를 통한 외부 API 호출 준비:", {
originalUrl: restApiSettings.apiUrl,
method: restApiSettings.httpMethod || "GET",
headers,
@ -393,24 +393,24 @@ export class ImprovedButtonActionExecutor {
templateData: restApiSettings.httpMethod !== "GET" && requestBody ? JSON.parse(requestBody) : formData,
};
console.log(`📤 백엔드로 전송할 데이터:`, requestPayload);
console.log("📤 백엔드로 전송할 데이터:", requestPayload);
const proxyResponse = await apiClient.post(`/external-calls/execute`, requestPayload);
const proxyResponse = await apiClient.post("/external-calls/execute", requestPayload);
console.log(`📡 백엔드 프록시 응답:`, proxyResponse.data);
console.log("📡 백엔드 프록시 응답:", proxyResponse.data);
if (!proxyResponse.data.success) {
throw new Error(`프록시 API 호출 실패: ${proxyResponse.data.error || proxyResponse.data.message}`);
}
const responseData = proxyResponse.data.result;
console.log(`✅ 외부 API 호출 성공 (프록시):`, responseData);
console.log("✅ 외부 API 호출 성공 (프록시):", responseData);
// 데이터 매핑 처리 (inbound mapping)
if (externalCallConfig.dataMappingConfig?.inboundMapping) {
console.log(`📥 데이터 매핑 설정 발견 - HTTP 메서드: ${restApiSettings.httpMethod}`);
console.log(`📥 매핑 설정:`, externalCallConfig.dataMappingConfig.inboundMapping);
console.log(`📥 응답 데이터:`, responseData);
console.log("📥 매핑 설정:", externalCallConfig.dataMappingConfig.inboundMapping);
console.log("📥 응답 데이터:", responseData);
await this.processInboundMapping(externalCallConfig.dataMappingConfig.inboundMapping, responseData, context);
} else {
@ -443,7 +443,7 @@ export class ImprovedButtonActionExecutor {
context: ButtonExecutionContext,
): Promise<ExecutionResult> {
try {
console.log(`💾 데이터 저장 실행 시작`);
console.log("💾 데이터 저장 실행 시작");
// 제어 조건 확인
const controlConditions = relationships.controlConditions || [];
@ -520,11 +520,13 @@ export class ImprovedButtonActionExecutor {
): Promise<ExecutionResult> {
try {
console.log(`🔧 데이터 액션 실행: ${action.name} (${action.actionType})`);
console.log(`📥 받은 formData:`, formData);
console.log("📥 받은 formData:", formData);
console.log("📥 formData 키들:", Object.keys(formData));
// 🔥 UPDATE 액션의 경우 formData를 기본으로 시작
// 🔥 UPDATE 액션의 경우 formData를 기본으로 시작 (기본키 포함)
const mappedData: Record<string, any> = action.actionType === "update" ? { ...formData } : {};
// 필드 매핑 처리 (기존 데이터에 덮어쓰기)
for (const mapping of action.fieldMappings) {
if (mapping.valueType === "static") {
// 정적 값 처리
@ -533,19 +535,22 @@ export class ImprovedButtonActionExecutor {
value = new Date().toISOString();
}
mappedData[mapping.targetField] = value;
console.log(`🔧 정적 값 매핑: ${mapping.targetField} = ${value}`);
} else {
// 필드 매핑 처리
const sourceField = mapping.fromField?.columnName;
if (sourceField && formData[sourceField] !== undefined) {
mappedData[mapping.toField.columnName] = formData[sourceField];
console.log(`🔧 필드 매핑: ${sourceField}${mapping.toField.columnName} = ${formData[sourceField]}`);
}
}
}
console.log(`📋 매핑된 데이터:`, mappedData);
console.log(`🔑 기본키 포함 여부 체크:`, {
console.log("📋 최종 매핑된 데이터:", mappedData);
console.log("🔑 기본키 포함 여부 체크:", {
hasId: "id" in mappedData,
keys: Object.keys(mappedData),
values: Object.values(mappedData),
});
// 대상 연결 정보
@ -616,7 +621,7 @@ export class ImprovedButtonActionExecutor {
formData: Record<string, any>,
context: ButtonExecutionContext,
): boolean {
console.log(`🔍 조건 평가 시작:`, {
console.log("🔍 조건 평가 시작:", {
conditions,
formDataKeys: Object.keys(formData),
formData,
@ -628,7 +633,7 @@ export class ImprovedButtonActionExecutor {
const conditionValue = condition.value;
const operator = condition.operator;
console.log(`🔍 개별 조건 검증:`, {
console.log("🔍 개별 조건 검증:", {
field: condition.field,
operator,
expectedValue: conditionValue,
@ -664,13 +669,13 @@ export class ImprovedButtonActionExecutor {
if (!conditionMet) {
console.log(`❌ 조건 불만족: ${condition.field} ${operator} ${conditionValue} (실제값: ${fieldValue})`);
console.log(`❌ 사용 가능한 필드들:`, Object.keys(formData));
console.log(`❌ 전체 formData:`, formData);
console.log("❌ 사용 가능한 필드들:", Object.keys(formData));
console.log("❌ 전체 formData:", formData);
return false;
}
}
console.log(`✅ 모든 조건 만족`);
console.log("✅ 모든 조건 만족");
return true;
}
@ -682,25 +687,25 @@ export class ImprovedButtonActionExecutor {
// null이나 undefined인 경우
if (!responseData) {
console.log(`⚠️ 응답 데이터가 null 또는 undefined`);
console.log("⚠️ 응답 데이터가 null 또는 undefined");
return [];
}
// 이미 배열인 경우 (직접 배열 응답)
if (Array.isArray(responseData)) {
console.log(`✅ 직접 배열 응답 감지`);
console.log("✅ 직접 배열 응답 감지");
return responseData;
}
// 문자열인 경우 JSON 파싱 시도
if (typeof responseData === "string") {
console.log(`🔄 JSON 문자열 파싱 시도`);
console.log("🔄 JSON 문자열 파싱 시도");
try {
const parsed = JSON.parse(responseData);
console.log(`✅ JSON 파싱 성공, 재귀 호출`);
console.log("✅ JSON 파싱 성공, 재귀 호출");
return this.extractActualData(parsed);
} catch (error) {
console.log(`⚠️ JSON 파싱 실패, 원본 문자열 반환:`, error);
console.log("⚠️ JSON 파싱 실패, 원본 문자열 반환:", error);
return [responseData];
}
}
@ -733,20 +738,20 @@ export class ImprovedButtonActionExecutor {
// 추출된 데이터가 문자열인 경우 JSON 파싱 시도
if (typeof extractedData === "string") {
console.log(`🔄 추출된 데이터가 JSON 문자열, 파싱 시도`);
console.log("🔄 추출된 데이터가 JSON 문자열, 파싱 시도");
try {
const parsed = JSON.parse(extractedData);
console.log(`✅ JSON 파싱 성공, 재귀 호출`);
console.log("✅ JSON 파싱 성공, 재귀 호출");
return this.extractActualData(parsed);
} catch (error) {
console.log(`⚠️ JSON 파싱 실패, 원본 문자열 반환:`, error);
console.log("⚠️ JSON 파싱 실패, 원본 문자열 반환:", error);
return [extractedData];
}
}
// 추출된 데이터가 객체이고 또 다른 중첩 구조일 수 있으므로 재귀 호출
if (typeof extractedData === "object" && !Array.isArray(extractedData)) {
console.log(`🔄 중첩된 객체 감지, 재귀 추출 시도`);
console.log("🔄 중첩된 객체 감지, 재귀 추출 시도");
return this.extractActualData(extractedData);
}
@ -759,14 +764,14 @@ export class ImprovedButtonActionExecutor {
const arrayValue = objectValues.find((value) => Array.isArray(value));
if (arrayValue) {
console.log(`✅ 객체 값 중 배열 발견`);
console.log("✅ 객체 값 중 배열 발견");
return arrayValue;
}
// 객체의 값들 중에서 객체를 찾아서 재귀 탐색
for (const value of objectValues) {
if (value && typeof value === "object" && !Array.isArray(value)) {
console.log(`🔄 객체 값에서 재귀 탐색`);
console.log("🔄 객체 값에서 재귀 탐색");
const nestedResult = this.extractActualData(value);
if (Array.isArray(nestedResult) && nestedResult.length > 0) {
return nestedResult;
@ -775,7 +780,7 @@ export class ImprovedButtonActionExecutor {
}
// 모든 시도가 실패한 경우, 원본 객체를 단일 항목 배열로 반환
console.log(`📦 원본 객체를 단일 항목으로 처리`);
console.log("📦 원본 객체를 단일 항목으로 처리");
return [responseData];
}
@ -788,38 +793,38 @@ export class ImprovedButtonActionExecutor {
context: ButtonExecutionContext,
): Promise<void> {
try {
console.log(`📥 인바운드 데이터 매핑 처리 시작`);
console.log(`📥 원본 응답 데이터:`, responseData);
console.log("📥 인바운드 데이터 매핑 처리 시작");
console.log("📥 원본 응답 데이터:", responseData);
const targetTable = inboundMapping.targetTable;
const fieldMappings = inboundMapping.fieldMappings || [];
const insertMode = inboundMapping.insertMode || "insert";
console.log(`📥 매핑 설정:`, {
console.log("📥 매핑 설정:", {
targetTable,
fieldMappings,
insertMode,
});
// 응답 데이터에서 실제 데이터 추출 (다양한 구조 지원)
let actualData = this.extractActualData(responseData);
const actualData = this.extractActualData(responseData);
console.log(`📥 추출된 실제 데이터:`, actualData);
console.log("📥 추출된 실제 데이터:", actualData);
// 배열이 아닌 경우 배열로 변환
const dataArray = Array.isArray(actualData) ? actualData : [actualData];
console.log(`📥 처리할 데이터 배열:`, dataArray);
console.log("📥 처리할 데이터 배열:", dataArray);
if (dataArray.length === 0) {
console.log(`⚠️ 처리할 데이터가 없습니다`);
console.log("⚠️ 처리할 데이터가 없습니다");
return;
}
for (const item of dataArray) {
const mappedData: Record<string, any> = {};
console.log(`📥 개별 아이템 처리:`, item);
console.log("📥 개별 아이템 처리:", item);
// 필드 매핑 적용
for (const mapping of fieldMappings) {
@ -831,17 +836,17 @@ export class ImprovedButtonActionExecutor {
}
}
console.log(`📋 매핑된 데이터:`, mappedData);
console.log("📋 매핑된 데이터:", mappedData);
// 매핑된 데이터가 비어있지 않은 경우에만 저장
if (Object.keys(mappedData).length > 0) {
await this.saveDataToTable(targetTable, mappedData, insertMode);
} else {
console.log(`⚠️ 매핑된 데이터가 비어있어 저장을 건너뜁니다`);
console.log("⚠️ 매핑된 데이터가 비어있어 저장을 건너뜁니다");
}
}
console.log(`✅ 인바운드 데이터 매핑 완료`);
console.log("✅ 인바운드 데이터 매핑 완료");
} catch (error) {
console.error("인바운드 데이터 매핑 오류:", error);
throw error;