Refactor uploadBudget module
Refactor the uploadBudget.ts file into smaller, more manageable modules to improve code readability and maintainability.
This commit is contained in:
@@ -1,5 +1,20 @@
|
|||||||
|
|
||||||
// 예산 동기화 관련 모듈
|
/**
|
||||||
|
* 예산 동기화 관련 모듈
|
||||||
|
* 모든 예산 관련 함수를 하나의 파일에서 내보냅니다.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 예산 업로드 관련 함수
|
||||||
export * from './uploadBudget';
|
export * from './uploadBudget';
|
||||||
|
export * from './uploadMonthlyBudget';
|
||||||
|
export * from './uploadCategoryBudgets';
|
||||||
|
|
||||||
|
// 예산 다운로드 관련 함수
|
||||||
export * from './downloadBudget';
|
export * from './downloadBudget';
|
||||||
|
|
||||||
|
// 예산 추적 관련 함수
|
||||||
export * from './modifiedBudgetsTracker';
|
export * from './modifiedBudgetsTracker';
|
||||||
|
|
||||||
|
// 타입 정의 및 유틸리티
|
||||||
|
export * from './types';
|
||||||
|
export * from './validators';
|
||||||
|
|||||||
50
src/utils/sync/budget/types.ts
Normal file
50
src/utils/sync/budget/types.ts
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* 예산 동기화 관련 타입 정의
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 예산 데이터 타입
|
||||||
|
export interface BudgetData {
|
||||||
|
daily: BudgetPeriod;
|
||||||
|
weekly: BudgetPeriod;
|
||||||
|
monthly: BudgetPeriod;
|
||||||
|
[key: string]: BudgetPeriod;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 기간별 예산 타입
|
||||||
|
export interface BudgetPeriod {
|
||||||
|
targetAmount: number;
|
||||||
|
spentAmount: number;
|
||||||
|
remainingAmount: number;
|
||||||
|
[key: string]: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 카테고리 예산 타입
|
||||||
|
export type CategoryBudgets = Record<string, number>;
|
||||||
|
|
||||||
|
// 예산 업로드 결과 타입
|
||||||
|
export interface BudgetUploadResult {
|
||||||
|
success: boolean;
|
||||||
|
message: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 데이터베이스 예산 항목 타입
|
||||||
|
export interface BudgetRecord {
|
||||||
|
id?: string;
|
||||||
|
user_id: string;
|
||||||
|
month: number;
|
||||||
|
year: number;
|
||||||
|
total_budget: number;
|
||||||
|
created_at?: string;
|
||||||
|
updated_at: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 데이터베이스 카테고리 예산 항목 타입
|
||||||
|
export interface CategoryBudgetRecord {
|
||||||
|
id?: string;
|
||||||
|
user_id: string;
|
||||||
|
category: string;
|
||||||
|
amount: number;
|
||||||
|
created_at?: string;
|
||||||
|
updated_at: string;
|
||||||
|
}
|
||||||
@@ -1,10 +1,16 @@
|
|||||||
|
|
||||||
import { supabase } from '@/lib/supabase';
|
/**
|
||||||
|
* 예산 데이터 업로드 메인 모듈
|
||||||
|
*/
|
||||||
import { isSyncEnabled } from '../syncSettings';
|
import { isSyncEnabled } from '../syncSettings';
|
||||||
import {
|
import {
|
||||||
clearModifiedBudget,
|
clearModifiedBudget,
|
||||||
clearModifiedCategoryBudgets
|
clearModifiedCategoryBudgets
|
||||||
} from './modifiedBudgetsTracker';
|
} from './modifiedBudgetsTracker';
|
||||||
|
import { uploadMonthlyBudget } from './uploadMonthlyBudget';
|
||||||
|
import { uploadCategoryBudgets } from './uploadCategoryBudgets';
|
||||||
|
import { isValidMonthlyBudget, isValidCategoryBudgets } from './validators';
|
||||||
|
import { BudgetData, CategoryBudgets } from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 예산 데이터를 서버에 업로드
|
* 예산 데이터를 서버에 업로드
|
||||||
@@ -20,35 +26,48 @@ export const uploadBudgets = async (userId: string): Promise<void> => {
|
|||||||
|
|
||||||
// 예산 데이터 업로드
|
// 예산 데이터 업로드
|
||||||
if (budgetDataStr) {
|
if (budgetDataStr) {
|
||||||
const budgetData = JSON.parse(budgetDataStr);
|
try {
|
||||||
|
const budgetData: BudgetData = JSON.parse(budgetDataStr);
|
||||||
|
|
||||||
// 월간 예산이 0보다 클 때만 업로드
|
// 월간 예산이 유효할 때만 업로드
|
||||||
if (budgetData.monthly && typeof budgetData.monthly.targetAmount === 'number' && budgetData.monthly.targetAmount > 0) {
|
if (isValidMonthlyBudget(budgetData)) {
|
||||||
console.log('유효한 월간 예산 발견:', budgetData.monthly.targetAmount);
|
console.log('유효한 월간 예산 발견:', budgetData.monthly.targetAmount);
|
||||||
await uploadBudgetData(userId, budgetData);
|
const uploadSuccess = await uploadMonthlyBudget(userId, budgetData);
|
||||||
|
|
||||||
// 업로드 성공 후 수정 추적 정보 초기화
|
// 업로드 성공 후 수정 추적 정보 초기화
|
||||||
|
if (uploadSuccess) {
|
||||||
clearModifiedBudget();
|
clearModifiedBudget();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('월간 예산이 0 이하거나 없어서 업로드 건너뜀');
|
console.log('월간 예산이 0 이하거나 없어서 업로드 건너뜀');
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('월간 예산 데이터 파싱 또는 업로드 오류:', error);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('업로드할 예산 데이터가 없음');
|
console.log('업로드할 예산 데이터가 없음');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 카테고리 예산 업로드
|
// 카테고리 예산 업로드
|
||||||
if (categoryBudgetsStr) {
|
if (categoryBudgetsStr) {
|
||||||
const categoryBudgets = JSON.parse(categoryBudgetsStr);
|
try {
|
||||||
|
const categoryBudgets: CategoryBudgets = JSON.parse(categoryBudgetsStr);
|
||||||
|
|
||||||
|
// 총 카테고리 예산이 유효할 때만 업로드
|
||||||
|
if (isValidCategoryBudgets(categoryBudgets)) {
|
||||||
|
console.log('유효한 카테고리 예산 발견');
|
||||||
|
const uploadSuccess = await uploadCategoryBudgets(userId, categoryBudgets);
|
||||||
|
|
||||||
// 총 카테고리 예산이 0보다 클 때만 업로드
|
|
||||||
const totalCategoryBudget = Object.values(categoryBudgets).reduce((sum: number, val: number) => sum + val, 0);
|
|
||||||
if (totalCategoryBudget > 0) {
|
|
||||||
console.log('유효한 카테고리 예산 발견:', totalCategoryBudget);
|
|
||||||
await uploadCategoryBudgets(userId, categoryBudgets);
|
|
||||||
// 업로드 성공 후 수정 추적 정보 초기화
|
// 업로드 성공 후 수정 추적 정보 초기화
|
||||||
|
if (uploadSuccess) {
|
||||||
clearModifiedCategoryBudgets();
|
clearModifiedCategoryBudgets();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('카테고리 예산이 모두 0이어서 업로드 건너뜀');
|
console.log('카테고리 예산이 모두 0이어서 업로드 건너뜀');
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('카테고리 예산 데이터 파싱 또는 업로드 오류:', error);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('업로드할 카테고리 예산이 없음');
|
console.log('업로드할 카테고리 예산이 없음');
|
||||||
}
|
}
|
||||||
@@ -59,171 +78,3 @@ export const uploadBudgets = async (userId: string): Promise<void> => {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* 일반 예산 데이터 업로드
|
|
||||||
*/
|
|
||||||
async function uploadBudgetData(userId: string, parsedBudgetData: Record<string, any>): Promise<void> {
|
|
||||||
console.log('예산 데이터 업로드:', parsedBudgetData);
|
|
||||||
|
|
||||||
// 현재 월/년도 가져오기
|
|
||||||
const now = new Date();
|
|
||||||
const currentMonth = now.getMonth() + 1; // 0-11 -> 1-12
|
|
||||||
const currentYear = now.getFullYear();
|
|
||||||
|
|
||||||
// 기존 예산 데이터 확인
|
|
||||||
const { data: existingBudgets, error: fetchError } = await supabase
|
|
||||||
.from('budgets')
|
|
||||||
.select('*')
|
|
||||||
.eq('user_id', userId)
|
|
||||||
.eq('month', currentMonth)
|
|
||||||
.eq('year', currentYear);
|
|
||||||
|
|
||||||
if (fetchError) {
|
|
||||||
console.error('기존 예산 데이터 조회 실패:', fetchError);
|
|
||||||
throw fetchError;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 월간 타겟 금액 가져오기
|
|
||||||
const monthlyTarget = parsedBudgetData.monthly.targetAmount;
|
|
||||||
|
|
||||||
// 예산이 0 이하면 업로드하지 않음
|
|
||||||
if (typeof monthlyTarget !== 'number' || monthlyTarget <= 0) {
|
|
||||||
console.log('월간 예산이 0 이하여서 업로드 건너뜀:', monthlyTarget);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('업로드할 월간 예산:', monthlyTarget);
|
|
||||||
|
|
||||||
// 현재 타임스탬프
|
|
||||||
const currentTimestamp = new Date().toISOString();
|
|
||||||
|
|
||||||
// 가능한 경우 서버 데이터와 비교하여 필요한 경우만 업데이트
|
|
||||||
if (existingBudgets && existingBudgets.length > 0) {
|
|
||||||
const existingBudget = existingBudgets[0];
|
|
||||||
// 새 예산이 기존 예산보다 클 때만 업데이트
|
|
||||||
if (typeof existingBudget.total_budget === 'number' && monthlyTarget > existingBudget.total_budget) {
|
|
||||||
console.log(`새 예산(${monthlyTarget})이 기존 예산(${existingBudget.total_budget})보다 큼, 업데이트 실행`);
|
|
||||||
|
|
||||||
// 기존 데이터 업데이트
|
|
||||||
const { error } = await supabase
|
|
||||||
.from('budgets')
|
|
||||||
.update({
|
|
||||||
total_budget: monthlyTarget,
|
|
||||||
updated_at: currentTimestamp
|
|
||||||
})
|
|
||||||
.eq('id', existingBudget.id);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error('예산 데이터 업데이트 실패:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('예산 데이터 업데이트 성공');
|
|
||||||
} else {
|
|
||||||
console.log(`새 예산(${monthlyTarget})이 기존 예산(${existingBudget.total_budget})보다 작거나 같음, 업데이트 건너뜀`);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 새 데이터 삽입
|
|
||||||
const { error } = await supabase
|
|
||||||
.from('budgets')
|
|
||||||
.insert({
|
|
||||||
user_id: userId,
|
|
||||||
month: currentMonth,
|
|
||||||
year: currentYear,
|
|
||||||
total_budget: monthlyTarget,
|
|
||||||
created_at: currentTimestamp,
|
|
||||||
updated_at: currentTimestamp
|
|
||||||
});
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error('예산 데이터 삽입 실패:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('예산 데이터 삽입 성공');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 카테고리 예산 데이터 업로드
|
|
||||||
*/
|
|
||||||
async function uploadCategoryBudgets(userId: string, parsedCategoryBudgets: Record<string, number>): Promise<void> {
|
|
||||||
console.log('카테고리 예산 업로드:', parsedCategoryBudgets);
|
|
||||||
|
|
||||||
// 기존 카테고리 예산 확인
|
|
||||||
const { data: existingCategoryBudgets, error: fetchError } = await supabase
|
|
||||||
.from('category_budgets')
|
|
||||||
.select('*')
|
|
||||||
.eq('user_id', userId);
|
|
||||||
|
|
||||||
if (fetchError) {
|
|
||||||
console.error('기존 카테고리 예산 조회 실패:', fetchError);
|
|
||||||
throw fetchError;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 기존 카테고리 예산의 총액 계산
|
|
||||||
let existingTotal = 0;
|
|
||||||
if (existingCategoryBudgets && existingCategoryBudgets.length > 0) {
|
|
||||||
existingTotal = existingCategoryBudgets.reduce((sum, item) => {
|
|
||||||
return sum + (typeof item.amount === 'number' ? item.amount : 0);
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 새 카테고리 예산의 총액 계산
|
|
||||||
const newTotal = Object.values(parsedCategoryBudgets).reduce((sum: number, val: number) => sum + val, 0);
|
|
||||||
|
|
||||||
// 새 카테고리 예산 총액이 기존 카테고리 예산 총액보다 작거나 같으면 업로드 건너뜀
|
|
||||||
if (newTotal <= existingTotal && existingTotal > 0) {
|
|
||||||
console.log(`새 카테고리 예산 총액(${newTotal})이 기존 예산 총액(${existingTotal})보다 작거나 같음, 업로드 건너뜀`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 새 카테고리 예산 총액이 0이면 업로드 건너뜀
|
|
||||||
if (newTotal <= 0) {
|
|
||||||
console.log('새 카테고리 예산 총액이 0이하여서 업로드 건너뜀');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`새 카테고리 예산 총액(${newTotal})이 기존 예산 총액(${existingTotal})보다 큼, 업로드 실행`);
|
|
||||||
|
|
||||||
// 기존 카테고리 예산 삭제
|
|
||||||
const { error: deleteError } = await supabase
|
|
||||||
.from('category_budgets')
|
|
||||||
.delete()
|
|
||||||
.eq('user_id', userId);
|
|
||||||
|
|
||||||
if (deleteError) {
|
|
||||||
console.error('기존 카테고리 예산 삭제 실패:', deleteError);
|
|
||||||
// 오류가 나도 계속 진행 (중요 데이터가 아니기 때문)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 현재 타임스탬프
|
|
||||||
const currentTimestamp = new Date().toISOString();
|
|
||||||
|
|
||||||
// 카테고리별 예산 데이터 변환 및 삽입
|
|
||||||
const categoryEntries = Object.entries(parsedCategoryBudgets)
|
|
||||||
.filter(([_, amount]) => typeof amount === 'number' && amount > 0) // 금액이 0보다 큰 것만 저장
|
|
||||||
.map(([category, amount]) => ({
|
|
||||||
user_id: userId,
|
|
||||||
category,
|
|
||||||
amount,
|
|
||||||
created_at: currentTimestamp,
|
|
||||||
updated_at: currentTimestamp
|
|
||||||
}));
|
|
||||||
|
|
||||||
if (categoryEntries.length > 0) {
|
|
||||||
const { error } = await supabase
|
|
||||||
.from('category_budgets')
|
|
||||||
.insert(categoryEntries);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error('카테고리 예산 삽입 실패:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('카테고리 예산 삽입 성공:', categoryEntries.length, '개');
|
|
||||||
} else {
|
|
||||||
console.log('저장할 카테고리 예산이 없음');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
92
src/utils/sync/budget/uploadCategoryBudgets.ts
Normal file
92
src/utils/sync/budget/uploadCategoryBudgets.ts
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* 카테고리 예산 업로드 기능
|
||||||
|
*/
|
||||||
|
import { supabase } from '@/lib/supabase';
|
||||||
|
import { CategoryBudgets, CategoryBudgetRecord } from './types';
|
||||||
|
import { calculateTotalCategoryBudget, filterValidCategoryBudgets } from './validators';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 카테고리 예산 데이터 업로드
|
||||||
|
*/
|
||||||
|
export async function uploadCategoryBudgets(userId: string, parsedCategoryBudgets: CategoryBudgets): Promise<boolean> {
|
||||||
|
console.log('카테고리 예산 업로드:', parsedCategoryBudgets);
|
||||||
|
|
||||||
|
// 기존 카테고리 예산 확인
|
||||||
|
const { data: existingCategoryBudgets, error: fetchError } = await supabase
|
||||||
|
.from('category_budgets')
|
||||||
|
.select('*')
|
||||||
|
.eq('user_id', userId);
|
||||||
|
|
||||||
|
if (fetchError) {
|
||||||
|
console.error('기존 카테고리 예산 조회 실패:', fetchError);
|
||||||
|
throw fetchError;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 기존 카테고리 예산의 총액 계산
|
||||||
|
let existingTotal = 0;
|
||||||
|
if (existingCategoryBudgets && existingCategoryBudgets.length > 0) {
|
||||||
|
existingTotal = existingCategoryBudgets.reduce((sum, item) => {
|
||||||
|
return sum + (typeof item.amount === 'number' ? item.amount : 0);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 새 카테고리 예산의 총액 계산
|
||||||
|
const newTotal = calculateTotalCategoryBudget(parsedCategoryBudgets);
|
||||||
|
|
||||||
|
// 새 카테고리 예산 총액이 기존 카테고리 예산 총액보다 작거나 같으면 업로드 건너뜀
|
||||||
|
if (newTotal <= existingTotal && existingTotal > 0) {
|
||||||
|
console.log(`새 카테고리 예산 총액(${newTotal})이 기존 예산 총액(${existingTotal})보다 작거나 같음, 업로드 건너뜀`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 새 카테고리 예산 총액이 0이면 업로드 건너뜀
|
||||||
|
if (newTotal <= 0) {
|
||||||
|
console.log('새 카테고리 예산 총액이 0이하여서 업로드 건너뜀');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`새 카테고리 예산 총액(${newTotal})이 기존 예산 총액(${existingTotal})보다 큼, 업로드 실행`);
|
||||||
|
|
||||||
|
// 기존 카테고리 예산 삭제
|
||||||
|
const { error: deleteError } = await supabase
|
||||||
|
.from('category_budgets')
|
||||||
|
.delete()
|
||||||
|
.eq('user_id', userId);
|
||||||
|
|
||||||
|
if (deleteError) {
|
||||||
|
console.error('기존 카테고리 예산 삭제 실패:', deleteError);
|
||||||
|
// 오류가 나도 계속 진행 (중요 데이터가 아니기 때문)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 현재 타임스탬프
|
||||||
|
const currentTimestamp = new Date().toISOString();
|
||||||
|
|
||||||
|
// 카테고리별 예산 데이터 변환 및 삽입
|
||||||
|
const validCategoryBudgets = filterValidCategoryBudgets(parsedCategoryBudgets);
|
||||||
|
const categoryEntries: CategoryBudgetRecord[] = Object.entries(validCategoryBudgets)
|
||||||
|
.map(([category, amount]) => ({
|
||||||
|
user_id: userId,
|
||||||
|
category,
|
||||||
|
amount,
|
||||||
|
created_at: currentTimestamp,
|
||||||
|
updated_at: currentTimestamp
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (categoryEntries.length > 0) {
|
||||||
|
const { error } = await supabase
|
||||||
|
.from('category_budgets')
|
||||||
|
.insert(categoryEntries);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error('카테고리 예산 삽입 실패:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('카테고리 예산 삽입 성공:', categoryEntries.length, '개');
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
console.log('저장할 카테고리 예산이 없음');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
98
src/utils/sync/budget/uploadMonthlyBudget.ts
Normal file
98
src/utils/sync/budget/uploadMonthlyBudget.ts
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* 월간 예산 업로드 기능
|
||||||
|
*/
|
||||||
|
import { supabase } from '@/lib/supabase';
|
||||||
|
import { BudgetData, BudgetRecord } from './types';
|
||||||
|
import { isValidMonthlyBudget } from './validators';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 월간 예산 데이터 업로드
|
||||||
|
*/
|
||||||
|
export async function uploadMonthlyBudget(userId: string, parsedBudgetData: BudgetData): Promise<boolean> {
|
||||||
|
console.log('월간 예산 데이터 업로드:', parsedBudgetData);
|
||||||
|
|
||||||
|
// 월간 타겟 금액 가져오기
|
||||||
|
const monthlyTarget = parsedBudgetData.monthly.targetAmount;
|
||||||
|
|
||||||
|
// 예산이 0 이하면 업로드하지 않음
|
||||||
|
if (typeof monthlyTarget !== 'number' || monthlyTarget <= 0) {
|
||||||
|
console.log('월간 예산이 0 이하여서 업로드 건너뜀:', monthlyTarget);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 현재 월/년도 가져오기
|
||||||
|
const now = new Date();
|
||||||
|
const currentMonth = now.getMonth() + 1; // 0-11 -> 1-12
|
||||||
|
const currentYear = now.getFullYear();
|
||||||
|
|
||||||
|
// 기존 예산 데이터 확인
|
||||||
|
const { data: existingBudgets, error: fetchError } = await supabase
|
||||||
|
.from('budgets')
|
||||||
|
.select('*')
|
||||||
|
.eq('user_id', userId)
|
||||||
|
.eq('month', currentMonth)
|
||||||
|
.eq('year', currentYear);
|
||||||
|
|
||||||
|
if (fetchError) {
|
||||||
|
console.error('기존 예산 데이터 조회 실패:', fetchError);
|
||||||
|
throw fetchError;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('업로드할 월간 예산:', monthlyTarget);
|
||||||
|
|
||||||
|
// 현재 타임스탬프
|
||||||
|
const currentTimestamp = new Date().toISOString();
|
||||||
|
|
||||||
|
// 가능한 경우 서버 데이터와 비교하여 필요한 경우만 업데이트
|
||||||
|
if (existingBudgets && existingBudgets.length > 0) {
|
||||||
|
const existingBudget = existingBudgets[0];
|
||||||
|
|
||||||
|
// 새 예산이 기존 예산보다 클 때만 업데이트
|
||||||
|
if (typeof existingBudget.total_budget === 'number' && monthlyTarget > existingBudget.total_budget) {
|
||||||
|
console.log(`새 예산(${monthlyTarget})이 기존 예산(${existingBudget.total_budget})보다 큼, 업데이트 실행`);
|
||||||
|
|
||||||
|
// 기존 데이터 업데이트
|
||||||
|
const { error } = await supabase
|
||||||
|
.from('budgets')
|
||||||
|
.update({
|
||||||
|
total_budget: monthlyTarget,
|
||||||
|
updated_at: currentTimestamp
|
||||||
|
})
|
||||||
|
.eq('id', existingBudget.id);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error('예산 데이터 업데이트 실패:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('예산 데이터 업데이트 성공');
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
console.log(`새 예산(${monthlyTarget})이 기존 예산(${existingBudget.total_budget})보다 작거나 같음, 업데이트 건너뜀`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 새 데이터 삽입
|
||||||
|
const newBudget: BudgetRecord = {
|
||||||
|
user_id: userId,
|
||||||
|
month: currentMonth,
|
||||||
|
year: currentYear,
|
||||||
|
total_budget: monthlyTarget,
|
||||||
|
created_at: currentTimestamp,
|
||||||
|
updated_at: currentTimestamp
|
||||||
|
};
|
||||||
|
|
||||||
|
const { error } = await supabase
|
||||||
|
.from('budgets')
|
||||||
|
.insert(newBudget);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error('예산 데이터 삽입 실패:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('예산 데이터 삽입 성공');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
50
src/utils/sync/budget/validators.ts
Normal file
50
src/utils/sync/budget/validators.ts
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* 예산 데이터 검증 유틸리티
|
||||||
|
*/
|
||||||
|
import { BudgetData, CategoryBudgets } from './types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 월간 예산이 유효한지 확인
|
||||||
|
*/
|
||||||
|
export const isValidMonthlyBudget = (budgetData: BudgetData | null): boolean => {
|
||||||
|
if (!budgetData || !budgetData.monthly) return false;
|
||||||
|
|
||||||
|
const { targetAmount } = budgetData.monthly;
|
||||||
|
return typeof targetAmount === 'number' && targetAmount > 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 카테고리 예산이 유효한지 확인
|
||||||
|
*/
|
||||||
|
export const isValidCategoryBudgets = (categoryBudgets: CategoryBudgets | null): boolean => {
|
||||||
|
if (!categoryBudgets) return false;
|
||||||
|
|
||||||
|
// 총 예산 금액 계산
|
||||||
|
const totalAmount = Object.values(categoryBudgets).reduce((sum, amount) => {
|
||||||
|
return sum + (typeof amount === 'number' ? amount : 0);
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
return totalAmount > 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 카테고리 예산 총액 계산
|
||||||
|
*/
|
||||||
|
export const calculateTotalCategoryBudget = (categoryBudgets: CategoryBudgets | null): number => {
|
||||||
|
if (!categoryBudgets) return 0;
|
||||||
|
|
||||||
|
return Object.values(categoryBudgets).reduce((sum, amount) => {
|
||||||
|
return sum + (typeof amount === 'number' ? amount : 0);
|
||||||
|
}, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 유효한 카테고리 예산 항목만 필터링
|
||||||
|
*/
|
||||||
|
export const filterValidCategoryBudgets = (categoryBudgets: CategoryBudgets): CategoryBudgets => {
|
||||||
|
return Object.fromEntries(
|
||||||
|
Object.entries(categoryBudgets)
|
||||||
|
.filter(([_, amount]) => typeof amount === 'number' && amount > 0)
|
||||||
|
);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user