This repository has been archived on 2026-07-08. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
state-hub/api/models/legacy_meter.py
tegwick 166aedfa8d feat: add workplan aliases and legacy meter
Adds preferred workplan REST/event surfaces, legacy-meter telemetry and weekly review summaries, documentation/dashboard terminology updates, dashboard API loading fixes, and close-out sync for STATE-WP-0052 and STATE-WP-0054.
2026-06-04 08:25:31 +02:00

80 lines
3.4 KiB
Python

import uuid
from datetime import date, datetime
from sqlalchemy import Boolean, Date, DateTime, ForeignKey, Index, Integer, String, Text, UniqueConstraint, func
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import Mapped, mapped_column, relationship
from api.models.base import Base, TimestampMixin, new_uuid
class LegacyInterface(Base, TimestampMixin):
__tablename__ = "legacy_interfaces"
id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True), primary_key=True, default=new_uuid
)
interface_key: Mapped[str] = mapped_column(String(300), nullable=False, unique=True, index=True)
interface_kind: Mapped[str] = mapped_column(String(40), nullable=False, index=True)
legacy_since: Mapped[datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now(), nullable=False, index=True
)
replacement_ref: Mapped[str] = mapped_column(Text, nullable=False)
owner_component: Mapped[str] = mapped_column(
String(100), nullable=False, default="state-hub", server_default="state-hub", index=True
)
status: Mapped[str] = mapped_column(
String(30), nullable=False, default="legacy", server_default="legacy", index=True
)
replacement_verified: Mapped[bool] = mapped_column(
Boolean, nullable=False, default=False, server_default="false"
)
manual_hold: Mapped[bool] = mapped_column(
Boolean, nullable=False, default=False, server_default="false"
)
hold_reason: Mapped[str | None] = mapped_column(Text, nullable=True)
notes: Mapped[str | None] = mapped_column(Text, nullable=True)
retired_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
usage_buckets: Mapped[list["LegacyInterfaceUsageBucket"]] = relationship( # noqa: F821
"LegacyInterfaceUsageBucket",
back_populates="legacy_interface",
cascade="all, delete-orphan",
lazy="selectin",
)
class LegacyInterfaceUsageBucket(Base, TimestampMixin):
__tablename__ = "legacy_interface_usage_buckets"
__table_args__ = (
UniqueConstraint(
"legacy_interface_id",
"period_start",
"bucket_kind",
"bucket_key",
name="uq_legacy_usage_bucket",
),
Index("ix_legacy_usage_interface_period", "legacy_interface_id", "period_start"),
Index("ix_legacy_usage_bucket_kind_key", "bucket_kind", "bucket_key"),
)
id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True), primary_key=True, default=new_uuid
)
legacy_interface_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
ForeignKey("legacy_interfaces.id", ondelete="CASCADE"),
nullable=False,
index=True,
)
period_start: Mapped[date] = mapped_column(Date, nullable=False, index=True)
bucket_kind: Mapped[str] = mapped_column(String(30), nullable=False)
bucket_key: Mapped[str] = mapped_column(String(200), nullable=False)
call_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0, server_default="0")
first_seen_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
last_seen_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, index=True)
legacy_interface: Mapped["LegacyInterface"] = relationship( # noqa: F821
"LegacyInterface", back_populates="usage_buckets"
)