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