Skip to content

Commit

Permalink
Merge branch 'release/1.2.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
tcrasset committed Jan 9, 2021
2 parents 695342c + 9aa4f18 commit 108f226
Show file tree
Hide file tree
Showing 15 changed files with 247 additions and 139 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# Changelog

## Version 1.1.4
## Version 1.2.1

- FEATURE: Payees are sorted by alphabetical order
- FEATURE: By default, the transactions of the most recently used account are used

## Version 1.2.0

- BUGFIX: Fix bug where you couldn't delete last character when setting budgeted value for a subcategory
- BUGFIX: Changing the name of a subcategory takes effect immediately
Expand Down
17 changes: 17 additions & 0 deletions lib/appState.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class AppState extends ChangeNotifier {
List<BudgetValue> _budgetValues;
List<Budget> _budgets;
Queries queryContext;
Account _mostRecentAccount;

double toBeBudgeted = 0;

Expand All @@ -48,6 +49,7 @@ class AppState extends ChangeNotifier {
UnmodifiableListView<MoneyTransaction> get transactions => UnmodifiableListView(_transactions);
UnmodifiableListView<Budget> get budgets => UnmodifiableListView(_budgets);
UnmodifiableListView<Goal> get goals => UnmodifiableListView(_goals);
Account get mostRecentAccount => _mostRecentAccount ?? _accounts[0];

AppState({@required Queries queryContext}) {
this.queryContext = queryContext;
Expand All @@ -67,9 +69,12 @@ class AppState extends ChangeNotifier {
_budgetValues = await queryContext.getBudgetValues();
_goals = await queryContext.getGoals();

_mostRecentAccount = await getMostRecentAccountUsed();

currentBudgetDate = getDateFromMonthStart(DateTime.now());
currentBudget = _getBudgetByDate(currentBudgetDate);


await computeToBeBudgeted();

notifyListeners();
Expand Down Expand Up @@ -221,6 +226,8 @@ class AppState extends ChangeNotifier {
);
_transactions.add(transaction);

setMostRecentAccountUsed(accountId);

if (transaction.subcatID == Constants.TO_BE_BUDGETED_ID_IN_MONEYTRANSACTION) {
print("Is to be budgeted money transaction");
// Update balance of the account
Expand Down Expand Up @@ -677,4 +684,14 @@ class AppState extends ChangeNotifier {
DateTime storedMaxBudgetDate = await queryContext.getMaxBudgetDateConstant();
return getMonthDifference(currentMaxBudgetDate, storedMaxBudgetDate);
}

void setMostRecentAccountUsed(int accountId){
queryContext.updateMostRecentAccountUsed(accountId);
_mostRecentAccount = accounts.singleWhere((account) => account.id == accountId, orElse: () => null);
}

Future<Account> getMostRecentAccountUsed() async {
int accountId = await queryContext.getMostRecentAccountUsed();
return accounts.singleWhere((account) => account.id == accountId, orElse: () => null);
}
}
1 change: 0 additions & 1 deletion lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import 'package:your_budget/screens/addTransaction/addTransaction.dart';
import 'package:your_budget/screens/addTransaction/addTransactionState.dart';

import 'package:your_budget/screens/budget/budgetPage.dart';
import 'package:your_budget/models/database_provider.dart';
import 'package:your_budget/screens/budget/budgetPageState.dart';
import 'package:your_budget/screens/deleteCategories/DeleteCategoriesState.dart';
import 'package:your_budget/screens/showTransactions/showTransactionsState.dart';
Expand Down
32 changes: 29 additions & 3 deletions lib/models/SQLQueries.dart
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ class SQLQueryClass implements Queries{

Future<DateTime> getStartingBudgetDateConstant() async {
final sql = '''SELECT ${DatabaseConstants.CONSTANT_VALUE} FROM ${DatabaseConstants.constantsTable}
WHERE ${DatabaseConstants.CONSTANT_NAME} == 'STARTING_BUDGET_DATE';''';
WHERE ${DatabaseConstants.CONSTANT_NAME} == '${DatabaseConstants.STARTING_BUDGET_DATE}';''';

final data = await database.rawQuery(sql);
int startingBudgetDateMillisecondsSinceEpoch = int.parse(data[0]['value'].toString());
Expand All @@ -482,7 +482,7 @@ class SQLQueryClass implements Queries{

Future<DateTime> getMaxBudgetDateConstant() async {
final sql = '''SELECT ${DatabaseConstants.CONSTANT_VALUE} FROM ${DatabaseConstants.constantsTable}
WHERE ${DatabaseConstants.CONSTANT_NAME} == 'MAX_BUDGET_DATE';''';
WHERE ${DatabaseConstants.CONSTANT_NAME} == '${DatabaseConstants.MAX_BUDGET_DATE}';''';

final data = await database.rawQuery(sql);
int maxBudgetDateMillisecondsSinceEpoch = int.parse(data[0]['value'].toString());
Expand All @@ -492,11 +492,37 @@ class SQLQueryClass implements Queries{
Future<void> setMaxBudgetDateConstant(DateTime newMaxBudgetDate) async {
final sql = '''UPDATE ${DatabaseConstants.constantsTable}
SET ${DatabaseConstants.CONSTANT_VALUE} = ?
WHERE ${DatabaseConstants.CONSTANT_NAME} == 'MAX_BUDGET_DATE'
WHERE ${DatabaseConstants.CONSTANT_NAME} == '${DatabaseConstants.MAX_BUDGET_DATE}'
;''';

List<dynamic> params = [newMaxBudgetDate.millisecondsSinceEpoch];
final result = await database.rawUpdate(sql, params);
DatabaseProvider.databaseLog('Update maxBudgetDate', sql, null, result, params);
}

@override
Future<void> updateMostRecentAccountUsed(int accountId) async{
// TODO: implement setMostRecentAccountUsed

final sql = '''UPDATE ${DatabaseConstants.constantsTable}
SET ${DatabaseConstants.CONSTANT_VALUE} = ?
WHERE ${DatabaseConstants.CONSTANT_NAME} == '${DatabaseConstants.MOST_RECENT_ACCOUNT}'
;''';

List<dynamic> params = [accountId.toString()];
final result = await database.rawUpdate(sql, params);
DatabaseProvider.databaseLog('Update most recent account used', sql, null, result, params);

}

@override
Future<int> getMostRecentAccountUsed() async {
final sql = '''SELECT ${DatabaseConstants.CONSTANT_VALUE} FROM ${DatabaseConstants.constantsTable}
WHERE ${DatabaseConstants.CONSTANT_NAME} == '${DatabaseConstants.MOST_RECENT_ACCOUNT}';''';

final data = await database.rawQuery(sql);
int accountId = int.parse(data[0]['value'].toString());
print(accountId);
return accountId;
}
}
6 changes: 6 additions & 0 deletions lib/models/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,10 @@ class DatabaseConstants {
static const String BUDGET_VALUE_OUTSIDE = 'budgetvalues_id';
static const String GOAL_ID_OUTSIDE = 'goal_id';


/// Constants
static const String STARTING_BUDGET_DATE = "STARTING_BUDGET_DATE";
static const String MAX_BUDGET_DATE = "MAX_BUDGET_DATE";
static const String MOST_RECENT_ACCOUNT = "MOST_RECENT_ACCOUNT";

}
23 changes: 20 additions & 3 deletions lib/models/database_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@ class DatabaseProvider {
final path = await getDatabasePath('budgetDB');
db = await openDatabase(
path,
version: 1,
version: 2,
onCreate: _onCreate,
onUpgrade: _onUpgrade,
);

return db;
Expand Down Expand Up @@ -203,11 +204,27 @@ class DatabaseProvider {
/// Create the starting budget date based on the first time the user uses the app
String startingDateMillisecondsSinceEpoch =
getDateYMD(DateTime.now()).millisecondsSinceEpoch.toString();
db.rawInsert(CREATE_CONSTANT, ["STARTING_BUDGET_DATE", startingDateMillisecondsSinceEpoch]);
db.rawInsert(CREATE_CONSTANT, [DatabaseConstants.STARTING_BUDGET_DATE, startingDateMillisecondsSinceEpoch]);

/// Create the maximum budget date based on current date + Constants.MAX_NB_MONTHS_AHEAD
String maxBudgetDateMillisecondsSinceEpoch =
getMaxBudgetDate().millisecondsSinceEpoch.toString();
db.rawInsert(CREATE_CONSTANT, ["MAX_BUDGET_DATE", maxBudgetDateMillisecondsSinceEpoch]);
db.rawInsert(CREATE_CONSTANT, [DatabaseConstants.MAX_BUDGET_DATE, maxBudgetDateMillisecondsSinceEpoch]);

///Save account most recently used.
db.rawInsert(CREATE_CONSTANT, [DatabaseConstants.MOST_RECENT_ACCOUNT, "0"]);

}

FutureOr<void> _onUpgrade(Database db, int oldVersion, int newVersion) {
const String CREATE_CONSTANT = '''INSERT INTO ${DatabaseConstants.constantsTable}
(${DatabaseConstants.CONSTANT_NAME}, ${DatabaseConstants.CONSTANT_VALUE})
VALUES(?, ?);''';

if(oldVersion == 1){
///Save account most recently used.
db.rawInsert(CREATE_CONSTANT, [DatabaseConstants.MOST_RECENT_ACCOUNT, "0"]);
print("Upgrading from version 1 to version 2");
}
}
}
4 changes: 4 additions & 0 deletions lib/models/queries.dart
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,8 @@ abstract class Queries {

Future<void> setMaxBudgetDateConstant(DateTime newMaxBudgetDate);

Future<void> updateMostRecentAccountUsed(int accountId);

Future<int> getMostRecentAccountUsed();

}
4 changes: 4 additions & 0 deletions lib/screens/addTransaction/selectValue.dart
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ class SelectValuePageState extends State<SelectValuePage> {
} else
listEntries = widget.listEntries;

if (isPayee){
listEntries.sort((a, b) => a.name.compareTo(b.name));
}

return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
Expand Down
152 changes: 24 additions & 128 deletions lib/screens/budget/budgetPage.dart
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:your_budget/appState.dart';
import 'package:your_budget/models/categories.dart';
import 'package:your_budget/models/constants.dart';
import 'package:your_budget/screens/modifyCategories/ModifyCategories.dart';
import 'package:your_budget/screens/about/aboutScreen.dart';
import 'package:your_budget/screens/budget/budgetPageState.dart';
import 'package:your_budget/screens/budget/components/MainCategoryRow.dart';
import 'package:your_budget/screens/budget/components/SubCategoryRow.dart';
import 'package:your_budget/screens/budget/components/buttonDial.dart';
import 'package:your_budget/screens/budget/components/toBeBudgeted.dart';
import 'package:your_budget/screens/budget/components/dateButtons.dart';
import 'package:your_budget/screens/budget/components/categoriesList.dart';
import 'package:provider/provider.dart';

class BudgetPage extends StatefulWidget {
Expand All @@ -24,8 +23,7 @@ class _BudgetPageState extends State<BudgetPage> {
bool showMenu = true;

//TODO: Settings
void handleSettings() {
}
void handleSettings() {}

void handlePopUpMenuButtonSelected(String selectedItem) async {
if (selectedItem == "About") {
Expand All @@ -35,12 +33,18 @@ class _BudgetPageState extends State<BudgetPage> {
}

void handleModifyCategories() {
Navigator.push(context, MaterialPageRoute(builder: (context) => ModifyCategories()));
Navigator.push(
context, MaterialPageRoute(builder: (context) => ModifyCategories()));
}

@override
Widget build(BuildContext context) {
BudgetPageState buttonDialState = Provider.of<BudgetPageState>(context);
ButtonDial buttonDial = buttonDialState.showButtonDial
? ButtonDial(MediaQuery.of(context).size.height * 0.3,
MediaQuery.of(context).size.width * 0.6)
: null;

print("Budget page build");
return Scaffold(
appBar: AppBar(
Expand All @@ -57,133 +61,25 @@ class _BudgetPageState extends State<BudgetPage> {
icon: Icon(FontAwesomeIcons.checkSquare),
onPressed: handleModifyCategories,
),
PopupMenuButton(
onSelected: handlePopUpMenuButtonSelected,
itemBuilder: (context) => [
PopupMenuItem<String>(
value: "About",
child: Text("About"),
),
],
),
PopupMenuButton(
onSelected: handlePopUpMenuButtonSelected,
itemBuilder: (context) => [
PopupMenuItem<String>(
value: "About",
child: Text("About"),
),
],
),
],
),
)
],
),
body: Column(children: <Widget>[
_DateButtons(), //
_ToBeBudgeted(),
Expanded(child: _CategoriesList()),

buttonDialState.showButtonDial
? ButtonDial(
MediaQuery.of(context).size.height * 0.3, MediaQuery.of(context).size.width * 0.6)
: ButtonDial(0, 0),
DateButtons(), //
ToBeBudgeted(),
Expanded(child: CategoriesList()),
if (buttonDial != null) buttonDial
]));
}
}

class _CategoriesList extends StatefulWidget {
@override
__CategoriesListState createState() => __CategoriesListState();
}

class __CategoriesListState extends State<_CategoriesList> {
final ScrollController _scrollController = ScrollController();

@override
void dispose() {
_scrollController.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
final AppState appState = Provider.of<AppState>(context);
final List<Category> categories = appState.allCategories;

if (categories.isEmpty) {
return Center(
child: CircularProgressIndicator(),
);
}
return Scrollbar(
isAlwaysShown: true,
controller: _scrollController,
child: ListView.separated(
controller: _scrollController,
itemCount: categories.length,
separatorBuilder: (BuildContext context, int index) =>
Divider(height: 1, color: Colors.black12),
itemBuilder: (context, index) {
var item = categories[index];
return (item is MainCategory) ? MainCategoryRow(cat: item) : SubcategoryRow(subcat: item);
},
),
);
}
}

class _ToBeBudgeted extends StatelessWidget {
final TextStyle _textStyle =
TextStyle(color: Colors.black, fontWeight: FontWeight.bold, fontSize: 25.0);

final TextStyle _positiveAmountTextStyle =
new TextStyle(color: Constants.GREEN_COLOR, fontSize: 32.0);
final TextStyle _negativeAmountTextStyle =
new TextStyle(color: Constants.RED_COLOR, fontSize: 32.0);

@override
Widget build(BuildContext context) {
return Container(
height: 50,
child: Row(
children: [
Expanded(
child: Text(
"To be budgeted",
style: _textStyle,
)),
Consumer<AppState>(
builder: (context, appState, child) {
return Text(
appState.toBeBudgeted.toStringAsFixed(2) + " €" ?? "0.00" + " €",
style: appState.toBeBudgeted >= 0
? _positiveAmountTextStyle
: _negativeAmountTextStyle,
);
},
)
],
));
}
}

class _DateButtons extends StatelessWidget {
void handleButtonOnPressed(BuildContext context, AppState appState, bool increment) {
increment ? appState.incrementMonth() : appState.decrementMonth();
BudgetPageState buttonDialState = Provider.of<BudgetPageState>(context, listen: false);
buttonDialState.toggleButtonDial(-1);
}

@override
Widget build(BuildContext context) {
return Consumer<AppState>(builder: (_, appState, __) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () => handleButtonOnPressed(context, appState, false)),
Text("${appState.currentBudget.monthAsString} ${appState.currentBudget.year}",
style: TextStyle(fontSize: 20)),
IconButton(
icon: Icon(Icons.arrow_forward),
onPressed: () => handleButtonOnPressed(context, appState, true))
],
);
});
}
}
Loading

0 comments on commit 108f226

Please sign in to comment.