Data Models
The Tanqueo Backend API uses TypeScript interfaces to define data models with strong type safety. All interfaces are defined in src/types/index.ts.
Core Entities
Usuario (User)
Represents authenticated users in the system:
export interface Usuario {
id : string ; // UUID from Supabase Auth
email : string ; // User email address
nombre : string ; // Full name
rol : string ; // User role (admin, operator, etc.)
creado_en ?: string ; // Creation timestamp
}
Usage:
Attached to req.user after authentication
Retrieved from usuarios table joined with Supabase Auth
AuthRequest
Extended Express Request with authentication data:
import { Request } from 'express' ;
import { SupabaseClient } from '@supabase/supabase-js' ;
export interface AuthRequest extends Request {
user ?: Usuario ; // Authenticated user
accessToken ?: string ; // JWT access token
supabase ?: SupabaseClient ; // User-authenticated Supabase client
}
Usage:
All protected route handlers receive AuthRequest
req.supabase has RLS policies applied automatically
Authentication Models
LoginRequest
export interface LoginRequest {
email : string ;
password : string ;
}
LoginResponse
export interface LoginResponse {
user : Usuario ;
access_token : string ;
refresh_token : string ;
expires_at : number ; // Unix timestamp
expires_in : number ; // Seconds (typically 3600)
}
Example:
{
"user" : {
"id" : "a1b2c3d4-e5f6-7890-abcd-ef1234567890" ,
"email" : "[email protected] " ,
"nombre" : "Juan Pérez" ,
"rol" : "admin"
},
"access_token" : "eyJhbGci..." ,
"refresh_token" : "v1.MRjrcL..." ,
"expires_at" : 1709564400 ,
"expires_in" : 3600
}
Fuel Tracking (Tanqueos)
Tanqueo
Base entity for fuel operations:
export interface Tanqueo {
id ?: number ;
fecha : string ; // Date (YYYY-MM-DD)
// Optional fields depending on operation type
conductor_id ?: number | null ;
placa_id ?: number | null ;
tipo_combustible ?: string | null ; // DIESEL, GASOLINA, etc.
valor_tanqueo ?: number | null ; // Total cost
cantidad_galones ?: number | null ; // Gallons refueled
costo_por_galon ?: number | null ; // Cost per gallon
valor_anticipo ?: number | null ; // Advance payment
saldo_disponible ?: number | null ; // Available balance
// Required fields
bomba_id : number ; // Fuel pump ID
area_operacion_id : number ; // Operating area ID
concepto : string ; // Concept/reason
tipo_operacion : string ; // TANQUEO, ANTICIPO, etc.
observacion ?: string | null ; // Notes
horometro ?: number | null ; // Hour meter reading
// Audit fields
creado_por ?: string ;
actualizado_por ?: string ;
actualizado_en ?: string ;
}
TanqueoRelacion
Enriched view with joined relationships:
export interface TanqueoRelacion {
idx : number ; // Row index
id : number ;
fecha : string ;
// Foreign key IDs
conductor_id : number ;
placa_id : number ;
bomba_id : number ;
area_operacion_id : number ;
// Joined display values
conductor : string ; // Driver name
placa : string ; // Vehicle plate
bomba : string ; // Pump name
area_operacion : string ; // Area name
// Fuel data
tipo_combustible : string ;
valor_tanqueo : number ;
cantidad_galones : number ;
horometro : number | null ;
costo_por_galon : number | null ;
valor_anticipo : number | null ;
saldo_disponible : number ;
concepto : string ;
tipo_operacion : string ;
observacion : string | null ;
}
Example:
{
"id" : 1542 ,
"fecha" : "2026-03-04" ,
"conductor" : "Juan Pérez" ,
"placa" : "ABC123" ,
"bomba" : "Bomba Central" ,
"area_operacion" : "Zona Norte" ,
"tipo_combustible" : "DIESEL" ,
"valor_tanqueo" : 250000 ,
"cantidad_galones" : 50 ,
"costo_por_galon" : 5000 ,
"concepto" : "Operación rutina" ,
"tipo_operacion" : "TANQUEO"
}
TanqueoFilters
export interface TanqueoFilters {
conductor ?: string ; // Partial match
placa ?: string ; // Partial match
bomba ?: string ; // Partial match
area_operacion ?: string ; // Partial match
tipo_combustible ?: string ; // Exact match
concepto ?: string ; // Exact match
fecha_inicio ?: string ; // Greater than or equal
fecha_fin ?: string ; // Less than or equal
}
PaginatedResponse
export interface PaginatedResponse {
data : TanqueoRelacion [];
pagination : {
page : number ;
limit : number ;
total : number ;
totalPages : number ;
};
}
Maintenance (Engrases)
Engrase
export interface Engrase {
id ?: number ;
fecha : string ;
conductor_id : number ;
placa_id : number ;
area_operacion_id : number ;
// Service costs
lavado : number ; // Wash cost
engrase : number ; // Lubrication cost
otros : number ; // Other costs
suma ?: number ; // Total (calculated)
observaciones ?: string | null ;
// Audit fields
creado_por ?: string ;
actualizado_por ?: string ;
actualizado_en ?: string ;
}
EngraseRelacion
export interface EngraseRelacion {
idx : number ;
id : number ;
fecha : string ;
conductor_id : number ;
conductor : string ; // Joined name
placa_id : number ;
placa : string ; // Joined plate
area_operacion_id : number ;
area_operacion : string ; // Joined area
lavado : number ;
engrase : number ;
otros : number ;
suma : number ; // Total cost
observaciones : string | null ;
}
Document Management
DocumentoVehiculo
export interface DocumentoVehiculo {
id ?: number ;
placa_id : number ;
area_operacion_id : number ;
// Expiration dates
fecha_vencimiento_soat ?: string | null ; // SOAT (mandatory insurance)
fecha_vencimiento_rtm ?: string | null ; // Technical review
fecha_vencimiento_poliza ?: string | null ; // Insurance policy
// Document files (URLs or paths)
pdf_soat ?: string | null ;
pdf_rtm ?: string | null ;
tarjeta_propiedad ?: string | null ; // Property card
pdf_poliza ?: string | null ;
creado_por ?: string ;
actualizado_por ?: string ;
actualizado_en ?: string ;
}
Fleet Management
Vehiculo
export interface Vehiculo {
id : number ;
placa_id : number ;
empresa_id : number | null ;
operacion_id : number | null ;
created_at ?: string ;
// Relations (populated when joined)
areas_placas ?: { placa : string };
empresas ?: { empresa : string };
areas_operacion ?: { nombre : string };
vehiculo_caracteristicas ?: VehiculoCaracteristicas ;
}
VehiculoCaracteristicas
export interface VehiculoCaracteristicas {
vehiculo_id : number ;
// Foreign keys to catalog tables
marca_id : number | null ;
tipo_vehiculo_id : number | null ;
clase_vehiculo_id : number | null ;
combustible_id : number | null ;
marca_compactadora_id : number | null ;
// Specifications
nro_ejes : string | null ; // Number of axles
nro_llantas : string | null ; // Number of tires
anio : string | null ; // Year (text field)
linea : string | null ; // Model line
nro_serie : string | null ; // Serial number
// Relations
cat_marca ?: CatMarca ;
cat_tipo_vehiculo ?: CatTipoVehiculo ;
cat_clase_vehiculo ?: CatClaseVehiculo ;
cat_combustible ?: CatCombustible ;
cat_marca_compactadora ?: CatMarcaCompactadora ;
}
Catalog Entities
export interface CatMarca {
id : number ;
nombre : string ;
}
export interface CatTipoVehiculo {
id : number ;
nombre : string ;
}
export interface CatClaseVehiculo {
id : number ;
nombre : string ;
}
export interface CatCombustible {
id : number ;
nombre : string ;
}
export interface CatMarcaCompactadora {
id : number ;
nombre : string ;
}
Budget Management
MaestroRubro
Hierarchical budget categories:
export interface MaestroRubro {
id : number ;
nivel : number ; // Hierarchy level
codigo : string ;
nombre : string ;
tipo : 'DEPENDENCIA' | 'GRUPO_RUBRO' | 'RUBRO' ;
codigo_concatenado : string | null ;
abreviatura : string | null ;
activo : boolean ;
rubro_padre_id : number | null ; // Parent category
}
Presupuesto
export interface Presupuesto {
id ?: number ;
empresa_id : number ;
vehiculo_id : number | null ;
area_operacion_id : number ;
grupo_rubro_id : number ;
rubro_id : number ;
anio : number ; // Budget year
estado : 'BORRADOR' | 'APROBADO' ; // Draft or approved
empleado_id ?: number | null ;
created_at ?: string ;
}
PresupuestoItem
export interface PresupuestoItem {
id ?: number ;
presupuesto_id : number ;
tipo_presupuesto_id : number ;
concepto_presupuesto_id : number ;
frecuencia_mes : number ; // Monthly frequency
meses_aplicables : number []; // Array: [1,2,3,...,12]
valor_unitario : number ;
valor_total : number ;
}
PresupuestoConItems
Complete budget with line items:
export interface PresupuestoConItems extends Presupuesto {
items : PresupuestoItem [];
// Joined relations
vehiculo ?: { placa : string };
area_operacion ?: { nombre : string };
grupo_rubro ?: { nombre : string ; codigo : string };
rubro ?: { nombre : string ; codigo : string };
}
Maintenance Planning
TipoMantenimiento
export interface TipoMantenimiento {
id : number ;
tipo : string ; // PREVENTIVO, CORRECTIVO, etc.
}
PlanMantenimiento
export interface PlanMantenimiento {
id : number ;
vehiculo_id : number ;
tipo_mantenimiento_id : number ;
nombre : string ;
activo : boolean ;
// Relations
vehiculo ?: Vehiculo ;
tipo_mantenimiento ?: TipoMantenimiento ;
condiciones ?: PlanCondicion [];
}
PlanCondicion
Maintenance trigger conditions:
export interface PlanCondicion {
id : number ;
plan_id : number ;
tipo_condicion_id : number ;
valor : number ; // Threshold value
unidad : string ; // Unit (km, hours, days, etc.)
tipo_condicion ?: TipoCondicion ;
}
export interface TipoCondicion {
id : number ;
codigo : string ;
nombre : string ;
}
MantenimientoEvento
Actual maintenance performed:
export interface MantenimientoEvento {
id : number ;
plan_id : number ;
vehiculo_id : number ;
fecha : string ;
descripcion : string | null ;
taller_id : number | null ; // Workshop/garage
costo : number | null ;
hr_evento : number | null ; // Hour meter at event
km_evento : number | null ; // Odometer at event
observaciones : string | null ;
// Relations
plan_mantenimiento ?: PlanMantenimiento ;
vehiculo ?: Vehiculo ;
talleres ?: { nombre : string };
}
Type Safety Benefits
TypeScript interfaces provide:
Compile-Time Validation Catch type errors before runtime
IDE Autocomplete IntelliSense support in editors
Documentation Self-documenting code with type hints
Refactoring Safety Rename and restructure with confidence
Using Types in Controllers
Example controller with proper typing:
import { AuthRequest , Tanqueo , TanqueoRelacion , PaginatedResponse } from '../types' ;
export const tanqueosController = {
async getAll ( req : AuthRequest , res : Response ) : Promise < void > {
// TypeScript knows req.user exists and has Usuario shape
const userId = req . user ?. id ;
// TypeScript validates query result matches TanqueoRelacion[]
const { data , error } = await supabase
. from ( 'tanqueo_relaciones' )
. select ( '*' );
// Response type is enforced
const response : PaginatedResponse = {
data: data || [],
pagination: { /* ... */ }
};
res . json ( response );
}
};
Database Schema Alignment
TypeScript interfaces should match the PostgreSQL schema. When the database schema changes, update the corresponding interfaces in src/types/index.ts.
Nullable fields in the database (null allowed) must be marked with | null in TypeScript to accurately reflect the data model.