diff --git a/src/GoodWood.Application/Interfaces/ISepaExportService.cs b/src/GoodWood.Application/Interfaces/ISepaExportService.cs index 59efb66..705d3f9 100644 --- a/src/GoodWood.Application/Interfaces/ISepaExportService.cs +++ b/src/GoodWood.Application/Interfaces/ISepaExportService.cs @@ -6,5 +6,6 @@ public interface ISepaExportService { Task<(SepaExportDto Export, byte[] XmlBytes)> CreateExportAsync(CreateSepaExportDto dto, CancellationToken ct = default); Task> GetExportsAsync(CancellationToken ct = default); + Task GetByIdAsync(Guid exportId, CancellationToken ct = default); Task RegenerateXmlAsync(Guid exportId, CancellationToken ct = default); } diff --git a/src/GoodWood.Application/Services/SepaExportService.cs b/src/GoodWood.Application/Services/SepaExportService.cs index c282728..229fba8 100644 --- a/src/GoodWood.Application/Services/SepaExportService.cs +++ b/src/GoodWood.Application/Services/SepaExportService.cs @@ -129,6 +129,31 @@ public class SepaExportService : ISepaExportService }).ToList(); } + public async Task GetByIdAsync(Guid exportId, CancellationToken ct = default) + { + await using var context = await _contextFactory.CreateDbContextAsync(ct); + + var export = await context.SepaExports + .Include(e => e.Entries).ThenInclude(e => e.Category) + .Include(e => e.Entries).ThenInclude(e => e.Person) + .FirstOrDefaultAsync(e => e.Id == exportId && e.ClubId == _clubContext.ClubId && !e.IsDeleted, ct); + + if (export is null) + return null; + + return new SepaExportDto + { + Id = export.Id, + ClubId = export.ClubId, + Description = export.Description, + RequestedCollectionDate = export.RequestedCollectionDate, + TotalAmount = export.TotalAmount, + EntryCount = export.EntryCount, + CreatedAt = export.CreatedAt, + Entries = _mapper.Map>(export.Entries) + }; + } + public async Task RegenerateXmlAsync(Guid exportId, CancellationToken ct = default) { var club = await _clubRepository.GetByIdAsync(_clubContext.ClubId, ct) diff --git a/src/GoodWood.Web/Components/Pages/CashBook/CashBook.razor b/src/GoodWood.Web/Components/Pages/CashBook/CashBook.razor index 0c9fa00..e3a8616 100644 --- a/src/GoodWood.Web/Components/Pages/CashBook/CashBook.razor +++ b/src/GoodWood.Web/Components/Pages/CashBook/CashBook.razor @@ -82,6 +82,10 @@ OnClick="OpenSepaExportDialog"> SEPA Export + + SEPA Historie + Neue Buchung diff --git a/src/GoodWood.Web/Components/Pages/CashBook/SepaExportDetailsDialog.razor b/src/GoodWood.Web/Components/Pages/CashBook/SepaExportDetailsDialog.razor new file mode 100644 index 0000000..b0d749a --- /dev/null +++ b/src/GoodWood.Web/Components/Pages/CashBook/SepaExportDetailsDialog.razor @@ -0,0 +1,100 @@ +@using GoodWood.Application.DTOs +@using GoodWood.Application.Interfaces + +@inject ISepaExportService SepaExportService + + + + SEPA Export Details + + + @if (_loading) + { + + } + else if (_exportDetails is not null) + { + + + + + Beschreibung + @_exportDetails.Description + + + Einzugsdatum + @_exportDetails.RequestedCollectionDate.ToString("dd.MM.yyyy") + + + Erstellt + @_exportDetails.CreatedAt.ToString("dd.MM.yyyy HH:mm") + + + Gesamtbetrag + @_exportDetails.TotalAmount.ToString("C") + + + + + Enthaltene Buchungen (@_exportDetails.EntryCount) + + + + Datum + Person + Beschreibung + Betrag + + + @context.BookingDate.ToString("dd.MM.yyyy") + @context.PersonName + @context.Comment + @context.Amount.ToString("C") + + + + } + else if (_error is not null) + { + @_error + } + + + Schließen + + + +@code { + [CascadingParameter] + private IMudDialogInstance? MudDialog { get; set; } + + [Parameter] + public SepaExportDto Export { get; set; } = null!; + + private SepaExportDto? _exportDetails; + private bool _loading = true; + private string? _error; + + protected override async Task OnInitializedAsync() + { + try + { + _exportDetails = await SepaExportService.GetByIdAsync(Export.Id); + + if (_exportDetails is null) + { + _error = "Export nicht gefunden"; + } + } + catch (Exception ex) + { + _error = ex.Message; + } + finally + { + _loading = false; + } + } + + private void Close() => MudDialog?.Close(); +} diff --git a/src/GoodWood.Web/Components/Pages/CashBook/SepaExports.razor b/src/GoodWood.Web/Components/Pages/CashBook/SepaExports.razor new file mode 100644 index 0000000..0dc40f2 --- /dev/null +++ b/src/GoodWood.Web/Components/Pages/CashBook/SepaExports.razor @@ -0,0 +1,111 @@ +@page "/cashbook/sepa-exports" +@attribute [Authorize(Policy = "ClubTreasurer")] + +@inherits Fluxor.Blazor.Web.Components.FluxorComponent + +@using Fluxor +@using GoodWood.Application.DTOs +@using GoodWood.Application.Interfaces +@using GoodWood.Web.Store.SepaExportState +@using Microsoft.AspNetCore.Authorization +@using Microsoft.JSInterop + +@inject IState SepaExportState +@inject IDispatcher Dispatcher +@inject ISnackbar Snackbar +@inject IDialogService DialogService +@inject ISepaExportService SepaExportService +@inject IJSRuntime JS + +SEPA Exporte + +SEPA Exporte + +@if (SepaExportState.Value.Error is not null) +{ + + @SepaExportState.Value.Error + +} + + + + + Zurück zum Kassenbuch + + + + + + + Erstellt + Beschreibung + Einzugsdatum + Anzahl + Betrag + Aktionen + + + @context.CreatedAt.ToString("dd.MM.yyyy HH:mm") + @context.Description + @context.RequestedCollectionDate.ToString("dd.MM.yyyy") + @context.EntryCount + @context.TotalAmount.ToString("C") + + + + + + + + + + + Keine SEPA Exporte vorhanden + + + +@code { + protected override void OnInitialized() + { + base.OnInitialized(); + Dispatcher.Dispatch(new LoadSepaExportsAction()); + } + + private void ClearError() + { + Dispatcher.Dispatch(new ClearSepaExportErrorAction()); + } + + private async Task OpenDetailsDialog(SepaExportDto export) + { + var parameters = new DialogParameters + { + { "Export", export } + }; + + await DialogService.ShowAsync("SEPA Export Details", parameters, + new DialogOptions { MaxWidth = MaxWidth.Large }); + } + + private async Task DownloadXml(SepaExportDto export) + { + try + { + var xmlBytes = await SepaExportService.RegenerateXmlAsync(export.Id); + var fileName = $"sepa-{export.RequestedCollectionDate:yyyy-MM-dd}.xml"; + await JS.InvokeVoidAsync("downloadFile", fileName, "application/xml", xmlBytes); + Snackbar.Add("XML heruntergeladen", Severity.Success); + } + catch (Exception ex) + { + Snackbar.Add($"Fehler: {ex.Message}", Severity.Error); + } + } +} diff --git a/src/GoodWood.Web/Components/Pages/Settings.razor b/src/GoodWood.Web/Components/Pages/Settings.razor index dbacb9a..f50545a 100644 --- a/src/GoodWood.Web/Components/Pages/Settings.razor +++ b/src/GoodWood.Web/Components/Pages/Settings.razor @@ -316,6 +316,10 @@ else StartIcon="@Icons.Material.Filled.Assessment" Href="/cashbook/reports"> Berichte anzeigen + + SEPA Exporte +