mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-22 03:49:18 +02:00
Keep the printer's name on statistics after it is deleted (issue #2873)
Every per-printer breakdown resolved the name against the printers that exist now, so deleting a printer and choosing to keep its prints turned "Ultron" into "Printer 1" in Prints by Printer, the success-rate and time-accuracy lists, and Failures by Printer. Archives lose their printer on that delete as well, so nothing was left to read a name from. The runs themselves recorded the name they printed on. /archives/stats now reports the last name each id was known by - taken from the newest run that has one, so a later name-less row cannot blank it - and failure analysis falls back to the same thing for ids with no printer left. The client keeps preferring a live printer's own record, so a rename still shows up straight away rather than after the next print.
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
"""Statistics keeps naming a printer that was deleted with its history (#2873).
|
||||
|
||||
Deleting a printer while keeping its prints leaves the log rows pointing at an
|
||||
id nothing resolves any more, so every per-printer breakdown fell back to
|
||||
"Printer 1" for machines the reporter knew as "Ultron". Each run recorded the
|
||||
name it printed on, so that is what the aggregates report now.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import pytest
|
||||
from httpx import AsyncClient
|
||||
|
||||
from backend.app.models.print_log import PrintLogEntry
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.integration
|
||||
async def test_stats_name_history_of_a_deleted_printer(async_client: AsyncClient, db_session):
|
||||
base = datetime(2026, 7, 15, 10, 0, 0)
|
||||
db_session.add_all(
|
||||
[
|
||||
PrintLogEntry(
|
||||
printer_id=71,
|
||||
printer_name="Ultron",
|
||||
status="completed",
|
||||
started_at=base,
|
||||
completed_at=base + timedelta(hours=1),
|
||||
duration_seconds=3600,
|
||||
),
|
||||
PrintLogEntry(
|
||||
printer_id=71,
|
||||
printer_name="Ultron",
|
||||
status="failed",
|
||||
started_at=base + timedelta(hours=2),
|
||||
completed_at=base + timedelta(hours=3),
|
||||
duration_seconds=3600,
|
||||
),
|
||||
]
|
||||
)
|
||||
await db_session.commit()
|
||||
|
||||
stats = (await async_client.get("/api/v1/archives/stats")).json()
|
||||
|
||||
assert stats["prints_by_printer"]["71"] == 2
|
||||
assert stats["printer_names"]["71"] == "Ultron"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.integration
|
||||
async def test_stats_reports_the_last_name_the_printer_ran_under(async_client: AsyncClient, db_session):
|
||||
"""A printer renamed before it was deleted is remembered by its last name."""
|
||||
base = datetime(2026, 7, 15, 10, 0, 0)
|
||||
db_session.add_all(
|
||||
[
|
||||
PrintLogEntry(printer_id=71, printer_name="Ultron", status="completed", started_at=base),
|
||||
PrintLogEntry(
|
||||
printer_id=71,
|
||||
printer_name="Ultron Mk II",
|
||||
status="completed",
|
||||
started_at=base + timedelta(days=1),
|
||||
),
|
||||
# A run logged before names were recorded must not blank the label.
|
||||
PrintLogEntry(printer_id=71, printer_name=None, status="completed", started_at=base + timedelta(days=2)),
|
||||
]
|
||||
)
|
||||
await db_session.commit()
|
||||
|
||||
stats = (await async_client.get("/api/v1/archives/stats")).json()
|
||||
|
||||
assert stats["printer_names"]["71"] == "Ultron Mk II"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.integration
|
||||
async def test_stats_names_do_not_override_a_live_printer(async_client: AsyncClient, db_session, printer_factory):
|
||||
"""Renaming a printer that still exists shows up straight away.
|
||||
|
||||
The client prefers the live record, so the historical name only has to be
|
||||
present, not authoritative.
|
||||
"""
|
||||
printer = await printer_factory(name="Renamed Later")
|
||||
db_session.add(PrintLogEntry(printer_id=printer.id, printer_name="Original Name", status="completed"))
|
||||
await db_session.commit()
|
||||
|
||||
stats = (await async_client.get("/api/v1/archives/stats")).json()
|
||||
printers = (await async_client.get("/api/v1/printers/")).json()
|
||||
|
||||
assert stats["printer_names"][str(printer.id)] == "Original Name"
|
||||
assert [p["name"] for p in printers if p["id"] == printer.id] == ["Renamed Later"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.integration
|
||||
async def test_failure_analysis_names_a_deleted_printer(async_client: AsyncClient, db_session, printer_factory):
|
||||
"""Failures by printer reads the recorded name once the printer is gone."""
|
||||
live = await printer_factory(name="Still Here")
|
||||
db_session.add_all(
|
||||
[
|
||||
PrintLogEntry(printer_id=71, printer_name="Ultron", status="failed"),
|
||||
PrintLogEntry(printer_id=live.id, printer_name="Older Name", status="failed"),
|
||||
]
|
||||
)
|
||||
await db_session.commit()
|
||||
|
||||
analysis = (await async_client.get("/api/v1/archives/analysis/failures")).json()
|
||||
|
||||
assert analysis["failures_by_printer"]["Ultron"] == 1
|
||||
assert analysis["failures_by_printer"]["Still Here"] == 1
|
||||
assert "Printer 71" not in analysis["failures_by_printer"]
|
||||
Reference in New Issue
Block a user