Add printer lifecycle fields and printer log

- Printer: bought_at, last_maintenance_at, decommissioned_at (all Date, nullable)
- PrinterLog: per-printer timestamped text entries (CASCADE delete)
- Migration 0003: adds columns + printer_logs table
- /printers/{id}: detail page showing lifecycle info + scrollable log
- POST /printers/{id}/log: add a log entry via modal form
- Printer names in list are now links to the detail page
- Add Printer modal includes optional purchase date

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Martin Hohenberg
2026-06-18 21:47:48 +02:00
parent 750edbbcec
commit c78f8c91cd
7 changed files with 206 additions and 4 deletions

View File

@@ -3,7 +3,8 @@ from app.models.filament import Filament
from app.models.pricing import PricingConfig
from app.models.print_job import PrintJob
from app.models.printer import Printer
from app.models.printer_log import PrinterLog
from app.models.printer_type import PrinterType
from app.models.todo import Todo
__all__ = ["Base", "Printer", "PrinterType", "Filament", "PrintJob", "Todo", "PricingConfig"]
__all__ = ["Base", "Printer", "PrinterLog", "PrinterType", "Filament", "PrintJob", "Todo", "PricingConfig"]

View File

@@ -1,7 +1,7 @@
import enum
from datetime import datetime
from datetime import date, datetime
from sqlalchemy import DateTime, Enum, ForeignKey, String, func
from sqlalchemy import Date, DateTime, Enum, ForeignKey, String, func
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.models.base import Base
@@ -24,6 +24,9 @@ class Printer(Base):
status: Mapped[PrinterStatus] = mapped_column(
Enum(PrinterStatus), default=PrinterStatus.offline
)
bought_at: Mapped[date | None] = mapped_column(Date)
last_maintenance_at: Mapped[date | None] = mapped_column(Date)
decommissioned_at: Mapped[date | None] = mapped_column(Date)
created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())
updated_at: Mapped[datetime] = mapped_column(
DateTime, server_default=func.now(), onupdate=func.now()
@@ -32,3 +35,6 @@ class Printer(Base):
printer_type: Mapped["PrinterType | None"] = relationship(back_populates="printers")
jobs: Mapped[list["PrintJob"]] = relationship(back_populates="printer")
todos: Mapped[list["Todo"]] = relationship(back_populates="printer")
logs: Mapped[list["PrinterLog"]] = relationship(
back_populates="printer", order_by="PrinterLog.created_at.desc()"
)

17
app/models/printer_log.py Normal file
View File

@@ -0,0 +1,17 @@
from datetime import datetime
from sqlalchemy import DateTime, ForeignKey, Text, func
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.models.base import Base
class PrinterLog(Base):
__tablename__ = "printer_logs"
id: Mapped[int] = mapped_column(primary_key=True)
printer_id: Mapped[int] = mapped_column(ForeignKey("printers.id"))
message: Mapped[str] = mapped_column(Text)
created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())
printer: Mapped["Printer"] = relationship(back_populates="logs")