Skip to main content

Overview

The Vehicle Management module is the core of MotorDesk’s fleet management system. It tracks vehicle information, maintenance schedules, kilometer-based service intervals, and provides complete service history with direct integration to the billing module.

Core Capabilities

  • Fleet registry with detailed vehicle information
  • Owner and driver relationship management
  • Kilometer-based maintenance tracking
  • Service history with product details
  • Direct sales invoice generation
  • Maintenance alerts for upcoming services

Vehicle Data Model

Each vehicle record contains comprehensive information:
interface Vehicle {
  id: string;
  propietarioId: string;          // Owner (customer ID)
  conductorHabitualId: string | null;  // Habitual driver (customer ID)
  placa: string;                  // License plate
  marca: string;                  // Brand
  modelo: string;                 // Model
  anio: number;                   // Year
  color: string;                  // Color
  kilometrajeActual: number;      // Current mileage
  createdAt: string;
  syncedAt: string;
  isDeleted: boolean;
}

Example Vehicle Record

{
  id: "veh-001",
  propietarioId: "cust-001",
  conductorHabitualId: "cust-002",
  placa: "ABC-123",
  marca: "Toyota",
  modelo: "Hilux",
  anio: 2020,
  color: "Blanco",
  kilometrajeActual: 45000,
  createdAt: "2023-10-25T10:00:00Z",
  syncedAt: "2023-10-25T10:01:00Z",
  isDeleted: false
}

Enhanced Vehicle Data Mapping

The system enriches vehicle data with relational information from customers, sales, and products:
const mappedVehicles = useMemo(() => {
  return vehiclesData.vehicles.filter(v => !v.isDeleted).map(v => {
    // Get owner and driver information
    const cliente = customersData.customers.find(c => c.id === v.propietarioId);
    const chofer = customersData.customers.find(c => c.id === v.conductorHabitualId);
    
    // Get all sales for this vehicle, sorted by date (newest first)
    const vehSales = salesData.sales
      .filter(s => s.vehicleId === v.id)
      .sort((a, b) => new Date(b.fechaEmision).getTime() - new Date(a.fechaEmision).getTime());
    
    const latestSale = vehSales[0];
    
    // Build complete service history with product details
    const historialConProductos = vehSales.map(sale => {
      const items = saleDetailsData.saleDetails
        .filter(si => si.saleId === sale.id)
        .map(si => {
          const prod = productsData.products.find(p => p.id === si.productId);
          return { ...si, productName: prod?.nombre || 'Producto no encontrado' };
        });
      return { ...sale, items };
    });
    
    return {
      ...v,
      clienteNombre: cliente?.nombreRazonSocial || 'Desconocido',
      clienteDocumento: cliente?.numeroDocumento || '',
      choferNombre: chofer?.nombreRazonSocial || 'Sin chofer',
      kmActual: latestSale?.kilometrajeIngreso || v.kilometrajeActual || 0,
      kmProximo: latestSale?.proximoCambioKm || 0,
      historial: historialConProductos,
    };
  });
}, []);

Vehicle Fleet Table

The main fleet view displays vehicles with real-time maintenance status:
1

Vehicle Identification

Shows license plate prominently with brand, model, and year information.
2

Customer Relationships

Displays both the vehicle owner (building icon) and habitual driver (user icon).
3

Mileage Tracking

Current mileage and next service interval with visual alerts when maintenance is due.
4

Quick Actions

View details, edit information, or delete vehicle records.

Table Implementation

// Vehicle table row (src/pages/Vehicles.tsx:92)
<tr key={vehicle.id} className={styles.tableRow}>
  <td>
    <strong className={styles.vehiclePlaca}>
      {vehicle.placa}
    </strong>
    <span className={styles.vehicleDetails}>
      {vehicle.marca} {vehicle.modelo} ({vehicle.anio})
    </span>
  </td>
  <td>
    <span className={styles.customerInfo}>
      <Building2 className={styles.customerIcon} />
      {vehicle.clienteNombre}
    </span>
    <span className={styles.driverInfo}>
      <User className={styles.driverIcon} />
      {vehicle.choferNombre}
    </span>
  </td>
  <td>
    <span className={styles.kmActualBadge}>
      Act: {vehicle.kmActual.toLocaleString()} km
    </span>
    <span className={`${styles.kmNextBadgeBase} ${
      vehicle.kmActual >= vehicle.kmProximo - 1000
        ? styles.kmNextBadgeAlert
        : styles.kmNextBadgeNormal
    }`}>
      Próx: {vehicle.kmProximo.toLocaleString()} km
      {vehicle.kmActual >= vehicle.kmProximo - 1000 && (
        <AlertTriangle className={styles.kmAlertIcon} />
      )}
    </span>
  </td>
</tr>

Maintenance Alerts

The system automatically displays an alert icon when a vehicle is within 1,000 km of its next scheduled service, helping prevent missed maintenance.

Alert Logic

// Alert when within 1000km of next service
{vehicle.kmActual >= vehicle.kmProximo - 1000 && (
  <AlertTriangle className={styles.kmAlertIcon} />
)}

Search and Filtering

The vehicle module supports multi-field search:
const filteredVehicles = useMemo(() => {
  return mappedVehicles.filter((v) => {
    const term = searchTerm.toLowerCase();
    return (
      v.placa.toLowerCase().includes(term) ||
      v.clienteNombre.toLowerCase().includes(term) ||
      v.marca.toLowerCase().includes(term) ||
      v.modelo.toLowerCase().includes(term)
    );
  });
}, [mappedVehicles, searchTerm]);

Searchable Fields

  • License plate (placa)
  • Owner name (clienteNombre)
  • Vehicle brand (marca)
  • Vehicle model (modelo)

Service History and Billing Integration

One of MotorDesk’s most powerful features is the seamless integration between vehicle service history and the billing module.

Generating New Sales

const handleEmitirFactura = (vehicle: any, pastSale?: any) => {
  closeModal();
  
  let productosParaCart: any[] = [];
  let observacionSugerida = "";
  
  // Repeat past service - pre-populate cart with previous products
  if (pastSale && pastSale.items && pastSale.items.length > 0) {
    pastSale.items.forEach((item: any) => {
      const fullProduct = productsData.products.find(p => p.id === item.productId);
      if (fullProduct) {
        productosParaCart.push({
          ...fullProduct,
          cantidad: item.cantidad,
          precioUnitario: fullProduct.precioVenta
        });
      }
    });
    observacionSugerida = `Servicio basado en el historial del ${new Date(pastSale.fechaEmision).toLocaleDateString()}.`;
  } else {
    // New blank sale
    observacionSugerida = `Atención al vehículo placa ${vehicle.placa}.`;
  }
  
  // Navigate to sales module with pre-filled data
  navigate('/sales', {
    state: {
      prefillData: {
        vehicleId: vehicle.id,
        customerId: vehicle.propietarioId,
        choferId: vehicle.conductorHabitualId,
        placa: vehicle.placa,
        cartItems: productosParaCart,
        observacionSugerida,
        kilometrajeActual: vehicle.kmActual || 0,
        kmProximo: pastSale ? pastSale.proximoCambioKm : 0
      }
    }
  });
};
Creates a blank sales invoice with the vehicle’s plate number and current mileage pre-filled, ready for adding new services.
Automatically populates the shopping cart with products from a previous service, maintaining the same quantities and suggesting the next service interval.

Vehicle CRUD Operations

Adding Vehicles

The vehicle form modal allows creating new vehicle records:
const handleSaveVehicle = (data: any) => {
  console.log("Datos a guardar:", data);
  alert(`Vehículo ${data.placa} guardado correctamente (Simulación)`);
  closeModal();
};

Editing Vehicles

Edit existing vehicle information while maintaining service history and relationships.

Deleting Vehicles

Vehicle deletion is a soft delete operation (sets isDeleted: true) to preserve service history and maintain data integrity.
const handleDeleteVehicle = (id: string) => {
  console.log("Eliminando vehículo con ID:", id);
  alert("Vehículo eliminado correctamente (Simulación)");
  closeModal();
};

Pagination Controls

The vehicle list supports configurable pagination:
const totalPages = Math.ceil(filteredVehicles.length / itemsPerPage);
const currentVehicles = useMemo(() => {
  const startIndex = (currentPage - 1) * itemsPerPage;
  return filteredVehicles.slice(startIndex, startIndex + itemsPerPage);
}, [filteredVehicles, currentPage, itemsPerPage]);

Page Size Options

Display 5, 10, 20, or 50 vehicles per page for optimal viewing based on your fleet size.
The vehicle module uses three specialized modals:
1

VehicleDetailsModal

Complete vehicle profile including:
  • Full vehicle specifications
  • Owner and driver information
  • Complete service history with products
  • Direct billing buttons for new or repeat services
2

VehicleFormModal

Add or edit vehicle information with customer selection dropdowns for owner and driver assignment.
3

VehicleDeleteModal

Confirmation dialog before soft-deleting a vehicle record.

Best Practices

Fleet Management Tips

  • Update mileage with each service to maintain accurate maintenance schedules
  • Use the repeat service feature to ensure consistent maintenance
  • Monitor alert indicators for upcoming services
  • Assign habitual drivers to improve service record accuracy
  • Review service history before scheduling new maintenance

Build docs developers (and LLMs) love