Fix: Display correct expense amount in monthly budget

The monthly budget and spending were not displaying the correct expense amount after adding an expense. This commit fixes the issue.
This commit is contained in:
gpt-engineer-app[bot]
2025-04-05 05:57:30 +00:00
parent 03e9671ec6
commit f8948e1221
5 changed files with 468 additions and 168 deletions

View File

@@ -1,72 +1,121 @@
import { useEffect } from 'react';
import { BudgetData, Transaction } from '../types';
import { calculateSpentAmounts, safelyLoadBudgetData } from '../budgetUtils';
import { saveBudgetDataToStorage } from '../storage';
import { Transaction, BudgetData } from '../types';
import { calculateSpentAmounts } from '../utils/spendingCalculation';
/**
* 예산 데이터 관련 이벤트를 처리하는 훅
*/
export const useBudgetDataEvents = (
isInitialized: boolean,
transactions: Transaction[],
setBudgetData: (data: BudgetData) => void,
setLastUpdateTime: (time: number) => void
setBudgetData: React.Dispatch<React.SetStateAction<BudgetData>>,
setLastUpdateTime: React.Dispatch<React.SetStateAction<number>>
) => {
// budgetDataUpdated 이벤트 리스너 설정
// 트랜잭션 데이터가 변경될 때마다 예산 데이터 업데이트
useEffect(() => {
const handleBudgetUpdate = () => {
console.log('예산 데이터 업데이트 이벤트 감지');
if (!isInitialized || transactions.length === 0) return;
console.log('트랜잭션 변경 감지, 예산 데이터 업데이트 중...', transactions.length);
setBudgetData(prevBudgetData => {
// 현재 지출 금액 계산
const updatedBudgetData = calculateSpentAmounts(transactions, prevBudgetData);
// 현재 예산 데이터 로드하여 상태 업데이트
const loadedData = safelyLoadBudgetData();
setBudgetData(loadedData);
// 마지막 업데이트 시간 기록
setLastUpdateTime(Date.now());
};
window.addEventListener('budgetDataUpdated', handleBudgetUpdate);
// 스토리지 이벤트도 함께 처리 (다른 탭/창에서의 업데이트 감지)
const storageUpdateHandler = (e: StorageEvent) => {
if (e.key === 'budgetData' || e.key === null) {
console.log('스토리지 이벤트 감지 - 예산 데이터 업데이트');
handleBudgetUpdate();
}
};
window.addEventListener('storage', storageUpdateHandler);
// 이벤트 리스너 정리
return () => {
window.removeEventListener('budgetDataUpdated', handleBudgetUpdate);
window.removeEventListener('storage', storageUpdateHandler);
};
}, [isInitialized]);
console.log('예산 데이터 업데이트 완료:', updatedBudgetData);
return updatedBudgetData;
});
}, [isInitialized, transactions, setBudgetData, setLastUpdateTime]);
// 트랜잭션 변경 시 지출 금액 업데이
// 트랜잭션 변경 감지 이벤
useEffect(() => {
if (transactions.length > 0 && isInitialized) {
console.log('트랜잭션 변경으로 인한 예산 데이터 업데이트. 트랜잭션 수:', transactions.length);
try {
// 현재 예산 데이터 다시 로드 (최신 상태 확보)
const currentBudgetData = safelyLoadBudgetData();
if (!isInitialized) return;
const handleTransactionChanged = (event: CustomEvent) => {
console.log('트랜잭션 변경 이벤트 감지', event.detail);
setBudgetData(prevBudgetData => {
// 현재 지출 금액 계산
const updatedBudgetData = calculateSpentAmounts(transactions, prevBudgetData);
// 지출 금액 업데이트
const updatedBudgetData = calculateSpentAmounts(transactions, currentBudgetData);
// 마지막 업데이트 시간 기록
setLastUpdateTime(Date.now());
// 변경이 있을 때만 저장
if (JSON.stringify(updatedBudgetData) !== JSON.stringify(currentBudgetData)) {
console.log('예산 지출액 업데이트 감지 - 데이터 저장');
// 상태 및 스토리지 모두 업데이트
setBudgetData(updatedBudgetData);
saveBudgetDataToStorage(updatedBudgetData);
setLastUpdateTime(Date.now());
// 기타 컴포넌트에 이벤트 알림
window.dispatchEvent(new Event('budgetDataUpdated'));
return updatedBudgetData;
});
};
// 이벤트 리스너 등록
window.addEventListener('transactionChanged', handleTransactionChanged as EventListener);
return () => {
// 이벤트 리스너 제거
window.removeEventListener('transactionChanged', handleTransactionChanged as EventListener);
};
}, [isInitialized, transactions, setBudgetData, setLastUpdateTime]);
// 스토리지 이벤트 리스너 (다른 탭에서도 데이터 동기화)
useEffect(() => {
if (!isInitialized) return;
const handleStorageChange = (event: StorageEvent) => {
if (event.key === 'transactions') {
console.log('스토리지 이벤트 감지: 트랜잭션 데이터 변경');
try {
// 새 트랜잭션 데이터로 예산 계산
if (event.newValue) {
const newTransactions = JSON.parse(event.newValue);
setBudgetData(prevBudgetData => {
// 현재 지출 금액 계산
const updatedBudgetData = calculateSpentAmounts(newTransactions, prevBudgetData);
// 마지막 업데이트 시간 기록
setLastUpdateTime(Date.now());
return updatedBudgetData;
});
}
} catch (error) {
console.error('스토리지 이벤트 처리 중 오류:', error);
}
} catch (error) {
console.error('예산 데이터 업데이트 중 오류:', error);
}
}
}, [transactions, isInitialized]);
};
// 이벤트 리스너 등록
window.addEventListener('storage', handleStorageChange);
return () => {
// 이벤트 리스너 제거
window.removeEventListener('storage', handleStorageChange);
};
}, [isInitialized, setBudgetData, setLastUpdateTime]);
// 예산 데이터 수동 새로고침 이벤트
useEffect(() => {
if (!isInitialized) return;
const handleBudgetRefresh = () => {
console.log('예산 데이터 수동 새로고침 이벤트 감지');
setBudgetData(prevBudgetData => {
// 현재 지출 금액 계산
const updatedBudgetData = calculateSpentAmounts(transactions, prevBudgetData);
// 마지막 업데이트 시간 기록
setLastUpdateTime(Date.now());
return updatedBudgetData;
});
};
// 수동 새로고침 이벤트 등록
window.addEventListener('budgetDataRefresh', handleBudgetRefresh);
return () => {
// 이벤트 리스너 제거
window.removeEventListener('budgetDataRefresh', handleBudgetRefresh);
};
}, [isInitialized, transactions, setBudgetData, setLastUpdateTime]);
};

View File

@@ -1,5 +1,6 @@
import { BudgetData, Transaction } from '../types';
import { format, isWithinInterval, subDays, startOfMonth, endOfMonth, parseISO } from 'date-fns';
// 지출액 계산 (일일, 주간, 월간)
export const calculateSpentAmounts = (
@@ -10,62 +11,145 @@ export const calculateSpentAmounts = (
// 지출 거래 필터링
const expenseTransactions = transactions.filter(t => t.type === 'expense');
console.log("필터링된 지출 트랜잭션:", expenseTransactions.length);
// 오늘 지출 계산
const todayExpenses = expenseTransactions.filter(t => {
if (t.date && (t.date.includes('오늘') || t.date.includes('today'))) return true;
return false;
// 현재 날짜 정보
const now = new Date();
const today = format(now, 'yyyy-MM-dd');
const currentMonth = format(now, 'yyyy-MM');
const startOfCurrentMonth = startOfMonth(now);
const endOfCurrentMonth = endOfMonth(now);
// 각 지출 트랜잭션의 날짜 정보 로깅
expenseTransactions.forEach((t, index) => {
if (index < 10) { // 처음 10개만 로그 출력 (너무 많은 로그 방지)
console.log(`트랜잭션 ${index}: 날짜=${t.date}, 금액=${t.amount}, 카테고리=${t.category}`);
}
});
const dailySpent = todayExpenses.reduce((sum, t) => sum + t.amount, 0);
// 이번 주 지출 계산 (단순화된 버전)
const weeklyExpenses = expenseTransactions.filter(t => {
if (t.date && (
t.date.includes('오늘') ||
t.date.includes('today') ||
t.date.includes('어제') ||
t.date.includes('yesterday') ||
t.date.includes('이번주') ||
t.date.includes('this week')
)) return true;
return false;
});
const weeklySpent = weeklyExpenses.reduce((sum, t) => sum + t.amount, 0);
// 이번 달 총 지출 계산 (모든 지출 트랜잭션)
const monthlySpent = expenseTransactions.reduce((sum, t) => sum + t.amount, 0);
// 기존 예산 목표 유지 (없으면 기본값 0)
// 날짜 문자열을 Date 객체로 변환하는 함수
const parseTransactionDate = (dateStr: string): Date | null => {
try {
if (dateStr.includes('오늘')) {
return new Date();
}
if (dateStr.includes('어제')) {
return subDays(new Date(), 1);
}
// "yyyy-MM-dd" 형식 확인
if (/^\d{4}-\d{2}-\d{2}/.test(dateStr)) {
return parseISO(dateStr);
}
// "MM월 dd일" 형식 확인 (한국어 날짜)
const koreanDateMatch = dateStr.match(/(\d+)월\s*(\d+)일/);
if (koreanDateMatch) {
const month = parseInt(koreanDateMatch[1]) - 1; // 0-based month
const day = parseInt(koreanDateMatch[2]);
const year = now.getFullYear();
return new Date(year, month, day);
}
// 기타 날짜 문자열은 그대로 Date 생성자에 전달
return new Date(dateStr);
} catch (e) {
console.error('날짜 파싱 실패:', dateStr, e);
return null;
}
};
// 월간 지출 계산 (현재 달의 모든 지출)
const monthlyExpenses = expenseTransactions.filter(t => {
try {
const transactionDate = parseTransactionDate(t.date);
if (!transactionDate) return false;
return isWithinInterval(transactionDate, {
start: startOfCurrentMonth,
end: endOfCurrentMonth
});
} catch (e) {
console.error('월간 지출 필터링 오류:', e);
// 날짜 형식이 명확하지 않은 경우, 트랜잭션 날짜 문자열에 현재 월 문자열이 포함되어 있는지 확인
return t.date.includes(currentMonth) ||
t.date.includes(format(now, 'M월')) ||
t.date.includes('이번 달');
}
});
// 주간 지출 계산 (최근 7일)
const weeklyExpenses = expenseTransactions.filter(t => {
try {
const transactionDate = parseTransactionDate(t.date);
if (!transactionDate) return false;
return isWithinInterval(transactionDate, {
start: subDays(now, 7),
end: now
});
} catch (e) {
// 날짜 형식이 명확하지 않은 경우, 최근에 추가된 항목으로 간주
return t.date.includes('오늘') ||
t.date.includes('어제') ||
t.date.includes('이번 주') ||
t.date.includes('일 전');
}
});
// 일일 지출 계산 (오늘)
const dailyExpenses = expenseTransactions.filter(t => {
try {
const transactionDate = parseTransactionDate(t.date);
if (!transactionDate) return false;
return format(transactionDate, 'yyyy-MM-dd') === today;
} catch (e) {
// 날짜 형식이 명확하지 않은 경우, 오늘 추가된 항목인지 확인
return t.date.includes('오늘') || t.date.includes('지금');
}
});
// 계산된 지출 금액
const dailyTotal = dailyExpenses.reduce((sum, t) => sum + t.amount, 0);
const weeklyTotal = weeklyExpenses.reduce((sum, t) => sum + t.amount, 0);
const monthlyTotal = monthlyExpenses.reduce((sum, t) => sum + t.amount, 0);
console.log("계산된 지출 금액:", {
일일: dailyTotal,
주간: weeklyTotal,
월간: monthlyTotal
});
// 예산 데이터에 적용 전 로그
console.log("기존 예산 데이터:", prevBudgetData);
// 기존 예산 목표 유지
const dailyTarget = prevBudgetData?.daily?.targetAmount || 0;
const weeklyTarget = prevBudgetData?.weekly?.targetAmount || 0;
const monthlyTarget = prevBudgetData?.monthly?.targetAmount || 0;
console.log("예산 목표 확인:", {
일일: dailyTarget,
주간: weeklyTarget,
월간: monthlyTarget
});
// 예산 데이터 업데이트
const updatedBudget = {
daily: {
targetAmount: dailyTarget,
spentAmount: dailySpent,
remainingAmount: Math.max(0, dailyTarget - dailySpent)
spentAmount: dailyTotal,
remainingAmount: Math.max(0, dailyTarget - dailyTotal)
},
weekly: {
targetAmount: weeklyTarget,
spentAmount: weeklySpent,
remainingAmount: Math.max(0, weeklyTarget - weeklySpent)
spentAmount: weeklyTotal,
remainingAmount: Math.max(0, weeklyTarget - weeklyTotal)
},
monthly: {
targetAmount: monthlyTarget,
spentAmount: monthlySpent,
remainingAmount: Math.max(0, monthlyTarget - monthlySpent)
spentAmount: monthlyTotal,
remainingAmount: Math.max(0, monthlyTarget - monthlyTotal)
}
};
console.log("지출액 계산 결과:", updatedBudget);
console.log("업데이트된 예산 데이터:", updatedBudget);
return updatedBudget;
};

View File

@@ -1,12 +1,20 @@
import { useCallback } from 'react';
import { FilteringProps, FilteringReturn } from './types';
import { useMonthSelection } from './useMonthSelection';
import { useFilterApplication } from './useFilterApplication';
import { useTotalCalculation } from './useTotalCalculation';
import { useCallback, useEffect } from 'react';
import { Transaction } from '@/contexts/budget/types';
import { getCurrentMonth, getPrevMonth, getNextMonth } from '../dateUtils';
import { filterTransactionsByMonth, filterTransactionsByQuery, calculateTotalExpenses } from '../filterUtils';
interface UseTransactionsFilteringProps {
transactions: Transaction[];
selectedMonth: string;
setSelectedMonth: (month: string) => void;
searchQuery: string;
setFilteredTransactions: React.Dispatch<React.SetStateAction<Transaction[]>>;
}
/**
* 트랜잭션 필터링 관련 기능을 통합한
* 트랜잭션 필터링 관련 커스텀
* 월간, 검색어 필터링 및 총 지출 계산 기능을 제공합니다.
*/
export const useTransactionsFiltering = ({
transactions,
@@ -14,34 +22,52 @@ export const useTransactionsFiltering = ({
setSelectedMonth,
searchQuery,
setFilteredTransactions
}: FilteringProps): FilteringReturn => {
// 월 선택 관련 기능
const { handlePrevMonth, handleNextMonth } = useMonthSelection({
selectedMonth,
setSelectedMonth
});
}: UseTransactionsFilteringProps) => {
// 필터링 적용
useEffect(() => {
console.log('트랜잭션 필터링 적용:', { 선택된월: selectedMonth, 검색어: searchQuery });
try {
// 먼저 월별 필터링
const monthFiltered = filterTransactionsByMonth(transactions, selectedMonth);
console.log('월별 필터링 결과:', monthFiltered.length);
// 그 다음 검색어 필터링
const searchFiltered = searchQuery
? filterTransactionsByQuery(monthFiltered, searchQuery)
: monthFiltered;
console.log('최종 필터링 결과:', searchFiltered.length);
setFilteredTransactions(searchFiltered);
} catch (error) {
console.error('트랜잭션 필터링 중 오류 발생:', error);
// 오류 발생 시 원본 데이터 유지
setFilteredTransactions(transactions);
}
}, [transactions, selectedMonth, searchQuery, setFilteredTransactions]);
// 필터 적용 관련 기능
const { filterTransactions } = useFilterApplication({
transactions,
selectedMonth,
searchQuery,
setFilteredTransactions
});
// 이전 달로 이동
const handlePrevMonth = useCallback(() => {
setSelectedMonth(getPrevMonth(selectedMonth));
}, [selectedMonth, setSelectedMonth]);
// 총 지출 계산 관련 기능
const { getTotalExpenses } = useTotalCalculation();
// 다음 달로 이동
const handleNextMonth = useCallback(() => {
setSelectedMonth(getNextMonth(selectedMonth));
}, [selectedMonth, setSelectedMonth]);
// 강제 필터링 실행 함수 (외부에서 호출 가능)
const forceRefresh = useCallback(() => {
console.log('필터 강제 새로고침');
filterTransactions();
}, [filterTransactions]);
// 총 지출 계산 - date-fns 없이도 사용 가능한 단순 버전
const getTotalExpenses = useCallback((filteredTransactions: Transaction[]): number => {
console.log('총 지출 계산 중...', filteredTransactions.length);
const total = calculateTotalExpenses(filteredTransactions);
console.log('계산된 총 지출:', total);
return total;
}, []);
return {
handlePrevMonth,
handleNextMonth,
getTotalExpenses,
forceRefresh
getTotalExpenses
};
};

View File

@@ -1,63 +1,108 @@
import { Transaction } from '@/components/TransactionCard';
import { MONTHS_KR } from './dateUtils';
import { Transaction } from '@/contexts/budget/types';
// 월별 거래 필터링
export const filterTransactionsByMonth = (transactions: Transaction[], selectedMonth: string): Transaction[] => {
console.log('월별 필터링:', selectedMonth, '트랜잭션 수:', transactions.length);
/**
* 월별로 트랜잭션 필터링
*/
export const filterTransactionsByMonth = (
transactions: Transaction[],
selectedMonth: string
): Transaction[] => {
console.log(`월별 트랜잭션 필터링: ${selectedMonth}, 총 데이터 수: ${transactions.length}`);
// 현재 날짜 정보
const now = new Date();
const currentYear = now.getFullYear();
const currentMonth = now.getMonth() + 1; // JavaScript 월은 0부터 시작
// 선택된 월의 인덱스 (0-11)
const selectedMonthIndex = MONTHS_KR.findIndex(month => month === selectedMonth);
// 특수 케이스 처리: '이번 달', '오늘', '이번 주' 등
if (transactions.some(t => t.date.includes('오늘') || t.date.includes('어제') || t.date.includes('이번주'))) {
return transactions;
// 필터링 전 샘플 데이터 로그
if (transactions.length > 0) {
console.log('샘플 트랜잭션 날짜:', transactions.slice(0, 3).map(t => t.date));
}
// 실제 필터링
return transactions.filter(transaction => {
// 날짜 형식이 '2023-05-15' 또는 '2023/05/15' 등의 형식인 경우
if (transaction.date.includes('-') || transaction.date.includes('/')) {
const parts = transaction.date.split(/[-\/]/);
if (parts.length >= 2) {
const transactionMonth = parseInt(parts[1]);
const monthIndex = transactionMonth - 1; // 0-11 인덱스로 변환
return monthIndex === selectedMonthIndex;
}
const filtered = transactions.filter(transaction => {
// 트랜잭션 타입 확인 - 지출 항목만 포함
if (transaction.type !== 'expense') {
return false;
}
// 날짜에 월이 포함된 경우 (예: '5월 15일')
for (let i = 0; i < MONTHS_KR.length; i++) {
if (transaction.date.includes(MONTHS_KR[i])) {
return MONTHS_KR[i] === selectedMonth;
try {
// 날짜가 없는 경우 필터링 제외
if (!transaction.date) {
console.warn('날짜 없는 트랜잭션:', transaction);
return false;
}
// 현재 월 포함 확인 (다양한 형식 지원)
const dateIncludes = transaction.date.includes(selectedMonth);
// 월 이름으로 확인 (한글)
const monthNumberMatch = selectedMonth.match(/\d{4}-(\d{2})/);
let monthNameIncluded = false;
if (monthNumberMatch) {
const monthNumber = parseInt(monthNumberMatch[1]);
const koreanMonths = [
'1월', '2월', '3월', '4월', '5월', '6월',
'7월', '8월', '9월', '10월', '11월', '12월'
];
// 해당 월의 한글 이름이 트랜잭션 날짜에 포함되어 있는지 확인
if (monthNumber >= 1 && monthNumber <= 12) {
monthNameIncluded = transaction.date.includes(koreanMonths[monthNumber - 1]);
}
}
return dateIncludes || monthNameIncluded;
} catch (e) {
console.error('트랜잭션 필터링 중 오류:', e, transaction);
return false;
}
// 기본적으로 모든 트랜잭션 표시 (필터링 실패 시)
return true;
});
};
// 검색어로 거래 필터링
export const filterTransactionsByQuery = (transactions: Transaction[], query: string): Transaction[] => {
if (!query.trim()) return transactions;
const lowercaseQuery = query.toLowerCase();
return transactions.filter(transaction =>
transaction.title.toLowerCase().includes(lowercaseQuery) ||
transaction.category.toLowerCase().includes(lowercaseQuery) ||
transaction.amount.toString().includes(lowercaseQuery)
);
console.log(`월별 필터링 결과: ${filtered.length}개 항목 (${selectedMonth})`);
return filtered;
};
// 총 지출 계산
export const calculateTotalExpenses = (transactions: Transaction[]): number => {
return transactions
.filter(t => t.type === 'expense')
.reduce((total, transaction) => total + transaction.amount, 0);
/**
* 검색어로 트랜잭션 필터링
*/
export const filterTransactionsByQuery = (
transactions: Transaction[],
searchQuery: string
): Transaction[] => {
if (!searchQuery.trim()) return transactions;
const query = searchQuery.toLowerCase().trim();
console.log(`검색어 필터링: "${query}"`);
const filtered = transactions.filter(transaction => {
try {
return (
(transaction.title?.toLowerCase().includes(query)) ||
(transaction.category?.toLowerCase().includes(query)) ||
(transaction.paymentMethod?.toLowerCase().includes(query))
);
} catch (e) {
console.error('검색어 필터링 중 오류:', e, transaction);
return false;
}
});
console.log(`검색어 필터링 결과: ${filtered.length}개 항목`);
return filtered;
};
/**
* 총 지출 금액 계산
*/
export const calculateTotalExpenses = (transactions: Transaction[]): number => {
try {
const total = transactions.reduce((sum, t) => {
// 유효한 숫자인지 확인
const amount = typeof t.amount === 'number' ? t.amount : 0;
return sum + amount;
}, 0);
console.log(`총 지출 계산: ${total}원 (${transactions.length}개 항목)`);
return total;
} catch (e) {
console.error('총 지출 계산 중 오류:', e);
return 0;
}
};

96
src/utils/dateParser.ts Normal file
View File

@@ -0,0 +1,96 @@
import { format, parse, isValid, parseISO } from 'date-fns';
import { ko } from 'date-fns/locale';
/**
* 다양한 형식의 날짜 문자열을 Date 객체로 변환하는 유틸리티
*/
export const parseTransactionDate = (dateStr: string): Date | null => {
// 빈 문자열 체크
if (!dateStr) {
return null;
}
try {
// 특수 키워드 처리
if (dateStr.includes('오늘')) {
return new Date();
}
if (dateStr.includes('어제')) {
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
return yesterday;
}
// ISO 형식 (yyyy-MM-dd) 시도
if (/^\d{4}-\d{2}-\d{2}/.test(dateStr)) {
const date = parseISO(dateStr);
if (isValid(date)) {
return date;
}
}
// "M월 d일" 형식 (한국어) 시도
const koreanDatePattern = /(\d+)월\s*(\d+)일/;
const koreanMatch = dateStr.match(koreanDatePattern);
if (koreanMatch) {
const month = parseInt(koreanMatch[1]) - 1; // 0-based month
const day = parseInt(koreanMatch[2]);
const date = new Date();
date.setMonth(month);
date.setDate(day);
return date;
}
// parse를 사용한 다양한 형식 시도
const formats = [
'yyyy-MM-dd',
'yyyy/MM/dd',
'MM-dd-yyyy',
'MM/dd/yyyy',
'yyyy년 MM월 dd일',
'MM월 dd일'
];
for (const formatStr of formats) {
try {
const date = parse(dateStr, formatStr, new Date(), { locale: ko });
if (isValid(date)) {
return date;
}
} catch (e) {
// 이 형식이 실패하면 다음 형식 시도
continue;
}
}
// 위 모든 형식이 실패하면 마지막으로 Date 생성자 시도
const dateFromConstructor = new Date(dateStr);
if (isValid(dateFromConstructor)) {
return dateFromConstructor;
}
// 모든 방법이 실패하면 null 반환
console.warn(`날짜 파싱 실패: ${dateStr}`);
return null;
} catch (error) {
console.error(`날짜 파싱 중 오류 발생: ${dateStr}`, error);
return null;
}
};
/**
* Date 객체를 yyyy-MM-dd 형식의 문자열로 변환
*/
export const formatDateToYMD = (date: Date): string => {
return format(date, 'yyyy-MM-dd');
};
/**
* 현재 년월 포맷 (yyyy-MM)
*/
export const getCurrentYearMonth = (): string => {
return format(new Date(), 'yyyy-MM');
};