Appearance
Entity: invoiceValue
Entity Type: Database table
Description: Segmented consumption and cost figures for an invoice. A single invoice has one invoiceValue row per (kind, tariff) combination — e.g. an invoice for a two-tariff electricity gauge produces separate rows for high-tariff consumption and low-tariff consumption. Replaces a single flat consumption/cost figure on invoice itself, mirroring the same segmented-row pattern already used by reading rather than EM2's single flat segment enum. Required by the consumption-tolerance check (F93) and the price check (F94), which compare these values against reading-derived consumption and computed cost.
Data Attributes Table
| Attribute Name | Description | Data Type | Default Value | Required (= Nullable) | Unique | Format | Validations | Index | Example |
|---|---|---|---|---|---|---|---|---|---|
| id | Primary key of the entity. | UUID | Generated in code (app layer) | Yes | Yes | UUID v7 | - | Primary Key | 018f6e2a-1234-7abc-9def-0123456789ab |
| tenantId | Tenant this record belongs to. | UUID | - | Yes | No | UUID v7 | Foreign Key → tenant; must exist | - | 018fa51f-fda1-79f4-8461-2cb8f1cabc10 |
| invoiceId | The invoice this segmented value belongs to. | UUID | - | Yes | Part of composite unique | UUID v7 | Foreign Key → invoice; must exist | name: idx_invoiceValue_invoiceId, type: btree | 018fa51f-fda3-7c63-b5a9-3fa33dc989de |
| kind | Measurement dimension: what the figure represents. | Enum | - | Yes | Part of composite unique | enum | - | Part of composite unique index | consumption |
| tariff | Measurement dimension: tariff band this figure applies to. Reuses the same enum as reading.tariff for consistency. | Enum | - | No | Part of composite unique | enum | - | Part of composite unique index | high |
| value | The recorded figure — a consumption/power quantity or a monetary amount, depending on kind. | Double precision | - | Yes | No | - | - | - | 1234.56 |
| unit | Unit of the value — an energy/power unit for consumption/power, or currency for the cost kinds. | Enum | - | Yes | No | enum — Unit | - | - | kWh |
| createdAt | Timestamp of entity creation. Is immutable. | Timestamp with time zone | now() | Yes | No | ISO 8601 — YYYY-MM-DDTHH:mm:ss.SSSZ | - | - | 2026-01-15T09:00:00Z |
| updatedAt | Timestamp of last entity update. Mutable. | Timestamp with time zone | now() | Yes | No | ISO 8601 — YYYY-MM-DDTHH:mm:ss.SSSZ | - | - | 2026-01-15T09:00:00Z |
| deletedAt | Timestamp of entity soft delete. Once set, immutable. | Timestamp with time zone | - | No | No | ISO 8601 — YYYY-MM-DDTHH:mm:ss.SSSZ | Immutable once set. Active records: WHERE deletedAt IS NULL | - | null |
| createdBy | Identifier of the author who created this record. | String | - | Yes | No | type:actor | - | - | user:c2d3f586-1c9a-4f5f-b9ae-45f2c4f69f7e |
| updatedBy | Identifier of the author who last updated this record. | String | - | Yes | No | type:actor | - | - | system:invoice-import-v1 |
| legacyId | Legacy-system identifier; migration provenance. | String | null | No | No | - | - | UNIQUE (tenantId, legacySource, legacyId) WHERE legacyId IS NOT NULL | 3313 |
| legacySource | Which legacy table this invoiceValue segment was migrated from. | String (enum) | null | No | No | enum: invoice_value | Must equal the listed value, or null | (composite with legacyId above) | invoice_value |
Business-identity dedup constraint (separate from the PK): UNIQUE (invoiceId, kind, tariff).
Note. Invoiced consumption and cost are modeled separately — see invoice.
Revision note (2026-08-18, from source page): confirmed against a staging data check. power was added as a new kind value (confirmed present in live data). costWithVat/costWithoutVat have no historical rows to migrate but remain supported — kept as valid, currently-unused values rather than removed, since absence in EM2 doesn't rule out future use.
Audited fields
Recorded on created (in full) and deleted (in full) — this entity never produces an updated entry (see below): invoiceId, kind, tariff, value, unit, legacyId, legacySource.
Excluded: none.
A changed segment is recorded as a deleted (old row) + created (new row) pair, never as a single updated entry: every save replaces the invoice's whole invoiceValue set with freshly-inserted rows (fresh ids each time), so no single row's lifetime ever spans an edit. No-op detection for a resend with identical content is keyed by the natural key (kind, tariff), not by row id, since ids are not stable across a replace.
legacyId/legacySource are real, migrated columns (202608182000-invoice-migration-fields.sql) not modeled in invoiceValueValidationMap — like the same pair on building/gauge/dataImport elsewhere in this batch, they're written only by CLI migration tooling, outside the domain layer, but are still real persisted columns and are documented and audited on that basis.
Not registered for entityName resolution, and has no independent human-readable attribute to register — identified by its invoiceId/kind/tariff combination.