- API 타입 정의 추가 (LoanDashboard, TaxSimulation) - API 엔드포인트 함수 추가 (endpoints.ts) - 모달 데이터 훅 생성 (useCardManagementModals.ts) 관련: docs/plans/card-management-section-plan.md
242 lines
6.7 KiB
TypeScript
242 lines
6.7 KiB
TypeScript
'use server';
|
|
|
|
/**
|
|
* CEO Dashboard API 엔드포인트 함수
|
|
*
|
|
* 카드/가지급금 관리 섹션 (cm1-cm4) 데이터 조회
|
|
*/
|
|
|
|
import { apiClient } from '../index';
|
|
import { isNextRedirectError } from '@/lib/utils/redirect-error';
|
|
import type {
|
|
ApiResponse,
|
|
CardDashboardDetailApiResponse,
|
|
LoanDashboardApiResponse,
|
|
TaxSimulationApiResponse,
|
|
} from './types';
|
|
|
|
// ============================================
|
|
// 에러 핸들링 헬퍼
|
|
// ============================================
|
|
|
|
/**
|
|
* 인증 에러인지 확인
|
|
*/
|
|
function isAuthenticationError(error: unknown): boolean {
|
|
if (error && typeof error === 'object') {
|
|
const err = error as { status?: number; code?: string; message?: string };
|
|
if (err.status === 401) return true;
|
|
if (err.code === 'AUTH_ERROR') return true;
|
|
if (err.message?.includes('회원정보') || err.message?.includes('인증')) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// ============================================
|
|
// 카드 거래 대시보드 API
|
|
// ============================================
|
|
|
|
/**
|
|
* 카드 거래 대시보드 데이터 조회
|
|
* GET /api/v1/card-transactions/dashboard
|
|
*
|
|
* @returns 카드 거래 요약, 월별 추이, 사용자별 분포, 거래 목록
|
|
*/
|
|
export async function fetchCardTransactionDashboard(): Promise<ApiResponse<CardDashboardDetailApiResponse>> {
|
|
try {
|
|
const response = await apiClient.get<ApiResponse<CardDashboardDetailApiResponse>>(
|
|
'/card-transactions/dashboard'
|
|
);
|
|
return response;
|
|
} catch (error) {
|
|
// Next.js redirect 에러는 전파
|
|
if (isNextRedirectError(error)) {
|
|
throw error;
|
|
}
|
|
|
|
console.error('[Dashboard] fetchCardTransactionDashboard error:', error);
|
|
|
|
// 인증 에러인 경우
|
|
if (isAuthenticationError(error)) {
|
|
return {
|
|
success: false,
|
|
message: '인증이 만료되었습니다.',
|
|
data: {
|
|
summary: {
|
|
current_month_total: 0,
|
|
previous_month_total: 0,
|
|
total_count: 0,
|
|
current_month_count: 0,
|
|
},
|
|
monthly_trend: [],
|
|
by_user: [],
|
|
items: [],
|
|
},
|
|
};
|
|
}
|
|
|
|
// 기타 에러
|
|
return {
|
|
success: false,
|
|
message: error instanceof Error ? error.message : 'API 요청 실패',
|
|
data: {
|
|
summary: {
|
|
current_month_total: 0,
|
|
previous_month_total: 0,
|
|
total_count: 0,
|
|
current_month_count: 0,
|
|
},
|
|
monthly_trend: [],
|
|
by_user: [],
|
|
items: [],
|
|
},
|
|
};
|
|
}
|
|
}
|
|
|
|
// ============================================
|
|
// 가지급금 대시보드 API
|
|
// ============================================
|
|
|
|
/**
|
|
* 가지급금 대시보드 데이터 조회
|
|
* GET /api/v1/loans/dashboard
|
|
*
|
|
* @returns 가지급금 요약, 월별 추이, 사용자별 분포, 거래 목록
|
|
*/
|
|
export async function fetchLoanDashboard(): Promise<ApiResponse<LoanDashboardApiResponse>> {
|
|
try {
|
|
const response = await apiClient.get<ApiResponse<LoanDashboardApiResponse>>(
|
|
'/loans/dashboard'
|
|
);
|
|
return response;
|
|
} catch (error) {
|
|
// Next.js redirect 에러는 전파
|
|
if (isNextRedirectError(error)) {
|
|
throw error;
|
|
}
|
|
|
|
console.error('[Dashboard] fetchLoanDashboard error:', error);
|
|
|
|
// 인증 에러인 경우
|
|
if (isAuthenticationError(error)) {
|
|
return {
|
|
success: false,
|
|
message: '인증이 만료되었습니다.',
|
|
data: {
|
|
summary: {
|
|
total_outstanding: 0,
|
|
settled_amount: 0,
|
|
recognized_interest: 0,
|
|
pending_count: 0,
|
|
},
|
|
monthly_trend: [],
|
|
user_distribution: [],
|
|
items: [],
|
|
},
|
|
};
|
|
}
|
|
|
|
// 기타 에러
|
|
return {
|
|
success: false,
|
|
message: error instanceof Error ? error.message : 'API 요청 실패',
|
|
data: {
|
|
summary: {
|
|
total_outstanding: 0,
|
|
settled_amount: 0,
|
|
recognized_interest: 0,
|
|
pending_count: 0,
|
|
},
|
|
monthly_trend: [],
|
|
user_distribution: [],
|
|
items: [],
|
|
},
|
|
};
|
|
}
|
|
}
|
|
|
|
// ============================================
|
|
// 세금 시뮬레이션 API
|
|
// ============================================
|
|
|
|
/**
|
|
* 세금 시뮬레이션 데이터 조회
|
|
* GET /api/v1/loans/tax-simulation?year={year}
|
|
*
|
|
* @param year - 시뮬레이션 연도 (기본값: 현재 연도)
|
|
* @returns 가지급금 요약, 법인세 비교, 소득세 비교
|
|
*/
|
|
export async function fetchTaxSimulation(year?: number): Promise<ApiResponse<TaxSimulationApiResponse>> {
|
|
try {
|
|
const targetYear = year || new Date().getFullYear();
|
|
const response = await apiClient.get<ApiResponse<TaxSimulationApiResponse>>(
|
|
'/loans/tax-simulation',
|
|
{ params: { year: String(targetYear) } }
|
|
);
|
|
return response;
|
|
} catch (error) {
|
|
// Next.js redirect 에러는 전파
|
|
if (isNextRedirectError(error)) {
|
|
throw error;
|
|
}
|
|
|
|
console.error('[Dashboard] fetchTaxSimulation error:', error);
|
|
|
|
const currentYear = year || new Date().getFullYear();
|
|
|
|
// 인증 에러인 경우
|
|
if (isAuthenticationError(error)) {
|
|
return {
|
|
success: false,
|
|
message: '인증이 만료되었습니다.',
|
|
data: {
|
|
year: currentYear,
|
|
loan_summary: {
|
|
total_outstanding: 0,
|
|
recognized_interest: 0,
|
|
interest_rate: 0.046,
|
|
},
|
|
corporate_tax: {
|
|
without_loan: { taxable_income: 0, tax_amount: 0 },
|
|
with_loan: { taxable_income: 0, tax_amount: 0 },
|
|
difference: 0,
|
|
rate_info: '법인세 19% 적용',
|
|
},
|
|
income_tax: {
|
|
without_loan: { taxable_income: 0, tax_rate: '0%', tax_amount: 0 },
|
|
with_loan: { taxable_income: 0, tax_rate: '35%', tax_amount: 0 },
|
|
difference: 0,
|
|
breakdown: { income_tax: 0, local_tax: 0, insurance: 0 },
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
// 기타 에러
|
|
return {
|
|
success: false,
|
|
message: error instanceof Error ? error.message : 'API 요청 실패',
|
|
data: {
|
|
year: currentYear,
|
|
loan_summary: {
|
|
total_outstanding: 0,
|
|
recognized_interest: 0,
|
|
interest_rate: 0.046,
|
|
},
|
|
corporate_tax: {
|
|
without_loan: { taxable_income: 0, tax_amount: 0 },
|
|
with_loan: { taxable_income: 0, tax_amount: 0 },
|
|
difference: 0,
|
|
rate_info: '법인세 19% 적용',
|
|
},
|
|
income_tax: {
|
|
without_loan: { taxable_income: 0, tax_rate: '0%', tax_amount: 0 },
|
|
with_loan: { taxable_income: 0, tax_rate: '35%', tax_amount: 0 },
|
|
difference: 0,
|
|
breakdown: { income_tax: 0, local_tax: 0, insurance: 0 },
|
|
},
|
|
},
|
|
};
|
|
}
|
|
} |