Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding transactions to account page #152

Merged
merged 5 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 42 additions & 19 deletions lib/custom_widgets/transactions_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,17 @@ class _TransactionsListState extends State<TransactionsList> with Functions {
Widget build(BuildContext context) {
return transactions.isNotEmpty
? SingleChildScrollView(
padding: widget.padding,
child: DefaultContainer(
padding: widget.padding,
child: DefaultContainer(
child: Column(
children: transactions.map((transaction) {
int index = transactions.indexOf(transaction);
bool first =
index == 0 || !transaction.date.isSameDate(transactions[index - 1].date);
bool first = index == 0 ||
!transaction.date
.isSameDate(transactions[index - 1].date);
bool last = index == transactions.length - 1 ||
!transaction.date.isSameDate(transactions[index + 1].date);
!transaction.date
.isSameDate(transactions[index + 1].date);

return Column(
children: [
Expand All @@ -87,7 +89,7 @@ class _TransactionsListState extends State<TransactionsList> with Functions {
}).toList(),
),
),
)
)
: Container(
padding: const EdgeInsets.all(16),
margin: const EdgeInsets.all(16),
Expand Down Expand Up @@ -133,7 +135,10 @@ class TransactionTitle extends StatelessWidget with Functions {
children: [
TextSpan(
text: numToCurrency(total),
style: Theme.of(context).textTheme.bodyLarge!.copyWith(color: color),
style: Theme.of(context)
.textTheme
.bodyLarge!
.copyWith(color: color),
),
TextSpan(
text: "€",
Expand All @@ -155,7 +160,8 @@ class TransactionTitle extends StatelessWidget with Functions {
}

class TransactionRow extends ConsumerWidget with Functions {
const TransactionRow(this.transaction, {this.first = false, this.last = false, super.key});
const TransactionRow(this.transaction,
{this.first = false, this.last = false, super.key});

final Transaction transaction;
final bool first;
Expand All @@ -176,7 +182,8 @@ class TransactionRow extends ConsumerWidget with Functions {
ref
.read(transactionsProvider.notifier)
.transactionUpdateState(transaction)
.whenComplete(() => Navigator.of(context).pushNamed("/add-page"));
.whenComplete(
() => Navigator.of(context).pushNamed("/add-page"));
},
borderRadius: BorderRadius.vertical(
top: first ? const Radius.circular(8) : Radius.zero,
Expand Down Expand Up @@ -216,8 +223,12 @@ class TransactionRow extends ConsumerWidget with Functions {
if (transaction.note != null)
Text(
transaction.note!,
style: Theme.of(context).textTheme.titleLarge!.copyWith(
color: Theme.of(context).colorScheme.primary,
style: Theme.of(context)
.textTheme
.titleLarge!
.copyWith(
color:
Theme.of(context).colorScheme.primary,
),
),
const Spacer(),
Expand All @@ -230,14 +241,18 @@ class TransactionRow extends ConsumerWidget with Functions {
style: Theme.of(context)
.textTheme
.labelLarge!
.copyWith(color: typeToColor(transaction.type)),
.copyWith(
color:
typeToColor(transaction.type)),
),
TextSpan(
text: "€",
style: Theme.of(context)
.textTheme
.labelSmall!
.copyWith(color: typeToColor(transaction.type)),
.copyWith(
color:
typeToColor(transaction.type)),
),
],
),
Expand All @@ -250,17 +265,25 @@ class TransactionRow extends ConsumerWidget with Functions {
if (transaction.categoryName != null)
Text(
transaction.categoryName!,
style: Theme.of(context).textTheme.labelMedium!.copyWith(
color: Theme.of(context).colorScheme.primary,
style: Theme.of(context)
.textTheme
.labelMedium!
.copyWith(
color:
Theme.of(context).colorScheme.primary,
),
),
const Spacer(),
Text(
transaction.type == TransactionType.transfer
? "${transaction.bankAccountName}→${transaction.bankAccountTransferName}"
: transaction.bankAccountName!,
style: Theme.of(context).textTheme.labelMedium!.copyWith(
color: Theme.of(context).colorScheme.primary,
? "${transaction.bankAccountName ?? ''}→${transaction.bankAccountTransferName ?? ''}"
: transaction.bankAccountName ?? '',
style: Theme.of(context)
.textTheme
.labelMedium!
.copyWith(
color:
Theme.of(context).colorScheme.primary,
),
),
],
Expand Down
85 changes: 59 additions & 26 deletions lib/model/bank_account.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:sqflite/sqflite.dart';
import '../database/sossoldi_database.dart';
import 'base_entity.dart';
import 'transaction.dart';
import 'category_transaction.dart';

const String bankAccountTable = 'bankAccount';

Expand Down Expand Up @@ -93,8 +94,9 @@ class BankAccount extends BaseEntity {
BankAccountFields.startingValue: startingValue,
BankAccountFields.active: active ? 1 : 0,
BankAccountFields.mainAccount: mainAccount ? 1 : 0,
BaseEntityFields.createdAt:
update ? createdAt?.toIso8601String() : DateTime.now().toIso8601String(),
BaseEntityFields.createdAt: update
? createdAt?.toIso8601String()
: DateTime.now().toIso8601String(),
BaseEntityFields.updatedAt: DateTime.now().toIso8601String(),
};
}
Expand Down Expand Up @@ -147,7 +149,8 @@ class BankAccountMethods extends SossoldiDatabase {
final db = await database;

final orderByASC = '${BankAccountFields.createdAt} ASC';
final where = '${BankAccountFields.active} = 1 AND (t.${TransactionFields.recurring} = 0 OR t.${TransactionFields.recurring} is NULL)';
final where =
'${BankAccountFields.active} = 1 AND (${TransactionFields.recurring} = 0 OR ${TransactionFields.recurring} is NULL)';

final result = await db.rawQuery('''
SELECT b.*, (b.${BankAccountFields.startingValue} +
Expand Down Expand Up @@ -199,32 +202,36 @@ class BankAccountMethods extends SossoldiDatabase {
Future<int> deleteById(int id) async {
final db = await database;

return await db.delete(bankAccountTable, where: '${BankAccountFields.id} = ?', whereArgs: [id]);
return await db.delete(bankAccountTable,
where: '${BankAccountFields.id} = ?', whereArgs: [id]);
}

Future<int> deactivateById(int id) async {
final db = await database;

return await db.update(
bankAccountTable,
{'active':0},
where: '${BankAccountFields.id} = ?',
whereArgs: [id],
bankAccountTable,
{'active': 0},
where: '${BankAccountFields.id} = ?',
whereArgs: [id],
);
}

Future<num?> getAccountSum(int? id) async {
final db = await database;

//get account infos first
final result = await db.query(bankAccountTable, where:'${BankAccountFields.id} = $id', limit: 1);
final result = await db.query(bankAccountTable,
where: '${BankAccountFields.id} = $id', limit: 1);
final singleObject = result.isNotEmpty ? result[0] : null;

if (singleObject != null) {
num balance = singleObject[BankAccountFields.startingValue] as num;

// get all transactions of that account
final transactionsResult = await db.query(transactionTable, where:'${TransactionFields.idBankAccount} = $id OR ${TransactionFields.idBankAccountTransfer} = $id');
final transactionsResult = await db.query(transactionTable,
where:
'${TransactionFields.idBankAccount} = $id OR ${TransactionFields.idBankAccountTransfer} = $id');

for (var transaction in transactionsResult) {
num amount = transaction[TransactionFields.amount] as num;
Expand Down Expand Up @@ -252,13 +259,40 @@ class BankAccountMethods extends SossoldiDatabase {
}
}

Future<List> accountDailyBalance(int accountId, {
Future<List> getTransactions(int accountId, int numTransactions) async {
final db = await database;

final accountFilter = "${TransactionFields.idBankAccount} = $accountId";

final resultQuery = await db.rawQuery('''
SELECT t.*,
c.${CategoryTransactionFields.name} as ${TransactionFields.categoryName},
c.${CategoryTransactionFields.color} as ${TransactionFields.categoryColor},
c.${CategoryTransactionFields.symbol} as ${TransactionFields.categorySymbol}
FROM
"$transactionTable" as t
LEFT JOIN
$categoryTransactionTable as c ON t.${TransactionFields.idCategory} = c.${CategoryTransactionFields.id}
WHERE
$accountFilter
ORDER BY
${TransactionFields.date} DESC
LIMIT
$numTransactions
''');

return resultQuery;
}

Future<List> accountDailyBalance(
int accountId, {
DateTime? dateRangeStart,
DateTime? dateRangeEnd,
}) async {
final db = await database;

final accountFilter = "(${TransactionFields.idBankAccount} = $accountId OR ${TransactionFields.idBankAccountTransfer} = $accountId)";
final accountFilter =
"(${TransactionFields.idBankAccount} = $accountId OR ${TransactionFields.idBankAccountTransfer} = $accountId)";
final recurrentFilter = "(${TransactionFields.recurring} = 0)";
final periodFilterEnd = dateRangeEnd != null
? "strftime('%Y-%m-%d', ${TransactionFields.date}) < '${dateRangeEnd.toString().substring(0, 10)}'"
Expand All @@ -276,29 +310,28 @@ class BankAccountMethods extends SossoldiDatabase {
GROUP BY day
''');

final statritngValue = await db.rawQuery(
'''
final statritngValue = await db.rawQuery('''
SELECT ${BankAccountFields.startingValue} as Value
FROM $bankAccountTable
WHERE ${BankAccountFields.id} = $accountId
'''
);
''');

double runningTotal = statritngValue[0]['Value'] as double;

var result = resultQuery.map((e) {
runningTotal += double.parse(e['income'].toString()) - double.parse(e['expense'].toString());
return {
"day": e["day"],
"balance": runningTotal
};
}).toList();

if(dateRangeStart != null){
return result.where((element) => dateRangeStart.isBefore(DateTime.parse(element["day"].toString()).add(const Duration(days: 1)))).toList();
runningTotal += double.parse(e['income'].toString()) -
double.parse(e['expense'].toString());
return {"day": e["day"], "balance": runningTotal};
}).toList();

if (dateRangeStart != null) {
return result
.where((element) => dateRangeStart.isBefore(
DateTime.parse(element["day"].toString())
.add(const Duration(days: 1))))
.toList();
}

return result;
}

}
22 changes: 16 additions & 6 deletions lib/pages/account_page/account_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../constants/functions.dart';
import '../../constants/style.dart';
import '../../custom_widgets/line_chart.dart';
import '../../custom_widgets/transactions_list.dart';
import '../../providers/accounts_provider.dart';
import '../../model/transaction.dart';

class AccountPage extends ConsumerStatefulWidget {
const AccountPage({super.key});
Expand All @@ -18,14 +20,17 @@ class _AccountPage extends ConsumerState<AccountPage> with Functions {
@override
Widget build(BuildContext context) {
final account = ref.read(selectedAccountProvider);
final accountTransactions = ref.watch(selectedAccountCurrentMonthDailyBalanceProvider);
final accountTransactions =
ref.watch(selectedAccountCurrentMonthDailyBalanceProvider);
final transactions = ref.watch(selectedAccountLastTransactions);

return Scaffold(
appBar: AppBar(
title: Text(account?.name ?? "", style: const TextStyle(color: white)),
backgroundColor: blue5,
elevation: 0,
),
title:
Text(account?.name ?? "", style: const TextStyle(color: white)),
backgroundColor: blue5,
elevation: 0,
iconTheme: const IconThemeData(color: Colors.white)),
body: SingleChildScrollView(
child: Column(
children: [
Expand Down Expand Up @@ -59,7 +64,12 @@ class _AccountPage extends ConsumerState<AccountPage> with Functions {
],
),
),
// TODO: add list of transactions
Container(
padding: const EdgeInsets.only(top: 40.0),
child: TransactionsList(
transactions: transactions
.map((json) => Transaction.fromJson(json))
.toList())),
],
),
),
Expand Down
Loading
Loading