124 lines
3.8 KiB
Dart
124 lines
3.8 KiB
Dart
import 'package:flutter/material.dart';
|
|
import '../models/category_model.dart';
|
|
import '../models/transaction_model.dart';
|
|
import '../db/database_helper.dart';
|
|
import '../utils/logger.dart';
|
|
|
|
class ExpenseProvider with ChangeNotifier {
|
|
List<TransactionModel> _transactions = [];
|
|
List<Category> _categories = [];
|
|
bool _isLoading = false;
|
|
|
|
List<TransactionModel> get transactions => _transactions;
|
|
List<Category> get categories => _categories;
|
|
bool get isLoading => _isLoading;
|
|
|
|
Future<void> loadData() async {
|
|
_isLoading = true;
|
|
notifyListeners();
|
|
|
|
try {
|
|
_categories = await DatabaseHelper.instance.readAllCategories();
|
|
_transactions = await DatabaseHelper.instance.readAllTransactions();
|
|
Logger.log('Data loaded successfully: ${_transactions.length} transactions, ${_categories.length} categories');
|
|
} catch (e, stack) {
|
|
Logger.error('Failed to load data', error: e, stackTrace: stack);
|
|
} finally {
|
|
_isLoading = false;
|
|
notifyListeners();
|
|
}
|
|
}
|
|
|
|
Future<void> addTransaction(TransactionModel transaction) async {
|
|
try {
|
|
await DatabaseHelper.instance.createTransaction(transaction);
|
|
_transactions.insert(0, transaction); // Insert at the beginning
|
|
Logger.log('Transaction added: ${transaction.id}');
|
|
notifyListeners();
|
|
} catch (e, stack) {
|
|
Logger.error('Failed to add transaction', error: e, stackTrace: stack);
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
Future<void> deleteTransaction(String id) async {
|
|
try {
|
|
await DatabaseHelper.instance.deleteTransaction(id);
|
|
_transactions.removeWhere((t) => t.id == id);
|
|
Logger.log('Transaction deleted: $id');
|
|
notifyListeners();
|
|
} catch (e, stack) {
|
|
Logger.error('Failed to delete transaction', error: e, stackTrace: stack);
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
// Category Management
|
|
Future<void> addCategory(Category category) async {
|
|
try {
|
|
await DatabaseHelper.instance.createCategory(category);
|
|
Logger.log('Category added: ${category.name}');
|
|
await loadCategories();
|
|
} catch (e, stack) {
|
|
Logger.error('Failed to add category', error: e, stackTrace: stack);
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
Future<void> updateCategory(Category category) async {
|
|
try {
|
|
await DatabaseHelper.instance.updateCategory(category);
|
|
Logger.log('Category updated: ${category.id}');
|
|
await loadCategories();
|
|
} catch (e, stack) {
|
|
Logger.error('Failed to update category', error: e, stackTrace: stack);
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
Future<void> deleteCategory(int id) async {
|
|
try {
|
|
await DatabaseHelper.instance.deleteCategory(id);
|
|
Logger.log('Category deleted: $id');
|
|
await loadCategories();
|
|
} catch (e, stack) {
|
|
Logger.error('Failed to delete category', error: e, stackTrace: stack);
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
Future<void> loadCategories() async {
|
|
try {
|
|
_categories = await DatabaseHelper.instance.readAllCategories();
|
|
notifyListeners();
|
|
} catch (e, stack) {
|
|
Logger.error('Failed to load categories', error: e, stackTrace: stack);
|
|
}
|
|
}
|
|
|
|
Category getCategoryById(int id) {
|
|
return _categories.firstWhere((c) => c.id == id, orElse: () => Category(name: '未知', type: 'expense', icon: 'help', color: 0xFF9E9E9E));
|
|
}
|
|
|
|
double get totalIncome {
|
|
return _transactions
|
|
.where((t) => t.type == 'income')
|
|
.fold(0.0, (sum, item) => sum + item.amount);
|
|
}
|
|
|
|
double get totalExpense {
|
|
return _transactions
|
|
.where((t) => t.type == 'expense')
|
|
.fold(0.0, (sum, item) => sum + item.amount);
|
|
}
|
|
|
|
// Helper to get hierarchical categories
|
|
List<Category> get rootCategories {
|
|
return _categories.where((c) => c.parentId == null).toList();
|
|
}
|
|
|
|
List<Category> getSubCategories(int parentId) {
|
|
return _categories.where((c) => c.parentId == parentId).toList();
|
|
}
|
|
}
|