Files
maziggy 6c8a821bca Add a wear cost per printing hour to printers (#694)
Print costs covered filament and energy but not the printer. Each printer
can now carry an optional wear cost per printing hour. Every run's wear is
its logged duration at that rate, stored on the print log entry; the
archive keeps the first run's wear, like energy (#1378). Failed and
cancelled runs count, reconciled runs (unknown duration) don't, and a rate
applies to new prints only.

Wear is shown on the archive card, as a hidden sortable Print Log column,
as a Quick Stats tile, in the most expensive record, in project totals and
in batch order cost, and is kept by GitHub backup and restore. Billing
still charges filament only.

New nullable columns: printers.wear_cost_per_hour, print_log_entries.wear_cost
and print_archives.wear_cost.
2026-10-05 09:29:12 +02:00

55 lines
1.9 KiB
Python

from datetime import datetime
from pydantic import BaseModel, ConfigDict
class PrintLogEntrySchema(BaseModel):
# from_attributes lets the routes build this straight off the ORM row.
# The GET serialiser used to name every field by hand, and each field it
# forgot came back as its default — a silent null rather than an error.
# That cost the log its failure_reason (#1687 part 4) and then its cost /
# energy_kwh / energy_cost (#2636). Validating from the row removes the
# chance to forget one.
model_config = ConfigDict(from_attributes=True)
id: int
archive_id: int | None = None
print_name: str | None = None
printer_name: str | None = None
printer_id: int | None = None
status: str
started_at: datetime | None = None
completed_at: datetime | None = None
duration_seconds: int | None = None
filament_type: str | None = None
filament_color: str | None = None
filament_used_grams: float | None = None
cost: float | None = None
energy_kwh: float | None = None
energy_cost: float | None = None
wear_cost: float | None = None # #694
failure_reason: str | None = None
user_verdict: str | None = None # Post-print quality verdict (#1898)
thumbnail_path: str | None = None
created_by_id: int | None = None
created_by_username: str | None = None
created_at: datetime
class PrintLogResponse(BaseModel):
items: list[PrintLogEntrySchema]
total: int
class PrintLogEntryUpdate(BaseModel):
"""Per-row classification edits (#1687 part 4 — IndividualGhost1905).
Lets the user set ``failure_reason`` (and re-classify ``status``) directly
on a Print Log row, including on orphan entries that have no archive to
edit through. The Failure Analysis widget already groups by
``PrintLogEntry.failure_reason``, so this just plugs the editor gap.
"""
failure_reason: str | None = None
status: str | None = None