From 8ef6b3d85381cdce0d90016dca2470950fef8a5a Mon Sep 17 00:00:00 2001 From: Eric Gullickson <16152721+ericgullickson@users.noreply.github.com> Date: Wed, 24 Dec 2025 17:20:11 -0600 Subject: [PATCH] fix: before admin stations removal --- backend/src/app.ts | 6 +- .../src/features/admin/api/admin.routes.ts | 2 +- .../admin/domain/catalog-import.service.ts | 94 +--- .../api/user-preferences.controller.ts | 113 ++++ .../api/user-preferences.routes.ts | 28 + .../src/features/user-preferences/index.ts | 6 + data/vehicle-etl/ACURA.txt | 74 +++ data/vehicle-etl/BMW.txt | 64 +++ data/vehicle-etl/GMC.txt | 68 +++ data/vehicle-etl/HONDA.txt | 79 +++ data/vehicle-etl/README.md | 3 +- .../vehicle-etl/logical-plotting-hartmanis.md | 514 ++++++++++++++++++ docs/PROMPTS.md | 38 +- frontend/src/core/units/UnitsContext.tsx | 146 +++-- frontend/src/core/units/units.types.ts | 2 +- frontend/src/core/units/units.utils.ts | 35 +- .../src/features/admin/hooks/useCatalog.ts | 2 +- .../admin/mobile/AdminCatalogMobileScreen.tsx | 3 - .../src/features/admin/types/admin.types.ts | 3 - .../fuel-logs/components/CostCalculator.tsx | 10 +- .../fuel-logs/components/DistanceInput.tsx | 4 +- .../fuel-logs/components/FuelLogForm.tsx | 6 +- .../fuel-logs/components/FuelLogsList.tsx | 10 +- .../fuel-logs/components/FuelStatsCard.tsx | 4 +- .../components/UnitSystemDisplay.tsx | 2 +- .../features/settings/api/preferences.api.ts | 13 + .../features/settings/hooks/usePreferences.ts | 61 +++ .../features/settings/hooks/useSettings.ts | 15 + .../settings/mobile/MobileSettingsScreen.tsx | 2 +- .../settings/types/preferences.types.ts | 22 + frontend/src/pages/SettingsPage.tsx | 2 +- frontend/src/pages/admin/AdminCatalogPage.tsx | 3 - 32 files changed, 1258 insertions(+), 176 deletions(-) create mode 100644 backend/src/features/user-preferences/api/user-preferences.controller.ts create mode 100644 backend/src/features/user-preferences/api/user-preferences.routes.ts create mode 100644 backend/src/features/user-preferences/index.ts create mode 100644 data/vehicle-etl/ACURA.txt create mode 100644 data/vehicle-etl/BMW.txt create mode 100644 data/vehicle-etl/GMC.txt create mode 100644 data/vehicle-etl/HONDA.txt create mode 100644 data/vehicle-etl/logical-plotting-hartmanis.md create mode 100644 frontend/src/features/settings/api/preferences.api.ts create mode 100644 frontend/src/features/settings/hooks/usePreferences.ts create mode 100644 frontend/src/features/settings/types/preferences.types.ts diff --git a/backend/src/app.ts b/backend/src/app.ts index 65eaec6..007220f 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -27,6 +27,7 @@ import { adminRoutes } from './features/admin/api/admin.routes'; import { notificationsRoutes } from './features/notifications'; import { userProfileRoutes } from './features/user-profile'; import { onboardingRoutes } from './features/onboarding'; +import { userPreferencesRoutes } from './features/user-preferences'; import { pool } from './core/config/database'; async function buildApp(): Promise { @@ -84,7 +85,7 @@ async function buildApp(): Promise { status: 'healthy', timestamp: new Date().toISOString(), environment: process.env['NODE_ENV'], - features: ['admin', 'auth', 'onboarding', 'vehicles', 'documents', 'fuel-logs', 'stations', 'maintenance', 'platform', 'notifications', 'user-profile'] + features: ['admin', 'auth', 'onboarding', 'vehicles', 'documents', 'fuel-logs', 'stations', 'maintenance', 'platform', 'notifications', 'user-profile', 'user-preferences'] }); }); @@ -94,7 +95,7 @@ async function buildApp(): Promise { status: 'healthy', scope: 'api', timestamp: new Date().toISOString(), - features: ['admin', 'auth', 'onboarding', 'vehicles', 'documents', 'fuel-logs', 'stations', 'maintenance', 'platform', 'notifications', 'user-profile'] + features: ['admin', 'auth', 'onboarding', 'vehicles', 'documents', 'fuel-logs', 'stations', 'maintenance', 'platform', 'notifications', 'user-profile', 'user-preferences'] }); }); @@ -132,6 +133,7 @@ async function buildApp(): Promise { await app.register(adminRoutes, { prefix: '/api' }); await app.register(notificationsRoutes, { prefix: '/api' }); await app.register(userProfileRoutes, { prefix: '/api' }); + await app.register(userPreferencesRoutes, { prefix: '/api' }); // 404 handler app.setNotFoundHandler(async (_request, reply) => { diff --git a/backend/src/features/admin/api/admin.routes.ts b/backend/src/features/admin/api/admin.routes.ts index 04e3b4f..660785d 100644 --- a/backend/src/features/admin/api/admin.routes.ts +++ b/backend/src/features/admin/api/admin.routes.ts @@ -50,7 +50,7 @@ export const adminRoutes: FastifyPluginAsync = async (fastify) => { // Initialize catalog dependencies const platformCacheService = new PlatformCacheService(cacheService); const catalogService = new VehicleCatalogService(pool, platformCacheService); - const catalogImportService = new CatalogImportService(pool); + const catalogImportService = new CatalogImportService(pool, platformCacheService); const catalogController = new CatalogController(catalogService); catalogController.setImportService(catalogImportService); diff --git a/backend/src/features/admin/domain/catalog-import.service.ts b/backend/src/features/admin/domain/catalog-import.service.ts index 3d30576..35880ad 100644 --- a/backend/src/features/admin/domain/catalog-import.service.ts +++ b/backend/src/features/admin/domain/catalog-import.service.ts @@ -5,9 +5,9 @@ import { Pool } from 'pg'; import { logger } from '../../../core/logging/logger'; +import { PlatformCacheService } from '../../platform/domain/platform-cache.service'; export interface ImportRow { - action: 'add' | 'update' | 'delete'; year: number; make: string; model: string; @@ -25,7 +25,6 @@ export interface ImportPreviewResult { previewId: string; toCreate: ImportRow[]; toUpdate: ImportRow[]; - toDelete: ImportRow[]; errors: ImportError[]; valid: boolean; } @@ -33,7 +32,6 @@ export interface ImportPreviewResult { export interface ImportApplyResult { created: number; updated: number; - deleted: number; errors: ImportError[]; } @@ -50,7 +48,10 @@ export interface ExportRow { const previewCache = new Map(); export class CatalogImportService { - constructor(private pool: Pool) {} + constructor( + private pool: Pool, + private platformCacheService?: PlatformCacheService + ) {} /** * Parse CSV content and validate without applying changes @@ -59,7 +60,6 @@ export class CatalogImportService { const previewId = uuidv4(); const toCreate: ImportRow[] = []; const toUpdate: ImportRow[] = []; - const toDelete: ImportRow[] = []; const errors: ImportError[] = []; const lines = csvContent.trim().split('\n'); @@ -68,7 +68,6 @@ export class CatalogImportService { previewId, toCreate, toUpdate, - toDelete, errors: [{ row: 0, error: 'CSV must have a header row and at least one data row' }], valid: false, }; @@ -78,15 +77,14 @@ export class CatalogImportService { const header = this.parseCSVLine(lines[0]); const headerLower = header.map(h => h.toLowerCase().trim()); - // Validate required headers - const requiredHeaders = ['action', 'year', 'make', 'model', 'trim']; + // Validate required headers (no action column required - matches export format) + const requiredHeaders = ['year', 'make', 'model', 'trim']; for (const required of requiredHeaders) { if (!headerLower.includes(required)) { return { previewId, toCreate, toUpdate, - toDelete, errors: [{ row: 1, error: `Missing required header: ${required}` }], valid: false, }; @@ -95,7 +93,6 @@ export class CatalogImportService { // Find column indices const colIndices = { - action: headerLower.indexOf('action'), year: headerLower.indexOf('year'), make: headerLower.indexOf('make'), model: headerLower.indexOf('model'), @@ -113,7 +110,6 @@ export class CatalogImportService { const rowNum = i + 1; try { - const action = values[colIndices.action]?.toLowerCase().trim(); const year = parseInt(values[colIndices.year], 10); const make = values[colIndices.make]?.trim(); const model = values[colIndices.model]?.trim(); @@ -121,12 +117,6 @@ export class CatalogImportService { const engineName = colIndices.engineName >= 0 ? values[colIndices.engineName]?.trim() || null : null; const transmissionType = colIndices.transmissionType >= 0 ? values[colIndices.transmissionType]?.trim() || null : null; - // Validate action - if (!['add', 'update', 'delete'].includes(action)) { - errors.push({ row: rowNum, error: `Invalid action: ${action}. Must be add, update, or delete` }); - continue; - } - // Validate year if (isNaN(year) || year < 1900 || year > 2100) { errors.push({ row: rowNum, error: `Invalid year: ${values[colIndices.year]}` }); @@ -148,7 +138,6 @@ export class CatalogImportService { } const row: ImportRow = { - action: action as 'add' | 'update' | 'delete', year, make, model, @@ -157,7 +146,7 @@ export class CatalogImportService { transmissionType, }; - // Check if record exists for validation + // Check if record exists to determine create vs update (upsert logic) const existsResult = await this.pool.query( `SELECT id FROM vehicle_options WHERE year = $1 AND make = $2 AND model = $3 AND trim = $4 @@ -166,26 +155,11 @@ export class CatalogImportService { ); const exists = (existsResult.rowCount || 0) > 0; - if (action === 'add' && exists) { - errors.push({ row: rowNum, error: `Record already exists: ${year} ${make} ${model} ${trim}` }); - continue; - } - if ((action === 'update' || action === 'delete') && !exists) { - errors.push({ row: rowNum, error: `Record not found: ${year} ${make} ${model} ${trim}` }); - continue; - } - - // Sort into appropriate bucket - switch (action) { - case 'add': - toCreate.push(row); - break; - case 'update': - toUpdate.push(row); - break; - case 'delete': - toDelete.push(row); - break; + // Auto-detect: if exists -> update, else -> create + if (exists) { + toUpdate.push(row); + } else { + toCreate.push(row); } } catch (error: any) { errors.push({ row: rowNum, error: error.message || 'Parse error' }); @@ -196,7 +170,6 @@ export class CatalogImportService { previewId, toCreate, toUpdate, - toDelete, errors, valid: errors.length === 0, }; @@ -230,7 +203,6 @@ export class CatalogImportService { const result: ImportApplyResult = { created: 0, updated: 0, - deleted: 0, errors: [], }; @@ -247,7 +219,7 @@ export class CatalogImportService { const engineResult = await client.query( `INSERT INTO engines (name, fuel_type) VALUES ($1, 'Gas') - ON CONFLICT (LOWER(name)) DO UPDATE SET name = EXCLUDED.name + ON CONFLICT ((lower(name))) DO UPDATE SET name = EXCLUDED.name RETURNING id`, [row.engineName] ); @@ -260,7 +232,7 @@ export class CatalogImportService { const transResult = await client.query( `INSERT INTO transmissions (type) VALUES ($1) - ON CONFLICT (LOWER(type)) DO UPDATE SET type = EXCLUDED.type + ON CONFLICT ((lower(type))) DO UPDATE SET type = EXCLUDED.type RETURNING id`, [row.transmissionType] ); @@ -289,7 +261,7 @@ export class CatalogImportService { const engineResult = await client.query( `INSERT INTO engines (name, fuel_type) VALUES ($1, 'Gas') - ON CONFLICT (LOWER(name)) DO UPDATE SET name = EXCLUDED.name + ON CONFLICT ((lower(name))) DO UPDATE SET name = EXCLUDED.name RETURNING id`, [row.engineName] ); @@ -302,7 +274,7 @@ export class CatalogImportService { const transResult = await client.query( `INSERT INTO transmissions (type) VALUES ($1) - ON CONFLICT (LOWER(type)) DO UPDATE SET type = EXCLUDED.type + ON CONFLICT ((lower(type))) DO UPDATE SET type = EXCLUDED.type RETURNING id`, [row.transmissionType] ); @@ -323,41 +295,21 @@ export class CatalogImportService { } } - // Process deletes - for (const row of preview.toDelete) { - try { - await client.query( - `DELETE FROM vehicle_options - WHERE year = $1 AND make = $2 AND model = $3 AND trim = $4`, - [row.year, row.make, row.model, row.trim] - ); - result.deleted++; - } catch (error: any) { - result.errors.push({ row: 0, error: `Failed to delete ${row.year} ${row.make} ${row.model} ${row.trim}: ${error.message}` }); - } - } - await client.query('COMMIT'); - // Log the import action - await this.pool.query( - `INSERT INTO platform_change_log (change_type, resource_type, resource_id, old_value, new_value, changed_by) - VALUES ('CREATE', 'import', $1, NULL, $2, $3)`, - [ - previewId, - JSON.stringify({ created: result.created, updated: result.updated, deleted: result.deleted }), - changedBy, - ] - ); - // Remove preview from cache previewCache.delete(previewId); + // Invalidate vehicle data cache so dropdowns reflect new data + if (this.platformCacheService) { + await this.platformCacheService.invalidateVehicleData(); + logger.debug('Vehicle data cache invalidated after import'); + } + logger.info('Catalog import completed', { previewId, created: result.created, updated: result.updated, - deleted: result.deleted, errors: result.errors.length, changedBy, }); diff --git a/backend/src/features/user-preferences/api/user-preferences.controller.ts b/backend/src/features/user-preferences/api/user-preferences.controller.ts new file mode 100644 index 0000000..870370f --- /dev/null +++ b/backend/src/features/user-preferences/api/user-preferences.controller.ts @@ -0,0 +1,113 @@ +/** + * @ai-summary Fastify route handlers for user preferences API + * @ai-context HTTP request/response handling for unit system and currency preferences + */ + +import { FastifyRequest, FastifyReply } from 'fastify'; +import { UserPreferencesRepository } from '../../../core/user-preferences/data/user-preferences.repository'; +import { UpdateUserPreferencesRequest } from '../../../core/user-preferences/user-preferences.types'; +import { pool } from '../../../core/config/database'; +import { logger } from '../../../core/logging/logger'; + +export class UserPreferencesController { + private repository: UserPreferencesRepository; + + constructor() { + this.repository = new UserPreferencesRepository(pool); + } + + async getPreferences(request: FastifyRequest, reply: FastifyReply) { + try { + const userId = (request as any).user.sub; + let preferences = await this.repository.findByUserId(userId); + + // Create default preferences if none exist + if (!preferences) { + preferences = await this.repository.create({ + userId, + unitSystem: 'imperial', + currencyCode: 'USD', + timeZone: 'UTC', + }); + } + + return reply.code(200).send({ + id: preferences.id, + userId: preferences.userId, + unitSystem: preferences.unitSystem, + currencyCode: preferences.currencyCode, + timeZone: preferences.timeZone, + createdAt: preferences.createdAt, + updatedAt: preferences.updatedAt, + }); + } catch (error) { + logger.error('Error getting user preferences', { error, userId: (request as any).user?.sub }); + return reply.code(500).send({ + error: 'Internal server error', + message: 'Failed to get preferences', + }); + } + } + + async updatePreferences( + request: FastifyRequest<{ Body: UpdateUserPreferencesRequest }>, + reply: FastifyReply + ) { + try { + const userId = (request as any).user.sub; + const { unitSystem, currencyCode, timeZone } = request.body; + + // Validate unitSystem if provided + if (unitSystem && !['imperial', 'metric'].includes(unitSystem)) { + return reply.code(400).send({ + error: 'Bad Request', + message: 'unitSystem must be either "imperial" or "metric"', + }); + } + + // Validate currencyCode if provided (basic 3-letter check) + if (currencyCode && !/^[A-Z]{3}$/.test(currencyCode)) { + return reply.code(400).send({ + error: 'Bad Request', + message: 'currencyCode must be a 3-letter ISO currency code', + }); + } + + // Check if preferences exist, create if not + let preferences = await this.repository.findByUserId(userId); + if (!preferences) { + preferences = await this.repository.create({ + userId, + unitSystem: unitSystem || 'imperial', + currencyCode: currencyCode || 'USD', + timeZone: timeZone || 'UTC', + }); + } else { + const updated = await this.repository.update(userId, { + unitSystem, + currencyCode, + timeZone, + }); + if (updated) { + preferences = updated; + } + } + + return reply.code(200).send({ + id: preferences.id, + userId: preferences.userId, + unitSystem: preferences.unitSystem, + currencyCode: preferences.currencyCode, + timeZone: preferences.timeZone, + createdAt: preferences.createdAt, + updatedAt: preferences.updatedAt, + }); + } catch (error) { + logger.error('Error updating user preferences', { error, userId: (request as any).user?.sub }); + return reply.code(500).send({ + error: 'Internal server error', + message: 'Failed to update preferences', + }); + } + } +} diff --git a/backend/src/features/user-preferences/api/user-preferences.routes.ts b/backend/src/features/user-preferences/api/user-preferences.routes.ts new file mode 100644 index 0000000..82dee8a --- /dev/null +++ b/backend/src/features/user-preferences/api/user-preferences.routes.ts @@ -0,0 +1,28 @@ +/** + * @ai-summary Fastify routes for user preferences API + * @ai-context Route definitions for unit system, currency, and timezone preferences + */ + +import { FastifyInstance, FastifyPluginOptions } from 'fastify'; +import { FastifyPluginAsync } from 'fastify'; +import { UserPreferencesController } from './user-preferences.controller'; +import { UpdateUserPreferencesRequest } from '../../../core/user-preferences/user-preferences.types'; + +export const userPreferencesRoutes: FastifyPluginAsync = async ( + fastify: FastifyInstance, + _opts: FastifyPluginOptions +) => { + const controller = new UserPreferencesController(); + + // GET /api/user/preferences - Get user preferences (creates defaults if none) + fastify.get('/user/preferences', { + preHandler: [fastify.authenticate], + handler: controller.getPreferences.bind(controller), + }); + + // PUT /api/user/preferences - Update user preferences + fastify.put<{ Body: UpdateUserPreferencesRequest }>('/user/preferences', { + preHandler: [fastify.authenticate], + handler: controller.updatePreferences.bind(controller), + }); +}; diff --git a/backend/src/features/user-preferences/index.ts b/backend/src/features/user-preferences/index.ts new file mode 100644 index 0000000..5d94fab --- /dev/null +++ b/backend/src/features/user-preferences/index.ts @@ -0,0 +1,6 @@ +/** + * @ai-summary User preferences feature entry point + * @ai-context Exports routes for unit system, currency, and timezone preferences + */ + +export { userPreferencesRoutes } from './api/user-preferences.routes'; diff --git a/data/vehicle-etl/ACURA.txt b/data/vehicle-etl/ACURA.txt new file mode 100644 index 0000000..d3f10c2 --- /dev/null +++ b/data/vehicle-etl/ACURA.txt @@ -0,0 +1,74 @@ + groupname | variable | value | itempatternid | itemvinschemaid | itemkeys | itemelementid | itemattributeid | itemcreatedon | itemwmiid | code | datatype | decode | itemsource | itemtobeqced +-----------------------------------------------------+-----------------------------------------------+-----------------------------------------------------------------------------------------------------------------+---------------+-----------------+--------------+---------------+-----------------------------------------------------------------------------------------------------------------+-------------------------+-----------+-------------------------------------+----------+--------------+----------------------------------+-------------- + | Possible Values | | | | | 144 | | | | PossibleValues | string | Decoding | Corrections | + | Suggested VIN | | | | | 142 | | | | SuggestedVIN | string | Decoding | Corrections | + | Error Text | 0 - VIN decoded clean. Check Digit (9th position) is correct | | | | 191 | 0 - VIN decoded clean. Check Digit (9th position) is correct | | | ErrorText | string | Decoding | Corrections | + | Vehicle Descriptor | 5J8YE1H0*SL | | | | 196 | 5J8YE1H0*SL | | | VehicleDescriptor | string | Decoding | Corrections | + | Error Code | 0 | | | | 143 | 0 | | | ErrorCode | lookup | Decoding | Corrections | + | Additional Error Text | | | | | 156 | | | | AdditionalErrorText | string | Decoding | Corrections | + General | Vehicle Type | MULTIPURPOSE PASSENGER VEHICLE (MPV) | | | 5J8 | 39 | 7 | 2015-03-27 15:31:28.273 | 2105 | VehicleType | lookup | WMI | VehType | + General | Make | ACURA | 2074168 | 26929 | Y[ED]*H | 26 | 475 | | | Make | lookup | WMI, Pattern | pattern - model | + General | Manufacturer Name | AMERICAN HONDA MOTOR CO., INC. | | | 5J8 | 27 | 988 | | 2105 | Manufacturer | lookup | WMI | Manu. Name | + General | Model Year | 2025 | | | ***X*|Y | 29 | 2025 | | | ModelYear | int | WMI, Input | ModelYear | + General | Model | MDX | 2074168 | 26929 | Y[ED]*H | 28 | 2147 | 2024-05-21 10:17:20.287 | 2105 | Model | lookup | Pattern | Pattern | + General | Plant City | EAST LIBERTY | 2117059 | 27341 | *****|*L | 31 | EAST LIBERTY | 2024-08-27 07:36:52.53 | 2105 | PlantCity | string | Pattern | Pattern | + General | Plant State | OHIO | 2117056 | 27341 | *****|*[ALY] | 77 | OHIO | 2024-08-27 07:35:26.557 | 2105 | PlantState | string | Pattern | Pattern | + General | Plant Country | UNITED STATES (USA) | 2117055 | 27341 | *****|*[ALY] | 75 | 6 | 2024-08-27 07:35:26.54 | 2105 | PlantCountry | lookup | Pattern | Pattern | + General | Trim | SH-AWD A-Spec | 2074202 | 26929 | YE1H0 | 38 | SH-AWD A-Spec | 2024-05-21 10:24:09.057 | 2105 | Trim | string | Pattern | Pattern | + Exterior / Body | Body Class | Sport Utility Vehicle (SUV)/Multi-Purpose Vehicle (MPV) | 2074165 | 26929 | Y[ED]*H | 5 | 7 | 2024-05-21 10:17:20.143 | 2105 | BodyClass | lookup | Pattern | Pattern | + Exterior / Body | Doors | 5 | 2074166 | 26929 | Y[ED]*H | 14 | 5 | 2024-05-21 10:17:20.223 | 2105 | Doors | int | Pattern | Pattern | + Exterior / Dimension | Gross Vehicle Weight Rating From | Class 1D: 5,001 - 6,000 lb (2,268 - 2,722 kg) | 2074167 | 26929 | Y[ED]*H | 25 | 13 | 2024-05-21 10:17:20.27 | 2105 | GVWR | lookup | Pattern | Pattern | + Exterior / Dimension | Gross Vehicle Weight Rating To | Class 1D: 5,001 - 6,000 lb (2,268 - 2,722 kg) | 2074180 | 26929 | Y[ED]*H | 190 | 13 | 2024-05-21 10:17:20.63 | 2105 | GVWR_to | lookup | Pattern | Pattern | + Exterior / Trailer | Trailer Type Connection | Not Applicable | | | | 116 | 0 | 2019-12-21 20:26:30.583 | | TrailerType | lookup | Pattern | Default | + Exterior / Trailer | Trailer Body Type | Not Applicable | | | | 117 | 0 | 2019-12-21 20:26:30.583 | | TrailerBodyType | lookup | Pattern | Default | + Exterior / Motorcycle | Motorcycle Suspension Type | Not Applicable | | | | 152 | 0 | 2019-12-21 20:26:30.583 | | MotorcycleSuspensionType | lookup | Pattern | Default | + Exterior / Motorcycle | Motorcycle Chassis Type | Not Applicable | | | | 153 | 0 | 2019-12-21 20:26:30.583 | | MotorcycleChassisType | lookup | Pattern | Default | + Exterior / Motorcycle | Custom Motorcycle Type | Not Applicable | | | | 151 | 0 | 2019-12-21 20:26:30.583 | | CustomMotorcycleType | lookup | Pattern | Default | + Exterior / Bus | Bus Floor Configuration Type | Not Applicable | | | | 148 | 0 | 2019-12-21 20:26:30.583 | | BusFloorConfigType | lookup | Pattern | Default | + Exterior / Bus | Bus Type | Not Applicable | | | | 149 | 0 | 2019-12-21 20:26:30.583 | | BusType | lookup | Pattern | Default | + Mechanical / Transmission | Transmission Speeds | 10 | 2074171 | 26929 | Y[ED]*H | 63 | 10 | 2024-05-21 10:17:20.343 | 2105 | TransmissionSpeeds | int | Pattern | Pattern | + Mechanical / Transmission | Transmission Style | Automatic | 2074169 | 26929 | Y[ED]*H | 37 | 2 | 2024-05-21 10:17:20.303 | 2105 | TransmissionStyle | lookup | Pattern | Pattern | + Mechanical / Drivetrain | Drive Type | 4WD/4-Wheel Drive/4x4 | 2074181 | 26929 | YE1 | 15 | 2 | 2024-05-21 10:18:30.127 | 2105 | DriveType | lookup | Pattern | Pattern | + Engine | Other Engine Info | Direct Fuel Injection | 2074214 | 26929 | Y[ED][19] | 129 | Direct Fuel Injection | 2024-05-21 10:42:05.407 | 2105 | OtherEngineInfo | string | Pattern | Pattern | + Engine | Displacement (CC) | 3500.0 | 2074206 | 26929 | Y[ED][19] | 11 | 3500.0 | | 2105 | DisplacementCC | decimal | Pattern | Conversion 4: 3.5 * 1000 | + Engine | Displacement (CI) | 213.5831043315629938 | 2074206 | 26929 | Y[ED][19] | 12 | 213.5831043315629938 | | 2105 | DisplacementCI | decimal | Pattern | Conversion 7: 3.5 / 0.016387064 | + Engine | Engine Number of Cylinders | 6 | 2074205 | 26929 | Y[ED][19] | 9 | 6 | 2024-05-21 10:42:05.137 | 2105 | EngineCylinders | int | Pattern | Pattern | + Engine | Displacement (L) | 3.5 | 2074206 | 26929 | Y[ED][19] | 13 | 3.5 | 2024-05-21 10:42:05.157 | 2105 | DisplacementL | decimal | Pattern | Pattern | + Engine | Engine Stroke Cycles | 4 | 2074207 | 26929 | Y[ED][19] | 17 | 4 | 2024-05-21 10:42:05.287 | 2105 | EngineCycles | int | Pattern | Pattern | + Engine | Engine Model | J35Y5 | 2074208 | 26929 | Y[ED][19] | 18 | J35Y5 | 2024-05-21 10:42:05.303 | 2105 | EngineModel | string | Pattern | Pattern | + Engine | Fuel Type - Primary | Gasoline | 2074209 | 26929 | Y[ED][19] | 24 | 4 | 2024-05-21 10:42:05.32 | 2105 | FuelTypePrimary | lookup | Pattern | Pattern | + Engine | Valve Train Design | Single Overhead Cam (SOHC) | 2074210 | 26929 | Y[ED][19] | 62 | 4 | 2024-05-21 10:42:05.337 | 2105 | ValveTrainDesign | lookup | Pattern | Pattern | + Engine | Engine Configuration | V-Shaped | 2074211 | 26929 | Y[ED][19] | 64 | 2 | 2024-05-21 10:42:05.353 | 2105 | EngineConfiguration | lookup | Pattern | Pattern | + Engine | Engine Brake (hp) From | 290 | 2074212 | 26929 | Y[ED][19] | 71 | 290 | 2024-05-21 10:42:05.37 | 2105 | EngineHP | decimal | Pattern | Pattern | + Engine | Cooling Type | Water | 2074213 | 26929 | Y[ED][19] | 122 | 2 | 2024-05-21 10:42:05.39 | 2105 | CoolingType | lookup | Pattern | Pattern | + Engine | Engine Manufacturer | Honda | 2074215 | 26929 | Y[ED][19] | 146 | Honda | 2024-05-21 10:42:05.423 | 2105 | EngineManufacturer | string | Pattern | Pattern | + Passive Safety System | Other Restraint System Info | Front: Seat Belts, Mid/Rear: Seat Belt and Side Curtain Air Bag (Outer positions) / Seat Belt (Center position) | 2074179 | 26929 | Y[ED]*H | 121 | Front: Seat Belts, Mid/Rear: Seat Belt and Side Curtain Air Bag (Outer positions) / Seat Belt (Center position) | 2024-05-21 10:17:20.61 | 2105 | OtherRestraintSystemInfo | string | Pattern | Pattern | + Passive Safety System | Seat Belt Type | Manual | 2074174 | 26929 | Y[ED]*H | 79 | 1 | 2024-05-21 10:17:20.393 | 2105 | SeatBeltsAll | lookup | Pattern | Pattern | + Passive Safety System / Air Bag Location | Side Air Bag Locations | 1st Row (Driver and Passenger) | 2074178 | 26929 | Y[ED]*H | 107 | 3 | 2024-05-21 10:17:20.593 | 2105 | AirBagLocSide | lookup | Pattern | Pattern | + Passive Safety System / Air Bag Location | Knee Air Bag Locations | 1st Row (Driver and Passenger) | 2074173 | 26929 | Y[ED]*H | 69 | 3 | 2024-05-21 10:17:20.377 | 2105 | AirBagLocKnee | lookup | Pattern | Pattern | + Passive Safety System / Air Bag Location | Front Air Bag Locations | 1st Row (Driver and Passenger) | 2074172 | 26929 | Y[ED]*H | 65 | 3 | 2024-05-21 10:17:20.36 | 2105 | AirBagLocFront | lookup | Pattern | Pattern | + Passive Safety System / Air Bag Location | Curtain Air Bag Locations | 1st and 2nd and 3rd Rows | 2074170 | 26929 | Y[ED]*H | 55 | 5 | 2024-05-21 10:17:20.327 | 2105 | AirBagLocCurtain | lookup | Pattern | Pattern | + Active Safety System | Keyless Ignition | Standard | 16875 | 5601 | | 176 | 1 | 2025-04-03 14:07:35.83 | | KeylessIgnition | lookup | Pattern | Vehicle Specs | + Active Safety System | Electronic Stability Control (ESC) | Standard | 16875 | 5601 | | 99 | 1 | 2025-04-03 14:07:35.587 | | ESC | lookup | Pattern | Vehicle Specs | + Active Safety System | Tire Pressure Monitoring System (TPMS) Type | Direct | 16875 | 5601 | | 168 | 1 | 2025-04-03 14:07:35.767 | | TPMS | lookup | Pattern | Vehicle Specs | + Active Safety System | Event Data Recorder (EDR) | Standard | 16875 | 5601 | | 175 | 1 | 2025-04-03 14:07:35.817 | | EDR | lookup | Pattern | Vehicle Specs | + Active Safety System | Auto-Reverse System for Windows and Sunroofs | Standard | 16875 | 5601 | | 172 | 1 | 2025-04-03 14:07:35.803 | | AutoReverseSystem | lookup | Pattern | Vehicle Specs | + Active Safety System | Anti-lock Braking System (ABS) | Standard | 16875 | 5601 | | 86 | 1 | 2025-04-03 14:07:35.56 | | ABS | lookup | Pattern | Vehicle Specs | + Active Safety System | Traction Control | Standard | 16875 | 5601 | | 100 | 1 | 2025-04-03 14:07:35.6 | | TractionControl | lookup | Pattern | Vehicle Specs | + Active Safety System / Maintaining Safe Distance | Adaptive Cruise Control (ACC) | Standard | 16875 | 5601 | | 81 | 1 | 2025-04-03 14:07:35.55 | | AdaptiveCruiseControl | lookup | Pattern | Vehicle Specs | + Active Safety System / Forward Collision Prevention | Forward Collision Warning (FCW) | Standard | 16875 | 5601 | | 101 | 1 | 2025-04-03 14:07:35.613 | | ForwardCollisionWarning | lookup | Pattern | Vehicle Specs | + Active Safety System / Forward Collision Prevention | Dynamic Brake Support (DBS) | Standard | 16875 | 5601 | | 170 | 1 | 2025-04-03 14:07:35.78 | | DynamicBrakeSupport | lookup | Pattern | Vehicle Specs | + Active Safety System / Forward Collision Prevention | Pedestrian Automatic Emergency Braking (PAEB) | Standard | 16875 | 5601 | | 171 | 1 | 2025-04-03 14:07:35.79 | | PedestrianAutomaticEmergencyBraking | lookup | Pattern | Vehicle Specs | + Active Safety System / Forward Collision Prevention | Crash Imminent Braking (CIB) | Standard | 16875 | 5601 | | 87 | 1 | 2025-04-03 14:07:35.573 | | CIB | lookup | Pattern | Vehicle Specs | + Active Safety System / Lane and Side Assist | Lane Keeping Assistance (LKA) | Standard | 16875 | 5601 | | 103 | 1 | 2025-04-03 14:07:35.64 | | LaneKeepSystem | lookup | Pattern | Vehicle Specs | + Active Safety System / Lane and Side Assist | Lane Departure Warning (LDW) | Standard | 16875 | 5601 | | 102 | 1 | 2025-04-03 14:07:35.627 | | LaneDepartureWarning | lookup | Pattern | Vehicle Specs | + Active Safety System / Lane and Side Assist | Lane Centering Assistance | Standard | 16875 | 5601 | | 194 | 1 | 2025-04-03 14:07:36.043 | | LaneCenteringAssistance | lookup | Pattern | Vehicle Specs | + Active Safety System / Lane and Side Assist | Blind Spot Intervention (BSI) | Standard | 16875 | 5601 | | 193 | 1 | 2025-04-03 14:07:36.03 | | BlindSpotIntervention | lookup | Pattern | Vehicle Specs | + Active Safety System / Backing Up and Parking | Rear Automatic Emergency Braking | Standard | 16875 | 5601 | | 192 | 1 | 2025-04-03 14:07:36.01 | | RearAutomaticEmergencyBraking | lookup | Pattern | Vehicle Specs | + Active Safety System / Backing Up and Parking | Rear Cross Traffic Alert | Standard | 16875 | 5601 | | 183 | 1 | 2025-04-03 14:07:35.897 | | RearCrossTrafficAlert | lookup | Pattern | Vehicle Specs | + Active Safety System / Backing Up and Parking | Backup Camera | Standard | 16875 | 5601 | | 104 | 1 | 2025-04-03 14:07:35.753 | | RearVisibilitySystem | lookup | Pattern | Vehicle Specs | + Active Safety System / Lighting Technologies | Headlamp Light Source | LED | 16875 | 5601 | | 178 | 3 | 2025-04-03 14:07:35.863 | | LowerBeamHeadlampLightSource | lookup | Pattern | Vehicle Specs | + Active Safety System / Lighting Technologies | Daytime Running Light (DRL) | Standard | 16875 | 5601 | | 177 | 1 | 2025-04-03 14:07:35.843 | | DaytimeRunningLight | lookup | Pattern | Vehicle Specs | + Active Safety System / Lighting Technologies | Semiautomatic Headlamp Beam Switching | Standard | 16875 | 5601 | | 179 | 1 | 2025-04-03 14:07:35.88 | | SemiautomaticHeadlampBeamSwitching | lookup | Pattern | Vehicle Specs | +(70 rows) + diff --git a/data/vehicle-etl/BMW.txt b/data/vehicle-etl/BMW.txt new file mode 100644 index 0000000..c559405 --- /dev/null +++ b/data/vehicle-etl/BMW.txt @@ -0,0 +1,64 @@ + groupname | variable | value | itempatternid | itemvinschemaid | itemkeys | itemelementid | itemattributeid | itemcreatedon | itemwmiid | code | datatype | decode | itemsource | itemtobeqced +-----------------------------------------------------+-----------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------+---------------+-----------------+----------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------+-----------+-------------------------------------+----------+--------------+----------------------------------+-------------- + | Possible Values | | | | | 144 | | | | PossibleValues | string | Decoding | Corrections | + | Additional Error Text | | | | | 156 | | | | AdditionalErrorText | string | Decoding | Corrections | + | Vehicle Descriptor | 5YM13ET0*R9 | | | | 196 | 5YM13ET0*R9 | | | VehicleDescriptor | string | Decoding | Corrections | + | Error Code | 0 | | | | 143 | 0 | | | ErrorCode | lookup | Decoding | Corrections | + | Error Text | 0 - VIN decoded clean. Check Digit (9th position) is correct | | | | 191 | 0 - VIN decoded clean. Check Digit (9th position) is correct | | | ErrorText | string | Decoding | Corrections | + | Suggested VIN | | | | | 142 | | | | SuggestedVIN | string | Decoding | Corrections | + General | Vehicle Type | MULTIPURPOSE PASSENGER VEHICLE (MPV) | | | 5YM | 39 | 7 | 2015-03-11 13:50:19.203 | 2020 | VehicleType | lookup | WMI | VehType | + General | Plant State | SOUTH CAROLINA | 1765033 | 23981 | *****|*9 | 77 | SOUTH CAROLINA | 2022-06-22 14:28:01.55 | 2020 | PlantState | string | Pattern | Pattern | + General | Plant Country | UNITED STATES (USA) | 1765032 | 23981 | *****|*9 | 75 | 6 | 2022-06-22 14:28:01.55 | 2020 | PlantCountry | lookup | Pattern | Pattern | + General | Plant City | GREER | 1765031 | 23981 | *****|*9 | 31 | GREER | 2022-06-22 14:28:01.55 | 2020 | PlantCity | string | Pattern | Pattern | + General | Manufacturer Name | BMW MANUFACTURER CORPORATION / BMW NORTH AMERICA | | | 5YM | 27 | 968 | | 2020 | Manufacturer | lookup | WMI | Manu. Name | + General | Make | BMW | 1895508 | 25151 | 13ET0 | 26 | 452 | | | Make | lookup | WMI, Pattern | pattern - model | + General | Model | X5 | 1895508 | 25151 | 13ET0 | 28 | 1717 | 2023-03-09 15:43:52.33 | 2020 | Model | lookup | Pattern | Pattern | f + General | Trim | X5 M Competition | 2031372 | 25151 | 13ET0 | 38 | X5 M Competition | 2024-02-20 12:44:30.22 | 2020 | Trim | string | Pattern | Pattern | f + General | Model Year | 2024 | | | ***X*|Y | 29 | 2024 | | | ModelYear | int | WMI, Input | ModelYear | + Exterior / Body | Doors | 4 | 1895505 | 25151 | 13ET0 | 14 | 4 | 2023-03-09 15:43:52.28 | 2020 | Doors | int | Pattern | Pattern | f + Exterior / Body | Body Class | Sport Utility Vehicle (SUV)/Multi-Purpose Vehicle (MPV) | 1895502 | 25151 | 13ET0 | 5 | 7 | 2023-03-09 15:43:52.227 | 2020 | BodyClass | lookup | Pattern | Pattern | f + Exterior / Dimension | Gross Vehicle Weight Rating From | Class 2E: 6,001 - 7,000 lb (2,722 - 3,175 kg) | 1895507 | 25151 | 13ET0 | 25 | 14 | 2023-03-09 15:43:52.313 | 2020 | GVWR | lookup | Pattern | Pattern | f + Exterior / Trailer | Trailer Body Type | Not Applicable | | | | 117 | 0 | 2019-12-21 20:26:30.583 | | TrailerBodyType | lookup | Pattern | Default | + Exterior / Trailer | Trailer Type Connection | Not Applicable | | | | 116 | 0 | 2019-12-21 20:26:30.583 | | TrailerType | lookup | Pattern | Default | + Exterior / Motorcycle | Motorcycle Chassis Type | Not Applicable | | | | 153 | 0 | 2019-12-21 20:26:30.583 | | MotorcycleChassisType | lookup | Pattern | Default | + Exterior / Motorcycle | Custom Motorcycle Type | Not Applicable | | | | 151 | 0 | 2019-12-21 20:26:30.583 | | CustomMotorcycleType | lookup | Pattern | Default | + Exterior / Motorcycle | Motorcycle Suspension Type | Not Applicable | | | | 152 | 0 | 2019-12-21 20:26:30.583 | | MotorcycleSuspensionType | lookup | Pattern | Default | + Exterior / Bus | Bus Type | Not Applicable | | | | 149 | 0 | 2019-12-21 20:26:30.583 | | BusType | lookup | Pattern | Default | + Exterior / Bus | Bus Floor Configuration Type | Not Applicable | | | | 148 | 0 | 2019-12-21 20:26:30.583 | | BusFloorConfigType | lookup | Pattern | Default | + Engine | Engine Number of Cylinders | 8 | 1895503 | 25151 | 13ET0 | 9 | 8 | 2023-03-09 15:43:52.243 | 2020 | EngineCylinders | int | Pattern | Pattern | f + Engine | Displacement (CC) | 4400.0 | 1895504 | 25151 | 13ET0 | 11 | 4400.0 | | 2020 | DisplacementCC | decimal | Pattern | Conversion 4: 4.4 * 1000 | + Engine | Displacement (CI) | 268.5044740168220494 | 1895504 | 25151 | 13ET0 | 12 | 268.5044740168220494 | | 2020 | DisplacementCI | decimal | Pattern | Conversion 7: 4.4 / 0.016387064 | + Engine | Displacement (L) | 4.4 | 1895504 | 25151 | 13ET0 | 13 | 4.4 | 2023-03-09 15:43:52.26 | 2020 | DisplacementL | decimal | Pattern | Pattern | f + Engine | Fuel Type - Primary | Gasoline | 1895506 | 25151 | 13ET0 | 24 | 4 | 2023-03-09 15:43:52.297 | 2020 | FuelTypePrimary | lookup | Pattern | Pattern | f + Engine | Engine Brake (hp) From | 617 | 1895513 | 25151 | 13ET0 | 71 | 617 | 2023-03-09 15:43:52.537 | 2020 | EngineHP | decimal | Pattern | Pattern | f + Passive Safety System | Seat Belt Type | Manual | 1895515 | 25151 | 13ET0 | 79 | 1 | 2023-03-09 15:43:52.57 | 2020 | SeatBeltsAll | lookup | Pattern | Pattern | f + Passive Safety System | Other Restraint System Info | Seat Belt: All positions / Pretensioners, Side Airbags, Head Inflatable Restraint: Front Row & Rear Outboard Driver-side, Rear Outboard Passenger-side | 1895520 | 25151 | 13ET0 | 121 | Seat Belt: All positions / Pretensioners, Side Airbags, Head Inflatable Restraint: Front Row & Rear Outboard Driver-side, Rear Outboard Passenger-side | 2023-03-09 15:43:52.77 | 2020 | OtherRestraintSystemInfo | string | Pattern | Pattern | f + Passive Safety System | Pretensioner | Yes | 1895514 | 25151 | 13ET0 | 78 | 1 | 2023-03-09 15:43:52.553 | 2020 | Pretensioner | lookup | Pattern | Pattern | f + Passive Safety System / Air Bag Location | Knee Air Bag Locations | 1st Row (Driver and Passenger) | 1895512 | 25151 | 13ET0 | 69 | 3 | 2023-03-09 15:43:52.517 | 2020 | AirBagLocKnee | lookup | Pattern | Pattern | f + Passive Safety System / Air Bag Location | Side Air Bag Locations | 1st and 2nd Rows | 1895519 | 25151 | 13ET0 | 107 | 4 | 2023-03-09 15:43:52.633 | 2020 | AirBagLocSide | lookup | Pattern | Pattern | f + Passive Safety System / Air Bag Location | Curtain Air Bag Locations | 1st and 2nd Rows | 1895510 | 25151 | 13ET0 | 55 | 4 | 2023-03-09 15:43:52.483 | 2020 | AirBagLocCurtain | lookup | Pattern | Pattern | f + Passive Safety System / Air Bag Location | Front Air Bag Locations | 1st Row (Driver and Passenger) | 1895511 | 25151 | 13ET0 | 65 | 3 | 2023-03-09 15:43:52.5 | 2020 | AirBagLocFront | lookup | Pattern | Pattern | f + Active Safety System | Tire Pressure Monitoring System (TPMS) Type | Direct | 14937 | 4656 | | 168 | 1 | 2024-03-12 13:41:17.253 | | TPMS | lookup | Pattern | Vehicle Specs | + Active Safety System | Anti-lock Braking System (ABS) | Standard | 14937 | 4656 | | 86 | 1 | 2024-03-12 13:41:17.01 | | ABS | lookup | Pattern | Vehicle Specs | + Active Safety System | Keyless Ignition | Standard | 14937 | 4656 | | 176 | 1 | 2024-03-12 13:41:17.317 | | KeylessIgnition | lookup | Pattern | Vehicle Specs | + Active Safety System | Auto-Reverse System for Windows and Sunroofs | Standard | 14937 | 4656 | | 172 | 1 | 2024-03-12 13:41:17.3 | | AutoReverseSystem | lookup | Pattern | Vehicle Specs | + Active Safety System | Electronic Stability Control (ESC) | Standard | 14937 | 4656 | | 99 | 1 | 2024-03-12 13:41:17.05 | | ESC | lookup | Pattern | Vehicle Specs | + Active Safety System | Traction Control | Standard | 14937 | 4656 | | 100 | 1 | 2024-03-12 13:41:17.183 | | TractionControl | lookup | Pattern | Vehicle Specs | + Active Safety System / Maintaining Safe Distance | Adaptive Cruise Control (ACC) | Optional | 14937 | 4656 | | 81 | 3 | 2024-03-12 13:41:16.993 | | AdaptiveCruiseControl | lookup | Pattern | Vehicle Specs | + Active Safety System / Forward Collision Prevention | Dynamic Brake Support (DBS) | Standard | 14937 | 4656 | | 170 | 1 | 2024-03-12 13:41:17.267 | | DynamicBrakeSupport | lookup | Pattern | Vehicle Specs | + Active Safety System / Forward Collision Prevention | Forward Collision Warning (FCW) | Standard | 14937 | 4656 | | 101 | 1 | 2024-03-12 13:41:17.2 | | ForwardCollisionWarning | lookup | Pattern | Vehicle Specs | + Active Safety System / Forward Collision Prevention | Crash Imminent Braking (CIB) | Standard | 14937 | 4656 | | 87 | 1 | 2024-03-12 13:41:17.02 | | CIB | lookup | Pattern | Vehicle Specs | + Active Safety System / Forward Collision Prevention | Pedestrian Automatic Emergency Braking (PAEB) | Standard | 14937 | 4656 | | 171 | 1 | 2024-03-12 13:41:17.28 | | PedestrianAutomaticEmergencyBraking | lookup | Pattern | Vehicle Specs | + Active Safety System / Lane and Side Assist | Lane Centering Assistance | Optional | 14937 | 4656 | | 194 | 3 | 2024-03-12 13:41:17.543 | | LaneCenteringAssistance | lookup | Pattern | Vehicle Specs | + Active Safety System / Lane and Side Assist | Blind Spot Warning (BSW) | Standard | 14937 | 4656 | | 88 | 1 | 2024-03-12 13:41:17.037 | | BlindSpotMon | lookup | Pattern | Vehicle Specs | + Active Safety System / Lane and Side Assist | Lane Keeping Assistance (LKA) | Optional | 14937 | 4656 | | 103 | 5 | 2024-03-12 13:41:17.227 | | LaneKeepSystem | lookup | Pattern | Vehicle Specs | + Active Safety System / Lane and Side Assist | Blind Spot Intervention (BSI) | Optional | 14937 | 4656 | | 193 | 3 | 2024-03-12 13:41:17.53 | | BlindSpotIntervention | lookup | Pattern | Vehicle Specs | + Active Safety System / Lane and Side Assist | Lane Departure Warning (LDW) | Standard | 14937 | 4656 | | 102 | 1 | 2024-03-12 13:41:17.213 | | LaneDepartureWarning | lookup | Pattern | Vehicle Specs | + Active Safety System / Backing Up and Parking | Rear Automatic Emergency Braking | Standard | 14937 | 4656 | | 192 | 1 | 2024-03-12 13:41:17.517 | | RearAutomaticEmergencyBraking | lookup | Pattern | Vehicle Specs | + Active Safety System / Backing Up and Parking | Rear Cross Traffic Alert | Optional | 14937 | 4656 | | 183 | 2 | 2024-03-12 13:41:17.503 | | RearCrossTrafficAlert | lookup | Pattern | Vehicle Specs | + Active Safety System / Backing Up and Parking | Backup Camera | Standard | 14937 | 4656 | | 104 | 1 | 2024-03-12 13:41:17.24 | | RearVisibilitySystem | lookup | Pattern | Vehicle Specs | + Active Safety System / Lighting Technologies | Semiautomatic Headlamp Beam Switching | Standard | 14937 | 4656 | | 179 | 1 | 2024-03-12 13:41:17.49 | | SemiautomaticHeadlampBeamSwitching | lookup | Pattern | Vehicle Specs | + Active Safety System / Lighting Technologies | Daytime Running Light (DRL) | Standard | 14937 | 4656 | | 177 | 1 | 2024-03-12 13:41:17.33 | | DaytimeRunningLight | lookup | Pattern | Vehicle Specs | + Active Safety System / Lighting Technologies | Headlamp Light Source | LED | 14937 | 4656 | | 178 | 3 | 2024-03-12 13:41:17.477 | | LowerBeamHeadlampLightSource | lookup | Pattern | Vehicle Specs | +(60 rows) + diff --git a/data/vehicle-etl/GMC.txt b/data/vehicle-etl/GMC.txt new file mode 100644 index 0000000..e7a23e8 --- /dev/null +++ b/data/vehicle-etl/GMC.txt @@ -0,0 +1,68 @@ + groupname | variable | value | itempatternid | itemvinschemaid | itemkeys | itemelementid | itemattributeid | itemcreatedon | itemwmiid | code | datatype | decode | itemsource | itemtobeqced +-----------------------------------------------------+-----------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+---------------+-----------------+----------------+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------+-----------+-------------------------------------+----------+--------------+----------------------------------+-------------- + | Suggested VIN | | | | | 142 | | | | SuggestedVIN | string | Decoding | Corrections | + | Error Text | 0 - VIN decoded clean. Check Digit (9th position) is correct | | | | 191 | 0 - VIN decoded clean. Check Digit (9th position) is correct | | | ErrorText | string | Decoding | Corrections | + | Additional Error Text | The Model Year decoded for this VIN may be incorrect. If you know the Model year, please enter it and decode again to get more accurate information. | | | | 156 | The Model Year decoded for this VIN may be incorrect. If you know the Model year, please enter it and decode again to get more accurate information. | | | AdditionalErrorText | string | Decoding | Corrections | + | Error Code | 0 | | | | 143 | 0 | | | ErrorCode | lookup | Decoding | Corrections | + | Vehicle Descriptor | 3GTUUFEL*PG | | | | 196 | 3GTUUFEL*PG | | | VehicleDescriptor | string | Decoding | Corrections | + | Possible Values | | | | | 144 | | | | PossibleValues | string | Decoding | Corrections | + General | Manufacturer Name | GENERAL MOTORS LLC | | | 3GT | 27 | 984 | | 2066 | Manufacturer | lookup | WMI | Manu. Name | + General | Model Year | 2023 | | | ***X*|Y | 29 | 2023 | | | ModelYear | int | WMI, Input | ModelYear | + General | Make | GMC | 1947758 | 25646 | [NPRUV][HU] | 26 | 472 | | | Make | lookup | WMI, Pattern | pattern - model | + General | Plant City | SILAO | 1947761 | 25646 | *****|*G | 31 | SILAO | 2023-07-11 14:39:30.503 | 2066 | PlantCity | string | Pattern | Pattern | + General | Series | 1500 | 1947762 | 25646 | [NPRUV][HU] | 34 | 1500 | 2023-07-11 14:39:30.503 | 2066 | Series | string | Pattern | Pattern | + General | Trim | AT4X | 1947769 | 25646 | *UF | 38 | AT4X | 2023-07-11 14:39:30.503 | 2066 | Trim | string | Pattern | Pattern | + General | Plant Country | MEXICO | 1947783 | 25646 | *****|*G | 75 | 12 | 2023-07-11 14:39:30.503 | 2066 | PlantCountry | lookup | Pattern | Pattern | + General | Plant State | GUANAJUATO | 1947786 | 25646 | *****|*G | 77 | GUANAJUATO | 2023-07-11 14:39:30.503 | 2066 | PlantState | string | Pattern | Pattern | + General | Vehicle Type | TRUCK | | | 3GT | 39 | 3 | 2015-03-24 15:16:38.563 | 2066 | VehicleType | lookup | WMI | VehType | + General | Model | Sierra | 1947758 | 25646 | [NPRUV][HU] | 28 | 1857 | 2023-07-11 14:46:06.22 | 2066 | Model | lookup | Pattern | Pattern | + Exterior / Body | Body Class | Pickup | 1947732 | 25646 | [NPRUV][HU] | 5 | 60 | 2023-07-11 14:46:06.22 | 2066 | BodyClass | lookup | Pattern | Pattern | + Exterior / Dimension | Gross Vehicle Weight Rating From | Class 2F: 7,001 - 8,000 lb (3,175 - 3,629 kg) | 1947756 | 25646 | [UV][HU] | 25 | 15 | 2023-07-11 14:46:18.457 | 2066 | GVWR | lookup | Pattern | Pattern | + Exterior / Trailer | Trailer Body Type | Not Applicable | | | | 117 | 0 | 2019-12-21 20:26:30.583 | | TrailerBodyType | lookup | Pattern | Default | + Exterior / Trailer | Trailer Type Connection | Not Applicable | | | | 116 | 0 | 2019-12-21 20:26:30.583 | | TrailerType | lookup | Pattern | Default | + Exterior / Motorcycle | Motorcycle Chassis Type | Not Applicable | | | | 153 | 0 | 2019-12-21 20:26:30.583 | | MotorcycleChassisType | lookup | Pattern | Default | + Exterior / Motorcycle | Custom Motorcycle Type | Not Applicable | | | | 151 | 0 | 2019-12-21 20:26:30.583 | | CustomMotorcycleType | lookup | Pattern | Default | + Exterior / Motorcycle | Motorcycle Suspension Type | Not Applicable | | | | 152 | 0 | 2019-12-21 20:26:30.583 | | MotorcycleSuspensionType | lookup | Pattern | Default | + Exterior / Bus | Bus Type | Not Applicable | | | | 149 | 0 | 2019-12-21 20:26:30.583 | | BusType | lookup | Pattern | Default | + Exterior / Bus | Bus Floor Configuration Type | Not Applicable | | | | 148 | 0 | 2019-12-21 20:26:30.583 | | BusFloorConfigType | lookup | Pattern | Default | + Mechanical / Drivetrain | Drive Type | 4WD/4-Wheel Drive/4x4 | 1947745 | 25646 | [NPRUV]U[A-J9] | 15 | 2 | 2023-07-11 14:39:30.503 | 2066 | DriveType | lookup | Pattern | Pattern | + Mechanical / Brake | Brake System Type | Hydraulic | 1947772 | 25646 | [NPRUV][HU] | 42 | 2 | 2023-07-11 14:46:06.22 | 2066 | BrakeSystemType | lookup | Pattern | Pattern | + Engine | Other Engine Info | DI DFM, ALUM, GEN 5 | 1947794 | 25646 | *[HU]**L | 129 | DI DFM, ALUM, GEN 5 | 2023-07-11 14:39:30.503 | 2066 | OtherEngineInfo | string | Pattern | Pattern | + Engine | Displacement (CI) | 378.3472133873401605 | 1947739 | 25646 | *[HU]**L | 12 | 378.3472133873401605 | | 2066 | DisplacementCI | decimal | Pattern | Conversion 7: 6.2 / 0.016387064 | + Engine | Engine Configuration | V-Shaped | 1947780 | 25646 | *[HU]**L | 64 | 2 | 2023-07-11 14:39:30.503 | 2066 | EngineConfiguration | lookup | Pattern | Pattern | + Engine | Fuel Type - Primary | Gasoline | 1947755 | 25646 | *[HU]**L | 24 | 4 | 2023-07-11 14:39:30.503 | 2066 | FuelTypePrimary | lookup | Pattern | Pattern | + Engine | Engine Model | L87 | 1947746 | 25646 | *[HU]**L | 18 | L87 | 2023-07-11 14:39:30.503 | 2066 | EngineModel | string | Pattern | Pattern | + Engine | Displacement (L) | 6.2 | 1947739 | 25646 | *[HU]**L | 13 | 6.2 | 2023-07-11 14:39:30.503 | 2066 | DisplacementL | decimal | Pattern | Pattern | + Engine | Engine Number of Cylinders | 8 | 1947733 | 25646 | *[HU]**L | 9 | 8 | 2023-07-11 14:39:30.503 | 2066 | EngineCylinders | int | Pattern | Pattern | + Engine | Displacement (CC) | 6200.0 | 1947739 | 25646 | *[HU]**L | 11 | 6200.0 | | 2066 | DisplacementCC | decimal | Pattern | Conversion 4: 6.2 * 1000 | + Passive Safety System | Seat Belt Type | Manual | 1947788 | 25646 | *[HU]*E | 79 | 1 | 2023-07-11 14:39:30.503 | 2066 | SeatBeltsAll | lookup | Pattern | Pattern | + Passive Safety System | Other Restraint System Info | AY0 - Active Manual Belts | 1947793 | 25646 | *[HU]*E | 121 | AY0 - Active Manual Belts | 2023-07-11 14:39:30.503 | 2066 | OtherRestraintSystemInfo | string | Pattern | Pattern | + Passive Safety System / Air Bag Location | Curtain Air Bag Locations | All Rows | 1947773 | 25646 | *[HU]*E | 55 | 6 | 2023-07-11 14:39:30.503 | 2066 | AirBagLocCurtain | lookup | Pattern | Pattern | + Passive Safety System / Air Bag Location | Front Air Bag Locations | 1st Row (Driver and Passenger) | 1947781 | 25646 | *[HU]*E | 65 | 3 | 2023-07-11 14:39:30.503 | 2066 | AirBagLocFront | lookup | Pattern | Pattern | + Passive Safety System / Air Bag Location | Side Air Bag Locations | 1st Row (Driver and Passenger) | 1947792 | 25646 | *[HU]*E | 107 | 3 | 2023-07-11 14:39:30.503 | 2066 | AirBagLocSide | lookup | Pattern | Pattern | + Active Safety System | Auto-Reverse System for Windows and Sunroofs | Optional | 13609 | 4140 | | 172 | 3 | 2024-01-31 16:04:17.207 | | AutoReverseSystem | lookup | Pattern | Vehicle Specs | f + Active Safety System | Electronic Stability Control (ESC) | Standard | 13609 | 4140 | | 99 | 1 | 2024-01-31 16:04:16.897 | | ESC | lookup | Pattern | Vehicle Specs | f + Active Safety System | Anti-lock Braking System (ABS) | Standard | 13609 | 4140 | | 86 | 1 | 2024-01-31 16:04:16.85 | | ABS | lookup | Pattern | Vehicle Specs | f + Active Safety System | Traction Control | Standard | 13609 | 4140 | | 100 | 1 | 2024-01-31 16:04:16.91 | | TractionControl | lookup | Pattern | Vehicle Specs | f + Active Safety System | Keyless Ignition | Standard | 13609 | 4140 | | 176 | 1 | 2024-01-31 16:04:17.257 | | KeylessIgnition | lookup | Pattern | Vehicle Specs | f + Active Safety System | Tire Pressure Monitoring System (TPMS) Type | Direct | 13609 | 4140 | | 168 | 1 | 2024-01-31 16:04:17.157 | | TPMS | lookup | Pattern | Vehicle Specs | f + Active Safety System | Event Data Recorder (EDR) | Standard | 13609 | 4140 | | 175 | 1 | 2024-01-31 16:04:17.24 | | EDR | lookup | Pattern | Vehicle Specs | f + Active Safety System / Maintaining Safe Distance | Adaptive Cruise Control (ACC) | Optional | 13609 | 4140 | | 81 | 3 | 2024-01-31 16:04:16.837 | | AdaptiveCruiseControl | lookup | Pattern | Vehicle Specs | f + Active Safety System / Forward Collision Prevention | Dynamic Brake Support (DBS) | Standard | 13609 | 4140 | | 170 | 1 | 2024-01-31 16:04:17.173 | | DynamicBrakeSupport | lookup | Pattern | Vehicle Specs | f + Active Safety System / Forward Collision Prevention | Crash Imminent Braking (CIB) | Standard | 13609 | 4140 | | 87 | 1 | 2024-01-31 16:04:16.863 | | CIB | lookup | Pattern | Vehicle Specs | f + Active Safety System / Forward Collision Prevention | Pedestrian Automatic Emergency Braking (PAEB) | Standard | 13609 | 4140 | | 171 | 1 | 2024-01-31 16:04:17.19 | | PedestrianAutomaticEmergencyBraking | lookup | Pattern | Vehicle Specs | f + Active Safety System / Forward Collision Prevention | Forward Collision Warning (FCW) | Standard | 13609 | 4140 | | 101 | 1 | 2024-01-31 16:04:16.923 | | ForwardCollisionWarning | lookup | Pattern | Vehicle Specs | f + Active Safety System / Lane and Side Assist | Lane Keeping Assistance (LKA) | Standard | 13609 | 4140 | | 103 | 1 | 2024-01-31 16:04:17.103 | | LaneKeepSystem | lookup | Pattern | Vehicle Specs | f + Active Safety System / Lane and Side Assist | Lane Departure Warning (LDW) | Standard | 13609 | 4140 | | 102 | 1 | 2024-01-31 16:04:16.94 | | LaneDepartureWarning | lookup | Pattern | Vehicle Specs | f + Active Safety System / Lane and Side Assist | Blind Spot Warning (BSW) | Optional | 13609 | 4140 | | 88 | 3 | 2024-01-31 16:04:16.88 | | BlindSpotMon | lookup | Pattern | Vehicle Specs | f + Active Safety System / Backing Up and Parking | Rear Automatic Emergency Braking | Optional | 13609 | 4140 | | 192 | 3 | 2024-01-31 16:04:17.487 | | RearAutomaticEmergencyBraking | lookup | Pattern | Vehicle Specs | f + Active Safety System / Backing Up and Parking | Backup Camera | Standard | 13609 | 4140 | | 104 | 1 | 2024-01-31 16:04:17.12 | | RearVisibilitySystem | lookup | Pattern | Vehicle Specs | f + Active Safety System / Backing Up and Parking | Rear Cross Traffic Alert | Optional | 13609 | 4140 | | 183 | 2 | 2024-01-31 16:04:17.47 | | RearCrossTrafficAlert | lookup | Pattern | Vehicle Specs | f + Active Safety System / Backing Up and Parking | Parking Assist | Optional | 13609 | 4140 | | 105 | 3 | 2024-01-31 16:04:17.14 | | ParkAssist | lookup | Pattern | Vehicle Specs | f + Active Safety System / 911 Notification | Automatic Crash Notification (ACN) / Advanced Automatic Crash Notification (AACN) | Standard | 13609 | 4140 | | 174 | 1 | 2024-01-31 16:04:17.22 | | CAN_AACN | lookup | Pattern | Vehicle Specs | f + Active Safety System / Lighting Technologies | Headlamp Light Source | LED | 13609 | 4140 | | 178 | 3 | 2024-01-31 16:04:17.427 | | LowerBeamHeadlampLightSource | lookup | Pattern | Vehicle Specs | f + Active Safety System / Lighting Technologies | Adaptive Driving Beam (ADB) | Standard | 13609 | 4140 | | 180 | 1 | 2024-01-31 16:04:17.453 | | AdaptiveDrivingBeam | lookup | Pattern | Vehicle Specs | f + Active Safety System / Lighting Technologies | Daytime Running Light (DRL) | Standard | 13609 | 4140 | | 177 | 1 | 2024-01-31 16:04:17.273 | | DaytimeRunningLight | lookup | Pattern | Vehicle Specs | f + Active Safety System / Lighting Technologies | Semiautomatic Headlamp Beam Switching | Standard | 13609 | 4140 | | 179 | 1 | 2024-01-31 16:04:17.44 | | SemiautomaticHeadlampBeamSwitching | lookup | Pattern | Vehicle Specs | f +(64 rows) + diff --git a/data/vehicle-etl/HONDA.txt b/data/vehicle-etl/HONDA.txt new file mode 100644 index 0000000..1b77a1f --- /dev/null +++ b/data/vehicle-etl/HONDA.txt @@ -0,0 +1,79 @@ + groupname | variable | value | itempatternid | itemvinschemaid | itemkeys | itemelementid | itemattributeid | itemcreatedon | itemwmiid | code | datatype | decode | itemsource | itemtobeqced +-----------------------------------------------------+--------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+---------------+-----------------+----------+---------------+----------------------------------------------------------------------------------------------------------------------------+-------------------------+-----------+-------------------------------------+----------+--------------+--------------------------------+-------------- + | Error Text | 0 - VIN decoded clean. Check Digit (9th position) is correct | | | | 191 | 0 - VIN decoded clean. Check Digit (9th position) is correct | | | ErrorText | string | Decoding | Corrections | + | Additional Error Text | | | | | 156 | | | | AdditionalErrorText | string | Decoding | Corrections | + | Error Code | 0 | | | | 143 | 0 | | | ErrorCode | lookup | Decoding | Corrections | + | Possible Values | | | | | 144 | | | | PossibleValues | string | Decoding | Corrections | + | Vehicle Descriptor | 2HGFE4F8*SH | | | | 196 | 2HGFE4F8*SH | | | VehicleDescriptor | string | Decoding | Corrections | + | Suggested VIN | | | | | 142 | | | | SuggestedVIN | string | Decoding | Corrections | + General | Plant City | ALLISTON | 2123543 | 27387 | *****|*H | 31 | ALLISTON | 2024-09-16 08:37:51.523 | 2096 | PlantCity | string | Pattern | Pattern | + General | Trim | Sport Hybrid / Sport Touring Hybrid | 2086003 | 27007 | FE4F8 | 38 | Sport Hybrid / Sport Touring Hybrid | 2024-06-17 10:36:46.323 | 2096 | Trim | string | Pattern | Pattern | + General | Plant Country | CANADA | 2123544 | 27387 | *****|*H | 75 | 1 | 2024-09-16 08:37:51.54 | 2096 | PlantCountry | lookup | Pattern | Pattern | + General | Plant State | ONTARIO | 2123545 | 27387 | *****|*H | 77 | ONTARIO | 2024-09-16 08:37:51.553 | 2096 | PlantState | string | Pattern | Pattern | + General | Model Year | 2025 | | | ***X*|Y | 29 | 2025 | | | ModelYear | int | WMI, Input | ModelYear | + General | Manufacturer Name | HONDA OF CANADA MFG., A DIVISION OF HONDA CANADA INC. | | | 2HG | 27 | 990 | | 2096 | Manufacturer | lookup | WMI | Manu. Name | + General | Make | HONDA | 2086001 | 27007 | FE4F8 | 26 | 474 | | | Make | lookup | WMI, Pattern | pattern - model | + General | Vehicle Type | PASSENGER CAR | | | 2HG | 39 | 2 | 2015-03-26 16:57:39.147 | 2096 | VehicleType | lookup | WMI | VehType | + General | Model | Civic | 2086001 | 27007 | FE4F8 | 28 | 1863 | 2024-06-17 10:36:46.287 | 2096 | Model | lookup | Pattern | Pattern | + Exterior / Body | Doors | 4 | 2085995 | 27007 | FE4F8 | 14 | 4 | 2024-06-17 10:36:46.163 | 2096 | Doors | int | Pattern | Pattern | + Exterior / Body | Body Class | Sedan/Saloon | 2085992 | 27007 | FE4F8 | 5 | 13 | 2024-06-17 10:36:45.88 | 2096 | BodyClass | lookup | Pattern | Pattern | + Exterior / Dimension | Gross Vehicle Weight Rating From | Class 1C: 4,001 - 5,000 lb (1,814 - 2,268 kg) | 2086000 | 27007 | FE4F8 | 25 | 12 | 2024-06-17 10:36:46.267 | 2096 | GVWR | lookup | Pattern | Pattern | + Exterior / Dimension | Gross Vehicle Weight Rating To | Class 1C: 4,001 - 5,000 lb (1,814 - 2,268 kg) | 2086015 | 27007 | FE4F8 | 190 | 12 | 2024-06-17 10:36:46.713 | 2096 | GVWR_to | lookup | Pattern | Pattern | + Exterior / Truck | Bed Type | Not Applicable | | | | 3 | 0 | 2019-12-21 20:26:30.583 | | BedType | lookup | Pattern | Default | + Exterior / Truck | Cab Type | Not Applicable | | | | 4 | 0 | 2019-12-21 20:26:30.583 | | BodyCabType | lookup | Pattern | Default | + Exterior / Trailer | Trailer Body Type | Not Applicable | | | | 117 | 0 | 2019-12-21 20:26:30.583 | | TrailerBodyType | lookup | Pattern | Default | + Exterior / Trailer | Trailer Type Connection | Not Applicable | | | | 116 | 0 | 2019-12-21 20:26:30.583 | | TrailerType | lookup | Pattern | Default | + Exterior / Motorcycle | Motorcycle Suspension Type | Not Applicable | | | | 152 | 0 | 2019-12-21 20:26:30.583 | | MotorcycleSuspensionType | lookup | Pattern | Default | + Exterior / Motorcycle | Custom Motorcycle Type | Not Applicable | | | | 151 | 0 | 2019-12-21 20:26:30.583 | | CustomMotorcycleType | lookup | Pattern | Default | + Exterior / Motorcycle | Motorcycle Chassis Type | Not Applicable | | | | 153 | 0 | 2019-12-21 20:26:30.583 | | MotorcycleChassisType | lookup | Pattern | Default | + Exterior / Bus | Bus Floor Configuration Type | Not Applicable | | | | 148 | 0 | 2019-12-21 20:26:30.583 | | BusFloorConfigType | lookup | Pattern | Default | + Exterior / Bus | Bus Type | Not Applicable | | | | 149 | 0 | 2019-12-21 20:26:30.583 | | BusType | lookup | Pattern | Default | + Mechanical / Transmission | Transmission Style | Electronic Continuously Variable (e-CVT) | 2086002 | 27007 | FE4F8 | 37 | 4 | 2024-06-17 10:36:46.307 | 2096 | TransmissionStyle | lookup | Pattern | Pattern | + Mechanical / Drivetrain | Drive Type | 4x2 | 2085996 | 27007 | FE4F8 | 15 | 7 | 2024-06-17 10:36:46.18 | 2096 | DriveType | lookup | Pattern | Pattern | + Mechanical / Battery | EV Drive Unit | Single Motor | 2086065 | 27007 | FE4F8 | 72 | 2 | 2024-06-17 10:59:49.297 | 2096 | EVDriveUnit | lookup | Pattern | Pattern | + Engine | Engine Manufacturer | Honda | 2086014 | 27007 | FE4F8 | 146 | Honda | 2024-06-17 10:36:46.69 | 2096 | EngineManufacturer | string | Pattern | Pattern | + Engine | Displacement (CC) | 2000 | 2085994 | 27007 | FE4F8 | 11 | 2000 | | 2096 | DisplacementCC | decimal | Pattern | Conversion 4: 2 * 1000 | + Engine | Displacement (CI) | 122.0474881894645679 | 2085994 | 27007 | FE4F8 | 12 | 122.0474881894645679 | | 2096 | DisplacementCI | decimal | Pattern | Conversion 7: 2 / 0.016387064 | + Engine | Engine Number of Cylinders | 4 | 2085993 | 27007 | FE4F8 | 9 | 4 | 2024-06-17 10:36:45.96 | 2096 | EngineCylinders | int | Pattern | Pattern | + Engine | Displacement (L) | 2 | 2085994 | 27007 | FE4F8 | 13 | 2 | 2024-06-17 10:36:46.023 | 2096 | DisplacementL | decimal | Pattern | Pattern | + Engine | Engine Stroke Cycles | 4 | 2085997 | 27007 | FE4F8 | 17 | 4 | 2024-06-17 10:36:46.203 | 2096 | EngineCycles | int | Pattern | Pattern | + Engine | Engine Model | LFC3 | 2085998 | 27007 | FE4F8 | 18 | LFC3 | 2024-06-17 10:36:46.223 | 2096 | EngineModel | string | Pattern | Pattern | + Engine | Fuel Type - Primary | Gasoline | 2085999 | 27007 | FE4F8 | 24 | 4 | 2024-06-17 10:36:46.247 | 2096 | FuelTypePrimary | lookup | Pattern | Pattern | + Engine | Valve Train Design | Dual Overhead Cam (DOHC) | 2086004 | 27007 | FE4F8 | 62 | 2 | 2024-06-17 10:36:46.343 | 2096 | ValveTrainDesign | lookup | Pattern | Pattern | + Engine | Engine Configuration | In-Line | 2086005 | 27007 | FE4F8 | 64 | 1 | 2024-06-17 10:36:46.363 | 2096 | EngineConfiguration | lookup | Pattern | Pattern | + Engine | Fuel Type - Secondary | Electric | 2086006 | 27007 | FE4F8 | 66 | 2 | 2024-06-17 10:36:46.527 | 2096 | FuelTypeSecondary | lookup | Pattern | Pattern | + Engine | Engine Brake (hp) From | 141 | 2086007 | 27007 | FE4F8 | 71 | 141 | 2024-06-17 10:36:46.543 | 2096 | EngineHP | decimal | Pattern | Pattern | + Engine | Cooling Type | Water | 2086011 | 27007 | FE4F8 | 122 | 2 | 2024-06-17 10:36:46.63 | 2096 | CoolingType | lookup | Pattern | Pattern | + Engine | Electrification Level | Strong HEV (Hybrid Electric Vehicle) | 2086012 | 27007 | FE4F8 | 126 | 2 | 2024-06-17 10:36:46.65 | 2096 | ElectrificationLevel | lookup | Pattern | Pattern | + Engine | Other Engine Info | Direct Fuel Injection / Motor: 135kW | 2086013 | 27007 | FE4F8 | 129 | Direct Fuel Injection / Motor: 135kW | 2024-06-17 10:36:46.67 | 2096 | OtherEngineInfo | string | Pattern | Pattern | + Passive Safety System | Other Restraint System Info | Front: Seat Belt / Rear: Seat Belt , Side Air Bag and Side Curtain Air Bag (Outer positions) / Seat Belt (Center position) | 2083833 | 27007 | FE[24]F | 121 | Front: Seat Belt / Rear: Seat Belt , Side Air Bag and Side Curtain Air Bag (Outer positions) / Seat Belt (Center position) | 2024-06-17 10:20:27.853 | 2096 | OtherRestraintSystemInfo | string | Pattern | Pattern | + Passive Safety System | Seat Belt Type | Manual | 2083828 | 27007 | FE[24]F | 79 | 1 | 2024-06-17 10:20:27.853 | 2096 | SeatBeltsAll | lookup | Pattern | Pattern | + Passive Safety System / Air Bag Location | Side Air Bag Locations | 1st and 2nd Rows | 2083832 | 27007 | FE[24]F | 107 | 4 | 2024-06-17 10:20:27.853 | 2096 | AirBagLocSide | lookup | Pattern | Pattern | + Passive Safety System / Air Bag Location | Knee Air Bag Locations | 1st Row (Driver and Passenger) | 2083826 | 27007 | FE[24]F | 69 | 3 | 2024-06-17 10:05:30.837 | 2096 | AirBagLocKnee | lookup | Pattern | Pattern | + Passive Safety System / Air Bag Location | Front Air Bag Locations | 1st Row (Driver and Passenger) | 2083825 | 27007 | FE[24]F | 65 | 3 | 2024-06-17 10:05:30.837 | 2096 | AirBagLocFront | lookup | Pattern | Pattern | + Passive Safety System / Air Bag Location | Curtain Air Bag Locations | 1st and 2nd Rows | 2083822 | 27007 | FE[24]F | 55 | 4 | 2024-06-17 10:05:30.837 | 2096 | AirBagLocCurtain | lookup | Pattern | Pattern | + Active Safety System | Anti-lock Braking System (ABS) | Standard | 16871 | 5597 | | 86 | 1 | 2025-04-03 14:40:02.47 | | ABS | lookup | Pattern | Vehicle Specs | + Active Safety System | Traction Control | Standard | 16871 | 5597 | | 100 | 1 | 2025-04-03 14:40:02.52 | | TractionControl | lookup | Pattern | Vehicle Specs | + Active Safety System | Automatic Pedestrian Alerting Sound (for Hybrid and EV only) | Standard | 17451 | 5597 | | 173 | 1 | 2025-04-01 10:29:03.217 | | AutomaticPedestrianAlertingSound | lookup | Pattern | Vehicle Specs | + Active Safety System | Tire Pressure Monitoring System (TPMS) Type | Indirect | 16871 | 5597 | | 168 | 2 | 2025-04-03 14:40:02.6 | | TPMS | lookup | Pattern | Vehicle Specs | + Active Safety System | Keyless Ignition | Standard | 16871 | 5597 | | 176 | 1 | 2025-04-03 14:40:02.793 | | KeylessIgnition | lookup | Pattern | Vehicle Specs | + Active Safety System | Electronic Stability Control (ESC) | Standard | 16871 | 5597 | | 99 | 1 | 2025-04-03 14:40:02.503 | | ESC | lookup | Pattern | Vehicle Specs | + Active Safety System | Auto-Reverse System for Windows and Sunroofs | Standard | 16871 | 5597 | | 172 | 1 | 2025-04-03 14:40:02.763 | | AutoReverseSystem | lookup | Pattern | Vehicle Specs | + Active Safety System | Event Data Recorder (EDR) | Standard | 16871 | 5597 | | 175 | 1 | 2025-04-03 14:40:02.78 | | EDR | lookup | Pattern | Vehicle Specs | + Active Safety System / Maintaining Safe Distance | Adaptive Cruise Control (ACC) | Standard | 16871 | 5597 | | 81 | 1 | 2025-04-03 14:40:02.337 | | AdaptiveCruiseControl | lookup | Pattern | Vehicle Specs | + Active Safety System / Forward Collision Prevention | Forward Collision Warning (FCW) | Standard | 16871 | 5597 | | 101 | 1 | 2025-04-03 14:40:02.537 | | ForwardCollisionWarning | lookup | Pattern | Vehicle Specs | + Active Safety System / Forward Collision Prevention | Dynamic Brake Support (DBS) | Standard | 16871 | 5597 | | 170 | 1 | 2025-04-03 14:40:02.61 | | DynamicBrakeSupport | lookup | Pattern | Vehicle Specs | + Active Safety System / Forward Collision Prevention | Crash Imminent Braking (CIB) | Standard | 16871 | 5597 | | 87 | 1 | 2025-04-03 14:40:02.487 | | CIB | lookup | Pattern | Vehicle Specs | + Active Safety System / Forward Collision Prevention | Pedestrian Automatic Emergency Braking (PAEB) | Standard | 16871 | 5597 | | 171 | 1 | 2025-04-03 14:40:02.627 | | PedestrianAutomaticEmergencyBraking | lookup | Pattern | Vehicle Specs | + Active Safety System / Lane and Side Assist | Lane Keeping Assistance (LKA) | Standard | 16871 | 5597 | | 103 | 1 | 2025-04-03 14:40:02.567 | | LaneKeepSystem | lookup | Pattern | Vehicle Specs | + Active Safety System / Lane and Side Assist | Blind Spot Intervention (BSI) | Standard | 17451 | 5597 | | 193 | 1 | 2025-04-01 10:29:03.243 | | BlindSpotIntervention | lookup | Pattern | Vehicle Specs | + Active Safety System / Lane and Side Assist | Blind Spot Warning (BSW) | Standard | 17451 | 5597 | | 88 | 1 | 2025-04-01 10:29:03.203 | | BlindSpotMon | lookup | Pattern | Vehicle Specs | + Active Safety System / Lane and Side Assist | Lane Departure Warning (LDW) | Standard | 16871 | 5597 | | 102 | 1 | 2025-04-03 14:40:02.55 | | LaneDepartureWarning | lookup | Pattern | Vehicle Specs | + Active Safety System / Backing Up and Parking | Backup Camera | Standard | 16871 | 5597 | | 104 | 1 | 2025-04-03 14:40:02.583 | | RearVisibilitySystem | lookup | Pattern | Vehicle Specs | + Active Safety System / Backing Up and Parking | Rear Automatic Emergency Braking | Standard | 16871 | 5597 | | 192 | 1 | 2025-04-03 14:40:02.877 | | RearAutomaticEmergencyBraking | lookup | Pattern | Vehicle Specs | + Active Safety System / Backing Up and Parking | Rear Cross Traffic Alert | Standard | 17451 | 5597 | | 183 | 1 | 2025-04-01 10:29:03.23 | | RearCrossTrafficAlert | lookup | Pattern | Vehicle Specs | + Active Safety System / Lighting Technologies | Semiautomatic Headlamp Beam Switching | Standard | 16871 | 5597 | | 179 | 1 | 2025-04-03 14:40:02.843 | | SemiautomaticHeadlampBeamSwitching | lookup | Pattern | Vehicle Specs | + Active Safety System / Lighting Technologies | Daytime Running Light (DRL) | Standard | 16871 | 5597 | | 177 | 1 | 2025-04-03 14:40:02.81 | | DaytimeRunningLight | lookup | Pattern | Vehicle Specs | + Active Safety System / Lighting Technologies | Headlamp Light Source | LED | 16871 | 5597 | | 178 | 3 | 2025-04-03 14:40:02.83 | | LowerBeamHeadlampLightSource | lookup | Pattern | Vehicle Specs | +(75 rows) + diff --git a/data/vehicle-etl/README.md b/data/vehicle-etl/README.md index d784997..6dfa2ef 100644 --- a/data/vehicle-etl/README.md +++ b/data/vehicle-etl/README.md @@ -33,9 +33,8 @@ Step 1: Fetch Data from VehAPI python3 vehapi_fetch_snapshot.py --min-year 2020 --max-year 2020 - # Full ETL workflow + # Full ETL workflow with cached results ./reset_database.sh # Clear old data - python3 vehapi_fetch_snapshot.py # Fetch from API python3 etl_generate_sql.py --snapshot-path snapshots/*.sqlite # Generate SQL ./import_data.sh # Import to Postgres docker compose exec mvp-redis redis-cli FLUSHALL # Flush Redis Cache for front end diff --git a/data/vehicle-etl/logical-plotting-hartmanis.md b/data/vehicle-etl/logical-plotting-hartmanis.md new file mode 100644 index 0000000..eee401d --- /dev/null +++ b/data/vehicle-etl/logical-plotting-hartmanis.md @@ -0,0 +1,514 @@ +# vPIC ETL Implementation Plan v2 + +## Overview + +Extract vehicle dropdown data from NHTSA vPIC database for MY2022+ to supplement existing VehAPI data. This revised plan uses a make-specific extraction approach with proper VIN schema parsing. + +## Key Changes from v1 + +1. **Limit to VehAPI makes only** - Only extract the 48 makes that exist in VehAPI data +2. **VIN schema-based extraction** - Extract directly from VIN patterns, not defs_model +3. **Proper field formatting** - Match VehAPI display string formats +4. **Make-specific logic** - Handle different manufacturers' data patterns + +## Critical Discovery: WMI Linkage + +**Must use `wmi_make` junction table (many-to-many), NOT `wmi.makeid` (one-to-many):** +```sql +-- CORRECT: via wmi_make (finds all makes including Toyota, Hyundai, etc.) +FROM vpic.make m +JOIN vpic.wmi_make wm ON wm.makeid = m.id +JOIN vpic.wmi w ON w.id = wm.wmiid + +-- WRONG: via wmi.makeid (misses many major brands) +FROM vpic.make m +JOIN vpic.wmi w ON w.makeid = m.id +``` + +--- + +## Make Availability Summary + +| Status | Count | Makes | +|--------|-------|-------| +| **Available (2022+ schemas)** | 46 | See table below | +| **No 2022+ data** | 2 | Hummer (discontinued 2010), Scion (discontinued 2016) | + +--- + +## Per-Make Analysis + +### Group 1: Japanese Manufacturers (Honda/Acura, Toyota/Lexus, Nissan/Infiniti) + +| Make | VehAPI Name | vPIC Name | Schemas (2022+) | Status | +|------|-------------|-----------|-----------------|--------| +| Acura | Acura | Acura | 48 | Ready | +| Honda | Honda | Honda | 238 | Ready | +| Lexus | Lexus | Lexus | 90 | Ready | +| Toyota | Toyota | Toyota | 152 | Ready | +| Infiniti | INFINITI | Infiniti | 76 | Ready | +| Nissan | Nissan | Nissan | 85 | Ready | +| Mazda | Mazda | Mazda | 37 | Ready | +| Mitsubishi | Mitsubishi | Mitsubishi | 11 | Ready | +| Subaru | Subaru | Subaru | 75 | Ready | +| Isuzu | Isuzu | Isuzu | 11 | Ready | + +### Group 2: Korean Manufacturers (Hyundai/Kia/Genesis) + +| Make | VehAPI Name | vPIC Name | Schemas (2022+) | Status | +|------|-------------|-----------|-----------------|--------| +| Genesis | Genesis | Genesis | 74 | Ready | +| Hyundai | Hyundai | Hyundai | 177 | Ready | +| Kia | Kia | Kia | 72 | Ready | + +### Group 3: American - GM (Chevrolet, GMC, Buick, Cadillac) + +| Make | VehAPI Name | vPIC Name | Schemas (2022+) | Status | +|------|-------------|-----------|-----------------|--------| +| Buick | Buick | Buick | 20 | Ready | +| Cadillac | Cadillac | Cadillac | 50 | Ready | +| Chevrolet | Chevrolet | Chevrolet | 185 | Ready | +| GMC | GMC | GMC | 107 | Ready | +| Oldsmobile | Oldsmobile | Oldsmobile | 1 | Limited | +| Pontiac | Pontiac | Pontiac | 5 | Limited (2022-2024) | + +### Group 4: American - Stellantis (Chrysler, Dodge, Jeep, Ram, Fiat) + +| Make | VehAPI Name | vPIC Name | Schemas (2022+) | Status | +|------|-------------|-----------|-----------------|--------| +| Chrysler | Chrysler | Chrysler | 81 | Ready | +| Dodge | Dodge | Dodge | 86 | Ready | +| FIAT | FIAT | Fiat | 91 | Ready (case diff) | +| Jeep | Jeep | Jeep | 81 | Ready | +| RAM | RAM | Ram | 81 | Ready (case diff) | +| Plymouth | Plymouth | Plymouth | 4 | Limited | + +### Group 5: American - Ford + +| Make | VehAPI Name | vPIC Name | Schemas (2022+) | Status | +|------|-------------|-----------|-----------------|--------| +| Ford | Ford | Ford | 108 | Ready | +| Lincoln | Lincoln | Lincoln | 21 | Ready | +| Mercury | Mercury | Mercury | 0 | No data (discontinued 2011) | + +### Group 6: American - EV Startups + +| Make | VehAPI Name | vPIC Name | Schemas (2022+) | Status | +|------|-------------|-----------|-----------------|--------| +| Polestar | Polestar | Polestar | 12 | Ready | +| Rivian | Rivian | RIVIAN | 10 | Ready (case diff) | +| Tesla | Tesla | Tesla | 14 | Ready | + +### Group 7: German Manufacturers + +| Make | VehAPI Name | vPIC Name | Schemas (2022+) | Status | +|------|-------------|-----------|-----------------|--------| +| Audi | Audi | Audi | 55 | Ready | +| BMW | BMW | BMW | 61 | Ready | +| Mercedes-Benz | Mercedes-Benz | Mercedes-Benz | 39 | Ready | +| MINI | MINI | MINI | 10 | Ready | +| Porsche | Porsche | Porsche | 23 | Ready | +| smart | smart | smart | 5 | Ready | +| Volkswagen | Volkswagen | Volkswagen | 134 | Ready | + +### Group 8: European Luxury + +| Make | VehAPI Name | vPIC Name | Schemas (2022+) | Status | +|------|-------------|-----------|-----------------|--------| +| Bentley | Bentley | Bentley | 48 | Ready | +| Ferrari | Ferrari | Ferrari | 9 | Ready | +| Jaguar | Jaguar | Jaguar | 17 | Ready | +| Lamborghini | Lamborghini | Lamborghini | 10 | Ready | +| Lotus | Lotus | Lotus | 5 | Ready | +| Maserati | Maserati | Maserati | 19 | Ready | +| McLaren | McLaren | McLaren | 4 | Ready | +| Volvo | Volvo | Volvo | 80 | Ready | + +### Group 9: Discontinued (No 2022+ Data) + +| Make | VehAPI Name | Reason | Action | +|------|-------------|--------|--------| +| Hummer | Hummer | Discontinued 2010 (new EV under GMC) | Skip - use existing VehAPI | +| Scion | Scion | Discontinued 2016 | Skip - use existing VehAPI | +| Saab | Saab | Discontinued 2012 | Limited schemas (9) | +| Mercury | Mercury | Discontinued 2011 | No schemas | + +--- + +## Extraction Architecture + +### Data Flow +``` +vPIC VIN Schemas → Pattern Extraction → Format Transformation → SQLite Pairs + ↓ + Filter by: + - 48 VehAPI makes only + - Year >= 2022 + - Vehicle types (exclude motorcycles, trailers, buses) +``` + +### Core Query Strategy + +For each allowed make: +1. Find WMIs linked to that make +2. Get VIN schemas for years 2022+ +3. Extract from patterns: + - Model (from schema name or pattern) + - Trim (Element: Trim) + - Displacement (Element: DisplacementL) + - Horsepower (Element: EngineHP) + - Cylinders (Element: EngineCylinders) + - Engine Config (Element: EngineConfiguration) + - Transmission Style (Element: TransmissionStyle) + - Transmission Speeds (Element: TransmissionSpeeds) + +--- + +## Acura Extraction Template + +This pattern applies to Honda/Acura and similar well-structured manufacturers. + +### Sample VIN Schema: Acura MDX 2025 (schema_id: 26929) + +| Element | Code | Values | +|---------|------|--------| +| Trim | Trim | MDX, Technology, SH-AWD, SH-AWD Technology, SH-AWD A-Spec, SH-AWD Advance, SH-AWD A-Spec Advance, SH-AWD TYPE S ADVANCE | +| Displacement | DisplacementL | 3.5, 3.0 | +| Horsepower | EngineHP | 290, 355 | +| Cylinders | EngineCylinders | 6 | +| Engine Config | EngineConfiguration | V-Shaped | +| Trans Style | TransmissionStyle | Automatic | +| Trans Speeds | TransmissionSpeeds | 10 | + +### Output Format + +**Engine Display** (match VehAPI): +``` +{DisplacementL}L {EngineHP} hp V{EngineCylinders} +→ "3.5L 290 hp V6" +``` + +**Transmission Display** (match VehAPI): +``` +{TransmissionSpeeds}-Speed {TransmissionStyle} +→ "10-Speed Automatic" +``` + +### Extraction SQL Template + +```sql +WITH schema_data AS ( + SELECT DISTINCT + vs.id AS schema_id, + vs.name AS schema_name, + wvs.yearfrom, + COALESCE(wvs.yearto, 2027) AS yearto, + m.name AS make_name + FROM vpic.wmi w + JOIN vpic.make m ON w.makeid = m.id + JOIN vpic.wmi_vinschema wvs ON w.id = wvs.wmiid + JOIN vpic.vinschema vs ON wvs.vinschemaid = vs.id + WHERE LOWER(m.name) IN ('acura', 'honda', ...) -- VehAPI makes + AND wvs.yearfrom >= 2022 OR (wvs.yearto >= 2022) +), +trim_data AS ( + SELECT DISTINCT sd.schema_id, p.attributeid AS trim + FROM schema_data sd + JOIN vpic.pattern p ON p.vinschemaid = sd.schema_id + JOIN vpic.element e ON p.elementid = e.id + WHERE e.code = 'Trim' +), +engine_data AS ( + SELECT DISTINCT + sd.schema_id, + MAX(CASE WHEN e.code = 'DisplacementL' THEN p.attributeid END) AS displacement, + MAX(CASE WHEN e.code = 'EngineHP' THEN p.attributeid END) AS hp, + MAX(CASE WHEN e.code = 'EngineCylinders' THEN p.attributeid END) AS cylinders, + MAX(CASE WHEN e.code = 'EngineConfiguration' THEN ec.name END) AS config + FROM schema_data sd + JOIN vpic.pattern p ON p.vinschemaid = sd.schema_id + JOIN vpic.element e ON p.elementid = e.id + LEFT JOIN vpic.engineconfiguration ec ON e.code = 'EngineConfiguration' + AND p.attributeid ~ '^[0-9]+$' AND ec.id = CAST(p.attributeid AS INT) + WHERE e.code IN ('DisplacementL', 'EngineHP', 'EngineCylinders', 'EngineConfiguration') + GROUP BY sd.schema_id, p.keys -- Group by VIN pattern position +), +trans_data AS ( + SELECT DISTINCT + sd.schema_id, + t.name AS style, + MAX(CASE WHEN e.code = 'TransmissionSpeeds' THEN p.attributeid END) AS speeds + FROM schema_data sd + JOIN vpic.pattern p ON p.vinschemaid = sd.schema_id + JOIN vpic.element e ON p.elementid = e.id + LEFT JOIN vpic.transmission t ON e.code = 'TransmissionStyle' + AND p.attributeid ~ '^[0-9]+$' AND t.id = CAST(p.attributeid AS INT) + WHERE e.code IN ('TransmissionStyle', 'TransmissionSpeeds') + GROUP BY sd.schema_id, t.name +) +SELECT ... +``` + +--- + +## Allowed Makes (48 from VehAPI) + +```python +ALLOWED_MAKES = [ + 'Acura', 'Audi', 'Bentley', 'BMW', 'Buick', 'Cadillac', 'Chevrolet', + 'Chrysler', 'Dodge', 'Ferrari', 'FIAT', 'Ford', 'Genesis', 'GMC', + 'Honda', 'Hummer', 'Hyundai', 'INFINITI', 'Isuzu', 'Jaguar', 'Jeep', + 'Kia', 'Lamborghini', 'Lexus', 'Lincoln', 'Lotus', 'Maserati', 'Mazda', + 'McLaren', 'Mercedes-Benz', 'Mercury', 'MINI', 'Mitsubishi', 'Nissan', + 'Oldsmobile', 'Plymouth', 'Polestar', 'Pontiac', 'Porsche', 'RAM', + 'Rivian', 'Saab', 'Scion', 'smart', 'Subaru', 'Tesla', 'Toyota', + 'Volkswagen', 'Volvo' +] +``` + +Note: Some makes may have different names in vPIC (case variations, abbreviations). + +--- + +## Implementation Steps + +### Phase 1: Rewrite vpic_extract.py + +**File:** `vpic_extract.py` + +Core extraction query (uses wmi_make junction table): +```sql +WITH base AS ( + SELECT DISTINCT + m.name AS make_name, + vs.id AS schema_id, + vs.name AS schema_name, + generate_series( + GREATEST(wvs.yearfrom, 2022), + COALESCE(wvs.yearto, EXTRACT(YEAR FROM NOW()) + 2) + )::INT AS year + FROM vpic.make m + JOIN vpic.wmi_make wm ON wm.makeid = m.id + JOIN vpic.wmi w ON w.id = wm.wmiid + JOIN vpic.wmi_vinschema wvs ON w.id = wvs.wmiid + JOIN vpic.vinschema vs ON wvs.vinschemaid = vs.id + WHERE LOWER(m.name) IN ({allowed_makes}) + AND (wvs.yearfrom >= 2022 OR wvs.yearto >= 2022) +) +SELECT ... +``` + +**Key functions to implement:** +1. `extract_model_from_schema_name(schema_name)` - Parse "Acura MDX Schema..." → "MDX" +2. `get_schema_patterns(schema_id)` - Get all pattern data for a schema +3. `format_engine_display(disp, hp, cyl, config)` - Format as "3.5L 290 hp V6" +4. `format_trans_display(style, speeds)` - Format as "10-Speed Automatic" +5. `generate_trans_records(has_data, style, speeds)` - Return 1 or 2 records + +**Make name normalization:** +```python +MAKE_MAPPING = { + 'INFINITI': 'INFINITI', # VehAPI uses all-caps + 'FIAT': 'FIAT', + 'RAM': 'RAM', + 'RIVIAN': 'Rivian', # vPIC uses all-caps, normalize + # ... etc +} +``` + +### Phase 2: Test Extraction + +Test with validated VINs: +```bash +source .venv/bin/activate +python3 vpic_extract.py --test-vin 5J8YE1H05SL018611 # Acura MDX +python3 vpic_extract.py --test-vin 5TFJA5DB4SX327537 # Toyota Tundra +python3 vpic_extract.py --test-vin 3GTUUFEL6PG140748 # GMC Sierra +``` + +### Phase 3: Full Extraction + +```bash +python3 vpic_extract.py --min-year 2022 --output-dir snapshots/vpic-2025-12 +``` + +### Phase 4: Merge & Import + +```bash +# Merge vPIC with existing VehAPI data +sqlite3 snapshots/merged/snapshot.sqlite " +CREATE TABLE pairs(...); +ATTACH 'snapshots/vehicle-drop-down.sqlite' AS db1; +ATTACH 'snapshots/vpic-2025-12/snapshot.sqlite' AS db2; +INSERT OR IGNORE INTO pairs SELECT * FROM db1.pairs WHERE year < 2022; +INSERT OR IGNORE INTO pairs SELECT * FROM db2.pairs; +" + +# Generate SQL and import +python3 etl_generate_sql.py --snapshot-path snapshots/merged/snapshot.sqlite +./import_data.sh +``` + +--- + +## Files to Modify + +| File | Changes | +|------|---------| +| `vpic_extract.py` | Complete rewrite: VIN schema extraction, dual-record trans logic | +| `README.md` | Already updated with workflow | + +--- + +## Success Criteria + +1. Extract all 41 makes with 2022+ VIN schemas +2. ~2,500-5,000 unique vehicle configurations (Year/Make/Model/Trim/Engine) +3. Transmission: Use vPIC data where available (7 makes), dual-record elsewhere +4. Output format matches VehAPI: "3.5L 290 hp V6" / "10-Speed Automatic" +5. Merge preserves 2015-2021 VehAPI data +6. QA validation passes after import + +--- + +## Make Analysis Status (All Families Validated) + +| Family | Makes | Status | Trans Data | Strategy | +|--------|-------|--------|------------|----------| +| Honda/Acura | Acura, Honda | VALIDATED | YES (93-97%) | Use vPIC trans data | +| Toyota/Lexus | Toyota, Lexus | VALIDATED | PARTIAL (Toyota 23%, Lexus 0%) | Dual-record for Lexus | +| Nissan/Infiniti | Nissan, Infiniti, Mitsubishi | VALIDATED | LOW (5%) | Dual-record | +| GM | Chevrolet, GMC, Buick, Cadillac | VALIDATED | LOW (0-7%) | Dual-record | +| Stellantis | Chrysler, Dodge, Jeep, Ram, Fiat | VALIDATED | NONE (0%) | Dual-record | +| Ford | Ford, Lincoln | VALIDATED | NONE (0%) | Dual-record | +| VW Group | Volkswagen, Audi, Porsche, Bentley, Lamborghini | VALIDATED | MIXED (0-84%) | VW/Audi use vPIC; others dual-record | +| BMW | BMW, MINI | VALIDATED | NONE (0%) | Dual-record | +| Mercedes | Mercedes-Benz, smart | VALIDATED | YES (52%) | Use vPIC trans data | +| Hyundai/Kia/Genesis | Hyundai, Kia, Genesis | VALIDATED | NONE (0%) | Dual-record | +| Subaru | Subaru | VALIDATED | YES (64%) | Use vPIC trans data | +| Mazda | Mazda | VALIDATED | LOW (11%) | Dual-record | +| Volvo | Volvo, Polestar | VALIDATED | LOW (3%/0%) | Dual-record | +| Exotics | Ferrari, Maserati, Jaguar, Lotus, McLaren | VALIDATED | MIXED | Per-make handling | +| EV | Tesla, Rivian | VALIDATED | NONE (0%) | Dual-record (though EVs don't have "manual") | + +### Special Cases + +1. **Electric Vehicles** (Tesla, Rivian, Polestar): Don't have manual transmissions + - Still create dual-record for consistency with dropdown + - User can select "Automatic" (single-speed EV) + +2. **Luxury Exotics** (Ferrari, Lamborghini, etc.): Mix of automated manual/DCT + - Dual-record covers all options + +--- + +## CRITICAL FINDING: Transmission Data Availability + +**Most manufacturers do NOT encode transmission info in VINs.** + +### VIN Decode Validation Results (12 Families) + +| Family | VIN | Make | Model | Year | Trim | Engine | Trans | +|--------|-----|------|-------|------|------|--------|-------| +| Honda/Acura | 5J8YE1H05SL018611 | ACURA | MDX | 2025 | SH-AWD A-Spec | 3.5L V6 290hp | 10-Spd Auto | +| Honda/Acura | 2HGFE4F88SH315466 | HONDA | Civic | 2025 | Sport Hybrid | 2.0L I4 141hp | e-CVT | +| Toyota/Lexus | 5TFJA5DB4SX327537 | TOYOTA | Tundra | 2025 | Limited | 3.4L V6 389hp | 10-Spd Auto | +| Nissan/Infiniti | 5N1AL1FW9TC332353 | INFINITI | QX60 | 2026 | Luxe | 2.0L (no cyl/hp) | **MISSING** | +| GM | 3GTUUFEL6PG140748 | GMC | Sierra | 2023 | AT4X | 6.2L V8 (no hp) | **MISSING** | +| Stellantis | 1C4HJXEG7PW506480 | JEEP | Wrangler | 2023 | Sahara | 3.6L V6 285hp | **MISSING** | +| Ford | 1FTFW4L59SFC03038 | FORD | F-150 | 2025 | Tremor | 5.0L V8 (no hp) | **MISSING** | +| VW Group | WVWEB7CD9RW229116 | VOLKSWAGEN | Golf R | 2024 | **MISSING** | 2.0L 4cyl 315hp | Auto (no spd) | +| BMW | 5YM13ET06R9S31554 | BMW | X5 | 2024 | X5 M Competition | 4.4L 8cyl 617hp | **MISSING** | +| Mercedes | W1KAF4HB1SR287126 | MERCEDES-BENZ | C-Class | 2025 | C300 4MATIC | 2.0L I4 255hp | 9-Spd Auto | +| Hyundai/Kia | 5XYRLDJC0SG336002 | KIA | Sorento | 2025 | S | 2.5L 4cyl 191hp | **MISSING** | +| Subaru | JF1VBAF67P9806852 | SUBARU | WRX | 2023 | Premium | 2.4L 4cyl 271hp | 6-Spd Manual | +| Mazda | JM3KFBCL3R0522361 | MAZDA | CX-5 | 2024 | Preferred Pkg | 2.5L I4 187hp | 6-Spd Auto | +| Volvo | YV4M12RJ9S1094167 | VOLVO | XC60 | 2025 | Core | 2.0L 4cyl 247hp | 8-Spd Auto | + +### Transmission Data Coverage in vPIC Schemas + +| Coverage | Makes | Trans Schemas / Total | +|----------|-------|----------------------| +| **HIGH (>40%)** | Honda, Acura, Subaru, Audi, VW, Mercedes, Jaguar | 225/233, 42/45, 47/74, 46/55, 47/132, 13/25, 17/17 | +| **LOW (<10%)** | Chevrolet, Cadillac, Nissan, Infiniti, Mazda, Volvo | 4/164, 7/43, 4/82, 4/74, 4/36, 2/72 | +| **NONE (0%)** | GMC, Buick, Ford, Lincoln, Jeep, Dodge, Chrysler, Ram, Fiat, BMW, MINI, Porsche, Hyundai, Kia, Genesis, Lexus, Tesla, Rivian, Polestar | 0% | + +### Makes WITHOUT Transmission Data (22 of 41 makes = 54%) +- **ALL Stellantis**: Chrysler, Dodge, Jeep, Ram, Fiat +- **ALL Ford**: Ford, Lincoln +- **ALL Korean**: Hyundai, Kia, Genesis +- **ALL BMW Group**: BMW, MINI +- **GM (partial)**: GMC, Buick (Chevy/Cadillac have minimal) +- **Others**: Lexus, Porsche, Bentley, Lamborghini, Tesla, Rivian, Polestar + +--- + +## Extraction Strategy (SELECTED) + +### Dual-Record Strategy for Missing Transmission Data + +When transmission data is NOT available from vPIC: +- **Create TWO records** for each vehicle configuration +- One with `trans_display = "Automatic"`, `trans_canon = "automatic"` +- One with `trans_display = "Manual"`, `trans_canon = "manual"` + +This ensures: +- All transmission options available in dropdown for user selection +- User can select the correct transmission type +- No false "Unknown" values that break filtering + +### Implementation Logic + +```python +def generate_trans_records(has_trans_data: bool, trans_style: str, trans_speeds: str): + if has_trans_data: + # Use actual vPIC data + return [(format_trans_display(trans_style, trans_speeds), + canonicalize_trans(trans_style))] + else: + # Generate both options + return [ + ("Automatic", "automatic"), + ("Manual", "manual") + ] +``` + +### Expected Output Growth + +For makes without trans data, record count approximately doubles: +- GMC Sierra AT4X + 6.2L V8 → 2 records (Auto + Manual) +- Ford F-150 Tremor + 5.0L V8 → 2 records (Auto + Manual) + +This is acceptable as it provides complete dropdown coverage. + +--- + +## Validated Extraction Examples + +### Acura MDX 2025 (VIN: 5J8YE1H05SL018611) +- **vPIC**: Make=ACURA, Model=MDX, Trim=SH-AWD A-Spec, Engine=3.5L V6 290hp, Trans=10-Speed Automatic +- **Output**: `3.5L 290 hp V6` | `10-Speed Automatic` + +### Honda Civic 2025 (VIN: 2HGFE4F88SH315466) +- **vPIC**: Make=HONDA, Model=Civic, Trim=Sport Hybrid / Sport Touring Hybrid, Engine=2L I4 141hp, Trans=e-CVT +- **Output**: `2.0L 141 hp I4` | `Electronic Continuously Variable (e-CVT)` + +### Toyota Tundra 2025 (VIN: 5TFJA5DB4SX327537) +- **vPIC**: Make=TOYOTA, Model=Tundra, Trim=Limited, Engine=3.4L V6 389hp, Trans=10-Speed Automatic +- **Output**: `3.4L 389 hp V6` | `10-Speed Automatic` + +### Mercedes C-Class 2025 (VIN: W1KAF4HB1SR287126) +- **vPIC**: Make=MERCEDES-BENZ, Model=C-Class, Trim=C300 4MATIC, Engine=2.0L I4 255hp, Trans=9-Speed Automatic +- **Output**: `2.0L 255 hp I4` | `9-Speed Automatic` + +### Subaru WRX 2023 (VIN: JF1VBAF67P9806852) +- **vPIC**: Make=SUBARU, Model=WRX, Trim=Premium, Engine=2.4L 4cyl 271hp, Trans=6-Speed Manual +- **Output**: `2.4L 271 hp 4cyl` | `6-Speed Manual` + +### Mazda CX-5 2024 (VIN: JM3KFBCL3R0522361) +- **vPIC**: Make=MAZDA, Model=CX-5, Trim=Preferred Package, Engine=2.5L I4 187hp, Trans=6-Speed Automatic +- **Output**: `2.5L 187 hp I4` | `6-Speed Automatic` + +### Volvo XC60 2025 (VIN: YV4M12RJ9S1094167) +- **vPIC**: Make=VOLVO, Model=XC60, Trim=Core, Engine=2.0L 4cyl 247hp, Trans=8-Speed Automatic +- **Output**: `2.0L 247 hp 4cyl` | `8-Speed Automatic` diff --git a/docs/PROMPTS.md b/docs/PROMPTS.md index 2025dfb..f917178 100644 --- a/docs/PROMPTS.md +++ b/docs/PROMPTS.md @@ -19,18 +19,17 @@ comprehensive spec.md - containing requirements, architecture decisions, data mo You are a senior software engineer specializsing in NodeJS, Typescript, front end and back end development. You will be delegating tasks to the platform-agent, feature-agent, first-frontend-agent and quality-agent when appropriate. *** ACTION *** -- You will be fixing a workflow logic in the new user sign up wizard. - Make no assumptions. - Ask clarifying questions. - Ultrathink +- You will be removing functionality that was never implemented. *** CONTEXT *** - This is a modern web app for managing a vehicle fleet. It has both a desktop and mobile versions of the site that both need to maintain feature parity. It's currently deployed via docker compose but in the future will be deployed via k8s. - Read README.md CLAUDE.md and AI-INDEX.md and follow relevant instructions to understand this code repository in the context of this change. -- When a new user signs up, they are immediately redirected to https://motovaultpro.com/verify-email which is supposed to send them through a new user wizard. -- The user is also allowed to login before the email is confirmed. There are API errors but the login is allowed. -- It should not even let people login without a verified email. -- The new user wizard exists. It worked in the past. Recent user changes must have broken the workflow. +- There is a "station management" section for admin users that was never implemented and needs to be removed. +- The route is located at https://motovaultpro.com/garage/settings/admin/stations +- Remove the front end and any associated routes or logic in the code. *** CHANGES TO IMPLEMENT *** - Research this code base and ask iterative questions to compile a complete plan. @@ -52,4 +51,31 @@ You are a senior software engineer specializsing in NodeJS, Typescript, front en - The secrets architecture is based of a future state of being deployed into k8s. Right now it's in docker compose with files that are copied in via the pipeline. *** ACTION - CHANGES TO IMPLEMENT *** -- Replicate the same secrets process that's implemented with the Google API and Auth0 API keys. \ No newline at end of file +- Replicate the same secrets process that's implemented with the Google API and Auth0 API keys. + + + +*** ROLE *** +- You are a senior DBA with expert knowledge in Postgres SQL. + +*** ACTION *** +- Make no assumptions. +- Ask clarifying questions. +- Ultrathink +- You will be implementing an ETL process that takes a export of the NHTSA vPIC database in Postgres and transforming it for use in this application. + +*** CONTEXT *** +- This is a modern web app for managing a vehicle fleet. It has both a desktop and mobile versions of the site that both need to maintain feature parity. It's currently deployed via docker compose but in the future will be deployed via k8s. +- Read README.md CLAUDE.md and AI-INDEX.md and follow relevant instructions to understand this code repository in the context of this change. +- There is an existing database import process in this directory. This process works and should not be changed. +- The source database from the NHTSA vPIC dataset is located in the @vpic-source directory +- Deep research needs to be conducted on how to execute this ETL process. +- The source database is designed for VIN decoding only. +- Example VIN: 2025 Honda Civic Hybrid - 2HGFE4F88SH315466 +- Example VIN: 2023 GMC Sierra 1500 AT4x - 3GTUUFEL6PG140748 +- Example VIN: 2017 Chevrolet Corvette Z06 - 1G1YU3D64H5602799 + +*** CHANGES TO IMPLEMENT *** +- Research this code base and ask iterative questions to compile a complete plan. +- generate a project plan +- break into bite-sized tasks and milestones \ No newline at end of file diff --git a/frontend/src/core/units/UnitsContext.tsx b/frontend/src/core/units/UnitsContext.tsx index 56e7637..286c26a 100644 --- a/frontend/src/core/units/UnitsContext.tsx +++ b/frontend/src/core/units/UnitsContext.tsx @@ -1,9 +1,9 @@ /** - * @ai-summary React context for unit system preferences - * @ai-context Provides unit preferences and conversion functions throughout the app + * @ai-summary React context for unit system preferences with backend sync + * @ai-context Provides unit preferences, conversion functions, and currency symbol throughout the app */ -import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react'; +import React, { createContext, useContext, useState, useEffect, useCallback, ReactNode } from 'react'; import { UnitSystem, UnitPreferences } from './units.types'; import { safeStorage } from '../utils/safe-storage'; import { @@ -18,22 +18,27 @@ import { getVolumeUnit, getFuelEfficiencyUnit } from './units.utils'; +import { usePreferences, useUpdatePreferences } from '../../features/settings/hooks/usePreferences'; +import { useAuth0 } from '@auth0/auth0-react'; interface UnitsContextType { unitSystem: UnitSystem; setUnitSystem: (system: UnitSystem) => void; preferences: UnitPreferences; - + currencySymbol: string; + currencyCode: string; + isLoading: boolean; + // Conversion functions convertDistance: (miles: number) => number; convertVolume: (gallons: number) => number; convertFuelEfficiency: (mpg: number) => number; - + // Formatting functions formatDistance: (miles: number, precision?: number) => string; formatVolume: (gallons: number, precision?: number) => string; formatFuelEfficiency: (mpg: number, precision?: number) => string; - formatPrice: (pricePerGallon: number, currency?: string, precision?: number) => string; + formatPrice: (pricePerGallon: number, precision?: number) => string; } const UnitsContext = createContext(undefined); @@ -43,34 +48,78 @@ interface UnitsProviderProps { initialSystem?: UnitSystem; } -export const UnitsProvider: React.FC = ({ - children, - initialSystem = 'imperial' -}) => { - const [unitSystem, setUnitSystem] = useState(initialSystem); - - // Load unit preference from storage on mount - useEffect(() => { - try { - const stored = safeStorage.getItem('motovaultpro-unit-system'); - if (stored === 'imperial' || stored === 'metric') { - setUnitSystem(stored); - } - } catch (error) { - console.warn('[Units] Failed to load unit system preference:', error); - } - }, []); +// Currency symbol mapping +const getCurrencySymbol = (system: UnitSystem): string => { + return system === 'metric' ? '\u20AC' : '$'; // EUR or USD +}; - // Save unit preference to storage when changed - const handleSetUnitSystem = (system: UnitSystem) => { - setUnitSystem(system); +const getCurrencyCode = (system: UnitSystem): string => { + return system === 'metric' ? 'EUR' : 'USD'; +}; + +export const UnitsProvider: React.FC = ({ + children, + initialSystem = 'imperial' +}) => { + const [unitSystem, setUnitSystemState] = useState(initialSystem); + const [hasInitialized, setHasInitialized] = useState(false); + + const { isAuthenticated } = useAuth0(); + const { data: backendPreferences, isLoading: preferencesLoading } = usePreferences(); + const updatePreferencesMutation = useUpdatePreferences(); + + // Load unit preference from localStorage on mount (fallback) + useEffect(() => { + if (!hasInitialized) { + try { + const stored = safeStorage.getItem('motovaultpro-unit-system'); + if (stored === 'imperial' || stored === 'metric') { + setUnitSystemState(stored); + } + } catch (error) { + console.warn('[Units] Failed to load unit system preference from storage:', error); + } + } + }, [hasInitialized]); + + // Sync with backend preferences when they load (takes priority over localStorage) + useEffect(() => { + if (backendPreferences?.unitSystem && !hasInitialized) { + setUnitSystemState(backendPreferences.unitSystem); + // Also update localStorage to keep them in sync + try { + safeStorage.setItem('motovaultpro-unit-system', backendPreferences.unitSystem); + } catch (error) { + console.warn('[Units] Failed to sync unit system to storage:', error); + } + setHasInitialized(true); + } + }, [backendPreferences, hasInitialized]); + + // Mark as initialized when not authenticated (localStorage is the source of truth) + useEffect(() => { + if (!isAuthenticated && !hasInitialized) { + setHasInitialized(true); + } + }, [isAuthenticated, hasInitialized]); + + // Handle unit system change with backend sync + const handleSetUnitSystem = useCallback((system: UnitSystem) => { + setUnitSystemState(system); + + // Always save to localStorage (offline fallback) try { safeStorage.setItem('motovaultpro-unit-system', system); } catch (error) { console.warn('[Units] Failed to save unit system preference:', error); } - }; - + + // Sync to backend if authenticated + if (isAuthenticated) { + updatePreferencesMutation.mutate({ unitSystem: system }); + } + }, [isAuthenticated, updatePreferencesMutation]); + // Generate preferences object based on current system const preferences: UnitPreferences = { system: unitSystem, @@ -78,29 +127,36 @@ export const UnitsProvider: React.FC = ({ volume: getVolumeUnit(unitSystem), fuelEfficiency: getFuelEfficiencyUnit(unitSystem), }; - + + // Currency based on unit system + const currencySymbol = getCurrencySymbol(unitSystem); + const currencyCode = getCurrencyCode(unitSystem); + // Conversion functions using current unit system - const convertDistance = (miles: number) => convertDistanceBySystem(miles, unitSystem); - const convertVolume = (gallons: number) => convertVolumeBySystem(gallons, unitSystem); - const convertFuelEfficiency = (mpg: number) => convertFuelEfficiencyBySystem(mpg, unitSystem); - + const convertDistance = useCallback((miles: number) => convertDistanceBySystem(miles, unitSystem), [unitSystem]); + const convertVolume = useCallback((gallons: number) => convertVolumeBySystem(gallons, unitSystem), [unitSystem]); + const convertFuelEfficiency = useCallback((mpg: number) => convertFuelEfficiencyBySystem(mpg, unitSystem), [unitSystem]); + // Formatting functions using current unit system - const formatDistance = (miles: number, precision?: number) => - formatDistanceBySystem(miles, unitSystem, precision); - - const formatVolume = (gallons: number, precision?: number) => - formatVolumeBySystem(gallons, unitSystem, precision); - - const formatFuelEfficiency = (mpg: number, precision?: number) => - formatFuelEfficiencyBySystem(mpg, unitSystem, precision); - - const formatPrice = (pricePerGallon: number, currency?: string, precision?: number) => - formatPriceBySystem(pricePerGallon, unitSystem, currency, precision); + const formatDistance = useCallback((miles: number, precision?: number) => + formatDistanceBySystem(miles, unitSystem, precision), [unitSystem]); + + const formatVolume = useCallback((gallons: number, precision?: number) => + formatVolumeBySystem(gallons, unitSystem, precision), [unitSystem]); + + const formatFuelEfficiency = useCallback((mpg: number, precision?: number) => + formatFuelEfficiencyBySystem(mpg, unitSystem, precision), [unitSystem]); + + const formatPrice = useCallback((pricePerGallon: number, precision?: number) => + formatPriceBySystem(pricePerGallon, unitSystem, currencyCode, precision), [unitSystem, currencyCode]); const value: UnitsContextType = { unitSystem, setUnitSystem: handleSetUnitSystem, preferences, + currencySymbol, + currencyCode, + isLoading: preferencesLoading && isAuthenticated, convertDistance, convertVolume, convertFuelEfficiency, @@ -123,4 +179,4 @@ export const useUnits = (): UnitsContextType => { throw new Error('useUnits must be used within a UnitsProvider'); } return context; -}; \ No newline at end of file +}; diff --git a/frontend/src/core/units/units.types.ts b/frontend/src/core/units/units.types.ts index 6e7b877..62ee74a 100644 --- a/frontend/src/core/units/units.types.ts +++ b/frontend/src/core/units/units.types.ts @@ -6,7 +6,7 @@ export type UnitSystem = 'imperial' | 'metric'; export type DistanceUnit = 'miles' | 'km'; export type VolumeUnit = 'gallons' | 'liters'; -export type FuelEfficiencyUnit = 'mpg' | 'kml'; +export type FuelEfficiencyUnit = 'mpg' | 'l100km'; export interface UnitPreferences { system: UnitSystem; diff --git a/frontend/src/core/units/units.utils.ts b/frontend/src/core/units/units.utils.ts index 84d02f8..62ff90b 100644 --- a/frontend/src/core/units/units.utils.ts +++ b/frontend/src/core/units/units.utils.ts @@ -10,9 +10,8 @@ const MILES_TO_KM = 1.60934; const KM_TO_MILES = 0.621371; const GALLONS_TO_LITERS = 3.78541; const LITERS_TO_GALLONS = 0.264172; -// For km/L conversion -const MPG_TO_KML = 1.60934 / 3.78541; // ≈ 0.425144 -const KML_TO_MPG = 3.78541 / 1.60934; // ≈ 2.352145 +// For L/100km conversion (inverse relationship: lower L/100km = better efficiency) +const MPG_TO_L100KM_FACTOR = 235.214; // Distance Conversions export function convertDistance(value: number, fromUnit: DistanceUnit, toUnit: DistanceUnit): number { @@ -58,24 +57,24 @@ export function convertVolumeBySystem(gallons: number, toSystem: UnitSystem): nu return gallons; } -// Fuel Efficiency Conversions +// Fuel Efficiency Conversions (L/100km is inverse: lower = better) export function convertFuelEfficiency(value: number, fromUnit: FuelEfficiencyUnit, toUnit: FuelEfficiencyUnit): number { if (fromUnit === toUnit) return value; - - if (fromUnit === 'mpg' && toUnit === 'kml') { - return value * MPG_TO_KML; + + if (fromUnit === 'mpg' && toUnit === 'l100km') { + return value === 0 ? 0 : MPG_TO_L100KM_FACTOR / value; } - if (fromUnit === 'kml' && toUnit === 'mpg') { - return value * KML_TO_MPG; + if (fromUnit === 'l100km' && toUnit === 'mpg') { + return value === 0 ? 0 : MPG_TO_L100KM_FACTOR / value; } - + return value; } export function convertFuelEfficiencyBySystem(mpg: number, toSystem: UnitSystem): number { if (toSystem === 'metric') { - return convertFuelEfficiency(mpg, 'mpg', 'kml'); + return convertFuelEfficiency(mpg, 'mpg', 'l100km'); } return mpg; } @@ -111,15 +110,15 @@ export function formatVolume(value: number, unit: VolumeUnit, precision = 2): st export function formatFuelEfficiency(value: number, unit: FuelEfficiencyUnit, precision = 1): string { if (typeof value !== 'number' || isNaN(value)) { - return unit === 'mpg' ? '0 MPG' : '0 km/L'; + return unit === 'mpg' ? '0 MPG' : '0 L/100km'; } - + const rounded = parseFloat(value.toFixed(precision)); - + if (unit === 'mpg') { return `${rounded} MPG`; } else { - return `${rounded} km/L`; + return `${rounded} L/100km`; } } @@ -168,8 +167,8 @@ export function formatVolumeBySystem(gallons: number, system: UnitSystem, precis export function formatFuelEfficiencyBySystem(mpg: number, system: UnitSystem, precision = 1): string { if (system === 'metric') { - const kml = convertFuelEfficiencyBySystem(mpg, system); - return formatFuelEfficiency(kml, 'kml', precision); + const l100km = convertFuelEfficiencyBySystem(mpg, system); + return formatFuelEfficiency(l100km, 'l100km', precision); } return formatFuelEfficiency(mpg, 'mpg', precision); } @@ -192,5 +191,5 @@ export function getVolumeUnit(system: UnitSystem): VolumeUnit { } export function getFuelEfficiencyUnit(system: UnitSystem): FuelEfficiencyUnit { - return system === 'metric' ? 'kml' : 'mpg'; + return system === 'metric' ? 'l100km' : 'mpg'; } diff --git a/frontend/src/features/admin/hooks/useCatalog.ts b/frontend/src/features/admin/hooks/useCatalog.ts index 42403ee..9fd185c 100644 --- a/frontend/src/features/admin/hooks/useCatalog.ts +++ b/frontend/src/features/admin/hooks/useCatalog.ts @@ -350,7 +350,7 @@ export const useImportApply = () => { onSuccess: (result) => { queryClient.invalidateQueries({ queryKey: ['catalogSearch'] }); toast.success( - `Import completed: ${result.created} created, ${result.updated} updated, ${result.deleted} deleted` + `Import completed: ${result.created} created, ${result.updated} updated` ); }, onError: (error: ApiError) => { diff --git a/frontend/src/features/admin/mobile/AdminCatalogMobileScreen.tsx b/frontend/src/features/admin/mobile/AdminCatalogMobileScreen.tsx index 5a53e62..57f0bf7 100644 --- a/frontend/src/features/admin/mobile/AdminCatalogMobileScreen.tsx +++ b/frontend/src/features/admin/mobile/AdminCatalogMobileScreen.tsx @@ -462,9 +462,6 @@ export const AdminCatalogMobileScreen: React.FC = () => {
{importPreview.toUpdate.length} to update
-
- {importPreview.toDelete.length} to delete -
{/* Errors */} diff --git a/frontend/src/features/admin/types/admin.types.ts b/frontend/src/features/admin/types/admin.types.ts index abc9a80..34ddfce 100644 --- a/frontend/src/features/admin/types/admin.types.ts +++ b/frontend/src/features/admin/types/admin.types.ts @@ -181,7 +181,6 @@ export interface CatalogSearchResponse { // Catalog import types export interface ImportRow { - action: 'add' | 'update' | 'delete'; year: number; make: string; model: string; @@ -199,7 +198,6 @@ export interface ImportPreviewResult { previewId: string; toCreate: ImportRow[]; toUpdate: ImportRow[]; - toDelete: ImportRow[]; errors: ImportError[]; valid: boolean; } @@ -207,7 +205,6 @@ export interface ImportPreviewResult { export interface ImportApplyResult { created: number; updated: number; - deleted: number; errors: ImportError[]; } diff --git a/frontend/src/features/fuel-logs/components/CostCalculator.tsx b/frontend/src/features/fuel-logs/components/CostCalculator.tsx index 765e459..b974b0c 100644 --- a/frontend/src/features/fuel-logs/components/CostCalculator.tsx +++ b/frontend/src/features/fuel-logs/components/CostCalculator.tsx @@ -1,15 +1,15 @@ import React from 'react'; import { Card, CardContent, Typography, Box, Chip } from '@mui/material'; -import { UnitSystem } from '../types/fuel-logs.types'; +import { useUnits } from '../../../core/units/UnitsContext'; interface Props { fuelUnits?: number; costPerUnit?: number; calculatedCost: number; - unitSystem?: UnitSystem; } -export const CostCalculator: React.FC = ({ fuelUnits, costPerUnit, calculatedCost, unitSystem = 'imperial' }) => { +export const CostCalculator: React.FC = ({ fuelUnits, costPerUnit, calculatedCost }) => { + const { unitSystem, currencySymbol } = useUnits(); const unitLabel = unitSystem === 'imperial' ? 'gallons' : 'liters'; // Ensure we have valid numbers @@ -30,8 +30,8 @@ export const CostCalculator: React.FC = ({ fuelUnits, costPerUnit, calcul - {safeUnits.toFixed(3)} {unitLabel} × ${safeCostPerUnit.toFixed(3)} - ${safeCost.toFixed(2)} + {safeUnits.toFixed(3)} {unitLabel} x {currencySymbol}{safeCostPerUnit.toFixed(3)} + {currencySymbol}{safeCost.toFixed(2)} diff --git a/frontend/src/features/fuel-logs/components/DistanceInput.tsx b/frontend/src/features/fuel-logs/components/DistanceInput.tsx index 8be48a4..311a19d 100644 --- a/frontend/src/features/fuel-logs/components/DistanceInput.tsx +++ b/frontend/src/features/fuel-logs/components/DistanceInput.tsx @@ -12,8 +12,8 @@ interface Props { } export const DistanceInput: React.FC = ({ type, value, onChange, unitSystem = 'imperial', error, disabled }) => { - const units = unitSystem === 'imperial' ? 'miles' : 'kilometers'; - const label = type === 'odometer' ? `Odometer (${units})` : `Trip Distance (${units})`; + const units = unitSystem === 'imperial' ? 'miles' : 'km'; + const label = type === 'odometer' ? 'Odometer' : 'Trip Distance'; return ( void; initial?: Partial )} /> - {/* Row 2: Date/Time | MPG/km/L */} + {/* Row 2: Date/Time | MPG/L/100km */} ( void; initial?: Partial 0 ? calculatedEfficiency.toFixed(3) : ''} fullWidth InputProps={{ @@ -283,7 +283,7 @@ const FuelLogFormComponent: React.FC<{ onSuccess?: () => void; initial?: Partial )} /> - + ( diff --git a/frontend/src/features/fuel-logs/components/FuelLogsList.tsx b/frontend/src/features/fuel-logs/components/FuelLogsList.tsx index df87a0a..64df06f 100644 --- a/frontend/src/features/fuel-logs/components/FuelLogsList.tsx +++ b/frontend/src/features/fuel-logs/components/FuelLogsList.tsx @@ -31,7 +31,7 @@ interface FuelLogsListProps { export const FuelLogsList: React.FC = ({ logs, onEdit, onDelete }) => { const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down('sm')); - const { unitSystem, convertDistance, convertVolume } = useUnits(); + const { unitSystem, convertDistance, convertVolume, currencySymbol } = useUnits(); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const [logToDelete, setLogToDelete] = useState(null); const [isDeleting, setIsDeleting] = useState(false); @@ -145,7 +145,7 @@ export const FuelLogsList: React.FC = ({ logs, onEdit, onDele if (unitSystem === 'metric') { const km = convertDistance(miles); const liters = convertVolume(gallons); - if (liters > 0) localEffLabel = `${(km / liters).toFixed(1)} km/L`; + if (km > 0) localEffLabel = `${((liters / km) * 100).toFixed(1)} L/100km`; } else { localEffLabel = `${(miles / gallons).toFixed(1)} MPG`; } @@ -173,8 +173,8 @@ export const FuelLogsList: React.FC = ({ logs, onEdit, onDele gap: isMobile ? 0.5 : 1 }}> {(log.efficiency && typeof log.efficiency === 'number' && !isNaN(log.efficiency) && log.efficiencyLabel) || localEffLabel ? ( @@ -262,7 +262,7 @@ export const FuelLogsList: React.FC = ({ logs, onEdit, onDele {logToDelete && ( - {new Date(logToDelete.dateTime).toLocaleString()} - ${logToDelete.totalCost.toFixed(2)} + {new Date(logToDelete.dateTime).toLocaleString()} - {currencySymbol}{logToDelete.totalCost.toFixed(2)} )} diff --git a/frontend/src/features/fuel-logs/components/FuelStatsCard.tsx b/frontend/src/features/fuel-logs/components/FuelStatsCard.tsx index 747878c..2435352 100644 --- a/frontend/src/features/fuel-logs/components/FuelStatsCard.tsx +++ b/frontend/src/features/fuel-logs/components/FuelStatsCard.tsx @@ -4,7 +4,7 @@ import { FuelLogResponse } from '../types/fuel-logs.types'; import { useUnits } from '../../../core/units/UnitsContext'; export const FuelStatsCard: React.FC<{ logs?: FuelLogResponse[] }> = ({ logs }) => { - const { unitSystem } = useUnits(); + const { unitSystem, currencySymbol } = useUnits(); const stats = useMemo(() => { if (!logs || logs.length === 0) return { count: 0, totalUnits: 0, totalCost: 0 }; @@ -37,7 +37,7 @@ export const FuelStatsCard: React.FC<{ logs?: FuelLogResponse[] }> = ({ logs }) Total Cost - ${(typeof stats.totalCost === 'number' && !isNaN(stats.totalCost) ? stats.totalCost : 0).toFixed(2)} + {currencySymbol}{(typeof stats.totalCost === 'number' && !isNaN(stats.totalCost) ? stats.totalCost : 0).toFixed(2)} diff --git a/frontend/src/features/fuel-logs/components/UnitSystemDisplay.tsx b/frontend/src/features/fuel-logs/components/UnitSystemDisplay.tsx index 774245d..c2fe8a9 100644 --- a/frontend/src/features/fuel-logs/components/UnitSystemDisplay.tsx +++ b/frontend/src/features/fuel-logs/components/UnitSystemDisplay.tsx @@ -4,7 +4,7 @@ import { UnitSystem } from '../types/fuel-logs.types'; export const UnitSystemDisplay: React.FC<{ unitSystem?: UnitSystem; showLabel?: string }> = ({ unitSystem, showLabel }) => { if (!unitSystem) return null; - const label = unitSystem === 'imperial' ? 'Imperial (miles, gallons, MPG)' : 'Metric (km, liters, km/L)'; + const label = unitSystem === 'imperial' ? 'Imperial (miles, gallons, MPG)' : 'Metric (km, liters, L/100km)'; return ( {showLabel ? `${showLabel} ` : ''}{label} diff --git a/frontend/src/features/settings/api/preferences.api.ts b/frontend/src/features/settings/api/preferences.api.ts new file mode 100644 index 0000000..fce9697 --- /dev/null +++ b/frontend/src/features/settings/api/preferences.api.ts @@ -0,0 +1,13 @@ +/** + * @ai-summary API client for user preferences endpoints + * @ai-context Handles unit system, currency, and timezone preferences sync + */ + +import { apiClient } from '../../../core/api/client'; +import { UserPreferences, UpdatePreferencesRequest } from '../types/preferences.types'; + +export const preferencesApi = { + getPreferences: () => apiClient.get('/user/preferences'), + updatePreferences: (data: UpdatePreferencesRequest) => + apiClient.put('/user/preferences', data), +}; diff --git a/frontend/src/features/settings/hooks/usePreferences.ts b/frontend/src/features/settings/hooks/usePreferences.ts new file mode 100644 index 0000000..5f86739 --- /dev/null +++ b/frontend/src/features/settings/hooks/usePreferences.ts @@ -0,0 +1,61 @@ +/** + * @ai-summary React hooks for user preferences management + * @ai-context Handles unit system, currency, and timezone preference sync with backend + */ + +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; +import { useAuth0 } from '@auth0/auth0-react'; +import { preferencesApi } from '../api/preferences.api'; +import { UpdatePreferencesRequest } from '../types/preferences.types'; +import toast from 'react-hot-toast'; + +interface ApiError { + response?: { + data?: { + error?: string; + message?: string; + }; + }; + message?: string; +} + +export const usePreferences = () => { + const { isAuthenticated, isLoading } = useAuth0(); + + return useQuery({ + queryKey: ['user-preferences'], + queryFn: async () => { + const response = await preferencesApi.getPreferences(); + return response.data; + }, + enabled: isAuthenticated && !isLoading, + staleTime: 5 * 60 * 1000, // 5 minutes + gcTime: 10 * 60 * 1000, // 10 minutes cache time + retry: (failureCount, error: any) => { + // Retry 401s a few times (auth token might be refreshing) + if (error?.response?.status === 401 && failureCount < 3) { + return true; + } + return false; + }, + retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000), + refetchOnWindowFocus: false, + refetchOnMount: false, + }); +}; + +export const useUpdatePreferences = () => { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: (data: UpdatePreferencesRequest) => preferencesApi.updatePreferences(data), + onSuccess: (response) => { + queryClient.setQueryData(['user-preferences'], response.data); + // Don't show toast for unit system changes - context handles UI feedback + }, + onError: (error: ApiError) => { + const message = error.response?.data?.message || error.response?.data?.error || 'Failed to update preferences'; + toast.error(message); + }, + }); +}; diff --git a/frontend/src/features/settings/hooks/useSettings.ts b/frontend/src/features/settings/hooks/useSettings.ts index 50a77af..98f222d 100644 --- a/frontend/src/features/settings/hooks/useSettings.ts +++ b/frontend/src/features/settings/hooks/useSettings.ts @@ -1,5 +1,6 @@ import { useState, useEffect } from 'react'; import { useSettingsPersistence, SettingsState } from './useSettingsPersistence'; +import { useUnits } from '../../../core/units/UnitsContext'; const defaultSettings: SettingsState = { darkMode: false, @@ -13,10 +14,12 @@ const defaultSettings: SettingsState = { export const useSettings = () => { const { loadSettings, saveSettings } = useSettingsPersistence(); + const { unitSystem: contextUnitSystem, setUnitSystem: setContextUnitSystem } = useUnits(); const [settings, setSettings] = useState(defaultSettings); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); + // Load settings from localStorage on mount useEffect(() => { try { setIsLoading(true); @@ -33,6 +36,13 @@ export const useSettings = () => { } }, [loadSettings]); + // Sync unitSystem from context (which may load from backend) + useEffect(() => { + if (contextUnitSystem && contextUnitSystem !== settings.unitSystem) { + setSettings(prev => ({ ...prev, unitSystem: contextUnitSystem })); + } + }, [contextUnitSystem, settings.unitSystem]); + const updateSetting = ( key: K, value: SettingsState[K] @@ -42,6 +52,11 @@ export const useSettings = () => { const newSettings = { ...settings, [key]: value }; setSettings(newSettings); saveSettings(newSettings); + + // Sync unitSystem changes to context (which syncs to backend) + if (key === 'unitSystem' && typeof value === 'string') { + setContextUnitSystem(value as 'imperial' | 'metric'); + } } catch (err) { setError(err instanceof Error ? err.message : 'Failed to save settings'); } diff --git a/frontend/src/features/settings/mobile/MobileSettingsScreen.tsx b/frontend/src/features/settings/mobile/MobileSettingsScreen.tsx index 4c758bb..d5d9276 100644 --- a/frontend/src/features/settings/mobile/MobileSettingsScreen.tsx +++ b/frontend/src/features/settings/mobile/MobileSettingsScreen.tsx @@ -367,7 +367,7 @@ export const MobileSettingsScreen: React.FC = () => {

Unit System

- Currently using {settings.unitSystem === 'imperial' ? 'Miles & Gallons' : 'Kilometers & Liters'} + Currently using {settings.unitSystem === 'imperial' ? 'Miles, Gallons, MPG, USD' : 'Km, Liters, L/100km, EUR'}