From ce95263ea8e6b0561554f06fb6da864cfd6c2cd0 Mon Sep 17 00:00:00 2001 From: aligneddev Date: Mon, 20 Jul 2026 13:35:38 +0000 Subject: [PATCH 1/2] removed combined savings --- .../src/pages/advanced-dashboard/SavingsWindowsTable.tsx | 4 ---- .../src/pages/advanced-dashboard/advanced-dashboard-page.css | 5 ----- 2 files changed, 9 deletions(-) diff --git a/src/BikeTracking.Frontend/src/pages/advanced-dashboard/SavingsWindowsTable.tsx b/src/BikeTracking.Frontend/src/pages/advanced-dashboard/SavingsWindowsTable.tsx index 336093c..e77ed78 100644 --- a/src/BikeTracking.Frontend/src/pages/advanced-dashboard/SavingsWindowsTable.tsx +++ b/src/BikeTracking.Frontend/src/pages/advanced-dashboard/SavingsWindowsTable.tsx @@ -59,9 +59,6 @@ function WindowRow({ window: w }: WindowRowProps) { ) : null} {formatCurrency(w.mileageRateSavings)} - - {formatCurrency(w.combinedSavings)} - {formatCurrency(w.totalExpenses)} {formatCurrency(w.oilChangeSavings)} Gallons Saved Fuel Cost Avoided Mileage Rate - Combined Savings Expenses Oil Change Savings Net Savings diff --git a/src/BikeTracking.Frontend/src/pages/advanced-dashboard/advanced-dashboard-page.css b/src/BikeTracking.Frontend/src/pages/advanced-dashboard/advanced-dashboard-page.css index f4c4e34..54f4f21 100644 --- a/src/BikeTracking.Frontend/src/pages/advanced-dashboard/advanced-dashboard-page.css +++ b/src/BikeTracking.Frontend/src/pages/advanced-dashboard/advanced-dashboard-page.css @@ -150,11 +150,6 @@ color: var(--adv-ink); } -.savings-windows-combined { - font-weight: 700; - color: #065f46; -} - .savings-windows-row:last-child .savings-windows-cell { border-bottom: none; } From 5c75881240281122556f8bb700f437f70b4372ea Mon Sep 17 00:00:00 2001 From: aligneddev Date: Mon, 20 Jul 2026 13:40:29 +0000 Subject: [PATCH 2/2] fix Net Savings --- .../Dashboard/GetAdvancedDashboardServiceTests.cs | 14 ++++++++++---- .../Dashboard/GetAdvancedDashboardService.cs | 9 +++------ .../Contracts/AdvancedDashboardContracts.cs | 4 ++-- .../src/services/advanced-dashboard-api.ts | 4 ++-- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/BikeTracking.Api.Tests/Application/Dashboard/GetAdvancedDashboardServiceTests.cs b/src/BikeTracking.Api.Tests/Application/Dashboard/GetAdvancedDashboardServiceTests.cs index f3faf21..f3e8632 100644 --- a/src/BikeTracking.Api.Tests/Application/Dashboard/GetAdvancedDashboardServiceTests.cs +++ b/src/BikeTracking.Api.Tests/Application/Dashboard/GetAdvancedDashboardServiceTests.cs @@ -426,7 +426,8 @@ public async Task GetAdvancedDashboardService_WithExpensesInWindow_IncludesExpen } [Fact] - public async Task GetAdvancedDashboardService_WithExpenses_NetSavingsIsCombinedMinusExpenses() + public async Task + GetAdvancedDashboardService_WithFuelCostAndMileageRate_NetSavingsUsesFuelCostOnly() { using var dbContext = CreateDbContext(); var rider = await CreateRiderAsync(dbContext, "NetSavings Rider"); @@ -437,6 +438,8 @@ public async Task GetAdvancedDashboardService_WithExpenses_NetSavingsIsCombinedM RiderId = rider.UserId, RideDateTimeLocal = DateTime.Now.AddMonths(-3), Miles = 100m, + SnapshotAverageCarMpg = 20m, + GasPricePerGallon = 3m, SnapshotMileageRateCents = 67m, CreatedAtUtc = DateTime.UtcNow, } @@ -458,10 +461,13 @@ public async Task GetAdvancedDashboardService_WithExpenses_NetSavingsIsCombinedM var service = new GetAdvancedDashboardService(dbContext, TimeProvider.System); var result = await service.GetAsync(rider.UserId); - // 100 miles × 67 = 6700 combined savings - 30 expenses = 6670 net - Assert.Equal(6700m, result.SavingsWindows.AllTime.CombinedSavings); + // 100 miles / 20 mpg × $3 = $15 fuel cost avoided - $30 expenses = -$15 net + // Mileage-rate savings still exists, but it does not feed net savings. + Assert.Equal(15m, result.SavingsWindows.AllTime.FuelCostAvoided); + Assert.Equal(6700m, result.SavingsWindows.AllTime.MileageRateSavings); + Assert.Equal(6715m, result.SavingsWindows.AllTime.CombinedSavings); Assert.Equal(30m, result.SavingsWindows.AllTime.TotalExpenses); - Assert.Equal(6670m, result.SavingsWindows.AllTime.NetSavings); + Assert.Equal(-15m, result.SavingsWindows.AllTime.NetSavings); } [Fact] diff --git a/src/BikeTracking.Api/Application/Dashboard/GetAdvancedDashboardService.cs b/src/BikeTracking.Api/Application/Dashboard/GetAdvancedDashboardService.cs index 69998d4..5317da0 100644 --- a/src/BikeTracking.Api/Application/Dashboard/GetAdvancedDashboardService.cs +++ b/src/BikeTracking.Api/Application/Dashboard/GetAdvancedDashboardService.cs @@ -253,15 +253,12 @@ private static AdvancedSavingsWindow BuildWindow( oilChangeSavings = crossings > 0 ? RoundTo2(crossings * oilChangePrice.Value) : 0m; } - // Net savings: gross savings + oil-change offset − expenses. - // Null only when all savings are unavailable and there are no expenses. + // Net savings: fuel-cost avoided plus oil-change offset minus expenses. decimal? netSavings = null; - bool hasSavingsData = combinedSavings.HasValue || oilChangeSavings.HasValue; + bool hasSavingsData = fuelCostAvoided.HasValue || oilChangeSavings.HasValue; if (hasSavingsData || totalExpenses > 0m) { - netSavings = RoundTo2( - (combinedSavings ?? 0m) + (oilChangeSavings ?? 0m) - totalExpenses - ); + netSavings = RoundTo2((fuelCostAvoided ?? 0m) + (oilChangeSavings ?? 0m) - totalExpenses); } return new AdvancedSavingsWindow( diff --git a/src/BikeTracking.Api/Contracts/AdvancedDashboardContracts.cs b/src/BikeTracking.Api/Contracts/AdvancedDashboardContracts.cs index 8bdd48e..9e8c327 100644 --- a/src/BikeTracking.Api/Contracts/AdvancedDashboardContracts.cs +++ b/src/BikeTracking.Api/Contracts/AdvancedDashboardContracts.cs @@ -88,8 +88,8 @@ public sealed record AdvancedSavingsWindow( /// decimal? OilChangeSavings, /// - /// Net financial position: (FuelCostAvoided ?? 0) + (MileageRateSavings ?? 0) + (OilChangeSavings ?? 0) − TotalExpenses. - /// Null only when all savings components are null and expenses are zero. + /// Net financial position: (FuelCostAvoided ?? 0) + (OilChangeSavings ?? 0) − TotalExpenses. + /// Null only when fuel/oil savings are unavailable and expenses are zero. /// Can be negative when expenses exceed savings. /// decimal? NetSavings diff --git a/src/BikeTracking.Frontend/src/services/advanced-dashboard-api.ts b/src/BikeTracking.Frontend/src/services/advanced-dashboard-api.ts index 69b99e3..a73c43b 100644 --- a/src/BikeTracking.Frontend/src/services/advanced-dashboard-api.ts +++ b/src/BikeTracking.Frontend/src/services/advanced-dashboard-api.ts @@ -23,8 +23,8 @@ export interface AdvancedSavingsWindow { */ oilChangeSavings: number | null; /** - * Net financial position: combinedSavings + oilChangeSavings − totalExpenses. - * Null only when all savings are null and expenses are zero. Can be negative. + * Net financial position: fuelCostAvoided + oilChangeSavings − totalExpenses. + * Null only when fuel/oil savings are unavailable and expenses are zero. Can be negative. */ netSavings: number | null; }