import 'package:freezed_annotation/freezed_annotation.dart'; part 'license_dto.freezed.dart'; part 'license_dto.g.dart'; // 날짜를 YYYY-MM-DD 형식으로 변환하는 헬퍼 함수 String? _dateToJson(DateTime? date) { if (date == null) return null; return '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}'; } // YYYY-MM-DD 형식 문자열을 DateTime으로 변환하는 헬퍼 함수 DateTime? _dateFromJson(String? dateStr) { if (dateStr == null || dateStr.isEmpty) return null; try { // YYYY-MM-DD 형식 파싱 if (dateStr.contains('-') && dateStr.length == 10) { final parts = dateStr.split('-'); return DateTime(int.parse(parts[0]), int.parse(parts[1]), int.parse(parts[2])); } // ISO 8601 형식도 지원 return DateTime.parse(dateStr); } catch (e) { return null; } } // 필수 날짜 필드용 헬퍼 함수 (항상 non-null DateTime 반환) DateTime _requiredDateFromJson(String? dateStr) { if (dateStr == null || dateStr.isEmpty) return DateTime.now(); try { // YYYY-MM-DD 형식 파싱 if (dateStr.contains('-') && dateStr.length == 10) { final parts = dateStr.split('-'); return DateTime(int.parse(parts[0]), int.parse(parts[1]), int.parse(parts[2])); } // ISO 8601 형식도 지원 return DateTime.parse(dateStr); } catch (e) { return DateTime.now(); } } /// 라이선스 전체 정보 DTO @freezed class LicenseDto with _$LicenseDto { const factory LicenseDto({ required int id, @JsonKey(name: 'license_key') required String licenseKey, @JsonKey(name: 'product_name') String? productName, String? vendor, @JsonKey(name: 'license_type') String? licenseType, @JsonKey(name: 'user_count') int? userCount, @JsonKey(name: 'purchase_date', toJson: _dateToJson, fromJson: _dateFromJson) DateTime? purchaseDate, @JsonKey(name: 'expiry_date', toJson: _dateToJson, fromJson: _dateFromJson) DateTime? expiryDate, @JsonKey(name: 'purchase_price') double? purchasePrice, @JsonKey(name: 'company_id') int? companyId, @JsonKey(name: 'branch_id') int? branchId, @JsonKey(name: 'assigned_user_id') int? assignedUserId, String? remark, @JsonKey(name: 'is_active') required bool isActive, @JsonKey(name: 'created_at') required DateTime createdAt, @JsonKey(name: 'updated_at') required DateTime updatedAt, // 추가 필드 (조인된 데이터) @JsonKey(name: 'company_name') String? companyName, @JsonKey(name: 'branch_name') String? branchName, @JsonKey(name: 'assigned_user_name') String? assignedUserName, }) = _LicenseDto; factory LicenseDto.fromJson(Map json) => _$LicenseDtoFromJson(json); } /// 라이선스 목록 응답 DTO @freezed class LicenseListResponseDto with _$LicenseListResponseDto { const factory LicenseListResponseDto({ required List items, required int total, required int page, @JsonKey(name: 'per_page') required int perPage, @JsonKey(name: 'total_pages') required int totalPages, }) = _LicenseListResponseDto; factory LicenseListResponseDto.fromJson(Map json) => _$LicenseListResponseDtoFromJson(json); } /// 만료 예정 라이선스 DTO @freezed class ExpiringLicenseDto with _$ExpiringLicenseDto { const factory ExpiringLicenseDto({ required int id, @JsonKey(name: 'license_key') required String licenseKey, @JsonKey(name: 'product_name') String? productName, String? vendor, @JsonKey(name: 'expiry_date', fromJson: _requiredDateFromJson) required DateTime expiryDate, @JsonKey(name: 'days_until_expiry') required int daysUntilExpiry, @JsonKey(name: 'assigned_user_id') int? assignedUserId, @JsonKey(name: 'company_id') int? companyId, @JsonKey(name: 'company_name') String? companyName, @JsonKey(name: 'assigned_user_name') String? assignedUserName, @JsonKey(name: 'is_active', defaultValue: true) bool? isActive, }) = _ExpiringLicenseDto; factory ExpiringLicenseDto.fromJson(Map json) => _$ExpiringLicenseDtoFromJson(json); } /// 만료 예정 라이선스 목록 응답 DTO @freezed class ExpiringLicenseListDto with _$ExpiringLicenseListDto { const factory ExpiringLicenseListDto({ required List items, required int total, required int page, @JsonKey(name: 'per_page') required int perPage, @JsonKey(name: 'total_pages') required int totalPages, }) = _ExpiringLicenseListDto; factory ExpiringLicenseListDto.fromJson(Map json) => _$ExpiringLicenseListDtoFromJson(json); }