379 lines
11 KiB
Dart
379 lines
11 KiB
Dart
class Category {
|
|
final int id;
|
|
final String name;
|
|
final String? iconName;
|
|
|
|
Category({required this.id, required this.name, this.iconName});
|
|
|
|
factory Category.fromJson(Map<String, dynamic> json) {
|
|
return Category(
|
|
id: json['id'],
|
|
name: json['name'],
|
|
iconName: json['iconName'],
|
|
);
|
|
}
|
|
|
|
Map<String, dynamic> toJson() => {'name': name, 'iconName': iconName};
|
|
}
|
|
|
|
|
|
class TransactionItem {
|
|
final int? id;
|
|
final String name;
|
|
final double amount;
|
|
|
|
TransactionItem({this.id, required this.name, required this.amount});
|
|
|
|
factory TransactionItem.fromJson(Map<String, dynamic> json) {
|
|
return TransactionItem(
|
|
id: json['id'],
|
|
name: json['name'],
|
|
amount: (json['amount'] is int) ? (json['amount'] as int).toDouble() : json['amount'],
|
|
);
|
|
}
|
|
|
|
Map<String, dynamic> toJson() => {
|
|
'name': name,
|
|
'amount': amount,
|
|
};
|
|
}
|
|
|
|
class TransactionAttachment {
|
|
final int id;
|
|
final String fileName;
|
|
final String filePath;
|
|
final String contentType;
|
|
|
|
TransactionAttachment({required this.id, required this.fileName, required this.filePath, required this.contentType});
|
|
|
|
factory TransactionAttachment.fromJson(Map<String, dynamic> json) {
|
|
return TransactionAttachment(
|
|
id: json['id'],
|
|
fileName: json['fileName'],
|
|
filePath: json['filePath'],
|
|
contentType: json['contentType'],
|
|
);
|
|
}
|
|
}
|
|
|
|
class Transaction {
|
|
final int id;
|
|
final int? categoryId;
|
|
final int? fromWalletId;
|
|
final int? toWalletId;
|
|
final String? type; // 'INCOME' or 'EXPENSE' or 'INVESTMENT' (kept for backward compatibility during migration)
|
|
final double amount;
|
|
final DateTime date;
|
|
final String? description;
|
|
final String? notes;
|
|
final String? investmentStatus;
|
|
final double? maturityAmount;
|
|
final double? profitLoss;
|
|
final DateTime? closingDate;
|
|
final DateTime? dueDate;
|
|
final String? alertSchedule;
|
|
final String? alertTime;
|
|
final List<TransactionItem>? items;
|
|
final List<TransactionAttachment>? attachments;
|
|
|
|
Transaction({
|
|
required this.id,
|
|
this.categoryId,
|
|
this.fromWalletId,
|
|
this.toWalletId,
|
|
this.type,
|
|
required this.amount,
|
|
required this.date,
|
|
this.description,
|
|
this.notes,
|
|
this.investmentStatus,
|
|
this.maturityAmount,
|
|
this.profitLoss,
|
|
this.closingDate,
|
|
this.dueDate,
|
|
this.alertSchedule,
|
|
this.alertTime,
|
|
this.items,
|
|
this.attachments,
|
|
});
|
|
|
|
factory Transaction.fromJson(Map<String, dynamic> json) {
|
|
return Transaction(
|
|
id: json['id'],
|
|
categoryId: json['categoryId'],
|
|
fromWalletId: json['fromWalletId'],
|
|
toWalletId: json['toWalletId'],
|
|
type: json['type'],
|
|
amount: (json['amount'] is int) ? (json['amount'] as int).toDouble() : json['amount'],
|
|
date: DateTime.parse(json['date']),
|
|
description: json['description'],
|
|
notes: json['notes'],
|
|
investmentStatus: json['investmentStatus'],
|
|
maturityAmount: json['maturityAmount'] != null ? ((json['maturityAmount'] is int) ? (json['maturityAmount'] as int).toDouble() : json['maturityAmount']) : null,
|
|
profitLoss: json['profitLoss'] != null ? ((json['profitLoss'] is int) ? (json['profitLoss'] as int).toDouble() : json['profitLoss']) : null,
|
|
closingDate: json['closingDate'] != null ? DateTime.parse(json['closingDate']) : null,
|
|
dueDate: json['dueDate'] != null ? DateTime.parse(json['dueDate']) : null,
|
|
alertSchedule: json['alertSchedule'],
|
|
alertTime: json['alertTime'],
|
|
items: json['items'] != null ? (json['items'] as List).map((i) => TransactionItem.fromJson(i)).toList() : null,
|
|
attachments: json['attachments'] != null ? (json['attachments'] as List).map((i) => TransactionAttachment.fromJson(i)).toList() : null,
|
|
);
|
|
}
|
|
|
|
Map<String, dynamic> toJson() {
|
|
final map = <String, dynamic>{
|
|
'categoryId': categoryId,
|
|
'fromWalletId': fromWalletId,
|
|
'toWalletId': toWalletId,
|
|
'type': type,
|
|
'amount': amount,
|
|
'date': date.toIso8601String().split('T')[0],
|
|
'description': description,
|
|
'notes': notes,
|
|
'investmentStatus': investmentStatus,
|
|
'maturityAmount': maturityAmount,
|
|
'profitLoss': profitLoss,
|
|
'closingDate': closingDate?.toIso8601String().split('T')[0],
|
|
'dueDate': dueDate?.toIso8601String().split('T')[0],
|
|
'alertSchedule': alertSchedule,
|
|
'alertTime': alertTime,
|
|
};
|
|
if (items != null) {
|
|
map['items'] = items!.map((i) => i.toJson()).toList();
|
|
}
|
|
return map;
|
|
}
|
|
}
|
|
|
|
class Budget {
|
|
final int id;
|
|
final int? categoryId;
|
|
final int? walletId;
|
|
final double monthlyLimit;
|
|
final bool isShared;
|
|
|
|
Budget({required this.id, this.categoryId, this.walletId, required this.monthlyLimit, this.isShared = false});
|
|
|
|
factory Budget.fromJson(Map<String, dynamic> json) {
|
|
double limit = 0.0;
|
|
if (json['monthlyLimit'] != null) {
|
|
if (json['monthlyLimit'] is num) {
|
|
limit = (json['monthlyLimit'] as num).toDouble();
|
|
} else if (json['monthlyLimit'] is String) {
|
|
limit = double.tryParse(json['monthlyLimit']) ?? 0.0;
|
|
}
|
|
}
|
|
int parseId(dynamic val, [int defaultVal = 0]) {
|
|
if (val == null) return defaultVal;
|
|
if (val is int) return val;
|
|
if (val is num) return val.toInt();
|
|
if (val is String) return int.tryParse(val) ?? double.tryParse(val)?.toInt() ?? defaultVal;
|
|
return defaultVal;
|
|
}
|
|
|
|
return Budget(
|
|
id: parseId(json['id']),
|
|
categoryId: json['categoryId'] != null ? parseId(json['categoryId']) : null,
|
|
walletId: json['walletId'] != null ? parseId(json['walletId']) : null,
|
|
monthlyLimit: limit,
|
|
isShared: json['isShared'] ?? false,
|
|
);
|
|
}
|
|
|
|
Map<String, dynamic> toJson() => {
|
|
'categoryId': categoryId,
|
|
'walletId': walletId,
|
|
'monthlyLimit': monthlyLimit,
|
|
'isShared': isShared,
|
|
};
|
|
}
|
|
|
|
class RecurringTransaction {
|
|
final int id;
|
|
final int? categoryId;
|
|
final int? fromWalletId;
|
|
final int? toWalletId;
|
|
final String type;
|
|
final double amount;
|
|
final String frequency; // DAILY, WEEKLY, MONTHLY
|
|
final DateTime? nextExecutionDate;
|
|
final DateTime? endDate;
|
|
final String? status;
|
|
final String? description;
|
|
|
|
RecurringTransaction({
|
|
required this.id,
|
|
this.categoryId,
|
|
this.fromWalletId,
|
|
this.toWalletId,
|
|
required this.type,
|
|
required this.amount,
|
|
required this.frequency,
|
|
this.nextExecutionDate,
|
|
this.endDate,
|
|
this.status,
|
|
this.description,
|
|
});
|
|
|
|
factory RecurringTransaction.fromJson(Map<String, dynamic> json) {
|
|
return RecurringTransaction(
|
|
id: json['id'],
|
|
categoryId: json['categoryId'],
|
|
fromWalletId: json['fromWalletId'],
|
|
toWalletId: json['toWalletId'],
|
|
type: json['type'],
|
|
amount: (json['amount'] is int) ? (json['amount'] as int).toDouble() : json['amount'],
|
|
frequency: json['frequency'],
|
|
nextExecutionDate: json['nextExecutionDate'] != null ? DateTime.parse(json['nextExecutionDate']) : null,
|
|
endDate: json['endDate'] != null ? DateTime.parse(json['endDate']) : null,
|
|
status: json['status'],
|
|
description: json['description'],
|
|
);
|
|
}
|
|
|
|
Map<String, dynamic> toJson() {
|
|
return {
|
|
'id': id,
|
|
'categoryId': categoryId,
|
|
'fromWalletId': fromWalletId,
|
|
'toWalletId': toWalletId,
|
|
'type': type,
|
|
'amount': amount,
|
|
'frequency': frequency,
|
|
'nextExecutionDate': nextExecutionDate?.toIso8601String(),
|
|
'endDate': endDate?.toIso8601String(),
|
|
'status': status ?? 'ACTIVE',
|
|
'description': description,
|
|
};
|
|
}
|
|
}
|
|
class Wallet {
|
|
final int id;
|
|
final String name;
|
|
final int ownerId;
|
|
final String? nature;
|
|
final double balance;
|
|
final String? currency;
|
|
final String? icon;
|
|
final String? color;
|
|
final String? subNature;
|
|
final double? creditLimit;
|
|
final double? fixedAmount;
|
|
final String? paymentCycle;
|
|
final int? cycleDate;
|
|
|
|
Wallet({
|
|
required this.id,
|
|
required this.name,
|
|
required this.ownerId,
|
|
this.nature,
|
|
this.balance = 0.0,
|
|
this.currency,
|
|
this.icon,
|
|
this.color,
|
|
this.subNature,
|
|
this.creditLimit,
|
|
this.fixedAmount,
|
|
this.paymentCycle,
|
|
this.cycleDate,
|
|
});
|
|
|
|
factory Wallet.fromJson(Map<String, dynamic> json) {
|
|
int parseId(dynamic val, [int defaultVal = 0]) {
|
|
if (val == null) return defaultVal;
|
|
if (val is int) return val;
|
|
if (val is num) return val.toInt();
|
|
if (val is String) return int.tryParse(val) ?? double.tryParse(val)?.toInt() ?? defaultVal;
|
|
return defaultVal;
|
|
}
|
|
|
|
double parseDouble(dynamic val, [double defaultVal = 0.0]) {
|
|
if (val == null) return defaultVal;
|
|
if (val is num) return val.toDouble();
|
|
if (val is String) return double.tryParse(val) ?? defaultVal;
|
|
return defaultVal;
|
|
}
|
|
|
|
return Wallet(
|
|
id: parseId(json['id']),
|
|
name: json['name'],
|
|
ownerId: parseId(json['ownerId']),
|
|
nature: json['nature'],
|
|
balance: parseDouble(json['balance']),
|
|
currency: json['currency'],
|
|
icon: json['icon'],
|
|
color: json['color'],
|
|
subNature: json['subNature'],
|
|
creditLimit: parseDouble(json['creditLimit']),
|
|
fixedAmount: parseDouble(json['fixedAmount']),
|
|
paymentCycle: json['paymentCycle'],
|
|
cycleDate: json['cycleDate'] != null ? parseId(json['cycleDate']) : null,
|
|
);
|
|
}
|
|
|
|
Map<String, dynamic> toJson() => {
|
|
'name': name,
|
|
'nature': nature,
|
|
'currency': currency,
|
|
'initialBalance': balance, // Note: backend uses initialBalance on creation
|
|
'icon': icon,
|
|
'color': color,
|
|
'subNature': subNature,
|
|
'creditLimit': creditLimit,
|
|
'fixedAmount': fixedAmount,
|
|
'paymentCycle': paymentCycle,
|
|
'cycleDate': cycleDate,
|
|
};
|
|
}
|
|
class WalletInvitation {
|
|
final int id;
|
|
final int walletId;
|
|
final int inviterId;
|
|
final String inviteeEmail;
|
|
final String status;
|
|
final String createdAt;
|
|
|
|
WalletInvitation({
|
|
required this.id,
|
|
required this.walletId,
|
|
required this.inviterId,
|
|
required this.inviteeEmail,
|
|
required this.status,
|
|
required this.createdAt,
|
|
});
|
|
|
|
factory WalletInvitation.fromJson(Map<String, dynamic> json) {
|
|
return WalletInvitation(
|
|
id: json['id'],
|
|
walletId: json['walletId'],
|
|
inviterId: json['inviterId'],
|
|
inviteeEmail: json['inviteeEmail'],
|
|
status: json['status'],
|
|
createdAt: json['createdAt'] ?? '',
|
|
);
|
|
}
|
|
}
|
|
|
|
class WalletMember {
|
|
final int userId;
|
|
final String email;
|
|
final String role;
|
|
final String joinedAt;
|
|
|
|
WalletMember({
|
|
required this.userId,
|
|
required this.email,
|
|
required this.role,
|
|
required this.joinedAt,
|
|
});
|
|
|
|
factory WalletMember.fromJson(Map<String, dynamic> json) {
|
|
return WalletMember(
|
|
userId: json['userId'],
|
|
email: json['email'],
|
|
role: json['role'],
|
|
joinedAt: json['joinedAt'] ?? '',
|
|
);
|
|
}
|
|
}
|