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 transactionList = new(); private IReadOnlyList accounts = []; private IReadOnlyList bookingTexts = []; private decimal openAmount = 0; private List validationErrors = new(); private IEnumerable sortedBookingTexts => bookingTexts.OrderBy(t => t); 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(); } }