M8-T01: add meter source identity schema

This commit is contained in:
2026-08-23 21:22:05 +02:00
parent 43c2ddce1a
commit 009856a50d
9 changed files with 644 additions and 3 deletions
+15 -1
View File
@@ -13,12 +13,12 @@ from __future__ import annotations
import uuid as _uuid
from datetime import datetime
from sqlalchemy import Boolean, DateTime, Float, ForeignKey, Integer, String
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy.types import JSON
from app.db import Base
from app.models.meter_source import MeterSourceBinding
def _uuid4_str() -> str:
@@ -85,6 +85,10 @@ class Meter(Base):
back_populates="meter", cascade="save-update, merge"
)
source_bindings: Mapped[list["MeterSourceBinding"]] = relationship(
back_populates="meter", cascade="save-update, merge"
)
class DsmrReading(Base):
"""One down-sampled DSMR telegram stored as a full JSON blob.
@@ -292,6 +296,12 @@ class EnergyCostPeriod(Base):
ForeignKey("meter.id", ondelete="RESTRICT"), nullable=True
)
# Nullable while M8 adopts historical DSMR rows. Future normal periods
# will point at the binding that supplied both cumulative endpoints.
source_binding_id: Mapped[int | None] = mapped_column(
ForeignKey("meter_source_binding.id", ondelete="RESTRICT"), nullable=True
)
# True when the period was computed with incomplete data (missing readings or
# missing price); serves as a flag for later recomputation.
degraded: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
@@ -307,6 +317,10 @@ class EnergyCostPeriod(Base):
# Relationship back to the meter epoch.
meter: Mapped["Meter | None"] = relationship(back_populates="cost_periods")
source_binding: Mapped["MeterSourceBinding | None"] = relationship(
back_populates="cost_periods"
)
# Index on recorded_at for efficient time-range queries on DSMR readings.
# (The ORM-level index=True on recorded_at already creates ix_dsmr_reading_recorded_at;