Skip to content
Updated Oct 5, 2026 by Pablo Coufal · Owner: analysisdraftentitygauge-management Edit on GitHub

Entity: gaugeUsageAllocation ​

Entity Type: Database table

Description: How the consumption of one channel is attributed to usage types (účel užití) from a given day on. One record per channel and validity; the record valid on a day is the one with the highest validFrom not after it (D02 — local day of the channel's daily aggregate). Three modes: single — one usage for 100 % of the channel; estimated — explicit monthly percentage shares per usage, every month summing to exactly 100 % (D03, no remainder); measured — measured parts taken from sub-gauge channels plus exactly one usage that receives the remainder of the parent (O01). The split itself is never stored: variant C computes it at read time from the daily aggregate and the allocation valid on that day (consumption_daily_by_usage, Epic 3.1 / 3.2), so a change needs no reprocessing and consumption keeps one row per channel and slot. Replaces gauge.usageType (one value per physical meter) — decisions R1–R3, 1 Oct 2026; rules D01–D09 confirmed by the product owner. Versioning follows the append-only pattern of gaugeSerialHistory with one addition: a backdated correction supersedes the version it replaces (supersededById) instead of creating a second effective version for the same day (UC-06).

Data Attributes Table ​

Attribute NameDescriptionData TypeDefault ValueRequired (= Nullable)UniqueFormatValidationsIndexExample
idPrimary key of the entity.UUIDGenerated in code (app layer)YesYesUUID v7-Primary Key01960000-0000-7000-8000-000000000801
tenantIdTenant that owns this record. Denormalised from gauge for uniform data-scoping.UUID-YesNoUUID v7Foreign Key → tenant; must equal the parent gauge.tenantId.name: idx_gaugeUsageAllocation_tenantId, type: btree01960000-0000-7000-8000-000000000099
gaugeIdThe channel whose consumption is allocated. Consumption channels only (purpose consumption; not export / production in v1 — K3; never KVP).UUID-YesNoUUID v7Foreign Key → gauge; must exist and be a consumption channel with a medium the usage catalogue covers.name: idx_gaugeUsageAllocation_gaugeId_validFrom, type: btree (composite, validFrom DESC)01960000-0000-7000-8000-000000000005
validFromFirst local day the allocation applies to (inclusive).Date-YesNoISO 8601 dateAt most one effective (non-superseded) record per gaugeId and validFrom.name: idx_gaugeUsageAllocation_gaugeId_validFrom, type: btree (composite)2026-10-01
modesingle · estimated · measured (kapitola 4.4 of the gauge form specification).String-YesNoenumsingle → exactly one item with no shares and no sources; estimated → ≥ 2 items with 12 shares each, every month summing to 100 %; measured → ≥ 1 item with sourceGaugeIds and exactly one item with isRemainder = true.-estimated
supersededByIdThe correction that replaced this version (UC-06). Null for the effective version.UUIDnullNoNoUUID v7Foreign Key → gaugeUsageAllocation; same gaugeId and validFrom.name: idx_gaugeUsageAllocation_supersededById, type: btreenull
noteOptional free text (why the split was set this way).StringnullNoNo-Max 500 characters.-Odhad podle projektu kotelny
createdAtTimestamp of entity creation. Immutable.Timestamp with time zoneSet in codeYesNoISO 8601--2026-10-05T10:00:00Z
createdByIdentifier of the actor who created this record.String-YesNotype:actor--user:01960000-0000-7000-8000-000000000099

Notes ​

  • Append-only with supersession. A new validFrom adds a version; a correction of an existing version (same gaugeId, same validFrom) adds a record and sets supersededById on the old one. One day never has two effective versions; reads use the effective version only; superseded versions stay for the audit trail (who corrected what, when).
  • Validation is atomic (UC-13): the record and its items are saved together or not at all; the backend validates the usage offer against usageType.allowedFor, the monthly sums, duplicate usages (N04), source channels (D04: same medium, inside the parent's balance boundary, not the channel itself, no overlapping branches), and refuses an inactive usage for a new assignment (N09).
  • Missing data is never zero (D05): when the parent's daily aggregate or a measured source is missing or incomplete for a day, that day's known total stays unassigned with a reason; no fallback to the estimate, no clipping. Measured parts exceeding the parent flag the day as inconsistent (D09); no negative remainder.
  • Sub-gauge creation copies the parent channel's effective allocation as the child's own first version (R5, D07, N07): usages and shares verbatim, sourceGaugeIds only where valid for the child (never a reference to itself); the child is independent afterwards.
  • Migration (M8): EM2 gauge_consumption_usage codes 1, 2, 5, 6, 7 → single; 4 → estimated with the monthly shares of gauge_consumption_usage_combi (EM2's implicit remainder → explicit heating share so months sum to 100 %); 3 / 8 → measured with the sub-gauge channel as source and the other usage as remainder; 0 → no record. validFrom = migration date unless EM2 carries a date.
  • Read model: GET /v1/gauges/:id/usage-allocations (versions) and GET /v1/gauges/:id/usage-allocations/effective?at= for the form; consumption_daily_by_usage joins the effective version for each day of the daily aggregate and multiplies by shares[month] or subtracts measured sources.