using MeterVault.App.Analysis; using MeterVault.App.Localization; using MeterVault.App.TariffEditing; using MeterVault.Core.Analysis; using MeterVault.Core.Analysis.Costing; using MeterVault.Core.Analysis.Totals; using MeterVault.Core.Analysis.Virtual; using MeterVault.Core.Domain; using static MeterVault.Integration.Tests.Analysis.AnalysisUiTestData; namespace MeterVault.Integration.Tests.Analysis; /// /// The seams where the reworked pages meet (integration of the page reworks): a cost whose quantity is unknown says so /// instead of "Priced" beside "—"; the meter's Calculation tab words a finding like the attention list, leaving the /// meters to its links; the tariff list and a meter's Tariffs tab agree on when a tariff ends. Pure; no database. /// public sealed class PageIntegrationTests { [Fact] public void A_priced_bucket_without_quantity_reads_as_its_quantity_status() => In("en", () => { var buckets = Buckets(D(2026, 1, 1), D(2026, 2, 28)); var tariff = new Tariff { Id = 1, ScopeType = TariffScope.EnergyType, ScopeId = 1, Component = TariffComponent.UnitPrice, Value = 0.3, Unit = "EUR/kWh", ValidFrom = D(2000, 1, 1), }; var parts = CostCalculator.Parts(buckets).ToList(); List quantities = [CostQuantity.Known(parts[0], 100), CostQuantity.Unknown(parts[1])]; var line = new CostLine(10, 1, BillLineKind.UnitPrice, "kWh", quantities); var cost = CostCalculator.Calculate(new CostRequest(buckets, D(2039, 12, 31), TariffBook.Create([tariff], "EUR"), [line])); var priced = FigureText.Of(cost.Totals[0]); Assert.True(priced.IsKnown); Assert.Equal("Priced", priced.Status); var noQuantity = FigureText.Of(cost.Totals[1]); Assert.False(noQuantity.IsKnown); Assert.Equal(BucketStatus.Missing.Display(), noQuantity.Status); Assert.Null(noQuantity.Detail); // A known cost over incomplete quantities keeps naming its prices, with the quantities' state as detail. var total = FigureText.Of(cost.Total); Assert.True(total.IsKnown); Assert.Equal("Priced", total.Status); Assert.Contains(BucketStatus.Partial.Display(), total.Detail); }); [Fact] public void The_calculation_tab_words_a_finding_like_the_attention_list_without_the_meters() => In("en", () => { var names = new AttentionNames(new Dictionary { [4] = "Solar 1", [8] = "Wasser" }); var units = new VirtualProblem(VirtualProblemKind.UnitMismatch, [4, 8], ["kWh", "m³"]); var cycle = new VirtualProblem(VirtualProblemKind.DependencyCycle, [9, 4, 9], []); var kinds = new VirtualProblem(VirtualProblemKind.ResultKindRequired, [4, 8], ["generation", "mixed"]); Assert.Equal(VirtualProblemKind.UnitMismatch.Display() + " (kWh, m³)", AttentionItems.VirtualReasonWithoutMeters(units)); Assert.Equal(VirtualProblemKind.DependencyCycle.Display(), AttentionItems.VirtualReasonWithoutMeters(cycle)); Assert.StartsWith(VirtualProblemKind.ResultKindRequired.Display() + " (" + QuantityKind.Generation.Display() + ", ", AttentionItems.VirtualReasonWithoutMeters(kinds)); Assert.EndsWith(", gemischt)", In("de", () => AttentionItems.VirtualReasonWithoutMeters(kinds))); // The attention list names the meters itself. Assert.Contains("Solar 1", AttentionItems.VirtualReason(new VirtualProblem(VirtualProblemKind.SourceInvalid, [4], []), names)); Assert.Equal( VirtualProblemKind.DependencyCycle.Display() + " (Meter #9 → Solar 1 → Meter #9)", AttentionItems.VirtualReason(cycle, names)); }); [Fact] public void A_tariff_ends_where_the_next_one_of_its_kind_starts() { TariffSpan[] tariffs = [ new(1, TariffScope.EnergyType, 1, TariffComponent.UnitPrice, D(2023, 1, 1), null), new(2, TariffScope.EnergyType, 1, TariffComponent.UnitPrice, D(2024, 1, 1), null), new(3, TariffScope.EnergyType, 1, TariffComponent.UnitPrice, D(2025, 1, 1), D(2025, 6, 30)), new(4, TariffScope.EnergyType, 2, TariffComponent.UnitPrice, D(2023, 6, 1), null), new(5, TariffScope.EnergyType, 1, TariffComponent.BasePrice, D(2023, 1, 1), D(2030, 12, 31)), new(6, TariffScope.EnergyType, 1, TariffComponent.BasePrice, D(2026, 1, 1), null), ]; var ends = TariffValidity.EffectiveEnds(tariffs); Assert.Equal(D(2023, 12, 31), ends[1]); Assert.Equal(D(2024, 12, 31), ends[2]); Assert.Equal(D(2025, 6, 30), ends[3]); Assert.Null(ends[4]); Assert.Equal(D(2025, 12, 31), ends[5]); Assert.Null(ends[6]); } }