feat: 결제 금액 계산 유틸리티 추가

This commit is contained in:
JiWoong Sul
2026-01-14 00:18:12 +09:00
parent 0f92206833
commit da530a99b7
2 changed files with 303 additions and 7 deletions

View File

@@ -1,5 +1,6 @@
import 'package:intl/intl.dart';
import '../models/subscription_model.dart';
import '../utils/billing_cost_util.dart';
import 'exchange_rate_service.dart';
import 'cache_manager.dart';
@@ -129,7 +130,8 @@ class CurrencyUtil {
return result;
}
/// 구독 목록의 총 비용을 계산 (언어별 기본 통화로)
/// 구독 목록의 이번 달 총 비용을 계산 (언어별 기본 통화로)
/// 이번 달에 결제가 발생하는 구독만 포함하며, 실제 결제 금액을 사용
static Future<double> calculateTotalMonthlyExpenseInDefaultCurrency(
List<SubscriptionModel> subscriptions,
String locale,
@@ -137,16 +139,33 @@ class CurrencyUtil {
final defaultCurrency = getDefaultCurrency(locale);
double total = 0.0;
final now = DateTime.now();
final currentYear = now.year;
final currentMonth = now.month;
for (var subscription in subscriptions) {
final price = subscription.currentPrice;
// 이번 달에 결제가 발생하는지 확인
final hasBilling = BillingCostUtil.hasBillingInMonth(
subscription.nextBillingDate,
subscription.billingCycle,
currentYear,
currentMonth,
);
if (!hasBilling) continue;
// 실제 결제 금액으로 역변환
final actualPrice = BillingCostUtil.convertFromMonthlyCost(
subscription.currentPrice,
subscription.billingCycle,
);
final converted = await _exchangeRateService.convertBetweenCurrencies(
price,
actualPrice,
subscription.currency,
defaultCurrency,
);
total += converted ?? price;
total += converted ?? actualPrice;
}
return total;
@@ -158,17 +177,46 @@ class CurrencyUtil {
return calculateTotalMonthlyExpenseInDefaultCurrency(subscriptions, 'ko');
}
/// 구독 목록의 예상 연간 총 비용을 계산 (언어별 기본 통화로)
/// 모든 구독의 연간 비용을 합산 (월 환산 비용 × 12)
static Future<double> calculateTotalAnnualExpenseInDefaultCurrency(
List<SubscriptionModel> subscriptions,
String locale,
) async {
final defaultCurrency = getDefaultCurrency(locale);
double total = 0.0;
for (var subscription in subscriptions) {
// 월 환산 비용 × 12 = 연간 비용
final annualPrice = subscription.currentPrice * 12;
final converted = await _exchangeRateService.convertBetweenCurrencies(
annualPrice,
subscription.currency,
defaultCurrency,
);
total += converted ?? annualPrice;
}
return total;
}
/// 구독의 월 비용을 표시 형식에 맞게 변환 (언어별 통화)
static Future<String> formatSubscriptionAmountWithLocale(
SubscriptionModel subscription, String locale) async {
final price = subscription.currentPrice;
// 구독 단위 캐시 키 (통화/가격/locale + id)
// 월 환산 금액을 실제 결제 금액으로 역변환
final price = BillingCostUtil.convertFromMonthlyCost(
subscription.currentPrice,
subscription.billingCycle,
);
// 구독 단위 캐시 키 (통화/가격/locale + id + billingCycle)
final decimals =
(subscription.currency == 'KRW' || subscription.currency == 'JPY')
? 0
: 2;
final key =
'subfmt:$locale:${subscription.currency}:${price.toStringAsFixed(decimals)}:${subscription.id}';
'subfmt:$locale:${subscription.currency}:${price.toStringAsFixed(decimals)}:${subscription.id}:${subscription.billingCycle}';
final cached = _fmtCache.get(key);
if (cached != null) return cached;