Database Schema - DigitalHerencia/FleetFusion GitHub Wiki
Overview
FleetFusion uses a PostgreSQL database with Prisma ORM for type-safe database access. The schema supports multi-tenant architecture with comprehensive fleet management capabilities including vehicles, drivers, loads, compliance tracking, and IFTA reporting.
Database Configuration
// Environment Variables
DATABASE_URL: PostgreSQL connection URL with connection pooling
DIRECT_URL: Direct PostgreSQL connection URL for migrations
Core Entities
organizations
)
Organization (The central entity for multi-tenant architecture. Each organization represents a trucking company.
model Organization {
id String @id @default(uuid())
clerkId String @unique // Clerk.js organization ID
name String
slug String @unique
mcNumber String? // Motor Carrier Number
dotNumber String? // DOT Number
address String?
city String?
state String?
zip String?
phone String?
email String?
logoUrl String?
subscriptionTier SubscriptionTier @default(free)
subscriptionStatus SubscriptionStatus @default(trial)
maxUsers Int @default(5)
billingEmail String?
settings Json? @default("{...}")
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
Key Features:
- Multi-tenant isolation via
organizationId
foreign keys - Subscription management with tiers and status
- Configurable settings (timezone, units, formats)
- Integration with Clerk.js for authentication
Relationships:
- Has many:
users
,vehicles
,drivers
,loads
,complianceDocuments
,iftaReports
,auditLogs
users
)
User (User accounts with role-based access control and organization membership.
model User {
id String @id @default(uuid())
clerkId String @unique // Clerk.js user ID
organizationId String? // Nullable for flexibility
email String?
firstName String?
lastName String?
profileImage String?
role UserRole @default(viewer)
permissions Json? @default("[]")
isActive Boolean @default(true)
lastLogin DateTime?
onboardingSteps Json? @default("{}")
onboardingComplete Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
User Roles:
enum UserRole {
admin // Full system access
manager // Management functions
user // Standard user access
dispatcher // Dispatch operations
driver // Driver-specific access
compliance // Compliance management
accountant // Financial/reporting access
viewer // Read-only access
}
vehicles
)
Vehicle (Fleet vehicle management with compliance tracking.
model Vehicle {
id String @id @default(uuid())
organizationId String
type String // truck, trailer, etc.
status VehicleStatus @default(active)
make String?
model String?
year Int?
vin String?
licensePlate String?
licensePlateState String?
unitNumber String // Unique within organization
currentOdometer Int?
lastOdometerUpdate DateTime?
fuelType String?
lastInspectionDate DateTime?
nextInspectionDue DateTime?
insuranceExpiration DateTime?
registrationExpiration DateTime?
notes String?
customFields Json? @default("{}")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
Vehicle Status:
enum VehicleStatus {
active
inactive
maintenance
decommissioned
}
drivers
)
Driver (Driver management with compliance and document tracking.
model Driver {
id String @id @default(uuid())
organizationId String
userId String? @unique // Optional link to User
employeeId String?
firstName String
lastName String
email String?
phone String?
address String?
city String?
state String?
zip String?
licenseNumber String?
licenseState String?
licenseClass String?
licenseExpiration DateTime?
drugTestDate DateTime?
backgroundCheckDate DateTime?
medicalCardExpiration DateTime?
hireDate DateTime?
terminationDate DateTime?
status DriverStatus @default(active)
emergencyContact1 String?
emergencyContact2 String?
emergencyContact3 String?
notes String?
customFields Json? @default("{}")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
loads
)
Load (Dispatch and load management with comprehensive tracking.
model Load {
id String @id @default(uuid())
organizationId String
driverId String?
vehicleId String?
trailerId String?
loadNumber String // Unique within organization
referenceNumber String?
status LoadStatus @default(pending)
customerName String?
customerContact String?
customerPhone String?
customerEmail String?
// Origin Details
originAddress String
originCity String
originState String
originZip String
originLat Decimal? @db.Decimal(10, 6)
originLng Decimal? @db.Decimal(10, 6)
// Destination Details
destinationAddress String
destinationCity String
destinationState String
destinationZip String
destinationLat Decimal? @db.Decimal(10, 6)
destinationLng Decimal? @db.Decimal(10, 6)
// Financial
rate Decimal? @db.Decimal(10, 2)
currency String? @default("USD")
// Scheduling
scheduledPickupDate DateTime?
actualPickupDate DateTime?
scheduledDeliveryDate DateTime?
actualDeliveryDate DateTime?
// Load Details
weight Int?
pieces Int?
commodity String?
hazmat Boolean? @default(false)
estimatedMiles Int?
actualMiles Int?
priority LoadPriority @default(medium)
tags String[] @default([])
notes String?
instructions String?
customFields Json? @default("{}")
createdBy String?
lastModifiedBy String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
Load Status Workflow:
enum LoadStatus {
draft // Initial creation
pending // Awaiting assignment
posted // Posted to load boards
booked // Customer confirmed
confirmed // Internal confirmation
assigned // Driver/vehicle assigned
dispatched // Dispatch sent
in_transit // En route to pickup
at_pickup // Arrived at pickup
picked_up // Load picked up
en_route // En route to delivery
at_delivery // Arrived at delivery
delivered // Load delivered
pod_required // Proof of delivery needed
completed // Fully completed
invoiced // Invoice sent
paid // Payment received
cancelled // Load cancelled
problem // Issue requiring attention
}
Compliance & Documentation
compliance_documents
)
ComplianceDocument (Document management for regulatory compliance.
model ComplianceDocument {
id String @id @default(uuid())
organizationId String
driverId String? // Driver-specific documents
vehicleId String? // Vehicle-specific documents
type String // license, insurance, permit, etc.
title String
documentNumber String?
issuingAuthority String?
fileUrl String? // Blob storage URL
fileName String?
fileSize Int?
mimeType String?
issueDate DateTime?
expirationDate DateTime? // Critical for compliance alerts
status String @default("active")
isVerified Boolean? @default(false)
verifiedBy String? // User ID
verifiedAt DateTime?
notes String?
tags Json? @default("[]")
metadata Json? @default("{}")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
compliance_alerts
)
ComplianceAlert (Automated compliance monitoring and alerting system.
model ComplianceAlert {
id String @id @default(uuid())
organizationId String
userId String? // Assigned user
driverId String? // Related driver
vehicleId String? // Related vehicle
type String // expiring_document, hos_violation, etc.
severity String // low, medium, high, critical
title String
message String
entityType String // driver, vehicle, trailer, company, load
entityId String
dueDate DateTime?
acknowledged Boolean @default(false)
acknowledgedBy String?
acknowledgedAt DateTime?
resolved Boolean @default(false)
resolvedBy String?
resolvedAt DateTime?
resolutionNotes String?
metadata Json? @default("{}")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
IFTA (International Fuel Tax Agreement)
ifta_reports
)
IftaReport (Quarterly IFTA tax reporting.
model IftaReport {
id String @id @default(uuid())
organizationId String
quarter Int // 1-4
year Int
status String @default("draft")
totalMiles Int?
totalGallons Decimal? @db.Decimal(10, 3)
totalTaxOwed Decimal? @db.Decimal(10, 2)
totalTaxPaid Decimal? @db.Decimal(10, 2)
submittedAt DateTime?
submittedBy String? // User ID
dueDate DateTime?
filedDate DateTime?
reportFileUrl String? // Generated report PDF
calculationData Json? @default("{}")
supportingDocs String?
notes String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
IftaTrip & IftaFuelPurchase
Supporting data for IFTA calculations.
model IftaTrip {
id String @id @default(uuid())
organizationId String
vehicleId String
date DateTime
distance Int // Miles driven
jurisdiction String // State/Province code
fuelUsed Decimal? @db.Decimal(10, 3)
notes String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model IftaFuelPurchase {
id String @id @default(uuid())
organizationId String
vehicleId String
date DateTime
jurisdiction String // State/Province where purchased
gallons Decimal @db.Decimal(10, 3)
amount Decimal @db.Decimal(10, 2)
vendor String?
receiptNumber String?
notes String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
Audit & Tracking
audit_logs
)
AuditLog (Comprehensive audit trail for all system operations.
model AuditLog {
id String @id @default(uuid())
organizationId String
userId String? // Who performed the action
entityType String // Table/model name
entityId String // Record ID
action String // create, update, delete, etc.
changes Json? // Before/after values
metadata Json? // Additional context
timestamp DateTime @default(now())
}
load_status_events
)
LoadStatusEvent (Detailed load status tracking history.
model LoadStatusEvent {
id String @id @default(uuid())
loadId String
status LoadStatus
timestamp DateTime @default(now())
location Json? // GPS coordinates, address
notes String?
automaticUpdate Boolean @default(false)
source String @default("dispatcher")
createdBy String?
}
System Tables
organization_memberships
)
OrganizationMembership (Many-to-many relationship between users and organizations.
model OrganizationMembership {
id String @id @default(uuid())
organizationId String
userId String
role String // Organization-specific role
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
webhook_events
)
WebhookEvent (Webhook processing and retry logic.
model WebhookEvent {
id String @id @default(uuid())
eventType String // clerk.user.created, etc.
eventId String @unique
organizationId String?
userId String?
payload Json
status String @default("pending")
processingError String?
processedAt DateTime?
retryCount Int @default(0)
createdAt DateTime @default(now())
}
Database Indexes
Key indexes for performance optimization:
-- Organization lookups
CREATE INDEX idx_orgs_clerk_id ON organizations(clerk_id);
CREATE INDEX idx_orgs_slug ON organizations(slug);
-- User authentication
CREATE INDEX idx_users_clerk_id ON users(clerk_id);
CREATE INDEX idx_users_org_id ON users(organization_id);
CREATE INDEX idx_users_email ON users(email);
-- Vehicle operations
CREATE INDEX idx_vehicles_org_unit ON vehicles(organization_id, unit_number);
CREATE INDEX idx_vehicles_status ON vehicles(status);
-- Load management
CREATE INDEX idx_loads_org_number ON loads(organization_id, load_number);
CREATE INDEX idx_loads_status ON loads(status);
CREATE INDEX idx_loads_pickup_date ON loads(scheduled_pickup_date);
-- Compliance monitoring
CREATE INDEX idx_compliance_expiration ON compliance_documents(expiration_date);
CREATE INDEX idx_alerts_due_date ON compliance_alerts(due_date);
-- Audit trails
CREATE INDEX idx_audit_timestamp ON audit_logs(timestamp);
CREATE INDEX idx_audit_entity ON audit_logs(entity_type, entity_id);
Data Relationships
erDiagram
Organization ||--o{ User : "has members"
Organization ||--o{ Vehicle : "owns"
Organization ||--o{ Driver : "employs"
Organization ||--o{ Load : "manages"
Organization ||--o{ ComplianceDocument : "maintains"
Organization ||--o{ IftaReport : "files"
User ||--o| Driver : "can be"
User ||--o{ AuditLog : "creates"
Driver ||--o{ Load : "assigned to"
Driver ||--o{ ComplianceDocument : "has documents"
Vehicle ||--o{ Load : "pulls"
Vehicle ||--o{ ComplianceDocument : "has documents"
Vehicle ||--o{ IftaTrip : "records"
Vehicle ||--o{ IftaFuelPurchase : "tracks"
Load ||--o{ LoadStatusEvent : "has events"
ComplianceDocument ||--o{ ComplianceAlert : "triggers"
Migration Strategy
FleetFusion uses Prisma migrations for database schema management:
# Development migrations
npx prisma migrate dev --name migration_name
# Production deployment
npx prisma migrate deploy
# Schema reset (development only)
npx prisma migrate reset
Data Retention Policies
- Audit Logs: Retained for 7 years for compliance
- Load History: Retained indefinitely for reporting
- IFTA Records: Retained for 4 years per regulations
- Compliance Documents: Retained while active + 3 years
- User Activity: Session data purged after 90 days
Performance Considerations
- Partition Strategy: Consider partitioning large tables by organization_id
- Index Maintenance: Regular REINDEX operations for heavily updated tables
- Connection Pooling: Configured via DATABASE_URL for optimal performance
- Query Optimization: Use Prisma's includeFor selective loading
- Caching: Redis layer for frequently accessed configuration data
Detailed Table Schemas
Core Business Tables
compliance_documents
Field | Type | Nullable | Description |
---|---|---|---|
id | text | not null | Primary key |
organization_id | text | not null | Tenant isolation |
driver_id | text | null | Associated driver (optional) |
vehicle_id | text | null | Associated vehicle (optional) |
type | text | not null | Document type (license, insurance, etc.) |
title | text | not null | Document title/name |
document_number | text | null | Official document number |
issuing_authority | text | null | Authority that issued document |
file_url | text | null | Storage URL for document file |
file_name | text | null | Original filename |
file_size | int4 | null | File size in bytes |
mime_type | text | null | File MIME type |
issue_date | date | null | Date document was issued |
expiration_date | date | null | Document expiration date |
status | text | not null | Document status (active, expired, etc.) |
is_verified | bool | null | Verification status |
verified_by | text | null | User who verified document |
verified_at | timestamp | null | Verification timestamp |
notes | text | null | Additional notes |
tags | jsonb | null | Flexible tagging system |
created_at | timestamp | not null | Record creation timestamp |
updated_at | timestamp | not null | Last update timestamp |
loads
Field | Type | Nullable | Description |
---|---|---|---|
id | text | not null | Primary key |
organization_id | text | not null | Tenant isolation |
driver_id | text | null | Assigned driver |
vehicle_id | text | null | Assigned vehicle |
trailer_id | text | null | Assigned trailer |
load_number | text | not null | Unique load identifier |
reference_number | text | null | Customer reference |
status | LoadStatus | not null | Current load status |
customer_name | text | null | Customer/shipper name |
customer_contact | text | null | Primary contact |
customer_phone | text | null | Contact phone |
customer_email | text | null | Contact email |
origin_address | text | not null | Pickup address |
origin_city | text | not null | Pickup city |
origin_state | text | not null | Pickup state |
origin_zip | text | not null | Pickup ZIP code |
origin_lat | numeric(10,6) | null | Pickup latitude |
origin_lng | numeric(10,6) | null | Pickup longitude |
destination_address | text | not null | Delivery address |
destination_city | text | not null | Delivery city |
destination_state | text | not null | Delivery state |
destination_zip | text | not null | Delivery ZIP code |
destination_lat | numeric(10,6) | null | Delivery latitude |
destination_lng | numeric(10,6) | null | Delivery longitude |
rate | numeric(10,2) | null | Load payment rate |
currency | text | null | Currency code |
scheduled_pickup_date | timestamp | null | Planned pickup time |
actual_pickup_date | timestamp | null | Actual pickup time |
scheduled_delivery_date | timestamp | null | Planned delivery time |
actual_delivery_date | timestamp | null | Actual delivery time |
weight | int4 | null | Load weight (lbs) |
pieces | int4 | null | Number of pieces |
commodity | text | null | Commodity description |
hazmat | bool | null | Hazardous materials flag |
estimated_miles | int4 | null | Estimated distance |
actual_miles | int4 | null | Actual distance traveled |
notes | text | null | Additional notes |
instructions | text | null | Special instructions |
custom_fields | jsonb | null | Flexible custom data |
created_at | timestamp | not null | Record creation timestamp |
updated_at | timestamp | not null | Last update timestamp |
audit_logs
Field | Type | Nullable | Description |
---|---|---|---|
id | text | not null | Primary key |
organization_id | text | not null | Tenant isolation |
user_id | text | null | User who performed action |
entity_type | text | not null | Type of entity affected |
entity_id | text | not null | ID of affected entity |
action | text | not null | Action performed |
changes | jsonb | null | Before/after data |
metadata | jsonb | null | Additional context |
timestamp | timestamp | not null | Action timestamp |
drivers
Field | Type | Nullable | Description |
---|---|---|---|
id | text | not null | Primary key |
organization_id | text | not null | Tenant isolation |
clerk_user_id | text | null | Linked Clerk user |
employee_id | text | null | Company employee ID |
name | text | not null | Driver full name |
text | null | Email address | |
phone | text | null | Phone number |
license_number | text | null | CDL number |
license_state | text | null | License issuing state |
license_expiry | date | null | License expiration |
dob | date | null | Date of birth |
hire_date | date | null | Employment start date |
status | DriverStatus | not null | Employment status |
address | text | null | Home address |
emergency_contact | jsonb | null | Emergency contact info |
medical_cert_expiry | date | null | Medical certificate expiry |
hazmat_expiry | date | null | Hazmat endorsement expiry |
drug_test_date | date | null | Last drug test date |
background_check_date | date | null | Background check date |
notes | text | null | Additional notes |
custom_fields | jsonb | null | Flexible custom data |
created_at | timestamp | not null | Record creation timestamp |
updated_at | timestamp | not null | Last update timestamp |
Compliance Document Schema Changes
The compliance_documents
table has been enhanced with additional fields for better tracking and management of compliance documents.
New Fields:
issuing_authority
: Authority that issued the documentfile_url
: Storage URL for the document filefile_name
: Original filename of the documentfile_size
: Size of the file in bytesmime_type
: MIME type of the fileissue_date
: Date when the document was issuedexpiration_date
: Expiration date of the documentis_verified
: Verification status of the documentverified_by
: User who verified the documentverified_at
: Timestamp when the document was verifiednotes
: Additional notes regarding the documenttags
: Flexible tagging system for categorizing documentsmetadata
: Additional metadata in JSON format
Updated Fields:
status
: Now uses a string type with a default value of "active". This can be extended in the future without schema changes.created_at
andupdated_at
: Timestamps are now automatically managed by the system.
Load Table Enhancements
The loads
table has been optimized for better performance and additional tracking capabilities.
New Fields:
reference_number
: Customer reference number for the loadcustomer_name
,customer_contact
,customer_phone
,customer_email
: Additional fields for customer contact informationhazmat
: Boolean flag to indicate if the load contains hazardous materialspriority
: Load priority leveltags
: Flexible tagging system for categorizing loadsinstructions
: Special instructions for the loadcustom_fields
: Flexible custom data in JSON formatcreated_by
andlast_modified_by
: Track who created and last modified the load
Updated Fields:
status
: Now uses theLoadStatus
enum for better clarity and control.scheduled_pickup_date
,actual_pickup_date
,scheduled_delivery_date
,actual_delivery_date
: Changed to timestamp type for precise tracking.origin_lat
,origin_lng
,destination_lat
,destination_lng
: Changed to numeric(10,6) type for better precision.rate
: Changed to numeric(10,2) type for consistent financial data handling.notes
: Expanded to text type to allow more detailed notes.
Audit Log Improvements
The audit_logs
table structure has been simplified and optimized.
New Fields:
metadata
: Additional metadata in JSON format for more context about the change.
Updated Fields:
changes
: Now uses JSONB type to store before/after data for changes.timestamp
: Automatically set to the current timestamp when the row is created.
Driver Table Updates
The drivers
table has been updated to streamline driver management and enhance compliance tracking.
New Fields:
clerk_user_id
: Link to the associated Clerk user accountemployee_id
: Company-specific employee ID for the driverdob
: Date of birth of the driverhire_date
: Date when the driver was hiredaddress
: Home address of the driveremergency_contact
: JSONB field to store emergency contact informationmedical_cert_expiry
: Expiration date of the medical certificatehazmat_expiry
: Expiration date of the hazmat endorsementdrug_test_date
: Date of the last drug testbackground_check_date
: Date when the background check was performednotes
: Additional notes regarding the drivercustom_fields
: Flexible custom data in JSON format
Updated Fields:
status
: Now uses theDriverStatus
enum for better clarity.license_expiry
: Changed to date type to accurately reflect expiration date.created_at
andupdated_at
: Timestamps are now automatically managed by the system.
Migration Strategy
FleetFusion uses Prisma migrations for database schema management:
# Development migrations
npx prisma migrate dev --name migration_name
# Production deployment
npx prisma migrate deploy
# Schema reset (development only)
npx prisma migrate reset
Data Retention Policies
- Audit Logs: Retained for 7 years for compliance
- Load History: Retained indefinitely for reporting
- IFTA Records: Retained for 4 years per regulations
- Compliance Documents: Retained while active + 3 years
- User Activity: Session data purged after 90 days
Performance Considerations
- Partition Strategy: Consider partitioning large tables by organization_id
- Index Maintenance: Regular REINDEX operations for heavily updated tables
- Connection Pooling: Configured via DATABASE_URL for optimal performance
- Query Optimization: Use Prisma's includeFor selective loading
- Caching: Redis layer for frequently accessed configuration data