fix: 품목관리 API 응답 파싱 및 필드명 수정
- ApiItem 인터페이스: code → item_code 변경 (API 응답 구조 반영) - transformItem: item_code 필드 사용하도록 수정 - transformItemToApi: item_type → product_type으로 변경 (API 요청 필드명) - getItemList: Laravel 페이지네이션 응답 구조 처리 개선 - getItem: API 응답 구조(success, message, data) 처리 - getCategoryOptions: 페이지네이션 응답 파싱 수정 - createItem: 응답에서 ID 추출 로직 개선 - 디버깅용 console.log 추가
This commit is contained in:
@@ -88,7 +88,7 @@ function transformOrderItems(options: Record<string, unknown> | null | undefined
|
||||
*/
|
||||
interface ApiItem {
|
||||
id: number;
|
||||
code: string;
|
||||
item_code: string; // API가 'code' 대신 'item_code'로 반환 (ApiResponse 충돌 방지)
|
||||
name: string;
|
||||
item_type: string | null;
|
||||
category_id: number | null;
|
||||
@@ -104,7 +104,7 @@ interface ApiItem {
|
||||
function transformItem(apiItem: ApiItem): Item {
|
||||
return {
|
||||
id: String(apiItem.id),
|
||||
itemNumber: apiItem.code || '',
|
||||
itemNumber: apiItem.item_code || '',
|
||||
itemName: apiItem.name || '',
|
||||
itemType: transformItemType(apiItem.item_type),
|
||||
categoryId: apiItem.category_id ? String(apiItem.category_id) : '',
|
||||
@@ -136,7 +136,7 @@ function transformItemToApi(data: ItemFormData): Record<string, unknown> {
|
||||
return {
|
||||
code: data.itemNumber,
|
||||
name: data.itemName,
|
||||
item_type: transformToBackendItemType(data.itemType),
|
||||
product_type: transformToBackendItemType(data.itemType),
|
||||
category_id: data.categoryId ? parseInt(data.categoryId, 10) : null,
|
||||
unit: data.unit,
|
||||
is_active: data.status === '사용' || data.status === '승인',
|
||||
@@ -161,6 +161,7 @@ function transformItemToApi(data: ItemFormData): Record<string, unknown> {
|
||||
export async function getItemList(
|
||||
params: ItemListParams = {}
|
||||
): Promise<{ success: boolean; data?: ItemListResponse; error?: string }> {
|
||||
console.log('📥 [getItemList] 호출됨, params:', params);
|
||||
try {
|
||||
const queryParams: Record<string, string> = {};
|
||||
|
||||
@@ -186,21 +187,59 @@ export async function getItemList(
|
||||
queryParams.active = params.status === '사용' || params.status === '승인' ? '1' : '0';
|
||||
}
|
||||
|
||||
console.log('📤 [getItemList] API 호출:', queryParams);
|
||||
const response = await apiClient.get<{
|
||||
data: ApiItem[];
|
||||
meta?: { total: number; current_page: number; per_page: number };
|
||||
total?: number;
|
||||
current_page?: number;
|
||||
per_page?: number;
|
||||
last_page?: number;
|
||||
per_page?: number;
|
||||
}>('/items', { params: queryParams });
|
||||
console.log('📥 [getItemList] API 응답:', JSON.stringify(response).slice(0, 500));
|
||||
|
||||
// API 응답 구조 처리 (data 배열 또는 페이지네이션 객체)
|
||||
const items = Array.isArray(response.data) ? response.data : (response.data as unknown as ApiItem[]);
|
||||
const meta = response.meta || {
|
||||
total: response.total || items.length,
|
||||
current_page: response.current_page || params.page || 1,
|
||||
per_page: response.per_page || params.size || 20,
|
||||
};
|
||||
// API 응답 구조 처리
|
||||
// Laravel 페이지네이션 응답: { current_page, data: [...], last_page, per_page, total, ... }
|
||||
// data 필드가 배열인 경우와 페이지네이션 객체인 경우 모두 처리
|
||||
let items: ApiItem[];
|
||||
let meta: { total: number; current_page: number; per_page: number };
|
||||
|
||||
if (Array.isArray(response.data)) {
|
||||
// response.data가 직접 배열인 경우
|
||||
items = response.data;
|
||||
meta = response.meta || {
|
||||
total: response.total || items.length,
|
||||
current_page: response.current_page || params.page || 1,
|
||||
per_page: response.per_page || params.size || 20,
|
||||
};
|
||||
} else if (response.data && Array.isArray((response as unknown as { data: { data: ApiItem[] } }).data.data)) {
|
||||
// response가 { data: { current_page, data: [...], ... } } 형태인 경우 (Laravel 페이지네이션)
|
||||
const paginatedResponse = response as unknown as {
|
||||
data: { data: ApiItem[]; current_page: number; total: number; per_page: number };
|
||||
};
|
||||
items = paginatedResponse.data.data;
|
||||
meta = {
|
||||
total: paginatedResponse.data.total || items.length,
|
||||
current_page: paginatedResponse.data.current_page || params.page || 1,
|
||||
per_page: paginatedResponse.data.per_page || params.size || 20,
|
||||
};
|
||||
} else if (response.current_page !== undefined && Array.isArray((response as unknown as { data: ApiItem[] }).data)) {
|
||||
// response가 { current_page, data: [...], total, per_page } 형태인 경우
|
||||
items = (response as unknown as { data: ApiItem[] }).data;
|
||||
meta = {
|
||||
total: response.total || items.length,
|
||||
current_page: response.current_page || params.page || 1,
|
||||
per_page: response.per_page || params.size || 20,
|
||||
};
|
||||
} else {
|
||||
// 예상치 못한 응답 구조
|
||||
console.error('❌ [getItemList] 예상치 못한 응답 구조:', response);
|
||||
items = [];
|
||||
meta = { total: 0, current_page: 1, per_page: 20 };
|
||||
}
|
||||
|
||||
console.log('📊 [getItemList] 파싱된 items 수:', items.length, ', meta:', meta);
|
||||
|
||||
// Frontend 필터링 (Backend에서 지원하지 않는 필터)
|
||||
let transformedItems = items.map(transformItem);
|
||||
@@ -248,7 +287,7 @@ export async function getItemList(
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('품목 목록 조회 오류:', error);
|
||||
console.error('❌ [getItemList] 오류:', error);
|
||||
return { success: false, error: '품목 목록을 불러오는데 실패했습니다.' };
|
||||
}
|
||||
}
|
||||
@@ -318,10 +357,23 @@ export async function getCategoryOptions(): Promise<{
|
||||
}> {
|
||||
try {
|
||||
const response = await apiClient.get<{
|
||||
data: { id: number; name: string }[];
|
||||
success: boolean;
|
||||
message: string;
|
||||
data: {
|
||||
current_page: number;
|
||||
data: { id: number; name: string }[];
|
||||
total: number;
|
||||
};
|
||||
}>('/categories', { params: { size: 100 } });
|
||||
|
||||
const categories = response.data.map((cat) => ({
|
||||
// API 응답 구조: { success, message, data: { current_page, data: [...], ... } }
|
||||
const categoryData = response.data?.data;
|
||||
if (!Array.isArray(categoryData)) {
|
||||
console.error('카테고리 응답 구조 오류:', response);
|
||||
return { success: true, data: [] };
|
||||
}
|
||||
|
||||
const categories = categoryData.map((cat) => ({
|
||||
id: String(cat.id),
|
||||
name: cat.name,
|
||||
}));
|
||||
@@ -343,9 +395,17 @@ export async function getItem(id: string): Promise<{
|
||||
error?: string;
|
||||
}> {
|
||||
try {
|
||||
const response = await apiClient.get<ApiItem>(`/items/${id}`);
|
||||
const response = await apiClient.get<{ success: boolean; message: string; data: ApiItem }>(`/items/${id}`);
|
||||
console.log('📥 [getItem] API 응답:', JSON.stringify(response).slice(0, 300));
|
||||
|
||||
return { success: true, data: transformItemDetail(response) };
|
||||
// API 응답 구조: { success, message, data: {...item...} }
|
||||
const item = response.data;
|
||||
if (!item) {
|
||||
console.error('❌ [getItem] 응답에 data가 없음:', response);
|
||||
return { success: false, error: '품목 정보를 찾을 수 없습니다.' };
|
||||
}
|
||||
|
||||
return { success: true, data: transformItemDetail(item) };
|
||||
} catch (error) {
|
||||
console.error('품목 상세 조회 오류:', error);
|
||||
return { success: false, error: '품목 정보를 불러오는데 실패했습니다.' };
|
||||
@@ -362,12 +422,21 @@ export async function createItem(data: ItemFormData): Promise<{
|
||||
error?: string;
|
||||
}> {
|
||||
try {
|
||||
console.log('📤 [createItem] 입력 데이터:', data);
|
||||
const apiData = transformItemToApi(data);
|
||||
const response = await apiClient.post<{ id: number }>('/items', apiData);
|
||||
console.log('📤 [createItem] 변환된 API 데이터:', apiData);
|
||||
const response = await apiClient.post<{ success: boolean; data: { id: number }; id?: number }>('/items', apiData);
|
||||
console.log('📥 [createItem] API 응답:', response);
|
||||
|
||||
return { success: true, data: { id: String(response.id) } };
|
||||
// API 응답 구조: { success, message, data: { id } } 또는 { id }
|
||||
const itemId = response.data?.id ?? response.id;
|
||||
if (!itemId) {
|
||||
console.error('❌ [createItem] 응답에서 ID를 찾을 수 없음:', response);
|
||||
return { success: false, error: '품목 등록 후 ID를 가져오지 못했습니다.' };
|
||||
}
|
||||
return { success: true, data: { id: String(itemId) } };
|
||||
} catch (error) {
|
||||
console.error('품목 등록 오류:', error);
|
||||
console.error('❌ [createItem] 품목 등록 오류:', error);
|
||||
return { success: false, error: '품목 등록에 실패했습니다.' };
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user