Appearance
Entity: readingEntry
Entity Type: Database table (tenant schema)
Description: One manual reading as the user enters it: a gauge, the moment the meter was read, and what belongs to that moment as a whole — the note and the supporting documents. The measured values stay in reading, one row per series (tariff, direction, channel); every reading row with the same gaugeId and readAt and source = manual belongs to the entry. A remote or invoice reading has no entry: it carries no note and no document.
Why a table of its own. A note or a photo of the meter describes the act of reading, not one tariff. Stored on reading, it would be repeated on every row of the same moment and could disagree between them; stored as a JSON column on reading, it would sit on a hypertable whose rows are written by the remote sync in bulk. The documents attached to an entry are a list that is queried from the other side ("where is this document used"), so they live in readingEntryDocument rather than in a JSON array here.
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 | 019247a1-5c3e-7d10-8a2b-1f4c6e8d9a01 |
| tenantId | Tenant the entry belongs to. | UUID | - | Yes | No | UUID v7 | Matches the tenant of the request context. | name: idx_reading_entry_tenant_id, type: btree | 018f6e2a-1b2c-7d3e-9f40-5a6b7c8d9e0f |
| gaugeId | Gauge the reading was taken on. Loose reference, as on reading: the gauge belongs to another part of the domain model. | UUID | - | Yes | Part of composite unique | UUID v7 | Resolved through the gauge lookup; the gauge must allow manual readings. | name: uq_reading_entry_gauge_read_at, type: btree (unique, partial) | 018f7a10-2c3d-7e4f-8a5b-6c7d8e9f0a1b |
| readAt | Moment the meter was read. Equal to the readAt of every reading row of the entry; changing it moves those rows with it. | Timestamp with time zone | - | Yes | Part of composite unique | ISO 8601 — YYYY-MM-DDTHH:mm:ss.SSSZ | Between 1990-01-01 and now. | Part of the unique index above | 2026-05-04T08:40:00.000Z |
| note | Free text the user wrote about this reading — why a value looks unusual, who read it, what was found on site. One note per entry, edited in place; earlier versions are in the audit trail. | String | null | No | No | - | Max 2 000 characters. | - | Odečteno při kontrole rozvaděče, displej špatně čitelný. |
| createdAt | Timestamp of record creation. | Timestamp with time zone | now() — set in code | Yes | No | ISO 8601 — YYYY-MM-DDTHH:mm:ss.SSSZ | Cannot be null. | - | 2026-05-04T09:41:12.000Z |
| updatedAt | Timestamp of the last update. | Timestamp with time zone | now() — set in code | Yes | No | ISO 8601 — YYYY-MM-DDTHH:mm:ss.SSSZ | Cannot be null. | - | 2026-05-06T14:12:40.000Z |
| deletedAt | Soft-delete marker, set when the reading is deleted. The entry's reading rows are removed; the entry stays so that its note and documents remain traceable from the audit trail. | Timestamp with time zone | null | No | No | ISO 8601 — YYYY-MM-DDTHH:mm:ss.SSSZ | Immutable once set. Active rows: WHERE deletedAt IS NULL. | - | null |
| createdBy | Actor who created the record. | String | - | Yes | No | type:actor | Non-empty. | - | user:018ed0b3-… |
| updatedBy | Actor who last updated the record. | String | - | Yes | No | type:actor | Non-empty. | - | user:018ed0b3-… |
Indexes
| Name | Columns | Type | Why |
|---|---|---|---|
uq_reading_entry_gauge_read_at | gaugeId, readAt where deletedAt is null | Unique, partial | One manual reading per gauge and moment; a deleted entry must not block entering the same moment again. |
idx_reading_entry_tenant_id | tenantId | btree | Tenant predicate on every read. |
Audited fields
Recorded on created (in full), updated (changed only) and deleted (in full): gaugeId, readAt, note.
Excluded: tenantId — fixed by the request context and identical on every entry of a tenant, so it carries no information about the change. The values of the entry are audited on reading; the attached documents on readingEntryDocument.