Browse Source

Fix cost tracking issues

maziggy 3 months ago
parent
commit
1404242e0c

+ 1 - 1
backend/app/api/routes/archives.py

@@ -929,7 +929,7 @@ async def recalculate_all_costs(
             usage_result = await db.execute(
                 select(func.sum(SpoolUsageHistory.cost)).where(
                     SpoolUsageHistory.print_name == archive.print_name,
-                    SpoolUsageHistory.archive_id is None,
+                    SpoolUsageHistory.archive_id.is_(None),
                 )
             )
             fallback_cost = usage_result.scalar()

+ 7 - 0
backend/app/core/database.py

@@ -1233,6 +1233,13 @@ async def run_migrations(conn):
         await conn.execute(text("ALTER TABLE spool_usage_history ADD COLUMN cost REAL"))
     except OperationalError:
         pass  # Already applied
+    # Migration: Add archive_id field to spool_usage_history table
+    try:
+        await conn.execute(
+            text("ALTER TABLE spool_usage_history ADD COLUMN archive_id INTEGER REFERENCES print_archives(id)")
+        )
+    except OperationalError:
+        pass  # Already applied
 
     # Migration: Migrate single virtual printer key-value settings to virtual_printers table
     try:

+ 0 - 20
backend/app/main.py

@@ -2403,26 +2403,6 @@ async def on_print_complete(printer_id: int, data: dict):
                     )
                     log_timing("Usage tracker")
 
-                # Aggregate spool usage costs to archive
-                if archive_id and usage_results:
-                    try:
-                        from backend.app.models.archive import PrintArchive
-
-                        # Sum all costs from usage results
-                        total_spool_cost = sum(result.get("cost", 0) or 0 for result in usage_results)
-
-                        if total_spool_cost > 0:
-                            # Update archive cost (replace any existing cost with accurate spool-based cost)
-                            archive_result = await db.execute(select(PrintArchive).where(PrintArchive.id == archive_id))
-                            archive = archive_result.scalar_one_or_none()
-                            if archive:
-                                archive.cost = round(total_spool_cost, 2)
-                                await db.commit()
-                                logger.info(
-                                    "[COST] Updated archive %s with spool-based cost: %.2f", archive_id, archive.cost
-                                )
-                    except Exception as e:
-                        logger.warning("[COST] Failed to aggregate spool costs to archive %s: %s", archive_id, e)
     except Exception as e:
         logger.warning("Usage tracker on_print_complete failed: %s", e)
 

+ 3 - 3
backend/app/services/usage_tracker.py

@@ -450,14 +450,14 @@ async def on_print_complete(
         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.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
+        if archive and total_cost > 0:
+            archive.cost = round(total_cost, 2)
             await db.commit()
 
     return results

+ 10 - 17
frontend/src/components/PrintModal/FilamentMapping.tsx

@@ -66,6 +66,10 @@ export function FilamentMapping({
     return total;
   }, [filamentComparison, trayCostMap, defaultCostPerKg]);
 
+  const hasAnyCost = useMemo(
+    () => Array.from(trayCostMap.values()).some((v) => v != null && v > 0),
+    [trayCostMap]
+  );
   const hasFilamentReqs = filamentReqs?.filaments && filamentReqs.filaments.length > 0;
   const isDualNozzle = filamentReqs?.filaments?.some((f) => f.nozzle_id != null) ?? false;
 
@@ -214,23 +218,12 @@ export function FilamentMapping({
               )}
             </div>
           ))}
-          {(() => {
-            // Check if any tray has a configured cost_per_kg
-            const hasAnyCost = Array.from(trayCostMap.values()).some((v) => v != null && v > 0);
-            if (totalCost > 0 || hasAnyCost) {
-              return (
-                <div className="text-xs text-bambu-gray">
-                  {t('printModal.totalCost')} <span className="text-white">{currencySymbol}{totalCost.toFixed(2)}</span>
-                </div>
-              );
-            } else {
-              return (
-                <div className="text-xs text-bambu-gray">
-                  {t('printModal.totalCost')} <span className="text-white">N/A</span>
-                </div>
-              );
-            }
-          })()}
+          <div className="text-xs text-bambu-gray">
+            {t('printModal.totalCost')}{' '}
+            <span className="text-white">
+              {totalCost > 0 || hasAnyCost ? `${currencySymbol}${totalCost.toFixed(2)}` : 'N/A'}
+            </span>
+          </div>
           {hasTypeMismatch && (
             <p className="text-xs text-orange-400 mt-2">Required filament type not found in printer.</p>
           )}

+ 0 - 5
frontend/src/pages/InventoryPage.tsx

@@ -365,11 +365,6 @@ export default function InventoryPage() {
     refetchInterval: 30000,
   });
 
-  const { data: settings } = useQuery({
-    queryKey: ['settings'],
-    queryFn: api.getSettings,
-  });
-
   const deleteMutation = useMutation({
     mutationFn: (id: number) => api.deleteSpool(id),
     onSuccess: () => {

File diff suppressed because it is too large
+ 0 - 0
static/assets/index-DY3iUVJG.js


+ 1 - 1
static/index.html

@@ -23,7 +23,7 @@
 
     <!-- Splash screens for iOS -->
     <link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
-    <script type="module" crossorigin src="/assets/index-uDg4paLx.js"></script>
+    <script type="module" crossorigin src="/assets/index-DY3iUVJG.js"></script>
     <link rel="stylesheet" crossorigin href="/assets/index-DJax8qcY.css">
   </head>
   <body>

Some files were not shown because too many files changed in this diff