249 lines
6.7 KiB
Dart
249 lines
6.7 KiB
Dart
/// 결제 주기에 따른 비용 변환 유틸리티
|
|
class BillingCostUtil {
|
|
/// 결제 주기별 비용을 월 비용으로 변환
|
|
///
|
|
/// [amount]: 입력된 비용
|
|
/// [billingCycle]: 결제 주기 ('monthly', 'yearly', 'quarterly', 'half-yearly' 등)
|
|
///
|
|
/// Returns: 월 환산 비용
|
|
static double convertToMonthlyCost(double amount, String billingCycle) {
|
|
final normalizedCycle = _normalizeBillingCycle(billingCycle);
|
|
|
|
switch (normalizedCycle) {
|
|
case 'monthly':
|
|
return amount;
|
|
case 'yearly':
|
|
return amount / 12;
|
|
case 'quarterly':
|
|
return amount / 3;
|
|
case 'half-yearly':
|
|
return amount / 6;
|
|
case 'weekly':
|
|
return amount * 4.33; // 평균 주당 4.33주
|
|
default:
|
|
return amount; // 알 수 없는 주기는 그대로 반환
|
|
}
|
|
}
|
|
|
|
/// 월 비용을 결제 주기별 비용으로 역변환
|
|
///
|
|
/// [monthlyCost]: 월 비용
|
|
/// [billingCycle]: 결제 주기
|
|
///
|
|
/// Returns: 해당 주기의 실제 결제 금액
|
|
static double convertFromMonthlyCost(double monthlyCost, String billingCycle) {
|
|
final normalizedCycle = _normalizeBillingCycle(billingCycle);
|
|
|
|
switch (normalizedCycle) {
|
|
case 'monthly':
|
|
return monthlyCost;
|
|
case 'yearly':
|
|
return monthlyCost * 12;
|
|
case 'quarterly':
|
|
return monthlyCost * 3;
|
|
case 'half-yearly':
|
|
return monthlyCost * 6;
|
|
case 'weekly':
|
|
return monthlyCost / 4.33;
|
|
default:
|
|
return monthlyCost;
|
|
}
|
|
}
|
|
|
|
/// 결제 주기를 정규화된 영어 키값으로 변환
|
|
static String _normalizeBillingCycle(String cycle) {
|
|
switch (cycle.toLowerCase()) {
|
|
case 'monthly':
|
|
case '월간':
|
|
case '매월':
|
|
case '月間':
|
|
case '月付':
|
|
case '每月':
|
|
case '毎月':
|
|
return 'monthly';
|
|
|
|
case 'yearly':
|
|
case 'annual':
|
|
case 'annually':
|
|
case '연간':
|
|
case '매년':
|
|
case '年間':
|
|
case '年付':
|
|
case '每年':
|
|
return 'yearly';
|
|
|
|
case 'quarterly':
|
|
case 'quarter':
|
|
case '분기별':
|
|
case '분기':
|
|
case '季付':
|
|
case '季度付':
|
|
case '四半期':
|
|
case '每季度':
|
|
return 'quarterly';
|
|
|
|
case 'half-yearly':
|
|
case 'half yearly':
|
|
case 'semiannual':
|
|
case 'semi-annual':
|
|
case '반기별':
|
|
case '半年付':
|
|
case '半年払い':
|
|
case '半年ごと':
|
|
case '每半年':
|
|
return 'half-yearly';
|
|
|
|
case 'weekly':
|
|
case '주간':
|
|
case '週間':
|
|
case '周付':
|
|
case '每周':
|
|
return 'weekly';
|
|
|
|
default:
|
|
return 'monthly';
|
|
}
|
|
}
|
|
|
|
/// 결제 주기의 배수 반환 (월 기준)
|
|
///
|
|
/// 예: yearly = 12, quarterly = 3
|
|
static double getBillingCycleMultiplier(String billingCycle) {
|
|
final normalizedCycle = _normalizeBillingCycle(billingCycle);
|
|
|
|
switch (normalizedCycle) {
|
|
case 'monthly':
|
|
return 1.0;
|
|
case 'yearly':
|
|
return 12.0;
|
|
case 'quarterly':
|
|
return 3.0;
|
|
case 'half-yearly':
|
|
return 6.0;
|
|
case 'weekly':
|
|
return 1 / 4.33;
|
|
default:
|
|
return 1.0;
|
|
}
|
|
}
|
|
|
|
/// 다음 결제일에서 이전 결제일 계산
|
|
///
|
|
/// [nextBillingDate]: 다음 결제 예정일
|
|
/// [billingCycle]: 결제 주기
|
|
///
|
|
/// Returns: 이전 결제일 (마지막으로 결제가 발생한 날짜)
|
|
static DateTime getLastBillingDate(
|
|
DateTime nextBillingDate, String billingCycle) {
|
|
final normalizedCycle = _normalizeBillingCycle(billingCycle);
|
|
|
|
switch (normalizedCycle) {
|
|
case 'yearly':
|
|
return DateTime(
|
|
nextBillingDate.year - 1,
|
|
nextBillingDate.month,
|
|
nextBillingDate.day,
|
|
);
|
|
case 'half-yearly':
|
|
return DateTime(
|
|
nextBillingDate.month <= 6
|
|
? nextBillingDate.year - 1
|
|
: nextBillingDate.year,
|
|
nextBillingDate.month <= 6
|
|
? nextBillingDate.month + 6
|
|
: nextBillingDate.month - 6,
|
|
nextBillingDate.day,
|
|
);
|
|
case 'quarterly':
|
|
return DateTime(
|
|
nextBillingDate.month <= 3
|
|
? nextBillingDate.year - 1
|
|
: nextBillingDate.year,
|
|
nextBillingDate.month <= 3
|
|
? nextBillingDate.month + 9
|
|
: nextBillingDate.month - 3,
|
|
nextBillingDate.day,
|
|
);
|
|
case 'monthly':
|
|
return DateTime(
|
|
nextBillingDate.month == 1
|
|
? nextBillingDate.year - 1
|
|
: nextBillingDate.year,
|
|
nextBillingDate.month == 1 ? 12 : nextBillingDate.month - 1,
|
|
nextBillingDate.day,
|
|
);
|
|
case 'weekly':
|
|
return nextBillingDate.subtract(const Duration(days: 7));
|
|
default:
|
|
return DateTime(
|
|
nextBillingDate.month == 1
|
|
? nextBillingDate.year - 1
|
|
: nextBillingDate.year,
|
|
nextBillingDate.month == 1 ? 12 : nextBillingDate.month - 1,
|
|
nextBillingDate.day,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// 특정 월에 결제가 발생하는지 확인
|
|
///
|
|
/// [nextBillingDate]: 다음 결제 예정일
|
|
/// [billingCycle]: 결제 주기
|
|
/// [targetYear]: 확인할 연도
|
|
/// [targetMonth]: 확인할 월 (1-12)
|
|
///
|
|
/// Returns: 해당 월에 결제가 발생하면 true
|
|
static bool hasBillingInMonth(
|
|
DateTime nextBillingDate,
|
|
String billingCycle,
|
|
int targetYear,
|
|
int targetMonth,
|
|
) {
|
|
final normalizedCycle = _normalizeBillingCycle(billingCycle);
|
|
|
|
// 주간 결제는 매주 발생하므로 항상 true
|
|
if (normalizedCycle == 'weekly') {
|
|
return true;
|
|
}
|
|
|
|
// 월간 결제는 매월 발생하므로 항상 true
|
|
if (normalizedCycle == 'monthly') {
|
|
return true;
|
|
}
|
|
|
|
// 결제 주기에 따른 개월 수
|
|
final cycleMonths = _getCycleMonths(normalizedCycle);
|
|
|
|
// 결제 발생 월 계산 (nextBillingDate 기준으로 역산)
|
|
final billingMonth = nextBillingDate.month;
|
|
|
|
// 대상 월이 결제 발생 월과 일치하는지 확인
|
|
// 예: 연간 결제(1월), targetMonth = 1 → true
|
|
// 예: 연간 결제(1월), targetMonth = 2 → false
|
|
for (int i = 0; i < 12; i += cycleMonths) {
|
|
final checkMonth = ((billingMonth - 1 + i) % 12) + 1;
|
|
if (checkMonth == targetMonth) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// 결제 주기별 개월 수 반환
|
|
static int _getCycleMonths(String normalizedCycle) {
|
|
switch (normalizedCycle) {
|
|
case 'yearly':
|
|
return 12;
|
|
case 'half-yearly':
|
|
return 6;
|
|
case 'quarterly':
|
|
return 3;
|
|
case 'monthly':
|
|
return 1;
|
|
default:
|
|
return 1;
|
|
}
|
|
}
|
|
}
|