Report PDF emailing

This commit is contained in:
2026-06-18 21:07:34 +01:00
parent 7254719794
commit 364f4fe57e
16 changed files with 1428 additions and 16 deletions
+83 -2
View File
@@ -1,8 +1,8 @@
from __future__ import annotations
from datetime import datetime
from datetime import date, datetime
from sqlalchemy import Boolean, DateTime, Float, ForeignKey, Index, Integer, String, func
from sqlalchemy import Boolean, Date, DateTime, Float, ForeignKey, Index, Integer, String, UniqueConstraint, func
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.db import Base
@@ -26,6 +26,7 @@ class Device(Base):
)
readings: Mapped[list["Reading"]] = relationship(back_populates="device")
scheduled_reports: Mapped[list["ScheduledReport"]] = relationship(back_populates="device")
class Reading(Base):
@@ -44,3 +45,83 @@ class Reading(Base):
version: Mapped[str | None] = mapped_column(String(32))
device: Mapped[Device] = relationship(back_populates="readings")
class ReportRecipient(Base):
__tablename__ = "report_recipients"
__table_args__ = (UniqueConstraint("email", name="uq_report_recipients_email"),)
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
email: Mapped[str] = mapped_column(String(255), nullable=False)
name: Mapped[str | None] = mapped_column(String(255))
active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), nullable=False)
updated_at: Mapped[datetime] = mapped_column(
DateTime,
server_default=func.now(),
onupdate=func.now(),
nullable=False,
)
scheduled_reports: Mapped[list["ScheduledReport"]] = relationship(back_populates="recipient")
class ScheduledReport(Base):
__tablename__ = "scheduled_reports"
__table_args__ = (
Index("ix_scheduled_reports_active_cadence", "active", "cadence"),
UniqueConstraint(
"recipient_id",
"cadence",
"send_time",
"weekday",
"monthday",
"device_id",
name="uq_scheduled_report_config",
),
)
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
recipient_id: Mapped[int] = mapped_column(ForeignKey("report_recipients.id"), nullable=False)
cadence: Mapped[str] = mapped_column(String(16), nullable=False)
send_time: Mapped[str] = mapped_column(String(5), nullable=False, default="08:00")
weekday: Mapped[int | None] = mapped_column(Integer)
monthday: Mapped[int | None] = mapped_column(Integer)
device_id: Mapped[str | None] = mapped_column(ForeignKey("devices.id"))
active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), nullable=False)
updated_at: Mapped[datetime] = mapped_column(
DateTime,
server_default=func.now(),
onupdate=func.now(),
nullable=False,
)
recipient: Mapped[ReportRecipient] = relationship(back_populates="scheduled_reports")
device: Mapped[Device | None] = relationship(back_populates="scheduled_reports")
runs: Mapped[list["ScheduledReportRun"]] = relationship(back_populates="scheduled_report")
class ScheduledReportRun(Base):
__tablename__ = "scheduled_report_runs"
__table_args__ = (
UniqueConstraint(
"scheduled_report_id",
"period_start",
"period_end",
name="uq_scheduled_report_run_period",
),
Index("ix_scheduled_report_runs_status", "status"),
)
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
scheduled_report_id: Mapped[int] = mapped_column(ForeignKey("scheduled_reports.id"), nullable=False)
period_start: Mapped[date] = mapped_column(Date, nullable=False)
period_end: Mapped[date] = mapped_column(Date, nullable=False)
status: Mapped[str] = mapped_column(String(16), nullable=False, default="pending")
pdf_path: Mapped[str | None] = mapped_column(String(1024))
error: Mapped[str | None] = mapped_column(String(1024))
created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), nullable=False)
sent_at: Mapped[datetime | None] = mapped_column(DateTime)
scheduled_report: Mapped[ScheduledReport] = relationship(back_populates="runs")