This commit is contained in:
2026-03-29 14:16:17 +03:00
parent 2fc1d3e200
commit 31dc972e52
4 changed files with 381 additions and 25 deletions
+6 -1
View File
@@ -30,10 +30,15 @@ class AddTransactionState {
});
factory AddTransactionState.fromTransaction(Transaction tx) {
// Override type to transfer when category is 'Transfer'
final resolvedType = (tx.category == 'Transfer')
? TransactionType.transfer
: tx.type;
return AddTransactionState(
amount: tx.amount,
category: tx.category,
type: tx.type,
type: resolvedType,
date: tx.date,
note: tx.note ?? '',
editingId: tx.id,
+79 -1
View File
@@ -1,3 +1,4 @@
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
@@ -75,6 +76,30 @@ class _AddTransactionScreenState extends ConsumerState<AddTransactionScreen>
if (widget.initial != null) {
_amountController.text = widget.initial!.amount.toString();
_noteController.text = widget.initial!.note ?? '';
// Pre-populate toAccountId when opening Transfer for edit
if (widget.initial!.category == 'Transfer') {
WidgetsBinding.instance.addPostFrameCallback((_) {
final allTxs = ref.read(transactionsProvider).valueOrNull ?? [];
final counterpart = allTxs.firstWhereOrNull(
(t) =>
t.category == 'Transfer' &&
t.type == TransactionType.income &&
t.amount == widget.initial!.amount &&
t.date.year == widget.initial!.date.year &&
t.date.month == widget.initial!.date.month &&
t.date.day == widget.initial!.date.day &&
t.date.hour == widget.initial!.date.hour &&
t.date.minute == widget.initial!.date.minute &&
t.note == widget.initial!.note,
);
if (counterpart != null) {
ref
.read(addTransactionProvider(widget.initial).notifier)
.setToAccountId(counterpart.accountId);
}
});
}
} else {
WidgetsBinding.instance.addPostFrameCallback((_) {
final activeAccount = ref.read(activeAccountProvider);
@@ -207,6 +232,58 @@ class _AddTransactionScreenState extends ConsumerState<AddTransactionScreen>
? state.overrideCurrencyCode
: curr.code;
if (state.isEditing) {
// Update both sides of the transfer pair
// Update the expense side (widget.initial = expense record)
final updatedExpense = Transaction(
id: widget.initial!.id,
amount: amount,
category: 'Transfer',
type: TransactionType.expense,
date: finalDateTime,
note: note,
currency: currency,
currencyCode: currencyCode,
accountId: widget.initial!.accountId, // locked, unchanged
);
await ref.read(transactionsProvider.notifier).update(updatedExpense);
// Find and update the income counterpart
final allTxs = ref.read(transactionsProvider).valueOrNull ?? [];
final counterpart = allTxs.firstWhereOrNull(
(t) =>
t.category == 'Transfer' &&
t.type == TransactionType.income &&
t.accountId == state.toAccountId &&
t.amount ==
widget.initial!.amount && // match by original amount
t.date.year == widget.initial!.date.year &&
t.date.month == widget.initial!.date.month &&
t.date.day == widget.initial!.date.day &&
t.date.hour == widget.initial!.date.hour &&
t.date.minute == widget.initial!.date.minute &&
t.note == widget.initial!.note,
);
if (counterpart != null) {
final updatedIncome = Transaction(
id: counterpart.id,
amount: amount, // updated amount
category: 'Transfer',
type: TransactionType.income,
date: finalDateTime,
note: note,
currency: currency, // updated currency
currencyCode: currencyCode,
accountId: counterpart.accountId, // locked, unchanged
);
await ref.read(transactionsProvider.notifier).update(updatedIncome);
}
if (mounted) context.pop();
return;
}
final expense = Transaction(
id: _uuid.v4(),
amount: amount,
@@ -378,8 +455,9 @@ class _AddTransactionScreenState extends ConsumerState<AddTransactionScreen>
final isDark = Theme.of(context).brightness == Brightness.dark;
final isEditing = state.isEditing;
final activeAccount = ref.watch(activeAccountProvider);
final isAccountLocked = activeAccount != null;
final isTransfer = state.type == TransactionType.transfer;
final isEditingTransfer = isEditing && isTransfer;
final isAccountLocked = activeAccount != null || isEditingTransfer;
return Scaffold(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,