Skip to content

Commit 38ee6fc

Browse files
committed
Added proper fix/refactor to use getServicableForPlaces function on ServiceRate model
1 parent 8e8d00e commit 38ee6fc

3 files changed

Lines changed: 100 additions & 33 deletions

File tree

server/src/Http/Controllers/Api/v1/ContactController.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
use Fleetbase\FleetOps\Http\Resources\v1\DeletedResource;
99
use Fleetbase\FleetOps\Models\Contact;
1010
use Fleetbase\Http\Controllers\Controller;
11-
use Fleetbase\Models\File;
1211
use Fleetbase\Models\User;
1312
use Fleetbase\Support\Utils;
1413
use Illuminate\Http\Request;

server/src/Http/Controllers/Api/v1/DriverController.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
use Fleetbase\LaravelMysqlSpatial\Types\Point;
2121
use Fleetbase\Models\Company;
2222
use Fleetbase\Models\CompanyUser;
23-
use Fleetbase\Models\File;
2423
use Fleetbase\Models\User;
2524
use Fleetbase\Models\UserDevice;
2625
use Fleetbase\Models\VerificationCode;

server/src/Models/ServiceRate.php

Lines changed: 100 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
use Fleetbase\Traits\HasUuid;
1313
use Fleetbase\Traits\SendsWebhooks;
1414
use Fleetbase\Traits\TracksApiCredential;
15-
use Illuminate\Support\Facades\DB;
1615

1716
class ServiceRate extends Model
1817
{
@@ -469,12 +468,11 @@ public static function getServicableForWaypoints($waypoints = [], ?\Closure $que
469468
*/
470469
public static function getServicableForPlaces($places = [], $service = null, $currency = null, ?\Closure $queryCallback = null): array
471470
{
472-
$reader = new GeoJSONReader();
473-
$applicableServiceRates = [];
474-
$serviceRatesQuery = static::with(['zone', 'serviceArea', 'rateFees', 'parcelFees']);
471+
$reader = new GeoJSONReader();
472+
$serviceRatesQuery = static::with(['zone', 'serviceArea', 'rateFees', 'parcelFees']);
475473

476474
if ($currency) {
477-
$serviceRatesQuery->where(DB::raw('lower(currency)'), strtolower($currency));
475+
$serviceRatesQuery->whereRaw('lower(currency) = ?', [strtolower($currency)]);
478476
}
479477

480478
if ($service) {
@@ -487,44 +485,115 @@ public static function getServicableForPlaces($places = [], $service = null, $cu
487485

488486
$serviceRates = $serviceRatesQuery->get();
489487

490-
$waypoints = collect($places)->map(function ($place) {
491-
$place = Place::createFromMixed($place);
488+
$waypoints = collect($places)
489+
->map(function ($place) {
490+
$place = Place::createFromMixed($place);
491+
492+
if (!$place instanceof Place) {
493+
return null;
494+
}
492495

493-
if ($place instanceof Place) {
494496
$point = $place->getLocationAsPoint();
495497

496-
// Conver to brick gis point
497-
return \Brick\Geo\Point::fromText(sprintf('POINT (%F %F)', $point->getLng(), $point->getLat()), 4326);
498+
// Brick point: X=lng, Y=lat (WKT order)
499+
return \Brick\Geo\Point::fromText(
500+
sprintf('POINT (%F %F)', $point->getLng(), $point->getLat()),
501+
4326
502+
);
503+
})
504+
->filter()
505+
->values();
506+
507+
if ($waypoints->isEmpty()) {
508+
return [];
509+
}
510+
511+
/**
512+
* Convert a casted spatial geometry (Zone::border / ServiceArea::border)
513+
* into a Brick geometry using GeoJSONReader.
514+
*/
515+
$toBrickGeometry = function ($spatialGeometry) use ($reader) {
516+
if (!$spatialGeometry) {
517+
return null;
518+
}
519+
520+
// Most Fleetbase spatial casts/types implement toJson()
521+
if (is_object($spatialGeometry) && method_exists($spatialGeometry, 'toJson')) {
522+
$json = $spatialGeometry->toJson();
523+
$json = is_string($json) ? trim($json) : null;
524+
525+
if ($json) {
526+
return $reader->read($json);
527+
}
528+
529+
return null;
530+
}
531+
532+
// Fallback if the cast ever returns array/object
533+
if (is_array($spatialGeometry) || is_object($spatialGeometry)) {
534+
$json = json_encode($spatialGeometry, JSON_UNESCAPED_UNICODE);
535+
if ($json && $json !== 'null') {
536+
return $reader->read($json);
537+
}
538+
}
539+
540+
// Fallback if it’s a raw JSON string
541+
if (is_string($spatialGeometry) && trim($spatialGeometry) !== '') {
542+
return $reader->read($spatialGeometry);
543+
}
544+
545+
return null;
546+
};
547+
548+
/**
549+
* Ensure ALL waypoints are inside the given Brick geometry.
550+
*/
551+
$containsAllWaypoints = function ($brickGeometry) use ($waypoints): bool {
552+
if (!$brickGeometry) {
553+
return false;
498554
}
499-
});
555+
556+
foreach ($waypoints as $waypoint) {
557+
if (!$brickGeometry->contains($waypoint)) {
558+
return false;
559+
}
560+
}
561+
562+
return true;
563+
};
564+
565+
$applicableServiceRates = [];
500566

501567
foreach ($serviceRates as $serviceRate) {
568+
// If a service area exists, all waypoints must be inside its border
502569
if ($serviceRate->hasServiceArea()) {
503-
// make sure all waypoints fall within the service area
504-
foreach ($serviceRate->serviceArea->border as $polygon) {
505-
$polygon = $reader->read($polygon->toJson());
506-
507-
/** @var \Brick\Geo\Point $waypoint */
508-
foreach ($waypoints as $waypoint) {
509-
if (!$polygon->contains($waypoint)) {
510-
// waypoint outside of service area, not applicable to route
511-
continue;
512-
}
513-
}
570+
$serviceAreaBorder = $serviceRate->serviceArea?->border;
571+
572+
$serviceAreaGeom = null;
573+
try {
574+
$serviceAreaGeom = $toBrickGeometry($serviceAreaBorder);
575+
} catch (\Throwable $e) {
576+
continue; // invalid geojson / geometry -> reject this rate
577+
}
578+
579+
if (!$containsAllWaypoints($serviceAreaGeom)) {
580+
continue;
514581
}
515582
}
516583

584+
// If a zone exists, all waypoints must be inside its border
517585
if ($serviceRate->hasZone()) {
518-
// make sure all waypoints fall within the service area
519-
foreach ($serviceRate->zone->border as $polygon) {
520-
$polygon = $reader->read($polygon->toJson());
586+
$zoneBorder = $serviceRate->zone?->border;
521587

522-
foreach ($waypoints as $waypoint) {
523-
if (!$polygon->contains($waypoint)) {
524-
// waypoint outside of zone, not applicable to route
525-
continue;
526-
}
527-
}
588+
$zoneGeom = null;
589+
try {
590+
$zoneGeom = $toBrickGeometry($zoneBorder);
591+
} catch (\Throwable $e) {
592+
continue;
593+
}
594+
595+
if (!$containsAllWaypoints($zoneGeom)) {
596+
continue;
528597
}
529598
}
530599

0 commit comments

Comments
 (0)