K20 fertig. Änderungen:

1. ClubService.cs:134 - MonthlyMembershipFee in UpdateAsync hinzugefügt
  2. Settings.razor:358-364 - Laden der Kassenbuch-Einstellungen beim Init
  3. Settings.razor:665-689 - SaveCashBookSettings() Methode implementiert

  Der Kassenbuch-Tab in den Vereins-Einstellungen funktioniert jetzt:
  - Zeigt aktuellen Kontostand
  - Erlaubt Ändern des monatlichen Mitgliedsbeitrags
  - Speichert Änderungen via Fluxor-Action
  - Quick-Links zu Kassenbuch, Kategorien, Berichten
This commit is contained in:
beo3000 2026-01-04 09:56:15 +01:00
parent a59fdac5d5
commit 0d94d4c5c0
4 changed files with 106 additions and 1 deletions

View File

@ -1718,7 +1718,7 @@ public enum CashBookEntryType { Income = 0, Expense = 1 }
| ✓ | K17 | Application | PDF Export (QuestPDF) | 1 |
| ✓ | K18 | Web | Export Controller | 1 |
| ✓ | K19 | Web | Membership Fees Feature | 2 |
| | K20 | Web | Club Settings Extension | 3 |
| | K20 | Web | Club Settings Extension | 3 |
| ☐ | K21 | Web | Navigation Integration | 1 |
| ☐ | K22 | Tests | Unit Tests | 2 |
| ☐ | K23 | Tests | Integration Tests | 1 |

View File

@ -66,6 +66,11 @@ public record ClubDto
/// Sender email for club notifications.
/// </summary>
public string? SenderEmail { get; init; }
/// <summary>
/// Monthly membership fee amount.
/// </summary>
public decimal MonthlyMembershipFee { get; init; }
}
/// <summary>
@ -123,6 +128,11 @@ public record UpdateClubDto
/// Sender email for club notifications.
/// </summary>
public string? SenderEmail { get; init; }
/// <summary>
/// Monthly membership fee amount.
/// </summary>
public decimal MonthlyMembershipFee { get; init; }
}
/// <summary>

View File

@ -131,6 +131,7 @@ public class ClubService : IClubService
existing.ExpenseCalculation = dto.ExpenseCalculation;
existing.ModifiedAt = DateTime.UtcNow;
existing.SenderEmail = dto.SenderEmail;
existing.MonthlyMembershipFee = dto.MonthlyMembershipFee;
var updated = await _clubRepository.UpdateAsync(existing, ct);
return _mapper.Map<ClubDto>(updated);

View File

@ -24,6 +24,7 @@
@inject IState<AuthState> AuthState
@inject NavigationManager NavigationManager
@inject IJSRuntime JSRuntime
@inject ICashBookService CashBookService
<PageTitle>Vereins-Einstellungen</PageTitle>
@ -251,6 +252,58 @@ else
</MudCardContent>
</MudCard>
</MudTabPanel>
<MudTabPanel Text="Kassenbuch" Icon="@Icons.Material.Filled.AccountBalance">
<MudCard Class="mt-4">
<MudCardContent>
<MudText Typo="Typo.h6" Class="mb-4">Kassenbuch-Einstellungen</MudText>
<MudGrid>
<MudItem xs="12" sm="6">
<MudNumericField @bind-Value="_monthlyMembershipFee"
Label="Monatlicher Mitgliedsbeitrag"
Format="N2"
Adornment="Adornment.Start"
AdornmentText="€"
Min="0m"
HelperText="Standard-Beitrag für automatische Buchungen" />
</MudItem>
<MudItem xs="12" sm="6">
<MudText Typo="Typo.caption" Color="Color.Secondary" Class="mb-2">Aktueller Kontostand</MudText>
<MudText Typo="Typo.h5" Color="@(_currentBalance >= 0 ? Color.Success : Color.Error)">
@_currentBalance.ToString("C")
</MudText>
</MudItem>
</MudGrid>
<MudDivider Class="my-4" />
<MudText Typo="Typo.subtitle2" Class="mb-2">Schnellzugriff</MudText>
<MudStack Row="true" Spacing="2">
<MudButton Variant="Variant.Outlined" Color="Color.Primary"
StartIcon="@Icons.Material.Filled.Book" Href="/cashbook">
Kassenbuch öffnen
</MudButton>
<MudButton Variant="Variant.Outlined" Color="Color.Secondary"
StartIcon="@Icons.Material.Filled.Category" Href="/cashbook/categories">
Kategorien verwalten
</MudButton>
<MudButton Variant="Variant.Outlined" Color="Color.Info"
StartIcon="@Icons.Material.Filled.Assessment" Href="/cashbook/reports">
Berichte anzeigen
</MudButton>
</MudStack>
</MudCardContent>
<MudCardActions>
<MudButton Variant="Variant.Filled" Color="Color.Primary"
StartIcon="@Icons.Material.Filled.Save"
OnClick="SaveCashBookSettings"
Disabled="@(!HasCashBookChanges)">
Speichern
</MudButton>
</MudCardActions>
</MudCard>
</MudTabPanel>
</MudTabs>
}
@ -265,6 +318,13 @@ else
private List<PendingMembershipDto> _pendingMemberships = new();
private List<UserDto> _clubMembers = new();
// Cashbook settings
private decimal _monthlyMembershipFee;
private decimal _originalMembershipFee;
private decimal _currentBalance;
private bool HasCashBookChanges => _monthlyMembershipFee != _originalMembershipFee;
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
@ -294,6 +354,14 @@ else
_clubMembers = (await UserService.GetUsersByClubAsync(clubId)).ToList();
_isLoadingMembers = false;
// Load cashbook settings
if (_club != null)
{
_monthlyMembershipFee = _club.MonthlyMembershipFee;
_originalMembershipFee = _club.MonthlyMembershipFee;
_currentBalance = await CashBookService.GetBalanceAsync();
}
}
}
finally
@ -593,4 +661,30 @@ else
StateHasChanged();
}
}
private async Task SaveCashBookSettings()
{
if (_club is null) return;
try
{
var dto = new UpdateClubDto
{
Id = _club.Id,
Name = _club.Name,
LoginName = _club.LoginName,
ExpenseCalculation = _club.ExpenseCalculation,
SenderEmail = _club.SenderEmail,
MonthlyMembershipFee = _monthlyMembershipFee
};
Dispatcher.Dispatch(new UpdateClubAction(dto));
_originalMembershipFee = _monthlyMembershipFee;
Snackbar.Add("Kassenbuch-Einstellungen gespeichert", Severity.Success);
}
catch (Exception ex)
{
Snackbar.Add($"Fehler: {ex.Message}", Severity.Error);
}
}
}