Transaction Tracking
DWallet provides comprehensive transaction tracking with categories, wallets, notes, and full CRUD operations.
Overview
Section titled “Overview”Users can record financial transactions with:
- Amount (income or expense)
- Category (food, transport, salary, etc.)
- Wallet (which account)
- Date and time
- Optional notes
Data Model
Section titled “Data Model”File: packages/dwallet_types/lib/src/abstractions/_transaction.dart
abstract class Transaction { String get id; double get amount; TransactionType get type; // income or expense Category get category; String? get note; DateTime get date; Wallet get wallet;}Transaction Types
Section titled “Transaction Types”enum TransactionType { income, expense,}TransactionModel
Section titled “TransactionModel”class TransactionModel implements Transaction { final String id; final double amount; final TransactionType type; final CategoryModel category; final String? note; final DateTime date; final WalletModel wallet;
const TransactionModel({ required this.id, required this.amount, required this.type, required this.category, this.note, required this.date, required this.wallet, });}Categories
Section titled “Categories”File: packages/dwallet_types/lib/src/abstractions/_category.dart
Predefined categories for both income and expense:
Expense Categories
Section titled “Expense Categories”| Category | Icon | Color |
|---|---|---|
| Food & Dining | 🍔 | Orange |
| Transport | 🚗 | Blue |
| Shopping | 🛍️ | Pink |
| Entertainment | 🎬 | Purple |
| Bills & Utilities | 💡 | Yellow |
| Health | 🏥 | Red |
| Education | 📚 | Green |
| Other | 📦 | Gray |
Income Categories
Section titled “Income Categories”| Category | Icon | Color |
|---|---|---|
| Salary | 💰 | Green |
| Freelance | 💻 | Blue |
| Investment | 📈 | Purple |
| Gift | 🎁 | Pink |
| Other | 💵 | Gray |
UI Components
Section titled “UI Components”Transaction Card
Section titled “Transaction Card”File: lib/app/widgets/_transaction_card.dart
TransactionCardWidget( transaction: TransactionModel( id: '1', amount: 50.00, type: TransactionType.expense, category: CategoryMock.food, note: 'Lunch with friends', date: DateTime.now(), wallet: wallet, ),)Features:
- Category icon with color background
- Transaction name/note
- Formatted amount with + or - sign
- Date display
- Swipe to edit/delete
Manage Transaction Modal
Section titled “Manage Transaction Modal”File: lib/app/pages/client/components/_manage_transaction_modal_sheet.dart
Bottom sheet for creating/editing transactions:
showModalBottomSheet( context: context, builder: (_) => ManageTransactionModalSheet( transaction: existingTransaction, // null for new initialType: TransactionType.expense, ),);Form Fields:
- Amount (numeric input with keypad)
- Type toggle (Income/Expense)
- Category selector (grid of icons)
- Wallet selector
- Date picker
- Note (optional text)
Creating a Transaction
Section titled “Creating a Transaction”1. Tap FAB (+) on any screen2. ManageTransactionModalSheet opens3. User enters amount4. Selects type (income/expense)5. Chooses category6. Selects wallet7. Picks date8. Adds optional note9. Taps Save10. Transaction added, wallet balance updatedCode Example
Section titled “Code Example”void _saveTransaction() { final transaction = TransactionModel( id: DateTime.now().toString(), amount: double.parse(_amountController.text), type: _selectedType, category: _selectedCategory, wallet: _selectedWallet, date: _selectedDate, note: _noteController.text.isEmpty ? null : _noteController.text, );
// Add transaction transactions.add(transaction);
// Update wallet balance if (transaction.type == TransactionType.income) { _selectedWallet.balance += transaction.amount; } else { _selectedWallet.balance -= transaction.amount; }
// Save to storage _saveTransactions();}Transaction List Views
Section titled “Transaction List Views”Home View (Recent)
Section titled “Home View (Recent)”Shows 5-10 most recent transactions:
final recentTransactions = transactions .sorted((a, b) => b.date.compareTo(a.date)) .take(5) .toList();Wallet Details
Section titled “Wallet Details”Shows transactions filtered by wallet:
final walletTransactions = transactions .where((t) => t.wallet.id == wallet.id) .sorted((a, b) => b.date.compareTo(a.date)) .toList();All Transactions
Section titled “All Transactions”File: lib/app/pages/client/all_transaction_list/all_transaction_list_view.dart
Complete transaction history with filtering:
- Filter by type (income/expense)
- Filter by category
- Filter by wallet
- Filter by date range
- Search by note
Filtering
Section titled “Filtering”File: lib/app/pages/client/all_transaction_list/components/_filter_modal.dart
class TransactionFilter { final TransactionType? type; final Category? category; final Wallet? wallet; final DateTime? fromDate; final DateTime? toDate;
List<Transaction> apply(List<Transaction> transactions) { return transactions.where((t) { if (type != null && t.type != type) return false; if (category != null && t.category.id != category.id) return false; if (wallet != null && t.wallet.id != wallet.id) return false; if (fromDate != null && t.date.isBefore(fromDate!)) return false; if (toDate != null && t.date.isAfter(toDate!)) return false; return true; }).toList(); }}Editing and Deleting
Section titled “Editing and Deleting”Edit Transaction
Section titled “Edit Transaction”void _editTransaction(Transaction transaction) { // Show modal with existing data showModalBottomSheet( context: context, builder: (_) => ManageTransactionModalSheet( transaction: transaction, ), );}Delete Transaction
Section titled “Delete Transaction”void _deleteTransaction(Transaction transaction) { // Reverse wallet balance change if (transaction.type == TransactionType.income) { transaction.wallet.balance -= transaction.amount; } else { transaction.wallet.balance += transaction.amount; }
// Remove from list transactions.remove(transaction);
// Save changes _saveTransactions();}Customization
Section titled “Customization”Adding New Categories
Section titled “Adding New Categories”- Edit
packages/dwallet_types/lib/src/mocks/_category.dart:
static const travel = CategoryModel( id: 'travel', name: 'Travel', icon: 'airplane', color: Colors.teal, type: TransactionType.expense,);- Add to categories list:
static const List<Category> expenseCategories = [ food, transport, travel, // Add here // ...];Custom Date Formatting
Section titled “Custom Date Formatting”String formatDate(DateTime date) { if (date.isToday) return 'Today'; if (date.isYesterday) return 'Yesterday'; return DateFormat('MMM d, y').format(date);}Best Practices
Section titled “Best Practices”- Validate amounts: Ensure positive numbers
- Require category: Every transaction needs a category
- Default wallet: Pre-select primary wallet
- Default date: Use current date
- Confirm deletes: Show confirmation dialog
- Undo option: Allow undo for recent deletes
- Receipt photos: Optional image attachment
Testing
Section titled “Testing”test('Transaction creation updates wallet balance', () { final wallet = WalletMock.cash(); final initialBalance = wallet.balance;
final transaction = TransactionModel( amount: 100, type: TransactionType.expense, wallet: wallet, // ... );
// Process transaction wallet.balance -= transaction.amount;
expect(wallet.balance, initialBalance - 100);});