mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-09 15:35:39 +02:00
Add archive_id to SpoolUsageHistory model and update cost calculations in usage_tracker
This commit is contained in:
@@ -862,7 +862,7 @@ async def rescan_archive(
|
||||
|
||||
if archive.filament_used_grams and archive.filament_type:
|
||||
usage_result = await db.execute(
|
||||
select(func.sum(SpoolUsageHistory.cost)).where(SpoolUsageHistory.print_name == archive.print_name)
|
||||
select(func.sum(SpoolUsageHistory.cost)).where(SpoolUsageHistory.archive_id == archive.id)
|
||||
)
|
||||
usage_cost = usage_result.scalar()
|
||||
if usage_cost is not None and usage_cost > 0:
|
||||
@@ -912,24 +912,35 @@ async def recalculate_all_costs(
|
||||
default_cost_setting = await get_setting(db, "default_filament_cost")
|
||||
default_cost_per_kg = float(default_cost_setting) if default_cost_setting else 25.0
|
||||
|
||||
# Pre-fetch all usage costs in one query
|
||||
# Pre-fetch all usage costs by archive_id
|
||||
usage_costs_result = await db.execute(
|
||||
select(SpoolUsageHistory.print_name, func.sum(SpoolUsageHistory.cost)).group_by(SpoolUsageHistory.print_name)
|
||||
select(SpoolUsageHistory.archive_id, func.sum(SpoolUsageHistory.cost)).group_by(SpoolUsageHistory.archive_id)
|
||||
)
|
||||
usage_costs = usage_costs_result.fetchall()
|
||||
cost_map = {row[0]: row[1] for row in usage_costs if row[1] is not None and row[1] > 0}
|
||||
cost_map = {row[0]: row[1] for row in usage_costs if row[0] is not None and row[1] is not None and row[1] > 0}
|
||||
|
||||
updated = 0
|
||||
for archive in archives:
|
||||
usage_cost = cost_map.get(archive.print_name)
|
||||
usage_cost = cost_map.get(archive.id)
|
||||
if usage_cost is not None:
|
||||
new_cost = round(usage_cost, 2)
|
||||
elif archive.filament_used_grams and archive.filament_type:
|
||||
primary_type = archive.filament_type.split(",")[0].strip()
|
||||
cost_per_kg = filaments.get(primary_type, default_cost_per_kg)
|
||||
new_cost = round((archive.filament_used_grams / 1000) * cost_per_kg, 2)
|
||||
else:
|
||||
new_cost = None
|
||||
# Fallback: sum costs for old records by print_name
|
||||
usage_result = await db.execute(
|
||||
select(func.sum(SpoolUsageHistory.cost)).where(
|
||||
SpoolUsageHistory.print_name == archive.print_name,
|
||||
SpoolUsageHistory.archive_id is None,
|
||||
)
|
||||
)
|
||||
fallback_cost = usage_result.scalar()
|
||||
if fallback_cost is not None and fallback_cost > 0:
|
||||
new_cost = round(fallback_cost, 2)
|
||||
elif archive.filament_used_grams and archive.filament_type:
|
||||
primary_type = archive.filament_type.split(",")[0].strip()
|
||||
cost_per_kg = filaments.get(primary_type, default_cost_per_kg)
|
||||
new_cost = round((archive.filament_used_grams / 1000) * cost_per_kg, 2)
|
||||
else:
|
||||
new_cost = None
|
||||
if new_cost is not None and archive.cost != new_cost:
|
||||
archive.cost = new_cost
|
||||
updated += 1
|
||||
|
||||
@@ -15,6 +15,7 @@ class SpoolUsageHistory(Base):
|
||||
spool_id: Mapped[int] = mapped_column(ForeignKey("spool.id", ondelete="CASCADE"))
|
||||
printer_id: Mapped[int | None] = mapped_column(ForeignKey("printers.id", ondelete="SET NULL"))
|
||||
print_name: Mapped[str | None] = mapped_column(String(500))
|
||||
archive_id: Mapped[int | None] = mapped_column(ForeignKey("print_archives.id"), nullable=True)
|
||||
weight_used: Mapped[float] = mapped_column(Float, default=0)
|
||||
percent_used: Mapped[int] = mapped_column(Integer, default=0)
|
||||
status: Mapped[str] = mapped_column(String(20), default="completed") # completed/failed/aborted
|
||||
|
||||
@@ -253,7 +253,10 @@ async def on_print_complete(
|
||||
|
||||
Returns a list of dicts describing what was logged (for WebSocket broadcast).
|
||||
"""
|
||||
from sqlalchemy import select
|
||||
|
||||
from backend.app.api.routes.settings import get_setting
|
||||
from backend.app.models.spool_usage_history import SpoolUsageHistory
|
||||
|
||||
session = _active_sessions.pop(printer_id, None)
|
||||
status = data.get("status", "completed")
|
||||
@@ -375,6 +378,7 @@ async def on_print_complete(
|
||||
percent_used=delta_pct,
|
||||
status=status,
|
||||
cost=cost,
|
||||
archive_id=archive_id,
|
||||
)
|
||||
db.add(history)
|
||||
|
||||
@@ -405,6 +409,35 @@ async def on_print_complete(
|
||||
if results:
|
||||
await db.commit()
|
||||
|
||||
# --- Update PrintArchive.cost to sum all SpoolUsageHistory costs for this archive ---
|
||||
|
||||
if archive_id:
|
||||
from sqlalchemy import func, select
|
||||
|
||||
from backend.app.models.archive import PrintArchive
|
||||
|
||||
# First try: sum by archive_id
|
||||
cost_result = await db.execute(
|
||||
select(func.coalesce(func.sum(SpoolUsageHistory.cost), 0)).where(SpoolUsageHistory.archive_id == archive_id)
|
||||
)
|
||||
total_cost = cost_result.scalar() or 0
|
||||
|
||||
# Fallback: if no cost found, sum by print_name and printer_id (legacy)
|
||||
archive_result = await db.execute(select(PrintArchive).where(PrintArchive.id == archive_id))
|
||||
archive = archive_result.scalar_one_or_none()
|
||||
if archive and total_cost == 0 and archive.print_name and archive.printer_id:
|
||||
legacy_cost_result = await db.execute(
|
||||
select(func.coalesce(func.sum(SpoolUsageHistory.cost), 0)).where(
|
||||
SpoolUsageHistory.archive_id is None,
|
||||
SpoolUsageHistory.print_name == archive.print_name,
|
||||
SpoolUsageHistory.printer_id == archive.printer_id,
|
||||
)
|
||||
)
|
||||
total_cost = legacy_cost_result.scalar() or 0
|
||||
if archive:
|
||||
archive.cost = total_cost
|
||||
await db.commit()
|
||||
|
||||
return results
|
||||
|
||||
|
||||
@@ -678,6 +711,7 @@ async def _track_from_3mf(
|
||||
percent_used=percent,
|
||||
status=status,
|
||||
cost=cost,
|
||||
archive_id=archive_id,
|
||||
)
|
||||
db.add(history)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user