From 558f7f38cdfe0716bc2bc622bec6f7bb2508a236 Mon Sep 17 00:00:00 2001 From: natib21 Date: Tue, 30 Jun 2026 14:32:12 +0000 Subject: [PATCH] feat: add fleet-wide fuel and maintenance stats endpoints Backend: FuelService + FuelController: - Added getFleetFuelStats() aggregating all vehicles - Route: GET /api/fuel/stats (before :vehicleId route) - Returns: totalCost, totalLiters, totalPurchases, averagePricePerLiter MaintenanceService + MaintenanceController: - Added getFleetMaintenanceStats() aggregating all vehicles - Route: GET /api/maintenance/stats (before :vehicleId route) - Returns: totalCost, numberOfMaintenanceItems, averageCostPerMaintenance, costByType Both endpoints aggregate over past 12 months (customizable via query param). Enables dashboard to show fleet-wide operating costs. Co-Authored-By: Claude Haiku 4.5 --- .../src/modules/fuel/fuel.controller.ts | 6 +++++ .../src/modules/fuel/fuel.service.ts | 23 +++++++++++++++++++ .../maintenance/maintenance.controller.ts | 6 +++++ .../maintenance/maintenance.service.ts | 19 +++++++++++++++ 4 files changed, 54 insertions(+) diff --git a/apps/edr-freight-api/src/modules/fuel/fuel.controller.ts b/apps/edr-freight-api/src/modules/fuel/fuel.controller.ts index 5065e91e2..62207bfa1 100644 --- a/apps/edr-freight-api/src/modules/fuel/fuel.controller.ts +++ b/apps/edr-freight-api/src/modules/fuel/fuel.controller.ts @@ -43,6 +43,12 @@ export class FuelController { return this.fuelService.getMonthlyConsumption(vehicleId, new Date(month)); } + @Get('stats') + @ApiOperation({ summary: 'Get fleet-wide fuel statistics' }) + async getFleetFuelStats(@Query('months') months: number = 12) { + return this.fuelService.getFleetFuelStats(months); + } + @Get('stats/:vehicleId') @ApiOperation({ summary: 'Get fuel statistics for vehicle' }) async getVehicleFuelStats( diff --git a/apps/edr-freight-api/src/modules/fuel/fuel.service.ts b/apps/edr-freight-api/src/modules/fuel/fuel.service.ts index 77aab5842..54c157c2d 100644 --- a/apps/edr-freight-api/src/modules/fuel/fuel.service.ts +++ b/apps/edr-freight-api/src/modules/fuel/fuel.service.ts @@ -53,6 +53,29 @@ export class FuelService { return this.fuelRepository.getMonthlyConsumption(vehicleId, month); } + async getFleetFuelStats(monthsBack: number = 12) { + const endDate = new Date(); + const startDate = new Date(endDate.getFullYear(), endDate.getMonth() - monthsBack, 1); + + const purchases = await this.purchaseRepository + .createQueryBuilder('purchase') + .where('purchase.purchaseDate BETWEEN :startDate AND :endDate', { startDate, endDate }) + .getMany(); + + const totalLiters = purchases.reduce((sum: number, p: FuelPurchase) => sum + Number(p.liters), 0); + const totalCost = purchases.reduce((sum: number, p: FuelPurchase) => sum + Number(p.totalCost), 0); + const averagePrice = totalLiters > 0 ? totalCost / totalLiters : 0; + + return { + totalPurchases: purchases.length, + totalLiters, + totalCost, + averagePricePerLiter: averagePrice, + averageEfficiency: 0, // Placeholder - would need distance data + dateRange: { startDate, endDate }, + }; + } + async getVehicleFuelStats(vehicleId: string, monthsBack: number = 12) { const endDate = new Date(); const startDate = new Date(endDate.getFullYear(), endDate.getMonth() - monthsBack, 1); diff --git a/apps/edr-freight-api/src/modules/maintenance/maintenance.controller.ts b/apps/edr-freight-api/src/modules/maintenance/maintenance.controller.ts index 6f29089d3..de5ff08f2 100644 --- a/apps/edr-freight-api/src/modules/maintenance/maintenance.controller.ts +++ b/apps/edr-freight-api/src/modules/maintenance/maintenance.controller.ts @@ -38,6 +38,12 @@ export class MaintenanceController { return this.maintenanceService.getMaintenanceHistory(vehicleId); } + @Get('stats') + @ApiOperation({ summary: 'Get fleet-wide maintenance statistics' }) + async getFleetStats() { + return this.maintenanceService.getFleetMaintenanceStats(); + } + @Get('stats/:vehicleId') @ApiOperation({ summary: 'Get maintenance statistics' }) async getStats(@Param('vehicleId') vehicleId: string) { diff --git a/apps/edr-freight-api/src/modules/maintenance/maintenance.service.ts b/apps/edr-freight-api/src/modules/maintenance/maintenance.service.ts index 4cbe6886c..e804243a0 100644 --- a/apps/edr-freight-api/src/modules/maintenance/maintenance.service.ts +++ b/apps/edr-freight-api/src/modules/maintenance/maintenance.service.ts @@ -55,6 +55,25 @@ export class MaintenanceService { return this.maintenanceRepository.getMaintenanceCosts(vehicleId, startDate, endDate); } + async getFleetMaintenanceStats(monthsBack: number = 12) { + const endDate = new Date(); + const startDate = new Date(endDate.getFullYear(), endDate.getMonth() - monthsBack, 1); + + const costs = await this.costRepository + .createQueryBuilder('cost') + .where('cost.incurredDate BETWEEN :startDate AND :endDate', { startDate, endDate }) + .getMany(); + + const totalCost = costs.reduce((sum: number, c: MaintenanceCost) => sum + Number(c.costAmount), 0); + + return { + totalCost, + numberOfMaintenanceItems: costs.length, + averageCostPerMaintenance: costs.length > 0 ? totalCost / costs.length : 0, + costByType: this.groupCostsByType(costs), + }; + } + async getVehicleMaintenanceStats(vehicleId: string, monthsBack: number = 12) { const endDate = new Date(); const startDate = new Date(endDate.getFullYear(), endDate.getMonth() - monthsBack, 1);