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