Appearance
Entity: gaugeFormula
Entity Type: Database table
Description: One version of the formula of a formula-bearing virtual gauge (gauge.kind = virtual, virtualSubtype = computed or buildingTotal). The formula is a linear combination of other gauges — its members are in gaugeFormulaMember, each with a sign. Versions are append-only: a change of the member set writes a new record with its own validFrom and voids the previous one, so consumption of an interval is always evaluated with the version that applied to that interval and a later edit never rewrites historical totals. The result of the evaluation is written as consumption of the owning gauge with source calculated (see Consumption calculation).
Source of the current shape: EM3 apps/backend/migrations/202609011000-gauge-formula.sql (gauge_formula), rules in apps/backend/src/core/assets/domain/rules/formula-member.rules.ts. The migration keeps gauge_id UNIQUE — one row per gauge edited in place; validFrom and voidedAt are the versioning this design requires (decided 2026-09-14 with Epic 3.1).
Data Attributes Table
| Attribute Name | Description | Data Type | Default Value | Required (= Nullable) | Unique | Format | Validations | Index | Example |
|---|---|---|---|---|---|---|---|---|---|
| id | Primary key of the formula version. | UUID | Generated in code (app layer) | Yes | Yes | UUID v7 | - | Primary Key | 01960000-0000-7000-8000-000000000401 |
| tenantId | Tenant that owns this record. Denormalised from gauge for uniform data-scoping; row-level security policy tenant_isolation. | UUID | - | Yes | No | UUID v7 | Foreign Key → tenant; must equal the owning gauge.tenantId. | name: idx_gaugeFormula_tenantId, type: btree | 01960000-0000-7000-8000-000000000099 |
| gaugeId | The virtual gauge this formula belongs to. | UUID | - | Yes | No | UUID v7 | Foreign Key → gauge; kind = virtual and virtualSubtype in (computed, buildingTotal). At most one active (not voided) version per gauge. | name: idx_gaugeFormula_gaugeId_validFrom, type: btree (composite, validFrom DESC) | 01960000-0000-7000-8000-000000000005 |
| validFrom | Date from which this version of the formula applies — the date the configuration changed, entered by the user (Platnost od), not the date the record was saved. | Date | - | Yes | No | ISO 8601 date | Must be unique per gaugeId; may lie in the past, which re-evaluates the gauge from that date. | name: idx_gaugeFormula_gaugeId_validFrom, type: btree (composite) | 2026-09-01 |
| voidedAt | Timestamp when this version was superseded by a newer one. Null for the active version. Versions are never updated or deleted. | Timestamp with time zone | null | No | No | ISO 8601 | Set once, together with the insert of the successor, in one transaction. | - | null |
| missingMemberPolicy | What the evaluation does with an interval in which a member has no value. Proposed in the 24 Sep design round, still open: leaveEmpty (the interval of the virtual gauge gets no value — the Epic 3.1 rule) or treatAsZero. | String | leaveEmpty | Yes | No | - | Values: leaveEmpty, treatAsZero. Becomes an enum page once decided. | - | leaveEmpty |
| needsReview | Set when a member gauge is archived or moved so that the formula no longer describes what the user configured; cleared when the user saves the formula again. | Boolean | false | Yes | No | - | - | name: idx_gaugeFormula_needsReview, type: partial (WHERE needsReview) | false |
| createdAt | Timestamp of entity creation. Immutable. | Timestamp with time zone | Set in code | Yes | No | ISO 8601 | - | - | 2026-09-24T09:00:00Z |
| updatedAt | Timestamp of last entity update. Set on insert equal to createdAt; only needsReview and voidedAt change afterwards. | Timestamp with time zone | Set in code | Yes | No | ISO 8601 | - | - | 2026-09-24T09:00:00Z |
| deletedAt | Timestamp of soft delete. Versions are voided, not deleted; kept for the uniform lifecycle. Once set, immutable. | Timestamp with time zone | null | No | No | ISO 8601 | - | - | null |
| createdBy | Identifier of the actor who created this record. | String | - | Yes | No | type:actor | - | - | user:01960000-0000-7000-8000-000000000099 |
| updatedBy | Identifier of the actor who last updated this record. | String | - | Yes | No | type:actor | - | - | user:01960000-0000-7000-8000-000000000099 |
Audited fields
Recorded on created (in full), updated (changed only) and deleted (in full): gaugeId, validFrom, voidedAt, missingMemberPolicy, needsReview.
Excluded: none — every column decides which formula applies to which interval; the members are recorded on gaugeFormulaMember.
Not registered for entityName resolution, and has no independent human-readable attribute to register — identified by its gaugeId/validFrom scope.
Row-level security
Enabled and forced, with the tenant-isolation policy every tenant-schema table carries (tenant_isolation on app.tenant_id).
Notes
- A
buildingTotalformula is system-managed (gauge.isSystemManaged); its versions are written by the building-formula suggestion flow, never by the formula editor. - Saving a version enqueues a recalculation of the owning gauge from
validFromin the same transaction (transactional outbox), as a coefficient change does. - The evaluation graph must be acyclic: a member may itself be a
computedvirtual gauge, but the chain must never reach the owner again (FormulaCycleError).