Add logbook entries, data export page, and JSON import
This commit is contained in:
@@ -1,10 +1,25 @@
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import Column, Integer, String, Text, ForeignKey
|
||||
from sqlalchemy import Column, Integer, String, Text, ForeignKey, Table
|
||||
from sqlalchemy.orm import declarative_base, relationship
|
||||
|
||||
Base = declarative_base()
|
||||
|
||||
# Association tables for logbook (defined before ORM classes so they can be
|
||||
# referenced as `secondary` in relationship()). String-based FKs are resolved
|
||||
# lazily when create_all() binds the metadata.
|
||||
battery_logbook_table = Table(
|
||||
"battery_logbook", Base.metadata,
|
||||
Column("battery_id", Integer, ForeignKey("battery.id", ondelete="CASCADE"), primary_key=True),
|
||||
Column("logbook_id", Integer, ForeignKey("logbook.id", ondelete="CASCADE"), primary_key=True),
|
||||
)
|
||||
|
||||
device_logbook_table = Table(
|
||||
"device_logbook", Base.metadata,
|
||||
Column("device_id", Integer, ForeignKey("device.id", ondelete="CASCADE"), primary_key=True),
|
||||
Column("logbook_id", Integer, ForeignKey("logbook.id", ondelete="CASCADE"), primary_key=True),
|
||||
)
|
||||
|
||||
|
||||
class Device(Base):
|
||||
__tablename__ = "device"
|
||||
@@ -19,6 +34,12 @@ class Device(Base):
|
||||
ha_entity_id = Column(String(100), nullable=True) # e.g. "sensor.tv_remote_battery"
|
||||
|
||||
batteries = relationship("Battery", back_populates="device")
|
||||
logbook_entries = relationship(
|
||||
"Logbook", secondary=device_logbook_table,
|
||||
order_by="Logbook.recorded_at.desc()",
|
||||
cascade="all, delete-orphan",
|
||||
single_parent=True,
|
||||
)
|
||||
|
||||
def installed_count(self):
|
||||
return sum(1 for b in self.batteries if b.status == "installed")
|
||||
@@ -70,6 +91,12 @@ class Battery(Base):
|
||||
order_by="BatteryPctLog.recorded_at.desc()",
|
||||
cascade="all, delete-orphan",
|
||||
)
|
||||
logbook_entries = relationship(
|
||||
"Logbook", secondary=battery_logbook_table,
|
||||
order_by="Logbook.recorded_at.desc()",
|
||||
cascade="all, delete-orphan",
|
||||
single_parent=True,
|
||||
)
|
||||
|
||||
def is_available(self):
|
||||
return self.status == "available"
|
||||
@@ -127,3 +154,18 @@ class BatteryPctLog(Base):
|
||||
|
||||
def __repr__(self):
|
||||
return f"<BatteryPctLog {self.battery_id} {self.recorded_at} {self.percentage}%>"
|
||||
|
||||
|
||||
class Logbook(Base):
|
||||
__tablename__ = "logbook"
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||
body = Column(Text, nullable=False)
|
||||
recorded_at = Column(String(19), nullable=False) # "YYYY-MM-DD HH:MM:SS"
|
||||
# Note: SQLite has no native DATETIME type (stores dates as text).
|
||||
# On MariaDB this would be a native DATETIME column — swap String(19) for
|
||||
# DateTime when migrating, since SQLAlchemy's DateTime maps to DATETIME there.
|
||||
# String(19) is used here to match every other timestamp column in the codebase.
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Logbook {self.recorded_at}>"
|
||||
|
||||
Reference in New Issue
Block a user