Skip to content
Updated Sep 26, 2026 by Barča Dvořáková · Owner: analysisactiveentity Edit on GitHub

Entity: vatRate ​

Entity Type: Database table (shared schema)

Description: The catalogue of statutory VAT rates, one row per medium and validity start. It is the single place a rate is defined, so a change in the law is one row per affected medium rather than a code change. A rate is valid from its validFrom until the validFrom of the next row for the same medium; the rate in force on an invoice's period start is the one used to complete that invoice's second amount, and the rate actually used is recorded on the invoice so the figure stays reproducible after the law changes.

Cross-tenant reference data. The row belongs to the platform, not to a tenant, so it lives in the shared schema alongside the other cross-tenant catalogues rather than being copied into every tenant schema. tenantId is present but null on every row this feature creates: it is the column the shared-schema policies key on, and a null value is what makes a row readable by every tenant. The same shape is used by the weather-station and climate-normal catalogues.

One row per medium, not one row per date. A change in the law that touches three media is three rows sharing a validFrom, and a medium whose rate did not change keeps its existing row. The alternative — a single row carrying a column per medium — makes adding a medium a schema change, and makes a medium that nobody remembered to fill in indistinguishable from one deliberately left alone.

Data Attributes Table ​

Attribute NameDescriptionData TypeDefault ValueRequired (= Nullable)UniqueFormatValidationsIndexExample
idPrimary key of the entity.UUIDGenerated in code (app layer)YesYesUUID v7-Primary Key018f9c4d-2c11-7a3e-9b77-4f0d3a5e6b21
tenantIdAlways null for a platform-maintained rate, which is what makes the row visible to every tenant. Present because the shared-schema row-level-security policies read it.UUIDnullNoNoUUID v7Must be null on a row created through the platform administration surface.name: idx_vat_rate_tenant_id, type: btreenull
mediumMedium the rate applies to. Rates differ by medium — a reduced rate for heat alongside the standard rate for electricity, gas and fuels — and every billable medium carries its own row, including those currently on the standard rate.Enum-YesPart of composite uniqueEnum - GaugeMediumAn entry from the enum. Only billable media are rated; kvp and otherSensor are never invoiced and carry no rows.name: uq_vat_rate_medium_valid_from, type: btree (unique, partial)heat
ratePercentThe rate as a percentage. Stored as a percentage rather than a multiplier so that the catalogue reads the way the legislation and the invoice do.Decimal-YesNonumeric(5,2)≥ 0 and < 100.-12.00
validFromFirst day the rate applies. A rate has no explicit end: it runs until the next row for the same medium begins.Date-YesPart of composite uniqueYYYY-MM-DDUnique per (medium, validFrom) among rows where deletedAt is null.Part of the unique index above2024-01-01
legalReferenceShort free-text reference to the amendment or notice the rate comes from, so an auditor can trace the number to its source.StringnullNoNo-Max 200 characters.-Zákon č. 349/2023 Sb., účinnost od 1. 1. 2024
createdAtTimestamp of record creation.Timestamp with time zonenow() — set in codeYesNoISO 8601 — YYYY-MM-DDTHH:mm:ss.SSSZCannot be null.-2023-12-18T10:00:00Z
updatedAtTimestamp of the last update.Timestamp with time zonenow() — set in codeYesNoISO 8601 — YYYY-MM-DDTHH:mm:ss.SSSZCannot be null.-2023-12-18T10:00:00Z
deletedAtSoft-delete marker for a withdrawn row. Null means active. Any rate can be withdrawn when needed; withdrawing a historical rate — one superseded by a later rate for its medium — needs the history permission. A withdrawn row is never physically removed, and invoices already completed keep the rate recorded on them.Timestamp with time zonenullNoNoISO 8601 — YYYY-MM-DDTHH:mm:ss.SSSZImmutable once set. Active rows: WHERE deletedAt IS NULL.-null
createdByActor who created the record.String-YesNotype:actorNon-empty.-user:018ed0b3-…
updatedByActor who last updated the record.String-YesNotype:actorNon-empty.-user:018ed0b3-…

Indexes ​

NameColumnsTypeWhy
uq_vat_rate_medium_valid_frommedium, validFrom where deletedAt is nullUnique, partialOne rate per medium per start date; a soft-deleted row must not block re-entering the same date.
idx_vat_rate_tenant_idtenantIdbtreeSupports the shared-schema policies.

Row-level security ​

Enabled and forced, with the split read and write policies the shared schema uses: a row is readable when its tenantId is null or matches the current tenant, and writable only in a context with no tenant set — which is the platform administration context. A tenant can therefore read every rate and change none of them.

Audited fields ​

Recorded on created (in full), updated (changed only) and deleted (in full): medium, ratePercent, validFrom, legalReference.

Excluded: tenantId — always null on a platform-maintained row, so it carries no information about the change.

Not registered for entityName resolution, and has no independent human-readable attribute to register — identified by its medium/validFrom scope.

Reference data ​

The catalogue is seeded with the statutory history of every billable medium since 1 January 2013 (the table is on the feature page), and gains a row per medium whenever the legislation changes. It is never empty: an invoice whose period starts before the earliest row for its medium cannot have its second amount completed, and the user is asked for both amounts instead.