Skip to content

Commit

Permalink
Merge pull request #58 from TheAxelander/hotfix
Browse files Browse the repository at this point in the history
Merge changes for version 1.4.1
  • Loading branch information
TheAxelander authored Nov 28, 2021
2 parents 811beb2 + 6ff45bd commit 641f009
Show file tree
Hide file tree
Showing 10 changed files with 181 additions and 14 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

## Custom files
*.db
*.db-shm
*.db-wal
*.DS_Store

# User-specific files
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
### 1.4.1 (2021-11-28)

* [Changed] Handling of Bucket Group creation (fixes also crashes during creation cancellation [#56](https://github.com/TheAxelander/OpenBudgeteer/issues/56))
* [Fixed] Unable to add multiple Buckets during Bank Transaction creation [#55](https://github.com/TheAxelander/OpenBudgeteer/issues/55)
* [Fixed] Crash on Report Page using sqlite [#57](https://github.com/TheAxelander/OpenBudgeteer/issues/57)

### 1.4 (2021-11-14)

* [Add] Info Dialog during Bucket proposal and optimized proposal performance [#21](https://github.com/TheAxelander/OpenBudgeteer/issues/21)
Expand Down
37 changes: 36 additions & 1 deletion OpenBudgeteer.Blazor/Pages/Bucket.razor
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
@using System.Drawing
@using System.Globalization
@using OpenBudgeteer.Core.Common
@using OpenBudgeteer.Core.Models
@inject DbContextOptions<DatabaseContext> DbContextOptions
@inject YearMonthSelectorViewModel YearMonthDataContext

Expand Down Expand Up @@ -159,7 +160,7 @@

<div class="row">
<div class="col">
<button class="btn btn-sm btn-primary header-action-button" @onclick="@CreateGroup">Create Bucket Group</button>
<button class="btn btn-sm btn-primary header-action-button" @onclick="@ShowNewBucketGroupDialog">Create Bucket Group</button>
<button class="btn btn-sm btn-primary header-action-button" @onclick="@DistributeBudget">Distribute Budget</button>
<button class="btn btn-sm btn-primary header-action-button" @onclick="@(() => _dataContext.ChangeBucketGroupCollapse())">Collapse All</button>
<button class="btn btn-sm btn-primary header-action-button" @onclick="@(() => _dataContext.ChangeBucketGroupCollapse(false))">Expend All</button>
Expand Down Expand Up @@ -298,6 +299,13 @@
</table>
}

<NewBucketGroupDialog
DataContext="@_newBucketGroupDialogDataContext"
IsDialogVisible="@_isNewBucketGroupModalDialogVisible"
OnCancelClickCallback="@(CancelNewBucketGroupDialog)"
OnSaveClickCallback="@(SaveAndCloseNewBucketGroupDialog)"
/>

<EditBucketDialog
Title="Edit Bucket"
DataContext="@_editBucketDialogDataContext"
Expand All @@ -322,6 +330,9 @@
@code {
BucketViewModel _dataContext;

BucketGroup _newBucketGroupDialogDataContext;
bool _isNewBucketGroupModalDialogVisible;

BucketViewModelItem _editBucketDialogDataContext;
bool _isEditBucketModalDialogVisible;

Expand Down Expand Up @@ -362,6 +373,30 @@
ShowEditBucketDialog(newBucket);
}

void ShowNewBucketGroupDialog()
{
_newBucketGroupDialogDataContext = new BucketGroup
{
BucketGroupId = 0,
Name = string.Empty
};
_isNewBucketGroupModalDialogVisible = true;
}

async void SaveAndCloseNewBucketGroupDialog()
{
_isNewBucketGroupModalDialogVisible = false;
// Requested Position is last, so set right position number
if (_newBucketGroupDialogDataContext.Position == -1)
_newBucketGroupDialogDataContext.Position = _dataContext.BucketGroups.Count + 1;
await HandleResult(_dataContext.CreateGroup(_newBucketGroupDialogDataContext));
}

void CancelNewBucketGroupDialog()
{
_isNewBucketGroupModalDialogVisible = false;
}

void ShowEditBucketDialog(BucketViewModelItem bucket)
{
_editBucketDialogDataContext = bucket;
Expand Down
2 changes: 1 addition & 1 deletion OpenBudgeteer.Blazor/Shared/NavMenu.razor
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
</div>
<div class="navbar-text">
<span>
Version: 1.4 (<a href="https://github.com/TheAxelander/OpenBudgeteer/blob/master/CHANGELOG.md" target="_blank">Change Log</a>)
Version: 1.4.1 (<a href="https://github.com/TheAxelander/OpenBudgeteer/blob/master/CHANGELOG.md" target="_blank">Change Log</a>)
</span>
</div>
</div>
Expand Down
73 changes: 73 additions & 0 deletions OpenBudgeteer.Blazor/Shared/NewBucketGroupDialog.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
@using OpenBudgeteer.Core.ViewModels.ItemViewModels
@using System.Drawing
@using OpenBudgeteer.Core.Models
@if (IsDialogVisible)
{
<div class="modal fade show" style=" display: block;">
<div class="modal-dialog modal-dialog-scrollable" style="max-width: 600px">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">New Bucket Group</h4>
<button type="button" class="close" data-dismiss="modal" @onclick="OnCancelClickCallback">&times;</button>
</div>
<div class="modal-body">
<div class="form-group">
<label>Name:</label>
<input class="form-control form-control-sm" type="text" @bind="DataContext.Name"/>
</div>
<div class="form-group">
<label>Position:</label>
<div>
<div class="form-check form-check-inline">
<input
class="form-check-input"
type="radio"
name="newBucketGroupDialogPositionOptions"
id="newBucketGroupDialogPositionOption1"
value="firstPosition"
checked
@onchange="@PositionSelectionChanged">
<label class="form-check-label" for="newBucketGroupDialogPositionOption1">Set on first position</label>
</div>
<div class="form-check form-check-inline">
<input
class="form-check-input"
type="radio"
name="newBucketGroupDialogPositionOptions"
id="newBucketGroupDialogPositionOption2"
value="lastPosition"
@onchange="@PositionSelectionChanged">
<label class="form-check-label" for="newBucketGroupDialogPositionOption2">Set on last position</label>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal" @onclick="OnSaveClickCallback">Save</button>
<button type="button" class="btn btn-danger" data-dismiss="modal" @onclick="OnCancelClickCallback">Cancel</button>
</div>
</div>
</div>
</div>
<div class="modal-backdrop fade show"></div>
}

@code {
[Parameter]
public BucketGroup DataContext { get; set; }

[Parameter]
public bool IsDialogVisible { get; set; }

[Parameter]
public EventCallback<MouseEventArgs> OnCancelClickCallback { get; set; }

[Parameter]
public EventCallback<MouseEventArgs> OnSaveClickCallback { get; set; }

private void PositionSelectionChanged(ChangeEventArgs eventArgs)
{
var selectedOption = eventArgs.Value as string;
DataContext.Position = selectedOption == "firstPosition" ? 0 : -1;
}
}
38 changes: 37 additions & 1 deletion OpenBudgeteer.Core/ViewModels/BucketViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,8 @@ public ViewModelOperationResult CreateGroup()
bucketGroup.BucketGroup.Position++;
dbContext.UpdateBucketGroup(bucketGroup.BucketGroup);
}
if (dbContext.CreateBucketGroup(newGroup) == 0) return new ViewModelOperationResult(false, "Unable to write changes to database");
if (dbContext.CreateBucketGroup(newGroup) == 0)
return new ViewModelOperationResult(false, "Unable to write changes to database");
}

var newBucketGroupViewModelItem =
Expand All @@ -203,6 +204,41 @@ public ViewModelOperationResult CreateGroup()
return new ViewModelOperationResult(true);
}

/// <summary>
/// Creates a new <see cref="BucketGroup"/> and adds it to ViewModel and Database.
/// Will be added on the requested position.
/// </summary>
/// <remarks>Triggers <see cref="ViewModelReloadRequired"/></remarks>
/// <param name="newBucketGroup">Instance of <see cref="BucketGroup"/> which needs to be created in database</param>
/// <returns>Object which contains information and results of this method</returns>
public ViewModelOperationResult CreateGroup(BucketGroup newBucketGroup)
{
if (newBucketGroup is null)
return new ViewModelOperationResult(false, "Unable to create Bucket Group");
if (newBucketGroup.Name == string.Empty)
return new ViewModelOperationResult(false, "Bucket Group Name cannot be empty");

// Set Id to 0 to enable creation
newBucketGroup.BucketGroupId = 0;

// Save Position, append Bucket Group and later move it to requested Position
var requestedPosition = newBucketGroup.Position;
newBucketGroup.Position = BucketGroups.Count + 1;

using (var dbContext = new DatabaseContext(_dbOptions))
{
if (dbContext.CreateBucketGroup(newBucketGroup) == 0)
return new ViewModelOperationResult(false, "Unable to write changes to database");

var newlyCreatedBucketGroup = dbContext.BucketGroup.OrderBy(i => i.BucketGroupId).Last();
var newBucketGroupViewModelItem = new BucketGroupViewModelItem(_dbOptions, newlyCreatedBucketGroup,
_yearMonthViewModel.CurrentMonth);
newBucketGroupViewModelItem.MoveGroup(requestedPosition - newBucketGroupViewModelItem.BucketGroup.Position);
}

return new ViewModelOperationResult(true, true);
}

/// <summary>
/// Starts deletion process in the passed <see cref="BucketGroupViewModelItem"/> and updates positions of
/// all other <see cref="BucketGroup"/> accordingly
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ public TransactionViewModelItem()
/// </summary>
/// <param name="dbOptions">Options to connect to a database</param>
/// <param name="yearMonthViewModel">YearMonth ViewModel instance</param>
public TransactionViewModelItem(DbContextOptions<DatabaseContext> dbOptions, YearMonthSelectorViewModel yearMonthViewModel) : this()
/// <param name="withEmptyBucket">Optionally creates an empty Bucket Assignment</param>
public TransactionViewModelItem(DbContextOptions<DatabaseContext> dbOptions, YearMonthSelectorViewModel yearMonthViewModel,
bool withEmptyBucket = false) : this()
{
_dbOptions = dbOptions;
_yearMonthViewModel = yearMonthViewModel;
Expand All @@ -114,6 +116,14 @@ public TransactionViewModelItem(DbContextOptions<DatabaseContext> dbOptions, Yea
}
}
SelectedAccount = AvailableAccounts.First();
// Create an empty Bucket Assignment if requested (required for "Create new Transaction")
if (withEmptyBucket)
{
var emptyBucket = new PartialBucketViewModelItem(dbOptions, yearMonthViewModel.CurrentMonth);
emptyBucket.AmountChanged += CheckBucketAssignments;
emptyBucket.DeleteAssignmentRequest += DeleteRequestedBucketAssignment;
Buckets.Add(emptyBucket);
}
}

/// <summary>
Expand All @@ -123,7 +133,8 @@ public TransactionViewModelItem(DbContextOptions<DatabaseContext> dbOptions, Yea
/// <param name="yearMonthViewModel">YearMonth ViewModel instance</param>
/// <param name="transaction">Transaction instance</param>
/// <param name="withBuckets">Include assigned Buckets</param>
public TransactionViewModelItem(DbContextOptions<DatabaseContext> dbOptions, YearMonthSelectorViewModel yearMonthViewModel, BankTransaction transaction, bool withBuckets = true) : this(dbOptions, yearMonthViewModel)
public TransactionViewModelItem(DbContextOptions<DatabaseContext> dbOptions, YearMonthSelectorViewModel yearMonthViewModel,
BankTransaction transaction, bool withBuckets = true) : this(dbOptions, yearMonthViewModel)
{
if (withBuckets)
{
Expand Down Expand Up @@ -226,7 +237,8 @@ public TransactionViewModelItem(BucketMovement bucketMovement) : this()
/// <param name="yearMonthViewModel">YearMonth ViewModel instance</param>
/// <param name="transaction">Transaction instance</param>
/// <returns>New ViewModel instance</returns>
public static async Task<TransactionViewModelItem> CreateAsync(DbContextOptions<DatabaseContext> dbOptions, YearMonthSelectorViewModel yearMonthViewModel, BankTransaction transaction)
public static async Task<TransactionViewModelItem> CreateAsync(DbContextOptions<DatabaseContext> dbOptions,
YearMonthSelectorViewModel yearMonthViewModel, BankTransaction transaction)
{
return await Task.Run(() => new TransactionViewModelItem(dbOptions, yearMonthViewModel, transaction));
}
Expand All @@ -239,7 +251,8 @@ public static async Task<TransactionViewModelItem> CreateAsync(DbContextOptions<
/// <param name="yearMonthViewModel">YearMonth ViewModel instance</param>
/// <param name="transaction">Transaction instance</param>
/// <returns>New ViewModel instance</returns>
public static async Task<TransactionViewModelItem> CreateWithoutBucketsAsync(DbContextOptions<DatabaseContext> dbOptions, YearMonthSelectorViewModel yearMonthViewModel, BankTransaction transaction)
public static async Task<TransactionViewModelItem> CreateWithoutBucketsAsync(DbContextOptions<DatabaseContext> dbOptions,
YearMonthSelectorViewModel yearMonthViewModel, BankTransaction transaction)
{
return await Task.Run(() => new TransactionViewModelItem(dbOptions, yearMonthViewModel, transaction, false));
}
Expand Down
11 changes: 8 additions & 3 deletions OpenBudgeteer.Core/ViewModels/ReportViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,12 @@ public async Task<List<Tuple<DateTime, decimal>>> LoadBankBalancesAsync(int mont
for (int monthIndex = months; monthIndex >= 0; monthIndex--)
{
var month = currentMonth.AddMonths(monthIndex * -1);
var bankBalance = dbContext.BankTransaction
var bankTransactions = dbContext.BankTransaction
.Where(i => i.TransactionDate < month.AddMonths(1))
.OrderBy(i => i.TransactionDate)
.Sum(i => i.Amount);
.ToList();
// Query split required due to incompatibility of decimal Sum operation on sqlite (see issue 57)
var bankBalance = bankTransactions.Sum(i => i.Amount);
result.Add(new Tuple<DateTime, decimal>(month, bankBalance));
}
}
Expand Down Expand Up @@ -243,7 +245,7 @@ public async Task<List<MonthlyBucketExpensesReportViewModelItem>> LoadMonthExpen
if (latestVersion.BucketType != 2) continue;
using (var budgetedTransactionDbContext = new DatabaseContext(_dbOptions))
{
var queryResults = budgetedTransactionDbContext.BankTransaction
var queryScope = budgetedTransactionDbContext.BankTransaction
// Join with BudgetedTransaction
.Join(budgetedTransactionDbContext.BudgetedTransaction,
transaction => transaction.TransactionId,
Expand All @@ -256,6 +258,9 @@ public async Task<List<MonthlyBucketExpensesReportViewModelItem>> LoadMonthExpen
// Limit on Transactions for the current Bucket and the last x months
.Where(i => i.BudgetedTransaction.BucketId == bucket.BucketId &&
i.Transaction.TransactionDate >= currentMonth.AddMonths(month * -1))
.ToList();
// Query split required due to incompatibility of decimal Sum operation on sqlite (see issue 57)
var queryResults = queryScope
// Group the results per YearMonth
.GroupBy(i => new DateTime(i.Transaction.TransactionDate.Year, i.Transaction.TransactionDate.Month, 1))
// Create a new Grouped Object
Expand Down
3 changes: 1 addition & 2 deletions OpenBudgeteer.Core/ViewModels/TransactionViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,7 @@ public ViewModelOperationResult CreateItem()
/// </summary>
public void ResetNewTransaction()
{
NewTransaction = new TransactionViewModelItem(_dbOptions, _yearMonthViewModel);
NewTransaction.Buckets.Add(new PartialBucketViewModelItem(_dbOptions, _yearMonthViewModel.CurrentMonth));
NewTransaction = new TransactionViewModelItem(_dbOptions, _yearMonthViewModel, true);
}

/// <summary>
Expand Down
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ OpenBudgeteer is a budgeting app based on the Bucket Budgeting Principle and ins

![Screenshot 1](assets/screenshot1.png)

![Screenshot 1](assets/screenshot1.png)

## Installation (Docker)

You can use the pre-built Docker Image from [Docker Hub](https://hub.docker.com/r/axelander/openbudgeteer). It requires a connection to a `MySQL` database which can be achieved by passing the following variables:
Expand Down

0 comments on commit 641f009

Please sign in to comment.