diff --git a/backend-node/src/controllers/conditionalConnectionController.ts b/backend-node/src/controllers/conditionalConnectionController.ts index a032ba6d..7ed1782f 100644 --- a/backend-node/src/controllers/conditionalConnectionController.ts +++ b/backend-node/src/controllers/conditionalConnectionController.ts @@ -16,7 +16,7 @@ export async function testConditionalConnection( const { diagramId } = req.params; const { testData } = req.body; - const companyCode = req.user?.company_code; + const companyCode = req.user?.companyCode; if (!companyCode) { const response: ApiResponse = { @@ -86,7 +86,7 @@ export async function executeConditionalActions( const { diagramId } = req.params; const { triggerType, tableName, data } = req.body; - const companyCode = req.user?.company_code; + const companyCode = req.user?.companyCode; if (!companyCode) { const response: ApiResponse = { diff --git a/backend-node/src/services/eventTriggerService.ts b/backend-node/src/services/eventTriggerService.ts index 10e3651e..a332d57a 100644 --- a/backend-node/src/services/eventTriggerService.ts +++ b/backend-node/src/services/eventTriggerService.ts @@ -1,5 +1,5 @@ import { PrismaClient } from "@prisma/client"; -import { logger } from "../config/logger.js"; +import { logger } from "../utils/logger"; const prisma = new PrismaClient(); @@ -9,24 +9,7 @@ interface ConditionNode { operator?: "AND" | "OR"; children?: ConditionNode[]; field?: string; - operator_type?: - | "=" - | "!=" - | ">" - | "<" - | ">=" - | "<=" - | "LIKE" - | "NOT_LIKE" - | "CONTAINS" - | "STARTS_WITH" - | "ENDS_WITH" - | "IN" - | "NOT_IN" - | "IS_NULL" - | "IS_NOT_NULL" - | "BETWEEN" - | "NOT_BETWEEN"; + operator_type?: "=" | "!=" | ">" | "<" | ">=" | "<=" | "LIKE"; value?: any; dataType?: string; } @@ -164,9 +147,9 @@ export class EventTriggerService { const errors: string[] = []; try { - const control = diagram.control as ConditionControl; - const category = diagram.category as ConnectionCategory; - const plan = diagram.plan as ExecutionPlan; + const control = diagram.control as unknown as ConditionControl; + const category = diagram.category as unknown as ConnectionCategory; + const plan = diagram.plan as unknown as ExecutionPlan; logger.info( `Executing diagram ${diagram.diagram_id} (${diagram.diagram_name})` @@ -302,38 +285,6 @@ export class EventTriggerService { return Number(fieldValue) <= Number(value); case "LIKE": return String(fieldValue).includes(String(value)); - case "NOT_LIKE": - return !String(fieldValue).includes(String(value)); - case "CONTAINS": - return String(fieldValue) - .toLowerCase() - .includes(String(value).toLowerCase()); - case "STARTS_WITH": - return String(fieldValue).startsWith(String(value)); - case "ENDS_WITH": - return String(fieldValue).endsWith(String(value)); - case "IN": - return Array.isArray(value) && value.includes(fieldValue); - case "NOT_IN": - return Array.isArray(value) && !value.includes(fieldValue); - case "IS_NULL": - return fieldValue == null || fieldValue === undefined; - case "IS_NOT_NULL": - return fieldValue != null && fieldValue !== undefined; - case "BETWEEN": - if (Array.isArray(value) && value.length === 2) { - const numValue = Number(fieldValue); - return numValue >= Number(value[0]) && numValue <= Number(value[1]); - } - return false; - case "NOT_BETWEEN": - if (Array.isArray(value) && value.length === 2) { - const numValue = Number(fieldValue); - return !( - numValue >= Number(value[0]) && numValue <= Number(value[1]) - ); - } - return false; default: return false; } @@ -553,7 +504,7 @@ export class EventTriggerService { throw new Error(`Diagram ${diagramId} not found`); } - const control = diagram.control as ConditionControl; + const control = diagram.control as unknown as ConditionControl; // 조건 평가만 수행 const conditionMet = control.conditionTree diff --git a/docs/조건부_연결_구현_계획.md b/docs/조건부_연결_구현_계획.md index a16b7cd7..c1e5b4f6 100644 --- a/docs/조건부_연결_구현_계획.md +++ b/docs/조건부_연결_구현_계획.md @@ -2,13 +2,13 @@ ## 📋 프로젝트 개요 -현재 DataFlow 시스템에서 3가지 연결 종류를 지원하고 있으며, 이 중 **데이터 저장**과 **외부 호출** 기능에 조건부 실행 로직을 추가해야 합니다. +현재 DataFlow 시스템에서 3가지 연결 종류를 지원하고 있으며, 이 중 **데이터 저장**과 **외부 호출** 기능에 실행 조건 로직을 추가해야 합니다. ### 현재 연결 종류 1. **단순 키값 연결** - 조건 설정 불필요 (기존 방식 유지) -2. **데이터 저장** - 조건부 실행 필요 ✨ -3. **외부 호출** - 조건부 실행 필요 ✨ +2. **데이터 저장** - 실행 조건 설정 필요 ✨ +3. **외부 호출** - 실행 조건 설정 필요 ✨ ## 🎯 기능 요구사항 @@ -78,9 +78,7 @@ CREATE INDEX idx_dataflow_category_type ON dataflow_diagrams USING GIN ((categor ```json { - "type": "data-save", // "simple-key" | "data-save" | "external-call" - "rollbackOnError": true, - "enableLogging": true + "type": "data-save" // "simple-key" | "data-save" | "external-call" } ``` @@ -265,7 +263,6 @@ router.post("/diagrams/:id/execute-actions", async (req, res) => { - 트랜잭션 롤백 지원 - 부분 실패 시 복구 메커니즘 -- 상세한 실행 로그 저장 ### 3. 보안 diff --git a/frontend/components/dataflow/ConnectionSetupModal.tsx b/frontend/components/dataflow/ConnectionSetupModal.tsx index 9a3b41d8..d8deba54 100644 --- a/frontend/components/dataflow/ConnectionSetupModal.tsx +++ b/frontend/components/dataflow/ConnectionSetupModal.tsx @@ -126,10 +126,7 @@ export const ConnectionSetupModal: React.FC = ({ const [selectedToColumns, setSelectedToColumns] = useState([]); // 조건부 연결을 위한 새로운 상태들 - const [triggerType, setTriggerType] = useState<"insert" | "update" | "delete" | "insert_update">("insert"); const [conditions, setConditions] = useState([]); - const [rollbackOnError, setRollbackOnError] = useState(true); - const [enableLogging, setEnableLogging] = useState(true); // 테이블 목록 로드 useEffect(() => { @@ -291,7 +288,7 @@ export const ConnectionSetupModal: React.FC = ({ const conditionalSettings = isConditionalConnection() ? { control: { - triggerType, + triggerType: "insert", conditionTree: conditions.length > 0 ? { @@ -303,8 +300,6 @@ export const ConnectionSetupModal: React.FC = ({ }, category: { type: config.connectionType, - rollbackOnError, - enableLogging, }, plan: { sourceTable: fromTableName, @@ -378,6 +373,7 @@ export const ConnectionSetupModal: React.FC = ({ operator_type: "=", value: "", dataType: "string", + operator: "AND", // 기본값으로 AND 설정 }; setConditions([...conditions, newCondition]); }; @@ -399,28 +395,7 @@ export const ConnectionSetupModal: React.FC = ({
- 조건부 실행 설정 -
- - {/* 트리거 타입 선택 */} -
- - + 실행 조건 설정
{/* 실행 조건 설정 */} @@ -443,81 +418,77 @@ export const ConnectionSetupModal: React.FC = ({
) : ( conditions.map((condition, index) => ( -
- +
+ {/* 첫 번째 조건이 아닐 때 AND/OR 연산자를 위에 표시 */} + {index > 0 && ( +
+ +
+ )} - + {/* 조건 행 */} +
+ - updateCondition(index, "value", e.target.value)} - className="h-8 flex-1 text-xs" - /> + - + updateCondition(index, "value", e.target.value)} + className="h-8 flex-1 text-xs" + /> + + +
)) )}
- - {/* 추가 옵션 */} -
- - - -
); }; diff --git a/frontend/lib/api/dataflow.ts b/frontend/lib/api/dataflow.ts index 04c95785..8e99db36 100644 --- a/frontend/lib/api/dataflow.ts +++ b/frontend/lib/api/dataflow.ts @@ -13,24 +13,7 @@ export interface ConditionNode { operator?: "AND" | "OR"; children?: ConditionNode[]; field?: string; - operator_type?: - | "=" - | "!=" - | ">" - | "<" - | ">=" - | "<=" - | "LIKE" - | "NOT_LIKE" - | "CONTAINS" - | "STARTS_WITH" - | "ENDS_WITH" - | "IN" - | "NOT_IN" - | "IS_NULL" - | "IS_NOT_NULL" - | "BETWEEN" - | "NOT_BETWEEN"; + operator_type?: "=" | "!=" | ">" | "<" | ">=" | "<=" | "LIKE"; value?: any; dataType?: string; }