Logistics platforms require real-time tracking. GPS coordinates, route optimization, and driver management create complex systems. At ZIRA Software, we've built logistics platforms tracking thousands of deliveries daily.
Core Features
Essential logistics features:
- Real-time GPS tracking
- Driver management
- Order assignment
- Route optimization
- Delivery status updates
- Customer notifications
- Analytics and reporting
Database Schema
// Drivers
Schema::create('drivers', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('phone');
$table->string('license_number');
$table->string('vehicle_type');
$table->string('vehicle_plate');
$table->enum('status', ['available', 'busy', 'offline'])->default('offline');
$table->decimal('current_latitude', 10, 7)->nullable();
$table->decimal('current_longitude', 10, 7)->nullable();
$table->timestamp('last_location_update')->nullable();
$table->timestamps();
});
// Orders/Deliveries
Schema::create('deliveries', function (Blueprint $table) {
$table->id();
$table->foreignId('driver_id')->nullable()->constrained();
$table->string('tracking_number')->unique();
$table->string('customer_name');
$table->string('customer_phone');
$table->string('pickup_address');
$table->decimal('pickup_latitude', 10, 7);
$table->decimal('pickup_longitude', 10, 7);
$table->string('delivery_address');
$table->decimal('delivery_latitude', 10, 7);
$table->decimal('delivery_longitude', 10, 7);
$table->enum('status', ['pending', 'assigned', 'picked_up', 'in_transit', 'delivered', 'cancelled']);
$table->timestamp('scheduled_at')->nullable();
$table->timestamp('picked_up_at')->nullable();
$table->timestamp('delivered_at')->nullable();
$table->timestamps();
});
// Location history
Schema::create('location_logs', function (Blueprint $table) {
$table->id();
$table->foreignId('driver_id')->constrained();
$table->foreignId('delivery_id')->nullable()->constrained();
$table->decimal('latitude', 10, 7);
$table->decimal('longitude', 10, 7);
$table->decimal('speed', 5, 2)->nullable();
$table->decimal('heading', 5, 2)->nullable();
$table->timestamp('recorded_at');
$table->index(['driver_id', 'recorded_at']);
});
Real-Time GPS Tracking
Mobile app sends location updates:
// app/Http/Controllers/Api/LocationController.php
public function updateLocation(Request $request)
{
$validated = $request->validate([
'latitude' => 'required|numeric|between:-90,90',
'longitude' => 'required|numeric|between:-180,180',
'speed' => 'nullable|numeric',
'heading' => 'nullable|numeric|between:0,360',
]);
$driver = $request->user()->driver;
// Update driver current location
$driver->update([
'current_latitude' => $validated['latitude'],
'current_longitude' => $validated['longitude'],
'last_location_update' => now(),
]);
// Log location history
LocationLog::create([
'driver_id' => $driver->id,
'delivery_id' => $driver->currentDelivery?->id,
'latitude' => $validated['latitude'],
'longitude' => $validated['longitude'],
'speed' => $validated['speed'],
'heading' => $validated['heading'],
'recorded_at' => now(),
]);
// Broadcast location update
broadcast(new DriverLocationUpdated($driver));
return response()->json(['message' => 'Location updated']);
}
Real-time broadcasting:
// app/Events/DriverLocationUpdated.php
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class DriverLocationUpdated implements ShouldBroadcast
{
public $driver;
public function __construct(Driver $driver)
{
$this->driver = $driver;
}
public function broadcastOn()
{
return new Channel('drivers');
}
public function broadcastWith()
{
return [
'driver_id' => $this->driver->id,
'latitude' => $this->driver->current_latitude,
'longitude' => $this->driver->current_longitude,
'status' => $this->driver->status,
];
}
}
Driver Assignment Algorithm
Find nearest available driver:
// app/Services/DriverAssignmentService.php
namespace App\Services;
class DriverAssignmentService
{
public function assignNearestDriver(Delivery $delivery)
{
// Haversine formula for distance calculation
$driver = Driver::where('status', 'available')
->selectRaw("
*,
(
6371 * acos(
cos(radians(?)) *
cos(radians(current_latitude)) *
cos(radians(current_longitude) - radians(?)) +
sin(radians(?)) *
sin(radians(current_latitude))
)
) AS distance
", [
$delivery->pickup_latitude,
$delivery->pickup_longitude,
$delivery->pickup_latitude,
])
->having('distance', '<', 10) // Within 10km
->orderBy('distance')
->first();
if (!$driver) {
throw new \Exception('No available drivers nearby');
}
// Assign delivery
$delivery->update([
'driver_id' => $driver->id,
'status' => 'assigned',
]);
$driver->update(['status' => 'busy']);
// Notify driver
$driver->notify(new NewDeliveryAssigned($delivery));
return $driver;
}
public function calculateDistance($lat1, $lon1, $lat2, $lon2)
{
$earthRadius = 6371; // km
$dLat = deg2rad($lat2 - $lat1);
$dLon = deg2rad($lon2 - $lon1);
$a = sin($dLat / 2) * sin($dLat / 2) +
cos(deg2rad($lat1)) * cos(deg2rad($lat2)) *
sin($dLon / 2) * sin($dLon / 2);
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
return $earthRadius * $c;
}
}
Route Optimization
Using Google Maps Directions API:
use GuzzleHttp\Client;
class RouteOptimizationService
{
protected $client;
protected $apiKey;
public function __construct()
{
$this->client = new Client();
$this->apiKey = config('services.google.maps_key');
}
public function optimizeRoute(array $waypoints)
{
$origin = array_shift($waypoints);
$destination = array_pop($waypoints);
$waypointsParam = collect($waypoints)
->map(fn($wp) => "{$wp['lat']},{$wp['lng']}")
->implode('|');
$response = $this->client->get('https://maps.googleapis.com/maps/api/directions/json', [
'query' => [
'origin' => "{$origin['lat']},{$origin['lng']}",
'destination' => "{$destination['lat']},{$destination['lng']}",
'waypoints' => "optimize:true|{$waypointsParam}",
'key' => $this->apiKey,
],
]);
$data = json_decode($response->getBody(), true);
return [
'optimized_order' => $data['routes'][0]['waypoint_order'] ?? [],
'total_distance' => $data['routes'][0]['legs'][0]['distance']['value'] ?? 0,
'total_duration' => $data['routes'][0]['legs'][0]['duration']['value'] ?? 0,
'polyline' => $data['routes'][0]['overview_polyline']['points'] ?? '',
];
}
}
Delivery Status Updates
// app/Http/Controllers/Api/DeliveryController.php
public function updateStatus(Request $request, Delivery $delivery)
{
$validated = $request->validate([
'status' => 'required|in:picked_up,in_transit,delivered',
'notes' => 'nullable|string',
'signature' => 'nullable|image', // For proof of delivery
]);
$oldStatus = $delivery->status;
$delivery->update([
'status' => $validated['status'],
]);
// Update timestamps
switch ($validated['status']) {
case 'picked_up':
$delivery->update(['picked_up_at' => now()]);
break;
case 'delivered':
$delivery->update(['delivered_at' => now()]);
$delivery->driver->update(['status' => 'available']);
break;
}
// Handle signature
if ($request->hasFile('signature')) {
$path = $request->file('signature')->store('signatures');
$delivery->update(['signature_path' => $path]);
}
// Notify customer
$delivery->notifyCustomer();
// Log status change
DeliveryStatusLog::create([
'delivery_id' => $delivery->id,
'old_status' => $oldStatus,
'new_status' => $validated['status'],
'notes' => $validated['notes'],
'updated_by' => $request->user()->id,
]);
return response()->json([
'message' => 'Status updated',
'delivery' => $delivery,
]);
}
Customer Tracking Interface
// app/Http/Controllers/TrackingController.php
public function show($trackingNumber)
{
$delivery = Delivery::where('tracking_number', $trackingNumber)
->with(['driver', 'locationLogs' => function ($query) {
$query->where('recorded_at', '>=', now()->subHours(2))
->orderBy('recorded_at');
}])
->firstOrFail();
return view('tracking.show', compact('delivery'));
}
<!-- resources/views/tracking/show.blade.php -->
<div id="map" style="height: 500px;"></div>
<script>
function initMap() {
const map = new google.maps.Map(document.getElementById('map'), {
zoom: 13,
center: {
lat: {{ $delivery->pickup_latitude }},
lng: {{ $delivery->pickup_longitude }}
}
});
// Pickup marker
new google.maps.Marker({
position: {
lat: {{ $delivery->pickup_latitude }},
lng: {{ $delivery->pickup_longitude }}
},
map: map,
label: 'A',
title: 'Pickup Location'
});
// Delivery marker
new google.maps.Marker({
position: {
lat: {{ $delivery->delivery_latitude }},
lng: {{ $delivery->delivery_longitude }}
},
map: map,
label: 'B',
title: 'Delivery Location'
});
// Driver location (if assigned)
@if($delivery->driver)
const driverMarker = new google.maps.Marker({
position: {
lat: {{ $delivery->driver->current_latitude }},
lng: {{ $delivery->driver->current_longitude }}
},
map: map,
icon: {
url: '/images/delivery-truck.png',
scaledSize: new google.maps.Size(40, 40)
},
title: 'Driver'
});
// Listen for real-time updates
Echo.channel('drivers')
.listen('DriverLocationUpdated', (e) => {
if (e.driver_id === {{ $delivery->driver_id }}) {
driverMarker.setPosition({
lat: e.latitude,
lng: e.longitude
});
}
});
@endif
// Draw route
const directionsService = new google.maps.DirectionsService();
const directionsRenderer = new google.maps.DirectionsRenderer();
directionsRenderer.setMap(map);
directionsService.route({
origin: {
lat: {{ $delivery->pickup_latitude }},
lng: {{ $delivery->pickup_longitude }}
},
destination: {
lat: {{ $delivery->delivery_latitude }},
lng: {{ $delivery->delivery_longitude }}
},
travelMode: 'DRIVING'
}, (response, status) => {
if (status === 'OK') {
directionsRenderer.setDirections(response);
}
});
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key={{ config('services.google.maps_key') }}&callback=initMap">
</script>
Analytics Dashboard
public function dashboard()
{
$metrics = [
'total_deliveries' => Delivery::whereDate('created_at', today())->count(),
'completed' => Delivery::where('status', 'delivered')
->whereDate('delivered_at', today())->count(),
'in_progress' => Delivery::whereIn('status', ['picked_up', 'in_transit'])->count(),
'active_drivers' => Driver::where('status', 'busy')->count(),
'avg_delivery_time' => Delivery::where('status', 'delivered')
->whereDate('delivered_at', today())
->selectRaw('AVG(TIMESTAMPDIFF(MINUTE, picked_up_at, delivered_at)) as avg_time')
->value('avg_time'),
];
return view('dashboard', compact('metrics'));
}
Conclusion
Logistics platforms combine real-time tracking, route optimization, and driver management. Laravel's broadcasting and location services enable scalable delivery systems.
Building a logistics or delivery platform? Contact ZIRA Software for custom development.