chore: Update Documentation
All checks were successful
Deploy to Staging / Build Images (push) Successful in 2m19s
Deploy to Staging / Deploy to Staging (push) Successful in 27s
Deploy to Staging / Verify Staging (push) Successful in 5s
Deploy to Staging / Notify Staging Ready (push) Successful in 5s
Deploy to Staging / Notify Staging Failure (push) Has been skipped
Mirror Base Images / Mirror Base Images (push) Successful in 29s
All checks were successful
Deploy to Staging / Build Images (push) Successful in 2m19s
Deploy to Staging / Deploy to Staging (push) Successful in 27s
Deploy to Staging / Verify Staging (push) Successful in 5s
Deploy to Staging / Notify Staging Ready (push) Successful in 5s
Deploy to Staging / Notify Staging Failure (push) Has been skipped
Mirror Base Images / Mirror Base Images (push) Successful in 29s
This commit is contained in:
@@ -1,167 +1,434 @@
|
||||
# Vehicles API – Platform Rebuild, App Integration, and Operations
|
||||
# Vehicles API Reference
|
||||
|
||||
This document explains the end‑to‑end Vehicles API architecture after the platform service rebuild, how the MotoVaultPro app consumes it, how migrations/seeding work, and how to operate the stack in production‑only development.
|
||||
Complete API documentation for the vehicles feature in MotoVaultPro.
|
||||
|
||||
## Overview
|
||||
- Architecture: MotoVaultPro backend (Fastify + TypeScript) includes an integrated platform module that shares Postgres and Redis with the rest of the stack.
|
||||
- Goal: Predictable year→make→model→trim→engine cascades, production‑only workflow, AI‑friendly code layout and docs.
|
||||
|
||||
## Platform Vehicles Module
|
||||
The Vehicles API provides endpoints for managing user vehicles, including CRUD operations, image management, and hierarchical dropdown data for vehicle selection forms.
|
||||
|
||||
### Database Schema (Postgres schema: `vehicles`)
|
||||
- `make(id, name)`
|
||||
- `model(id, make_id → make.id, name)`
|
||||
- `model_year(id, model_id → model.id, year)`
|
||||
- `trim(id, model_year_id → model_year.id, name)`
|
||||
- `engine(id, name, code, displacement_l, cylinders, fuel_type, aspiration)`
|
||||
- `trim_engine(trim_id → trim.id, engine_id → engine.id)`
|
||||
- Optional (present, not exposed yet): `transmission`, `trim_transmission`, `performance`
|
||||
**Authentication**: All endpoints require JWT authentication via `Authorization: Bearer <token>` header.
|
||||
|
||||
Idempotent constraints/indexes added where applicable (e.g., unique lower(name), unique(model_id, year), guarded `CREATE INDEX IF NOT EXISTS`, guarded trigger).
|
||||
## Base URL
|
||||
|
||||
### Dropdown API (Bearer auth required)
|
||||
Prefix: `/api/vehicles/dropdown`
|
||||
- `GET /years` → `[number]` (latest to oldest model years)
|
||||
- `GET /makes?year={year}` → `{ id, name }[]` (makes available in that year)
|
||||
- `GET /models?year={year}&make_id={make}` → `{ id, name }[]` (models filtered by year + make)
|
||||
- `GET /trims?year={year}&make_id={make}&model_id={model}` → `{ id, name }[]` (trims for the selection)
|
||||
- `GET /engines?year={year}&make_id={make}&model_id={model}&trim_id={trim}` → `{ id, name }[]` (engines for the trim)
|
||||
- `GET /transmissions?year={year}&make_id={make}&model_id={model}` → `{ id, name }[]` (`Automatic`, `Manual`)
|
||||
```
|
||||
https://motovaultpro.com/api
|
||||
```
|
||||
|
||||
Selection order is enforced: each endpoint requires the IDs returned by the previous stage, so users never see invalid combinations (e.g., 2023 Chevrolet excludes the S-10, 1999 GMC trims exclude AT4X, etc.).
|
||||
## Vehicle CRUD Operations
|
||||
|
||||
### Platform module (internal bridge)
|
||||
Prefix: `/api/platform`
|
||||
- Same hierarchical endpoints as above, but responses are wrapped (`{ makes: [...] }`, `{ models: [...] }`) for service-to-service integrations.
|
||||
- VIN decode endpoint: `GET /api/platform/vehicle?vin={vin}`
|
||||
### List User Vehicles
|
||||
|
||||
### Authentication
|
||||
- Auth0 JWT via `Authorization: Bearer ${JWT_TOKEN}` (required for both `/api/vehicles/*` and `/api/platform/*`)
|
||||
- Configured in backend: `src/core/plugins/auth.plugin.ts` with JWKS validation
|
||||
Returns all vehicles for the authenticated user.
|
||||
|
||||
### Caching (Redis)
|
||||
- Keys: `platform:years`, `platform:vehicle-data:makes:{year}`, `platform:vehicle-data:models:{year}:{make}`, `platform:vehicle-data:trims:{year}:{model}`, `platform:vehicle-data:engines:{year}:{model}:{trim}`
|
||||
- Dropdown TTL: 6 hours (`21600s`)
|
||||
- VIN decode TTL: 7 days (`604800s`) via `platform:vin-decode:{vin}`
|
||||
- Implementation: `backend/src/features/platform/domain/platform-cache.service.ts`
|
||||
```
|
||||
GET /api/vehicles
|
||||
```
|
||||
|
||||
### Seeds & Specific Examples
|
||||
Platform seed migrations (TypeScript backend):
|
||||
- Schema definition (`backend/src/features/platform/migrations/001_create_platform_schema.sql`)
|
||||
- Constraints and indexes (`backend/src/features/platform/migrations/002_create_indexes.sql`)
|
||||
- Sample vehicle data (`backend/src/features/platform/migrations/003_seed_vehicles.sql`)
|
||||
Seeds are auto-migrated on backend container start via `backend/src/_system/migrations/run-all.ts`.
|
||||
**Response** (200):
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "uuid",
|
||||
"userId": "auth0|123456",
|
||||
"vin": "1HGBH41JXMN109186",
|
||||
"make": "Honda",
|
||||
"model": "Civic",
|
||||
"year": 2021,
|
||||
"engine": "2.0L 4-Cylinder",
|
||||
"transmission": "CVT Automatic",
|
||||
"trimLevel": "EX",
|
||||
"driveType": "FWD",
|
||||
"fuelType": "Gasoline",
|
||||
"nickname": "My Honda",
|
||||
"color": "Blue",
|
||||
"licensePlate": "ABC123",
|
||||
"odometerReading": 15000,
|
||||
"isActive": true,
|
||||
"createdAt": "2025-01-01T00:00:00.000Z",
|
||||
"updatedAt": "2025-01-01T00:00:00.000Z",
|
||||
"imageUrl": "/api/vehicles/{id}/image"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Clear platform cache:
|
||||
- `docker compose exec -T mvp-redis sh -lc "redis-cli FLUSHALL"`
|
||||
- Or restart containers: `make rebuild`
|
||||
### Get Single Vehicle
|
||||
|
||||
## MotoVaultPro Backend (Application Service)
|
||||
```
|
||||
GET /api/vehicles/:id
|
||||
```
|
||||
|
||||
### Proxy Dropdown Endpoints
|
||||
Vehicles service simply re-emits the data returned by `Platform VehicleDataService`, normalizing it to `{ id, name }[]` arrays for frontend consumption. Redis caching and Postgres lookups all remain centralized in the platform module.
|
||||
**Parameters**:
|
||||
- `id` (path): Vehicle UUID
|
||||
|
||||
### Platform Integration
|
||||
- `VehiclesService` lazily instantiates `VehicleDataService` via `getVehicleDataService()`, guaranteeing a shared cache.
|
||||
- Each dropdown call passes the shared Postgres pool (`getPool()`) and propagates selection context (year/make/model/trim).
|
||||
- Transmission dropdown is intentionally static (`Automatic`, `Manual`) until richer metadata is available.
|
||||
**Response** (200): Single vehicle object (same structure as list item)
|
||||
|
||||
### Authentication (App)
|
||||
- Auth0 JWT enforced via Fastify + JWKS. No mock users.
|
||||
**Errors**:
|
||||
- `404`: Vehicle not found or not owned by user
|
||||
|
||||
### Migrations (Production‑Quality)
|
||||
- Migrations packaged in image under `/app/migrations/features/[feature]/migrations`.
|
||||
- Runner (`backend/src/_system/migrations/run-all.ts`):
|
||||
- Reads base dir from `MIGRATIONS_DIR` (env in Dockerfile)
|
||||
- Tracks executed files in `_migrations` table and skips already executed files
|
||||
- **Idempotent at file level**: Safe to re-run migration system multiple times
|
||||
- Wait/retry for DB readiness to avoid flapping on cold starts
|
||||
- Auto‑migrate on backend container start: `node dist/_system/migrations/run-all.js && npm start`
|
||||
- Manual: `make migrate` (runs runner inside the container)
|
||||
### Create Vehicle
|
||||
|
||||
## Frontend Changes
|
||||
- Vehicles form cascades: year → make → model → trim → engine.
|
||||
- Engines load only after a trim is selected (requires `trim_id`).
|
||||
- Validation updated: user must provide either a 17‑char VIN or a non‑empty license plate.
|
||||
- VIN Decode button still requires a valid 17‑char VIN.
|
||||
- APIs used:
|
||||
- `/api/vehicles/dropdown/years`
|
||||
- `/api/vehicles/dropdown/makes|models|trims|engines`
|
||||
- `/api/vehicles/dropdown/transmissions`
|
||||
```
|
||||
POST /api/vehicles
|
||||
```
|
||||
|
||||
## Add Vehicle Form – Change/Add/Modify/Delete Fields (Fast Track)
|
||||
**Request Body**:
|
||||
```json
|
||||
{
|
||||
"vin": "1HGBH41JXMN109186",
|
||||
"year": 2021,
|
||||
"make": "Honda",
|
||||
"model": "Civic",
|
||||
"engine": "2.0L 4-Cylinder",
|
||||
"transmission": "CVT Automatic",
|
||||
"trimLevel": "EX",
|
||||
"driveType": "FWD",
|
||||
"fuelType": "Gasoline",
|
||||
"nickname": "My Honda",
|
||||
"color": "Blue",
|
||||
"licensePlate": "ABC123",
|
||||
"odometerReading": 15000
|
||||
}
|
||||
```
|
||||
|
||||
Where to edit
|
||||
- UI + validation: `frontend/src/features/vehicles/components/VehicleForm.tsx`
|
||||
- Frontend types: `frontend/src/features/vehicles/types/vehicles.types.ts`
|
||||
- Backend controller/service/repo: `backend/src/features/vehicles/api/vehicles.controller.ts`, `domain/vehicles.service.ts`, `data/vehicles.repository.ts`, types in `domain/vehicles.types.ts`
|
||||
- App DB migrations: `backend/src/features/vehicles/migrations/*.sql` (auto‑migrated on backend start)
|
||||
**Required**: Either `vin` OR `licensePlate` must be provided (not both required).
|
||||
|
||||
Add a new field (example: bodyStyle)
|
||||
1) DB: `ALTER TABLE vehicles ADD COLUMN IF NOT EXISTS body_style VARCHAR(100);` in a new migration file.
|
||||
2) Backend: add `bodyStyle?: string;` to types; include in repository insert/update mapping as `body_style`.
|
||||
3) Frontend: add `bodyStyle` to Zod schema and a new input bound via `register('bodyStyle')`.
|
||||
4) Rebuild frontend/backend and verify in Network + logs.
|
||||
**Response** (201): Created vehicle object
|
||||
|
||||
Modify an existing field
|
||||
- Update labels/placeholders in VehicleForm.
|
||||
- Update Zod schema for new validation rules; mirror on the server if desired.
|
||||
- Adjust service logic only if business behavior changes.
|
||||
### Update Vehicle
|
||||
|
||||
Delete a field (safe path)
|
||||
- Remove from VehicleForm and frontend types.
|
||||
- Remove from backend types/repository mapping.
|
||||
- Optional migration to drop the column later.
|
||||
```
|
||||
PUT /api/vehicles/:id
|
||||
```
|
||||
|
||||
Dropdown ordering
|
||||
- Implemented in VehicleForm; current order is Year → Make → Model → Trim → Engine → Transmission (static).
|
||||
- Engine select is enabled only after a Trim is selected.
|
||||
**Parameters**:
|
||||
- `id` (path): Vehicle UUID
|
||||
|
||||
VIN/License rule
|
||||
- Frontend Zod: either 17‑char VIN or non‑empty license plate; if no plate, VIN must be 17.
|
||||
- Backend controller enforces the same rule; service decodes/validates only when VIN is present.
|
||||
- Repository normalizes empty VIN to NULL to avoid unique collisions.
|
||||
**Request Body**: Same fields as create (all optional, only provided fields are updated)
|
||||
|
||||
## Operations
|
||||
**Response** (200): Updated vehicle object
|
||||
|
||||
### Rebuild a single service
|
||||
- Frontend: `docker compose up -d --build frontend`
|
||||
- Backend (includes platform module): `docker compose up -d --build backend`
|
||||
### Delete Vehicle
|
||||
|
||||
### Logs & Health
|
||||
- Backend: `https://motovaultpro.com/api/health` – shows status/feature list, including platform readiness
|
||||
- Logs: `make logs-backend`, `make logs-frontend`
|
||||
Soft-deletes a vehicle (sets `deleted_at` timestamp).
|
||||
|
||||
### Common Reset Sequences
|
||||
- Platform seed reapply (non‑destructive): apply `005_seed_specific_vehicles.sql` and flush Redis cache.
|
||||
- Platform reset (WARNING - DESTRUCTIVE to shared resources):
|
||||
- `docker compose rm -sf mvp-postgres mvp-redis`
|
||||
- `docker volume rm motovaultpro_postgres_data motovaultpro_redis_data`
|
||||
- `docker compose up -d mvp-postgres mvp-redis mvp-backend`
|
||||
- Note: This will destroy ALL application data, not just platform data, as database and cache are shared
|
||||
```
|
||||
DELETE /api/vehicles/:id
|
||||
```
|
||||
|
||||
## Security Summary
|
||||
- Platform Module: Auth0 JWT via `Authorization: Bearer ${JWT_TOKEN}` required on all `/api/platform/*` endpoints.
|
||||
- Vehicles Feature: Auth0 JWT required on all protected `/api/vehicles/*` routes.
|
||||
- Health Check: `/api/health` is unauthenticated (Traefik readiness probe).
|
||||
**Parameters**:
|
||||
- `id` (path): Vehicle UUID
|
||||
|
||||
## CI Summary
|
||||
- Workflow `.github/workflows/ci.yml` builds backend/frontend/platform API.
|
||||
- Runs backend lint/tests in a builder image on a stable network.
|
||||
**Response** (204): No content
|
||||
|
||||
## Troubleshooting
|
||||
- Frontend shows generic “Server error” right after login:
|
||||
- Check backend `/api/vehicles` 500s (migrations not run or DB unavailable).
|
||||
- Run `make migrate` or ensure backend container auto‑migrate is succeeding; check `docker compose logs backend`.
|
||||
- Dropdowns not updating after seed:
|
||||
- Run specific seed SQL (see above) and `redis-cli FLUSHALL` on shared Redis (mvp-redis).
|
||||
- Backend flapping on start after rebuild:
|
||||
- Ensure Postgres is up; the runner now waits/retries, but confirm logs.
|
||||
## Vehicle Images
|
||||
|
||||
## Notable Files
|
||||
- Platform schema & seeds: maintained by database admins (legacy FastAPI scripts available on request)
|
||||
- Platform API integration: `backend/src/features/platform/api/*`
|
||||
- Backend dropdown proxy: `backend/src/features/vehicles/api/*`
|
||||
- Backend platform module: `backend/src/features/platform/*`
|
||||
- Backend migrations runner: `backend/src/_system/migrations/run-all.ts`
|
||||
- Frontend vehicles UI: `frontend/src/features/vehicles/*`
|
||||
### Upload Image
|
||||
|
||||
Upload or replace the vehicle's image.
|
||||
|
||||
```
|
||||
POST /api/vehicles/:id/image
|
||||
Content-Type: multipart/form-data
|
||||
```
|
||||
|
||||
**Parameters**:
|
||||
- `id` (path): Vehicle UUID
|
||||
|
||||
**Form Data**:
|
||||
- `image`: Image file (JPEG, PNG, WebP; max 5MB)
|
||||
|
||||
**Response** (200):
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"imageUrl": "/api/vehicles/{id}/image"
|
||||
}
|
||||
```
|
||||
|
||||
### Download Image
|
||||
|
||||
```
|
||||
GET /api/vehicles/:id/image
|
||||
```
|
||||
|
||||
**Parameters**:
|
||||
- `id` (path): Vehicle UUID
|
||||
|
||||
**Response**: Image binary with appropriate `Content-Type` header
|
||||
|
||||
**Errors**:
|
||||
- `404`: No image exists for vehicle
|
||||
|
||||
### Delete Image
|
||||
|
||||
```
|
||||
DELETE /api/vehicles/:id/image
|
||||
```
|
||||
|
||||
**Parameters**:
|
||||
- `id` (path): Vehicle UUID
|
||||
|
||||
**Response** (204): No content
|
||||
|
||||
## Dropdown Cascade API
|
||||
|
||||
Hierarchical endpoints for vehicle selection dropdowns. Each level filters based on previous selections.
|
||||
|
||||
### Get Years
|
||||
|
||||
Returns available model years in descending order.
|
||||
|
||||
```
|
||||
GET /api/vehicles/dropdown/years
|
||||
```
|
||||
|
||||
**Response** (200):
|
||||
```json
|
||||
{
|
||||
"years": [2025, 2024, 2023, 2022, ...]
|
||||
}
|
||||
```
|
||||
|
||||
### Get Makes
|
||||
|
||||
Returns makes available for a specific year.
|
||||
|
||||
```
|
||||
GET /api/vehicles/dropdown/makes?year={year}
|
||||
```
|
||||
|
||||
**Query Parameters**:
|
||||
- `year` (required): Model year (e.g., 2024)
|
||||
|
||||
**Response** (200):
|
||||
```json
|
||||
{
|
||||
"makes": ["Acura", "Audi", "BMW", "Chevrolet", "Ford", ...]
|
||||
}
|
||||
```
|
||||
|
||||
### Get Models
|
||||
|
||||
Returns models available for a specific year and make.
|
||||
|
||||
```
|
||||
GET /api/vehicles/dropdown/models?year={year}&make={make}
|
||||
```
|
||||
|
||||
**Query Parameters**:
|
||||
- `year` (required): Model year
|
||||
- `make` (required): Make name (e.g., "Ford")
|
||||
|
||||
**Response** (200):
|
||||
```json
|
||||
{
|
||||
"models": ["Bronco", "Edge", "Explorer", "F-150", "Mustang", ...]
|
||||
}
|
||||
```
|
||||
|
||||
### Get Trims
|
||||
|
||||
Returns trims available for a specific year, make, and model.
|
||||
|
||||
```
|
||||
GET /api/vehicles/dropdown/trims?year={year}&make={make}&model={model}
|
||||
```
|
||||
|
||||
**Query Parameters**:
|
||||
- `year` (required): Model year
|
||||
- `make` (required): Make name
|
||||
- `model` (required): Model name (e.g., "F-150")
|
||||
|
||||
**Response** (200):
|
||||
```json
|
||||
{
|
||||
"trims": ["XL", "XLT", "Lariat", "King Ranch", "Platinum", ...]
|
||||
}
|
||||
```
|
||||
|
||||
### Get Engines
|
||||
|
||||
Returns engines available for a specific year, make, model, and trim.
|
||||
|
||||
```
|
||||
GET /api/vehicles/dropdown/engines?year={year}&make={make}&model={model}&trim={trim}
|
||||
```
|
||||
|
||||
**Query Parameters**:
|
||||
- `year` (required): Model year
|
||||
- `make` (required): Make name
|
||||
- `model` (required): Model name
|
||||
- `trim` (required): Trim level (e.g., "XLT")
|
||||
|
||||
**Response** (200):
|
||||
```json
|
||||
{
|
||||
"engines": [
|
||||
"3.3L V6 Ti-VCT",
|
||||
"2.7L V6 EcoBoost",
|
||||
"5.0L V8 Ti-VCT",
|
||||
"3.5L V6 EcoBoost"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Get Transmissions
|
||||
|
||||
Returns transmissions available for a specific year, make, model, and trim.
|
||||
|
||||
```
|
||||
GET /api/vehicles/dropdown/transmissions?year={year}&make={make}&model={model}&trim={trim}
|
||||
```
|
||||
|
||||
**Query Parameters**:
|
||||
- `year` (required): Model year
|
||||
- `make` (required): Make name
|
||||
- `model` (required): Model name
|
||||
- `trim` (required): Trim level
|
||||
|
||||
**Response** (200):
|
||||
```json
|
||||
{
|
||||
"transmissions": [
|
||||
"10-Speed Automatic",
|
||||
"6-Speed Automatic"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Get Pair-Safe Options
|
||||
|
||||
Returns valid engine/transmission combinations, ensuring only compatible pairs are shown.
|
||||
|
||||
```
|
||||
GET /api/vehicles/dropdown/options?year={year}&make={make}&model={model}&trim={trim}[&engine={engine}][&transmission={transmission}]
|
||||
```
|
||||
|
||||
**Query Parameters**:
|
||||
- `year` (required): Model year
|
||||
- `make` (required): Make name
|
||||
- `model` (required): Model name
|
||||
- `trim` (required): Trim level
|
||||
- `engine` (optional): If provided, returns only transmissions compatible with this engine
|
||||
- `transmission` (optional): If provided, returns only engines compatible with this transmission
|
||||
|
||||
**Response** (200):
|
||||
```json
|
||||
{
|
||||
"engines": ["3.3L V6 Ti-VCT", "2.7L V6 EcoBoost"],
|
||||
"transmissions": ["10-Speed Automatic"]
|
||||
}
|
||||
```
|
||||
|
||||
## Platform API
|
||||
|
||||
Direct platform endpoints for vehicle data lookups (alternative to dropdown cascade).
|
||||
|
||||
```
|
||||
GET /api/platform/years
|
||||
GET /api/platform/makes?year={year}
|
||||
GET /api/platform/models?year={year}&make={make}
|
||||
GET /api/platform/trims?year={year}&make={make}&model={model}
|
||||
GET /api/platform/engines?year={year}&make={make}&model={model}&trim={trim}
|
||||
GET /api/platform/transmissions?year={year}&make={make}&model={model}&trim={trim}
|
||||
```
|
||||
|
||||
Same functionality as dropdown cascade API but with `/api/platform/` prefix.
|
||||
|
||||
## Error Responses
|
||||
|
||||
All endpoints return standard error responses:
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "Error message",
|
||||
"statusCode": 400
|
||||
}
|
||||
```
|
||||
|
||||
**Common Status Codes**:
|
||||
- `400`: Bad request (validation error)
|
||||
- `401`: Unauthorized (missing or invalid JWT)
|
||||
- `404`: Resource not found
|
||||
- `500`: Internal server error
|
||||
|
||||
## Data Model
|
||||
|
||||
### Vehicle Fields
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| id | UUID | Auto | Primary key |
|
||||
| userId | string | Auto | Auth0 user ID (from JWT) |
|
||||
| vin | string | No* | Vehicle Identification Number (17 chars) |
|
||||
| make | string | No | Manufacturer (e.g., "Ford") |
|
||||
| model | string | No | Model name (e.g., "F-150") |
|
||||
| year | integer | No | Model year |
|
||||
| engine | string | No | Engine specification |
|
||||
| transmission | string | No | Transmission type |
|
||||
| trimLevel | string | No | Trim level (e.g., "XLT") |
|
||||
| driveType | string | No | Drive type (e.g., "4WD", "FWD") |
|
||||
| fuelType | string | No | Fuel type (e.g., "Gasoline", "Diesel") |
|
||||
| nickname | string | No | User-defined name |
|
||||
| color | string | No | Vehicle color |
|
||||
| licensePlate | string | No* | License plate number |
|
||||
| odometerReading | integer | No | Current odometer (default: 0) |
|
||||
| isActive | boolean | Auto | Active status (default: true) |
|
||||
| createdAt | datetime | Auto | Creation timestamp |
|
||||
| updatedAt | datetime | Auto | Last update timestamp |
|
||||
| imageUrl | string | Auto | URL to vehicle image (if uploaded) |
|
||||
|
||||
*Either `vin` OR `licensePlate` should be provided for vehicle identification.
|
||||
|
||||
### VIN Validation
|
||||
|
||||
When a VIN is provided:
|
||||
- Must be exactly 17 characters
|
||||
- Cannot contain letters I, O, or Q
|
||||
- Check digit validation is performed
|
||||
|
||||
## Database Schema
|
||||
|
||||
### Platform Tables
|
||||
|
||||
Vehicle lookup data is stored in three denormalized tables optimized for dropdown cascade queries:
|
||||
|
||||
- **engines**: Engine specifications (name, displacement, horsepower, fuel_type, etc.)
|
||||
- **transmissions**: Transmission types (type, speeds, drive_type)
|
||||
- **vehicle_options**: Denormalized year/make/model/trim combinations with engine/transmission references
|
||||
|
||||
See `docs/DATABASE-SCHEMA.md` for complete table definitions.
|
||||
|
||||
### Migration Location
|
||||
|
||||
Platform migrations: `backend/src/features/platform/migrations/001_create_vehicle_lookup_schema.sql`
|
||||
|
||||
## Caching
|
||||
|
||||
- **Dropdown data**: Cached in Redis for 6 hours (key: `dropdown:{dataType}:{params}`)
|
||||
- **User vehicle lists**: Cached for 5 minutes (key: `vehicles:user:{userId}`)
|
||||
- Cache is invalidated on vehicle create/update/delete operations
|
||||
|
||||
## Frontend Integration
|
||||
|
||||
### Form Cascade Order
|
||||
|
||||
The vehicle form uses cascading dropdowns in this order:
|
||||
1. Year (loads makes)
|
||||
2. Make (loads models)
|
||||
3. Model (loads trims)
|
||||
4. Trim (loads engines and transmissions)
|
||||
5. Engine and Transmission (pair-safe filtering via `/dropdown/options`)
|
||||
|
||||
### Files
|
||||
|
||||
- Form component: `frontend/src/features/vehicles/components/VehicleForm.tsx`
|
||||
- Types: `frontend/src/features/vehicles/types/vehicles.types.ts`
|
||||
- API hooks: `frontend/src/features/vehicles/hooks/`
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- Feature README: `backend/src/features/vehicles/README.md`
|
||||
- Platform README: `backend/src/features/platform/README.md`
|
||||
- Database Schema: `docs/DATABASE-SCHEMA.md`
|
||||
- Architecture: `docs/ARCHITECTURE-OVERVIEW.md`
|
||||
|
||||
Reference in New Issue
Block a user