feat: Total Cost of Ownership (TCO) per Vehicle #28

Merged
egullickson merged 11 commits from issue-15-add-tco-feature into main 2026-01-14 03:08:35 +00:00
2 changed files with 21 additions and 1 deletions
Showing only changes of commit 35fd1782b4 - Show all commits

View File

@@ -9,7 +9,8 @@ import type {
MaintenanceRecordResponse,
MaintenanceScheduleResponse,
MaintenanceCategory,
ScheduleType
ScheduleType,
MaintenanceCostStats
} from './maintenance.types';
import { validateSubtypes } from './maintenance.types';
import { MaintenanceRepository } from '../data/maintenance.repository';
@@ -63,6 +64,19 @@ export class MaintenanceService {
return records.map(r => this.toRecordResponse(r));
}
async getVehicleMaintenanceCosts(vehicleId: string, userId: string): Promise<MaintenanceCostStats> {
const records = await this.repo.findRecordsByVehicleId(vehicleId, userId);
const totalCost = records.reduce((sum, r) => {
if (r.cost === null || r.cost === undefined) return sum;
const cost = Number(r.cost);
if (isNaN(cost)) {
throw new Error(`Invalid cost value for maintenance record ${r.id}`);
}
return sum + cost;
}, 0);
return { totalCost, recordCount: records.length };
}
async updateRecord(userId: string, id: string, patch: UpdateMaintenanceRecordRequest): Promise<MaintenanceRecordResponse | null> {
const existing = await this.repo.findRecordById(id, userId);
if (!existing) return null;

View File

@@ -162,6 +162,12 @@ export interface MaintenanceRecordResponse extends MaintenanceRecord {
subtypeCount: number;
}
// TCO aggregation stats
export interface MaintenanceCostStats {
totalCost: number;
recordCount: number;
}
export interface MaintenanceScheduleResponse extends MaintenanceSchedule {
subtypeCount: number;
isDueSoon?: boolean;