diff --git a/src/hooks/useCEODashboard.ts b/src/hooks/useCEODashboard.ts index d5ede586..2d9d5dea 100644 --- a/src/hooks/useCEODashboard.ts +++ b/src/hooks/useCEODashboard.ts @@ -23,8 +23,15 @@ import type { WelfareApiResponse, WelfareDetailApiResponse, ExpectedExpenseDashboardDetailApiResponse, + LoanDashboardApiResponse, + TaxSimulationApiResponse, } from '@/lib/api/dashboard/types'; +import { + fetchLoanDashboard, + fetchTaxSimulation, +} from '@/lib/api/dashboard/endpoints'; + import { transformDailyReportResponse, transformReceivableResponse, @@ -226,8 +233,18 @@ export function useCardManagement(fallbackData?: CardManagementData) { setLoading(true); setError(null); - const apiData = await fetchApi('card-transactions/summary'); - const transformed = transformCardManagementResponse(apiData, fallbackData); + // 3개 API 병렬 호출: 카드거래, 가지급금, 세금 시뮬레이션 + const [cardApiData, loanResponse, taxResponse] = await Promise.all([ + fetchApi('card-transactions/summary'), + fetchLoanDashboard(), + fetchTaxSimulation(), + ]); + + // LoanDashboard와 TaxSimulation은 ApiResponse wrapper가 있으므로 data 추출 + const loanData = loanResponse.success ? loanResponse.data : null; + const taxData = taxResponse.success ? taxResponse.data : null; + + const transformed = transformCardManagementResponse(cardApiData, loanData, taxData, fallbackData); setData(transformed); } catch (err) { @@ -1028,8 +1045,21 @@ export function useCEODashboard(options: UseCEODashboardOptions = {}): CEODashbo try { setCardManagementLoading(true); setCardManagementError(null); - const apiData = await fetchApi('card-transactions/summary'); - setCardManagementData(transformCardManagementResponse(apiData, cardManagementFallback)); + + // 3개 API 병렬 호출: 카드거래, 가지급금, 세금 시뮬레이션 + const [cardApiData, loanResponse, taxResponse] = await Promise.all([ + fetchApi('card-transactions/summary'), + fetchLoanDashboard(), + fetchTaxSimulation(), + ]); + + // LoanDashboard와 TaxSimulation은 ApiResponse wrapper가 있으므로 data 추출 + const loanData = loanResponse.success ? loanResponse.data : null; + const taxData = taxResponse.success ? taxResponse.data : null; + + setCardManagementData( + transformCardManagementResponse(cardApiData, loanData, taxData, cardManagementFallback) + ); } catch (err) { setCardManagementError(err instanceof Error ? err.message : '데이터 로딩 실패'); } finally { diff --git a/src/lib/api/dashboard/transformers.ts b/src/lib/api/dashboard/transformers.ts index fb2b5acd..7d000159 100644 --- a/src/lib/api/dashboard/transformers.ts +++ b/src/lib/api/dashboard/transformers.ts @@ -21,6 +21,8 @@ import type { CardDashboardDetailApiResponse, BillDashboardDetailApiResponse, ExpectedExpenseDashboardDetailApiResponse, + LoanDashboardApiResponse, + TaxSimulationApiResponse, } from './types'; import type { @@ -485,43 +487,60 @@ function generateCardManagementCheckPoints(api: CardTransactionApiResponse): Che /** * CardTransaction API 응답 → Frontend 타입 변환 - * 4개 카드 구조 유지: 카드, 가지급금, 법인세 예상 가중, 대표자 종합세 예상 가중 - * 주의: 가지급금, 법인세, 종합세 관련 데이터는 별도 API 필요 (현재 목업 유지) + * 4개 카드 구조: + * - cm1: 카드 사용액 (CardTransaction API) + * - cm2: 가지급금 (LoanDashboard API) + * - cm3: 법인세 예상 가중 (TaxSimulation API - corporate_tax.difference) + * - cm4: 대표자 종합세 예상 가중 (TaxSimulation API - income_tax.difference) */ export function transformCardManagementResponse( summaryApi: CardTransactionApiResponse, + loanApi?: LoanDashboardApiResponse | null, + taxApi?: TaxSimulationApiResponse | null, fallbackData?: CardManagementData ): CardManagementData { const changeRate = calculateChangeRate(summaryApi.current_month_total, summaryApi.previous_month_total); + // cm2: 가지급금 금액 (LoanDashboard API 또는 fallback) + const loanAmount = loanApi?.summary?.total_outstanding ?? fallbackData?.cards[1]?.amount ?? 0; + + // cm3: 법인세 예상 가중 (TaxSimulation API 또는 fallback) + const corporateTaxDifference = taxApi?.corporate_tax?.difference ?? fallbackData?.cards[2]?.amount ?? 0; + + // cm4: 대표자 종합세 예상 가중 (TaxSimulation API 또는 fallback) + const incomeTaxDifference = taxApi?.income_tax?.difference ?? fallbackData?.cards[3]?.amount ?? 0; + + // 가지급금 경고 배너 표시 여부 결정 (가지급금 잔액 > 0이면 표시) + const hasLoanWarning = loanAmount > 0; + return { - // 가지급금 관련 경고 배너 (별도 API 필요) - warningBanner: fallbackData?.warningBanner, + // 가지급금 관련 경고 배너 (가지급금 있을 때만 표시) + warningBanner: hasLoanWarning ? fallbackData?.warningBanner : undefined, cards: [ - // cm1: 카드 사용액 (API 데이터) + // cm1: 카드 사용액 (CardTransaction API) { id: 'cm1', label: '카드', amount: summaryApi.current_month_total, previousLabel: `전월 대비 ${changeRate > 0 ? '+' : ''}${changeRate.toFixed(1)}%`, }, - // cm2: 가지급금 (별도 API 필요 - 현재 fallback) - fallbackData?.cards[1] ?? { + // cm2: 가지급금 (LoanDashboard API) + { id: 'cm2', label: '가지급금', - amount: 0, + amount: loanAmount, }, - // cm3: 법인세 예상 가중 (별도 API 필요 - 현재 fallback) - fallbackData?.cards[2] ?? { + // cm3: 법인세 예상 가중 (TaxSimulation API) + { id: 'cm3', label: '법인세 예상 가중', - amount: 0, + amount: corporateTaxDifference, }, - // cm4: 대표자 종합세 예상 가중 (별도 API 필요 - 현재 fallback) - fallbackData?.cards[3] ?? { + // cm4: 대표자 종합세 예상 가중 (TaxSimulation API) + { id: 'cm4', label: '대표자 종합세 예상 가중', - amount: 0, + amount: incomeTaxDifference, }, ], checkPoints: generateCardManagementCheckPoints(summaryApi),