ERP-node/frontend/types/control-management.ts

554 lines
12 KiB
TypeScript

/**
* 🎮 제어관리 시스템 전용 타입 정의
*
* 버튼 액션, 데이터플로우, 조건부 실행, 트랜잭션 처리 등 제어관리에서만 사용하는 타입들
*/
import {
ButtonActionType,
ConditionOperator,
CompanyCode,
ActiveStatus,
TimestampFields,
BaseApiResponse,
} from "./unified-core";
// ===== 버튼 제어 관련 =====
/**
* 확장된 버튼 설정 (화면관리의 ButtonTypeConfig 확장)
*/
export interface ExtendedButtonTypeConfig {
// 기본 버튼 설정
actionType: ButtonActionType;
text?: string;
variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link";
size?: "sm" | "md" | "lg";
icon?: string;
// 확인 및 검증
confirmMessage?: string;
requiresConfirmation?: boolean;
// 모달 관련 설정
popupTitle?: string;
popupContent?: string;
popupScreenId?: number;
// 네비게이션 관련 설정
navigateType?: "url" | "screen";
navigateUrl?: string;
navigateScreenId?: number;
navigateTarget?: "_self" | "_blank";
// 커스텀 액션 설정
customAction?: string;
// 🎯 제어관리 기능
enableDataflowControl?: boolean;
dataflowConfig?: ButtonDataflowConfig;
dataflowTiming?: "before" | "after" | "replace";
// 🆕 플로우 단계별 표시 제어
flowVisibilityConfig?: FlowVisibilityConfig;
// 스타일 설정
backgroundColor?: string;
textColor?: string;
borderColor?: string;
}
/**
* 플로우 단계별 버튼 표시 설정
*/
export interface FlowVisibilityConfig {
enabled: boolean;
targetFlowComponentId: string;
targetFlowId?: number;
targetFlowName?: string;
mode: "whitelist" | "blacklist" | "all";
visibleSteps?: number[];
hiddenSteps?: number[];
layoutBehavior: "preserve-position" | "auto-compact";
}
/**
* 🔥 단순화된 버튼 데이터플로우 설정
*/
export interface ButtonDataflowConfig {
// 제어 방식 선택 (관계 실행 + 🆕 노드 플로우)
controlMode: "relationship" | "flow" | "none";
// 관계 기반 제어
relationshipConfig?: {
relationshipId: string; // 관계 직접 선택
relationshipName: string; // 관계명 표시
executionTiming: "before" | "after" | "replace";
contextData?: Record<string, any>; // 실행 시 전달할 컨텍스트
};
// 🆕 노드 플로우 기반 제어
flowConfig?: {
flowId: number; // 노드 플로우 ID
flowName: string; // 플로우명 표시
executionTiming: "before" | "after" | "replace";
contextData?: Record<string, any>; // 실행 시 전달할 컨텍스트
};
// 제어 데이터 소스 (기존 호환성 유지)
controlDataSource?: ControlDataSource;
// 실행 옵션
executionOptions?: ExecutionOptions;
// 🔧 기존 호환성을 위한 필드들 (deprecated)
selectedDiagramId?: number;
selectedRelationshipId?: number;
directControl?: DirectControlConfig;
// 🔧 제거된 필드들 (하위 호환성을 위해 optional로 유지)
externalCallConfig?: any; // deprecated
customConfig?: any; // deprecated
}
/**
* 제어 데이터 소스 타입
*/
export type ControlDataSource = "form" | "table-selection" | "flow-selection" | "both";
/**
* 직접 제어 설정
*/
export interface DirectControlConfig {
conditions: DataflowCondition[];
actions: DataflowAction[];
logic?: "AND" | "OR" | "CUSTOM";
customLogic?: string; // "(A AND B) OR (C AND D)"
}
/**
* 실행 옵션
*/
export interface ExecutionOptions {
timeout?: number; // ms
retryCount?: number;
parallelExecution?: boolean;
continueOnError?: boolean;
}
// ===== 데이터플로우 조건 및 액션 =====
/**
* 데이터플로우 조건
*/
export interface DataflowCondition {
id: string;
type: "condition" | "group";
// 단일 조건
field?: string;
operator?: ConditionOperator;
value?: unknown;
dataSource?: ControlDataSource;
// 그룹 조건
conditions?: DataflowCondition[];
logic?: "AND" | "OR";
// 메타데이터
name?: string;
description?: string;
}
/**
* 데이터플로우 액션
*/
export interface DataflowAction {
id: string;
name: string;
type: ActionType;
// 데이터베이스 액션
tableName?: string;
operation?: DatabaseOperation;
fields?: ActionField[];
conditions?: DataflowCondition[];
// API 액션
endpoint?: string;
method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
headers?: Record<string, string>;
body?: unknown;
// 알림 액션
notificationType?: NotificationType;
message?: string;
recipients?: string[];
// 리다이렉트 액션
redirectUrl?: string;
redirectTarget?: "_self" | "_blank";
// 실행 옵션
timeout?: number;
retryCount?: number;
rollbackable?: boolean;
// 메타데이터
description?: string;
order?: number;
}
/**
* 액션 타입
*/
export type ActionType = "database" | "api" | "notification" | "redirect" | "custom";
/**
* 데이터베이스 작업 타입
*/
export type DatabaseOperation = "INSERT" | "UPDATE" | "DELETE" | "SELECT";
/**
* 액션 필드
*/
export interface ActionField {
name: string;
value: unknown;
type?: "static" | "dynamic" | "computed";
source?: string; // 동적 값의 소스 (form field, selected row 등)
}
/**
* 알림 타입
*/
export type NotificationType = "success" | "error" | "warning" | "info" | "toast" | "modal" | "email";
// ===== 트랜잭션 관리 =====
/**
* 트랜잭션 그룹
*/
export interface TransactionGroup {
id: string;
name: string;
description?: string;
actions: DataflowAction[];
rollbackStrategy: RollbackStrategy;
executionMode: "sequential" | "parallel";
onFailure: FailureHandling;
}
/**
* 롤백 전략
*/
export type RollbackStrategy =
| "none" // 롤백 안함
| "partial" // 실패한 액션만 롤백
| "complete"; // 전체 트랜잭션 롤백
/**
* 실패 처리 방식
*/
export type FailureHandling =
| "stop" // 실패 시 중단
| "continue" // 실패해도 계속 진행
| "alternative"; // 대안 액션 실행
/**
* 조건부 실행 계획
*/
export interface ConditionalExecutionPlan {
id: string;
name: string;
conditions: ExecutionCondition[];
logic: "AND" | "OR" | "CUSTOM";
customLogic?: string;
}
/**
* 실행 조건
*/
export interface ExecutionCondition {
id: string;
type: "action_group" | "validation" | "data_check";
// 액션 그룹 조건
actionGroup?: TransactionGroup;
// 검증 조건
validation?: {
field: string;
operator: ConditionOperator;
value: unknown;
};
// 성공/실패 조건
expectedResult: "success" | "failure" | "any";
}
/**
* 조건부 액션 그룹
*/
export interface ConditionalActionGroup {
id: string;
name: string;
description?: string;
// 실행 조건
executionCondition: {
type: "always" | "conditional" | "fallback";
conditions?: DataflowCondition[];
logic?: "AND" | "OR";
};
// 액션들
actions: DataflowAction[];
// 성공/실패 조건 정의
successCriteria: {
type: "all_success" | "any_success" | "custom";
customLogic?: string;
};
// 다음 단계 정의
onSuccess?: {
nextGroup?: string;
completeTransaction?: boolean;
};
onFailure?: {
retryCount?: number;
fallbackGroup?: string;
rollbackStrategy?: RollbackStrategy;
};
}
// ===== 실행 결과 및 상태 =====
/**
* 액션 실행 결과
*/
export interface ActionExecutionResult {
actionId: string;
transactionId?: string;
status: "pending" | "running" | "success" | "failed" | "rolled_back";
startTime: Date;
endTime?: Date;
result?: unknown;
error?: {
code: string;
message: string;
details?: unknown;
};
rollbackData?: unknown;
}
/**
* 트랜잭션 실행 상태
*/
export interface TransactionExecutionState {
transactionId: string;
status: "pending" | "running" | "success" | "failed" | "rolling_back" | "rolled_back";
actions: ActionExecutionResult[];
rollbackActions?: ActionExecutionResult[];
startTime: Date;
endTime?: Date;
}
/**
* 트랜잭션 실행 결과
*/
export interface TransactionExecutionResult {
success: boolean;
message: string;
requiresRollback: boolean;
results: [string, boolean][];
transactionId?: string;
}
/**
* 데이터플로우 실행 결과
*/
export interface DataflowExecutionResult {
success: boolean;
message: string;
data?: unknown;
executedActions?: ActionExecutionResult[];
failedActions?: ActionExecutionResult[];
totalActions?: number;
executionTime?: number;
}
// ===== 제어 컨텍스트 =====
/**
* 확장된 제어 컨텍스트
*/
export interface ExtendedControlContext {
// 기존 폼 데이터
formData: Record<string, unknown>;
// 테이블 선택 데이터
selectedRows?: unknown[];
selectedRowsData?: Record<string, unknown>[];
// 플로우 선택 데이터
flowSelectedData?: Record<string, unknown>[];
flowSelectedStepId?: number | null;
// 제어 데이터 소스 타입
controlDataSource: ControlDataSource;
// 기타 컨텍스트
buttonId?: string;
componentData?: unknown;
timestamp?: string;
clickCount?: number;
// 사용자 정보
userId?: string;
companyCode?: CompanyCode;
// 화면 정보
screenId?: number;
screenCode?: string;
}
/**
* 빠른 검증 결과
*/
export interface QuickValidationResult {
success: boolean;
message?: string;
canExecuteImmediately: boolean;
actions?: DataflowAction[];
}
// ===== 버튼 액션 표준 (DB 기반) =====
/**
* 버튼 액션 표준 정의 (DB의 button_action_standards 테이블)
*/
export interface ButtonActionStandard extends TimestampFields {
action_type: string;
action_name: string;
action_name_eng?: string;
description?: string;
category: string;
default_text?: string;
default_text_eng?: string;
default_icon?: string;
default_color?: string;
default_variant?: string;
confirmation_required: boolean;
confirmation_message?: string;
validation_rules?: unknown;
action_config?: unknown;
sort_order?: number;
is_active: ActiveStatus;
}
/**
* 버튼 액션 생성/수정 요청
*/
export interface ButtonActionFormData {
action_type: string;
action_name: string;
action_name_eng?: string;
description?: string;
category: string;
default_text?: string;
default_text_eng?: string;
default_icon?: string;
default_color?: string;
default_variant?: string;
confirmation_required: boolean;
confirmation_message?: string;
validation_rules?: unknown;
action_config?: unknown;
sort_order?: number;
is_active: ActiveStatus;
}
// ===== API 응답 타입들 =====
/**
* 버튼 액션 목록 응답
*/
export interface ButtonActionListResponse extends BaseApiResponse<ButtonActionStandard[]> {}
/**
* 데이터플로우 실행 응답
*/
export interface DataflowExecutionResponse extends BaseApiResponse<DataflowExecutionResult> {}
/**
* 트랜잭션 실행 응답
*/
export interface TransactionExecutionResponse extends BaseApiResponse<TransactionExecutionResult> {}
// ===== 유틸리티 타입들 =====
/**
* 롤백 핸들러
*/
export interface RollbackHandler {
actionId: string;
rollbackFn: () => Promise<void>;
}
/**
* 최적화된 실행 결과
*/
export interface OptimizedExecutionResult {
jobId: string;
immediateResult?: unknown;
isBackground?: boolean;
timing?: "before" | "after" | "replace";
}
// ===== 타입 가드 및 유틸리티 함수들 =====
/**
* DataflowCondition이 단일 조건인지 확인
*/
export const isSingleCondition = (condition: DataflowCondition): boolean => {
return condition.type === "condition" && !!condition.field;
};
/**
* DataflowCondition이 그룹 조건인지 확인
*/
export const isGroupCondition = (condition: DataflowCondition): boolean => {
return condition.type === "group" && !!condition.conditions?.length;
};
/**
* DataflowAction이 데이터베이스 액션인지 확인
*/
export const isDatabaseAction = (action: DataflowAction): boolean => {
return action.type === "database" && !!action.tableName;
};
/**
* DataflowAction이 API 액션인지 확인
*/
export const isApiAction = (action: DataflowAction): boolean => {
return action.type === "api" && !!action.endpoint;
};
/**
* 액션 실행 결과가 성공인지 확인
*/
export const isActionSuccess = (result: ActionExecutionResult): boolean => {
return result.status === "success";
};
/**
* 트랜잭션이 완료되었는지 확인 (성공 또는 실패)
*/
export const isTransactionCompleted = (state: TransactionExecutionState): boolean => {
return ["success", "failed", "rolled_back"].includes(state.status);
};