Skip to main content

ElastiCORE Automotive Domain Sample Model

An entity model design guide for the automotive industry based on ElastiCORE. Referencing the Salesforce Automotive Cloud data model, this guide presents models ready for real-world use.

📋 Domain Overview

Core Business Entities

  • Vehicle: Vehicle basic information and specifications management
  • Vehicle Definition: Vehicle model and specification definitions
  • Asset: Vehicle asset management and tracking
  • Appraisal: Vehicle value assessment and appraisal
  • Service Record: Vehicle maintenance and service history
  • Warranty: Vehicle warranty management
  • Inventory: Parts and vehicle inventory management

🏗️ Entity Model Definitions

1. Vehicle

entity:
Vehicle:
meta: entity @expose(50) @audited @pageable @extend(AuditEntity) @table(name="VEHICLE")
fields:
vehicleId: long @id @sequence @search(eq) -- Vehicle ID
vin: string(17)! @search(eq) @unique -- Vehicle Identification Number (VIN)
licensePlate: string(20) @search(like) @unique -- License plate number
vehicleDefinitionId: long! @search(eq) @ref(VehicleDefinition.id) -- Vehicle definition ID
ownerId: long @search(eq) @ref(Contact.id) -- Owner ID
dealerId: long @search(eq) @ref(Dealer.id) -- Dealer ID
vehicleStatus: string(20)! @search(eq) -- Vehicle status (NEW, USED, CERTIFIED, DAMAGED, SOLD)
condition: string(20) @search(eq) -- Condition grade (EXCELLENT, GOOD, FAIR, POOR)
mileage: int @search(between) -- Mileage (km)
engineNumber: string(50) @search(eq) -- Engine number
fuelType: string(20) @search(eq) -- Fuel type (GASOLINE, DIESEL, HYBRID, ELECTRIC, HYDROGEN)
transmission: string(20) @search(eq) -- Transmission (MANUAL, AUTOMATIC, CVT)
exteriorColor: string(30) @search(eq) -- Exterior color
interiorColor: string(30) @search(eq) -- Interior color
manufactureDate: date @search(between) -- Manufacture date
firstRegistrationDate: date @search(between) -- First registration date
purchaseDate: date @search(between) -- Purchase date
purchasePrice: bigdecimal(12.2) @search(between) -- Purchase price
currentValue: bigdecimal(12.2) @search(between) -- Current value
lastServiceDate: date @search(between) -- Last service date
nextServiceDate: date @search(between) -- Next scheduled service date
insurancePolicyNumber: string(50) @search(like) -- Insurance policy number
notes: text @search(like) -- Special notes
isActive: boolean @search(eq) @default(true) -- Active status

2. Vehicle Definition

entity:
VehicleDefinition:
meta: entity @expose(50) @table(name="VEHICLE_DEFINITION")
fields:
definitionId: long @id @sequence @search(eq) -- Vehicle definition ID
make: string(50)! @search(like) -- Manufacturer (HYUNDAI, KIA, BMW, MERCEDES)
model: string(50)! @search(like) -- Model name
trim: string(30) @search(like) -- Trim name
modelYear: int! @search(between) -- Model year
vehicleType: string(20)! @search(eq) -- Vehicle type (SEDAN, SUV, HATCHBACK, COUPE, TRUCK, MOTORCYCLE)
bodyStyle: string(20) @search(eq) -- Body style
engineSize: bigdecimal(3.1) @search(between) -- Engine displacement (liters)
horsepower: int @search(between) -- Horsepower
torque: int @search(between) -- Torque (Nm)
fuelEfficiency: bigdecimal(4.1) @search(between) -- Fuel efficiency (km/L)
seatingCapacity: int @search(eq) -- Seating capacity
driveType: string(10) @search(eq) -- Drive type (FWD, RWD, AWD, 4WD)
msrp: bigdecimal(12.2) @search(between) -- Manufacturer's Suggested Retail Price
length: int @search(between) -- Length (mm)
width: int @search(between) -- Width (mm)
height: int @search(between) -- Height (mm)
wheelbase: int @search(between) -- Wheelbase (mm)
curbWeight: int @search(between) -- Curb weight (kg)
maxWeight: int @search(between) -- Maximum loaded weight (kg)
isActive: boolean @search(eq) @default(true) -- In production
productionStartYear: int @search(between) -- Production start year
productionEndYear: int @search(between) -- Production end year

3. Vehicle Appraisal

entity:
VehicleAppraisal:
meta: entity @expose(50) @audited @pageable @extend(AuditEntity) @table(name="VEHICLE_APPRAISAL")
fields:
appraisalId: long @id @sequence @search(eq) -- Appraisal ID
appraisalNumber: string(50)! @search(like) @unique -- Appraisal number
vehicleId: long! @search(eq) @ref(Vehicle.id) -- Vehicle ID
appraisalType: string(20)! @search(eq) -- Appraisal type (PURCHASE, SALE, INSURANCE, LOAN, TRADE_IN)
appraisalStatus: string(20)! @search(eq) -- Appraisal status (REQUESTED, IN_PROGRESS, COMPLETED, CANCELLED)
requestDate: datetime! @search(between) -- Request date
completedDate: datetime @search(between) -- Completion date
appraiserId: long @search(eq) @ref(Appraiser.id) -- Appraiser ID
requesterId: long! @search(eq) @ref(Contact.id) -- Requester ID
marketValue: bigdecimal(12.2) @search(between) -- Market value
tradeInValue: bigdecimal(12.2) @search(between) -- Trade-in value
retailValue: bigdecimal(12.2) @search(between) -- Retail value
estimatedMileage: int @search(between) -- Mileage at appraisal
overallCondition: string(20) @search(eq) -- Overall condition (EXCELLENT, GOOD, FAIR, POOR)
exteriorCondition: string(20) @search(eq) -- Exterior condition
interiorCondition: string(20) @search(eq) -- Interior condition
mechanicalCondition: string(20) @search(eq) -- Mechanical condition
accidentHistory: boolean @search(eq) @default(false) -- Accident history
floodDamage: boolean @search(eq) @default(false) -- Flood damage history
modifications: text @search(like) -- Modifications
remarks: text @search(like) -- Appraisal remarks
photos: text -- Photo paths (JSON array)

4. Service Record

entity:
ServiceRecord:
meta: entity @expose(50) @pageable @table(name="SERVICE_RECORD")
fields:
serviceId: long @id @sequence @search(eq) -- Service ID
serviceNumber: string(50)! @search(like) @unique -- Service number
vehicleId: long! @search(eq) @ref(Vehicle.id) -- Vehicle ID
serviceCenterId: long! @search(eq) @ref(ServiceCenter.id) -- Service center ID
serviceType: string(30)! @search(eq) -- Service type (MAINTENANCE, REPAIR, INSPECTION, WARRANTY, RECALL)
serviceDate: date! @search(between) -- Service date
mileageAtService: int @search(between) -- Mileage at service
workDescription: text! @search(like) -- Work description
partsUsed: text -- Parts used (JSON array)
laborCost: bigdecimal(10.2) @search(between) -- Labor cost
partsCost: bigdecimal(10.2) @search(between) -- Parts cost
totalCost: bigdecimal(10.2)! @search(between) -- Total cost
warranty: boolean @search(eq) @default(false) -- Warranty work
warrantyPeriod: int @search(between) -- Warranty period (months)
technicianId: long @search(eq) @ref(Technician.id) -- Assigned technician ID
customerSatisfaction: int @search(between) -- Customer satisfaction (1-5)
nextServiceDate: date @search(between) -- Next scheduled service date
notes: text @search(like) -- Notes

5. Vehicle Warranty

entity:
VehicleWarranty:
meta: entity @expose(50) @table(name="VEHICLE_WARRANTY")
fields:
warrantyId: long @id @sequence @search(eq) -- Warranty ID
vehicleId: long! @search(eq) @ref(Vehicle.id) -- Vehicle ID
warrantyType: string(30)! @search(eq) -- Warranty type (BASIC, POWERTRAIN, BUMPER_TO_BUMPER, EXTENDED)
warrantyProvider: string(100)! @search(like) -- Warranty provider (manufacturer, dealer, insurance company)
startDate: date! @search(between) -- Warranty start date
endDate: date! @search(between) -- Warranty end date
mileageLimit: int @search(between) -- Mileage limit (km)
isActive: boolean @search(eq) @default(true) -- Active status
coverageDetails: text @search(like) -- Coverage details
deductible: bigdecimal(8.2) @search(between) -- Deductible amount
maxClaim: bigdecimal(10.2) @search(between) -- Maximum claim amount
termsAndConditions: text -- Terms and conditions

6. Vehicle Inventory

entity:
VehicleInventory:
meta: entity @expose(50) @pageable @table(name="VEHICLE_INVENTORY")
fields:
inventoryId: long @id @sequence @search(eq) -- Inventory ID
vehicleId: long! @search(eq) @ref(Vehicle.id) -- Vehicle ID
dealerId: long! @search(eq) @ref(Dealer.id) -- Dealer ID
stockNumber: string(50)! @search(like) @unique -- Stock number
location: string(50) @search(like) -- Storage location
acquisitionDate: date! @search(between) -- Acquisition date
acquisitionType: string(20)! @search(eq) -- Acquisition type (NEW, TRADE_IN, AUCTION, LEASE_RETURN)
acquisitionCost: bigdecimal(12.2) @search(between) -- Acquisition cost
listPrice: bigdecimal(12.2) @search(between) -- List price
marketPrice: bigdecimal(12.2) @search(between) -- Market price
daysInInventory: int @search(between) -- Days in inventory
status: string(20)! @search(eq) -- Inventory status (AVAILABLE, RESERVED, SOLD, PENDING)
reservedDate: date @search(between) -- Reserved date
soldDate: date @search(between) -- Sold date
soldPrice: bigdecimal(12.2) @search(between) -- Sold price
salespersonId: long @search(eq) @ref(Salesperson.id) -- Salesperson ID
isDisplayVehicle: boolean @search(eq) @default(false) -- Display vehicle flag
notes: text @search(like) -- Notes

7. Parts Inventory

entity:
PartsInventory:
meta: entity @expose(50) @pageable @table(name="PARTS_INVENTORY")
fields:
partId: long @id @sequence @search(eq) -- Part ID
partNumber: string(50)! @search(like) @unique -- Part number
partName: string(100)! @search(like) -- Part name
category: string(30)! @search(eq) -- Part category (ENGINE, TRANSMISSION, BRAKE, SUSPENSION, ELECTRICAL)
manufacturer: string(50) @search(like) -- Manufacturer
compatibleMakes: string(200) -- Compatible makes (JSON array)
unitPrice: bigdecimal(10.2)! @search(between) -- Unit price
cost: bigdecimal(10.2) @search(between) -- Cost
quantityOnHand: int! @search(between) -- Quantity on hand
minimumStock: int @search(between) @default(0) -- Minimum stock level
maximumStock: int @search(between) -- Maximum stock level
reorderPoint: int @search(between) -- Reorder point
supplierId: long @search(eq) @ref(Supplier.id) -- Supplier ID
location: string(30) @search(like) -- Storage location
isActive: boolean @search(eq) @default(true) -- Active status
lastOrderDate: date @search(between) -- Last order date
lastReceivedDate: date @search(between) -- Last received date

🔗 Relational Design Patterns

1:N Relationships

  • VehicleDefinition (1) ↔ (N) Vehicle
  • Vehicle (1) ↔ (N) VehicleAppraisal
  • Vehicle (1) ↔ (N) ServiceRecord
  • Vehicle (1) ↔ (N) VehicleWarranty
  • Vehicle (1) ↔ (1) VehicleInventory

N:M Relationships (Using Junction Tables)

  • PartsInventoryServiceRecord (ServiceParts junction table)
  • VehiclePartsInventory (CompatibleParts junction table)

📊 DTO Design Examples

VehicleSearchDTO

dto:
VehicleSearchDTO:
meta: dto @searchable @template('SEARCH')
fields:
vin: string @search(eq) -- VIN
licensePlate: string @search(like) -- License plate
make: string @search(like) @param('vehicleDefinition.make') -- Manufacturer
model: string @search(like) @param('vehicleDefinition.model') -- Model name
modelYearFrom: int @search(gte) @param('vehicleDefinition.modelYear') -- Model year (from)
modelYearTo: int @search(lte) @param('vehicleDefinition.modelYear') -- Model year (to)
vehicleStatus: string @search(eq) -- Vehicle status
mileageMax: int @search(lte) @param('mileage') -- Maximum mileage

AppraisalSummaryDTO

dto:
AppraisalSummaryDTO:
meta: dto
fields:
appraisalNumber: string -- Appraisal number
vin: string -- VIN
vehicleInfo: string -- Vehicle info (make model year)
appraisalType: string -- Appraisal type
marketValue: bigdecimal(12.2) -- Market value
requestDate: datetime -- Request date
completedDate: datetime -- Completion date

📚 Repository Design Patterns

Complex Search Queries

repository:
Vehicle:
methods:
- id: findVehiclesByMakeAndYear
params:
make: string
yearFrom: int
yearTo: int
return: List<Vehicle>
nativeQuery: true
query: |
SELECT v.* FROM VEHICLE v
JOIN VEHICLE_DEFINITION vd ON v.vehicle_definition_id = vd.definition_id
WHERE vd.make = :make AND vd.model_year BETWEEN :yearFrom AND :yearTo
ORDER BY vd.model_year DESC, v.mileage ASC

- id: getServiceHistoryByVehicle
params:
vehicleId: long
return: List<ServiceHistoryDTO>
nativeQuery: true
query: |
SELECT sr.*, sc.center_name
FROM SERVICE_RECORD sr
JOIN SERVICE_CENTER sc ON sr.service_center_id = sc.center_id
WHERE sr.vehicle_id = :vehicleId
ORDER BY sr.service_date DESC

- id: getInventoryValueByDealer
params:
dealerId: long
return: InventoryStatsDTO
nativeQuery: true
query: |
SELECT
COUNT(*) as vehicle_count,
AVG(list_price) as avg_price,
SUM(list_price) as total_value,
AVG(days_in_inventory) as avg_days
FROM VEHICLE_INVENTORY
WHERE dealer_id = :dealerId AND status = 'AVAILABLE'

🎯 Best Practice Guidelines

1. Data Integrity

  • VIN must be managed as a 17-character unique value
  • Vehicle definitions and vehicles should be normalized in a 1:N relationship
  • Use bigdecimal type for monetary fields to ensure precision

2. Search Optimization

  • VIN and license plate use exact match search (@search(eq))
  • Manufacturer and model name use partial match search (@search(like))
  • Dates, mileage, and prices use range search (@search(between))

3. Business Logic

  • Manage vehicle status through a clear workflow
  • Store service history sorted by chronological order
  • Include date information for inventory turnover calculation

4. Performance Considerations

  • Use pagination for large vehicle data queries
  • Create composite indexes for frequently queried conditions
  • Consider separate aggregation tables for statistics

5. Scalability Design

  • Extensible for new fuel types such as EV and hydrogen
  • Prepared for new specifications like autonomous driving features
  • Support dealer-specific customized business logic

These models provide a foundation for building a scalable system that can effectively handle various business requirements in the automotive industry.