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

@@ -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()"
)