diff --git a/src/views/account/AccountDashboardView.vue b/src/views/account/AccountDashboardView.vue index d03c308..f6d62b4 100644 --- a/src/views/account/AccountDashboardView.vue +++ b/src/views/account/AccountDashboardView.vue @@ -26,6 +26,8 @@ const categoryList = ref([]) // 분류 목록(대/소분류 매핑용) const trendData = ref([]) // [{month, netWorth}] const aiBullets = ref([]) // AI 재무 코멘트(현황 관찰) const aiTips = ref([]) // AI 절약 가이드(실행 제안) +const aiForecast = ref(null) // AI 월말 예상 지출(일회성 큰 지출 제외 추정) +const aiForecastNote = ref('') // 예상 지출 근거 문장 const aiLoading = ref(false) const periodLabel = computed(() => `${year.value}년 ${String(month.value).padStart(2, '0')}월`) @@ -65,16 +67,8 @@ const expenseDelta = computed(() => { return { prev, diff, pct } }) -/* ===== 이번달 예상 지출 (실제 지출 추세로 월말 추정, run-rate) ===== - 경과일까지 실제 지출을 일평균으로 환산해 그 달 총일수로 추정. 이번 달에만 표시. */ -const expenseForecast = computed(() => { - const isCurrent = year.value === now.getFullYear() && month.value === now.getMonth() + 1 - if (!isCurrent) return null // 지난/미래 달은 추정 불필요(이미 확정 또는 데이터 없음) - const totalDays = daysInMonth(year.value, month.value) - const elapsed = now.getDate() - const projected = elapsed > 0 ? Math.round((monthExpense.value / elapsed) * totalDays) : monthExpense.value - return { projected, elapsed, totalDays } -}) +/* 월말 예상 지출은 단순 선형(run-rate) 대신 AI가 추정한다(aiForecast). + 일회성 큰 지출(노트북 등)을 일평균에서 제외해 현실적인 값을 준다. loadAiComment 참고. */ /* ===== 막대 차트 (기간별 예산 대비 지출) ===== */ const bars = computed(() => { @@ -280,7 +274,10 @@ async function loadAiComment() { aiLoading.value = true aiBullets.value = [] aiTips.value = [] + aiForecast.value = null + aiForecastNote.value = '' try { + const isCurrent = year.value === now.getFullYear() && month.value === now.getMonth() + 1 const res = await accountApi.aiComment({ year: year.value, month: month.value, @@ -289,13 +286,19 @@ async function loadAiComment() { prevExpense: prevMonthExpense.value, budget: budgetTotal.value, spent: spentTotal.value, + elapsedDays: isCurrent ? now.getDate() : 0, + totalDays: daysInMonth(year.value, month.value), categories: (catData.value || []).slice(0, 8).map((c) => ({ category: c.category, total: c.total })), }) aiBullets.value = res?.bullets || [] aiTips.value = res?.tips || [] + aiForecast.value = res?.forecast || null + aiForecastNote.value = res?.forecastNote || '' } catch { aiBullets.value = [] aiTips.value = [] + aiForecast.value = null + aiForecastNote.value = '' } finally { aiLoading.value = false } @@ -417,17 +420,15 @@ onMounted(async () => { {{ expenseDelta.diff >= 0 ? '+' : '' }}{{ won(expenseDelta.diff) }} ({{ expenseDelta.pct >= 0 ? '+' : '' }}{{ expenseDelta.pct }}%) -
- 최근 추세 기준({{ expenseForecast.elapsed }}/{{ expenseForecast.totalDays }}일 · 현재 {{ won(monthExpense) }}), 예산 대비 {{ Math.round((expenseForecast.projected / budgetTotal) * 100) }}% -
+{{ aiForecastNote }}