From c86edfdde2fa9952e5ce515e7477ee3b90017ccc Mon Sep 17 00:00:00 2001 From: Claudio Schaad Date: Tue, 13 May 2025 20:27:09 +0200 Subject: [PATCH] Add transaction split dialog --- .../Datasets/TransactionDataset.cs | 2 +- .../Models/Transaction.cs | 2 +- .../Repositories/TransactionRepository.cs | 2 + Schaad.Accounting.Services/ViewService.cs | 2 +- .../Pages/Controls/AccountSelector.razor | 7 ++ .../Pages/Controls/AccountSelector.razor.cs | 19 ++++ .../Pages/Controls/AccountSelector.razor.css | 5 ++ .../Dialogs/TransactionSplitDialog.razor | 83 ++++++++++++++++++ .../Dialogs/TransactionSplitDialog.razor.cs | 87 +++++++++++++++++++ .../Dialogs/TransactionSplitDialog.razor.css | 10 +++ .../Components/Pages/Home.razor | 55 +++++++----- .../Components/Pages/Home.razor.cs | 21 ++++- .../Components/Pages/Home.razor.css | 13 +-- .../Components/_Imports.razor | 1 + 14 files changed, 276 insertions(+), 33 deletions(-) create mode 100644 Schaad.Accounting.UI/Components/Pages/Controls/AccountSelector.razor create mode 100644 Schaad.Accounting.UI/Components/Pages/Controls/AccountSelector.razor.cs create mode 100644 Schaad.Accounting.UI/Components/Pages/Controls/AccountSelector.razor.css create mode 100644 Schaad.Accounting.UI/Components/Pages/Dialogs/TransactionSplitDialog.razor create mode 100644 Schaad.Accounting.UI/Components/Pages/Dialogs/TransactionSplitDialog.razor.cs create mode 100644 Schaad.Accounting.UI/Components/Pages/Dialogs/TransactionSplitDialog.razor.css diff --git a/Schaad.Accounting.Common/Datasets/TransactionDataset.cs b/Schaad.Accounting.Common/Datasets/TransactionDataset.cs index 7d28f92..b080b64 100644 --- a/Schaad.Accounting.Common/Datasets/TransactionDataset.cs +++ b/Schaad.Accounting.Common/Datasets/TransactionDataset.cs @@ -3,7 +3,7 @@ using Schaad.Accounting.Models; namespace Schaad.Accounting.Datasets { - public record TransactionDataset : Transaction + public class TransactionDataset : Transaction { public Account OriginAccount { get; set; } diff --git a/Schaad.Accounting.Common/Models/Transaction.cs b/Schaad.Accounting.Common/Models/Transaction.cs index dabbe07..8dc7ee0 100644 --- a/Schaad.Accounting.Common/Models/Transaction.cs +++ b/Schaad.Accounting.Common/Models/Transaction.cs @@ -5,7 +5,7 @@ using System.Linq; namespace Schaad.Accounting.Models { - public record Transaction + public class Transaction { public string Id { get; set; } public string BankTransactionId { get; set; } diff --git a/Schaad.Accounting.Db/Repositories/TransactionRepository.cs b/Schaad.Accounting.Db/Repositories/TransactionRepository.cs index 973cc92..8689e7d 100644 --- a/Schaad.Accounting.Db/Repositories/TransactionRepository.cs +++ b/Schaad.Accounting.Db/Repositories/TransactionRepository.cs @@ -30,6 +30,8 @@ namespace Schaad.Accounting.Repositories /// public void SaveTransaction(Transaction transaction) { + transaction.Value = Math.Abs(transaction.Value); + // prevent saving fxrate for chf account var isFxAccount = accountRepository.GetAccount(transaction.OriginAccountId).IsFxAccount; diff --git a/Schaad.Accounting.Services/ViewService.cs b/Schaad.Accounting.Services/ViewService.cs index aca1643..e60111d 100644 --- a/Schaad.Accounting.Services/ViewService.cs +++ b/Schaad.Accounting.Services/ViewService.cs @@ -169,7 +169,7 @@ namespace Schaad.Accounting.Services if (account.Class == ClassIds.Activa && accountId == t.OriginAccountId ) { - return t with { Value = -t.Value }; + t.Value *= -1; } return t; diff --git a/Schaad.Accounting.UI/Components/Pages/Controls/AccountSelector.razor b/Schaad.Accounting.UI/Components/Pages/Controls/AccountSelector.razor new file mode 100644 index 0000000..dcbef09 --- /dev/null +++ b/Schaad.Accounting.UI/Components/Pages/Controls/AccountSelector.razor @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/Schaad.Accounting.UI/Components/Pages/Controls/AccountSelector.razor.cs b/Schaad.Accounting.UI/Components/Pages/Controls/AccountSelector.razor.cs new file mode 100644 index 0000000..900ff6c --- /dev/null +++ b/Schaad.Accounting.UI/Components/Pages/Controls/AccountSelector.razor.cs @@ -0,0 +1,19 @@ +using Microsoft.AspNetCore.Components; +using Schaad.Accounting.Models; + +namespace Schaad.Accounting.UI.Components.Pages.Controls; + +public partial class AccountSelector : ComponentBase +{ + [Parameter] public required string? AccountId { get; set; } + + [Parameter] public required IReadOnlyList Accounts { get; set; } + + [Parameter] public EventCallback AccountIdChanged { get; set; } + + private async Task OnInputChanged(ChangeEventArgs e) + { + AccountId = e.Value?.ToString(); + await AccountIdChanged.InvokeAsync(AccountId); + } +} \ No newline at end of file diff --git a/Schaad.Accounting.UI/Components/Pages/Controls/AccountSelector.razor.css b/Schaad.Accounting.UI/Components/Pages/Controls/AccountSelector.razor.css new file mode 100644 index 0000000..f83e867 --- /dev/null +++ b/Schaad.Accounting.UI/Components/Pages/Controls/AccountSelector.razor.css @@ -0,0 +1,5 @@ +select { + width: 100%; + height: 30px; + box-sizing: border-box; +} diff --git a/Schaad.Accounting.UI/Components/Pages/Dialogs/TransactionSplitDialog.razor b/Schaad.Accounting.UI/Components/Pages/Dialogs/TransactionSplitDialog.razor new file mode 100644 index 0000000..03e7bc9 --- /dev/null +++ b/Schaad.Accounting.UI/Components/Pages/Dialogs/TransactionSplitDialog.razor @@ -0,0 +1,83 @@ +@implements IDialogContentComponent +@rendermode InteractiveServer + + + + + + @Dialog.Instance.Parameters.Title + + + + + + Total: @Math.Abs(Content.Value) / Rest: @openAmount + + Transaktion hinzufügen + + + + + + + + + + + + + + + + @foreach (var transaction in transactionList) + { + + + + + + + + } + +
DatumBetragTextKonto
+
@transaction.ValueDate.ToString("dd.MM.yyyy")
+
+
+ +
+
+
+ + + @foreach (var text in bookingTexts.OrderBy(t => t)) + { + + } + +
+
+ + + +
+
+ +
+
+
+ + + + Abbrechen + + + Speichern + + \ No newline at end of file diff --git a/Schaad.Accounting.UI/Components/Pages/Dialogs/TransactionSplitDialog.razor.cs b/Schaad.Accounting.UI/Components/Pages/Dialogs/TransactionSplitDialog.razor.cs new file mode 100644 index 0000000..25d0925 --- /dev/null +++ b/Schaad.Accounting.UI/Components/Pages/Dialogs/TransactionSplitDialog.razor.cs @@ -0,0 +1,87 @@ +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Forms; +using Microsoft.FluentUI.AspNetCore.Components; +using Schaad.Accounting.Datasets; +using Schaad.Accounting.Interfaces; +using Schaad.Accounting.Models; + +namespace Schaad.Accounting.UI.Components.Pages.Dialogs; + +public partial class TransactionSplitDialog : ComponentBase +{ + private EditContext editContext = null!; + + [CascadingParameter] + public FluentDialog Dialog { get; set; } = null!; + + [Parameter] + public Transaction Content { get; set; } = null!; + + [Inject] + private ITransactionRepository transactionRepository { get; set; } = null!; + + [Inject] + private IBankTransactionRepository bankTransactionRepository { get; set; } = null!; + + [Inject] + private IAccountRepository accountRepository { get; set; } = null!; + + [Inject] + private IBookingTextRepository bookingTextRepository { get; set; } = null!; + + [Inject] + private IViewService viewService { get; set; } = null!; + + private List transactionList = new(); + private IReadOnlyList accounts = null!; + private IReadOnlyList bookingTexts = []; + private decimal openAmount = 0; + + + protected override void OnInitialized() + { + accounts = viewService.GetAccountViewList(); + bookingTexts = bookingTextRepository.GetBookingTextList().Select(b => b.Text).ToArray(); + var accountList = accountRepository.GetAccountList(); + var bankTrx = bankTransactionRepository.GetBankTransaction(Content.BankTransactionId); + var trx = new Transaction(bankTrx, accountList); + trx.Value = Math.Abs(bankTrx.Value); + transactionList.Add(trx); + editContext = new EditContext(trx); + } + + private async Task AddTransactionAsync() + { + transactionList.Add(new Transaction + { + ValueDate = Content.ValueDate, + BookingDate = Content.BookingDate, + OriginAccountId = Content.OriginAccountId, + Value = 0 + }); + + await Task.CompletedTask; + } + + private void CalculateOpenAmount() + { + openAmount = Content.Value + transactionList.Sum(t => t.Value); + } + + private async Task SaveAsync() + { + if (editContext.Validate()) + { + foreach (var transtaction in transactionList) + { + transactionRepository.SaveTransaction(transtaction); + } + await Dialog.CloseAsync(Content); + } + } + + private async Task CancelAsync() + { + await Dialog.CancelAsync(); + } +} \ No newline at end of file diff --git a/Schaad.Accounting.UI/Components/Pages/Dialogs/TransactionSplitDialog.razor.css b/Schaad.Accounting.UI/Components/Pages/Dialogs/TransactionSplitDialog.razor.css new file mode 100644 index 0000000..bad5d5f --- /dev/null +++ b/Schaad.Accounting.UI/Components/Pages/Dialogs/TransactionSplitDialog.razor.css @@ -0,0 +1,10 @@ +th:nth-child(1), td:nth-child(1) { width: 100px; } +th:nth-child(2), td:nth-child(2) { width: 50px; } +th:nth-child(3), td:nth-child(3) { width: 200px; } +th:nth-child(4), td:nth-child(4) { width: 200px; } +th:nth-child(5), td:nth-child(5) { width: 40px; text-align: center; } + +.text-column input { + width: 100%; + box-sizing: border-box; +} \ No newline at end of file diff --git a/Schaad.Accounting.UI/Components/Pages/Home.razor b/Schaad.Accounting.UI/Components/Pages/Home.razor index 2b95793..a38be25 100644 --- a/Schaad.Accounting.UI/Components/Pages/Home.razor +++ b/Schaad.Accounting.UI/Components/Pages/Home.razor @@ -12,18 +12,20 @@ MaximumFileSize="@(10 * 1024 * 1024)" Accept=".zip, .xml" OnProgressChange="@OnProgressChangeAsync" - OnCompleted="@OnCompletedAsync" /> + OnCompleted="@OnCompletedAsync"/> - + @progressTitle - + Upload files - + Cancel @@ -38,10 +40,10 @@ else Buchungsdatum Valutadatum - Text Betrag - Konto Zusatzinfo + Text + Konto @@ -51,9 +53,17 @@ else { -
@transaction.BookingDate.ToString("dd.MM.yyyy")
+
@transaction.BookingDate.ToString("dd.MM.yyyy")
+ -
@transaction.ValueDate.ToString("dd.MM.yyyy")
+
@transaction.ValueDate.ToString("dd.MM.yyyy")
+ + +
@Math.Abs(transaction.Value).ToFormattedString()
+ + +
@transaction.BankTransactionText
+
@@ -65,23 +75,24 @@ else
- -
@transaction.Value.ToFormattedString()
- - + @if (transaction.Value > 0) + { + + } + else + { + + } - -
@transaction.BankTransactionText
+ + + + + - - } diff --git a/Schaad.Accounting.UI/Components/Pages/Home.razor.cs b/Schaad.Accounting.UI/Components/Pages/Home.razor.cs index 65b0ab4..a4f9e8f 100644 --- a/Schaad.Accounting.UI/Components/Pages/Home.razor.cs +++ b/Schaad.Accounting.UI/Components/Pages/Home.razor.cs @@ -5,6 +5,7 @@ using Microsoft.FluentUI.AspNetCore.Components; using Schaad.Accounting.Datasets; using Schaad.Accounting.Interfaces; using Schaad.Accounting.Models; +using Schaad.Accounting.UI.Components.Pages.Dialogs; namespace Schaad.Accounting.UI.Components.Pages; @@ -19,6 +20,9 @@ public partial class Home : ComponentBase [Inject] private IMessageService messageService { get; set; } = null!; + [Inject] + private IDialogService dialogService { get; set; } = null!; + [Inject] private ISettingsService settingsService { get; set; } = null!; @@ -166,7 +170,20 @@ public partial class Home : ComponentBase private async Task SplitBankTransactionAsync(Transaction transaction) { - ShowToast("Split noch nicht implementiert!", ToastIntent.Warning); - await Task.CompletedTask; + var dialog = await dialogService.ShowDialogAsync(transaction, new DialogParameters() + { + Height = "500px", + Width = "800px", + Title = "Split Transaktion", + PreventDismissOnOverlayClick = true, + PreventScroll = true, + }); + + var result = await dialog.Result; + if (!result.Cancelled && result.Data != null) + { + matchingBankTransactions!.RemoveAll(q => q == transaction); + await Task.CompletedTask; + } } } diff --git a/Schaad.Accounting.UI/Components/Pages/Home.razor.css b/Schaad.Accounting.UI/Components/Pages/Home.razor.css index f98d341..e8088fd 100644 --- a/Schaad.Accounting.UI/Components/Pages/Home.razor.css +++ b/Schaad.Accounting.UI/Components/Pages/Home.razor.css @@ -16,16 +16,17 @@ th { background-color: #f8f8f8; } -th:nth-child(1), td:nth-child(1) { width: 120px; } /* Buchungsdatum */ -th:nth-child(2), td:nth-child(2) { width: 120px; } /* Valutadatum */ -th:nth-child(3), td:nth-child(3) { width: 240px; } /* Text */ -th:nth-child(4), td:nth-child(4) { width: 100px; text-align: right; } /* Betrag */ -th:nth-child(5), td:nth-child(5) { width: 300px; } /* Konto */ +th:nth-child(1), td:nth-child(1) { width: 120px; } +th:nth-child(2), td:nth-child(2) { width: 120px; } +th:nth-child(3), td:nth-child(3) { width: 100px; text-align: right; } +th:nth-child(5), td:nth-child(5) { width: 240px; } +th:nth-child(6), td:nth-child(6) { width: 300px; } th:nth-child(7), td:nth-child(7), -th:nth-child(8), td:nth-child(8) { width: 40px; text-align: center; } /* Buttons */ +th:nth-child(8), td:nth-child(8) { width: 40px; text-align: center; } .text-column input { width: 100%; + height: 30px; box-sizing: border-box; /* Ensures padding/border doesn't overflow */ } diff --git a/Schaad.Accounting.UI/Components/_Imports.razor b/Schaad.Accounting.UI/Components/_Imports.razor index 1c85a1a..5631017 100644 --- a/Schaad.Accounting.UI/Components/_Imports.razor +++ b/Schaad.Accounting.UI/Components/_Imports.razor @@ -13,6 +13,7 @@ @using Plotly.Blazor @using Schaad.Accounting.UI @using Schaad.Accounting.UI.Components +@using Schaad.Accounting.UI.Components.Pages.Controls @using Schaad.Accounting.Models @using Schaad.Accounting.Interfaces