Просмотр исходного кода

Print time stats using slicer estimates

Quick Stats "Print Time" now uses actual elapsed time (`completed_at - started_at`) instead of slicer estimates;
cancelled prints only count time actually printed

Closes #137
maziggy 4 месяцев назад
Родитель
Сommit
a6b1c5adbe
2 измененных файлов с 18 добавлено и 3 удалено
  1. 1 0
      CHANGELOG.md
  2. 17 3
      backend/app/api/routes/archives.py

+ 1 - 0
CHANGELOG.md

@@ -30,6 +30,7 @@ All notable changes to Bambuddy will be documented in this file.
   - Full URL constructed for external notification services (Telegram, Email, Discord, etc.)
   - Full URL constructed for external notification services (Telegram, Email, Discord, etc.)
 
 
 ### Fixed
 ### Fixed
+- **Print time stats using slicer estimates** - Quick Stats "Print Time" now uses actual elapsed time (`completed_at - started_at`) instead of slicer estimates; cancelled prints only count time actually printed (Issue #137)
 - **Filament cost using wrong default** - Statistics now correctly uses the "Default filament cost (per kg)" setting instead of hardcoded €25 value (Issue #120)
 - **Filament cost using wrong default** - Statistics now correctly uses the "Default filament cost (per kg)" setting instead of hardcoded €25 value (Issue #120)
 - **Spoolman tag field not auto-created** - The required "tag" extra field is now automatically created in Spoolman on first connect, fixing sync failures for fresh Spoolman installs (Issue #123)
 - **Spoolman tag field not auto-created** - The required "tag" extra field is now automatically created in Spoolman on first connect, fixing sync failures for fresh Spoolman installs (Issue #123)
 - **P2S/X1E/H2 completion photo not captured** - Internal model codes (N7, C13, O1D, etc.) from MQTT/SSDP are now recognized for RTSP camera support (Issue #127)
 - **P2S/X1E/H2 completion photo not captured** - Internal model codes (N7, C13, O1D, etc.) from MQTT/SSDP are now recognized for RTSP camera support (Issue #127)

+ 17 - 3
backend/app/api/routes/archives.py

@@ -425,9 +425,23 @@ async def get_archive_stats(db: AsyncSession = Depends(get_db)):
     failed_result = await db.execute(select(func.count(PrintArchive.id)).where(PrintArchive.status == "failed"))
     failed_result = await db.execute(select(func.count(PrintArchive.id)).where(PrintArchive.status == "failed"))
     failed_prints = failed_result.scalar() or 0
     failed_prints = failed_result.scalar() or 0
 
 
-    # Totals
-    time_result = await db.execute(select(func.sum(PrintArchive.print_time_seconds)))
-    total_time = (time_result.scalar() or 0) / 3600  # Convert to hours
+    # Totals - use actual print time from timestamps (not slicer estimates)
+    # For archives with both started_at and completed_at, calculate actual duration
+    # Fall back to print_time_seconds only for archives without timestamps
+    archives_for_time = await db.execute(
+        select(PrintArchive.started_at, PrintArchive.completed_at, PrintArchive.print_time_seconds)
+    )
+    total_seconds = 0
+    for started_at, completed_at, print_time_seconds in archives_for_time.all():
+        if started_at and completed_at:
+            # Use actual elapsed time
+            actual_seconds = (completed_at - started_at).total_seconds()
+            if actual_seconds > 0:
+                total_seconds += actual_seconds
+        elif print_time_seconds:
+            # Fallback to estimate only if no timestamps
+            total_seconds += print_time_seconds
+    total_time = total_seconds / 3600  # Convert to hours
 
 
     filament_result = await db.execute(select(func.sum(PrintArchive.filament_used_grams)))
     filament_result = await db.execute(select(func.sum(PrintArchive.filament_used_grams)))
     total_filament = filament_result.scalar() or 0
     total_filament = filament_result.scalar() or 0