@golemio/energetics 2.0.0-dev.2922626380 → 2.0.0-dev.2962537365
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/db/example/09_enapo_consumption_history.sql +52 -11
- package/db/migrations/postgresql/20261013090000-enapo-ave-zero-core.js +53 -0
- package/db/migrations/postgresql/20261013090100-enapo-consumption-history-gas.js +53 -0
- package/db/migrations/postgresql/20261019090000-enapo-consumption-history-invoice-zero.js +53 -0
- package/db/migrations/postgresql/sqls/20261013090000-enapo-ave-zero-core-down.sql +1 -0
- package/db/migrations/postgresql/sqls/20261013090000-enapo-ave-zero-core-up.sql +7 -0
- package/db/migrations/postgresql/sqls/20261013090100-enapo-consumption-history-gas-down.sql +511 -0
- package/db/migrations/postgresql/sqls/20261013090100-enapo-consumption-history-gas-up.sql +492 -0
- package/db/migrations/postgresql/sqls/20261019090000-enapo-consumption-history-invoice-zero-down.sql +492 -0
- package/db/migrations/postgresql/sqls/20261019090000-enapo-consumption-history-invoice-zero-up.sql +495 -0
- package/dist/integration-engine/enapo/transformations/PPasMeasurementTransformation.d.ts +2 -2
- package/dist/integration-engine/enapo/transformations/PPasMeasurementTransformation.js +8 -5
- package/dist/integration-engine/enapo/transformations/PPasMeasurementTransformation.js.map +1 -1
- package/dist/output-gateway/routers/v2/V2EnoBuildingsRouter.d.ts +4 -1
- package/dist/output-gateway/routers/v2/V2EnoBuildingsRouter.js +17 -5
- package/dist/output-gateway/routers/v2/V2EnoBuildingsRouter.js.map +1 -1
- package/docs/implementation_documentation.md +7 -5
- package/docs/openapi-output.yaml +3 -1
- package/package.json +1 -1
|
@@ -492,6 +492,7 @@ Metoda sbírá data o spotřebách od poskytovatele komodit - PPAS (Pražská pl
|
|
|
492
492
|
- PPAS (Pražská plynárenská) InternetAVE API
|
|
493
493
|
- transformace
|
|
494
494
|
- [PPasMeasurementTransformation](../src/integration-engine/enapo/transformations/PPasMeasurementTransformation.ts)
|
|
495
|
+
- nulový `OperatingAmount` (`core`) se zahazuje: kumulativní stav měřidla nikdy není nula, AVE tak posílá hodinu bez odečtu a nula by rozbila měsíční rozdíl v `mv_enapo_om_consumption`. Už uložené nuly maže migrace `20261013090000-enapo-ave-zero-core`
|
|
495
496
|
- data modely
|
|
496
497
|
- [EnapoMeasurementsModel](../src/schema-definitions/models/EnapoMeasurementsModel.ts) tabulka `enapo_measurements`
|
|
497
498
|
|
|
@@ -717,13 +718,13 @@ Task přegeneruje materializovaný pohled `mv_enapo_om_consumption`, ze kterého
|
|
|
717
718
|
- prod `0 45 3 * * *`
|
|
718
719
|
- samotná definice cronu je vedena mimo tento repozitář (deployment konfigurace)
|
|
719
720
|
- spouštění na základě událostí
|
|
720
|
-
- žádné, a to záměrně: [EnapoPpasTask](#task-enapoppastask) stahuje po pětidenních intervalech a spouštěl by desítky refreshů za jeden běh, přičemž endpoint stejně garantuje svěžest jen na 6 hodin
|
|
721
|
+
- žádné, a to záměrně: [EnapoPpasTask](#task-enapoppastask) stahuje po pětidenních intervalech a spouštěl by desítky refreshů za jeden běh, přičemž endpoint stejně garantuje svěžest jen na dobu cache (hlavička `s-maxage`, výchozích 6 hodin; per env ji nastavuje proměnná `ENERGETICS_DED_BUILDING_CACHE_MAX_AGE` v sekundách, na OG se předává přes `extraEnvVars` v infrastruktuře, neplatná hodnota zachová výchozí). Jde o sdílenou cache (CDN), takže ji z prohlížeče obejít nejde
|
|
721
722
|
- data modely
|
|
722
723
|
- [EnapoConsumptionHistoryIndexRepository](../src/integration-engine/enapo/repositories/EnapoConsumptionHistoryIndexRepository.ts) — `REFRESH MATERIALIZED VIEW CONCURRENTLY energetics.mv_enapo_om_consumption`, kontrakt [IEnapoConsumptionHistoryIndexRepository](../src/integration-engine/enapo/repositories/interfaces/IEnapoConsumptionHistoryIndexRepository.ts)
|
|
723
724
|
- funkce
|
|
724
725
|
- **CONCURRENTLY**: refresh neblokuje čtenáře; vyžaduje unikátní index nad `(gid, place_id, commodity, source, unit, period_type, period_start)` (vytvořen migrací) a **nesmí běžet v transakci**. Nenaplněný pohled (`pg_matviews.ispopulated = false`) `CONCURRENTLY` odmítne, proto ho repository v takovém případě obnoví obyčejným `REFRESH` (platí pro všechny pohledy nad `AbstractMaterializedViewIndexRepository`). Migrace `20260923090000` pohled vytváří rovnou naplněný, takže endpoint funguje hned po nasazení
|
|
725
|
-
- zdroj `energy_broker` = jednorázově naimportovaná historie z Energy Brokera (`enapo_eb_consumption`, MWh → kWh pro elektřinu i plyn, m³ z EB spočítat nelze). Bere se jen záznam přesně za kalendářní měsíc (delší/neúplná období čekají na metodiku rozpadu). Totéž EAN/EIC pod dvěma `idodbmistoom` se bere jednou (nejnovější řádek). Měsíc, který živý zdroj (PRE, PPAS) přečetl celý, nerozpočítaně a v kWh, EB přenechá živým datům, aby se v grafu nezdvojil. Měsíc s plynoměrem PPAS (jen m³) EB ponechá, protože jinak by spojitá kWh řada v tom měsíci neměla hodnotu
|
|
726
|
-
- spojitou řadu pro graf skládá až output gateway (`ConsumptionHistoryBuilder.buildCombined` → `consumption_history.combined` za budovu a `combined_history` za OM): pro každé OM a měsíc vybere jeden řádek s kWh — živý zdroj, který měsíc přečetl celý a nerozpočítaně (pořadí PPAS měřené, PRE, Porsenna, distribuční, obchodní faktura), jinak EB, jinak částečný/rozpočtený živý údaj — a výběry sečte přes OM. Každé období nese `sources`, odkud hodnota je, a `points_total` počítá všechna OM řady v každém období, aby OM bez výběru bylo vidět jako chybějící data. Řada je vždy v kWh; měřený plyn PPAS (jen m³) se jí proto
|
|
726
|
+
- zdroj `energy_broker` = jednorázově naimportovaná historie z Energy Brokera (`enapo_eb_consumption`, MWh → kWh pro elektřinu i plyn, m³ z EB spočítat nelze). Bere se jen záznam přesně za kalendářní měsíc (delší/neúplná období čekají na metodiku rozpadu). Totéž EAN/EIC pod dvěma `idodbmistoom` se bere jednou (nejnovější řádek). Měsíc, který živý zdroj (PRE, PPAS) přečetl celý, nerozpočítaně a v kWh, EB přenechá živým datům, aby se v grafu nezdvojil. Měsíc s plynoměrem PPAS (jen m³) EB ponechá, protože jinak by spojitá kWh řada v tom měsíci neměla hodnotu — výjimkou je měsíc, kdy plynoměr naměřil nulovou spotřebu: 0 m³ je 0 kWh za celý měsíc, takže vyhrává plynoměr a EB se v tom měsíci neukáže
|
|
727
|
+
- spojitou řadu pro graf skládá až output gateway (`ConsumptionHistoryBuilder.buildCombined` → `consumption_history.combined` za budovu a `combined_history` za OM): pro každé OM a měsíc vybere jeden řádek s kWh — živý zdroj, který měsíc přečetl celý a nerozpočítaně (pořadí PPAS měřené, PRE, Porsenna, distribuční, obchodní faktura), jinak EB, jinak částečný/rozpočtený živý údaj — a výběry sečte přes OM. Každé období nese `sources`, odkud hodnota je, a `points_total` počítá všechna OM řady v každém období, aby OM bez výběru bylo vidět jako chybějící data. Řada je vždy v kWh; měřený plyn PPAS (jen m³) se jí proto účastní jen v měsících s nulovou spotřebou (0 m³ je 0 kWh bez ohledu na přepočet)
|
|
727
728
|
- pohled je omezen na posledních 48 měsíců, aby refresh nemusel procházet celou historii; endpoint standardně vrací 36 (`?months=`, max 48)
|
|
728
729
|
- sloupec `invoice_ids` nese doklady, ze kterých bylo období rozpočteno (prázdné pole u měřených a Porsenna řad). Roční řádky ho neskládají z měsíčních polí — `array_agg` nad poli různé délky spadne a sjednocovací agregát nad polem v PG není — ale rollupem přímo z fakturačních řádků (CTE `invoice_device_month` → `invoice_month` / `invoice_year`)
|
|
729
730
|
- `enapo_measurements` má ~45 mil. řádků a jediný index byl primární klíč, jehož vedoucí sloupec je pro tento průchod nepoužitelný — migrace proto přidává `enapo_measurements_source_var_ts_idx (source, var, timestamp)`; bez něj trval elektroměrový agregát 5 min 45 s a plynový 1 min 24 s
|
|
@@ -772,7 +773,7 @@ Sloupec `value` míchá **kumulativní stavy měřidla** a **rozdíly za interva
|
|
|
772
773
|
| -------------- | ----------- | ---------------------------------- | ----------- | -------------------------------------------------- | -------- | --------------------------------------------------- |
|
|
773
774
|
| `ppas_ave_api` | plyn | `corediff` | hodinová | **rozdíl** (`OperatingDifference`) | m³ | `sum`, jen registrace (viz níže) |
|
|
774
775
|
| `ppas_ave_api` | plyn | `core2` | hodinová | **rozdíl**, přepočtený (`ConvertDifference`) | Nm³ | `sum`, jen registrace (viz níže) |
|
|
775
|
-
| `ppas_ave_api` | plyn | `core` | hodinová | **kumulativní** stav měřidla (`OperatingAmount`)
|
|
776
|
+
| `ppas_ave_api` | plyn | `core` | hodinová | **kumulativní** stav měřidla (`OperatingAmount`); nula se neukládá (AVE ji posílá za hodinu bez odečtu) | m³ | rozdíl 1. dne měsíce a 1. dne dalšího ← **primární v `mv_enapo_om_consumption.gas_metered`** |
|
|
776
777
|
| `predi_input` | elektřina | `EActi_VT_NT_DaySum` | denní | **odvozený součet** VT+NT | **kWh** | `sum` ← **primární** |
|
|
777
778
|
| `predi_input` | elektřina | `EActi_VT_DaySum` / `_NT_DaySum` | denní | denní energie; NT je dnes všude nulové | **kWh** | `sum` (jen fallback) |
|
|
778
779
|
| `predi_input` | elektřina | `EFwActi_VT` / `_NT` | 15 min | průměrný **výkon**, tedy 4× energie | kW | **nepoužívat** (`sum / 4` by byly kWh) |
|
|
@@ -787,7 +788,7 @@ Další ověřené vlastnosti dat, na které agregace spoléhá:
|
|
|
787
788
|
|
|
788
789
|
- `id_type` **není spolehlivý** — v produkci je aspoň jedno elektroměrové EAN uložené s `id_type = 'eic'`, takže join na měření jde výhradně přes `enapo_measurements.id` a `id_type` se nefiltruje
|
|
789
790
|
- `enapo_gid_mapping.place_id` je **kód EAN/EIC**, zatímco `enapo_measurements.place_id` je interní PPAS place id — join `place_id = place_id` vrací nula řádků a vypadá jako „nejsou data“
|
|
790
|
-
- jedno EIC může mít několik `place_id
|
|
791
|
+
- jedno EIC může mít několik `place_id` — buď několik měřidel, nebo dvě registrace jednoho fyzického měřidla. `mv_enapo_om_consumption.gas_metered` proto páruje `core(1. den dalšího měsíce) - core(1. den měsíce)` na granularitě `(id, place_id)` a rozdíly sečte přes `place_id` daného EIC; napříč celým EIC (bez vazby na `place_id`) by `core` rozdíl byl rozpětím mezi dvěma nesouvisejícími počítadly. Registrace bez `core` odečtů do součtu nic nepřidá, takže se spotřeba nezdvojí. Párování **není** podle `device_serial_number`: integrace razítkuje každou (i znovu staženou) hodinu sériovým číslem, které AVE uvádí v okamžiku stažení, takže po výměně plynoměru se historie přeznačí a dvě měřidla jednoho EIC mohou sdílet jedno číslo. Měsíc, jehož součet vyjde záporný (výměna nebo reset měřidla), zůstává prázdný.
|
|
791
792
|
|
|
792
793
|
#### _PPAS Distribution API_
|
|
793
794
|
|
|
@@ -807,6 +808,7 @@ Další ověřené vlastnosti dat, na které agregace spoléhá:
|
|
|
807
808
|
- `ZSCBM3` (M3, 49 EIC) — nese 92 % objemu `ZIZWC` z devítiny jeho EIC; vyloučeno jako bezpečnější strana otevřené otázky (chybějící řada se vrací jako `null`, zdvojené číslo by se tvářilo jako platné)
|
|
808
809
|
- sloupec `consumption` je denominovaný podle `unit` (M3 / NM3 / KWH), **není to vždy m³**
|
|
809
810
|
- `combustion_heat` a `volume_coefficient` s hodnotou 0 znamenají „nedodáno“, ne nulu — bez `NULLIF` by se z odvozených kWh stala nula, která se na grafu kreslí jako skutečný odečet
|
|
811
|
+
- měsíc **bez spotřeby** PPAS fakturuje s prázdným `consumption` a nulovými `normometers_nm3` i `gas_consumption_kwh` (explicitní `consumption = 0` se v datech nevyskytuje; ověřeno 2026-10-19, ~5 600 takových řádků). `mv_enapo_om_consumption` takový řádek bere jako 0 m³ a 0 kWh — nulová spotřeba je 0 kWh bez ohledu na přepočet, takže tu `NULLIF` neplatí. Řádek bez `consumption` i bez Nm³/kWh (všechno `NULL`) nic neříká a zůstává chybějícím údajem
|
|
810
812
|
- existují **duplicitní faktury bez vazby přes `preceding_id`** nesoucí bajtově shodné řádky pro totéž EIC a období; deduplikace proto musí jít podle obsahu řádku `(eic, place_id, device_serial_number, date_from, date_to, kind, reading_type, unit)`, nikoli podle návaznosti faktur
|
|
811
813
|
- `mv_enapo_om_consumption` zatím bere jen `reading_type = 'STANDARD'`. Protože CORRECTION je storno (viz výše, negativní consumptionKwh), znamená to, že se storna neodečítají a spotřeba je **nadhodnocená o ~0,68 %**. Vědomé zjednodušení první verze: znaménko nese pouze `gas_consumption_kwh`, `consumption` zůstává pozitivní, takže naivní součet by v jednom sloupci odečítal a ve druhém přičítal
|
|
812
814
|
- formát dat
|
package/docs/openapi-output.yaml
CHANGED
|
@@ -1068,7 +1068,9 @@ components:
|
|
|
1068
1068
|
nullable: true
|
|
1069
1069
|
description: >-
|
|
1070
1070
|
Comparable energy. For gas this is derived (normometers_nm3 * combustion_heat) and is
|
|
1071
|
-
null whenever the conversion inputs are missing
|
|
1071
|
+
null whenever the conversion inputs are missing. Zero consumption is 0 regardless of the
|
|
1072
|
+
conversion inputs, so metered gas (m3 only) reports 0 for a month without consumption
|
|
1073
|
+
and null otherwise.
|
|
1072
1074
|
coverage_count:
|
|
1073
1075
|
type: number
|
|
1074
1076
|
description: Days of the period carrying data.
|