Service Areas define the geographic boundaries where Viax operates, ensuring drivers and clients can only request or accept trips within designated zones.
Service area configuration prevents trips outside operational zones and helps manage driver coverage.
Service areas are defined using geographic coordinates:
class ServiceArea { final int id; final String nombre; final String descripcion; final List<LatLng> boundaries; // Polygon coordinates final bool activo; final DateTime creadoEn; final DateTime? actualizadoEn;}
Future<Result<bool>> validateTripLocations({ required LatLng origin, required LatLng destination,}) async { final serviceAreas = await getActiveServiceAreas(); bool originValid = false; bool destinationValid = false; for (final area in serviceAreas) { if (isLocationInServiceArea(origin, area)) { originValid = true; } if (isLocationInServiceArea(destination, area)) { destinationValid = true; } } if (!originValid) { return Error(ValidationFailure( 'El origen está fuera del área de servicio' )); } if (!destinationValid) { return Error(ValidationFailure( 'El destino está fuera del área de servicio' )); } return Success(true);}
CREATE TABLE service_areas ( id INT AUTO_INCREMENT PRIMARY KEY, nombre VARCHAR(100) NOT NULL, descripcion TEXT, activo BOOLEAN DEFAULT TRUE, creado_en TIMESTAMP DEFAULT CURRENT_TIMESTAMP, actualizado_en TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);CREATE TABLE service_area_boundaries ( id INT AUTO_INCREMENT PRIMARY KEY, service_area_id INT NOT NULL, latitud DECIMAL(10, 8) NOT NULL, longitud DECIMAL(11, 8) NOT NULL, orden INT NOT NULL, -- Order of point in polygon FOREIGN KEY (service_area_id) REFERENCES service_areas(id) ON DELETE CASCADE);CREATE TABLE service_area_restrictions ( id INT AUTO_INCREMENT PRIMARY KEY, service_area_id INT NOT NULL, tipo_vehiculo ENUM('moto', 'carro', 'moto_carga', 'carro_carga'), hora_inicio TIME, hora_fin TIME, activo BOOLEAN DEFAULT TRUE, FOREIGN KEY (service_area_id) REFERENCES service_areas(id) ON DELETE CASCADE);
Track which service areas have adequate driver coverage:
class CoverageMetrics { final ServiceArea area; final int activeDrivers; final int minimumRequired; final double averageResponseTime; // seconds bool get hasAdequateCoverage => activeDrivers >= minimumRequired; CoverageStatus get status { if (activeDrivers == 0) return CoverageStatus.noCoverage; if (activeDrivers < minimumRequired * 0.5) return CoverageStatus.low; if (activeDrivers < minimumRequired) return CoverageStatus.medium; return CoverageStatus.high; }}enum CoverageStatus { noCoverage, low, medium, high,}
enum TripAreaPolicy { // Both origin and destination must be in same area sameAreaOnly, // Origin must be in an area, destination can be anywhere originAreaOnly, // Either origin or destination must be in an area eitherInArea, // Both origin and destination must be in areas (can be different) bothInAreas,}bool validateMultiAreaTrip({ required LatLng origin, required LatLng destination, required TripAreaPolicy policy,}) { final originArea = findServiceAreaForLocation(origin); final destArea = findServiceAreaForLocation(destination); switch (policy) { case TripAreaPolicy.sameAreaOnly: return originArea != null && destArea != null && originArea.id == destArea.id; case TripAreaPolicy.originAreaOnly: return originArea != null; case TripAreaPolicy.eitherInArea: return originArea != null || destArea != null; case TripAreaPolicy.bothInAreas: return originArea != null && destArea != null; }}