Appearance
Formulář objektu — zadání
Jeden formulář pro založení i úpravu objektu, postavený jako detail s bočním panelem (šablona design systému e-manažer, stejně jako Formulář měřidla). Vlevo strom majetku, vpravo hlavička s KPI, SubNav a DetailCard se dvěma sekcemi; pod kartou blok archivace. Detail se edituje na místě — samostatný režim čtení ani stránka /edit neexistují (kapitola 4).
Obrazovky: Claude Design canvas „Založení objektu — e-manažer DS“ (https://claude.ai/artifact/MkHyG9Arvhqr4KVyFKcxVk, verze 18, 6. 10. 2026: artboardy Detail objektu, Po vytvoření, Historie hodnoty, Uložení změn, Archivovat objekt); Figma Majetek — Objekt · Detail (583:9486, hlavička 1392:25102). Anglický feature doc: index.md. Vzor zadání: Formulář měřidla.
Stav kódu, proti kterému je zadání psané: EM3 origin/main e516b77c6 (6. 10. 2026, PR #370), analytické repo origin/main d1e2240 (5. 10. 2026, PR #28 Odečty v55, PR #32 Měřidlo v16). Rozdíly proti kódu jsou v kapitole 6, otevřené body v kapitole 7.
Rozsah: tři typy objektu (Budova, Veřejné osvětlení, Ostatní), záložka Detail (Identifikace objektu, Parametry objektu, archivace), formulář založení (varianta A — samostatná stránka /buildings/new, varianta B — modál nad přehledem), jednotný vzor Historie pro verzovaná pole napříč objektem, měřidlem a odečty (kapitola 5). Mimo rozsah: záložky Souhrn, Měřidla, Rozvrh, Dokumenty, Odpovědné osoby, Opatření, Uživatelé, Provoz; vzorec souhrnu objektu (Gauge Management); normalizace (Epic 3.2); pasport objektu (Epic 1.2, v2).
1. Typ objektu a Areál
Objekt má Typ (Budova · Veřejné osvětlení · Ostatní), který se po uložení nemění (změna bude oprávnění správce, až bude hotová správa uživatelů). Typ řídí, které sekce a pole se zobrazují: Veřejné osvětlení nemá adresu ani souřadnice, má Počet RVO, Počet světelných bodů a Z toho s FVE; PENB a obálka budovy se zobrazují jen u Budovy.
Areál (rozhodnuto 30. 9. a 1. 10. 2026) je obálka, která pod sebe řadí budovy: nemá měřidla, parametry ani spotřebu vlastní (spotřeba areálu = součet budov), ale lze podle něj filtrovat a seskupovat v seznamech, grafech a reportech. Ve formuláři je to jedno pole „Areál“ (Combobox nad uzly úrovně campus klienta, nepovinný, prázdná volba Bez areálu, položka + Nový areál = rychlé založení jen s názvem). Pole Úroveň a Nadřazený objekt ve formuláři nejsou; úrovně portfolio a region jsou systémové a uživatel je nikdy nevidí, floor a unit se v UI nenabízejí (pasport, v2).
Technicky Areál zůstává uzlem stromu (building.levelType = campus, parentId budovy = areál; Data Model v Confluence: „CAMPUS is the only level users set manually on a building — Campus field on the building detail, auto-create“). Pravidla navíc: na uzel campus nelze přiřadit měřidlo ani parametry; uzel campus se nevrací v seznamu objektů, v exportu ani v KPI počtech; areál bez budov lze smazat, s budovami jen přejmenovat nebo sloučit.
2. Pořadí sekcí a pravidlo
Pravidlo: pole, které mění podobu formuláře, je nad poli, která mění — proto je Typ objektu první pole Identifikace.
| # | Kde | Sekce | Obsah |
|---|---|---|---|
| 1 | Detail | Identifikace objektu | typ, sektor, název, ID, areál, vlastník / přenesená správa / správce, GID, adresa, mapa a souřadnice, rok výstavby, klimatická stanice, památková ochrana, popis, fotografie |
| 2 | Detail | Parametry objektu | verzované stavební a energetické parametry včetně PENB a obálky budovy (přesun z Hospodaření s energií) |
| — | Detail, pod kartou | Archivovat objekt | blok Archivovat / Smazat objekt jako u měřidla |
| 3 | Hospodaření s energií | Zařazení do EH · Projekty a programy | beze změny (Figma 1392:24668); PENB, Obálka a VO odcházejí na Detail |
| 4 | Rozvrh | Provozní rozvrh | verze rozvrhu (existuje); textová Provozní doba z Hospodaření sem |
Mřížka 4 sloupce (24 × 16 px), sekce oddělené SectionDivider, bez mezinadpisů uvnitř sekce, rytmus 40 px; ★ = povinné. Formulář založení (A i B) má jen pole Typ★, Sektor, Název★, Areál v pořadí Detailu; po Vytvořit a otevřít detail se otevře Detail v režimu úprav s předvyplněnými hodnotami a štítkem Nový · neúplné údaje (zmizí po doplnění adresy a aspoň jednoho parametru).
3. Sekce a pole
Sloupec EM3 uvádí pole entity a stav v kódu e516b77c6: BE+API+FE = hotovo, BE = jen v databázi a entitě (DTO ani frontend ho nevystavují), demo = frontend kreslí zástupnou hodnotu, — = neexistuje.
3.1 Identifikace objektu
| Pole | ★ | Podmínka | Pravidlo | EM3 |
|---|---|---|---|---|
| Typ objektu | ★ | Budova · Veřejné osvětlení · Ostatní; po uložení zamčený (zašedlý se zámkem). | building.type · BE+API+FE | |
| Sektor | Výběr ze sektorů klienta, default Nezařazeno; bez hodnoty „vše“ (to je filtr seznamu). Po uložení zamčený. | building.sectorId · BE+API+FE; FE nabízí placeholder „vše“ | ||
| Název objektu | ★ | 2–120 znaků, unikátní mezi sourozenci (v rámci areálu, resp. na nejvyšší úrovni). | building.name · BE+API+FE | |
| ID identifikace objektu | jen uložený | Jen ke čtení; u migrovaných objektů EM2 id, u nových interní id. | building.legacyId · BE; FE demo | |
| Areál | Combobox nad uzly campus klienta; Bez areálu; + Nový areál. Kapitola 1. | building.parentId · BE+API; FE má obecný výběr Nadřazený objekt + zamčenou Úroveň (D1) | ||
| Vlastník · Přenesená správa · Správce | Combobox nad registrem subjektů (název nebo IČO), volba + Nový subjekt; bez tlačítka ARES, které by přepsalo název (Subjekty, D12). Pod polem poznámka o propojeném subjektu. | ownerId / delegatedManagerId / managerId + snapshot *Name / *Ico · BE+API+FE | ||
| GID | jen klienti regionu Praha s oprávněním | Textové pole; skryté, pokud klient nemá příznak. | building.gid · BE | |
| Ulice · Číslo popisné · Číslo orientační · PSČ · Obec | ne u Veřejného osvětlení | PSČ přesně 5 číslic, po opuštění pole doplní Obec (lze přepsat). Popisek třetího pole je Číslo orientační (ne „evidenční“, D2). | street / houseNumber / referenceNumber / zip / city · BE+API+FE | |
| Zobrazit na mapě | ne u VO | Přepínač Ano / Ne; default Ano. | building.showOnMap · BE; FE demo | |
| Vlastní souřadnice: šířka · délka | ne u VO | Pár — obě, nebo žádná. Geokódování z adresy plní jen lat/lng, vlastní pár nikdy nepřepisuje. | latCustom / lngCustom · BE+API+FE | |
| Odkaz na Mapy.com | ne u VO | Odkaz bez popisku na lince vstupů; z účinných souřadnic; bez souřadnic se nezobrazí. | mapyComUrl (počítané) · BE+API+FE | |
| Rok výstavby | Celé číslo 1000–aktuální rok. | building.yearBuilt · BE; FE demo | ||
| Klimatická stanice | Výběr ze stanic; návrh podle polohy jen do prázdného pole. | building.climateStationId · BE+API+FE | ||
| Památkově chráněný objekt | Přepínač Ano / Ne (přesun ze zrušené sekce Zařazení). | building.isHeritage · BE | ||
| Popis | Textarea, 3 řádky, max. 1000 znaků; přes 3 sloupce. | building.description · BE+API+FE | ||
| Fotografie objektu | Nahrání JPG / PNG do 10 MB přes files (karanténa, antivirus); jedna hlavní fotografie. | building.photoFileId · BE; FE demo |
3.2 Parametry objektu
Pole označená ⟳ jsou verzovaná a mají Historie podle kapitoly 5. Pořadí podle zadání z 23. 9. 2026.
| Pole | Jednotka | Podmínka | Pravidlo | EM3 |
|---|---|---|---|---|
| Počet aktivních uživatelů ⟳ | os. | Celé číslo ≥ 0. | buildingParameter.userCount · BE; FE ukazuje occupancy „Obsazenost“ (D3) | |
| Celková energeticky vztažná plocha ⟳ | m² | Budova | > 0. | buildingParameter.areaEnergyReference · BE; FE ukazuje floorArea „Celková plocha“ (D3) |
| Celková užitná plocha ⟳ | m² | Budova | > 0. | buildingParameter.areaUsable · BE; FE ukazuje heatedArea „Vytápěná plocha“ (D3) |
| Celková plocha ⟳ | m² | Budova | > 0; navíc oproti EM2. | — nový sloupec (areaTotal); dnes FE zobrazuje legacy floorArea pod tímto popiskem (D3) |
| Obestavěný prostor ⟳ | m³ | Budova | > 0. | buildingParameter.volumeEnclosed (DAT po PR #37: EM2 building_built_up_area je obestavěný prostor v m³, areaBuiltUp zrušen) · BE má zatím areaBuiltUp; FE demo |
| Objemový faktor A/V | m²/m³ | Budova | 0–2, 2 desetinná místa. | buildingEnergyProfile.factorAv · BE+API+FE (na Hospodaření) |
| Počet podlaží | Budova | Celé číslo ≥ 1. | buildingEnergyProfile.floorCount · BE+API+FE (na Hospodaření); FE Detail demo | |
| Převažující vnitřní teplota ⟳ | °C | Budova | −50…50. | buildingParameter.temperatureReference · BE+API+FE, popisek „Referenční teplota“ (D3) |
| Jmenovitý výkon zdroje | kW / MW | Výkon · jednotka · původní zápis z EM2 (jen čtení). | installedPowerKw / installedPowerUnit / installedPowerRaw · BE+API+FE (na Hospodaření) | |
| Uem vypočtené · Uem referenční | W/m²K | Budova | ≥ 0. | uemCalculated / uemReference · BE+API+FE (na Hospodaření) |
| Celková dodaná energie: hodnocená · referenční | kWh/m² | Budova | ≥ 0. | penbTotalEnergy / penbTotalEnergyRef · BE+API+FE (na Hospodaření) |
| Neobnovitelná primární energie: hodnocená · referenční | kWh/m² | Budova | ≥ 0. | penbNonRenewableEnergy / penbNonRenewableEnergyRef · dtto |
| Měrná dodaná energie: vytápění · ohřev TUV | kWh/m² | Budova | ≥ 0. | penbHeatingConsumption / penbHotWaterConsumption · dtto |
| Hodnocení budovy dle ENB | Budova | Select A–G. | penbClass · dtto | |
| Počet RVO | Veřejné osvětlení | Celé číslo ≥ 0. | buildingEnergyProfile.rvoCount · BE+API+FE (na Hospodaření) | |
| Počet světelných bodů ⟳ · Z toho s FVE ⟳ | Veřejné osvětlení | FVE ≤ světelné body. | buildingParameter.lightPoints / lightPointsPv · BE+API+FE |
Verzování: buildingParameter je jeden záznam s jedním Platí od pro všechna ⟳ pole; buildingEnergyProfile má čtyři skupiny (obálka, PENB, VO, programy), každá s vlastním Platí od. Na obrazovce je to pro uživatele neviditelné — všechna pole se ukládají jedním Uložit změny a volba Platí od se dělá jednou pro celé uložení (kapitola 5.3). Které parametry se skryjí u typu Ostatní, je otevřený bod 4.
4. Režim úprav
Uživatel po otevření záložky Detail edituje rovnou. Dokud nic nezmění, je vpravo v hlavičce Historie (historie záznamu, kapitola 5.1) a KPI; po první změně se hlavička přepne na Vrátit změny / Uložit změny (nový objekt: Zrušit / Vytvořit a otevřít detail) a v kartě je nahoře i v patičce pill „Režim úprav · N neuložených změn“. Pole bez oprávnění a pole zamčená po uložení (typ, sektor) jsou zašedlá se zámkem a nápovědou, proč jsou zamčená; neskrývají se. Ve formuláři nejsou žádné zástupné hodnoty „Připravujeme“ — každé pole je buď editovatelné, nebo zamčené se zámkem, nebo na obrazovce není (dnes FE kreslí devět polí jako nepropsatelné demo zástupce z hashe id objektu, viz D3, D4 a D5). Odchod s neuloženými změnami se potvrzuje (Zahodit / Zůstat / Uložit a pokračovat).
Pravidla proti přepsání zadaných dat (potvrzeno 24. 9. 2026): geokódování plní jen prázdné souřadnice; klimatická stanice se navrhne jen do prázdného pole; změna Typu pole skryje, hodnoty smaže až při uložení s upozorněním; Historie a Vygenerovat pasport jen bez neuložených změn.
Archivace: pod kartou blok Archivovat objekt s popisem a tlačítky Archivovat (dialog: důvod archivace ze čtyř hodnot, upozornění na kaskádu na měřidla a podřízené objekty, přepínač Zobrazovat v reportech i po archivaci) a Smazat objekt (jen objekt bez měřidel, odečtů, faktur a podřízených objektů). Volba Zobrazovat v reportech i po archivaci je v dialogu archivace, ne ve formuláři — stejně jako u měřidla (building.showArchivedInReports).
5. Jednotný vzor Historie
Dnes má aplikace tři různé podoby: objekt (Figma / canvas) kreslí pole s připojeným segmentem Historie a nápovědou „Platí od“, kód objektu má tlačítko Historie vpravo od popisku s vyskakovací tabulkou, Hospodaření má vlastní Platnost od + Uložit v každé skupině, měřidlo v16 má segment Historie u pole a tlačítko Historie v hlavičce, odečty mají ikonu hodin na řádku. Sjednocení platí pro objekt, měřidlo i odečty a doplňuje design systém e-manažer (design-system/components.md).
5.1 Dva druhy historie
| Historie záznamu (audit log) | Historie hodnoty (verzované pole) | |
|---|---|---|
| Co ukazuje | kdo, co a kdy změnil na celém záznamu (objekt, měřidlo, odečet, dokument) | jaká hodnota platila od kdy — časová řada verzí jednoho pole nebo skupiny polí |
| Zdroj | audit-log, sdílená komponenta Per-Record History | validFrom verze entity (buildingParameter, buildingEnergyProfile, gaugeDistributionRateHistory, gaugeUsageAllocation, buildingSchedule …) |
| Vstup | hlavička detailu: tlačítko Historie s ikonou hodin, secondary, vlevo od Vrátit změny; řádek seznamu: ikona hodin mezi Detail a Smazat | pole: připojený segment Historie (addon InputField / Select, text bez ikony) + pod polem nápověda „Platí od D. M. RRRR“; skupina polí (PENB, obálka, programy, rozdělení užití): tlačítko Historie secondary sm v záhlaví skupiny + nápověda „Platí od D. M. RRRR“ pod nadpisem skupiny |
| Cíl | modál Historie záznamu (audit log) | modál Historie hodnoty (5.2) |
Ikona hodin patří jen historii záznamu; historie hodnoty je vždy textový segment nebo tlačítko Historie, aby se oba vstupy nepletly.
5.2 Modál Historie hodnoty
Modal md (pole) / lg (skupina). Titulek: název pole nebo skupiny; podtitulek: objekt nebo měřidlo. Tabulka: Platí od · hodnota (u skupiny sloupec na každé pole, vodorovné rolování) · Změnil · Kdy, seřazená od nejnovější; platná verze zvýrazněná štítkem Platná, verze s datem v budoucnu štítkem Od budoucna. U pole se zobrazují jen verze, ve kterých se hodnota pole změnila (po sobě jdoucí stejné hodnoty se slučují). Prázdný stav „Zatím žádná historie“. Akce: Zavřít; Otevřít historii záznamu (proklik na 5.1) pro dohledání, kdo změnu udělal. Žádná editace v modálu.
5.3 Uložení verzované změny
Při Uložit změny s aspoň jednou změnou verzované hodnoty se otevře dialog Uložit změny: Nová verze od data (výchozí dnes, datum nejde před Platí od platné verze) × Oprava platné verze (ponechá Platí od, nahradí hodnoty). Jedna volba pro všechny verzované změny v jednom uložení, i když patří různým entitám. Nová verze se stejným Platí od jako platná verze = oprava (nahrazení) — tím je sjednoceno s pravidlem rozdělení užití u měřidla. Specifická omezení data zůstávají u svých entit (distribuční sazba: Platí od po posledním ručním odečtu). Historie nejde otevřít nad polem s neuloženou změnou.
5.4 Kde se vzor použije
| Obrazovka | Historie záznamu | Historie hodnoty |
|---|---|---|
| Objekt · Detail | hlavička | ⟳ pole Parametrů; skupiny PENB a Obálka |
| Objekt · Hospodaření s energií | hlavička | skupina Projekty a programy |
| Objekt · Rozvrh | hlavička | seznam verzí rozvrhu zůstává (verze = celá mřížka), popisek Platí od; tlačítko Historie v záhlaví otevírá tentýž seznam |
| Měřidlo · Detail | hlavička | distribuční sazba, tarify, jistič, výrobní číslo, jednotka, koeficient, účel užití kanálu, vzorec |
| Měřidlo · Odečty | řádek ručního odečtu; dialog Detail odečtu | — |
| Seznamy (objekty, měřidla, dokumenty, subjekty) | ikona hodin na řádku | — |
Při založení (nový objekt, nové měřidlo) se Historie nezobrazuje nikde — první verze vzniká uložením s Platí od = datum založení.
6. Rozdíly proti kódu (origin/main e516b77c6)
| # | Kde | Stav v kódu | Zadání |
|---|---|---|---|
| D1 | FE building-form-identification.tsx, building-placement-field.tsx | Detail má zamčenou Úroveň a obecný výběr Nadřazený objekt (strom, „Bez zařazení“); story Parent Node Display Corrections chtěla dropdown Areál jen z uzlů campus. Založení (creation/) nabízí Úroveň i Nadřazený objekt. | Jedno pole Areál (kapitola 1); Úroveň a Nadřazený objekt pryč z obou formulářů; levelType nastaví FE podle typu (building), campus jen přes + Nový areál. |
| D2 | FE cs_CZ.json | fields.referenceNumber = „Číslo evidenční“, fields.city = „Město“, fields.temperatureReference = „Referenční teplota“. | „Číslo orientační“, „Obec“, „Převažující vnitřní teplota“. |
| D3 | BE DTO add-building-parameter.dto.ts, FE building-form-parameters.tsx, migrace | API i FE pracují jen s floorArea / heatedArea / occupancy; entita a migrace mají areaEnergyReference / areaUsable / areaBuiltUp / userCount, ale DTO je nevystavuje. Migrace mapuje EM2 building_heated_area → heatedArea a areaEnergyReference nechává NULL. DAT buildingParameter po PR #37 zná jen areaEnergyReference, areaUsable, volumeEnclosed, userCount, temperatureReference, lightPoints(Pv). | Kód sladit s DAT: userCount nahradí occupancy, areaEnergyReference nahradí heatedArea, areaBuiltUp přejmenovat na volumeEnclosed (m³); mapper migrace podle slovníku; legacy trojici odstranit; pro Celkovou plochu založit areaTotal. |
| D4 | BE DTO create-building.dto.ts, update-building.dto.ts, FE | yearBuilt, showOnMap, isHeritage, gid, photoFileId, legacyId jsou v entitě, ne v DTO; FE je kreslí jako demo zástupce (placeholder-field.tsx, demo-data.ts). | Vystavit v DTO (PATCH i POST kromě legacyId), FE nahradit demo zástupce skutečnými poli; fotografie přes files upload. |
| D5 | FE energy-profile/* | PENB, obálka, VO a programy jsou na záložce Hospodaření s energií, každá skupina s vlastním Platnost od + Uložit změny / Vrátit změny. | PENB, obálka a VO na Detail do Parametrů; jedno Uložit změny pro celou stránku; Platí od jen v dialogu uložení (5.3). Programy zůstávají na Hospodaření se stejným vzorem. |
| D6 | FE versioned-field.tsx, group-history-timeline.tsx | Historie je tlačítko accent sm vpravo od popisku, popover s tabulkou Platnost od · hodnota; skupinová historie je tlačítko v záhlaví sekce s popoverem. | Segment Historie u pole + nápověda „Platí od“, tlačítko v záhlaví skupiny; oba otevírají modál Historie hodnoty (5.2) se sloupci Změnil · Kdy a štítkem Platná. |
| D7 | FE building-form-parameters.tsx (useParameterDraft.save) | Uložení vždy zapíše novou verzi s validFrom = dnes; oprava platné verze neexistuje. | Dialog Uložit změny (5.3); BE: POST /v1/buildings/:id/parameters přijme validFrom shodné s platnou verzí jako nahrazení (nebo nový PATCH na verzi). |
| D8 | FE building-form-identification.tsx (ShowArchivedCell) | Zobrazovat v reportech i po archivaci je checkbox v Identifikaci. | Jen v dialogu archivace (kapitola 4). |
| D9 | FE building-form-identification.tsx | Sektor má placeholder „vše“ (building.filters.all). | Default Nezařazeno, bez „vše“. |
| D10 | FE building-card-tabs.tsx, building-detail-page.tsx | Záložka Struktura zrušena, panel podstromu na detailu; blok Archivovat / Smazat objekt pod kartou chybí — archivace je v hlavičce (building-archive-dialog.tsx). | Blok pod kartou jako u měřidla; dialog zůstává. |
| D11 | Analytický doc index.md | Popisuje strom s Úrovní a Nadřazeným objektem, PENB na Hospodaření, bez vzoru Historie hodnoty. | Doplnit odstavec Areál = campus bez měřidel a parametrů, odkaz na toto zadání a na kapitolu 5; stories Parent Node Display Corrections, Move Guard Parity a Subtree Panel and Object Assignment sladit. |
7. Otevřené body
| # | Otázka | Návrh |
|---|---|---|
| 1 | docs/migration/slovnik-em2-em3.md, ř. 102 a 592): EM2 „Vytápěná plocha“ (building_heated_area) = EM3 areaEnergyReference („Energeticky vztažná plocha“, stejná hodnota, jiný název); building_usable_area → areaUsable, building_built_up_area → areaBuiltUp. | Migrace (building-parameter.mapper.ts ř. 83–85) plní heatedArea a areaEnergyReference nechává NULL — opravit podle slovníku; trojici floorArea / heatedArea / occupancy z API i FE odstranit (D3). Celková plocha je nové pole bez EM2 předlohy — založit areaTotal (legacy floorArea DAT už nezná). |
| 2 | building_built_up_area eviduje obestavěný prostor v m³, DAT má volumeEnclosed a areaBuiltUp ruší; zastavěná plocha se v EM3 neeviduje. | Kód přejmenuje sloupec (D3). |
| 3 | secondary sm — stejný vzor jako podsekce Odběrného místa u měřidla; datum jen v dialogu uložení. | — |
| 4 | Které parametry se skryjí u typu Ostatní? | Ostatní = jako Budova bez PENB a obálky (jen plochy, uživatelé, teplota). K potvrzení. |
| 5 | Dědí se Sektor, adresa nebo klimatická stanice z areálu? | Jen při založení do prázdných polí (sektor a klimatická stanice ano, adresa ne). |
| 6 | create-building.dto.ts přijímá volitelně responsibleUserIds (min. 1, je-li uvedeno); formulář založení A/B odpovědné osoby nemá. | Založení přiřadí zakládajícího uživatele automaticky (Confluence: „assigns the current user“); pole se při založení nezobrazuje, osoby se řeší na záložce Odpovědné osoby. |
| 7 | „Budova pod budovou“ (MŠ pod ZŠ) ze zadání 23. 9. bez pole Nadřazený objekt nejde zadat. | Nepodporovat v v1; nahradit druhým areálem. Pokud to EM2 data obsahují, migrace je zploští pod areál. |
| 8 | Oprava platné verze u buildingParameter: nový endpoint, nebo POST …/parameters se shodným validFrom? | POST se shodným validFrom = nahrazení (idempotentní), jak to má rozdělení užití; rozhodnutí D4 z Creation Contract Hardening nedotčeno. |