Core Entities
Reference for the principal Prisma models — tenancy, CRM, commercial layer, operations, fleet, and pricing.
This page describes the main Prisma models. All monetary values are in EUR unless noted otherwise.
Tenancy & Identity
Organization
Top-level tenant. Every VTC business model is scoped to an Organization via organizationId.
| Field | Type | Notes |
|---|---|---|
id | String | Better Auth-managed CUID |
name | String | Display name |
slug | String? | URL-safe unique identifier |
primaryColor | String? | Hex brand color for tracking pages (default #1e40af) |
gracePeriodMinutes | Int | Minutes before tracking link expires after mission completion (default 30) |
timezone | String | Display timezone (default Europe/Paris) |
Relations: members, contacts, vehicles, drivers, quotes, invoices, missions, and all other VTC entities.
User
A Better Auth user. One User can belong to multiple organizations via Member.
| Field | Type | Notes |
|---|---|---|
id | String | Better Auth-managed |
email | String | Unique |
role | String? | Organization-level role |
twoFactorEnabled | Boolean | TOTP enabled flag (default false) |
onboardingComplete | Boolean | Whether first-login wizard is done |
Member
Junction between User and Organization. Carries the role and granular permission maps.
| Field | Type | Notes |
|---|---|---|
role | String | owner / admin / member |
permissions | Json | Legacy array of permission keys |
permissionsMap | Json | Fine-grained PermissionMap overrides |
status | String | PENDING / ACTIVE / INACTIVE |
CRM
Contact
Unified contact model for customers, corporate clients, and agency partners.
| Field | Type | Notes |
|---|---|---|
type | ContactType | PRIVATE / BUSINESS / PARTNER / AGENCY |
displayName | String | Display name (required) |
firstName, lastName | String? | Person fields |
companyName, vatNumber, siret | String? | Company fields |
isHotel | Boolean | Sub-flag for hotel-type PARTNER/AGENCY contacts |
defaultClientType | ClientType | PARTNER / PRIVATE — drives pricing path |
difficultyScore | Int? | 1–5 patience-tax multiplier (null = no adjustment) |
preferredLanguage | String | ISO-2 code (fr / en); drives PDF language |
autoValidationMode | ValidationMode | MANUAL / AUTO_GRID_MATCH / AUTO_ALL |
isArchived | Boolean | Soft-archive flag (default false) |
A
PARTNERorAGENCYcontact has an associatedPartnerContract(1:1) and may haveAgencyPortalUsermembers.
EndCustomer
Individual passenger within an agency partner's portfolio.
| Field | Type | Notes |
|---|---|---|
contactId | String | Owning agency/partner Contact |
ownerContactId | String? | Explicit owner contact (for delegation) |
firstName, lastName | String | Required |
difficultyScore | Int? | 1–5 patience-tax override |
preferredLanguage | String | Overrides owning contact's language preference |
Commercial Layer
Quote
Central commercial object. Every service request starts as a Quote.
| Field | Type | Notes |
|---|---|---|
status | QuoteStatus | DRAFT → SENT → ACCEPTED → INVOICED (see full enum) |
source | QuoteSource | OPERATOR_DIRECT / AGENCY_PORTAL |
pricingMode | PricingMode | FIXED_GRID / DYNAMIC / PARTNER_GRID / CLIENT_DIRECT / MANUAL |
tripType | TripType | TRANSFER / EXCURSION / DISPO / OFF_GRID |
pickupAt | DateTime | Planned pickup date/time |
pickupAddress | String | Departure address |
dropoffAddress | String? | Null for DISPO and OFF_GRID |
durationHours | Decimal? | For DISPO — duration in hours |
suggestedPrice | Decimal | Engine-calculated price HT |
finalPrice | Decimal | Operator-confirmed price HT |
commissionPercent | Decimal? | Snapshot from PartnerContract at quote time |
tripAnalysis | Json? | Shadow calculation (segments, distances, cost breakdown) |
appliedRules | Json? | Grids, multipliers, promotions applied |
reference | String? | Sequential reference, e.g. QT-2026-001 (unique per org) |
awaitingOperatorPricing | Boolean | Agency submitted, pending operator price |
autoValidated | Boolean | Auto-validated by agency booking wizard |
Key indexes: (organizationId), (contactId), (status), (pickupAt), (organizationId, status), (source, awaitingOperatorPricing)
QuoteLine
Structured line item within a Quote (Hybrid Blocks architecture).
| Field | Type | Notes |
|---|---|---|
type | QuoteLineType | CALCULATED / MANUAL / GROUP / FEE / PROMOTION |
label | String | Display label (e.g. "Transfert CDG → Paris") |
quantity | Decimal | Default 1, precision (10,3) |
unitPrice | Decimal | HT unit price (excl. tax), precision (10,2) |
totalPrice | Decimal | unitPrice × quantity, HT, precision (10,2) |
vatRate | Decimal | Default 10.00 — stored as decimal percent (10.00 = 10 %) |
vatAmount | Decimal? | totalTtc - totalPrice |
totalTtc | Decimal? | unitPriceTtc × quantity |
unitPriceTtc | Decimal? | TTC source of truth from user input |
priceSource | PriceSource? | DYNAMIC / FIXED_GRID / PARTNER_GRID / MANUAL_OVERRIDE |
dispatchable | Boolean | Whether this line spawns a Mission (default true) |
parentId | String? | Parent line for GROUP hierarchy |
sortOrder | Int | Display order |
Critical semantics:
unitPriceandtotalPriceare always HT (excl. tax).vatRateis a decimal percentage —10.00means 10 %, not 0.10.
Order
Groups multiple quotes, missions, and invoices under a "Dossier de commande".
| Field | Type | Notes |
|---|---|---|
reference | String | Unique sequential ref, e.g. ORD-2026-001 |
status | OrderStatus | DRAFT → QUOTED → CONFIRMED → INVOICED → PAID |
contactId | String | Customer contact (onDelete: Restrict) |
Operations
Mission
Operational unit linking a QuoteLine to a driver + vehicle assignment.
| Field | Type | Notes |
|---|---|---|
quoteId | String? | Nullable — internal tasks have no parent quote |
quoteLineId | String? | The specific line that generated this mission |
status | MissionStatus | PENDING / ASSIGNED / IN_PROGRESS / COMPLETED / CANCELLED / BILLED |
startAt | DateTime | Planned start |
endAt | DateTime? | Planned end (null for open-ended) |
driverId | String? | Primary driver (nullable until assigned) |
vehicleId | String? | Assigned vehicle (nullable until assigned) |
driverMode | DriverMode | SIMPLE / DOUBLE_EQUIPAGE / RELAIS |
isInternal | Boolean | Non-billable internal mission (default false) |
kmStart, kmEnd, kmActual | Decimal? | Odometer readings from driver sheet |
actualPickupAt, actualDropoffAt | DateTime? | Actual execution timestamps |
ref | String? | Sequential ref, e.g. ORD-2026-001-01 |
liveTrackingShareEnabled | Boolean | Whether the tracking link is active |
Notable:
Mission.quoteIdis nullable. Commercial missions always have aquoteId; internal tasks (created directly by operators without a quote) leave it null.
MissionTransition
Typed audit log for every mission status change (9-stage lifecycle).
| Field | Type | Notes |
|---|---|---|
fromStage, toStage | MissionStage | One of 11 granular stages |
triggerType | TransitionTrigger | MANUAL / AUTOMATIC / FORCE |
actorId, actorName | String? | Who triggered the transition |
Fleet
Vehicle
| Field | Type | Notes |
|---|---|---|
vehicleCategoryId | String | Required — links to VehicleCategory |
operatingBaseId | String | Home base/garage |
registrationNumber | String | Unique per org |
status | VehicleStatus | ACTIVE / MAINTENANCE / OUT_OF_SERVICE / ARCHIVED / SOLD |
consumptionLPer100Km | Decimal? | For fuel cost calculation |
purchasePrice | Decimal? | TCO field |
expectedLifespanKm | Int? | For depreciation calculation |
VehicleCategory
Groups vehicles commercially and regulatorily.
| Field | Type | Notes |
|---|---|---|
code | String | Unique per org (e.g. SEDAN, VAN) |
regulatoryCategory | VehicleRegulatoryCategory | LIGHT / HEAVY |
maxPassengers | Int | Capacity constraint |
priceMultiplier | Decimal | Multiplier applied in the pricing engine (default 1.0) |
Driver
| Field | Type | Notes |
|---|---|---|
employmentStatus | DriverEmploymentStatus | EMPLOYEE / CONTRACTOR / FREELANCE |
hourlyCost | Decimal? | For cost calculations |
isActive | Boolean | Soft-delete flag |
homeLat, homeLng | Decimal? | Home location for deadhead distance |
preferredLanguage | String | ISO-2 code for driver-facing documents |
Related models: DriverLicense (M:N with LicenseCategory), DriverCalendarEvent (absences), DriverRSECounter (daily RSE compliance counters).
Finance
Invoice
Immutable financial document derived from accepted quotes.
| Field | Type | Notes |
|---|---|---|
number | String | Unique per org (e.g. INV-2026-001) |
invoiceType | InvoiceType | STANDARD / CREDIT_NOTE / SUPPLEMENT |
status | InvoiceStatus | DRAFT / ISSUED / PARTIAL / PAID / CANCELLED |
totalExclVat | Decimal | Total HT |
totalVat | Decimal | Total VAT amount |
totalInclVat | Decimal | Total TTC |
paidAmount | Decimal | Running paid amount (for partial payment tracking) |
commissionHT | Decimal? | Partner commission excl. tax |
commissionTTC | Decimal? | Partner commission incl. tax |
language | String | PDF rendering language |
InvoiceLine
| Field | Type | Notes |
|---|---|---|
unitPriceExclVat | Decimal | HT unit price, precision (10,4) |
vatRate | Decimal | Decimal percent (e.g. 20.00 = 20 %), precision (5,2) |
totalExclVat | Decimal | Stored for immutability |
quoteLineId | String? | Traceability back to source QuoteLine |
BankAccount
Multi-account support per organization, with per-contact and per-document overrides.
| Field | Type | Notes |
|---|---|---|
iban | String | IBAN (max 34 chars) |
isDefault | Boolean | Org-wide default account |
isActive | Boolean | Soft-delete flag |
currency | String | ISO 4217 (default EUR) |
Phase 2 — Real-time & Portal Entities
AgencyPortalUser
Links a Better Auth User to an agency Contact with granular portal permissions.
| Field | Type | Notes |
|---|---|---|
agencyId | String | The PARTNER/AGENCY Contact this user belongs to |
role | PortalUserRole | ADMIN / OPERATOR / MEMBER |
status | PortalUserStatus | PENDING / ACTIVE / INACTIVE |
canCreateQuotes | Boolean | Portal permission flags |
canViewInvoices | Boolean | Portal permission flags |
DriverLocation
Latest driver GPS position (upsert pattern — one row per driver).
| Field | Type | Notes |
|---|---|---|
driverId | String | Unique — one row per driver |
lat, lng | Float | Current position |
heading, speed | Float? | Optional motion data |
DriverLocationHistory stores the full breadcrumb trail. missionId is nullable so the trail records even between missions.
TrackingToken
Public magic link for customer tracking.
| Field | Type | Notes |
|---|---|---|
token | String | cuid(2), URL-safe unique |
missionId | String | Linked mission |
expiresAt | DateTime | Auto-expire after gracePeriodMinutes past completion |
language | String | ISO-2, resolved at mint time from contact preference |
langLocked | Boolean | Operator-pinned language — ignores URL param auto-resolution |
Pricing Engine Entities
OrganizationPricingSettings
Single-row settings per organization (1:1 with Organization).
Key fields: baseRatePerKm, baseRatePerHour, defaultMarginPercent, defaultVatRate (default 10.00), zone conflict/aggregation strategies, MAD configuration.
PricingZone
Geographic zone used in Method 1 (fixed-grid) pricing.
| Field | Type | Notes |
|---|---|---|
code | String | Unique per org (e.g. PARIS_0, CDG) |
zoneType | ZoneType | POLYGON / RADIUS / POINT / CORRIDOR |
priceMultiplier | Decimal | Applied to base fare (default 1.0) |
isCentralZone | Boolean | Priority-1 flat rate zone flag |
priority | Int | Conflict resolution priority |
ZoneRoute
Zone-to-zone fixed price grid entry for TRANSFER trips.
| Field | Type | Notes |
|---|---|---|
vehicleCategoryId | String | Required |
fixedPrice | Decimal | Grid price |
priceMode | PriceMode | HT / TTC — indicates how fixedPrice is stored |
vatRate | Decimal | Decimal percent (default 10.00) |
direction | RouteDirection | BIDIRECTIONAL / A_TO_B / B_TO_A |
Grid prices (
ZoneRoute.fixedPrice,ExcursionPackage.price,DispoPackage.basePrice) may be stored as HT or TTC depending onpriceMode. CheckpriceModebefore interpreting the value.