AccountingNext/Schaad.Accounting.UI/Components/Pages/Dialogs/TransactionSplitDialog.razor.cs

115 lines
No EOL
3.7 KiB
C#

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;
[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<Transaction> transactionList = new();
private IReadOnlyList<AccountDataset> accounts = [];
private IReadOnlyList<string> bookingTexts = [];
private decimal openAmount = 0;
private List<string> validationErrors = new();
protected override async Task OnInitializedAsync()
{
accounts = await viewService.GetAccountViewListAsync();
bookingTexts = (await bookingTextRepository.GetBookingTextListAsync()).Select(b => b.Text).ToArray();
var accountList = await accountRepository.GetAccountListAsync();
var bankTrx = await bankTransactionRepository.GetBankTransactionAsync(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);
}
// Every row in transactionList needs Text, TargetAccountId, and a non-zero Value.
// The single EditContext above only covers the first row (that's what it was
// constructed with) — so DataAnnotations validation misses subsequent split rows.
// Run explicit per-row checks here and surface everything in validationErrors.
private bool ValidateAllRows()
{
validationErrors.Clear();
for (var i = 0; i < transactionList.Count; i++)
{
var t = transactionList[i];
if (string.IsNullOrWhiteSpace(t.Text))
{
validationErrors.Add($"Zeile {i + 1}: Buchungstext fehlt");
}
if (string.IsNullOrEmpty(t.TargetAccountId))
{
validationErrors.Add($"Zeile {i + 1}: Konto fehlt");
}
if (t.Value == 0)
{
validationErrors.Add($"Zeile {i + 1}: Betrag darf nicht 0 sein");
}
}
return validationErrors.Count == 0;
}
private async Task SaveAsync()
{
if (!ValidateAllRows())
{
return;
}
foreach (var transtaction in transactionList)
{
await transactionRepository.SaveTransactionAsync(transtaction);
}
await Dialog.CloseAsync(Content);
}
private async Task CancelAsync()
{
await Dialog.CancelAsync();
}
}