ERP-node/frontend/lib/api/data.ts

273 lines
9.1 KiB
TypeScript
Raw Permalink Normal View History

2025-10-15 17:25:38 +09:00
import { apiClient } from "./client";
/**
* API
*/
export const dataApi = {
/**
*
* @param tableName
* @param params (, )
*/
getTableData: async (
tableName: string,
params?: {
page?: number;
size?: number;
searchTerm?: string;
sortBy?: string;
sortOrder?: "asc" | "desc";
filters?: Record<string, any>;
},
): Promise<{
data: any[];
total: number;
page: number;
size: number;
totalPages: number;
}> => {
// filters를 평탄화하여 쿼리 파라미터로 전달 (백엔드 ...filters 형식에 맞춤)
const { filters, ...restParams } = params || {};
const flattenedParams = {
...restParams,
...(filters || {}), // filters 객체를 평탄화
};
const response = await apiClient.get(`/data/${tableName}`, { params: flattenedParams });
2025-10-15 17:25:38 +09:00
const raw = response.data || {};
const items: any[] = (raw.data ?? raw.items ?? raw.rows ?? []) as any[];
const page = raw.page ?? params?.page ?? 1;
const size = raw.size ?? params?.size ?? items.length;
const total = raw.total ?? items.length;
const totalPages = raw.totalPages ?? Math.max(1, Math.ceil(total / (size || 1)));
return { data: items, total, page, size, totalPages };
},
/**
*
* @param tableName
* @param id ID
* @param enableEntityJoin Entity (기본값: false)
* @param groupByColumns ()
2025-10-15 17:25:38 +09:00
*/
getRecordDetail: async (
tableName: string,
id: string | number,
enableEntityJoin: boolean = false,
groupByColumns: string[] = []
): Promise<{ success: boolean; data?: any; error?: string }> => {
try {
const params: any = {};
if (enableEntityJoin) {
params.enableEntityJoin = true;
}
if (groupByColumns.length > 0) {
params.groupByColumns = JSON.stringify(groupByColumns);
}
console.log("🌐 [dataApi.getRecordDetail] API 호출:", {
tableName,
id,
enableEntityJoin,
groupByColumns,
params,
url: `/data/${tableName}/${id}`,
});
const response = await apiClient.get(`/data/${tableName}/${id}`, { params });
console.log("📥 [dataApi.getRecordDetail] API 응답:", {
success: response.data?.success,
dataType: Array.isArray(response.data?.data) ? "배열" : "객체",
dataCount: Array.isArray(response.data?.data) ? response.data.data.length : 1,
});
return response.data; // { success: true, data: ... } 형식 그대로 반환
} catch (error: any) {
console.error("❌ [dataApi.getRecordDetail] API 오류:", error);
return {
success: false,
error: error.response?.data?.message || error.message || "레코드 조회 실패",
};
}
2025-10-15 17:25:38 +09:00
},
/**
*
* @param leftTable
* @param rightTable
* @param leftColumn
* @param rightColumn ()
* @param leftValue ()
* @param dataFilter
* @param enableEntityJoin Entity
* @param displayColumns (tableName.columnName )
2025-10-15 17:25:38 +09:00
*/
getJoinedData: async (
leftTable: string,
rightTable: string,
leftColumn: string,
rightColumn: string,
leftValue?: any,
dataFilter?: any,
enableEntityJoin?: boolean,
displayColumns?: Array<{ name: string; label?: string }>,
deduplication?: { // 🆕 중복 제거 설정
enabled: boolean;
groupByColumn: string;
keepStrategy: "latest" | "earliest" | "base_price" | "current_date";
sortColumn?: string;
},
2025-10-15 17:25:38 +09:00
): Promise<any[]> => {
const response = await apiClient.get(`/data/join`, {
params: {
leftTable,
rightTable,
leftColumn,
rightColumn,
leftValue,
dataFilter: dataFilter ? JSON.stringify(dataFilter) : undefined,
enableEntityJoin: enableEntityJoin ?? true,
displayColumns: displayColumns ? JSON.stringify(displayColumns) : undefined, // 🆕 표시 컬럼 전달
deduplication: deduplication ? JSON.stringify(deduplication) : undefined, // 🆕 중복 제거 설정 전달
2025-10-15 17:25:38 +09:00
},
});
const raw = response.data || {};
return (raw.data ?? raw.items ?? raw.rows ?? []) as any[];
},
/**
*
* @param tableName
* @param data
*/
createRecord: async (tableName: string, data: Record<string, any>): Promise<any> => {
const response = await apiClient.post(`/data/${tableName}`, data);
return response.data; // success, data, message 포함된 전체 응답 반환
2025-10-15 17:25:38 +09:00
},
/**
*
* @param tableName
* @param id ID
* @param data
*/
updateRecord: async (tableName: string, id: string | number, data: Record<string, any>): Promise<any> => {
const response = await apiClient.put(`/data/${tableName}/${id}`, data);
2025-11-07 16:02:01 +09:00
return response.data; // success, data, message 포함된 전체 응답 반환
2025-10-15 17:25:38 +09:00
},
/**
*
* @param tableName
* @param id ID
2025-10-15 17:25:38 +09:00
*/
deleteRecord: async (tableName: string, id: string | number | Record<string, any>): Promise<any> => {
// 복합키 객체인 경우 POST로 전달
if (typeof id === 'object' && !Array.isArray(id)) {
const response = await apiClient.post(`/data/${tableName}/delete`, id);
return response.data;
}
// 단일 ID인 경우 기존 방식
2025-11-07 16:02:01 +09:00
const response = await apiClient.delete(`/data/${tableName}/${id}`);
return response.data; // success, message 포함된 전체 응답 반환
2025-10-15 17:25:38 +09:00
},
2025-11-20 11:58:43 +09:00
/**
* ( )
* @param tableName
* @param filterConditions (: { customer_id: "CUST-0002", item_id: "SLI-2025-0002" })
*/
deleteGroupRecords: async (
tableName: string,
filterConditions: Record<string, any>
): Promise<{ success: boolean; deleted?: number; message?: string; error?: string }> => {
try {
console.log(`🗑️ [dataApi] 그룹 삭제 요청:`, { tableName, filterConditions });
const response = await apiClient.post(`/data/${tableName}/delete-group`, filterConditions);
console.log(`✅ [dataApi] 그룹 삭제 성공:`, response.data);
return response.data;
} catch (error: any) {
console.error(`❌ [dataApi] 그룹 삭제 실패:`, error);
return {
success: false,
error: error.response?.data?.message || error.message || "그룹 삭제 실패",
};
}
},
/**
*
* @param tableName
* @param id ID
* @param enableEntityJoin Entity (기본값: false)
*/
getRecordDetail: async (
tableName: string,
id: string | number,
enableEntityJoin: boolean = false
): Promise<{ success: boolean; data?: any; error?: string }> => {
try {
const params: any = {};
if (enableEntityJoin) {
params.enableEntityJoin = "true";
}
const response = await apiClient.get(`/data/${tableName}/${id}`, { params });
return response.data; // { success: true, data: ... } 형식 그대로 반환
} catch (error: any) {
return {
success: false,
error: error.response?.data?.message || error.message || "레코드 조회 실패",
};
}
},
/**
* UPSERT
* @param tableName
* @param parentKeys (: { customer_id: "CUST-0002", item_id: "SLI-2025-0002" })
* @param records
*/
upsertGroupedRecords: async (
tableName: string,
parentKeys: Record<string, any>,
records: Array<Record<string, any>>
): Promise<{ success: boolean; inserted?: number; updated?: number; deleted?: number; message?: string; error?: string }> => {
try {
2025-11-20 11:58:43 +09:00
console.log("📡 [dataApi.upsertGroupedRecords] 요청 데이터:", {
tableName,
2025-11-20 11:58:43 +09:00
tableNameType: typeof tableName,
tableNameValue: JSON.stringify(tableName),
parentKeys,
2025-11-20 11:58:43 +09:00
recordsCount: records.length,
});
2025-11-20 11:58:43 +09:00
const requestBody = {
tableName,
parentKeys,
records,
};
console.log("📦 [dataApi.upsertGroupedRecords] 요청 본문 (JSON):", JSON.stringify(requestBody, null, 2));
const response = await apiClient.post('/data/upsert-grouped', requestBody);
return response.data;
} catch (error: any) {
2025-11-20 11:58:43 +09:00
console.error("❌ [dataApi.upsertGroupedRecords] 에러:", {
status: error.response?.status,
statusText: error.response?.statusText,
data: error.response?.data,
message: error.message,
});
return {
success: false,
error: error.response?.data?.message || error.message || "데이터 저장 실패",
};
}
},
2025-10-15 17:25:38 +09:00
};