Skip to content

Commit

Permalink
Merge pull request #105 from mikev-cw/main
Browse files Browse the repository at this point in the history
Dashboard account summaries fix
  • Loading branch information
mikev-cw authored Jun 20, 2023
2 parents ba4e177 + 86cf80a commit 124affc
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 58 deletions.
64 changes: 41 additions & 23 deletions lib/custom_widgets/accounts_sum.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import '../constants/functions.dart';
import '../constants/style.dart';
import 'account_modal.dart';

/// This class shows account summaries in dashboard
/// This class shows account summaries in the dashboard
class AccountsSum extends StatelessWidget with Functions {
final BankAccount account;

const AccountsSum({
super.key,
Key? key,
required this.account,
});
}) : super(key: key);

@override
Widget build(BuildContext context) {
Expand All @@ -26,10 +26,10 @@ class AccountsSum extends StatelessWidget with Functions {
boxShadow: [defaultShadow],
),
child: Container(
decoration: BoxDecoration(
color: accountColorList[account.color].withOpacity(0.2),
borderRadius: BorderRadius.circular(8),
),
decoration: BoxDecoration(
color: accountColorList[account.color].withOpacity(0.2),
borderRadius: BorderRadius.circular(8),
),
child: Material(
color: Colors.transparent,
child: InkWell(
Expand All @@ -52,7 +52,7 @@ class AccountsSum extends StatelessWidget with Functions {
children: [
AccountDialog(
accountName: account.name,
amount: account.value,
amount: account.startingValue,
)
],
),
Expand Down Expand Up @@ -84,22 +84,40 @@ class AccountsSum extends StatelessWidget with Functions {
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(account.name, style: Theme.of(context).textTheme.bodyLarge),
RichText(
textScaleFactor: MediaQuery.of(context).textScaleFactor,
text: TextSpan(
children: [
TextSpan(
text: numToCurrency(account.value),
style: Theme.of(context).textTheme.titleSmall,
),
TextSpan(
text: "€",
style: Theme.of(context).textTheme.bodyMedium?.apply(
fontFeatures: [const FontFeature.subscripts()],
FutureBuilder<num?>(
future: BankAccountMethods().getAccountSum(account.id),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
// Show a loading indicator while waiting for the future to complete
return Transform.scale(
scale: 0.5,
child: CircularProgressIndicator(),
);
} else if (snapshot.hasError) {
// Show an error message if the future encounters an error
return Text('Error: ${snapshot.error}');
} else {
// Display the result once the future completes successfully
final accountSum = snapshot.data ?? 0;
return RichText(
textScaleFactor: MediaQuery.of(context).textScaleFactor,
text: TextSpan(
children: [
TextSpan(
text: numToCurrency(accountSum),
style: Theme.of(context).textTheme.titleSmall,
),
TextSpan(
text: "€",
style: Theme.of(context).textTheme.bodyMedium?.apply(
fontFeatures: [const FontFeature.subscripts()],
),
),
],
),
),
],
),
);
}
},
),
],
),
Expand Down
1 change: 0 additions & 1 deletion lib/custom_widgets/transactions_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import '../providers/accounts_provider.dart';
import '../providers/categories_provider.dart';
import '../constants/style.dart';

/// This class shows account summaries in dashboard
class TransactionsList extends StatefulWidget {
final List<Transaction> transactions;

Expand Down
37 changes: 25 additions & 12 deletions lib/database/sossoldi_database.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class SossoldiDatabase {
`${BankAccountFields.name}` $textNotNull,
`${BankAccountFields.symbol}` $textNotNull,
`${BankAccountFields.color}` $integerNotNull,
`${BankAccountFields.value}` $realNotNull,
`${BankAccountFields.startingValue}` $realNotNull,
`${BankAccountFields.active}` $integerNotNull CHECK (${BankAccountFields.active} IN (0, 1)),
`${BankAccountFields.mainAccount}` $integerNotNull CHECK (${BankAccountFields.mainAccount} IN (0, 1)),
`${BankAccountFields.createdAt}` $textNotNull,
Expand Down Expand Up @@ -137,10 +137,10 @@ class SossoldiDatabase {
Future fillDemoData() async {
// Add some fake accounts
await _database?.execute('''
INSERT INTO bankAccount(id, name, symbol, color, value, active, mainAccount, createdAt, updatedAt) VALUES
INSERT INTO bankAccount(id, name, symbol, color, startingValue, active, mainAccount, createdAt, updatedAt) VALUES
(70, "Revolut", 'payments', 1, 1235.10, 1, 1, '${DateTime.now()}', '${DateTime.now()}'),
(71, "N26", 'credit_card', 2, 3823.56, 1, 0, '${DateTime.now()}', '${DateTime.now()}'),
(72, "Fineco", 'account_balance', 3, 0.07, 1, 0, '${DateTime.now()}', '${DateTime.now()}');
(72, "Fineco", 'account_balance', 3, 0.00, 1, 0, '${DateTime.now()}', '${DateTime.now()}');
''');

// Add fake categories
Expand Down Expand Up @@ -174,11 +174,12 @@ class SossoldiDatabase {
// First initialize some config stuff
final rnd = Random();
var accounts = [70,71,72];
var outNotes = ['Grocery', 'Tolls', 'Toys', 'Tobacco', 'Concert', 'Clothing', 'Pizza', 'Drugs', 'Laundry', 'Taxes', 'Health insurance', 'Furniture', 'Car Fuel', 'Train', 'Amazon', 'Delivery', 'Hotel', 'Babysitter', 'Paypal Fees', 'Quingentole trip'];
var outNotes = ['Grocery', 'Tolls', 'Toys', 'Tobacco', 'Concert', 'Clothing', 'Pizza', 'Drugs', 'Laundry', 'Taxes', 'Health insurance', 'Furniture', 'Car Fuel', 'Train', 'Amazon', 'Delivery', 'CHEK dividends', 'Babysitter', 'sono.pove.ro Fees', 'Quingentole trip'];
var categories = [10,11,12,13,14];
int countOfGeneratedTransaction = 5000;
int countOfGeneratedTransaction = 10000;
double maxAmountOfSingleTransaction = 250.00;
int dateInPastMaxRange = 2*365; // we want simulate past 2 years
int dateInPastMaxRange = (countOfGeneratedTransaction / 90 ).round() * 30; // we want simulate about 90 transactions per month
num fakeSalary = 5000;
DateTime now = DateTime.now();

// start building mega-query
Expand All @@ -189,19 +190,29 @@ class SossoldiDatabase {

// Start a loop
for (int i = 0; i < countOfGeneratedTransaction; i++) {
var randomAmount = rnd.nextDouble() * maxAmountOfSingleTransaction;
num randomAmount = 0;

// we are more likely to give low amounts
if (rnd.nextInt(10) < 8) {
randomAmount = rnd.nextDouble() * (19.99 - 1) + 1;
} else {
randomAmount = rnd.nextDouble() * (maxAmountOfSingleTransaction - 100) + 100;
}

var randomType = 'OUT';
var randomAccount = accounts[rnd.nextInt(accounts.length)];
var randomNote = outNotes[rnd.nextInt(outNotes.length)];
var randomCategory = categories[rnd.nextInt(categories.length)];
var idBankAccountTransfer;
DateTime randomDate = now.subtract(Duration(days: rnd.nextInt(dateInPastMaxRange), hours: rnd.nextInt(20), minutes: rnd.nextInt(50)));

if (i % 70 == 0) {
// simulating a transfer every 70 iterations
if (i % (countOfGeneratedTransaction/100) == 0) {
// simulating a transfer every 1% of total iterations
randomType = 'TRSF';
randomNote = '';
randomNote = 'Transfer';
randomAccount = 70; // sender account is hardcoded with the one that receives our fake salary
idBankAccountTransfer = accounts[rnd.nextInt(accounts.length)];
randomAmount = (fakeSalary/100)*70;

// be sure our FROM/TO accounts are not the same
while (idBankAccountTransfer == randomAccount) {
Expand All @@ -214,9 +225,11 @@ class SossoldiDatabase {
}

// add salary every month
for (int i = 0; i < dateInPastMaxRange/30; i++) {
for (int i = 1; i < dateInPastMaxRange/30; i++) {
DateTime randomDate = now.subtract(Duration(days: 30*i));
demoTransactions.add('''('$randomDate', 1550.00, 'IN', 'Salary', 15, 70, null, 0, null, null, null, null, '$randomDate', '$randomDate')''');
var time = randomDate.toLocal();
DateTime salaryDateTime = DateTime(time.year, time.month, 27, time.hour, time.minute, time.second, time.millisecond, time.microsecond);
demoTransactions.add('''('$salaryDateTime', $fakeSalary, 'IN', 'Salary', 15, 70, null, 0, null, null, null, null, '$salaryDateTime', '$salaryDateTime')''');
}

// add some recurring payment too
Expand Down
57 changes: 49 additions & 8 deletions lib/model/bank_account.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:sossoldi/model/transaction.dart';
import 'package:sqflite/sqflite.dart';

import '../database/sossoldi_database.dart';
Expand All @@ -10,7 +11,7 @@ class BankAccountFields extends BaseEntityFields {
static String name = 'name';
static String symbol = 'symbol';
static String color = 'color';
static String value = 'value';
static String startingValue = 'startingValue';
static String active = 'active';
static String mainAccount = 'mainAccount';
static String createdAt = BaseEntityFields.getCreatedAt;
Expand All @@ -21,7 +22,7 @@ class BankAccountFields extends BaseEntityFields {
name,
symbol,
color,
value,
startingValue,
active,
mainAccount,
BaseEntityFields.createdAt,
Expand All @@ -33,7 +34,7 @@ class BankAccount extends BaseEntity {
final String name;
final String symbol;
final int color;
final num value;
final num startingValue;
final bool active;
final bool mainAccount;

Expand All @@ -42,7 +43,7 @@ class BankAccount extends BaseEntity {
required this.name,
required this.symbol,
required this.color,
required this.value,
required this.startingValue,
required this.mainAccount,
required this.active,
DateTime? createdAt,
Expand All @@ -54,7 +55,7 @@ class BankAccount extends BaseEntity {
String? name,
String? symbol,
int? color,
num? value,
num? startingValue,
bool? active,
bool? mainAccount,
DateTime? createdAt,
Expand All @@ -64,7 +65,7 @@ class BankAccount extends BaseEntity {
name: name ?? this.name,
symbol: symbol ?? this.symbol,
color: color ?? this.color,
value: value ?? this.value,
startingValue: startingValue ?? this.startingValue,
active: active ?? this.active,
mainAccount: mainAccount ?? this.mainAccount,
createdAt: createdAt ?? this.createdAt,
Expand All @@ -75,7 +76,7 @@ class BankAccount extends BaseEntity {
name: json[BankAccountFields.name] as String,
symbol: json[BankAccountFields.symbol] as String,
color: json[BankAccountFields.color] as int,
value: json[BankAccountFields.value] as num,
startingValue: json[BankAccountFields.startingValue] as num,
active: json[BankAccountFields.active] == 1 ? true : false,
mainAccount: json[BankAccountFields.mainAccount] == 1 ? true : false,
createdAt: DateTime.parse(json[BaseEntityFields.createdAt] as String),
Expand All @@ -86,7 +87,7 @@ class BankAccount extends BaseEntity {
BankAccountFields.name: name,
BankAccountFields.symbol: symbol,
BankAccountFields.color: color,
BankAccountFields.value: value,
BankAccountFields.startingValue: startingValue,
BankAccountFields.active: active ? 1 : 0,
BankAccountFields.mainAccount: mainAccount ? 1 : 0,
BaseEntityFields.createdAt:
Expand Down Expand Up @@ -185,6 +186,7 @@ class BankAccountMethods extends SossoldiDatabase {

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

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

Expand All @@ -195,4 +197,43 @@ class BankAccountMethods extends SossoldiDatabase {
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 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');

for (var transaction in transactionsResult) {
num amount = transaction[TransactionFields.amount] as num;

switch (transaction[TransactionFields.type]) {
case ('IN'):
balance += amount;
break;
case ('OUT'):
balance -= amount;
break;
case ('TRSF'):
if (transaction[TransactionFields.idBankAccount] == id) {
balance -= amount;
} else {
balance += amount;
}
break;
}
}

return balance;
} else {
return 0;
}
}
}
8 changes: 4 additions & 4 deletions lib/pages/statistics_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ class _StatsPageState extends ConsumerState<StatsPage> with Functions {
double max = 0;
for(var i = 0; i < accounts.length; i++)
{
if (max <= accounts[i].value){max = accounts[i].value.toDouble();}
if (max <= accounts[i].startingValue){max = accounts[i].startingValue.toDouble();}
}
return SizedBox(
height: 50.0,
Expand All @@ -170,7 +170,7 @@ class _StatsPageState extends ConsumerState<StatsPage> with Functions {
),
Expanded(
child: Text(
"${account.value}€",
"${account.startingValue}€",
textAlign: TextAlign.right,
style: Theme.of(context).textTheme.bodySmall?.copyWith(color: blue1),
),
Expand All @@ -184,7 +184,7 @@ class _StatsPageState extends ConsumerState<StatsPage> with Functions {
child: Row(
children: [
Container(
width: MediaQuery.of(context).size.width * 0.9 * (account.value.toDouble()/max),
width: MediaQuery.of(context).size.width * 0.9 * (account.startingValue.toDouble()/max),
decoration: const BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(4.0),
Expand All @@ -194,7 +194,7 @@ class _StatsPageState extends ConsumerState<StatsPage> with Functions {
),
),
Container(
width: MediaQuery.of(context).size.width * 0.9 *(1 - (account.value.toDouble()/max)),
width: MediaQuery.of(context).size.width * 0.9 *(1 - (account.startingValue.toDouble()/max)),
decoration: const BoxDecoration(
borderRadius: BorderRadius.only(
topRight: Radius.circular(4.0),
Expand Down
2 changes: 1 addition & 1 deletion lib/providers/accounts_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class AsyncAccountsNotifier extends AsyncNotifier<List<BankAccount>> {
name: ref.read(accountNameProvider)!,
symbol: ref.read(accountIconProvider),
color: ref.read(accountColorProvider),
value: 0,
startingValue: 0,
active: true,
mainAccount: ref.read(accountMainSwitchProvider),
);
Expand Down
Loading

0 comments on commit 124affc

Please sign in to comment.