diff --git a/backend/src/features/vehicles/api/vehicles.controller.ts b/backend/src/features/vehicles/api/vehicles.controller.ts index 3e94dfa..4bf7870 100644 --- a/backend/src/features/vehicles/api/vehicles.controller.ts +++ b/backend/src/features/vehicles/api/vehicles.controller.ts @@ -166,20 +166,20 @@ export class VehiclesController { try { const userId = (request as any).user.sub; const { id } = request.params; - + await this.vehiclesService.deleteVehicle(id, userId); - + return reply.code(204).send(); } catch (error: any) { logger.error('Error deleting vehicle', { error, vehicleId: request.params.id, userId: (request as any).user?.sub }); - + if (error.message === 'Vehicle not found' || error.message === 'Unauthorized') { return reply.code(404).send({ error: 'Not Found', message: 'Vehicle not found' }); } - + return reply.code(500).send({ error: 'Internal server error', message: 'Failed to delete vehicle' @@ -187,6 +187,37 @@ export class VehiclesController { } } + async getTCO(request: FastifyRequest<{ Params: VehicleParams }>, reply: FastifyReply) { + try { + const userId = (request as any).user.sub; + const { id } = request.params; + + const tco = await this.vehiclesService.getTCO(id, userId); + return reply.code(200).send(tco); + } catch (error: any) { + logger.error('Error getting vehicle TCO', { error, vehicleId: request.params.id, userId: (request as any).user?.sub }); + + if (error.statusCode === 404 || error.message === 'Vehicle not found') { + return reply.code(404).send({ + error: 'Not Found', + message: 'Vehicle not found' + }); + } + + if (error.statusCode === 403 || error.message === 'Unauthorized') { + return reply.code(403).send({ + error: 'Forbidden', + message: 'Not authorized to access this vehicle' + }); + } + + return reply.code(500).send({ + error: 'Internal server error', + message: 'Failed to calculate TCO' + }); + } + } + async getDropdownMakes(request: FastifyRequest<{ Querystring: { year: number } }>, reply: FastifyReply) { try { const { year } = request.query; diff --git a/backend/src/features/vehicles/api/vehicles.routes.ts b/backend/src/features/vehicles/api/vehicles.routes.ts index c874441..e82cb6c 100644 --- a/backend/src/features/vehicles/api/vehicles.routes.ts +++ b/backend/src/features/vehicles/api/vehicles.routes.ts @@ -100,6 +100,12 @@ export const vehiclesRoutes: FastifyPluginAsync = async ( handler: vehiclesController.deleteImage.bind(vehiclesController) }); + // GET /api/vehicles/:id/tco - Get vehicle Total Cost of Ownership + fastify.get<{ Params: VehicleParams }>('/vehicles/:id/tco', { + preHandler: [fastify.authenticate], + handler: vehiclesController.getTCO.bind(vehiclesController) + }); + // Dynamic :id routes MUST come last to avoid matching specific paths like "dropdown" // GET /api/vehicles/:id - Get specific vehicle fastify.get<{ Params: VehicleParams }>('/vehicles/:id', {