diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1b24db5..8ad060e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+## 1.9.1 (2025-01-11)
+
+### :beetle: Bug Fixes
+
+* Unable to move a Bucket Group [#282](https://github.com/TheAxelander/OpenBudgeteer/issues/282)
+* Data Inconsistency Check for incomplete Bucket assignments didn't cover Transactions without any assignment [#283](https://github.com/TheAxelander/OpenBudgeteer/issues/283)
+
## 1.9 (2025-01-04)
### :gear: Features & Enhancements
diff --git a/OpenBudgeteer.Blazor/Shared/MainLayout.razor b/OpenBudgeteer.Blazor/Shared/MainLayout.razor
index 36b0fba..da8e97e 100644
--- a/OpenBudgeteer.Blazor/Shared/MainLayout.razor
+++ b/OpenBudgeteer.Blazor/Shared/MainLayout.razor
@@ -16,7 +16,7 @@
OpenBudgeteer
Database: @CurrentDatabase
- Version: 1.9.0 (Change Log)
+ Version: 1.9.1 (Change Log)
diff --git a/OpenBudgeteer.Core.Data.Services/Generic/GenericBucketGroupService.cs b/OpenBudgeteer.Core.Data.Services/Generic/GenericBucketGroupService.cs
index 9b915e8..7ee8cbb 100644
--- a/OpenBudgeteer.Core.Data.Services/Generic/GenericBucketGroupService.cs
+++ b/OpenBudgeteer.Core.Data.Services/Generic/GenericBucketGroupService.cs
@@ -103,31 +103,33 @@ public override void Delete(Guid id)
public BucketGroup Move(Guid bucketGroupId, int positions)
{
- var bucketGroup = Get(bucketGroupId);
- if (positions == 0) return bucketGroup;
-
- // Create in an interim List for later use
+ // Create in an interim list to handle position updates
var existingBucketGroups = new ObservableCollection();
foreach (var group in GetAll().ToList())
{
existingBucketGroups.Add(group);
}
+
+ // Re-use existing reference in interim list of passed Bucket Group (see #282)
+ var bucketGroup = existingBucketGroups.First(i => i.Id == bucketGroupId);
+ if (positions == 0) return bucketGroup;
+
+ // Calculate new target position
var bucketGroupCount = existingBucketGroups.Count();
var targetPosition = bucketGroup.Position + positions;
if (targetPosition < 1) targetPosition = 1;
if (targetPosition > bucketGroupCount) targetPosition = bucketGroupCount;
if (targetPosition == bucketGroup.Position) return bucketGroup; // Group is already at the end or top. No further action
- // Move Group in interim List
+ // Move Group in interim list
existingBucketGroups.Move(bucketGroup.Position - 1, targetPosition - 1);
- // Update Position number
+ // Update Position number for each group
var newPosition = 1;
foreach (var group in existingBucketGroups)
{
group.Position = newPosition;
_bucketGroupRepository.Update(group);
- if (group.Id == bucketGroupId) bucketGroup = group; // Use correct object reference for final return
newPosition++;
}
diff --git a/OpenBudgeteer.Core/ViewModels/PageViewModels/DataConsistencyPageViewModel.cs b/OpenBudgeteer.Core/ViewModels/PageViewModels/DataConsistencyPageViewModel.cs
index 6a5cd3f..bd1c428 100644
--- a/OpenBudgeteer.Core/ViewModels/PageViewModels/DataConsistencyPageViewModel.cs
+++ b/OpenBudgeteer.Core/ViewModels/PageViewModels/DataConsistencyPageViewModel.cs
@@ -134,6 +134,33 @@ public async Task CheckBankTransactionIncompleteBuck
{
const string checkName = "Transactions with incomplete bucket assignment";
var results = new List>();
+
+ // Check on Transactions which have overall no Bucket assignments
+ var unassignedTransactions = ServiceManager.BankTransactionService
+ .GetAll(DateTime.MinValue, DateTime.MaxValue)
+ .GroupJoin(
+ ServiceManager.BudgetedTransactionService.GetAll(DateTime.MinValue, DateTime.MaxValue),
+ transaction => transaction.Id,
+ budgetedTransaction => budgetedTransaction.TransactionId,
+ (bankTransaction, budgetedTransactions) => new
+ { BankTransaction = bankTransaction, BudgetedTransactions = budgetedTransactions })
+ .Where(i => !i.BudgetedTransactions.Any())
+ .Select(i => i.BankTransaction)
+ .ToList();
+
+ foreach (var unassignedTransaction in unassignedTransactions)
+ {
+ results.Add(new(
+ DataConsistencyCheckResult.StatusCode.Warning,
+ [
+ unassignedTransaction.TransactionDate.ToShortDateString(),
+ unassignedTransaction.Memo ?? string.Empty,
+ unassignedTransaction.Amount.ToString("C", CultureInfo.CurrentCulture),
+ new decimal(0).ToString("C", CultureInfo.CurrentCulture)
+ ]));
+ }
+
+ // Check on incomplete assignments
var findings =
// Get all BudgetedTransaction which are not 1:1 budgeted (Missing Assignments or Split Transaction)
ServiceManager.BudgetedTransactionService.GetAll(DateTime.MinValue, DateTime.MaxValue)
@@ -158,14 +185,13 @@ public async Task CheckBankTransactionIncompleteBuck
foreach (var finding in findings)
{
results.Add(new(
- DataConsistencyCheckResult.StatusCode.Warning,
- new[]
- {
+ DataConsistencyCheckResult.StatusCode.Warning,
+ [
finding.Transaction.TransactionDate.ToShortDateString(),
finding.Transaction.Memo ?? string.Empty,
finding.TransactionAmount.ToString("C", CultureInfo.CurrentCulture),
finding.BudgetedAmount.ToString("C", CultureInfo.CurrentCulture)
- }));
+ ]));
}
if (!results.Any())
diff --git a/SECURITY.md b/SECURITY.md
index 010337f..bde2f49 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -4,9 +4,9 @@
| Version | Supported |
|-------------| ------------------ |
-| 1.9 | :white_check_mark: |
+| 1.9.1 | :white_check_mark: |
| pre-release | :white_check_mark: |
-| < 1.9 | :x: |
+| < 1.9.1 | :x: |
## Reporting a Vulnerability