using MeterVault.Infrastructure.Import; using static MeterVault.Integration.Tests.Reconciliation.ReconciliationSupport; namespace MeterVault.Integration.Tests.Reconciliation; /// /// The Kosten sheet is pre-computed category costs (SDD §2.1). The importer stages one manual /// cost per category column; their monthly sum must equal the sheet's total Kosten column, and /// the meterless "Pool Betrieb" column becomes manual costs with no meter. /// public sealed class CostsReconciliationTests { [Fact] public void Category_costs_sum_to_the_monthly_total() { var staged = Stage(ReferenceProfiles.Costs(), Costs); var computed = staged.ManualCosts .GroupBy(c => new DateOnly(c.PeriodStart.Year, c.PeriodStart.Month, 1)) .ToDictionary(g => g.Key, g => g.Sum(c => c.Amount)); var oracle = OracleByMonth(ReadRows(Costs), dateColumn: 0, valueColumn: 2, firstDataRow: 1); AssertReconciles(computed, oracle, tolerance: 0.02, "category totals", minMatches: 20); } [Fact] public void Manual_costs_are_staged_meterless_by_category() { var staged = Stage(ReferenceProfiles.Costs(), Costs); Assert.NotEmpty(staged.ManualCosts); Assert.All(staged.ManualCosts, c => Assert.Null(c.MeterId)); // Wasser Dez 2022 = 70,00 € (SDD §2.1: categories decoupled from meters). var wasserDec = staged.ManualCosts.Single(c => c.CategoryId == ReferenceProfiles.CategoryWasser && c.PeriodStart == new DateOnly(2022, 12, 1)); Assert.Equal(70d, wasserDec.Amount, 2); } }