Add ILogger<ViewService> and log the match-count summary at the end
of MatchOpenBankTransactions: "Matched {Matched} of {Total} open bank
transactions". Completes item 18.
Also drop the ISettingsService [Inject] from Home.razor.cs that was
declared but never referenced.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
New IFxConverter.ConvertToChf(amount, fromCurrency) and FxConverter
wrap the vendor IFxService and the FixerIo API key so callers stop
threading the key through every conversion. ViewService drops
IFxService and ISettingsService from its constructor and takes
IFxConverter instead; GetAccountViewList and GetBalanceSheetView no
longer read settingsService.GetSettings() per method.
FxConverterTestShould locks in the target-currency + API-key routing.
40 tests total, all passing.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add Schaad.Accounting.Tests (xUnit + NSubstitute + Shouldly, net9.0)
wired into Accounting.sln with a direct Reference to
Schaad.Finance.Api.dll so it flows into the test binary.
Naming convention: file/class is <Subject>TestShould, each test method
is DoThisWhenThat. Reads as a sentence:
"ViewService test should sum activa and passiva totals separately when
getting balance view". All assertions use Shouldly (.ShouldBe,
.ShouldBeNull, .ShouldContain, ...) rather than xUnit Assert.*.
38 tests across seven files:
- ViewServiceTestShould: balance math (activa/passiva totals, per-
account balance from start balance + credits - debits, FX conversion
to CHF) and bank-transaction auto-matching (booking-rule text,
value-matching preference, same-accounts-last-month fallback,
open-transaction filter).
- TransactionRepositoryTestShould: FX round-trip against a temp XML
directory, unknown-id -> null, and the mutation-on-read regression
from PR A (a second Get on the same FX transaction used to divide
by FxRate again).
- FormattingTestShould: Swiss thousands separator, two-decimal
rounding, culture independence.
- RepositoryCacheTestShould: loader called once, per-key isolation,
invalidation forces reload, case-insensitive keys.
- AccountRepositoryTestShould: id assignment, in-place update,
currency defaulting, delete, bank-account lookup, bank-balance
update, and constructor re-run against an existing file.
- ChartServiceTestShould: honours settingsService.GetYear() without
mutating it (locks in PR E), account vs sub-class grouping
heuristic, skips empty accounts.
- FileServiceTestShould: CSV header + running balance for debit and
credit lines, ordering by BookingDate/ValueDate/Value, no in-place
value mutation (locks in PR A).
CLAUDE.md gains a `dotnet test` line. IMPROVEMENT_PLAN.md notes that
this landed as three PRs (G, H, I) and was squashed on request.
Also add `*.DotSettings.user` to .gitignore so Rider's per-user
solution settings don't get accidentally staged.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>