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

Entity: climateData ​

Entity: climateData

Description: Stores actual measured or reported climate values (heating days, average temperature) for a specific weather station and time period. Each record represents one time slot at a given granularity (monthly, daily or hourly). Records are written once and never modified — corrections are represented by a new row with a later validFrom for the same (weatherStationId, date, granularity) combination; the previous row is retained permanently as an immutable historical fact. Used as the source for climate data tables in the client UI and as an input to the degree-day normalisation calculation together with climateNormal. Stations with a richer data source may report additional parameters beyond heating days and temperature — these are stored in extraParameters.

Entity Type: database table

Append-only entity. Records are written once and never modified or deleted. updatedAt, updatedBy and deletedAt are intentionally omitted. The lifecycle of a record is expressed by its date, granularity and validFrom. Corrections are handled via versioning (a new row with a later validFrom), never by mutating an existing row.

Data Attributes Table ​

Attribute NameDescriptionData TypeDefault ValueRequired (= Nullable)UniqueFormatValidationsIndexExample
idPrimary key of the entity.UUIDGenerated in code (app layer)YesYesUUID v7-Primary Key018ed0b3-c298-7c7a-96d5-8b36f5a7f8d2
tenantIdTenant this record belongs to. Mirrors the tenantId of the parent weather station. null for global station data.UUID-NoNoUUID v7 or nullForeign Key: tenant (when non-null); must existname: idx_climateData_tenantId, type: btree018fa51f-fda1-79f4-8461-2cb8f1cabc10
weatherStationIdThe weather station this record belongs to.UUID-YesNoUUID v7Foreign Key: weatherStation.id; must existname: idx_climateData_weatherStationId_date, type: btree (composite with date, granularity, validFrom)018ed0b3-c298-7c7a-96d5-8b36f5a7f8d2
dateStart of the time period this record covers. For monthly granularity: first day of the month. For daily: the day. For hourly: the start of the hour.timestamp with time zone-YesNoISO 8601Part of composite unique constraint (weatherStationId, date, granularity, validFrom)name: idx_climateData_weatherStationId_date, type: btree (composite with weatherStationId, granularity, validFrom)2024-01-01T00:00:00Z
granularityTime resolution of this record.string (enum)-YesNoenum — see Granularity (source Confluence page; not yet migrated to the local enum catalog)Must be one of the valid values-monthly
validFromTimestamp when this version of the value became the recorded truth. Not the weather period itself (that's date) — this is the versioning dimension that enables corrections.timestamp with time zonecreatedAt — set in codeYesNoISO 8601Part of composite unique constraint (weatherStationId, date, granularity, validFrom) — prevents duplicate imports at the exact same instant while allowing corrections-2025-06-01T09:00:00Z
heatingDaysMeaning depends on granularity: daily → 0/1 (heating day yes/no); monthly → count of heating days; hourly and finer → null. Derived automatically for source = remote stations. Set directly by the admin for manual entries (or as a manual correction of an automatically computed value).integer0 / null (depending on granularity)NoNo-0–1 for daily; 0–31 for monthly; null for hourly/finer-18
avgTempAverage outdoor temperature for the period in °C. Derived automatically for source = remote stations. null for hourly and finer. Set directly by the admin for manual entries (or as a manual correction of an automatically computed value).decimal-NoNo°C, two decimal places--2.40
extraParametersAdditional optional climate parameters, as reported by the station's data source. Free-form — keys and units are not enumerated or validated by the system; whatever the source provides is stored as-is.JSONBnullNoNoJSON — free-form, no fixed shape (see note below)--{"solarRadiation": 4.2, "precipitation": 12.5, "windSpeed": 3.1}
sourceOrigin of this data record. Distinguishes remote from manual entry.string (enum)-YesNoenum — see ClimateDataSource (source Confluence page; not yet migrated to the local enum catalog)--remote
createdAtTimestamp of when the record was created. Immutable after insert.timestamp with time zonenow() — set in codeYesNoISO 8601 — YYYY-MM-DDTHH:mm:ss.SSSZCannot be null; cannot be modified after creation-2025-03-16T18:00:00Z
createdByIdentifier of the actor who created the record.string-YesNotype:actor — e.g. user:uuid or system:climate-importNon-empty-system:climate-import

Note — no updatedAt/updatedBy/deletedAt. This is an append-only entity (see above); the standard audit quintet is intentionally reduced to createdAt/createdBy only.

Note — extraParameters JSON shape not documented. The source Confluence page describes this JSONB column as genuinely free-form ("keys and units are not enumerated or validated by the system; whatever the source provides is stored as-is"). Per the foundations doc (§8.1) a JSONB column should get a sibling JSON-DAT documenting its internal shape; no sibling file was created here because there is no fixed shape to document faithfully without inventing one. Flagging for review — a maintainer may want a JSON-DAT that explicitly documents "no fixed shape" rather than omitting it, or may know of a de-facto key set worth capturing.

Audited fields ​

Recorded on created only — this entity is explicitly append-only (no updatedAt/updatedBy/deletedAt at all; a correction is a new row with a later validFrom, never a mutation of an existing one): weatherStationId, date, granularity, validFrom, heatingDays, avgTemp, extraParameters, source.

Excluded: none.

Every entry would carry subjectEntityType = weatherStation / subjectEntityId = weatherStationId — climateData has no human-readable key of its own; the station plus the (date, granularity, validFrom) triple on the entry itself is what identifies one record.

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