Files
sam-react-prod/src/lib/api/dashboard/transformers/expense.ts

232 lines
8.0 KiB
TypeScript
Raw Normal View History

/**
* (MonthlyExpense) + / (CardManagement)
*/
import type {
ExpectedExpenseApiResponse,
CardTransactionApiResponse,
LoanDashboardApiResponse,
TaxSimulationApiResponse,
} from '../types';
import type {
MonthlyExpenseData,
CardManagementData,
CheckPoint,
CheckPointType,
} from '@/components/business/CEODashboard/types';
import { formatAmount } from './common';
// ============================================
// 월 예상 지출 (MonthlyExpense)
// ============================================
/**
* CheckPoints
*/
function generateMonthlyExpenseCheckPoints(api: ExpectedExpenseApiResponse): CheckPoint[] {
const checkPoints: CheckPoint[] = [];
// 총 예상 지출
checkPoints.push({
id: 'me-total',
type: 'info' as CheckPointType,
message: `이번 달 예상 지출은 ${formatAmount(api.total_amount)}입니다.`,
highlights: [
{ text: formatAmount(api.total_amount), color: 'blue' as const },
],
});
return checkPoints;
}
/**
* ExpectedExpense API Frontend
* 주의: 실제 API는 (// )
* by_transaction_type에서
*/
export function transformMonthlyExpenseResponse(api: ExpectedExpenseApiResponse): MonthlyExpenseData {
// transaction_type별 금액 추출
const purchaseTotal = api.by_transaction_type['purchase']?.total ?? 0;
const cardTotal = api.by_transaction_type['card']?.total ?? 0;
const billTotal = api.by_transaction_type['bill']?.total ?? 0;
return {
cards: [
{
id: 'me1',
label: '매입',
amount: purchaseTotal,
},
{
id: 'me2',
label: '카드',
amount: cardTotal,
},
{
id: 'me3',
label: '발행어음',
amount: billTotal,
},
{
id: 'me4',
label: '총 예상 지출 합계',
amount: api.total_amount,
},
],
checkPoints: generateMonthlyExpenseCheckPoints(api),
};
}
// ============================================
// 카드/가지급금 (CardManagement) — D1.7 5장 카드 구조
// ============================================
/**
* / CheckPoints (D1.7)
*
* CP1: 법인카드
* CP2: 인정이자
* CP3: 접대비
* CP4: 주말 ( )
*/
function generateCardManagementCheckPoints(
loanApi?: LoanDashboardApiResponse | null,
taxApi?: TaxSimulationApiResponse | null,
cardApi?: CardTransactionApiResponse | null,
): CheckPoint[] {
const checkPoints: CheckPoint[] = [];
const totalOutstanding = loanApi?.summary?.total_outstanding ?? 0;
const interestRate = taxApi?.loan_summary?.interest_rate ?? 4.6;
const recognizedInterest = taxApi?.loan_summary?.recognized_interest ?? 0;
// CP1: 법인카드 사용 중 가지급금 전환 경고
if (totalOutstanding > 0) {
checkPoints.push({
id: 'cm-cp1',
type: 'success' as CheckPointType,
message: `법인카드 사용 중 ${formatAmount(totalOutstanding)}이 가지급금으로 전환되었습니다. 연 ${interestRate}% 인정이자가 발생합니다.`,
highlights: [
{ text: formatAmount(totalOutstanding), color: 'red' as const },
{ text: '가지급금', color: 'red' as const },
{ text: `${interestRate}% 인정이자`, color: 'red' as const },
],
});
}
// CP2: 인정이자 발생 현황
if (totalOutstanding > 0 && recognizedInterest > 0) {
checkPoints.push({
id: 'cm-cp2',
type: 'success' as CheckPointType,
message: `현재 가지급금 ${formatAmount(totalOutstanding)} × ${interestRate}% = 연간 약 ${formatAmount(recognizedInterest)}의 인정이자가 발생 중입니다.`,
highlights: [
{ text: `연간 약 ${formatAmount(recognizedInterest)}의 인정이자`, color: 'red' as const },
],
});
}
// CP3: 접대비 불인정 항목 감지
const entertainmentCount = loanApi?.category_breakdown?.entertainment?.unverified_count ?? 0;
if (entertainmentCount > 0) {
checkPoints.push({
id: 'cm-cp3',
type: 'success' as CheckPointType,
message: '상품권/귀금속 등 접대비 불인정 항목 결제 감지. 가지급금 처리 예정입니다.',
highlights: [
{ text: '불인정 항목 결제 감지', color: 'red' as const },
],
});
}
// CP4: 주말 카드 사용 감지 (향후 card-transactions API 확장 시)
// 현재는 cardApi 데이터에서 주말 사용 정보가 없으므로 placeholder
if (cardApi && cardApi.current_month_total > 0) {
// 향후 weekend_amount 필드 추가 시 활성화
}
return checkPoints;
}
/**
* CardTransaction API Frontend
* D1.7 5 :
* - cm1: 카드 (loans category_breakdown.card)
* - cm2: 경조사 (loans category_breakdown.congratulatory)
* - cm3: 상품권 (loans category_breakdown.gift_certificate)
* - cm4: 접대비 (loans category_breakdown.entertainment)
* - cm_total: (loans summary.total_outstanding)
*/
export function transformCardManagementResponse(
summaryApi: CardTransactionApiResponse,
loanApi?: LoanDashboardApiResponse | null,
taxApi?: TaxSimulationApiResponse | null,
fallbackData?: CardManagementData
): CardManagementData {
const breakdown = loanApi?.category_breakdown;
const totalOutstanding = loanApi?.summary?.total_outstanding ?? 0;
// 카테고리별 금액 추출
const cardAmount = breakdown?.card?.outstanding_amount ?? fallbackData?.cards[0]?.amount ?? 0;
const congratulatoryAmount = breakdown?.congratulatory?.outstanding_amount ?? fallbackData?.cards[1]?.amount ?? 0;
const giftCertificateAmount = breakdown?.gift_certificate?.outstanding_amount ?? fallbackData?.cards[2]?.amount ?? 0;
const entertainmentAmount = breakdown?.entertainment?.outstanding_amount ?? fallbackData?.cards[3]?.amount ?? 0;
// 카테고리별 미증빙/미정리 건수
const cardUnverified = breakdown?.card?.unverified_count ?? 0;
const congratulatoryUnverified = breakdown?.congratulatory?.unverified_count ?? 0;
const giftCertificateUnverified = breakdown?.gift_certificate?.unverified_count ?? 0;
const entertainmentUnverified = breakdown?.entertainment?.unverified_count ?? 0;
// 총 합계 (API summary 또는 카테고리 합산)
const totalAmount = totalOutstanding > 0
? totalOutstanding
: cardAmount + congratulatoryAmount + giftCertificateAmount + entertainmentAmount;
// 가지급금 경고 배너 표시 여부 (가지급금 잔액 > 0이면 표시)
const hasLoanWarning = totalAmount > 0;
return {
warningBanner: hasLoanWarning
? (fallbackData?.warningBanner ?? '가지급금 인정이자 4.6%, 법인세 및 연말정산 시 대표자 종합세 가중 주의')
: undefined,
cards: [
// cm1: 카드
{
id: 'cm1',
label: '카드',
amount: cardAmount,
previousLabel: cardUnverified > 0 ? `미정리 ${cardUnverified}` : undefined,
},
// cm2: 경조사
{
id: 'cm2',
label: '경조사',
amount: congratulatoryAmount,
previousLabel: congratulatoryUnverified > 0 ? `미증빙 ${congratulatoryUnverified}` : undefined,
},
// cm3: 상품권
{
id: 'cm3',
label: '상품권',
amount: giftCertificateAmount,
previousLabel: giftCertificateUnverified > 0 ? `미증빙 ${giftCertificateUnverified}` : undefined,
},
// cm4: 접대비
{
id: 'cm4',
label: '접대비',
amount: entertainmentAmount,
previousLabel: entertainmentUnverified > 0 ? `미증빙 ${entertainmentUnverified}` : undefined,
},
// cm_total: 총 가지급금 합계
{
id: 'cm_total',
label: '총 가지급금 합계',
amount: totalAmount,
},
],
checkPoints: generateCardManagementCheckPoints(loanApi, taxApi, summaryApi),
};
}