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

Fix filament calculation incorrectly multiplied by quantity

The filament_used_grams field already contains the total filament for
the entire print job (all items combined). The code was incorrectly
multiplying this value by quantity, causing inflated filament totals.

Example: A print with 26 objects using 126g total was being calculated
as 126g * 26 = 3,276g instead of the correct 126g.

Fixes:
- backend/app/api/routes/archives.py: Archive stats endpoint
- backend/app/api/routes/metrics.py: Prometheus metrics endpoint
- frontend/src/components/FilamentTrends.tsx: Trends chart calculations

Closes #229
maziggy 3 месяцев назад
Родитель
Сommit
d4ca646581

+ 7 - 0
CHANGELOG.md

@@ -5,6 +5,13 @@ All notable changes to Bambuddy will be documented in this file.
 
 ## [0.1.8b] - Not released
 
+### Fixed
+- **Filament Statistics Incorrectly Multiplied by Quantity** (Issue #229):
+  - Fixed filament totals being inflated by incorrectly multiplying by quantity
+  - The `filament_used_grams` field already contains the total for the entire print job
+  - Removed incorrect `* quantity` multiplication from archive stats, Prometheus metrics, and FilamentTrends chart
+  - Example: A print with 26 objects using 126g was incorrectly shown as 3,276g
+
 ### Added
 - **Windows Portable Launcher** (contributed by nmori):
   - New `start_bambuddy.bat` for Windows users - double-click to run, no installation required

+ 2 - 4
backend/app/api/routes/archives.py

@@ -466,10 +466,8 @@ async def get_archive_stats(
             total_seconds += print_time_seconds
     total_time = total_seconds / 3600  # Convert to hours
 
-    # Multiply filament by quantity to account for multiple items printed
-    filament_result = await db.execute(
-        select(func.sum(PrintArchive.filament_used_grams * func.coalesce(PrintArchive.quantity, 1)))
-    )
+    # Sum filament directly - filament_used_grams already contains the total for the print job
+    filament_result = await db.execute(select(func.coalesce(func.sum(PrintArchive.filament_used_grams), 0)))
     total_filament = filament_result.scalar() or 0
 
     cost_result = await db.execute(select(func.sum(PrintArchive.cost)))

+ 2 - 4
backend/app/api/routes/metrics.py

@@ -362,13 +362,11 @@ async def get_metrics(
             )
             lines.append(f"bambuddy_printer_prints_total{labels} {count}")
 
-    # Total filament used (multiply by quantity to account for multiple items printed)
+    # Total filament used - filament_used_grams already contains the total for each print job
     lines.append("")
     lines.append("# HELP bambuddy_filament_used_grams Total filament used in grams")
     lines.append("# TYPE bambuddy_filament_used_grams counter")
-    result = await db.execute(
-        select(func.coalesce(func.sum(PrintArchive.filament_used_grams * func.coalesce(PrintArchive.quantity, 1)), 0))
-    )
+    result = await db.execute(select(func.coalesce(func.sum(PrintArchive.filament_used_grams), 0)))
     total_filament = result.scalar() or 0
     lines.append(f"bambuddy_filament_used_grams {total_filament:.1f}")
 

+ 2 - 2
frontend/src/components/FilamentTrends.tsx

@@ -143,7 +143,7 @@ export function FilamentTrends({ archives, currency = '$' }: FilamentTrendsProps
 
       months.push({
         month: monthStr,
-        filament: Math.round(monthArchives.reduce((sum, a) => sum + (a.filament_used_grams || 0) * (a.quantity || 1), 0)),
+        filament: Math.round(monthArchives.reduce((sum, a) => sum + (a.filament_used_grams || 0), 0)),
         cost: monthArchives.reduce((sum, a) => sum + (a.cost || 0), 0),
         prints: monthArchives.reduce((sum, a) => sum + (a.quantity || 1), 0),
       });
@@ -153,7 +153,7 @@ export function FilamentTrends({ archives, currency = '$' }: FilamentTrendsProps
   }, [archives]);
 
   const chartData = timeRange === '7d' || timeRange === '30d' ? dailyData : weeklyData;
-  const totalFilament = filteredArchives.reduce((sum, a) => sum + (a.filament_used_grams || 0) * (a.quantity || 1), 0);
+  const totalFilament = filteredArchives.reduce((sum, a) => sum + (a.filament_used_grams || 0), 0);
   const totalCost = filteredArchives.reduce((sum, a) => sum + (a.cost || 0), 0);
   const totalPrints = filteredArchives.reduce((sum, a) => sum + (a.quantity || 1), 0);
 

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
static/assets/index-2WXQ5Rri.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
static/assets/index-B5vyvTs3.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
static/assets/index-BtqA5ccK.css


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
static/assets/index-DME4t7XG.css


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
static/assets/index-SHZgHE2U.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
static/assets/index-hIPoB0LS.css


+ 2 - 2
static/index.html

@@ -23,8 +23,8 @@
 
     <!-- Splash screens for iOS -->
     <link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
-    <script type="module" crossorigin src="/assets/index-B5vyvTs3.js"></script>
-    <link rel="stylesheet" crossorigin href="/assets/index-DME4t7XG.css">
+    <script type="module" crossorigin src="/assets/index-2WXQ5Rri.js"></script>
+    <link rel="stylesheet" crossorigin href="/assets/index-hIPoB0LS.css">
   </head>
   <body>
     <div id="root"></div>

Некоторые файлы не были показаны из-за большого количества измененных файлов