2025-09-24 10:04:25 +09:00
|
|
|
// 수집 관리 API 클라이언트
|
|
|
|
|
// 작성일: 2024-12-23
|
|
|
|
|
|
|
|
|
|
import { apiClient } from "./client";
|
|
|
|
|
|
|
|
|
|
export interface DataCollectionConfig {
|
|
|
|
|
id?: number;
|
|
|
|
|
config_name: string;
|
|
|
|
|
description?: string;
|
|
|
|
|
source_connection_id: number;
|
|
|
|
|
source_table: string;
|
|
|
|
|
target_table?: string;
|
2026-03-10 18:30:18 +09:00
|
|
|
collection_type: "full" | "incremental" | "delta";
|
2025-09-24 10:04:25 +09:00
|
|
|
schedule_cron?: string;
|
|
|
|
|
is_active: string;
|
|
|
|
|
last_collected_at?: Date;
|
|
|
|
|
collection_options?: Record<string, any>;
|
|
|
|
|
created_date?: Date;
|
|
|
|
|
created_by?: string;
|
|
|
|
|
updated_date?: Date;
|
|
|
|
|
updated_by?: string;
|
|
|
|
|
company_code: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface CollectionFilter {
|
|
|
|
|
config_name?: string;
|
|
|
|
|
source_connection_id?: number;
|
|
|
|
|
collection_type?: string;
|
|
|
|
|
is_active?: string;
|
|
|
|
|
company_code?: string;
|
|
|
|
|
search?: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface CollectionJob {
|
|
|
|
|
id?: number;
|
|
|
|
|
config_id: number;
|
2026-03-10 18:30:18 +09:00
|
|
|
job_status: "pending" | "running" | "completed" | "failed";
|
2025-09-24 10:04:25 +09:00
|
|
|
started_at?: Date;
|
|
|
|
|
completed_at?: Date;
|
|
|
|
|
records_processed?: number;
|
|
|
|
|
error_message?: string;
|
|
|
|
|
job_details?: Record<string, any>;
|
|
|
|
|
created_date?: Date;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface CollectionHistory {
|
|
|
|
|
id?: number;
|
|
|
|
|
config_id: number;
|
|
|
|
|
collection_date: Date;
|
|
|
|
|
records_collected: number;
|
|
|
|
|
execution_time_ms: number;
|
2026-03-10 18:30:18 +09:00
|
|
|
status: "success" | "partial" | "failed";
|
2025-09-24 10:04:25 +09:00
|
|
|
error_details?: string;
|
|
|
|
|
created_date?: Date;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface ApiResponse<T> {
|
|
|
|
|
success: boolean;
|
|
|
|
|
data?: T;
|
|
|
|
|
message?: string;
|
|
|
|
|
error?: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export class CollectionAPI {
|
|
|
|
|
private static readonly BASE_PATH = "/collections";
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 수집 설정 목록 조회
|
|
|
|
|
*/
|
|
|
|
|
static async getCollectionConfigs(filter: CollectionFilter = {}): Promise<DataCollectionConfig[]> {
|
|
|
|
|
try {
|
|
|
|
|
const params = new URLSearchParams();
|
|
|
|
|
|
|
|
|
|
if (filter.config_name) params.append("config_name", filter.config_name);
|
|
|
|
|
if (filter.source_connection_id) params.append("source_connection_id", filter.source_connection_id.toString());
|
|
|
|
|
if (filter.collection_type) params.append("collection_type", filter.collection_type);
|
|
|
|
|
if (filter.is_active) params.append("is_active", filter.is_active);
|
|
|
|
|
if (filter.company_code) params.append("company_code", filter.company_code);
|
|
|
|
|
if (filter.search) params.append("search", filter.search);
|
|
|
|
|
|
|
|
|
|
const response = await apiClient.get<ApiResponse<DataCollectionConfig[]>>(
|
2026-03-10 18:30:18 +09:00
|
|
|
`${this.BASE_PATH}?${params.toString()}`,
|
2025-09-24 10:04:25 +09:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (!response.data.success) {
|
|
|
|
|
throw new Error(response.data.message || "수집 설정 목록 조회에 실패했습니다.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return response.data.data || [];
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("수집 설정 목록 조회 오류:", error);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 수집 설정 상세 조회
|
|
|
|
|
*/
|
|
|
|
|
static async getCollectionConfigById(id: number): Promise<DataCollectionConfig> {
|
|
|
|
|
try {
|
|
|
|
|
const response = await apiClient.get<ApiResponse<DataCollectionConfig>>(`${this.BASE_PATH}/${id}`);
|
|
|
|
|
|
|
|
|
|
if (!response.data.success) {
|
|
|
|
|
throw new Error(response.data.message || "수집 설정 조회에 실패했습니다.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!response.data.data) {
|
|
|
|
|
throw new Error("수집 설정을 찾을 수 없습니다.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return response.data.data;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("수집 설정 조회 오류:", error);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 수집 설정 생성
|
|
|
|
|
*/
|
|
|
|
|
static async createCollectionConfig(data: DataCollectionConfig): Promise<DataCollectionConfig> {
|
|
|
|
|
try {
|
|
|
|
|
const response = await apiClient.post<ApiResponse<DataCollectionConfig>>(this.BASE_PATH, data);
|
|
|
|
|
|
|
|
|
|
if (!response.data.success) {
|
|
|
|
|
throw new Error(response.data.message || "수집 설정 생성에 실패했습니다.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!response.data.data) {
|
|
|
|
|
throw new Error("생성된 수집 설정 정보를 받을 수 없습니다.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return response.data.data;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("수집 설정 생성 오류:", error);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 수집 설정 수정
|
|
|
|
|
*/
|
|
|
|
|
static async updateCollectionConfig(id: number, data: Partial<DataCollectionConfig>): Promise<DataCollectionConfig> {
|
|
|
|
|
try {
|
|
|
|
|
const response = await apiClient.put<ApiResponse<DataCollectionConfig>>(`${this.BASE_PATH}/${id}`, data);
|
|
|
|
|
|
|
|
|
|
if (!response.data.success) {
|
|
|
|
|
throw new Error(response.data.message || "수집 설정 수정에 실패했습니다.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!response.data.data) {
|
|
|
|
|
throw new Error("수정된 수집 설정 정보를 받을 수 없습니다.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return response.data.data;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("수집 설정 수정 오류:", error);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 수집 설정 삭제
|
|
|
|
|
*/
|
|
|
|
|
static async deleteCollectionConfig(id: number): Promise<void> {
|
|
|
|
|
try {
|
|
|
|
|
const response = await apiClient.delete<ApiResponse<null>>(`${this.BASE_PATH}/${id}`);
|
|
|
|
|
|
|
|
|
|
if (!response.data.success) {
|
|
|
|
|
throw new Error(response.data.message || "수집 설정 삭제에 실패했습니다.");
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("수집 설정 삭제 오류:", error);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 수집 작업 실행
|
|
|
|
|
*/
|
|
|
|
|
static async executeCollection(id: number): Promise<CollectionJob> {
|
|
|
|
|
try {
|
|
|
|
|
const response = await apiClient.post<ApiResponse<CollectionJob>>(`${this.BASE_PATH}/${id}/execute`);
|
|
|
|
|
|
|
|
|
|
if (!response.data.success) {
|
|
|
|
|
throw new Error(response.data.message || "수집 작업 실행에 실패했습니다.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!response.data.data) {
|
|
|
|
|
throw new Error("수집 작업 정보를 받을 수 없습니다.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return response.data.data;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("수집 작업 실행 오류:", error);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 수집 작업 목록 조회
|
|
|
|
|
*/
|
|
|
|
|
static async getCollectionJobs(configId?: number): Promise<CollectionJob[]> {
|
|
|
|
|
try {
|
|
|
|
|
const params = new URLSearchParams();
|
|
|
|
|
if (configId) params.append("config_id", configId.toString());
|
|
|
|
|
|
|
|
|
|
const response = await apiClient.get<ApiResponse<CollectionJob[]>>(
|
2026-03-10 18:30:18 +09:00
|
|
|
`${this.BASE_PATH}/jobs/list?${params.toString()}`,
|
2025-09-24 10:04:25 +09:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (!response.data.success) {
|
|
|
|
|
throw new Error(response.data.message || "수집 작업 목록 조회에 실패했습니다.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return response.data.data || [];
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("수집 작업 목록 조회 오류:", error);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 수집 이력 조회
|
|
|
|
|
*/
|
|
|
|
|
static async getCollectionHistory(configId: number): Promise<CollectionHistory[]> {
|
|
|
|
|
try {
|
2026-03-10 18:30:18 +09:00
|
|
|
const response = await apiClient.get<ApiResponse<CollectionHistory[]>>(`${this.BASE_PATH}/${configId}/history`);
|
2025-09-24 10:04:25 +09:00
|
|
|
|
|
|
|
|
if (!response.data.success) {
|
|
|
|
|
throw new Error(response.data.message || "수집 이력 조회에 실패했습니다.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return response.data.data || [];
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("수집 이력 조회 오류:", error);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 수집 타입 옵션 조회
|
|
|
|
|
*/
|
|
|
|
|
static getCollectionTypeOptions() {
|
|
|
|
|
return [
|
2026-03-10 18:30:18 +09:00
|
|
|
{ value: "full", label: "전체 수집" },
|
|
|
|
|
{ value: "incremental", label: "증분 수집" },
|
|
|
|
|
{ value: "delta", label: "변경분 수집" },
|
2025-09-24 10:04:25 +09:00
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 작업 상태 옵션 조회
|
|
|
|
|
*/
|
|
|
|
|
static getJobStatusOptions() {
|
|
|
|
|
return [
|
2026-03-10 18:30:18 +09:00
|
|
|
{ value: "pending", label: "대기 중" },
|
|
|
|
|
{ value: "running", label: "실행 중" },
|
|
|
|
|
{ value: "completed", label: "완료" },
|
|
|
|
|
{ value: "failed", label: "실패" },
|
2025-09-24 10:04:25 +09:00
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
}
|