Appearance
Client Management
Business Context
Business-Level Definition
A client is the top-level organisational unit in the system. Every object, gauge, user, document and operational record belongs to exactly one client.
The client record defines:
- the identity of the organisation
- its system-wide behavioural settings
- the licence governing access to features
- the set of add-on modules available to its users
The client domain also manages the registry of all legal entities and associated persons — building owners, managers, tenants, contracted service providers and others. This registry (Organisations) is the single source of truth for subject data referenced across buildings and gauges.
Requirements Definition
Client management must support:
- Creating and editing client records with full identification, system settings, distribution territory, licence and module configuration
- Managing the registry of organisations (legal entities and natural persons) linked to a client
- Assigning weather stations to a client and displaying climate data at monthly, daily and hourly granularity
- Configuring consumption tolerances per gauge type and energy medium
- Managing a three-level hierarchy of calorific values (system default → client override → per-gauge individual)
- Managing a three-level hierarchy of emission factors (system default → client override → per-gauge individual)
- Configuring the notification dispatch matrix (notification type × user role × delivery form)
- Viewing and configuring API connectors including pairing of unmatched remote endpoints with gauges
- Controlling access to add-on modules and features through a per-client module catalogue
- Storing and evaluating EnMS data: EnPI indicators, SEU definition and organisation-level targets and certification status
Acceptance Criteria
- A client record can be created, viewed and edited through the UI and API
- Client identification fields (IČO) support ARES lookup: typing a company name or IČO returns matching results; selecting one populates name and IČO automatically
- System settings (reading cycle, VAT display, prediction, gauge lifecycle) are saved and immediately reflected in all downstream calculations
- The distribution territory section stores a default electricity distributor and gas distributor with a per-client flag for whether all consumption points share a single distributor
- Licence fields (type, level, validity date) are editable only by users with the admin role; an invalid or expired licence does not restrict access — instead, a persistent warning banner is displayed on every screen informing the user that the licence has expired
- Module assignments are editable only by users with the admin role; a module that is not assigned is not visible to any user of that client
- A new organisation (legal entity or natural person) can be added to the registry, edited and linked to buildings and gauges; the registry aggregates subjects from all sources automatically
- ARES lookup is available on the organisation form; a natural person can be entered without an IČO
- An organisation can be deleted only when it is not referenced in
building.ownerId,building.managerId,building.delegatedManagerId, orgauge.subscriberId; a409 Conflictresponse is returned with the list of referencing records if deletion is blocked - Each client can have one default weather station and additional supplementary stations; the default station is set and changed via the API; a supplementary station can be assigned to a specific building; climate data table supports monthly, daily and hourly granularity; hourly granularity is available for any station with a connected remote source (
weatherStation.remoteConnectionIdset), regardless of tier - The long-term climate normal (historical monthly averages from ČHMÚ) can be displayed for each assigned weather station
- The Tolerances tab displays two separate views of the same underlying data — manual reading tolerances and consumption anomaly alert thresholds — both backed by
clientTolerance; each view has its own rows and save action; invoice validation tolerances are out of scope for v1 - Tolerance overrides are stored per (medium, primarySource) combination; combinations without an override fall back to system defaults (±20%); the UI pre-populates rows from the client's actual gauge combinations
- Calorific value resolution follows the precedence: per-gauge individual → client override → system default; the client calorific values tab shows all three tiers for the client's gauge combinations and allows editing the client-level tier
- Emission factors follow the same three-tier resolution and editing model as calorific values
- The notification matrix is initialised with 7 notification types (see "Notification matrix" below) and their seeded defaults; the matrix can be configured per (type, role) cell; "Reset to defaults" restores all cells to the seeded values
- API connectors are listed with status, endpoint counts and the configurable outage threshold; unmatched endpoints can be paired with gauges individually or in bulk
- EnMS tab stores EnPI definitions, SEU method and included objects, and organisation-level numerical and textual targets; ISO 50001 certification dates and certifying body are stored when the client is certified
- Summary tab data is composed client-side from multiple domain endpoints (KPI data from Data Collection, alerts from Actions, users from Users & Access, connector status from API connectors); no dedicated summary endpoint is provided in v1
Loom Link
N/A — not available in the source material.
Technical Context
User Stories / Use Cases
View client summary: A manager opens a client and sees a summary dashboard with key consumption KPIs, recent alerts, user list and API connector status. The Summary tab is composed client-side from multiple existing API endpoints.
Edit client identification and settings: A user with edit rights opens the Detail tab and updates identification fields, system settings or distribution territory. Changes are saved atomically. Changing the VAT display setting when zero-VAT invoices exist triggers a warning.
Configure modules: An admin enables or disables add-on modules for a client. The change takes effect immediately — non-assigned modules disappear from navigation for all users of that client. Enabling iso50001 atomically creates a clientEnms record.
Manage organisations: An energy manager opens the Organisations tab, which lists all subjects referenced anywhere in the client. The manager adds a new organisation by searching ARES or entering a natural person manually. The manager edits an existing organisation's contact persons, bank details and billing address.
Manage weather stations: A manager assigns a default weather station (from the global catalogue or a client's own station) and optionally assigns supplementary stations to specific buildings. The manager views monthly climate data and exports it to XLSX. For each assigned station the manager can display the station's long-term climate normal.
Configure tolerances: A manager opens the Tolerance tab and sees two views — manual reading tolerances and consumption anomaly alert thresholds — both reading from the same clientTolerance entity. Each view has its own rows (pre-populated from the client's gauge combinations) and its own save action.
Configure calorific values: A manager opens the Calorific Values tab and sees all three tiers for the client's gauge combinations. The manager sets a client-level override; from that point the system uses the override for all gauges of that combination that do not have an individual value.
Configure emission factors: Same flow as calorific values, using the Emission Factors tab.
Configure notifications: A manager opens the Notifications tab, reviews the matrix and toggles cells to enable or disable email dispatch per notification type and role. The manager changes the delivery form for a notification type — this updates all rows of that type atomically.
Manage API connectors: A manager opens the API Connectors tab, checks the status of each connector, adjusts the outage threshold for a connector, expands the list of unmatched endpoints and pairs them with the correct gauges.
Manage EnMS: An energy manager opens the EnMS tab, records the ISO 50001 certification dates, selects the SEU method (TOP N / percentage threshold / coverage target) and adjusts the EnPI list.
UI/UX Design
A click-through prototype exists covering all client tabs. Detailed UI/UX design (spacing, component specs, responsive behaviour) has not been completed. Acceptance criteria describe functional behaviour only.
Note: the Tolerance tab (K4) screen is not yet present in the prototype — the tab is listed among the client tabs but has no corresponding screen in the prototype's screen set. The design is pending.
Per-record history wireframes. Three tabs carry a "Historie" entry point onto that tab's own record (see Audit Log — Per-Record History component for the shared destination view and its two entry-point conventions): Detail (header button, including the centered before/after table), Klimadata (header button, on the assigned weather station in the context of its assignment to the client) and Emisní faktory (per-row icon, mirroring the Výhřevnost table's own pattern below).
Functional Requirements
Client tabs
The client detail page is organised into the following tabs:
| UI label (CZ) | UI label (EN) | Description |
|---|---|---|
| Souhrn | Summary | Dashboard: consumption KPIs, recent alerts, user list, API connector status. Data composed client-side from multiple domain endpoints. |
| Detail | Detail | Identification, system settings, licence, modules |
| Klimadata | Climate data | Assigned weather stations, meteogram GPS, climate data table, long-term normals |
| Tolerance | Tolerances | Two views of clientTolerance data: manual reading tolerances and consumption anomaly alert thresholds. Invoice validation tolerances out of scope v1. |
| Výhřevnosti | Calorific values | Three-tier calorific value management |
| Emisní faktory | Emission factors | Three-tier emission factor management — visible only when the emissionFactors module is enabled |
| Přehled organizací | Organisations | Registry of all subjects linked to the client |
| Uživatelé | Users | User list — managed via the Users & Access domain |
| Notifikace | Notifications | Notification dispatch matrix |
| API konektory | API connectors | Remote source connectors and endpoint pairing |
| EnMS | EnMS | ISO 50001 EnPI, SEU and organisational targets — visible only when the iso50001 module is enabled |
Client identification
The Detail tab identification section stores:
A client's membership in one or more client groups (named, capacity-bounded tags used for reporting and permission-scoping) is managed on its own screen, not this tab — see Client Groups.
client.type(enumClientType) — determines which fields are displayedclient.icowith ARES lookup — see External Integrations — ARESclient.name, address (.street,.houseNumber,.orientationNumber,.zip,.municipality),.lat/.lng.regionIdclient.population,.buildingCountOwned,.otherFacilityCount— manually entered reference values
System settings
The system settings section stores behavioural defaults that apply across all buildings and gauges of the client:
| Setting | Attribute | Description |
|---|---|---|
| Main manager | client.mainManagerId | Reference to the user acting as the default responsible person; their contact details are shown to field workers |
| Default action deadline | client.defaultActionDeadlineDays | Default number of days used when generating action deadlines automatically; falls back to 7 if null |
| Monthly reading cycle day | client.gaugeMonthControlDaySetting / .gaugeMonthControlDay | Mode: first day of month / last day of month / custom day; custom day is 1–28 |
| Weekly reading cycle day | client.gaugeWeekControlDay | Day of the week on which the weekly reading cycle starts |
| Display expenses without VAT | client.displayExpensesWithoutVat | When enabled, all invoice and report expense values are shown excluding VAT |
| Show prediction | client.showPrediction | How many years of consumption prediction to display (0 = none, 1, 2, 3, 9) |
| Include other factors in prediction | client.includeOtherElementsInPrediction | When enabled, energy prices and weather data feed into consumption predictions |
| Gauge reading reminder | client.gaugeReadingReminder | Master on/off for gauge reading reminder emails across the whole client |
| Gauge limit notification delay | client.gaugeLimitNotificationDelayHours | Hours before the first limit-overflow notification fires; falls back to system default if null |
| Gauge limit notification frequency | client.gaugeLimitNotificationFrequencyHours | Hours between repeated limit-overflow notifications; falls back to system default if null |
| Reference medians | client.median / .republicMedian | Client-specific and republic-wide consumption baseline values for comparison in reports |
| Electricity distributor | client.electricityDistributorId | Default electricity distributor for the client, referenced from the shared price-decision registry |
| Single electricity distributor | client.singleElectricityDistributor | When enabled, all electricity measuring points share this distributor; when disabled, each electricity OM must expose an individual distributor field |
| Gas distributor | client.gasDistributorId | Default gas distributor for the client, referenced from the shared price-decision registry |
| Single gas distributor | client.singleGasDistributor | When enabled, all gas measuring points share this distributor; when disabled, each gas OM must expose an individual distributor field |
Cross-feature dependency: client.singleElectricityDistributor and .singleGasDistributor drive conditional field visibility on individual measuring points — when .singleElectricityDistributor = false, each electricity OM must expose an individual distributor field; when .singleGasDistributor = false, each gas OM must expose an individual distributor field.
Implementation note for Gauge Management: the conditional visibility of the distributor field on an OM record depends on these client-level flags.
Licence
The licence section is editable by admin-role users only.
| Field | Attribute | Values / Notes |
|---|---|---|
| Licence type | client.licenceType | enum LicenceType: indefinitePeriod / timeLimit / autoExtension |
| Licence level | client.licenceLevel | enum LicenceLevel: demo / basic / extended |
| Licence valid to | client.licenceValidTo | Required for timeLimit and autoExtension; ignored for indefinitePeriod |
Licence validity is computed at runtime. An invalid or expired licence does not restrict system access or functionality. Instead, the system displays a persistent warning banner on every screen, informing the user that the licence has expired. This applies to all users regardless of role.
Add-on modules
Each client has a set of enabled add-on modules stored in clientModule. A module not present in the client's set is invisible to all users of that client. All add-on modules are initially (by default) disabled.
| Module key | Description |
|---|---|
invoiceImport | Automated invoice import via API connectors. Separate from remoteReadings. |
buildingPassport | Building passportisation and passport generation |
iso50001 | ISO 50001 EnMS features. Gates the EnMS tab. Enabling this module atomically creates a clientEnms record. |
emissionFactors | CO₂ emission factor management. Gates the Emission Factors tab. |
energySharing | Community energy sharing and allocation keys (EDC) |
settlement | Consumption settlement across consumption points |
consumptionMonitoring | Consumption monitoring rules, alerts and discrepancies |
tariffOptimisation | Tariff and circuit-breaker optimisation suggestions |
Organisation registry
The Organisations tab shows all legal entities and natural persons referenced anywhere in the client's data, stored as organisation records. ARES lookup is available; natural persons are entered without IČO. The list supports filtering and user-configurable columns.
Delete reference check: checks building.ownerId, building.managerId, building.delegatedManagerId, gauge.subscriberId. If referenced, returns 409 Conflict with {"error": "ORGANISATION_REFERENCED", "referencedIn": [...]}. The client itself cannot be deleted.
Climate data (weather stations)
- Default station —
client.defaultWeatherStationId; used for degree-day normalisation across all buildings without a building-level override - Supplementary stations —
clientWeatherStationrows; building-level assignment takes precedence over the client default
The climate data table shows monthly heating days, average temperature, degree-days (D21) and difference against the long-term normal.
Long-term climate normal (dlouhodobý normál): Per-station long-term reference averages (average temperature and degree-days) — period length and data source are a business decision, not a system constraint. Stored per station, not per client. Accessible via GET /v1/weather-stations/:id/normals. For each assigned station the user can open a pop-up showing the monthly normal values.
Consumption tolerances
The Tolerance tab presents two views of the same underlying clientTolerance entity. Both views share the same lookup key (medium, primarySource) and the same toleranceMin/toleranceMax values. The UI presents them as two separate sections with their own rows and save actions, but they read from and write to the same table.
View 1 — Manual reading tolerances: Applied when a manual reading value is entered. A reading is flagged when it deviates more than toleranceMin (lower) or toleranceMax (upper) from the rolling average. System default: ±20%. UI slider: ±25%.
View 2 — Consumption anomaly alerts: Applied during automated remote reading processing. The same toleranceMin/toleranceMax values are used to detect anomalous consumption (order-of-magnitude deviation from rolling average). This is consistent with EM2 behaviour where gauge_tolerance_types served both purposes.
Invoice validation tolerances are out of scope for v1. The invoice validation tolerance section will be added as a separate entity in a future epic.
The UI pre-populates rows from the client's distinct (medium, primarySource) combinations. A row is persisted only when its values differ from the system default.
Calorific values — three-tier hierarchy
- Per-gauge individual value — highest precedence; set on the gauge detail
- Client value —
calorificValuewith no gauge set; the only tier this tab edits - Platform default —
defaultCalorificValue, maintained by the platform operator; read-only here - Per-gauge individual value — highest precedence
- Client override —
calorificValuewith no gauge set - Platform default —
defaultCalorificValue, maintained by the platform operator
Every tier carries its own validity date, and resolution picks the most specific scope holding a value valid on the date being computed — see Calorific Value Management.
Every tier carries its own validity date, and resolution picks the most specific scope holding a value valid on the date being computed — see Calorific Value Management.
The tab shows one row per combination of medium and primary source the client's gauges use, with the value applying today and the tier it comes from (Výchozí / Vlastní / Individuální), a row marked Chybí where no tier holds a value, and a coverage indicator (gauges without any resolved value) in the header — all returned by one GET /v1/client/calorific-values (the client is the request's tenant, so no id in the path). Values are dated and append-only: a new or corrected client value is a POST with its own validFrom, never an in-place update; a value entered in error is withdrawn ("Vzít zpět") and stays in the row's history. Screen states, dialogs and history: Calorific Value Management — UI/UX Design; endpoints: API analysis.
Emission factors — three-tier hierarchy
Same three-tier resolution as calorific values; client-level overrides in clientEmissionFactor. Tab visible only when the emissionFactors module is enabled.
Notification matrix
Stored per client in clientNotification. Delivery form is per notification type (not per role cell) — a PATCH must write the same value to all rows with the same (clientId, notificationType).
v1 catalogue:
| Key | EM2 equivalent | Admin | Manager | Worker | Technician | Accountant | Default delivery |
|---|---|---|---|---|---|---|---|
readingDueReminder | emailReminder | ✓ | ✓ | ✓ | — | — | Immediate |
dailyEventsReport | emailReporting | ✓ | ✓ | — | — | — | Daily summary |
gaugeLimitOverflow | incidentEmailReporting | ✓ | ✓ | — | ✓ | — | Immediate |
missingReadingRemote * | — | ✓ | ✓ | — | ✓ | — | Daily summary |
fileExpiring * | — | ✓ | ✓ | — | — | ✓ | Daily summary |
remoteEndpointUnmatched | — (new in EM3) | ✓ | — | — | — | — | Daily summary |
contractPriceExpiring | — (new in EM3) | ✓ | ✓ | — | — | ✓ | Immediate |
* role/delivery values for missingReadingRemote and fileExpiring are a first draft.
SMS delivery channel: decided separately in a child migration-map page (out of scope for this pass); sms_reporting kept as a hidden attribute, no UI exposure (for v1).
API connectors
Each connector (apiConnector) linked to the client via many-to-many join; contains one or more apiConnectorEndpoint records each mapping to one gauge. Tab shows connector status, endpoint counts, and unmatched endpoint pairing.
EnMS (ISO 50001)
Visible only when iso50001 module is enabled. Data across three entities: clientEnms, clientEnpi, clientEnmsTarget.
Permissions model
Pending — to be defined during Users & Access design. Admin-only sections: Licence, Add-on modules.
Per-record history
The Detail, Klimadata and Emisní faktory tabs each carry a "Historie" entry point onto their own record's change history (client, weatherStation/clientWeatherStation, clientEmissionFactor respectively) — the same audit trail as Audit Log, reached in place rather than via the investigation surface. See UI/UX Design above for each tab's own wireframe and review status.
Soft-delete cascade
When a client is soft-deleted, the following child entities are soft-deleted atomically: clientModule, clientTolerance, clientNotification, calorificValue, clientEmissionFactor, clientEnms, clientEnpi, clientEnmsTarget, organisation. Buildings and gauges are archived per Building Management lifecycle.
Non-Functional Requirements
Transactional Operations
- Client creation (default modules + notification matrix) must be atomic
- Enabling
iso50001and creatingclientEnmsmust be atomic - Notification matrix save and
deliveryFormupdate must be atomic per operation - Organisation creation and update must be atomic
- Calorific value and emission factor saves must be atomic per row
- Client soft-delete cascade must be atomic
API Analysis
Client core:
GET /v1/clients
GET /v1/clients/:id
POST /v1/clients
PATCH /v1/clients/:id
GET /v1/clients/exports (note: /exports avoids routing conflict with /:id)Organisation registry (page-based pagination):
GET /v1/clients/:id/organisations
GET /v1/clients/:id/organisations/:orgId
POST /v1/clients/:id/organisations
PATCH /v1/clients/:id/organisations/:orgId
DELETE /v1/clients/:id/organisations/:orgId (409 if referenced; see delete spec above)Climate data, weather stations, normals:
GET /v1/clients/:id/climate
GET /v1/clients/:id/climate/exports
PATCH /v1/clients/:id/weather-stations (set default + supplementary assignments)
GET /v1/weather-stations/:id/normals (monthly long-term normals from ČHMÚ)Tolerances — two sub-resources for the two UI views, both backed by clientTolerance:
GET /v1/clients/:id/tolerances/readings Manual reading tolerance overrides
PATCH /v1/clients/:id/tolerances/readings
GET /v1/clients/:id/tolerances/anomaly Consumption anomaly alert threshold overrides
PATCH /v1/clients/:id/tolerances/anomalyCalorific values and emission factors (calorific values: the client is the request's tenant — no client id in the path, see Calorific Value Management API-A):
GET /v1/client/calorific-values (rows per combination, three tiers, coverage indicator)
GET /v1/client/calorific-values/history (one combination's client values)
POST /v1/client/calorific-values (new dated client value)
PATCH /v1/client/calorific-values/:id (citation only)
DELETE /v1/client/calorific-values/:id (withdraw a value entered in error)
GET /v1/clients/:id/emission-factors
PATCH /v1/clients/:id/emission-factorsNotification matrix:
GET /v1/clients/:id/notifications
PATCH /v1/clients/:id/notifications (deliveryForm update applies to all rows of same type)
POST /v1/clients/:id/notifications/resetAPI connectors:
GET /v1/clients/:id/connectors
PATCH /v1/clients/:id/connectors/:connId
POST /v1/clients/:id/connectors/:connId/pairEnMS (no pagination on targets/enpis — bounded):
GET /v1/clients/:id/enms
PATCH /v1/clients/:id/enms
GET /v1/clients/:id/enms/targets
POST /v1/clients/:id/enms/targets
PATCH /v1/clients/:id/enms/targets/:targetId
DELETE /v1/clients/:id/enms/targets/:targetId
GET /v1/clients/:id/enms/enpis
POST /v1/clients/:id/enms/enpis
PATCH /v1/clients/:id/enms/enpis/:enpiId
DELETE /v1/clients/:id/enms/enpis/:enpiIdDomain Model (ER diagram) & Data Attribute Table
No ER diagram in source material. Related entity pages (Confluence, not yet migrated into this repo's Entity DAT catalog):
- client — core client record, system settings, licence, default weather station
- clientModule — enabled add-on modules per client
- organisation — legal entities and natural persons linked to the client
- clientWeatherStation — supplementary weather station assignments
- clientTolerance — tolerance overrides (manual reading + anomaly detection, two UI views)
- calorificValue — calorific values at client and gauge scope, each with its own validity
- clientEmissionFactor — tier-2 client-level emission factor overrides
- clientNotification — notification dispatch matrix
- clientEnms — ISO 50001 EnMS configuration
- clientEnpi — custom Energy Performance Indicators
- clientEnmsTarget — energy targets
- apiConnector — API connector (remote source)
- apiConnectorEndpoint — individual data channel within a connector
Data
When a new client is created, the system initialises:
- 2 base
clientModulerecords are always created:remoteReadings(automatic data collection from remote gauges) andremoteReadingsAnalysis(hourly profiles, anomaly detection) - No tolerance override rows (system defaults apply)
- Notification matrix: 7 types × 5 roles = 35 rows from seeded catalogue defaults
Test Data
N/A — not covered in source material; no Test Data location was specified in the source page.
Logging
.info: licence fields updated; module assignments changed; notification matrix reset; organisation created or deleted; remote endpoint paired.
.debug: ARES lookup; calorific value / emission factor resolution trace; notification matrix recipient resolution.
Monitoring
N/A — not covered in source material.
Caching
N/A — not covered in source material.
Backward Compatibility and Migration
The complete field-by-field migration map was maintained on a child Confluence page ("Client Migration Map") that is out of scope for this migration pass. Note: the source page references an SMS-delivery decision recorded in that migration-map page's "Notification flags" section, not reproduced here.
Legal Context
N/A — not addressed in the source Confluence page; migrated as a reference copy without new legal analysis.
Cybersecurity Considerations
N/A — not addressed in the source Confluence page; migrated as a reference copy without new security analysis. Note: the Organisation registry and client identification hold personal/organisational data (contacts, addresses, IČO) — this should be reviewed when Cybersecurity/Data Privacy is formally analysed for this feature.
Risk Assessment
N/A — not addressed in the source Confluence page; migrated as a reference copy without new risk analysis.
Auditing, Reporting & Measurement
N/A — not addressed in the source Confluence page; migrated as a reference copy without new analysis.