LCOV - code coverage report
Current view: top level - lib/models - subscription_model.dart Coverage Total Hit
Test: lcov.info Lines: 100.0 % 92 92
Test Date: 2025-08-12 03:21:51 Functions: - 0 0

            Line data    Source code
       1              : 
       2              : /// 구독 플랜 타입
       3              : enum SubscriptionPlanType {
       4              :   free,      // 무료 플랜
       5              :   basic,     // 기본 유료 플랜
       6              :   premium,   // 프리미엄 플랜
       7              :   enterprise // 기업용 플랜
       8              : }
       9              : 
      10              : /// 구독 상태
      11              : enum SubscriptionStatus {
      12              :   active,    // 활성화 상태
      13              :   canceled,  // 취소됨 (아직 만료 안됨)
      14              :   expired,   // 만료됨
      15              :   pending,   // 결제 대기 중
      16              :   failed     // 결제 실패
      17              : }
      18              : 
      19              : /// 구독 모델
      20              : class Subscription {
      21              :   final String id;
      22              :   final String userId;
      23              :   final String? clubId;
      24              :   final SubscriptionPlanType planType;
      25              :   final SubscriptionStatus status;
      26              :   final DateTime startDate;
      27              :   final DateTime endDate;
      28              :   final double price;
      29              :   final String currency;
      30              :   final bool autoRenew;
      31              :   final Map<String, dynamic>? features;
      32              :   final String? paymentMethod;
      33              :   final String? transactionId;
      34              :   final DateTime createdAt;
      35              :   final DateTime updatedAt;
      36              : 
      37            3 :   Subscription({
      38              :     required this.id,
      39              :     required this.userId,
      40              :     this.clubId,
      41              :     required this.planType,
      42              :     required this.status,
      43              :     required this.startDate,
      44              :     required this.endDate,
      45              :     required this.price,
      46              :     required this.currency,
      47              :     required this.autoRenew,
      48              :     this.features,
      49              :     this.paymentMethod,
      50              :     this.transactionId,
      51              :     required this.createdAt,
      52              :     required this.updatedAt,
      53              :   });
      54              : 
      55              :   /// JSON에서 구독 객체 생성
      56            3 :   factory Subscription.fromJson(Map<String, dynamic> json) {
      57            3 :     return Subscription(
      58            3 :       id: json['id'],
      59            3 :       userId: json['userId'],
      60            3 :       clubId: json['clubId'],
      61            3 :       planType: SubscriptionPlanType.values.firstWhere(
      62           18 :         (e) => e.toString().split('.').last == json['planType'],
      63            1 :         orElse: () => SubscriptionPlanType.free,
      64              :       ),
      65            3 :       status: SubscriptionStatus.values.firstWhere(
      66           18 :         (e) => e.toString().split('.').last == json['status'],
      67            1 :         orElse: () => SubscriptionStatus.expired,
      68              :       ),
      69            6 :       startDate: DateTime.parse(json['startDate']),
      70            6 :       endDate: DateTime.parse(json['endDate']),
      71            6 :       price: json['price'].toDouble(),
      72            3 :       currency: json['currency'],
      73            3 :       autoRenew: json['autoRenew'] ?? false,
      74            3 :       features: json['features'],
      75            3 :       paymentMethod: json['paymentMethod'],
      76            3 :       transactionId: json['transactionId'],
      77            6 :       createdAt: DateTime.parse(json['createdAt']),
      78            6 :       updatedAt: DateTime.parse(json['updatedAt']),
      79              :     );
      80              :   }
      81              : 
      82              :   /// 구독 객체를 JSON으로 변환
      83            1 :   Map<String, dynamic> toJson() {
      84            1 :     return {
      85            1 :       'id': id,
      86            1 :       'userId': userId,
      87            1 :       'clubId': clubId,
      88            4 :       'planType': planType.toString().split('.').last,
      89            4 :       'status': status.toString().split('.').last,
      90            2 :       'startDate': startDate.toIso8601String(),
      91            2 :       'endDate': endDate.toIso8601String(),
      92            1 :       'price': price,
      93            1 :       'currency': currency,
      94            1 :       'autoRenew': autoRenew,
      95            1 :       'features': features,
      96            1 :       'paymentMethod': paymentMethod,
      97            1 :       'transactionId': transactionId,
      98            2 :       'createdAt': createdAt.toIso8601String(),
      99            2 :       'updatedAt': updatedAt.toIso8601String(),
     100              :     };
     101              :   }
     102              : 
     103              :   /// 구독이 활성 상태인지 확인
     104            3 :   bool get isActive => status == SubscriptionStatus.active;
     105              : 
     106              :   /// 구독이 만료되었는지 확인
     107            3 :   bool get isExpired => status == SubscriptionStatus.expired || 
     108            3 :                         DateTime.now().isAfter(endDate);
     109              : 
     110              :   /// 구독 남은 일수 계산
     111            1 :   int get daysLeft {
     112            1 :     if (isExpired) return 0;
     113            4 :     return endDate.difference(DateTime.now()).inDays;
     114              :   }
     115              : 
     116              :   /// 구독 플랜 이름 (한글)
     117            1 :   String get planName {
     118            1 :     switch (planType) {
     119            1 :       case SubscriptionPlanType.free:
     120              :         return '무료';
     121            1 :       case SubscriptionPlanType.basic:
     122              :         return '기본';
     123            1 :       case SubscriptionPlanType.premium:
     124              :         return '프리미엄';
     125            1 :       case SubscriptionPlanType.enterprise:
     126              :         return '기업용';
     127              :     }
     128              :   }
     129              : }
     130              : 
     131              : /// 구독 플랜 정보 모델
     132              : class SubscriptionPlan {
     133              :   final SubscriptionPlanType type;
     134              :   final String name;
     135              :   final String description;
     136              :   final double monthlyPrice;
     137              :   final double yearlyPrice;
     138              :   final String currency;
     139              :   final List<String> features;
     140              :   final int maxMembers;
     141              :   final int maxEvents;
     142              :   final bool hasAdvancedStats;
     143              :   final bool hasCustomization;
     144              :   final bool hasPriority;
     145              : 
     146            3 :   SubscriptionPlan({
     147              :     required this.type,
     148              :     required this.name,
     149              :     required this.description,
     150              :     required this.monthlyPrice,
     151              :     required this.yearlyPrice,
     152              :     required this.currency,
     153              :     required this.features,
     154              :     required this.maxMembers,
     155              :     required this.maxEvents,
     156              :     required this.hasAdvancedStats,
     157              :     required this.hasCustomization,
     158              :     required this.hasPriority,
     159              :   });
     160              : 
     161              :   /// JSON에서 구독 플랜 객체 생성
     162            1 :   factory SubscriptionPlan.fromJson(Map<String, dynamic> json) {
     163            1 :     return SubscriptionPlan(
     164            1 :       type: SubscriptionPlanType.values.firstWhere(
     165            6 :         (e) => e.toString().split('.').last == json['type'],
     166            1 :         orElse: () => SubscriptionPlanType.free,
     167              :       ),
     168            1 :       name: json['name'],
     169            1 :       description: json['description'],
     170            2 :       monthlyPrice: json['monthlyPrice'].toDouble(),
     171            2 :       yearlyPrice: json['yearlyPrice'].toDouble(),
     172            1 :       currency: json['currency'],
     173            2 :       features: List<String>.from(json['features']),
     174            1 :       maxMembers: json['maxMembers'],
     175            1 :       maxEvents: json['maxEvents'],
     176            1 :       hasAdvancedStats: json['hasAdvancedStats'] ?? false,
     177            1 :       hasCustomization: json['hasCustomization'] ?? false,
     178            1 :       hasPriority: json['hasPriority'] ?? false,
     179              :     );
     180              :   }
     181              : 
     182              :   /// 구독 플랜 객체를 JSON으로 변환
     183            1 :   Map<String, dynamic> toJson() {
     184            1 :     return {
     185            4 :       'type': type.toString().split('.').last,
     186            1 :       'name': name,
     187            1 :       'description': description,
     188            1 :       'monthlyPrice': monthlyPrice,
     189            1 :       'yearlyPrice': yearlyPrice,
     190            1 :       'currency': currency,
     191            1 :       'features': features,
     192            1 :       'maxMembers': maxMembers,
     193            1 :       'maxEvents': maxEvents,
     194            1 :       'hasAdvancedStats': hasAdvancedStats,
     195            1 :       'hasCustomization': hasCustomization,
     196            1 :       'hasPriority': hasPriority,
     197              :     };
     198              :   }
     199              : 
     200              :   /// 기본 구독 플랜 목록 반환
     201            3 :   static List<SubscriptionPlan> getDefaultPlans() {
     202            3 :     return [
     203            3 :       SubscriptionPlan(
     204              :         type: SubscriptionPlanType.free,
     205              :         name: '무료',
     206              :         description: '소규모 클럽을 위한 기본 기능',
     207              :         monthlyPrice: 0,
     208              :         yearlyPrice: 0,
     209              :         currency: 'KRW',
     210            3 :         features: [
     211              :           '최대 10명 회원 관리',
     212              :           '기본 점수 기록',
     213              :           '간단한 통계',
     214              :         ],
     215              :         maxMembers: 10,
     216              :         maxEvents: 5,
     217              :         hasAdvancedStats: false,
     218              :         hasCustomization: false,
     219              :         hasPriority: false,
     220              :       ),
     221            3 :       SubscriptionPlan(
     222              :         type: SubscriptionPlanType.basic,
     223              :         name: '기본',
     224              :         description: '중소규모 클럽을 위한 확장 기능',
     225              :         monthlyPrice: 9900,
     226              :         yearlyPrice: 99000,
     227              :         currency: 'KRW',
     228            3 :         features: [
     229              :           '최대 30명 회원 관리',
     230              :           '상세 점수 분석',
     231              :           '이벤트 관리',
     232              :           '회원 통계',
     233              :         ],
     234              :         maxMembers: 30,
     235              :         maxEvents: 20,
     236              :         hasAdvancedStats: true,
     237              :         hasCustomization: false,
     238              :         hasPriority: false,
     239              :       ),
     240            3 :       SubscriptionPlan(
     241              :         type: SubscriptionPlanType.premium,
     242              :         name: '프리미엄',
     243              :         description: '대규모 클럽을 위한 고급 기능',
     244              :         monthlyPrice: 19900,
     245              :         yearlyPrice: 199000,
     246              :         currency: 'KRW',
     247            3 :         features: [
     248              :           '무제한 회원 관리',
     249              :           '고급 통계 및 분석',
     250              :           '무제한 이벤트',
     251              :           '맞춤형 보고서',
     252              :           '우선 지원',
     253              :         ],
     254              :         maxMembers: 100,
     255              :         maxEvents: 100,
     256              :         hasAdvancedStats: true,
     257              :         hasCustomization: true,
     258              :         hasPriority: true,
     259              :       ),
     260            3 :       SubscriptionPlan(
     261              :         type: SubscriptionPlanType.enterprise,
     262              :         name: '기업용',
     263              :         description: '프로 클럽 및 단체를 위한 맞춤형 솔루션',
     264              :         monthlyPrice: 49900,
     265              :         yearlyPrice: 499000,
     266              :         currency: 'KRW',
     267            3 :         features: [
     268              :           '무제한 회원 및 이벤트',
     269              :           '전문가 수준 분석',
     270              :           '맞춤형 기능',
     271              :           '전담 지원',
     272              :           'API 액세스',
     273              :         ],
     274              :         maxMembers: 1000,
     275              :         maxEvents: 1000,
     276              :         hasAdvancedStats: true,
     277              :         hasCustomization: true,
     278              :         hasPriority: true,
     279              :       ),
     280              :     ];
     281              :   }
     282              : }
        

Generated by: LCOV version 2.3.1-1