@fleetbase/fleetops-engine 0.2.6 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitattributes +14 -0
- package/.php-cs-fixer.php +29 -0
- package/LICENSE.md +16 -4
- package/README.md +103 -13
- package/composer.json +85 -0
- package/extension.json +10 -0
- package/package.json +3 -3
- package/phpstan.neon.dist +8 -0
- package/phpunit.xml.dist +16 -0
- package/server/config/api.php +765 -0
- package/server/config/cache.stores.php +18 -0
- package/server/config/dompdf.php +242 -0
- package/server/config/fleetops.php +19 -0
- package/server/config/geocoder.php +108 -0
- package/server/data/globe.json +261 -0
- package/server/migrations/2023_04_27_053456_create_contacts_table.php +49 -0
- package/server/migrations/2023_04_27_053456_create_drivers_table.php +62 -0
- package/server/migrations/2023_04_27_053456_create_entities_table.php +67 -0
- package/server/migrations/2023_04_27_053456_create_fleet_drivers_table.php +39 -0
- package/server/migrations/2023_04_27_053456_create_fleets_table.php +47 -0
- package/server/migrations/2023_04_27_053456_create_fuel_reports_table.php +50 -0
- package/server/migrations/2023_04_27_053456_create_integrated_vendors_table.php +44 -0
- package/server/migrations/2023_04_27_053456_create_issues_table.php +53 -0
- package/server/migrations/2023_04_27_053456_create_orders_table.php +70 -0
- package/server/migrations/2023_04_27_053456_create_payloads_table.php +51 -0
- package/server/migrations/2023_04_27_053456_create_places_table.php +62 -0
- package/server/migrations/2023_04_27_053456_create_positions_table.php +46 -0
- package/server/migrations/2023_04_27_053456_create_proofs_table.php +44 -0
- package/server/migrations/2023_04_27_053456_create_purchase_rates_table.php +46 -0
- package/server/migrations/2023_04_27_053456_create_routes_table.php +40 -0
- package/server/migrations/2023_04_27_053456_create_service_areas_table.php +47 -0
- package/server/migrations/2023_04_27_053456_create_service_quote_items_table.php +42 -0
- package/server/migrations/2023_04_27_053456_create_service_quotes_table.php +47 -0
- package/server/migrations/2023_04_27_053456_create_service_rate_fees_table.php +45 -0
- package/server/migrations/2023_04_27_053456_create_service_rate_parcel_fees_table.php +47 -0
- package/server/migrations/2023_04_27_053456_create_service_rates_table.php +61 -0
- package/server/migrations/2023_04_27_053456_create_tracking_numbers_table.php +46 -0
- package/server/migrations/2023_04_27_053456_create_tracking_statuses_table.php +54 -0
- package/server/migrations/2023_04_27_053456_create_vehicles_table.php +84 -0
- package/server/migrations/2023_04_27_053456_create_vendors_table.php +56 -0
- package/server/migrations/2023_04_27_053456_create_waypoints_table.php +45 -0
- package/server/migrations/2023_04_27_053456_create_zones_table.php +46 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_companies_table.php +32 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_contacts_table.php +34 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_drivers_table.php +40 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_entities_table.php +40 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_fleet_drivers_table.php +34 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_fleets_table.php +36 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_fuel_reports_table.php +36 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_integrated_vendors_table.php +34 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_issues_table.php +38 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_orders_table.php +48 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_payloads_table.php +40 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_places_table.php +32 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_positions_table.php +36 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_proofs_table.php +34 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_purchase_rates_table.php +38 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_routes_table.php +34 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_areas_table.php +34 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_quote_items_table.php +32 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_quotes_table.php +38 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_rate_fees_table.php +32 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_rate_parcel_fees_table.php +32 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_rates_table.php +36 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_tracking_numbers_table.php +34 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_tracking_statuses_table.php +34 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_vehicles_table.php +36 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_vendors_table.php +40 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_waypoints_table.php +38 -0
- package/server/migrations/2023_04_27_053459_add_foreign_keys_to_zones_table.php +34 -0
- package/server/migrations/2023_09_14_074512_update_vehicles_table.php +100 -0
- package/server/migrations/2023_09_14_074619_create_vehicle_devices_table.php +44 -0
- package/server/migrations/2023_09_26_071205_add_online_column_to_vehicles_table.php +32 -0
- package/server/migrations/2023_09_26_083957_create_fleet_vehicles_table.php +45 -0
- package/server/migrations/2023_09_27_023757_add_column_to_fleets_table.php +46 -0
- package/server/migrations/2023_10_05_074811_update_vehicle.php +42 -0
- package/server/resources/views/labels/default.php +165 -0
- package/server/src/Auth/Schemas/FleetOps.php +75 -0
- package/server/src/Casts/MultiPolygon.php +50 -0
- package/server/src/Casts/Point.php +109 -0
- package/server/src/Casts/Polygon.php +46 -0
- package/server/src/Console/Commands/DispatchAdhocOrders.php +137 -0
- package/server/src/Console/Commands/DispatchOrders.php +71 -0
- package/server/src/Console/Commands/TrackOrderDistanceAndTime.php +62 -0
- package/server/src/Events/DriverLocationChanged.php +174 -0
- package/server/src/Events/DriverSimulatedLocationChanged.php +183 -0
- package/server/src/Events/EntityDriverAssigned.php +36 -0
- package/server/src/Events/OrderCanceled.php +15 -0
- package/server/src/Events/OrderCompleted.php +15 -0
- package/server/src/Events/OrderDispatchFailed.php +42 -0
- package/server/src/Events/OrderDispatched.php +15 -0
- package/server/src/Events/OrderDriverAssigned.php +15 -0
- package/server/src/Events/OrderReady.php +15 -0
- package/server/src/Events/OrderStarted.php +15 -0
- package/server/src/Exceptions/IntegratedVendorException.php +18 -0
- package/server/src/Expansions/UserExpansion.php +63 -0
- package/server/src/Exports/ContactExport.php +56 -0
- package/server/src/Exports/DriverExport.php +61 -0
- package/server/src/Exports/FleetExport.php +53 -0
- package/server/src/Exports/PlaceExport.php +55 -0
- package/server/src/Exports/ServiceAreaExport.php +58 -0
- package/server/src/Exports/VehicleExport.php +57 -0
- package/server/src/Exports/VendorExport.php +57 -0
- package/server/src/Http/Controllers/Api/v1/ContactController.php +133 -0
- package/server/src/Http/Controllers/Api/v1/DriverController.php +691 -0
- package/server/src/Http/Controllers/Api/v1/EntityController.php +230 -0
- package/server/src/Http/Controllers/Api/v1/FleetController.php +146 -0
- package/server/src/Http/Controllers/Api/v1/LabelController.php +63 -0
- package/server/src/Http/Controllers/Api/v1/OrderController.php +1114 -0
- package/server/src/Http/Controllers/Api/v1/PayloadController.php +195 -0
- package/server/src/Http/Controllers/Api/v1/PlaceController.php +333 -0
- package/server/src/Http/Controllers/Api/v1/PurchaseRateController.php +199 -0
- package/server/src/Http/Controllers/Api/v1/ServiceAreaController.php +133 -0
- package/server/src/Http/Controllers/Api/v1/ServiceQuoteController.php +381 -0
- package/server/src/Http/Controllers/Api/v1/ServiceRateController.php +223 -0
- package/server/src/Http/Controllers/Api/v1/TrackingNumberController.php +146 -0
- package/server/src/Http/Controllers/Api/v1/TrackingStatusController.php +138 -0
- package/server/src/Http/Controllers/Api/v1/VehicleController.php +191 -0
- package/server/src/Http/Controllers/Api/v1/VendorController.php +159 -0
- package/server/src/Http/Controllers/Api/v1/ZoneController.php +146 -0
- package/server/src/Http/Controllers/FleetOpsController.php +13 -0
- package/server/src/Http/Controllers/Internal/v1/ContactController.php +69 -0
- package/server/src/Http/Controllers/Internal/v1/DriverController.php +261 -0
- package/server/src/Http/Controllers/Internal/v1/EntityController.php +15 -0
- package/server/src/Http/Controllers/Internal/v1/FleetController.php +152 -0
- package/server/src/Http/Controllers/Internal/v1/FleetOpsLookupController.php +80 -0
- package/server/src/Http/Controllers/Internal/v1/FuelReportController.php +15 -0
- package/server/src/Http/Controllers/Internal/v1/GeocoderController.php +96 -0
- package/server/src/Http/Controllers/Internal/v1/IntegratedVendorController.php +63 -0
- package/server/src/Http/Controllers/Internal/v1/IssueController.php +15 -0
- package/server/src/Http/Controllers/Internal/v1/LiveController.php +127 -0
- package/server/src/Http/Controllers/Internal/v1/MetricsController.php +75 -0
- package/server/src/Http/Controllers/Internal/v1/MorphController.php +77 -0
- package/server/src/Http/Controllers/Internal/v1/OrderConfigController.php +269 -0
- package/server/src/Http/Controllers/Internal/v1/OrderController.php +564 -0
- package/server/src/Http/Controllers/Internal/v1/PayloadController.php +15 -0
- package/server/src/Http/Controllers/Internal/v1/PlaceController.php +163 -0
- package/server/src/Http/Controllers/Internal/v1/ProofController.php +139 -0
- package/server/src/Http/Controllers/Internal/v1/PurchaseRateController.php +15 -0
- package/server/src/Http/Controllers/Internal/v1/RouteController.php +15 -0
- package/server/src/Http/Controllers/Internal/v1/ServiceAreaController.php +32 -0
- package/server/src/Http/Controllers/Internal/v1/ServiceQuoteController.php +345 -0
- package/server/src/Http/Controllers/Internal/v1/ServiceRateController.php +47 -0
- package/server/src/Http/Controllers/Internal/v1/SettingController.php +30 -0
- package/server/src/Http/Controllers/Internal/v1/TrackingNumberController.php +15 -0
- package/server/src/Http/Controllers/Internal/v1/TrackingStatusController.php +15 -0
- package/server/src/Http/Controllers/Internal/v1/VehicleController.php +65 -0
- package/server/src/Http/Controllers/Internal/v1/VehicleDeviceController.php +15 -0
- package/server/src/Http/Controllers/Internal/v1/VendorController.php +120 -0
- package/server/src/Http/Controllers/Internal/v1/ZoneController.php +15 -0
- package/server/src/Http/Filter/ContactFilter.php +86 -0
- package/server/src/Http/Filter/DriverFilter.php +148 -0
- package/server/src/Http/Filter/FleetFilter.php +108 -0
- package/server/src/Http/Filter/IntegratedVendorFilter.php +13 -0
- package/server/src/Http/Filter/OrderFilter.php +242 -0
- package/server/src/Http/Filter/PlaceFilter.php +111 -0
- package/server/src/Http/Filter/ServiceAreaFilter.php +13 -0
- package/server/src/Http/Filter/ServiceQuoteFilter.php +13 -0
- package/server/src/Http/Filter/ServiceRateFilter.php +33 -0
- package/server/src/Http/Filter/TrackingStatusFilter.php +43 -0
- package/server/src/Http/Filter/VehicleFilter.php +91 -0
- package/server/src/Http/Filter/VendorFilter.php +83 -0
- package/server/src/Http/Filter/ZoneFilter.php +13 -0
- package/server/src/Http/Requests/CancelOrderRequest.php +31 -0
- package/server/src/Http/Requests/CreateContactRequest.php +33 -0
- package/server/src/Http/Requests/CreateDriverRequest.php +55 -0
- package/server/src/Http/Requests/CreateEntityRequest.php +43 -0
- package/server/src/Http/Requests/CreateFleetRequest.php +32 -0
- package/server/src/Http/Requests/CreateOrderRequest.php +66 -0
- package/server/src/Http/Requests/CreatePayloadRequest.php +37 -0
- package/server/src/Http/Requests/CreatePlaceRequest.php +38 -0
- package/server/src/Http/Requests/CreatePurchaseRateRequest.php +33 -0
- package/server/src/Http/Requests/CreateServiceAreaRequest.php +35 -0
- package/server/src/Http/Requests/CreateServiceQuoteRequest.php +29 -0
- package/server/src/Http/Requests/CreateServiceRateRequest.php +56 -0
- package/server/src/Http/Requests/CreateTrackingNumberRequest.php +34 -0
- package/server/src/Http/Requests/CreateTrackingStatusRequest.php +42 -0
- package/server/src/Http/Requests/CreateVehicleRequest.php +32 -0
- package/server/src/Http/Requests/CreateVendorRequest.php +35 -0
- package/server/src/Http/Requests/CreateZoneRequest.php +35 -0
- package/server/src/Http/Requests/DecodeTrackingNumberQR.php +30 -0
- package/server/src/Http/Requests/DriverSimulationRequest.php +46 -0
- package/server/src/Http/Requests/Internal/AssignOrderRequest.php +31 -0
- package/server/src/Http/Requests/Internal/CreateDriverRequest.php +42 -0
- package/server/src/Http/Requests/Internal/FleetActionRequest.php +32 -0
- package/server/src/Http/Requests/Internal/UpdateDriverRequest.php +7 -0
- package/server/src/Http/Requests/QueryServiceQuotesRequest.php +41 -0
- package/server/src/Http/Requests/UpdateContactRequest.php +20 -0
- package/server/src/Http/Requests/UpdateDriverRequest.php +7 -0
- package/server/src/Http/Requests/UpdateEntityRequest.php +7 -0
- package/server/src/Http/Requests/UpdateFleetRequest.php +7 -0
- package/server/src/Http/Requests/UpdateOrderRequest.php +7 -0
- package/server/src/Http/Requests/UpdatePayloadRequest.php +7 -0
- package/server/src/Http/Requests/UpdatePlaceRequest.php +7 -0
- package/server/src/Http/Requests/UpdatePurchaseRateRequest.php +7 -0
- package/server/src/Http/Requests/UpdateServiceAreaRequest.php +29 -0
- package/server/src/Http/Requests/UpdateServiceQuoteRequest.php +29 -0
- package/server/src/Http/Requests/UpdateServiceRateRequest.php +29 -0
- package/server/src/Http/Requests/UpdateTrackingNumberRequest.php +7 -0
- package/server/src/Http/Requests/UpdateTrackingStatusRequest.php +32 -0
- package/server/src/Http/Requests/UpdateVehicleRequest.php +7 -0
- package/server/src/Http/Requests/UpdateVendorRequest.php +7 -0
- package/server/src/Http/Requests/UpdateZoneRequest.php +7 -0
- package/server/src/Http/Resources/Internal/v1/IntegratedVendorFacilitator.php +37 -0
- package/server/src/Http/Resources/Internal/v1/Vehicle.php +33 -0
- package/server/src/Http/Resources/Internal/v1/Waypoint.php +34 -0
- package/server/src/Http/Resources/v1/Contact.php +62 -0
- package/server/src/Http/Resources/v1/CurrentJob.php +36 -0
- package/server/src/Http/Resources/v1/DeletedResource.php +61 -0
- package/server/src/Http/Resources/v1/Driver.php +89 -0
- package/server/src/Http/Resources/v1/Entity.php +107 -0
- package/server/src/Http/Resources/v1/Fleet.php +60 -0
- package/server/src/Http/Resources/v1/FuelReport.php +67 -0
- package/server/src/Http/Resources/v1/Order.php +131 -0
- package/server/src/Http/Resources/v1/Payload.php +94 -0
- package/server/src/Http/Resources/v1/Place.php +84 -0
- package/server/src/Http/Resources/v1/Proof.php +36 -0
- package/server/src/Http/Resources/v1/PurchaseRate.php +77 -0
- package/server/src/Http/Resources/v1/ServiceArea.php +55 -0
- package/server/src/Http/Resources/v1/ServiceQuote.php +57 -0
- package/server/src/Http/Resources/v1/ServiceRate.php +94 -0
- package/server/src/Http/Resources/v1/ServiceRateFee.php +58 -0
- package/server/src/Http/Resources/v1/ServiceRateParcelFee.php +48 -0
- package/server/src/Http/Resources/v1/TrackingNumber.php +62 -0
- package/server/src/Http/Resources/v1/TrackingStatus.php +84 -0
- package/server/src/Http/Resources/v1/Vehicle.php +75 -0
- package/server/src/Http/Resources/v1/VehicleDevice.php +44 -0
- package/server/src/Http/Resources/v1/VehicleWithoutDriver.php +72 -0
- package/server/src/Http/Resources/v1/Vendor.php +72 -0
- package/server/src/Http/Resources/v1/Zone.php +60 -0
- package/server/src/Imports/OrdersImport.php +18 -0
- package/server/src/Integrations/Lalamove/Lalamove.php +678 -0
- package/server/src/Integrations/Lalamove/LalamoveDeliveryStop.php +97 -0
- package/server/src/Integrations/Lalamove/LalamoveMarket.php +123 -0
- package/server/src/Integrations/Lalamove/LalamoveServiceType.php +161 -0
- package/server/src/Jobs/SimulateDrivingRoute.php +81 -0
- package/server/src/Jobs/SimulateWaypointReached.php +79 -0
- package/server/src/Listeners/HandleOrderCanceled.php +46 -0
- package/server/src/Listeners/HandleOrderCreated.php +23 -0
- package/server/src/Listeners/HandleOrderDispatchFailed.php +35 -0
- package/server/src/Listeners/HandleOrderDispatched.php +108 -0
- package/server/src/Listeners/HandleOrderDriverAssigned.php +42 -0
- package/server/src/Listeners/HandleOrderReady.php +27 -0
- package/server/src/Listeners/HandleUserRemovedFromCompany.php +31 -0
- package/server/src/Models/Contact.php +239 -0
- package/server/src/Models/Driver.php +543 -0
- package/server/src/Models/Entity.php +416 -0
- package/server/src/Models/Fleet.php +203 -0
- package/server/src/Models/FleetDriver.php +73 -0
- package/server/src/Models/FleetVehicle.php +73 -0
- package/server/src/Models/FuelReport.php +125 -0
- package/server/src/Models/IntegratedVendor.php +219 -0
- package/server/src/Models/Issue.php +111 -0
- package/server/src/Models/Order.php +1132 -0
- package/server/src/Models/Payload.php +699 -0
- package/server/src/Models/Place.php +656 -0
- package/server/src/Models/Position.php +119 -0
- package/server/src/Models/Proof.php +94 -0
- package/server/src/Models/PurchaseRate.php +208 -0
- package/server/src/Models/Route.php +128 -0
- package/server/src/Models/ServiceArea.php +161 -0
- package/server/src/Models/ServiceQuote.php +207 -0
- package/server/src/Models/ServiceQuoteItem.php +46 -0
- package/server/src/Models/ServiceRate.php +953 -0
- package/server/src/Models/ServiceRateFee.php +96 -0
- package/server/src/Models/ServiceRateParcelFee.php +116 -0
- package/server/src/Models/TrackingNumber.php +310 -0
- package/server/src/Models/TrackingStatus.php +177 -0
- package/server/src/Models/Vehicle.php +452 -0
- package/server/src/Models/VehicleDevice.php +79 -0
- package/server/src/Models/Vendor.php +244 -0
- package/server/src/Models/Waypoint.php +226 -0
- package/server/src/Models/Zone.php +95 -0
- package/server/src/Notifications/OrderAssigned.php +140 -0
- package/server/src/Notifications/OrderCanceled.php +129 -0
- package/server/src/Notifications/OrderDispatchFailed.php +81 -0
- package/server/src/Notifications/OrderDispatched.php +173 -0
- package/server/src/Notifications/OrderPing.php +162 -0
- package/server/src/Notifications/OrderSplit.php +56 -0
- package/server/src/Observers/DriverObserver.php +34 -0
- package/server/src/Observers/OrderObserver.php +34 -0
- package/server/src/Observers/PayloadObserver.php +30 -0
- package/server/src/Observers/PlaceObserver.php +26 -0
- package/server/src/Observers/PurchaseRateObserver.php +61 -0
- package/server/src/Observers/ServiceAreaObserver.php +35 -0
- package/server/src/Observers/ServiceRateObserver.php +78 -0
- package/server/src/Observers/TrackingNumberObserver.php +44 -0
- package/server/src/Observers/UserObserver.php +20 -0
- package/server/src/Observers/VehicleObserver.php +66 -0
- package/server/src/Providers/EventServiceProvider.php +30 -0
- package/server/src/Providers/FleetOpsServiceProvider.php +94 -0
- package/server/src/Rules/ResolvablePoint.php +37 -0
- package/server/src/Scopes/DriverScope.php +21 -0
- package/server/src/Support/Algo.php +55 -0
- package/server/src/Support/DistanceMatrix.php +27 -0
- package/server/src/Support/Encoding/Polyline.php +168 -0
- package/server/src/Support/Flow.php +622 -0
- package/server/src/Support/Geocoding.php +216 -0
- package/server/src/Support/IntegratedVendors.php +287 -0
- package/server/src/Support/Metrics.php +305 -0
- package/server/src/Support/OSRM.php +191 -0
- package/server/src/Support/ParsePhone.php +21 -0
- package/server/src/Support/Utils.php +1145 -0
- package/server/src/Traits/HasTrackingNumber.php +185 -0
- package/server/src/routes.php +381 -0
- package/server/tests/Feature.php +5 -0
|
@@ -0,0 +1,1114 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\FleetOps\Http\Controllers\Api\v1;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\FleetOps\Events\OrderDispatchFailed;
|
|
6
|
+
use Fleetbase\FleetOps\Events\OrderReady;
|
|
7
|
+
use Fleetbase\FleetOps\Events\OrderStarted;
|
|
8
|
+
use Fleetbase\FleetOps\Http\Requests\CreateOrderRequest;
|
|
9
|
+
use Fleetbase\FleetOps\Http\Requests\UpdateOrderRequest;
|
|
10
|
+
use Fleetbase\FleetOps\Http\Resources\v1\DeletedResource;
|
|
11
|
+
use Fleetbase\FleetOps\Http\Resources\v1\Order as OrderResource;
|
|
12
|
+
use Fleetbase\FleetOps\Http\Resources\v1\Proof as ProofResource;
|
|
13
|
+
use Fleetbase\FleetOps\Models\Driver;
|
|
14
|
+
use Fleetbase\FleetOps\Models\Entity;
|
|
15
|
+
use Fleetbase\FleetOps\Models\Order;
|
|
16
|
+
use Fleetbase\FleetOps\Models\Payload;
|
|
17
|
+
use Fleetbase\FleetOps\Models\Place;
|
|
18
|
+
use Fleetbase\FleetOps\Models\Proof;
|
|
19
|
+
use Fleetbase\FleetOps\Models\ServiceQuote;
|
|
20
|
+
use Fleetbase\FleetOps\Models\Waypoint;
|
|
21
|
+
use Fleetbase\FleetOps\Support\Flow;
|
|
22
|
+
use Fleetbase\FleetOps\Support\Utils;
|
|
23
|
+
use Fleetbase\Http\Controllers\Controller;
|
|
24
|
+
use Fleetbase\Models\Company;
|
|
25
|
+
use Fleetbase\Models\File;
|
|
26
|
+
use Illuminate\Http\Request;
|
|
27
|
+
use Illuminate\Support\Carbon;
|
|
28
|
+
use Illuminate\Support\Facades\Storage;
|
|
29
|
+
use Illuminate\Support\Str;
|
|
30
|
+
|
|
31
|
+
class OrderController extends Controller
|
|
32
|
+
{
|
|
33
|
+
/**
|
|
34
|
+
* Creates a new Fleetbase Order resource.
|
|
35
|
+
*
|
|
36
|
+
* @param \Fleetbase\Http\Requests\CreateOrderRequest $request
|
|
37
|
+
*
|
|
38
|
+
* @return \Fleetbase\Http\Resources\Order
|
|
39
|
+
*/
|
|
40
|
+
public function create(CreateOrderRequest $request)
|
|
41
|
+
{
|
|
42
|
+
// get request input
|
|
43
|
+
$input = $request->only(['internal_id', 'payload', 'service_quote', 'purchase_rate', 'adhoc', 'adhoc_distance', 'pod_method', 'pod_required', 'scheduled_at', 'type', 'status', 'meta', 'notes']);
|
|
44
|
+
|
|
45
|
+
// make sure company is set
|
|
46
|
+
$input['company_uuid'] = session('company');
|
|
47
|
+
|
|
48
|
+
// resolve service quote if applicable
|
|
49
|
+
$serviceQuote = ServiceQuote::resolveFromRequest($request);
|
|
50
|
+
$integratedVendorOrder = null;
|
|
51
|
+
|
|
52
|
+
// if service quote is applied, resolve it
|
|
53
|
+
if ($serviceQuote instanceof ServiceQuote && $serviceQuote->fromIntegratedVendor()) {
|
|
54
|
+
// create order with integrated vendor, then resume fleetbase order creation
|
|
55
|
+
try {
|
|
56
|
+
$integratedVendorOrder = $serviceQuote->integratedVendor->api()->createOrderFromServiceQuote($serviceQuote, $request);
|
|
57
|
+
} catch (\Exception $e) {
|
|
58
|
+
return response()->error($e->getMessage());
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// create payload
|
|
63
|
+
if ($request->has('payload') && $request->isArray('payload')) {
|
|
64
|
+
$payloadInput = $request->input('payload');
|
|
65
|
+
$payload = new Payload();
|
|
66
|
+
|
|
67
|
+
$payload->setPickup($payloadInput['pickup']);
|
|
68
|
+
$payload->setDropoff($payloadInput['dropoff']);
|
|
69
|
+
if ($request->has('payload.return')) {
|
|
70
|
+
$payload->setReturn($payloadInput['return']);
|
|
71
|
+
}
|
|
72
|
+
$payload->setWaypoints($payloadInput['waypoints'] ?? []);
|
|
73
|
+
$payload->setEntities($payloadInput['entities'] ?? []);
|
|
74
|
+
$payload->save();
|
|
75
|
+
|
|
76
|
+
$input['payload_uuid'] = $payload->uuid;
|
|
77
|
+
} elseif ($request->isString('payload')) {
|
|
78
|
+
$input['payload_uuid'] = Utils::getUuid('payloads', [
|
|
79
|
+
'public_id' => $request->input('payload'),
|
|
80
|
+
'company_uuid' => session('company'),
|
|
81
|
+
]);
|
|
82
|
+
unset($input['payload']);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// create a payload if missing payload[] but has pickup/dropoff/etc
|
|
86
|
+
if ($request->missing('payload')) {
|
|
87
|
+
$payloadInput = $request->only(['pickup', 'dropoff', 'return', 'waypoints', 'entities']);
|
|
88
|
+
$payload = new Payload();
|
|
89
|
+
|
|
90
|
+
$payload->setPickup($payloadInput['pickup']);
|
|
91
|
+
$payload->setDropoff($payloadInput['dropoff']);
|
|
92
|
+
if ($request->has('return')) {
|
|
93
|
+
$payload->setReturn($payloadInput['return']);
|
|
94
|
+
}
|
|
95
|
+
$payload->setWaypoints($payloadInput['waypoints'] ?? []);
|
|
96
|
+
$payload->setEntities($payloadInput['entities'] ?? []);
|
|
97
|
+
$payload->save();
|
|
98
|
+
|
|
99
|
+
$input['payload_uuid'] = $payload->uuid;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// driver assignment
|
|
103
|
+
if ($request->has('driver') && $integratedVendorOrder === null) {
|
|
104
|
+
$input['driver_assigned_uuid'] = Utils::getUuid('drivers', [
|
|
105
|
+
'public_id' => $request->input('driver'),
|
|
106
|
+
'company_uuid' => session('company'),
|
|
107
|
+
]);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// facilitator assignment
|
|
111
|
+
if ($request->has('facilitator') && $integratedVendorOrder === null) {
|
|
112
|
+
$facilitator = Utils::getUuid(
|
|
113
|
+
['contacts', 'vendors', 'integrated_vendors'],
|
|
114
|
+
[
|
|
115
|
+
'public_id' => $request->input('facilitator'),
|
|
116
|
+
'company_uuid' => session('company'),
|
|
117
|
+
]
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
if (is_array($facilitator)) {
|
|
121
|
+
$input['facilitator_uuid'] = Utils::get($facilitator, 'uuid');
|
|
122
|
+
$input['facilitator_type'] = Utils::getModelClassName(Utils::get($facilitator, 'table'));
|
|
123
|
+
}
|
|
124
|
+
} elseif ($integratedVendorOrder) {
|
|
125
|
+
$input['facilitator_uuid'] = $serviceQuote->integratedVendor->uuid;
|
|
126
|
+
$input['facilitator_type'] = Utils::getModelClassName('integrated_vendors');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// customer assignment
|
|
130
|
+
if ($request->has('customer')) {
|
|
131
|
+
$customer = Utils::getUuid(
|
|
132
|
+
['contacts', 'vendors'],
|
|
133
|
+
[
|
|
134
|
+
'public_id' => $request->input('customer'),
|
|
135
|
+
'company_uuid' => session('company'),
|
|
136
|
+
]
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
if (is_array($customer)) {
|
|
140
|
+
$input['customer_uuid'] = Utils::get($customer, 'uuid');
|
|
141
|
+
$input['customer_type'] = Utils::getModelClassName(Utils::get($customer, 'table'));
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// if no type is set its default to default
|
|
146
|
+
if (!isset($input['type'])) {
|
|
147
|
+
$input['type'] = 'default';
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// if adhoc set convert to sql ready boolean value 1 or 0
|
|
151
|
+
if (isset($input['adhoc']) && $integratedVendorOrder === null) {
|
|
152
|
+
$input['adhoc'] = Utils::isTrue($input['adhoc']) ? 1 : 0;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (!isset($input['payload_uuid'])) {
|
|
156
|
+
return response()->error('Attempted to attach invalid payload to order.');
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// create the order
|
|
160
|
+
$order = Order::create($input);
|
|
161
|
+
|
|
162
|
+
// notify driver if assigned
|
|
163
|
+
$order->notifyDriverAssigned();
|
|
164
|
+
|
|
165
|
+
// set driving distance and time
|
|
166
|
+
$order->setPreliminaryDistanceAndTime();
|
|
167
|
+
|
|
168
|
+
// if service quote attached purchase
|
|
169
|
+
$order->purchaseServiceQuote($serviceQuote);
|
|
170
|
+
|
|
171
|
+
// if it's integrated vendor order apply to meta
|
|
172
|
+
if ($integratedVendorOrder) {
|
|
173
|
+
$order->updateMeta([
|
|
174
|
+
'integrated_vendor' => $serviceQuote->integratedVendor->public_id,
|
|
175
|
+
'integrated_vendor_order' => $integratedVendorOrder,
|
|
176
|
+
]);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// dispatch if flagged true
|
|
180
|
+
if ($request->boolean('dispatch') && $integratedVendorOrder === null) {
|
|
181
|
+
$order->dispatch();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// load required relations
|
|
185
|
+
$order->load(['trackingNumber', 'driverAssigned', 'purchaseRate', 'customer', 'facilitator']);
|
|
186
|
+
|
|
187
|
+
// Trigger order created event
|
|
188
|
+
event(new OrderReady($order));
|
|
189
|
+
|
|
190
|
+
// response the driver resource
|
|
191
|
+
return new OrderResource($order);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Updates a Fleetbase Order resource.
|
|
196
|
+
*
|
|
197
|
+
* @param string $id
|
|
198
|
+
* @param \Fleetbase\Http\Requests\UpdateOrderRequest $request
|
|
199
|
+
*
|
|
200
|
+
* @return \Fleetbase\Http\Resources\Order
|
|
201
|
+
*/
|
|
202
|
+
public function update($id, UpdateOrderRequest $request)
|
|
203
|
+
{
|
|
204
|
+
// find for the order
|
|
205
|
+
try {
|
|
206
|
+
$order = Order::findRecordOrFail($id);
|
|
207
|
+
} catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
|
|
208
|
+
return response()->json(
|
|
209
|
+
[
|
|
210
|
+
'error' => 'Order resource not found.',
|
|
211
|
+
],
|
|
212
|
+
404
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// get request input
|
|
217
|
+
$input = $request->only(['internal_id', 'payload', 'adhoc', 'adhoc_distance', 'pod_method', 'pod_required', 'scheduled_at', 'meta', 'type', 'status', 'notes']);
|
|
218
|
+
|
|
219
|
+
// update payload if new input or change payload by id
|
|
220
|
+
if ($request->isArray('payload')) {
|
|
221
|
+
$payloadInput = $request->input('payload');
|
|
222
|
+
$payload = new Payload();
|
|
223
|
+
|
|
224
|
+
$payload->setPickup($payloadInput['pickup']);
|
|
225
|
+
$payload->setDropoff($payloadInput['dropoff']);
|
|
226
|
+
if ($request->has('payload.return')) {
|
|
227
|
+
$payload->setReturn($payloadInput['return']);
|
|
228
|
+
}
|
|
229
|
+
$payload->setWaypoints($payloadInput['waypoints'] ?? []);
|
|
230
|
+
$payload->setEntities($payloadInput['entities'] ?? []);
|
|
231
|
+
$payload->save();
|
|
232
|
+
|
|
233
|
+
$input['payload_uuid'] = $payload->uuid;
|
|
234
|
+
} elseif ($request->has('payload')) {
|
|
235
|
+
$input['payload_uuid'] = Utils::getUuid('payloads', [
|
|
236
|
+
'public_id' => $request->input('payload'),
|
|
237
|
+
'company_uuid' => session('company'),
|
|
238
|
+
]);
|
|
239
|
+
unset($input['payload']);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// update payload properties if applicable
|
|
243
|
+
if ($request->has('pickup')) {
|
|
244
|
+
if ($order->payload) {
|
|
245
|
+
$order->payload->setPickup($request->input('pickup'));
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
if ($request->has('dropoff')) {
|
|
249
|
+
if ($order->payload) {
|
|
250
|
+
$order->payload->setDropoff($request->input('dropoff'));
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if ($request->has('return')) {
|
|
255
|
+
if ($order->payload) {
|
|
256
|
+
$order->payload->setReturn($request->input('return'));
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if ($request->has('waypoints')) {
|
|
261
|
+
if ($order->payload) {
|
|
262
|
+
$order->payload->setWaypoints($request->input('waypoints'));
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if ($request->has('entities')) {
|
|
267
|
+
if ($order->payload) {
|
|
268
|
+
$order->payload->setEntities($request->input('entities'));
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// driver assignment
|
|
273
|
+
if ($request->has('driver')) {
|
|
274
|
+
$input['driver_assigned_uuid'] = Utils::getUuid('drivers', [
|
|
275
|
+
'public_id' => $request->input('driver'),
|
|
276
|
+
'company_uuid' => session('company'),
|
|
277
|
+
]);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// facilitator assignment
|
|
281
|
+
if ($request->has('facilitator')) {
|
|
282
|
+
$facilitator = Utils::getUuid(
|
|
283
|
+
['contacts', 'vendors'],
|
|
284
|
+
[
|
|
285
|
+
'public_id' => $request->input('facilitator'),
|
|
286
|
+
'company_uuid' => session('company'),
|
|
287
|
+
]
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
if (is_array($facilitator)) {
|
|
291
|
+
$input['facilitator_uuid'] = Utils::get($facilitator, 'uuid');
|
|
292
|
+
$input['facilitator_type'] = Utils::getModelClassName(Utils::get($facilitator, 'table'));
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// customer assignment
|
|
297
|
+
if ($request->has('customer')) {
|
|
298
|
+
$customer = Utils::getUuid(
|
|
299
|
+
['contacts', 'vendors'],
|
|
300
|
+
[
|
|
301
|
+
'public_id' => $request->input('customer'),
|
|
302
|
+
'company_uuid' => session('company'),
|
|
303
|
+
]
|
|
304
|
+
);
|
|
305
|
+
|
|
306
|
+
if (is_array($customer)) {
|
|
307
|
+
$input['customer_uuid'] = Utils::get($customer, 'uuid');
|
|
308
|
+
$input['customer_type'] = Utils::getModelClassName(Utils::get($customer, 'table'));
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// dispatch if flagged true
|
|
313
|
+
if ($request->boolean('dispatch')) {
|
|
314
|
+
$order->dispatch();
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// update the order
|
|
318
|
+
$order->update($input);
|
|
319
|
+
$order->flushAttributesCache();
|
|
320
|
+
|
|
321
|
+
// response the order resource
|
|
322
|
+
return new OrderResource($order);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Query for Fleetbase Order resources.
|
|
327
|
+
*
|
|
328
|
+
* @return \Fleetbase\Http\Resources\OrderCollection
|
|
329
|
+
*/
|
|
330
|
+
public function query(Request $request)
|
|
331
|
+
{
|
|
332
|
+
$results = Order::queryWithRequest($request, function (&$query, $request) {
|
|
333
|
+
if ($request->has('payload')) {
|
|
334
|
+
$query->whereHas('payload', function ($q) use ($request) {
|
|
335
|
+
$q->where('public_id', $request->input('payload'));
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
if ($request->has('pickup')) {
|
|
340
|
+
$query->whereHas('payload.pickup', function ($q) use ($request) {
|
|
341
|
+
$q->where('public_id', $request->input('pickup'));
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if ($request->has('dropoff')) {
|
|
346
|
+
$query->whereHas('payload.dropoff', function ($q) use ($request) {
|
|
347
|
+
$q->where('public_id', $request->input('dropoff'));
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
if ($request->has('return')) {
|
|
352
|
+
$query->whereHas('payload.return', function ($q) use ($request) {
|
|
353
|
+
$q->where('public_id', $request->input('return'));
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if ($request->has('facilitator')) {
|
|
358
|
+
$query->whereHas('facilitator', function ($q) use ($request) {
|
|
359
|
+
$q->where(function ($q) use ($request) {
|
|
360
|
+
$q->where('public_id', $request->input('facilitator'));
|
|
361
|
+
$q->orWhere('internal_id', $request->input('facilitator'));
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
if ($request->has('customer')) {
|
|
367
|
+
$query->whereHas('customer', function ($q) use ($request) {
|
|
368
|
+
$q->where(function ($q) use ($request) {
|
|
369
|
+
$q->where('public_id', $request->input('customer'));
|
|
370
|
+
$q->orWhere('internal_id', $request->input('customer'));
|
|
371
|
+
});
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if ($request->has('entity')) {
|
|
376
|
+
$query->whereHas('payload.entities', function ($q) use ($request) {
|
|
377
|
+
$q->where(function ($q) use ($request) {
|
|
378
|
+
$q->where('public_id', $request->input('entity'));
|
|
379
|
+
$q->orWhere('internal_id', $request->input('entity'));
|
|
380
|
+
});
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
if ($request->has('entity_status')) {
|
|
385
|
+
$query->whereHas('payload.entities.trackingNumber.status', function ($q) use ($request) {
|
|
386
|
+
if ($request->isArray('entity_status')) {
|
|
387
|
+
$q->whereIn('code', $request->input('entity_status'));
|
|
388
|
+
} else {
|
|
389
|
+
$q->where('code', $request->input('entity_status'));
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
if ($request->has('on')) {
|
|
395
|
+
$on = Carbon::fromString($request->input('on'));
|
|
396
|
+
|
|
397
|
+
$query->where(function ($q) use ($on) {
|
|
398
|
+
$q->whereDate('created_at', $on);
|
|
399
|
+
$q->orWhereDate('scheduled_at', $on);
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
if ($request->boolean('pod_required')) {
|
|
404
|
+
$query->where('pod_required', 1);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
if ($request->boolean('dispatched')) {
|
|
408
|
+
$query->where('dispatched', 1);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
if ($request->has('nearby')) {
|
|
412
|
+
$nearby = $request->input('nearby');
|
|
413
|
+
$distance = 6000; // default in meters
|
|
414
|
+
$company = Company::currentSession();
|
|
415
|
+
$addedNearbyQuery = false;
|
|
416
|
+
|
|
417
|
+
if ($company) {
|
|
418
|
+
$distance = $company->getOption('fleetops.adhoc_distance', 6000);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// if wants to find nearby place or coordinates
|
|
422
|
+
if (Utils::isCoordinates($nearby)) {
|
|
423
|
+
$location = Utils::getPointFromMixed($nearby);
|
|
424
|
+
|
|
425
|
+
$query->whereHas('payload', function ($q) use ($location, $distance) {
|
|
426
|
+
$q->whereHas('pickup', function ($q) use ($location, $distance) {
|
|
427
|
+
$q->distanceSphere('location', $location, $distance);
|
|
428
|
+
$q->distanceSphereValue('location', $location);
|
|
429
|
+
})->orWhereHas('waypoints', function ($q) use ($location, $distance) {
|
|
430
|
+
$q->distanceSphere('location', $location, $distance);
|
|
431
|
+
$q->distanceSphereValue('location', $location);
|
|
432
|
+
});
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
// Update so additional nearby queries are not added
|
|
436
|
+
$addedNearbyQuery = true;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// request wants to find orders nearby a driver ?
|
|
440
|
+
if ($addedNearbyQuery === false && is_string($nearby) && Str::startsWith($nearby, 'driver_')) {
|
|
441
|
+
$driver = Driver::where('public_id', $nearby)->first();
|
|
442
|
+
|
|
443
|
+
if ($driver) {
|
|
444
|
+
$query->whereHas('payload', function ($q) use ($driver, $distance) {
|
|
445
|
+
$q->whereHas('pickup', function ($q) use ($driver, $distance) {
|
|
446
|
+
$q->distanceSphere('location', $driver->location, $distance);
|
|
447
|
+
$q->distanceSphereValue('location', $driver->location);
|
|
448
|
+
})->orWhereHas('waypoints', function ($q) use ($driver, $distance) {
|
|
449
|
+
$q->distanceSphere('location', $driver->location, $distance);
|
|
450
|
+
$q->distanceSphereValue('location', $driver->location);
|
|
451
|
+
});
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
// Update so additional nearby queries are not added
|
|
455
|
+
$addedNearbyQuery = true;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// if is a string like address string
|
|
460
|
+
if ($addedNearbyQuery === false && is_string($nearby)) {
|
|
461
|
+
$nearby = Place::createFromMixed($nearby, [], false);
|
|
462
|
+
|
|
463
|
+
if ($nearby instanceof Place) {
|
|
464
|
+
$query->whereHas('payload', function ($q) use ($nearby, $distance) {
|
|
465
|
+
$q->whereHas('pickup', function ($q) use ($nearby, $distance) {
|
|
466
|
+
$q->distanceSphere('location', $nearby->location, $distance);
|
|
467
|
+
$q->distanceSphereValue('location', $nearby->location);
|
|
468
|
+
})->orWhereHas('waypoints', function ($q) use ($nearby, $distance) {
|
|
469
|
+
$q->distanceSphere('location', $nearby->location, $distance);
|
|
470
|
+
$q->distanceSphereValue('location', $nearby->location);
|
|
471
|
+
});
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
// Update so additional nearby queries are not added
|
|
475
|
+
$addedNearbyQuery = true;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
return OrderResource::collection($results);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Finds a single Fleetbase Order resources.
|
|
486
|
+
*
|
|
487
|
+
* @return \Fleetbase\Http\Resources\OrderCollection
|
|
488
|
+
*/
|
|
489
|
+
public function find($id, Request $request)
|
|
490
|
+
{
|
|
491
|
+
// find for the order
|
|
492
|
+
try {
|
|
493
|
+
$order = Order::findRecordOrFail($id);
|
|
494
|
+
} catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
|
|
495
|
+
return response()->json(
|
|
496
|
+
[
|
|
497
|
+
'error' => 'Order resource not found.',
|
|
498
|
+
],
|
|
499
|
+
404
|
|
500
|
+
);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// response the order resource
|
|
504
|
+
return new OrderResource($order);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Deletes a Fleetbase Order resources.
|
|
509
|
+
*
|
|
510
|
+
* @return \Fleetbase\Http\Resources\OrderCollection
|
|
511
|
+
*/
|
|
512
|
+
public function delete($id, Request $request)
|
|
513
|
+
{
|
|
514
|
+
// find for the driver
|
|
515
|
+
try {
|
|
516
|
+
$order = Order::findRecordOrFail($id);
|
|
517
|
+
} catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
|
|
518
|
+
return response()->json(
|
|
519
|
+
[
|
|
520
|
+
'error' => 'Order resource not found.',
|
|
521
|
+
],
|
|
522
|
+
404
|
|
523
|
+
);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// delete the order
|
|
527
|
+
$order->delete();
|
|
528
|
+
|
|
529
|
+
// response the order resource
|
|
530
|
+
return new DeletedResource($order);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Returns current distance and time matrix for an order.
|
|
535
|
+
*
|
|
536
|
+
* @return \Illuminate\Http\Response $response
|
|
537
|
+
*/
|
|
538
|
+
public function getDistanceMatrix(string $id)
|
|
539
|
+
{
|
|
540
|
+
// find the order
|
|
541
|
+
try {
|
|
542
|
+
$order = Order::findRecordOrFail($id);
|
|
543
|
+
} catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
|
|
544
|
+
return response()->json(
|
|
545
|
+
[
|
|
546
|
+
'error' => 'Order resource not found.',
|
|
547
|
+
],
|
|
548
|
+
404
|
|
549
|
+
);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
$order->load(['payload', 'payload.waypoints', 'payload.pickup', 'payload.dropoff']);
|
|
553
|
+
|
|
554
|
+
$origin = $order->payload->pickup ?? $order->payload->waypoints->first();
|
|
555
|
+
$destination = $order->payload->dropoff ?? $order->payload->waypoints->firstWhere('current_waypoint_uuid', $order->current_waypoint_uuid);
|
|
556
|
+
|
|
557
|
+
$matrix = Utils::getDrivingDistanceAndTime($origin, $destination);
|
|
558
|
+
|
|
559
|
+
$order->update(['distance' => $matrix->distance, 'time' => $matrix->time]);
|
|
560
|
+
|
|
561
|
+
// response distance and time matrix
|
|
562
|
+
return response()->json($matrix);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* Dispatches an order.
|
|
567
|
+
*
|
|
568
|
+
* @return \Fleetbase\Http\Resources\v1\Order
|
|
569
|
+
*/
|
|
570
|
+
public function dispatchOrder(string $id)
|
|
571
|
+
{
|
|
572
|
+
try {
|
|
573
|
+
$order = Order::findRecordOrFail($id);
|
|
574
|
+
} catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
|
|
575
|
+
return response()->json(
|
|
576
|
+
[
|
|
577
|
+
'error' => 'Order resource not found.',
|
|
578
|
+
],
|
|
579
|
+
404
|
|
580
|
+
);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
if (!$order->hasDriverAssigned && !$order->adhoc) {
|
|
584
|
+
return response()->error('No driver assigned to dispatch!');
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
if ($order->dispatched) {
|
|
588
|
+
return response()->error('Order has already been dispatched!');
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
$order->dispatch();
|
|
592
|
+
|
|
593
|
+
return new OrderResource($order);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Request to start order, this assumes order is dispatched.
|
|
598
|
+
* Unless there is a param to skip dispatch throw a order not dispatched error.
|
|
599
|
+
*
|
|
600
|
+
* @return \Fleetbase\Http\Resources\v1\Order
|
|
601
|
+
*/
|
|
602
|
+
public function startOrder(string $id, Request $request)
|
|
603
|
+
{
|
|
604
|
+
$skipDispatch = $request->or(['skip_dispatch', 'skipDispatch'], false);
|
|
605
|
+
$assignAdhocDriver = $request->input('assign');
|
|
606
|
+
|
|
607
|
+
try {
|
|
608
|
+
$order = Order::findRecordOrFail($id, ['payload.waypoints'], []);
|
|
609
|
+
} catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
|
|
610
|
+
return response()->json(
|
|
611
|
+
[
|
|
612
|
+
'error' => 'Order resource not found.',
|
|
613
|
+
],
|
|
614
|
+
404
|
|
615
|
+
);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
if ($order->started) {
|
|
619
|
+
return response()->error('Order has already started.');
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
// if the order is adhoc and the parameter of `assign` is set with a valid driver id, assign the driver and continue
|
|
623
|
+
if ($order->adhoc && $assignAdhocDriver && Str::startsWith($assignAdhocDriver, 'driver_')) {
|
|
624
|
+
$order->assignDriver($assignAdhocDriver, true);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
/** @var \Fleetbase\Models\Driver */
|
|
628
|
+
$driver = Driver::where('uuid', $order->driver_assigned_uuid)->withoutGlobalScopes()->first();
|
|
629
|
+
|
|
630
|
+
/** @var \Fleetbase\Models\Payload */
|
|
631
|
+
$payload = Payload::where('uuid', $order->payload_uuid)->withoutGlobalScopes()->with(['waypoints', 'waypointMarkers', 'entities'])->first();
|
|
632
|
+
|
|
633
|
+
if ($order->adhoc && !$driver) {
|
|
634
|
+
return response()->error('You must send driver to accept adhoc order.');
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
if (!$driver) {
|
|
638
|
+
return response()->error('No driver assigned to order.');
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
// get the next order activity
|
|
642
|
+
$flow = $activity = Flow::getNextActivity($order);
|
|
643
|
+
|
|
644
|
+
// order is not dispatched if next activity code is dispatch or order is not flagged as dispatched
|
|
645
|
+
$isNotDispatched = $activity['code'] === 'dispatched' || $order->isNotDispatched;
|
|
646
|
+
|
|
647
|
+
// if order is not dispatched yet $activity['code'] === 'dispatched' || $order->dispatched === true
|
|
648
|
+
// and not skipping throw order not dispatched error
|
|
649
|
+
if ($isNotDispatched && !$skipDispatch) {
|
|
650
|
+
return response()->error('Order has not been dispatched yet and cannot be started.');
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
// if we're going to skip the dispatch get the next activity status and flow and continue
|
|
654
|
+
if ($isNotDispatched && $skipDispatch) {
|
|
655
|
+
$flow = $activity = Flow::getAfterNextActivity($order);
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
// set order to started
|
|
659
|
+
$order->started = true;
|
|
660
|
+
$order->started_at = now();
|
|
661
|
+
$order->save();
|
|
662
|
+
|
|
663
|
+
// trigger start event
|
|
664
|
+
event(new OrderStarted($order));
|
|
665
|
+
|
|
666
|
+
// set order as drivers current order
|
|
667
|
+
$driver->current_job_uuid = $order->uuid;
|
|
668
|
+
$driver->save();
|
|
669
|
+
|
|
670
|
+
/** @var \Grimzy\LaravelMysqlSpatial\Types\Point */
|
|
671
|
+
$location = $order->getLastLocation();
|
|
672
|
+
|
|
673
|
+
// set first destination for payload
|
|
674
|
+
$payload->setFirstWaypoint($activity, $location);
|
|
675
|
+
$order->setRelation('payload', $payload);
|
|
676
|
+
|
|
677
|
+
// update order activity
|
|
678
|
+
$updateActivityRequest = new Request(['activity' => $flow]);
|
|
679
|
+
|
|
680
|
+
// update activity
|
|
681
|
+
return $this->updateActivity($order, $updateActivityRequest);
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* Update an order activity.
|
|
686
|
+
*
|
|
687
|
+
* @param \Fleetbase\Models\Order|string $order
|
|
688
|
+
*
|
|
689
|
+
* @return \Fleetbase\Http\Resources\v1\Order
|
|
690
|
+
*/
|
|
691
|
+
public function updateActivity($order, Request $request)
|
|
692
|
+
{
|
|
693
|
+
$skipDispatch = $request->or(['skip_dispatch', 'skipDispatch'], false);
|
|
694
|
+
$proof = $request->input('proof', null);
|
|
695
|
+
|
|
696
|
+
/** @var \Fleetbase\FleetOps\Models\Order $order */
|
|
697
|
+
$order = ($order instanceof Order) ? $order : Order::withoutGlobalScopes()
|
|
698
|
+
->where('public_id', $order)
|
|
699
|
+
->whereNull('deleted_at')
|
|
700
|
+
->with(['driverAssigned', 'payload.entities', 'payload.currentWaypoint', 'payload.waypoints'])
|
|
701
|
+
->first();
|
|
702
|
+
|
|
703
|
+
if (!$order) {
|
|
704
|
+
return response()->error('No resource not found.');
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
// if orser is created trigger started flag
|
|
708
|
+
if ($order->status === 'created') {
|
|
709
|
+
$order->started = true;
|
|
710
|
+
$order->started_at = now();
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
$activity = $request->input('activity', Flow::getNextActivity($order));
|
|
714
|
+
|
|
715
|
+
// if we're going to skip the dispatch get the next activity status and flow and continue
|
|
716
|
+
if (is_array($activity) && $activity['code'] === 'dispatched' && $skipDispatch) {
|
|
717
|
+
$activity = Flow::getAfterNextActivity($order);
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
// handle pickup/dropoff order activity update as normal
|
|
721
|
+
if (is_array($activity) && $activity['code'] === 'dispatched') {
|
|
722
|
+
// make sure driver is assigned if not trigger failed dispatch
|
|
723
|
+
if (!$order->hasDriverAssigned && !$order->adhoc) {
|
|
724
|
+
event(new OrderDispatchFailed($order, 'No driver assigned for order to dispatch to.'));
|
|
725
|
+
|
|
726
|
+
return response()->error('No driver assigned for order to dispatch to.');
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
$order->dispatch();
|
|
730
|
+
|
|
731
|
+
return new OrderResource($order);
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
/** @var \Grimzy\LaravelMysqlSpatial\Types\Point */
|
|
735
|
+
$location = $order->getLastLocation();
|
|
736
|
+
|
|
737
|
+
// if is multi drop order and no current destination set it
|
|
738
|
+
if ($order->payload->isMultipleDropOrder && !$order->payload->current_waypoint_uuid) {
|
|
739
|
+
$order->payload->setFirstWaypoint($activity, $location);
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
if (is_array($activity) && $activity['code'] === 'completed' && $order->payload->isMultipleDropOrder) {
|
|
743
|
+
// confirm every waypoint is completed
|
|
744
|
+
$isCompleted = $order->payload->waypointMarkers->every(function ($waypoint) {
|
|
745
|
+
return $waypoint->status_code === 'COMPLETED';
|
|
746
|
+
});
|
|
747
|
+
|
|
748
|
+
// only update activity for waypoint
|
|
749
|
+
if (!$isCompleted) {
|
|
750
|
+
$order->payload->updateWaypointActivity($activity, $location, $proof);
|
|
751
|
+
$order->payload->setNextWaypointDestination();
|
|
752
|
+
$order->payload->refresh();
|
|
753
|
+
|
|
754
|
+
// recheck if order is completed
|
|
755
|
+
$isFullyCompleted = $order->payload->waypointMarkers->every(function ($waypoint) {
|
|
756
|
+
return $waypoint->status_code === 'COMPLETED';
|
|
757
|
+
});
|
|
758
|
+
|
|
759
|
+
if (!$isFullyCompleted) {
|
|
760
|
+
return new OrderResource($order);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
if (is_array($activity) && $activity['code'] === 'completed' && $order->driverAssigned) {
|
|
766
|
+
// unset from driver current job
|
|
767
|
+
$order->driverAssigned->unassignCurrentOrder();
|
|
768
|
+
$order->notifyCompleted();
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
$order->setStatus($activity['code']);
|
|
772
|
+
$order->insertActivity($activity['status'], $activity['details'] ?? '', $location, $activity['code'], $proof);
|
|
773
|
+
|
|
774
|
+
// also update for each order entities if not multiple drop order
|
|
775
|
+
// all entities will share the same activity status as is one drop order
|
|
776
|
+
if (!$order->payload->isMultipleDropOrder) {
|
|
777
|
+
foreach ($order->payload->entities as $entity) {
|
|
778
|
+
$entity->insertActivity($activity['status'], $activity['details'] ?? '', $location, $activity['code'], $proof);
|
|
779
|
+
}
|
|
780
|
+
} else {
|
|
781
|
+
$order->payload->updateWaypointActivity($activity, $location);
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
return new OrderResource($order);
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
/**
|
|
788
|
+
* Retrieve the next activity for the order flow.
|
|
789
|
+
*
|
|
790
|
+
* @return \Illuminate\Http\Response
|
|
791
|
+
*/
|
|
792
|
+
public function getNextActivity(string $id, Request $request)
|
|
793
|
+
{
|
|
794
|
+
$waypointId = $request->input('waypoint');
|
|
795
|
+
|
|
796
|
+
try {
|
|
797
|
+
$order = Order::findRecordOrFail($id, ['payload']);
|
|
798
|
+
} catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
|
|
799
|
+
return response()->json(
|
|
800
|
+
[
|
|
801
|
+
'error' => 'Order resource not found.',
|
|
802
|
+
],
|
|
803
|
+
404
|
|
804
|
+
);
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
$isMultipleDropOrder = $order->payload->isMultipleDropOrder;
|
|
808
|
+
|
|
809
|
+
if ($waypointId && $isMultipleDropOrder) {
|
|
810
|
+
$waypoint = Waypoint::where('payload_uuid', $order->payload_uuid)->where(function ($q) use ($waypointId) {
|
|
811
|
+
$q->whereHas('place', function ($q) use ($waypointId) {
|
|
812
|
+
$q->where('public_id', $waypointId);
|
|
813
|
+
});
|
|
814
|
+
$q->orWhere('public_id', $waypointId);
|
|
815
|
+
})->withoutGlobalScopes()->first();
|
|
816
|
+
|
|
817
|
+
$activity = Flow::getOrderWaypointFlow($order, $waypoint);
|
|
818
|
+
|
|
819
|
+
return response()->json($activity);
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
$activity = Flow::getOrderFlow($order);
|
|
823
|
+
|
|
824
|
+
return response()->json($activity);
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
/**
|
|
828
|
+
* Confirms and completes an order.
|
|
829
|
+
*
|
|
830
|
+
* @return \Fleetbase\Http\Resources\v1\Order
|
|
831
|
+
*/
|
|
832
|
+
public function completeOrder(string $id)
|
|
833
|
+
{
|
|
834
|
+
try {
|
|
835
|
+
$order = Order::findRecordOrFail($id);
|
|
836
|
+
} catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
|
|
837
|
+
return response()->json(
|
|
838
|
+
[
|
|
839
|
+
'error' => 'Order resource not found.',
|
|
840
|
+
],
|
|
841
|
+
404
|
|
842
|
+
);
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
// confirm every waypoint is completed
|
|
846
|
+
$isCompleted = $order->payload->waypointMarkers->every(function ($waypoint) {
|
|
847
|
+
return $waypoint->status_code === 'COMPLETED';
|
|
848
|
+
});
|
|
849
|
+
|
|
850
|
+
// if not completed respond with error
|
|
851
|
+
if (!$isCompleted) {
|
|
852
|
+
return response()->error('Not all waypoints completed for order.');
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
$activity = [
|
|
856
|
+
'status' => 'Order completed',
|
|
857
|
+
'details' => 'Driver has completed order for all waypoints',
|
|
858
|
+
'code' => 'completed',
|
|
859
|
+
];
|
|
860
|
+
|
|
861
|
+
if ($order->driverAssigned) {
|
|
862
|
+
// unset from driver current job
|
|
863
|
+
$order->driverAssigned->unassignCurrentOrder();
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
$order->notifyCompleted();
|
|
867
|
+
|
|
868
|
+
/** @var \Grimzy\LaravelMysqlSpatial\Types\Point */
|
|
869
|
+
$location = $order->getLastLocation();
|
|
870
|
+
|
|
871
|
+
$order->setStatus($activity['code']);
|
|
872
|
+
$order->insertActivity($activity['status'], $activity['details'] ?? '', $location, $activity['code']);
|
|
873
|
+
|
|
874
|
+
return new OrderResource($order);
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
/**
|
|
878
|
+
* Updates a order to canceled and updates order activity.
|
|
879
|
+
*
|
|
880
|
+
* @return \Fleetbase\Http\Resources\v1\Order
|
|
881
|
+
*/
|
|
882
|
+
public function cancelOrder(string $id)
|
|
883
|
+
{
|
|
884
|
+
try {
|
|
885
|
+
$order = Order::findRecordOrFail($id);
|
|
886
|
+
} catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
|
|
887
|
+
return response()->json(
|
|
888
|
+
[
|
|
889
|
+
'error' => 'Order resource not found.',
|
|
890
|
+
],
|
|
891
|
+
404
|
|
892
|
+
);
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
$order->cancel();
|
|
896
|
+
|
|
897
|
+
return new OrderResource($order);
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
/**
|
|
901
|
+
* Updates the order payload destination with a valid place.
|
|
902
|
+
*
|
|
903
|
+
* @return \Fleetbase\Http\Resources\v1\Order
|
|
904
|
+
*/
|
|
905
|
+
public function setDestination(string $id, string $placeId)
|
|
906
|
+
{
|
|
907
|
+
try {
|
|
908
|
+
$order = Order::findRecordOrFail($id);
|
|
909
|
+
} catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
|
|
910
|
+
return response()->json(
|
|
911
|
+
[
|
|
912
|
+
'error' => 'Order resource not found.',
|
|
913
|
+
],
|
|
914
|
+
404
|
|
915
|
+
);
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
$place = $order->payload->waypoints->firstWhere('public_id', $placeId);
|
|
919
|
+
|
|
920
|
+
if (!$place) {
|
|
921
|
+
return response()->error('Place resource is not a valid destination.');
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
$order->payload->update(['current_waypoint_uuid' => $place->uuid]);
|
|
925
|
+
$order->payload->refresh();
|
|
926
|
+
|
|
927
|
+
return new OrderResource($order);
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
/**
|
|
931
|
+
* Sends request for route optimization and re-sorts waypoints.
|
|
932
|
+
*
|
|
933
|
+
* @return \Fleetbase\Http\Resources\v1\Order
|
|
934
|
+
*/
|
|
935
|
+
public function optimize(string $id)
|
|
936
|
+
{
|
|
937
|
+
try {
|
|
938
|
+
$order = Order::findRecordOrFail($id);
|
|
939
|
+
} catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
|
|
940
|
+
return response()->json(
|
|
941
|
+
[
|
|
942
|
+
'error' => 'Order resource not found.',
|
|
943
|
+
],
|
|
944
|
+
404
|
|
945
|
+
);
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
// do this code
|
|
949
|
+
|
|
950
|
+
return new OrderResource($order);
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
/**
|
|
954
|
+
* Verify & Capture QR Code Scan.
|
|
955
|
+
*
|
|
956
|
+
* @return void
|
|
957
|
+
*/
|
|
958
|
+
public function captureQrScan(string $id, string $subjectId = null, Request $request)
|
|
959
|
+
{
|
|
960
|
+
$code = $request->input('code');
|
|
961
|
+
$data = $request->input('data', []);
|
|
962
|
+
$rawData = $request->input('raw_data', []);
|
|
963
|
+
$type = $subjectId ? strtok($subjectId, '_') : null;
|
|
964
|
+
|
|
965
|
+
try {
|
|
966
|
+
$order = Order::findRecordOrFail($id);
|
|
967
|
+
} catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
|
|
968
|
+
return response()->json(
|
|
969
|
+
[
|
|
970
|
+
'error' => 'Order resource not found.',
|
|
971
|
+
],
|
|
972
|
+
404
|
|
973
|
+
);
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
if (!$code) {
|
|
977
|
+
return response()->error('No QR code data to capture.');
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
$subject = $type === null ? $order : null;
|
|
981
|
+
|
|
982
|
+
switch ($type) {
|
|
983
|
+
case 'place':
|
|
984
|
+
case 'waypoint':
|
|
985
|
+
$subject = Waypoint::where('payload_uuid', $order->payload_uuid)->where(function ($q) use ($code) {
|
|
986
|
+
$q->whereHas('place', function ($q) use ($code) {
|
|
987
|
+
$q->where('uuid', $code);
|
|
988
|
+
});
|
|
989
|
+
$q->orWhere('uuid', $code);
|
|
990
|
+
})->withoutGlobalScopes()->first();
|
|
991
|
+
break;
|
|
992
|
+
|
|
993
|
+
case 'entity':
|
|
994
|
+
$subject = Entity::where('uuid', $code)->withoutGlobalScopes()->first();
|
|
995
|
+
break;
|
|
996
|
+
|
|
997
|
+
default:
|
|
998
|
+
break;
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
if (!$subject) {
|
|
1002
|
+
return response()->error('Unable to capture QR code data.');
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
// validate
|
|
1006
|
+
if ($subject && $code === $subject->uuid) {
|
|
1007
|
+
// create verification proof
|
|
1008
|
+
$proof = Proof::create([
|
|
1009
|
+
'company_uuid' => session('company'),
|
|
1010
|
+
'order_uuid' => $order->uuid,
|
|
1011
|
+
'subject_uuid' => $subject->uuid,
|
|
1012
|
+
'subject_type' => Utils::getModelClassName($subject),
|
|
1013
|
+
'remarks' => 'Verified by QR Code Scan',
|
|
1014
|
+
'raw_data' => $rawData,
|
|
1015
|
+
'data' => $data,
|
|
1016
|
+
]);
|
|
1017
|
+
|
|
1018
|
+
return new ProofResource($proof);
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
return response()->error('Unable to validate QR code data.');
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
/**
|
|
1025
|
+
* Validate a QR code.
|
|
1026
|
+
*
|
|
1027
|
+
* @return void
|
|
1028
|
+
*/
|
|
1029
|
+
public function captureSignature(string $id, string $subjectId = null, Request $request)
|
|
1030
|
+
{
|
|
1031
|
+
$disk = $request->input('disk', config('filesystems.default'));
|
|
1032
|
+
$bucket = $request->input('bucket', config('filesystems.disks.' . $disk . '.bucket', config('filesystems.disks.s3.bucket')));
|
|
1033
|
+
$signature = $request->input('signature');
|
|
1034
|
+
$data = $request->input('data', []);
|
|
1035
|
+
$type = $subjectId ? strtok($subjectId, '_') : null;
|
|
1036
|
+
|
|
1037
|
+
try {
|
|
1038
|
+
$order = Order::findRecordOrFail($id);
|
|
1039
|
+
} catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
|
|
1040
|
+
return response()->json(
|
|
1041
|
+
[
|
|
1042
|
+
'error' => 'Order resource not found.',
|
|
1043
|
+
],
|
|
1044
|
+
404
|
|
1045
|
+
);
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
if (!$signature) {
|
|
1049
|
+
return response()->error('No signature data to capture.');
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
$subject = $type === null ? $order : null;
|
|
1053
|
+
|
|
1054
|
+
switch ($type) {
|
|
1055
|
+
case 'place':
|
|
1056
|
+
case 'waypoint':
|
|
1057
|
+
$subject = Waypoint::where('payload_uuid', $order->payload_uuid)->where(function ($q) use ($subjectId) {
|
|
1058
|
+
$q->whereHas('place', function ($q) use ($subjectId) {
|
|
1059
|
+
$q->where('public_id', $subjectId);
|
|
1060
|
+
});
|
|
1061
|
+
$q->orWhere('public_id', $subjectId);
|
|
1062
|
+
})->withoutGlobalScopes()->first();
|
|
1063
|
+
break;
|
|
1064
|
+
|
|
1065
|
+
case 'entity':
|
|
1066
|
+
$subject = Entity::where('public_id', $subjectId)->withoutGlobalScopes()->first();
|
|
1067
|
+
break;
|
|
1068
|
+
|
|
1069
|
+
default:
|
|
1070
|
+
break;
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
if (!$subject) {
|
|
1074
|
+
return response()->error('Unable to capture signature data.');
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
// create proof instance
|
|
1078
|
+
$proof = Proof::create([
|
|
1079
|
+
'company_uuid' => session('company'),
|
|
1080
|
+
'order_uuid' => $order->uuid,
|
|
1081
|
+
'subject_uuid' => $subject->uuid,
|
|
1082
|
+
'subject_type' => Utils::getModelClassName($subject),
|
|
1083
|
+
'remarks' => 'Verified by Signature',
|
|
1084
|
+
'raw_data' => $signature,
|
|
1085
|
+
'data' => $data,
|
|
1086
|
+
]);
|
|
1087
|
+
|
|
1088
|
+
// set the signature storage path
|
|
1089
|
+
$path = 'uploads/' . session('company') . '/signatures/' . $proof->public_id . '.png';
|
|
1090
|
+
|
|
1091
|
+
// upload signature
|
|
1092
|
+
Storage::disk($disk)->put($path, base64_decode($signature));
|
|
1093
|
+
|
|
1094
|
+
// create file record for upload
|
|
1095
|
+
$file = File::create([
|
|
1096
|
+
'company_uuid' => session('company'),
|
|
1097
|
+
'uploader_uuid' => session('user'),
|
|
1098
|
+
'name' => basename($path),
|
|
1099
|
+
'original_filename' => basename($path),
|
|
1100
|
+
'extension' => 'png',
|
|
1101
|
+
'content_type' => 'image/png',
|
|
1102
|
+
'path' => $path,
|
|
1103
|
+
'bucket' => $bucket,
|
|
1104
|
+
'type' => 'signature',
|
|
1105
|
+
'size' => Utils::getBase64ImageSize($signature),
|
|
1106
|
+
])->setKey($proof);
|
|
1107
|
+
|
|
1108
|
+
// set file to proof
|
|
1109
|
+
$proof->file_uuid = $file->uuid;
|
|
1110
|
+
$proof->save();
|
|
1111
|
+
|
|
1112
|
+
return new ProofResource($proof);
|
|
1113
|
+
}
|
|
1114
|
+
}
|