PR N: polish pass — ClassIds static, drop loaded flag, mandator from config

Three long-noted rough edges from the original analysis, each a
one-line touch:

- ClassIds becomes static class (was instantiable).
- Home.razor.cs drops the `loaded` bool guard (Blazor already runs
  OnInitializedAsync exactly once per component instance).
- Move the "Claudio Schaad" mandator default out of SettingsService
  into SettingsDataset.DefaultMandator, plumbed through
  appsettings.Development.json.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Claudio Schaad 2026-07-02 22:07:08 +02:00
parent 1f1575b0af
commit 786fafefa5
6 changed files with 16 additions and 14 deletions

View file

@ -109,3 +109,4 @@ Analysis and phased plan produced 2026-07-02. See conversation history for full
- **PR K** — Phase 5 item 27: introduce `IFxConverter.ConvertToChf(amount, fromCurrency)` and its `FxConverter` implementation. The vendor `IFxService` and the FixerIo API key are now hidden inside `FxConverter`; callers stop threading the API key through every method call. `ViewService` drops both `IFxService` and `ISettingsService` from its constructor and takes `IFxConverter` instead. Simplifies `GetAccountViewList` (no more per-call `settingsService.GetSettings()` reads) and `GetBalanceSheetView`. Two-test `FxConverterTestShould` locks in the target-currency and API-key routing.
- **PR L** — Phase 2 item 10: drop the hand-rolled `Copy(target)` methods from `Account`, `BookingRule`, `BookingText`, `SubClass`, and `SplitPredefinition`; keep only a `Transaction.Clone()` for defensive-copy needs in `GetTransaction` / `ViewService.WithDisplaySign`. Every `SaveXxx` now uses `FindIndex` → in-place replace (or `Add` for new entries), moving the two "hidden" defaults (`Account.Currency = "CHF"` when unset, `Transaction.BookingDate = ValueDate` when unset) into the corresponding `SaveXxx` method where they belong. Fixes a pre-existing bug: `Transaction.Copy` never copied `RelatedParty`, so update-saves silently dropped it. Added `PreserveRelatedPartyWhenRoundTrippingTransaction` and `DefaultBookingDateToValueDateWhenBookingDateIsUnset` as regression tests. 42 tests total.
- **PR M** — Phase 2 item 18 (final slice): add `ILogger<ViewService>` and log a match-count summary from `MatchOpenBankTransactions` (`"Matched {Matched} of {Total} open bank transactions"`). Completes item 18 — statement imports (PR H), repository save failures (PR J), and match runs now all emit structured logs. Also removes a dead `ISettingsService` injection from `Home.razor.cs` (declared with `[Inject]` but never used anywhere in the file).
- **PR N** — Small polish pass covering three long-noted rough edges from the original analysis: `ClassIds` becomes a `static class` (was instantiable); `Home.razor.cs` loses the redundant `loaded` guard in `OnInitializedAsync` (Blazor already runs that lifecycle hook once per component instance); the hardcoded `mandator = "Claudio Schaad"` in `SettingsService` moves to a `DefaultMandator` field on `SettingsDataset`, plumbed through `appsettings.Development.json`.

View file

@ -1,6 +1,6 @@
namespace Schaad.Accounting
{
public class ClassIds
public static class ClassIds
{
public const int Activa = 1;
public const int Passiva = 2;

View file

@ -5,5 +5,10 @@
public string DataPath { get; set; }
public string FixerIoApiKey { get; set; }
/// <summary>
/// Mandator selected when the app starts. Users can switch via the header dropdown.
/// </summary>
public string DefaultMandator { get; set; } = "Claudio Schaad";
}
}

View file

@ -10,12 +10,13 @@ namespace Schaad.Accounting.Services
public class SettingsService : ISettingsService
{
private readonly SettingsDataset settingsDataset;
private string mandator = "Claudio Schaad";
private string mandator;
private int year = DateTime.Now.Year;
public SettingsService(SettingsDataset settingsDataset)
{
this.settingsDataset = settingsDataset;
this.mandator = settingsDataset.DefaultMandator;
}
public int GetYear()

View file

@ -44,17 +44,11 @@ public partial class Home : ComponentBase
bool IsCanceled;
Dictionary<int, string> Files = new();
private bool loaded;
protected override Task OnInitializedAsync()
{
if (loaded == false) {
matchingBankTransactions = viewService.MatchOpenBankTransactions();
accounts = viewService.GetAccountViewList();
bookingTexts = bookingTextRepository.GetBookingTextList().Select(b => b.Text).ToArray();
loaded = true;
}
return base.OnInitializedAsync();
}

View file

@ -7,6 +7,7 @@
},
"Settings": {
"DataPath": "D:\\Developer\\AccountingData\\",
"FixerIoApiKey": "ee23142f1120bb1223b0e76f98abfa97"
"FixerIoApiKey": "ee23142f1120bb1223b0e76f98abfa97",
"DefaultMandator": "Claudio Schaad"
}
}