Skip to content
Updated Sep 22, 2026 by Pablo Coufal · Owner: analysisactiveuse-casestest-cases Edit on GitHub

Výpočet spotřeby a nákladů — testovací případy ​

Sada případů, na kterých se ověří, že Consumption Calculation, Cost Calculation a Consumption Aggregation & Effective Consumption počítají tak, jak říkají rozhodnutí OR-1 až OR-15 (Confluence Epic 3.1, 718471209) a jak jsou nastavené příklady na stránkách Implementation examples 1 (535101445) a Implementation examples 2 (536576002). Pro každý případ je uvedeno, z čeho se počítá, jak výpočet probíhá, jaké řádky vzniknou v tabulce consumption a jaké součty musí vyjít. Čísla jsou přepočítaná skriptem; kde dokument doplňuje pravidlo, které feature doc dosud neříká, je označené R-n; jejich stav po projednání 2026-09-22 je v tabulce na konci.

Podklad pro testovací analýzu epicu a pro akceptační testy jeho implementačních ticketů.

Konvence společné všem případům ​

Čas. slotAt je začátek čtvrthodiny v UTC. Fakturační období a „den“ se berou v Europe/Prague: leden 2026 je 2 976 čtvrthodin od 2025-12-31T23:00Z do 2026-01-31T22:45Z včetně. Řádek slotAt = 10:00Z popisuje interval 10:00–10:15.

Rozklad hodnoty do intervalů (R-1). Kde se jedna hodnota V (rozdíl odečtů, fakturované množství, částka) rozkládá do N intervalů s vahami w₁…w_N (W = Σw), hodnota k-tého intervalu je rozdíl zaokrouhlených kumulativních součtů:

v_k = round(V × (w₁+…+w_k) / W) − round(V × (w₁+…+w_{k−1}) / W)

Zaokrouhluje se na 6 desetinných míst u veličin a na 2 u peněz. Součet řádků je vždy přesně V, součet za libovolný souvislý úsek (den, měsíc) je přesně round(V × podíl úseku), a přepočet je deterministický — dvě spuštění dají stejné řádky. Rovnoměrný rozklad je speciální případ s w = 1.

Odečty v libovolném čase — hodnota registru na hranici čtvrthodiny (R-2). Odečty nechodí zarovnané na čtvrthodinu: ruční odečet je v 07:50, dálkový zdroj může posílat stavy v 10:03, 10:18, …, po hodině nebo po dni. Kumulativní registr jednoho zdroje a tarifu se proto bere jako po částech lineární funkce času R(t) mezi po sobě jdoucími odečty a hodnota intervalu je rozdíl registru na jeho hranicích:

v_k = round(R(b_k) − R(t₀)) − round(R(b_{k−1}) − R(t₀))     b_k = začátek k+1. čtvrthodiny, t₀ = první odečet řady

Pro odečty zarovnané na čtvrthodinu je to přesně rozdíl sousedních stavů (CC-01); pro dva ruční odečty je to rovnoměrný rozklad podle času (R-1 s w = délka překryvu intervalu); pro hodinový dálkový odečet vyjdou čtyři stejné čtvrthodiny; z odečtů hustších než čtvrthodina se použijí jen hodnoty na hranicích. Krajní čtvrthodiny řady (ta, ve které leží první a poslední odečet) dostanou jen svůj částečný podíl, takže součet řady je vždy přesně R(t_N) − R(t₀); s dalším odečtem se poslední částečná čtvrthodina přepočte na celou (upsert). delta a average odečet se vztahuje k období od předchozího odečtu téhož zdroje a rozkládá se podle překryvu s čtvrthodinami stejně. Uložený reading.readAt se nemění; přes hranici výměny měřidla (lifecycleState final → initial) se R(t) neinterpoluje.

Identita řádku. gaugeId · slotAt · kind · type · direction · tariff · source · invoiceId (R-6: invoiceId je null u veličin z odečtů a u výsledků virtuálních měřidel; u fakturovaných řad odlišuje fakturu od dobropisu na stejném období); unit identitu netvoří. Přepočet je upsert na tuto identitu. Interval bez vstupu nemá řádek.

Zkratky. MG = fyzické měřidlo (jeden měřený kanál), VG = virtuální měřidlo; identifikátory jsou v reálných datech UUID v7, zde symbolické. createdBy/updatedBy je vždy system:consumption-calculation, u přepočtu system:consumption-recalculation; ve výpisech řádků se vynechávají.

Fixture. Klient Město, objekt Škola (elektřina, plyn, teplo, voda), objekt Dům (US3–US5), areál Kampus (objekty A a B, special US1). Priorita zdrojů klienta remote_manual_invoice, na měřidlech neuvedeno, pokud případ neříká jinak.


CC-01 · Elektřina — dálkový kumulativní odečet s tarify ​

Situace. MG-E1 Škola — hlavní elektroměr, medium=electricity, readingMode=cumulative, direction=import, outputMode=include, dálkově čtený registr VT i NT každých 15 minut. Odpovídá US1 (Implementation examples 1) s dálkovým odečtem.

Vstupy — reading (source=remote, format=cumulative, type=energy):

readAt (UTC)tariffvalue (kWh)
2026-01-15T10:00Zhigh125 480,0
2026-01-15T10:15Zhigh125 483,2
2026-01-15T10:30Zhigh125 486,5
2026-01-15T10:45Zhigh125 489,1
2026-01-15T11:00Zhigh125 492,4
2026-01-15T10:00Z … 11:00Zlow88 120,0 (beze změny)

Objemový koeficient pro readingSource=remote: žádný (= 1). Výhřevnost se u energie nepoužije.

Výpočet. Pro každou dvojici po sobě jdoucích stavů stejného zdroje a tarifu: v = stav(t+15) − stav(t), uloží se pod slotAt = t. Tarify se nikdy nesčítají. NT dává rozdíl 0 — řádek se zapíše (nula je změřená hodnota, chybějící řádek by znamenal „nezměřeno“).

Datové věty — consumption

gaugeIdslotAtkindtypedirectiontariffsourcevalueunit
MG-E12026-01-15T10:00Zconsumptionenergyimporthighremote3.200000kWh
MG-E12026-01-15T10:15Zconsumptionenergyimporthighremote3.300000kWh
MG-E12026-01-15T10:30Zconsumptionenergyimporthighremote2.600000kWh
MG-E12026-01-15T10:45Zconsumptionenergyimporthighremote3.300000kWh
MG-E12026-01-15T10:00Zconsumptionenergyimportlowremote0.000000kWh
…(10:15, 10:30, 10:45)lowremote0.000000kWh

Kontrolní součty. Hodina 10:00–11:00, VT = 12,4 kWh, NT = 0,0 kWh; hodinový souhrn (continuous aggregate) vrátí obě řady zvlášť. Pro stav v 11:00 nevzniká řádek 11:00Z, dokud nepřijde stav 11:15.

Varianty — dálkové odečty mimo čtvrthodinový rastr (R-2)

Odečty registru VT (readAt → value)Řádky consumption (slotAt → value)Σ
10:03 → 125 480,6 · 10:18 → 125 483,8 · 10:33 → 125 487,1 · 10:48 → 125 489,6 · 11:03 → 125 492,910:00 → 2,560000 (jen 10:03–10:15) · 10:15 → 3,280000 · 10:30 → 2,660000 · 10:45 → 3,140000 · 11:00 → 0,660000 (jen 11:00–11:03, přepočte se s dalším odečtem)12,300000 = 125 492,9 − 125 480,6
hodinově: 10:00 → 125 480,0 · 11:00 → 125 492,410:00, 10:15, 10:30, 10:45 → 3,10000012,400000
po 5 min: 10:00 → 125 480,0 · 10:05 → 125 481,5 · 10:10 → 125 482,0 · 10:15 → 125 483,210:00 → 3,200000 (hodnoty 10:05 a 10:10 tvar čtvrthodiny neovlivní)3,200000

Co test ověřuje. Rozdíl jen uvnitř jednoho source × tariff; poslední stav dávky nezakládá celý řádek; nula ≠ chybějící řádek; nezarovnané, hrubší i hustší dálkové odečty dávají stejný součet jako registr.


CC-02 · Elektřina — výkonový odečet (OR-10) ​

Situace. MG-E2 Škola — výkonový kanál, dálkový zdroj posílá průměrný výkon za čtvrthodinu (type=power, format=average, tarif total).

Vstupy — reading (source=remote):

readAt (UTC)typevalue (kW)
2026-01-15T10:00Zpower12,8
2026-01-15T10:15Zpower13,6
2026-01-15T10:30Zpower11,2
2026-01-15T10:45Zpower14,0

Výpočet. energie = výkon × 0,25 h; source zůstává remote (ne calculated). Výkonová hodnota se do consumption neukládá jako type=power — uloží se jen odvozená energie; sizing (maximum čtvrthodiny) se čte z energetické řady (feature Aggregation, Serving a period total).

Datové věty

gaugeIdslotAtkindtypedirectiontariffsourcevalueunit
MG-E22026-01-15T10:00Zconsumptionenergyimporttotalremote3.200000kWh
MG-E22026-01-15T10:15Zconsumptionenergyimporttotalremote3.400000kWh
MG-E22026-01-15T10:30Zconsumptionenergyimporttotalremote2.800000kWh
MG-E22026-01-15T10:45Zconsumptionenergyimporttotalremote3.500000kWh

Varianta — přednost přímo měřené energie. Když tentýž zdroj dodá pro 10:15Z i type=energy, value=3,45, uloží se 3.450000 a hodnota z výkonu (3,4) se zahodí; log .info uvede „power-derived value discarded“.

Kontrolní součty. Hodina 10:00–11:00 = 12,9 kWh; maximum čtvrthodiny = 3,5 kWh (= 14,0 kW).

Co test ověřuje. Převod podle délky intervalu; zachování zdroje; přednost energie před výkonem ve stejném intervalu a zdroji.


CC-03 · Elektřina — ruční odečet, rozklad do čtvrthodin (R-1, R-2) ​

Situace. MG-E3 Dům — hlavní elektroměr (US3), readingMode=cumulative, jen ruční odečty, tarif total.

Vstupy — reading (source=manual, format=cumulative, type=energy):

readAt (UTC)value (kWh)
2026-01-05T07:50Z40 210
2026-02-02T08:10Z41 090

Výpočet. Rozdíl 880 kWh za 28 dní 0 h 20 min = 40 340 minut → 0,327219 kWh na celou čtvrthodinu (R-2: registr lineární v čase). Řada pokrývá čtvrthodiny od 07:45Z (částečná, 07:50–08:00 = 10 min → 0,218146) přes 2 688 celých až po 2026-02-02T08:00Z (částečná, 08:00–08:10 → 0,218146) = 2 690 řádků; kumulativní zaokrouhlení (R-1) dává 0,327218 / 0,327219 tak, aby součet byl přesně 880.

Datové věty (první, druhá, poslední)

gaugeIdslotAtkindtypedirectiontariffsourcevalueunit
MG-E32026-01-05T07:45Zconsumptionenergyimporttotalmanual0.218146kWh
MG-E32026-01-05T08:00Zconsumptionenergyimporttotalmanual0.327218kWh
MG-E32026-01-05T08:15Zconsumptionenergyimporttotalmanual0.327219kWh
…
MG-E32026-02-02T07:45Zconsumptionenergyimporttotalmanual0.327218kWh
MG-E32026-02-02T08:00Zconsumptionenergyimporttotalmanual0.218146kWh

Řádek 08:00Z z 2. 2. je částečný (10 min); až přijde další odečet, přepočte se na celou čtvrthodinu z obou odečtů kolem hranice 08:15Z.

Kontrolní součty. Σ všech řádků = 880,000000 kWh přesně; 5. 1. (lokálně, od 07:50Z) = 19,851264 kWh; celé čtvrthodiny nabývají jen dvou sousedních hodnot (bez driftu). Před 5. 1. 07:45Z žádný řádek.

Varianta — nižší odečet. Druhý odečet 40 100 (uživatel potvrdil, Reading Management): rozdíl −110 kWh, řádky záporné (−0,040907 …), Σ = −110,000000. Nic se tiše nezahazuje (rozdíl proti EM2).

Co test ověřuje. Částečné krajní čtvrthodiny, počet intervalů, přesný součet, záporný rozdíl po potvrzení.


CC-04 · Výměna měřidla — žádný rozdíl přes hranici ​

Situace. MG-E3 z CC-03; 20. 1. 2026 vyměněn elektroměr (Meter Replacement Flow zapsal lifecycleState).

Vstupy — reading (source=manual, type=energy):

readAt (UTC)valuelifecycleStatesériové číslo
2026-01-05T07:50Z40 210readingS-1
2026-01-20T10:00Z40 690finalS-1
2026-01-20T10:00Z0initialS-2
2026-02-02T08:10Z400readingS-2

Výpočet. Dvě nezávislé řady R(t): final − předchozí = 480 kWh za 21 730 min → 0,331339 na čtvrthodinu, 1 449 řádků [05T07:45Z, 20T10:00Z) (první částečný 0,220893); další − initial = 400 kWh za 18 610 min → 0,322407, 1 241 řádků [20T10:00Z, 02-02T08:15Z) (poslední částečný 0,214938). Přes dvojici initial(0) / final(40 690) se registr neinterpoluje; kdyby to někdo spočetl, dal by −40 690 kWh — to je hodnota, kterou test hlídá, že nikde není.

Datové věty (hraniční řádky)

gaugeIdslotAtsourcevaluepoznámka
MG-E32026-01-20T09:45Zmanual0.331339poslední interval starého měřidla
MG-E32026-01-20T10:00Zmanual0.322407první interval nového

Kontrolní součty. Staré měřidlo Σ = 480,000000; nové Σ = 400,000000; leden (lokálně, do 31. 1. 22:45Z) = 837,227297 kWh; žádný záporný řádek. Log .warn „difference discarded across replacement boundary“ se neobjeví (hranice je řádná, ne chyba) — nebo se objeví jako .info; k dořešení v logging konvencích.


CC-05 · Plyn — objemový koeficient a výhřevnost (F332, F333, OR-5, OR-12, OR-13) ​

Situace. MG-G1 Škola — plynoměr, medium=gas, unit měřidla m³, readingMode=cumulative, ruční i dálkové odečty. Odpovídá příkladu „plynoměr“ na stránce Epicu.

Vstupy

reading (type=volume, format=cumulative):

readAt (UTC)sourcevalue (m³)
2026-01-01T08:00Zmanual12 000
2026-02-01T08:00Zmanual13 000
2026-01-15T10:00Zremote45 210,00
2026-01-15T10:15Zremote45 210,35

volumeCoefficient (MG-G1):

readingSourcevalidFromvalue
manual2025-06-011,0234
remote2025-06-011,0150

calorificValue (scope klient Město, medium=gas, primarySource=naturalGas, unitFrom=m³, unitTo=kWh): validFrom=2026-01-01, value=10,55. Na měřidle žádná; systémová výchozí existuje, ale nepoužije se (klientská má přednost: měřidlo → klient → systém).

Výpočet — ruční řada. 1 000 m³ × 1,0234 × 10,55 = 10 796,87 kWh; rozklad na 2 976 intervalů [01T08:00Z, 02-01T08:00Z) (R-1): 3,627980 / 3,627981 kWh. Uloží se jen energie v kWh (OR-13); objemová řada se neukládá.

Výpočet — dálková řada. 0,35 m³ × 1,0150 × 10,55 = 3,747888 kWh pro 10:00Z. Použije se koeficient historie remote — kdyby výpočet sáhl po ručním (1,0234), vyšlo by 3,778905; to je chyba, kterou test hlídá (OR-12).

Datové věty

gaugeIdslotAtkindtypedirectiontariffsourcevalueunit
MG-G12026-01-01T08:00Zconsumptionenergyimporttotalmanual3.627981kWh
MG-G12026-01-01T08:15Zconsumptionenergyimporttotalmanual3.627980kWh
…
MG-G12026-01-15T10:00Zconsumptionenergyimporttotalmanual3.627981kWh
MG-G12026-01-15T10:00Zconsumptionenergyimporttotalremote3.747888kWh

Dva řádky pro 10:00Z — jeden na zdroj — vedle sebe, nepřepisují se.

Kontrolní součty. Ruční řada Σ = 10 796,870000 kWh; první den (96 intervalů) 348,286129 kWh; zpětný přepočet na m³ pro zobrazení 348,286129 / (1,0234 × 10,55) = 32,258065 m³ (= 1 000 × 96 / 2 976).

Varianty (stejný odečet, jiné nastavení)

NastaveníVýsledek za obdobíNa interval
koeficient manual chybí (žádný řádek) → 1,010 550,00 kWh3,545027
výhřevnost na měřidle 9,50 (certifikát dodavatele, gaugeId=MG-G1, validFrom 2026-01-01)9 722,30 kWh3,266902
výhřevnost chybí na všech třech úrovníchžádný řádek, log .warn „calorific value missing“—
výhřevnost klienta se od 16. 1. změní na 10,40intervaly od 2026-01-15T23:00Z přepočteny (OR-13), předchozí zůstávají3,576398

Co test ověřuje. Pořadí měřidlo → klient → systém; výběr koeficientu podle zdroje řady; chybějící koeficient = 1, chybějící výhřevnost = bez řádku; uložení v kWh a dopočet m³; přepočet od data platnosti.


CC-06 · Teplo — přírůstkový odečet v GJ ​

Situace. MG-T1 Škola — měřič tepla, medium=heat, readingMode=delta (dodavatel hlásí spotřebu za měsíc, ne stav), unit měřidla GJ, tarif total.

Vstupy — reading (source=manual, format=delta, type=energy):

readAt (UTC)value (GJ)význam
2025-12-31T23:00Z171,0prosinec 2025 (ohraničuje začátek)
2026-01-31T23:00Z162,5leden 2026

Výpočet. U delta se rozdíl netvoří: hodnota odečtu je spotřeba za období od předchozího odečtu téhož zdroje ([2025-12-31T23:00Z, 2026-01-31T23:00Z) = 2 976 intervalů; u odečtu mimo rastr se krajní čtvrthodiny dělí podle překryvu, R-2). Převod GJ → kWh pevným faktorem 1 GJ = 1 000 / 3,6 kWh: 162,5 GJ = 45 138,888889 kWh (R-3: kanonická jednotka energie v consumption je kWh i pro měřidla s gauge.unit = GJ; zobrazení v GJ dělá převodní vrstva Chart Engine). Rozklad R-1: 15,167637 / 15,167638 kWh.

Datové věty

gaugeIdslotAtkindtypedirectiontariffsourcevalueunit
MG-T12025-12-31T23:00Zconsumptionenergyimporttotalmanual15.167637kWh
MG-T12025-12-31T23:15Zconsumptionenergyimporttotalmanual15.167638kWh
…
MG-T12026-01-31T22:45Zconsumptionenergyimporttotalmanual15.167638kWh

Kontrolní součty. Leden Σ = 45 138,888889 kWh (= 162,500000 GJ po zpětném převodu); 1. 1. (lokálně) = 1 456,093190 kWh. Měsíční souhrn tepla musí vyjít stejně jako dnešní dočasný adapter building-monthly-consumption-postgres.adapter.ts pro tentýž vstup — to je regresní kotva.

Co test ověřuje. delta bez tvorby rozdílu; okno od předchozího odečtu; převod jednotek bez ztráty; regrese proti dočasnému výpočtu.


CC-07 · Voda — objem bez výhřevnosti, podružná měřidla ​

Situace. Dům (US3/US5): MG-W1 hlavní vodoměr (standard, include), MG-W2 Byt A a MG-W3 Byt B (subGauge, reportOnly, parentGaugeId=MG-W1). medium=water, type=volume, unit=m³, ruční kumulativní odečty.

Vstupy — reading (source=manual, format=cumulative, type=volume):

gaugereadAt (UTC)value (m³)
MG-W12025-12-31T23:00Z2 345,6
MG-W12026-01-31T23:00Z2 402,1
MG-W22025-12-31T23:00Z / 2026-01-31T23:00Z810,0 / 832,4
MG-W32025-12-31T23:00Z / 2026-01-31T23:00Z655,2 / 684,0

Výpočet. Rozdíly 56,5 / 22,4 / 28,8 m³; bez koeficientu, bez výhřevnosti (objem zůstává objemem). Rozklad R-1 na 2 976 intervalů: MG-W1 0,018985 / 0,018986 m³.

Datové věty

gaugeIdslotAtkindtypedirectiontariffsourcevalueunit
MG-W12025-12-31T23:00Zconsumptionvolumeimporttotalmanual0.018985m³
MG-W22025-12-31T23:00Zconsumptionvolumeimporttotalmanual0.007527m³
MG-W32025-12-31T23:00Zconsumptionvolumeimporttotalmanual0.009677m³
VG-W Dům — voda celkem2025-12-31T23:00Zconsumptionvolumeimporttotalcalculated0.018985m³

Kontrolní součty. MG-W1 Σ = 56,500000; 1. 1. = 1,822581 m³. Objekt (VG-W, vzorec MG-W1): Σ = 56,5 — ne 56,5 + 22,4 + 28,8 = 107,7 (podružná se nepočítají dvakrát). Nezměřený zbytek domu = 56,5 − 22,4 − 28,8 = 5,3 m³ není nikde uložen; kdo ho chce, založí virtuální měřidlo MG-W1 − MG-W2 − MG-W3 (US4).

Co test ověřuje. Objemová veličina bez převodu; reportOnly podružná nevstupují do součtu objektu.


CC-08 · Efektivní spotřeba — částečné dálkové pokrytí (OR-1, OR-14) ​

Situace. MG-E1 z CC-01 má za leden 2026 tři řady: dálkovou jen za 1.–21. 1. (výpadek DO od 22. 1.), ruční za celý měsíc, fakturovanou za celý měsíc. Priorita: na měřidle nic → klient remote_manual_invoice.

Vstupy (zjednodušené řady, tarif total)

ŘadaPokrytí (lokálně)IntervalůHodnota na intervalΣ za leden
remote1.–21. 1.2 0162,000000 kWh4 032,00
manual (odečty 10 000 → 16 200)1.–31. 1.2 9762,083333 (R-1)6 200,00
invoice (fakturováno 6 150 kWh)1.–31. 1.2 9762,066532 / 2,0665336 150,00

Výpočet. Efektivní řada se neukládá. Při čtení se pro každý interval vybere první dostupný zdroj v pořadí: 1.–21. 1. remote (2,0), 22.–31. 1. manual (2,083333). Teprve pak se sčítá.

Datové věty. V consumption jsou jen tři zdrojové řady, např. pro 2026-01-21T23:00Z (22. 1. 00:00 lokálně):

gaugeIdslotAtsourcevalueunit
MG-E12026-01-21T23:00Zmanual2.083333kWh
MG-E12026-01-21T23:00Zinvoice2.066532kWh
(žádný řádek remote)

Kontrolní součty (co vrátí period total / Chart Engine)

DotazVýsledekPokrytí
efektivní, leden6 032,00 kWh (2 016 × 2 + 960 × 2,083333)2 976 / 2 976 intervalů, zdroje remote+manual
efektivní, 1. 1.192,0096 intervalů, remote
efektivní, 22. 1.200,0096 intervalů, manual
source=remote, leden4 032,002 016 / 2 976
source=manual, leden6 200,002 976 / 2 976
source=invoice, leden6 150,00 — označeno jako fakturované2 976 / 2 976
priorita měřidla změněna na manual_remote_invoice, leden6 200,00 — bez zápisu do consumption
priorita invoice_remote_manual, leden6 150,00

Efektivní součet 6 032 se nerovná žádné zdrojové řadě — to je očekávané. Měsíční výběr „podle priority“ (vzal by remote = 4 032, nebo manual = 6 200) je chyba.

Co test ověřuje. Výběr po intervalech před součtem; žádná uložená efektivní řada; změna priority nemění uložené řádky; označení fakturované řady; pokrytí ve výsledku.


CC-09 · Náklad z faktury — s DPH a bez, rovnoměrný rozklad (F238, F338, F347, OR-3) ​

Situace. Faktura za MG-E1, elektřina, období 1.–31. 1. 2026, uživatel zadal 10 000,00 Kč bez DPH. Na MG-E1 není pro leden žádný profil (varianta bez CC-08 dat). Odpovídá příkladu „faktura za leden“ na stránce Epicu.

Vstupy

vatRate: medium=electricity, ratePercent=21,00, validFrom=2024-01-01.

invoice: gaugeId=MG-E1, dateFrom=2026-01-01, dateTo=2026-01-31, priceWithoutVat=10 000,00, price dopočteno, vatRateId → řádek výše.

Výpočet. Sazba k dateFrom = 21 % → price = 10 000 × 1,21 = 12 100,00. Dvě řady, každá rozklad R-1 na 2 976 intervalů na 2 desetinná místa: s DPH 4,06 / 4,07 (1 744 intervalů po 4,07, 1 232 po 4,06), bez DPH 3,36 / 3,37.

Datové věty

gaugeIdslotAtkindtypedirectiontariffsourcevalueunitinvoiceId
MG-E12025-12-31T23:00ZcostWithVatnullnulltotalinvoice4.07KčINV-1
MG-E12025-12-31T23:15ZcostWithVatnullnulltotalinvoice4.06KčINV-1
MG-E12025-12-31T23:30ZcostWithVatnullnulltotalinvoice4.07KčINV-1
MG-E12025-12-31T23:00ZcostWithoutVatnullnulltotalinvoice3.36KčINV-1
…
MG-E12026-01-31T22:45ZcostWithVatnullnulltotalinvoice4.07KčINV-1

type a direction jsou u peněz null; tariff=total, protože faktura tarify nerozlišuje (R-4: u faktury s invoiceValue po tarifech vzniká nákladová řada per tarif, viz CC-11).

Kontrolní součty

Úseks DPHbez DPH
1. 1.390,32322,58
1.–10. 1.3 903,233 225,81
11.–31. 1.8 196,776 774,19
leden12 100,0010 000,00

Součet 12 099,99 nebo 12 100,01 je chyba zápisu (feature doc: write se odmítne).

Co test ověřuje. Dopočet druhé částky ze sazby k dateFrom; uložení vatRateId; dvě řady; přesnost na haléř za den, dekádu i měsíc; vazba invoiceId.


CC-10 · Náklad podle profilu spotřeby s neúplným pokrytím (OR-2) ​

Situace. Stejná faktura jako CC-09, ale MG-E1 má dálkový profil: 1.–10. 1. mrazivo (3,0 kWh/interval), 11.–21. 1. (1,0 kWh/interval), 22.–31. 1. výpadek DO — bez profilu.

Výpočet. Váhy = dálková řada (R-5: profil je řada remote; není-li, manual; není-li ani ta, rovnoměrně). Nepokryté intervaly dostanou průměr pokryté části: (960 × 3 + 1 056 × 1) / 2 016 = 1,952381. W = 5 810,285714. Rozklad R-1 obou částek podle vah.

Důsledek OR-2, který stojí za to znát: nepokrytá část dostane vždy přesně svůj časový podíl (960 / 2 976 = 10/31), tedy 3 903,23 Kč — stejně jako při rovnoměrném rozkladu; profil mění jen tvar uvnitř pokryté části.

Datové věty (jeden interval z každé části)

gaugeIdslotAtkindsourcevalueunitinvoiceId
MG-E12025-12-31T23:00Z (1. 1.)costWithVatinvoice6.25KčINV-1
MG-E12026-01-10T23:00Z (11. 1.)costWithVatinvoice2.08KčINV-1
MG-E12026-01-21T23:00Z (22. 1.)costWithVatinvoice4.07KčINV-1

Kontrolní součty

Úseks DPHbez DPHpodíl
1.–10. 1.5 997,644 956,7349,57 %
11.–21. 1.2 199,131 817,46
22.–31. 1.3 903,233 225,8110/31
leden12 100,0010 000,00

Varianta — přepočet profilu. Když se doplní dálková data za 22.–31. 1., přepočte se nákladová řada této faktury (spouštěč „Consumption profile recomputed“); měsíční součet zůstane 12 100,00, změní se jen tvar. Řádky mají nové updatedAt, updatedBy=system:consumption-recalculation.

Co test ověřuje. Průměrná váha nepokryté části; normalizace na fakturu; spotřeba se nemění; přepočet jen nákladové řady.


CC-11 · DPH — dopočet, sazba podle média, tolerance, dobropis, tarify (F347, OR-7, OR-11) ​

Vstupy — vatRate

mediumratePercentvalidFrom
electricity21,002024-01-01
gas21,002024-01-01
heat12,002024-01-01
water12,002024-01-01

Případy

#Vstup uživateleSazbaUloženo (priceWithoutVat / price)Chování
aelektřina, 12 100,00 s DPH21 %10 000,00 / 12 100,00dopočet dolů, vatRateId uložen
bteplo (MG-T1), 10 000,00 bez DPH12 %10 000,00 / 11 200,00sazba podle média
celektřina, období od 1. 12. 2023žádná v platnosti—formulář vyžaduje obě částky, vatRateId=null
delektřina, uživatel přepsal na 10 000,00 / 12 300,0021 %10 000,00 / 12 300,00implikovaná sazba 23,00 % → odchylka 2,0 p. b. > 0,5 → varování, uložení povoleno
edobropis (creditNote=true), −2 000,00 bez DPH, období 1.–31. 1.21 %−2 000,00 / −2 420,00řady záporné: −0,81 / −0,82 Kč, Σ = −2 420,00
fsazba elektřiny od 2027-01-01 změněna na 23 %faktury s dateFrom < 2027-01-01 beze změny (mají vatRateId)přepočítá se nic; nové faktury 23 %

Datové věty — dobropis (e)

gaugeIdslotAtkindsourcevalueunitinvoiceId
MG-E12025-12-31T23:00ZcostWithVatinvoice-0.81KčCN-1
MG-E12025-12-31T23:15ZcostWithVatinvoice-0.81KčCN-1
MG-E12025-12-31T23:30ZcostWithVatinvoice-0.82KčCN-1

Faktura INV-1 a dobropis CN-1 stojí vedle sebe: liší se jen invoiceId, které je proto součástí identity řádku (R-6, rozhodnuto 2026-09-22 — unikátní index entity consumption rozšířen). Součet obou řad za leden = 12 100,00 − 2 420,00 = 9 680,00 Kč.

Faktura s tarify (R-4). EM2 ukládá na faktuře množství po tarifech (InvoiceValue.segment VT/NT), ale cenu jen jednu (invoice.price); náklad po tarifech v EM2 neexistuje. Proto:

Co je na faktuřeŘady source=invoice
invoiceValue VT 700 kWh, NT 300 kWh; price 12 100 / priceWithoutVat 10 000spotřeba tariff=high 700 kWh a tariff=low 300 kWh; náklad jedna řada tariff=total 12 100 / 10 000
jen price / priceWithoutVat, žádné invoiceValuejen nákladové řady tariff=total; fakturovaná spotřeba nevzniká
navíc invoiceValue costWithoutVat VT 8 000, NT 2 000 (F353)nákladové řady tariff=high 8 000 a tariff=low 2 000 místo řady total; zápis se odmítne, když Σ per tarif ≠ priceWithoutVat

Cena se nikdy nerozpočítává na tarify poměrem kWh — VT a NT mají různé sazby a výsledek by byl smyšlený.

Co test ověřuje. Směr dopočtu; sazba podle média a dateFrom; chybějící sazba; tolerance 0,5 p. b. jako varování; záporné řady; reprodukovatelnost po změně číselníku; rozpad po tarifech.


CC-12 · Spotřeba objektu per médium — systémové virtuální měřidlo (US1, US3, US5, OR-10) ​

Situace. Dům: elektřina MG-E3 (include) + MG-E4, MG-E5 (subGauge, reportOnly); voda MG-W1 + MG-W2, MG-W3 (CC-07); plyn MG-G2 (include). Systém založil tři isSystemManaged virtuální měřidla: VG-E MG-E3, VG-W MG-W1, VG-G MG-G2.

Vstupy. Efektivní spotřeba členů pro 2026-01-15T10:00Z: MG-E3 2,000000 (manual), MG-E4 0,400000, MG-E5 0,350000, MG-W1 0,018985, MG-G2 3,627981 (kWh).

Výpočet. Pro každý interval a každé VG: vyhodnotit vzorec nad efektivní spotřebou členů (ne nad odečty); uložit se source=calculated. Verze vzorce platná pro daný interval (OR-10 formula version). Chybí-li kterýkoli člen v intervalu, řádek VG nevzniká.

Datové věty

gaugeIdslotAtkindtypedirectiontariffsourcevalueunit
VG-E Dům — elektřina celkem2026-01-15T10:00Zconsumptionenergyimporttotalcalculated2.000000kWh
VG-W Dům — voda celkem2026-01-15T10:00Zconsumptionvolumeimporttotalcalculated0.018985m³
VG-G Dům — plyn celkem2026-01-15T10:00Zconsumptionenergyimporttotalcalculated3.627981kWh

Tři média = tři virtuální měřidla = tři řádky; nikdy jeden řádek „objekt celkem“ přes média. Součet elektřina + plyn (kWh) vznikne až při čtení po převodu na společnou jednotku a výsledek to říká.

Kontrolní součty (leden). VG-E = Σ MG-E3 = 880 × (podíl v lednu) — ne + MG-E4 + MG-E5; VG-W = 56,5 m³; VG-G = Σ MG-G2.

Varianty

ZměnaCo se stane
MG-E4 přepnuto na subtract (nájemce s vlastní smlouvou, US4)nová verze vzorce VG-E MG-E3 − MG-E4 od data změny; interval 10:00Z → 1,600000; předchozí intervaly beze změny
MG-E4 a MG-E5 obě subtract (US4)2,0 − 0,4 − 0,35 = 1,250000
MG-E3 nemá pro 10:15Z hodnotu v žádném zdrojiVG-E 10:15Z bez řádku; period total označí pokrytí 95 / 96
ruční odečet MG-E3 opravenpřepočet MG-E3 → invalidace VG-E ve stejném okně → přepočet souhrnů; VG-E updatedBy=system:consumption-recalculation
priorita MG-E3 změněnaMG-E3 řádky beze změny, VG-E se přepočte (staví na efektivní hodnotě)

Co test ověřuje. Jedno VG na médium; reportOnly mimo součet; subtract odečítá; verze vzorce; žádná hodnota při chybějícím členu; kaskáda přepočtu.


CC-13 · Objekt s fotovoltaikou — směr a znaménka (US2, OR-10) ​

Situace. Škola: MG-E1 odběr ze sítě (import, include), MG-E6 přetoky do sítě (export, reportOnly), MG-E7 výroba FVE (export, reportOnly). Systém součet nesestaví (dva reportOnly exporty) a upozorní; uživatel založil VG-S FVE vlastní spotřeba MG-E7 − MG-E6 a VG-B Škola — elektřina celkem MG-E1 + VG-S (isSystemManaged=false).

Vstupy (2026-01-15T10:00Z, efektivní): MG-E1 2,000000 · MG-E6 0,300000 · MG-E7 0,750000 kWh. Měsíčně (příklad Epicu): 8 000 / 1 200 / 3 000 kWh.

Výpočet. VG-S = 0,75 − 0,30 = 0,450000; VG-B = 2,0 + 0,45 = 2,450000. Vyhodnocení topologicky: VG-B až po VG-S. Za leden VG-S = 1 800, VG-B = 9 800 kWh.

Datové věty

gaugeIdslotAtkindtypedirectiontariffsourcevalueunit
MG-E62026-01-15T10:00Zconsumptionenergyexporttotalremote0.300000kWh
MG-E72026-01-15T10:00Zconsumptionenergyexporttotalremote0.750000kWh
VG-S2026-01-15T10:00Zconsumptionenergyimporttotalcalculated0.450000kWh
VG-B2026-01-15T10:00Zconsumptionenergyimporttotalcalculated2.450000kWh

Exportní řady se ukládají kladně s direction=export; znaménko dává až vzorec. Graf „pod osou“ = řada MG-E6, ne záporný řádek.

Kontrolní součty. Leden: VG-B 9 800; MG-E6 (export, pod osou) 1 200; bez VG-S by objekt ukázal 8 000 — o 1 800 méně. Závazné je nastavení z Implementation examples 1 US2 (export + reportOnly + uživatelský vzorec; R-7, potvrzeno 2026-09-22). Stránka outputMode + direction (556400657, naposledy 17. 7. 2026) a z ní převzatý enum GaugePurpose.fveProduction (include + import) jsou starší než Gauge Management (3. 9.) a Implementation examples (16. 9.) a mají se podle nich opravit — vlastní je Gauge Management, zde se neupravují.

Vlastní spotřeba z výroby (VG-S = výroba − přetoky) je údaj, který klienti potřebují u každého objektu s výrobou. V US2 vzniká v průvodci jako uživatelské VG; doporučení pro Gauge Management: zakládat ho automaticky a systémově spravované pro každé výrobní měřidlo, s přetoky jako volitelným členem (instalace bez měřených přetoků → vlastní spotřeba = celá výroba). Na výpočet v tomto epicu to nemá vliv — VG se vyhodnotí stejně, ať ho založil uživatel nebo systém.

Co test ověřuje. Uložení exportu kladně; uživatelský vzorec se zápornou položkou; závislé VG v pořadí; hodnota 9 800 vs. 8 000.


CC-14 · Spotřeba za areál — součet přes objekty při čtení (special US1) ​

Situace. Areál Kampus = objekt A (MG-A1 hlavní, include; MG-A2 podružné reportOnly) a objekt B (MG-B1 podružné pod MG-A1, fyzicky v B, reportOnly). Uživatel po upozornění založil VG-A MG-A1 − MG-B1 a VG-B MG-B1. Druhý areál Kampus 2 má objekt C bez include měřidla (žádný uznaný součet).

Vstupy (2026-01-15T10:00Z, efektivní): MG-A1 2,000000 · MG-A2 0,500000 · MG-B1 0,600000.

Výpočet. Nic se pro areál neukládá. Při dotazu na areál se výběr rozloží na množinu měřidel, deduplikuje, každému se jednou přiřadí znaménko z outputMode × direction, reportOnly/exclude nevstupují; součty objektů se nesčítají. Kampus = {MG-A1 (include, +)} = 2,000000. Kontrola: VG-A + VG-B = 1,4 + 0,6 = 2,0 — shoda, protože každé měřidlo je započteno jednou.

Datové věty. Uložené jsou jen:

gaugeIdslotAtsourcevalue
VG-A Objekt A celkem2026-01-15T10:00Zcalculated1.400000
VG-B Objekt B celkem2026-01-15T10:00Zcalculated0.600000

Žádný řádek pro Kampus.

Kontrolní součty (period total, leden, groupBy=building)

VýběrVýsledekPokrytí
Kampus, elektřinaΣ MG-A1gauges 3, s daty 3, objekty bez součtu 0
Kampus, groupBy=buildingA = Σ VG-A, B = Σ VG-B
Kampus 2Σ include měřidel = 0 řádkůobjekty bez součtu 1 — číslo se nevrací jako 0 bez varování
Kampus, elektřina + plyndvě položky per médium; společný součet jen po převodu na kWh a s příznakem
výběr obsahuje neexistující gaugeIdchyba, ne menší součet

Co test ověřuje. Součet přes měřidla, ne přes objekty; deduplikace; pokrytí a objekty bez součtu; média zvlášť; chyba při neznámém měřidle.


CC-15 · Náklad objektu — jen měřidla v bilanci provozovatele (OR-4) ​

Situace. Dům (US4): MG-E3 hlavní (include), MG-E4 nájemce s vlastní smlouvou (subtract), MG-E5 podružné (reportOnly). Faktury: MG-E3 leden 12 100 s DPH (CC-09). Nájemcova faktura na MG-E4 (3 000 s DPH) je v systému jen informativně; MG-E5 faktury nemá.

Výpočet (R-8, rozhodnuto 2026-09-22). Náklad objektu = Σ nákladových řad měřidel s outputMode=include a direction=import. subtract, reportOnly a exclude nevstupují — nájemcova faktura jsou peníze, které provozovatel neplatí, a znaménko ze vzorce spotřeby na peníze přenést nelze (odečtení 3 000 by dalo 9 100 Kč bez reálného významu; u exportu by dobropis dokonce přičetlo). Export (include/export) je výnos a vykazuje se zvlášť. Tím platí OR-4 (rozhoduje tentýž atribut outputMode, žádné nové nastavení) i feature doc Cost Calculation (finanční zahrnutí není znaménková aritmetika). Čistý náklad po přeúčtování nájemci je samostatná funkce (odchozí faktury), mimo tento epic.

Datové věty. Náklad objektu se neukládá jako řada VG (nákladové řady mají invoiceId, které by u VG nedávalo smysl) — sčítá se při čtení stejně jako areál. R-9.

Kontrolní součty (leden, s DPH)

SituaceNáklad objektuPoznámka
MG-E3 12 100, MG-E4 (subtract) 3 00012 100,00nájemcova faktura nevstupuje; pokrytí: 1 faktura mimo bilanci
MG-E4 přepnut na include (provozovatel platí i nájemce)15 100,00
přetoky MG-E6 (include/export) mají dobropis −50012 100,00; výnos 500,00 zvlášťne 12 600 ani 11 600
chybná implementace „znaménko ze vzorce“9 100,00hodnota, kterou test hlídá, že nevznikne

Co test ověřuje. Vstupují jen include/import; export je výnos; přepnutí outputMode mění náklad od data změny.


CC-16 · Přepočet po opravě — idempotence a rozsah (OR-9) ​

Situace. MG-G1 z CC-05. 10. 2. uživatel opraví odečet z 1. 2. z 13 000 na 12 950 m³ (rozdíl 950 m³) a 12. 2. přidá objemový koeficient manual 1,0300 s validFrom=2026-01-16.

Krok 1 — oprava odečtu. Invalidace: MG-G1, manual, okno [01-01T08:00Z, 02-01T08:00Z). Nová hodnota 950 × 1,0234 × 10,55 = 10 257,03 kWh, 3,446581 / 3,446582 na interval. Všech 2 976 řádků upsert; updatedAt = čas přepočtu, updatedBy=system:consumption-recalculation; createdAt zůstává. Dálková řada beze změny. VG s MG-G1 jako členem přepočteno, souhrny obnoveny.

Krok 2 — nový koeficient. Invalidace od 2026-01-15T23:00Z (16. 1. lokálně) do konce okna, jen řada manual. Vstupní rozdíl je jeden (950 m³ za období), koeficient ale platí po intervalech — R-10: koeficient se aplikuje na intervalový objem, tj. interval před 16. 1. 0,319220 m³ × 1,0234 × 10,55, od 16. 1. × 1,0300 × 10,55; období tak má dva různé řádky hodnot (3,446581 → 3,468809). Součet za období už není 950 × jeden koeficient.

Datové věty (po kroku 2)

gaugeIdslotAtsourcevalueupdatedBy
MG-G12026-01-15T22:45Zmanual3.446581system:consumption-recalculation
MG-G12026-01-15T23:00Zmanual3.468809system:consumption-recalculation

Kontrolní součty. Opakované spuštění téhož přepočtu nezmění žádný řádek (porovnat updatedAt). Během přepočtu vrací period total pro MG-G1 příznak provisional. Po dokončení: žádný řádek se createdAt novějším než původní výpočet (upsert, ne delete-insert).

Co test ověřuje. Rozsah invalidace (jen zdroj, jen okno / od validFrom); idempotence; provizorní stav; kaskáda do VG a souhrnů.


Pokrytí Confluence příkladů ​

ConfluencePřípad
Epic 3.1 — příklad plynoměrCC-05
Epic 3.1 — příklad faktura za ledenCC-09, CC-10
Epic 3.1 — příklad objekt s FVECC-13
Implementation examples 1 — US1 (2 standardní)CC-01, CC-12
Implementation examples 1 — US2 (4Q + FVE)CC-13
Implementation examples 1 — US3 (podružná reportOnly)CC-07, CC-12
Implementation examples 1 — US4 (podružná subtract)CC-12 varianta, CC-15
Implementation examples 1 — US5 (více médií)CC-12
Implementation examples 2 — US1 (podružné v jiném objektu)CC-14
Implementation examples 2 — US2 (objekt třetí strany, exclude)CC-14 varianta: MG exclude nevstupuje, include podružné definuje součet
Souhrn výpočtu a evidence spotřeby — efektivní spotřebaCC-08
Spotřeba virtuálního měřidla (719290369) — 100 − 20 − 15 = 65CC-12/CC-13 stejný mechanismus

Pravidla doplněná tímto dokumentem ​

Projednáno s Pablem 2026-09-22; všechna pravidla jsou rozhodnutá. Kde z nich plyne změna jiného artefaktu, je uvedena ve sloupci Dopad.

#PravidloKde se projevíStavDopad
R-1Rozklad hodnoty do intervalů kumulativním zaokrouhlením (6 míst veličiny, 2 místa peníze) — jediný algoritmus pro spotřebu i náklad, přesný součet za každý úsek. EM2 dělil ve float bez zaokrouhlení (F238).všechny rozkladyrozhodnutofeature docs Consumption / Cost Calculation: doplnit algoritmus
R-2Odečty v libovolném čase: kumulativní registr je po částech lineární funkce času, hodnota čtvrthodiny = rozdíl registru na jejích hranicích; krajní čtvrthodiny částečné; delta/average podle překryvu. Platí pro ruční i dálkové odečty.CC-01, CC-03, CC-04, CC-06rozhodnutofeature doc Consumption Calculation: nahradit „spread evenly“ / „store directly“ tímto pravidlem
R-3Energie se ukládá vždy v kWh bez ohledu na gauge.unit (GJ, MWh)CC-06rozhodnutogauge.unit přeformulovat na jednotku zobrazení (Gauge Management)
R-4Nákladová řada je z invoice.price jedna (tariff=total); spotřební řady source=invoice per tarif podle invoiceValue; náklad per tarif jen z explicitních invoiceValue položek cost*, Σ musí sedět na fakturuCC-11rozhodnuto—
R-5Profil pro rozklad nákladu = řada remote, jinak manual, jinak rovnoměrně (ne efektivní řada — ta se mění s prioritou)CC-10rozhodnutofeature doc Cost Calculation: upřesnit „profile“
R-6invoiceId je součástí identity řádku (faktura + dobropis na stejném období)CC-11rozhodnutoentita consumption: uq_consumption_slot rozšířen o invoiceId — provedeno na této větvi
R-7FVE: výroba export/reportOnly + uživatelský vzorec podle Implementation examples 1 (validované, 16. 9. 2026)CC-13rozhodnutoopravit stránku outputMode + direction 556400657 (17. 7. 2026, zastaralá) a z ní převzatý enum GaugePurpose.fveProduction (include + import → export + reportOnly); zvážit automatické systémové VG „vlastní spotřeba z výroby“ (Gauge Management)
R-8Náklad objektu = Σ nákladů měřidel include/import; subtract/reportOnly/exclude nevstupují; export je výnosCC-15rozhodnutofeature doc Cost Calculation: sekce Cost of a building přepsat tímto pravidlem
R-9Náklad objektu se neukládá jako řada VG, sčítá se při čteníCC-15rozhodnuto—
R-10Koeficient s validFrom uvnitř odečtového období se aplikuje po intervalech, ne na celý rozdílCC-16rozhodnuto—
R-11Nulový rozdíl dálkového registru zakládá řádek 0; chybějící dávka řádek nezakládáCC-01rozhodnuto—

Co v repu tento dokument neřeší ​

  • Fixture pro automatické testy (UUID, seed) — vznikne v EM3 podle těchto případů.
  • Odečty typu average pro KVP (teplota, CO₂) — nejsou spotřeba, do consumption nevstupují.
  • Média fuel a phm — rozdílová logika stejná jako plyn (objem × výhřevnost podle primarySource), samostatný případ až po rozhodnutí o jednotkách (t, l).