import '../core/utils/safe_convert.dart'; import 'student.dart'; class CurrencyInfo { final int id; final String name; final String symbol; const CurrencyInfo({ required this.id, required this.name, required this.symbol, }); factory CurrencyInfo.fromJson(Map json) { return CurrencyInfo( id: SafeConvert.toSafeInt(json['id']), name: SafeConvert.toSafeString(json['name'], 'INR'), symbol: SafeConvert.toSafeString(json['symbol'], '₹'), ); } static CurrencyInfo? fromNullableJson(dynamic json) { final map = SafeConvert.toNullableMap(json); if (map == null) return null; return CurrencyInfo.fromJson(map); } } class FeeSummary { final double totalFees; final double totalPaid; final double outstandingBalance; final double overdueAmount; final String paymentStatus; final String? nextDueDate; final String? lastPaymentDate; final String? lastReceiptNumber; final CurrencyInfo? currency; const FeeSummary({ required this.totalFees, required this.totalPaid, required this.outstandingBalance, required this.overdueAmount, required this.paymentStatus, this.nextDueDate, this.lastPaymentDate, this.lastReceiptNumber, this.currency, }); String get currencySymbol => currency?.symbol ?? '₹'; factory FeeSummary.fromJson(Map json) { return FeeSummary( totalFees: SafeConvert.toSafeDouble(json['total_fees']), totalPaid: SafeConvert.toSafeDouble(json['total_paid']), outstandingBalance: SafeConvert.toSafeDouble(json['outstanding_balance']), overdueAmount: SafeConvert.toSafeDouble(json['overdue_amount']), paymentStatus: SafeConvert.toSafeString(json['payment_status'], 'no_dues'), nextDueDate: SafeConvert.toNullableString(json['next_due_date']), lastPaymentDate: SafeConvert.toNullableString(json['last_payment_date']), lastReceiptNumber: SafeConvert.toNullableString(json['last_receipt_number']), currency: CurrencyInfo.fromNullableJson(json['currency']), ); } } class DashboardFeeSummary { final double totalFees; final double totalPaid; final double outstandingBalance; final double overdueAmount; final String paymentStatus; final String? nextDueDate; final String currencySymbol; const DashboardFeeSummary({ required this.totalFees, required this.totalPaid, required this.outstandingBalance, required this.overdueAmount, required this.paymentStatus, this.nextDueDate, this.currencySymbol = '₹', }); factory DashboardFeeSummary.fromJson(Map json) { return DashboardFeeSummary( totalFees: SafeConvert.toSafeDouble(json['total_fees']), totalPaid: SafeConvert.toSafeDouble(json['total_paid']), outstandingBalance: SafeConvert.toSafeDouble(json['outstanding_balance']), overdueAmount: SafeConvert.toSafeDouble(json['overdue_amount']), paymentStatus: SafeConvert.toSafeString(json['payment_status'], 'no_dues'), nextDueDate: SafeConvert.toNullableString(json['next_due_date']), currencySymbol: SafeConvert.toSafeString(json['currency_symbol'], '₹'), ); } } class FeeInvoiceLine { final int id; final String name; final String? category; final double amount; final bool mandatory; const FeeInvoiceLine({ required this.id, required this.name, this.category, required this.amount, required this.mandatory, }); factory FeeInvoiceLine.fromJson(Map json) { return FeeInvoiceLine( id: SafeConvert.toSafeInt(json['id']), name: SafeConvert.toSafeString(json['name']), category: SafeConvert.toNullableString(json['category']), amount: SafeConvert.toSafeDouble(json['amount']), mandatory: SafeConvert.toSafeBool(json['mandatory'], true), ); } } class FeeInvoicePayment { final int id; final String receiptNumber; final String? paymentDate; final String? paymentMethod; final String? paymentMethodLabel; final double amount; final String? referenceNumber; const FeeInvoicePayment({ required this.id, required this.receiptNumber, this.paymentDate, this.paymentMethod, this.paymentMethodLabel, required this.amount, this.referenceNumber, }); factory FeeInvoicePayment.fromJson(Map json) { return FeeInvoicePayment( id: SafeConvert.toSafeInt(json['id']), receiptNumber: SafeConvert.toSafeString(json['receipt_number']), paymentDate: SafeConvert.toNullableString(json['payment_date']), paymentMethod: SafeConvert.toNullableString(json['payment_method']), paymentMethodLabel: SafeConvert.toNullableString(json['payment_method_label']), amount: SafeConvert.toSafeDouble(json['amount']), referenceNumber: SafeConvert.toNullableString(json['reference_number']), ); } } class FeeInvoice { final int id; final String invoiceNumber; final String title; final NamedRecord? academicYear; final NamedRecord? academicTerm; final NamedRecord? semester; final String? assignmentDate; final String? dueDate; final double amount; final double amountPaid; final double amountDue; final String paymentStatus; final String state; final CurrencyInfo? currency; final List lines; final List payments; const FeeInvoice({ required this.id, required this.invoiceNumber, required this.title, this.academicYear, this.academicTerm, this.semester, this.assignmentDate, this.dueDate, required this.amount, required this.amountPaid, required this.amountDue, required this.paymentStatus, required this.state, this.currency, this.lines = const [], this.payments = const [], }); String get currencySymbol => currency?.symbol ?? '₹'; bool get isOverdue => paymentStatus == 'overdue'; bool get isPaid => paymentStatus == 'paid'; bool get isPartial => paymentStatus == 'partial'; factory FeeInvoice.fromJson(Map json) { return FeeInvoice( id: SafeConvert.toSafeInt(json['id']), invoiceNumber: SafeConvert.toSafeString(json['invoice_number']), title: SafeConvert.toSafeString(json['title']), academicYear: NamedRecord.fromNullableJson(json['academic_year']), academicTerm: NamedRecord.fromNullableJson(json['academic_term']), semester: NamedRecord.fromNullableJson(json['semester']), assignmentDate: SafeConvert.toNullableString(json['assignment_date']), dueDate: SafeConvert.toNullableString(json['due_date']), amount: SafeConvert.toSafeDouble(json['amount']), amountPaid: SafeConvert.toSafeDouble(json['amount_paid']), amountDue: SafeConvert.toSafeDouble(json['amount_due']), paymentStatus: SafeConvert.toSafeString(json['payment_status'], 'unpaid'), state: SafeConvert.toSafeString(json['state'], 'draft'), currency: CurrencyInfo.fromNullableJson(json['currency']), lines: SafeConvert.toSafeList( json['lines'], (item) => FeeInvoiceLine.fromJson(SafeConvert.toNullableMap(item) ?? {}), ), payments: SafeConvert.toSafeList( json['payments'], (item) => FeeInvoicePayment.fromJson(SafeConvert.toNullableMap(item) ?? {}), ), ); } } class FeePayment { final int id; final String receiptNumber; final String? paymentDate; final String? paymentMethod; final String paymentMethodLabel; final double amount; final String? referenceNumber; final String? remarks; final String status; final int? invoiceId; final String? invoiceNumber; final CurrencyInfo? currency; const FeePayment({ required this.id, required this.receiptNumber, this.paymentDate, this.paymentMethod, required this.paymentMethodLabel, required this.amount, this.referenceNumber, this.remarks, required this.status, this.invoiceId, this.invoiceNumber, this.currency, }); String get currencySymbol => currency?.symbol ?? '₹'; factory FeePayment.fromJson(Map json) { final invoiceMap = SafeConvert.toNullableMap(json['invoice']); return FeePayment( id: SafeConvert.toSafeInt(json['id']), receiptNumber: SafeConvert.toSafeString(json['receipt_number']), paymentDate: SafeConvert.toNullableString(json['payment_date']), paymentMethod: SafeConvert.toNullableString(json['payment_method']), paymentMethodLabel: SafeConvert.toSafeString(json['payment_method_label'], 'Payment'), amount: SafeConvert.toSafeDouble(json['amount']), referenceNumber: SafeConvert.toNullableString(json['reference_number']), remarks: SafeConvert.toNullableString(json['remarks']), status: SafeConvert.toSafeString(json['status'], 'confirmed'), invoiceId: invoiceMap != null ? SafeConvert.toNullableInt(invoiceMap['id']) : null, invoiceNumber: invoiceMap != null ? SafeConvert.toNullableString(invoiceMap['invoice_number']) : null, currency: CurrencyInfo.fromNullableJson(json['currency']), ); } }