@fleetbase/fleetops-engine 0.2.6 → 0.2.7

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.
Files changed (307) hide show
  1. package/.gitattributes +14 -0
  2. package/.php-cs-fixer.cache +1 -0
  3. package/.php-cs-fixer.php +29 -0
  4. package/LICENSE.md +16 -4
  5. package/README.md +103 -13
  6. package/composer.json +85 -0
  7. package/extension.json +10 -0
  8. package/package.json +3 -3
  9. package/phpstan.neon.dist +8 -0
  10. package/phpunit.xml.dist +16 -0
  11. package/server/config/api.php +765 -0
  12. package/server/config/cache.stores.php +18 -0
  13. package/server/config/dompdf.php +242 -0
  14. package/server/config/fleetops.php +19 -0
  15. package/server/config/geocoder.php +108 -0
  16. package/server/data/globe.json +261 -0
  17. package/server/migrations/2023_04_27_053456_create_contacts_table.php +49 -0
  18. package/server/migrations/2023_04_27_053456_create_drivers_table.php +62 -0
  19. package/server/migrations/2023_04_27_053456_create_entities_table.php +67 -0
  20. package/server/migrations/2023_04_27_053456_create_fleet_drivers_table.php +39 -0
  21. package/server/migrations/2023_04_27_053456_create_fleets_table.php +47 -0
  22. package/server/migrations/2023_04_27_053456_create_fuel_reports_table.php +50 -0
  23. package/server/migrations/2023_04_27_053456_create_integrated_vendors_table.php +44 -0
  24. package/server/migrations/2023_04_27_053456_create_issues_table.php +53 -0
  25. package/server/migrations/2023_04_27_053456_create_orders_table.php +70 -0
  26. package/server/migrations/2023_04_27_053456_create_payloads_table.php +51 -0
  27. package/server/migrations/2023_04_27_053456_create_places_table.php +62 -0
  28. package/server/migrations/2023_04_27_053456_create_positions_table.php +46 -0
  29. package/server/migrations/2023_04_27_053456_create_proofs_table.php +44 -0
  30. package/server/migrations/2023_04_27_053456_create_purchase_rates_table.php +46 -0
  31. package/server/migrations/2023_04_27_053456_create_routes_table.php +40 -0
  32. package/server/migrations/2023_04_27_053456_create_service_areas_table.php +47 -0
  33. package/server/migrations/2023_04_27_053456_create_service_quote_items_table.php +42 -0
  34. package/server/migrations/2023_04_27_053456_create_service_quotes_table.php +47 -0
  35. package/server/migrations/2023_04_27_053456_create_service_rate_fees_table.php +45 -0
  36. package/server/migrations/2023_04_27_053456_create_service_rate_parcel_fees_table.php +47 -0
  37. package/server/migrations/2023_04_27_053456_create_service_rates_table.php +61 -0
  38. package/server/migrations/2023_04_27_053456_create_tracking_numbers_table.php +46 -0
  39. package/server/migrations/2023_04_27_053456_create_tracking_statuses_table.php +54 -0
  40. package/server/migrations/2023_04_27_053456_create_vehicles_table.php +84 -0
  41. package/server/migrations/2023_04_27_053456_create_vendors_table.php +56 -0
  42. package/server/migrations/2023_04_27_053456_create_waypoints_table.php +45 -0
  43. package/server/migrations/2023_04_27_053456_create_zones_table.php +46 -0
  44. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_companies_table.php +32 -0
  45. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_contacts_table.php +34 -0
  46. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_drivers_table.php +40 -0
  47. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_entities_table.php +40 -0
  48. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_fleet_drivers_table.php +34 -0
  49. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_fleets_table.php +36 -0
  50. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_fuel_reports_table.php +36 -0
  51. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_integrated_vendors_table.php +34 -0
  52. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_issues_table.php +38 -0
  53. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_orders_table.php +48 -0
  54. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_payloads_table.php +40 -0
  55. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_places_table.php +32 -0
  56. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_positions_table.php +36 -0
  57. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_proofs_table.php +34 -0
  58. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_purchase_rates_table.php +38 -0
  59. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_routes_table.php +34 -0
  60. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_areas_table.php +34 -0
  61. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_quote_items_table.php +32 -0
  62. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_quotes_table.php +38 -0
  63. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_rate_fees_table.php +32 -0
  64. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_rate_parcel_fees_table.php +32 -0
  65. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_rates_table.php +36 -0
  66. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_tracking_numbers_table.php +34 -0
  67. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_tracking_statuses_table.php +34 -0
  68. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_vehicles_table.php +36 -0
  69. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_vendors_table.php +40 -0
  70. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_waypoints_table.php +38 -0
  71. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_zones_table.php +34 -0
  72. package/server/migrations/2023_09_14_074512_update_vehicles_table.php +100 -0
  73. package/server/migrations/2023_09_14_074619_create_vehicle_devices_table.php +44 -0
  74. package/server/migrations/2023_09_26_071205_add_online_column_to_vehicles_table.php +32 -0
  75. package/server/migrations/2023_09_26_083957_create_fleet_vehicles_table.php +45 -0
  76. package/server/migrations/2023_09_27_023757_add_column_to_fleets_table.php +46 -0
  77. package/server/migrations/2023_10_05_074811_update_vehicle.php +42 -0
  78. package/server/resources/views/labels/default.php +165 -0
  79. package/server/src/Auth/Schemas/FleetOps.php +75 -0
  80. package/server/src/Casts/MultiPolygon.php +50 -0
  81. package/server/src/Casts/Point.php +109 -0
  82. package/server/src/Casts/Polygon.php +46 -0
  83. package/server/src/Console/Commands/DispatchAdhocOrders.php +137 -0
  84. package/server/src/Console/Commands/DispatchOrders.php +71 -0
  85. package/server/src/Console/Commands/TrackOrderDistanceAndTime.php +62 -0
  86. package/server/src/Events/DriverLocationChanged.php +174 -0
  87. package/server/src/Events/DriverSimulatedLocationChanged.php +183 -0
  88. package/server/src/Events/EntityDriverAssigned.php +36 -0
  89. package/server/src/Events/OrderCanceled.php +15 -0
  90. package/server/src/Events/OrderCompleted.php +15 -0
  91. package/server/src/Events/OrderDispatchFailed.php +42 -0
  92. package/server/src/Events/OrderDispatched.php +15 -0
  93. package/server/src/Events/OrderDriverAssigned.php +15 -0
  94. package/server/src/Events/OrderReady.php +15 -0
  95. package/server/src/Events/OrderStarted.php +15 -0
  96. package/server/src/Exceptions/IntegratedVendorException.php +18 -0
  97. package/server/src/Expansions/UserExpansion.php +63 -0
  98. package/server/src/Exports/ContactExport.php +56 -0
  99. package/server/src/Exports/DriverExport.php +61 -0
  100. package/server/src/Exports/FleetExport.php +53 -0
  101. package/server/src/Exports/PlaceExport.php +55 -0
  102. package/server/src/Exports/ServiceAreaExport.php +58 -0
  103. package/server/src/Exports/VehicleExport.php +57 -0
  104. package/server/src/Exports/VendorExport.php +57 -0
  105. package/server/src/Http/Controllers/Api/v1/ContactController.php +133 -0
  106. package/server/src/Http/Controllers/Api/v1/DriverController.php +691 -0
  107. package/server/src/Http/Controllers/Api/v1/EntityController.php +230 -0
  108. package/server/src/Http/Controllers/Api/v1/FleetController.php +146 -0
  109. package/server/src/Http/Controllers/Api/v1/LabelController.php +63 -0
  110. package/server/src/Http/Controllers/Api/v1/OrderController.php +1114 -0
  111. package/server/src/Http/Controllers/Api/v1/PayloadController.php +195 -0
  112. package/server/src/Http/Controllers/Api/v1/PlaceController.php +333 -0
  113. package/server/src/Http/Controllers/Api/v1/PurchaseRateController.php +199 -0
  114. package/server/src/Http/Controllers/Api/v1/ServiceAreaController.php +133 -0
  115. package/server/src/Http/Controllers/Api/v1/ServiceQuoteController.php +381 -0
  116. package/server/src/Http/Controllers/Api/v1/ServiceRateController.php +223 -0
  117. package/server/src/Http/Controllers/Api/v1/TrackingNumberController.php +146 -0
  118. package/server/src/Http/Controllers/Api/v1/TrackingStatusController.php +138 -0
  119. package/server/src/Http/Controllers/Api/v1/VehicleController.php +191 -0
  120. package/server/src/Http/Controllers/Api/v1/VendorController.php +159 -0
  121. package/server/src/Http/Controllers/Api/v1/ZoneController.php +146 -0
  122. package/server/src/Http/Controllers/FleetOpsController.php +13 -0
  123. package/server/src/Http/Controllers/Internal/v1/ContactController.php +69 -0
  124. package/server/src/Http/Controllers/Internal/v1/DriverController.php +261 -0
  125. package/server/src/Http/Controllers/Internal/v1/EntityController.php +15 -0
  126. package/server/src/Http/Controllers/Internal/v1/FleetController.php +152 -0
  127. package/server/src/Http/Controllers/Internal/v1/FleetOpsLookupController.php +80 -0
  128. package/server/src/Http/Controllers/Internal/v1/FuelReportController.php +15 -0
  129. package/server/src/Http/Controllers/Internal/v1/GeocoderController.php +96 -0
  130. package/server/src/Http/Controllers/Internal/v1/IntegratedVendorController.php +63 -0
  131. package/server/src/Http/Controllers/Internal/v1/IssueController.php +15 -0
  132. package/server/src/Http/Controllers/Internal/v1/LiveController.php +127 -0
  133. package/server/src/Http/Controllers/Internal/v1/MetricsController.php +75 -0
  134. package/server/src/Http/Controllers/Internal/v1/MorphController.php +77 -0
  135. package/server/src/Http/Controllers/Internal/v1/OrderConfigController.php +269 -0
  136. package/server/src/Http/Controllers/Internal/v1/OrderController.php +564 -0
  137. package/server/src/Http/Controllers/Internal/v1/PayloadController.php +15 -0
  138. package/server/src/Http/Controllers/Internal/v1/PlaceController.php +163 -0
  139. package/server/src/Http/Controllers/Internal/v1/ProofController.php +139 -0
  140. package/server/src/Http/Controllers/Internal/v1/PurchaseRateController.php +15 -0
  141. package/server/src/Http/Controllers/Internal/v1/RouteController.php +15 -0
  142. package/server/src/Http/Controllers/Internal/v1/ServiceAreaController.php +32 -0
  143. package/server/src/Http/Controllers/Internal/v1/ServiceQuoteController.php +345 -0
  144. package/server/src/Http/Controllers/Internal/v1/ServiceRateController.php +47 -0
  145. package/server/src/Http/Controllers/Internal/v1/SettingController.php +30 -0
  146. package/server/src/Http/Controllers/Internal/v1/TrackingNumberController.php +15 -0
  147. package/server/src/Http/Controllers/Internal/v1/TrackingStatusController.php +15 -0
  148. package/server/src/Http/Controllers/Internal/v1/VehicleController.php +65 -0
  149. package/server/src/Http/Controllers/Internal/v1/VehicleDeviceController.php +15 -0
  150. package/server/src/Http/Controllers/Internal/v1/VendorController.php +120 -0
  151. package/server/src/Http/Controllers/Internal/v1/ZoneController.php +15 -0
  152. package/server/src/Http/Filter/ContactFilter.php +86 -0
  153. package/server/src/Http/Filter/DriverFilter.php +148 -0
  154. package/server/src/Http/Filter/FleetFilter.php +108 -0
  155. package/server/src/Http/Filter/IntegratedVendorFilter.php +13 -0
  156. package/server/src/Http/Filter/OrderFilter.php +242 -0
  157. package/server/src/Http/Filter/PlaceFilter.php +111 -0
  158. package/server/src/Http/Filter/ServiceAreaFilter.php +13 -0
  159. package/server/src/Http/Filter/ServiceQuoteFilter.php +13 -0
  160. package/server/src/Http/Filter/ServiceRateFilter.php +33 -0
  161. package/server/src/Http/Filter/TrackingStatusFilter.php +43 -0
  162. package/server/src/Http/Filter/VehicleFilter.php +91 -0
  163. package/server/src/Http/Filter/VendorFilter.php +83 -0
  164. package/server/src/Http/Filter/ZoneFilter.php +13 -0
  165. package/server/src/Http/Requests/CancelOrderRequest.php +31 -0
  166. package/server/src/Http/Requests/CreateContactRequest.php +33 -0
  167. package/server/src/Http/Requests/CreateDriverRequest.php +55 -0
  168. package/server/src/Http/Requests/CreateEntityRequest.php +43 -0
  169. package/server/src/Http/Requests/CreateFleetRequest.php +32 -0
  170. package/server/src/Http/Requests/CreateOrderRequest.php +66 -0
  171. package/server/src/Http/Requests/CreatePayloadRequest.php +37 -0
  172. package/server/src/Http/Requests/CreatePlaceRequest.php +38 -0
  173. package/server/src/Http/Requests/CreatePurchaseRateRequest.php +33 -0
  174. package/server/src/Http/Requests/CreateServiceAreaRequest.php +35 -0
  175. package/server/src/Http/Requests/CreateServiceQuoteRequest.php +29 -0
  176. package/server/src/Http/Requests/CreateServiceRateRequest.php +56 -0
  177. package/server/src/Http/Requests/CreateTrackingNumberRequest.php +34 -0
  178. package/server/src/Http/Requests/CreateTrackingStatusRequest.php +42 -0
  179. package/server/src/Http/Requests/CreateVehicleRequest.php +32 -0
  180. package/server/src/Http/Requests/CreateVendorRequest.php +35 -0
  181. package/server/src/Http/Requests/CreateZoneRequest.php +35 -0
  182. package/server/src/Http/Requests/DecodeTrackingNumberQR.php +30 -0
  183. package/server/src/Http/Requests/DriverSimulationRequest.php +46 -0
  184. package/server/src/Http/Requests/Internal/AssignOrderRequest.php +31 -0
  185. package/server/src/Http/Requests/Internal/CreateDriverRequest.php +42 -0
  186. package/server/src/Http/Requests/Internal/FleetActionRequest.php +32 -0
  187. package/server/src/Http/Requests/Internal/UpdateDriverRequest.php +7 -0
  188. package/server/src/Http/Requests/QueryServiceQuotesRequest.php +41 -0
  189. package/server/src/Http/Requests/UpdateContactRequest.php +20 -0
  190. package/server/src/Http/Requests/UpdateDriverRequest.php +7 -0
  191. package/server/src/Http/Requests/UpdateEntityRequest.php +7 -0
  192. package/server/src/Http/Requests/UpdateFleetRequest.php +7 -0
  193. package/server/src/Http/Requests/UpdateOrderRequest.php +7 -0
  194. package/server/src/Http/Requests/UpdatePayloadRequest.php +7 -0
  195. package/server/src/Http/Requests/UpdatePlaceRequest.php +7 -0
  196. package/server/src/Http/Requests/UpdatePurchaseRateRequest.php +7 -0
  197. package/server/src/Http/Requests/UpdateServiceAreaRequest.php +29 -0
  198. package/server/src/Http/Requests/UpdateServiceQuoteRequest.php +29 -0
  199. package/server/src/Http/Requests/UpdateServiceRateRequest.php +29 -0
  200. package/server/src/Http/Requests/UpdateTrackingNumberRequest.php +7 -0
  201. package/server/src/Http/Requests/UpdateTrackingStatusRequest.php +32 -0
  202. package/server/src/Http/Requests/UpdateVehicleRequest.php +7 -0
  203. package/server/src/Http/Requests/UpdateVendorRequest.php +7 -0
  204. package/server/src/Http/Requests/UpdateZoneRequest.php +7 -0
  205. package/server/src/Http/Resources/Internal/v1/IntegratedVendorFacilitator.php +37 -0
  206. package/server/src/Http/Resources/Internal/v1/Vehicle.php +33 -0
  207. package/server/src/Http/Resources/Internal/v1/Waypoint.php +34 -0
  208. package/server/src/Http/Resources/v1/Contact.php +62 -0
  209. package/server/src/Http/Resources/v1/CurrentJob.php +36 -0
  210. package/server/src/Http/Resources/v1/DeletedResource.php +61 -0
  211. package/server/src/Http/Resources/v1/Driver.php +89 -0
  212. package/server/src/Http/Resources/v1/Entity.php +107 -0
  213. package/server/src/Http/Resources/v1/Fleet.php +60 -0
  214. package/server/src/Http/Resources/v1/FuelReport.php +67 -0
  215. package/server/src/Http/Resources/v1/Order.php +131 -0
  216. package/server/src/Http/Resources/v1/Payload.php +94 -0
  217. package/server/src/Http/Resources/v1/Place.php +84 -0
  218. package/server/src/Http/Resources/v1/Proof.php +36 -0
  219. package/server/src/Http/Resources/v1/PurchaseRate.php +77 -0
  220. package/server/src/Http/Resources/v1/ServiceArea.php +55 -0
  221. package/server/src/Http/Resources/v1/ServiceQuote.php +57 -0
  222. package/server/src/Http/Resources/v1/ServiceRate.php +94 -0
  223. package/server/src/Http/Resources/v1/ServiceRateFee.php +58 -0
  224. package/server/src/Http/Resources/v1/ServiceRateParcelFee.php +48 -0
  225. package/server/src/Http/Resources/v1/TrackingNumber.php +62 -0
  226. package/server/src/Http/Resources/v1/TrackingStatus.php +84 -0
  227. package/server/src/Http/Resources/v1/Vehicle.php +75 -0
  228. package/server/src/Http/Resources/v1/VehicleDevice.php +44 -0
  229. package/server/src/Http/Resources/v1/VehicleWithoutDriver.php +72 -0
  230. package/server/src/Http/Resources/v1/Vendor.php +72 -0
  231. package/server/src/Http/Resources/v1/Zone.php +60 -0
  232. package/server/src/Imports/OrdersImport.php +18 -0
  233. package/server/src/Integrations/Lalamove/Lalamove.php +678 -0
  234. package/server/src/Integrations/Lalamove/LalamoveDeliveryStop.php +97 -0
  235. package/server/src/Integrations/Lalamove/LalamoveMarket.php +123 -0
  236. package/server/src/Integrations/Lalamove/LalamoveServiceType.php +161 -0
  237. package/server/src/Jobs/SimulateDrivingRoute.php +81 -0
  238. package/server/src/Jobs/SimulateWaypointReached.php +79 -0
  239. package/server/src/Listeners/HandleOrderCanceled.php +46 -0
  240. package/server/src/Listeners/HandleOrderCreated.php +23 -0
  241. package/server/src/Listeners/HandleOrderDispatchFailed.php +35 -0
  242. package/server/src/Listeners/HandleOrderDispatched.php +108 -0
  243. package/server/src/Listeners/HandleOrderDriverAssigned.php +42 -0
  244. package/server/src/Listeners/HandleOrderReady.php +27 -0
  245. package/server/src/Listeners/HandleUserRemovedFromCompany.php +31 -0
  246. package/server/src/Models/Contact.php +239 -0
  247. package/server/src/Models/Driver.php +543 -0
  248. package/server/src/Models/Entity.php +416 -0
  249. package/server/src/Models/Fleet.php +203 -0
  250. package/server/src/Models/FleetDriver.php +73 -0
  251. package/server/src/Models/FleetVehicle.php +73 -0
  252. package/server/src/Models/FuelReport.php +125 -0
  253. package/server/src/Models/IntegratedVendor.php +219 -0
  254. package/server/src/Models/Issue.php +111 -0
  255. package/server/src/Models/Order.php +1132 -0
  256. package/server/src/Models/Payload.php +699 -0
  257. package/server/src/Models/Place.php +656 -0
  258. package/server/src/Models/Position.php +119 -0
  259. package/server/src/Models/Proof.php +94 -0
  260. package/server/src/Models/PurchaseRate.php +208 -0
  261. package/server/src/Models/Route.php +128 -0
  262. package/server/src/Models/ServiceArea.php +161 -0
  263. package/server/src/Models/ServiceQuote.php +207 -0
  264. package/server/src/Models/ServiceQuoteItem.php +46 -0
  265. package/server/src/Models/ServiceRate.php +953 -0
  266. package/server/src/Models/ServiceRateFee.php +96 -0
  267. package/server/src/Models/ServiceRateParcelFee.php +116 -0
  268. package/server/src/Models/TrackingNumber.php +310 -0
  269. package/server/src/Models/TrackingStatus.php +177 -0
  270. package/server/src/Models/Vehicle.php +452 -0
  271. package/server/src/Models/VehicleDevice.php +79 -0
  272. package/server/src/Models/Vendor.php +244 -0
  273. package/server/src/Models/Waypoint.php +226 -0
  274. package/server/src/Models/Zone.php +95 -0
  275. package/server/src/Notifications/OrderAssigned.php +140 -0
  276. package/server/src/Notifications/OrderCanceled.php +129 -0
  277. package/server/src/Notifications/OrderDispatchFailed.php +81 -0
  278. package/server/src/Notifications/OrderDispatched.php +173 -0
  279. package/server/src/Notifications/OrderPing.php +162 -0
  280. package/server/src/Notifications/OrderSplit.php +56 -0
  281. package/server/src/Observers/DriverObserver.php +34 -0
  282. package/server/src/Observers/OrderObserver.php +34 -0
  283. package/server/src/Observers/PayloadObserver.php +30 -0
  284. package/server/src/Observers/PlaceObserver.php +26 -0
  285. package/server/src/Observers/PurchaseRateObserver.php +61 -0
  286. package/server/src/Observers/ServiceAreaObserver.php +35 -0
  287. package/server/src/Observers/ServiceRateObserver.php +78 -0
  288. package/server/src/Observers/TrackingNumberObserver.php +44 -0
  289. package/server/src/Observers/UserObserver.php +20 -0
  290. package/server/src/Observers/VehicleObserver.php +66 -0
  291. package/server/src/Providers/EventServiceProvider.php +30 -0
  292. package/server/src/Providers/FleetOpsServiceProvider.php +94 -0
  293. package/server/src/Rules/ResolvablePoint.php +37 -0
  294. package/server/src/Scopes/DriverScope.php +21 -0
  295. package/server/src/Support/Algo.php +55 -0
  296. package/server/src/Support/DistanceMatrix.php +27 -0
  297. package/server/src/Support/Encoding/Polyline.php +168 -0
  298. package/server/src/Support/Flow.php +622 -0
  299. package/server/src/Support/Geocoding.php +216 -0
  300. package/server/src/Support/IntegratedVendors.php +287 -0
  301. package/server/src/Support/Metrics.php +305 -0
  302. package/server/src/Support/OSRM.php +191 -0
  303. package/server/src/Support/ParsePhone.php +21 -0
  304. package/server/src/Support/Utils.php +1145 -0
  305. package/server/src/Traits/HasTrackingNumber.php +185 -0
  306. package/server/src/routes.php +381 -0
  307. package/server/tests/Feature.php +5 -0
@@ -0,0 +1,691 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Http\Controllers\Api\v1;
4
+
5
+ use Fleetbase\FleetOps\Events\DriverLocationChanged;
6
+ use Fleetbase\FleetOps\Http\Requests\CreateDriverRequest;
7
+ use Fleetbase\FleetOps\Http\Requests\DriverSimulationRequest;
8
+ use Fleetbase\FleetOps\Http\Requests\UpdateDriverRequest;
9
+ use Fleetbase\FleetOps\Http\Resources\v1\DeletedResource;
10
+ use Fleetbase\FleetOps\Http\Resources\v1\Driver as DriverResource;
11
+ use Fleetbase\FleetOps\Jobs\SimulateDrivingRoute;
12
+ use Fleetbase\FleetOps\Models\Driver;
13
+ use Fleetbase\FleetOps\Models\Order;
14
+ use Fleetbase\FleetOps\Support\Flow;
15
+ use Fleetbase\FleetOps\Support\OSRM;
16
+ use Fleetbase\FleetOps\Support\Utils;
17
+ use Fleetbase\Http\Controllers\Controller;
18
+ use Fleetbase\Http\Requests\SwitchOrganizationRequest;
19
+ use Fleetbase\Http\Resources\Organization;
20
+ use Fleetbase\Models\Company;
21
+ use Fleetbase\Models\CompanyUser;
22
+ use Fleetbase\Models\User;
23
+ use Fleetbase\Models\UserDevice;
24
+ use Fleetbase\Models\VerificationCode;
25
+ use Fleetbase\Support\Auth;
26
+ use Geocoder\Laravel\Facades\Geocoder;
27
+ use Grimzy\LaravelMysqlSpatial\Types\Point;
28
+ use Illuminate\Http\Request;
29
+ use Illuminate\Support\Arr;
30
+ use Illuminate\Support\Carbon;
31
+ use Illuminate\Support\Facades\Hash;
32
+ use Illuminate\Support\Str;
33
+
34
+ class DriverController extends Controller
35
+ {
36
+ /**
37
+ * Creates a new Fleetbase Driver resource.
38
+ *
39
+ * @param \Fleetbase\Http\Requests\CreateDriverRequest $request
40
+ *
41
+ * @return \Fleetbase\Http\Resources\Driver
42
+ */
43
+ public function create(CreateDriverRequest $request)
44
+ {
45
+ // get request input
46
+ $input = $request->except(['name', 'password', 'email', 'phone', 'location', 'meta']);
47
+
48
+ // get user details for driver
49
+ $userDetails = $request->only(['name', 'password', 'email', 'phone']);
50
+ $userDetails['company_uuid'] = session('company');
51
+
52
+ // create user account for driver
53
+ $user = User::create($userDetails);
54
+
55
+ // set user id
56
+ $input['user_uuid'] = $user->uuid;
57
+ $input['company_uuid'] = session('company');
58
+
59
+ // vehicle assignment public_id -> uuid
60
+ if ($request->has('vehicle')) {
61
+ $input['vehicle_uuid'] = Utils::getUuid('vehicles', [
62
+ 'public_id' => $request->input('vehicle'),
63
+ 'company_uuid' => session('company'),
64
+ ]);
65
+ }
66
+
67
+ // vendor assignment public_id -> uuid
68
+ if ($request->has('vendor')) {
69
+ $input['vendor_uuid'] = Utils::getUuid('vendors', [
70
+ 'public_id' => $request->input('vendor'),
71
+ 'company_uuid' => session('company'),
72
+ ]);
73
+ }
74
+
75
+ // order|alias:job assignment public_id -> uuid
76
+ if ($request->has('job')) {
77
+ $input['current_job_uuid'] = Utils::getUuid('orders', [
78
+ 'public_id' => $request->input('job'),
79
+ 'company_uuid' => session('company'),
80
+ ]);
81
+ }
82
+
83
+ // default location
84
+ if ($request->missing('location')) {
85
+ $input['location'] = new Point(0, 0);
86
+ }
87
+
88
+ // create the driver
89
+ $driver = Driver::create($input);
90
+
91
+ // load user
92
+ $driver = $driver->load(['user', 'vehicle', 'vendor', 'currentJob']);
93
+
94
+ // response the driver resource
95
+ return new DriverResource($driver);
96
+ }
97
+
98
+ /**
99
+ * Updates a Fleetbase Driver resource.
100
+ *
101
+ * @param string $id
102
+ * @param \Fleetbase\Http\Requests\UpdateDriverRequest $request
103
+ *
104
+ * @return \Fleetbase\Http\Resources\Driver
105
+ */
106
+ public function update($id, UpdateDriverRequest $request)
107
+ {
108
+ // find for the driver
109
+ try {
110
+ $driver = Driver::findRecordOrFail($id, ['user']);
111
+ } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
112
+ return response()->json(
113
+ [
114
+ 'error' => 'Driver resource not found.',
115
+ ],
116
+ 404
117
+ );
118
+ }
119
+
120
+ // get request input
121
+ $input = $request->except(['name', 'password', 'email', 'phone', 'location', 'meta']);
122
+
123
+ // get user details for driver
124
+ $userDetails = $request->only(['name', 'password', 'email', 'phone']);
125
+
126
+ // update driver user details
127
+ $driver->user->update($userDetails);
128
+
129
+ // vehicle assignment public_id -> uuid
130
+ if ($request->has('vehicle')) {
131
+ $input['vehicle_uuid'] = Utils::getUuid('vehicles', [
132
+ 'public_id' => $request->input('vehicle'),
133
+ 'company_uuid' => session('company'),
134
+ ]);
135
+ }
136
+
137
+ // vendor assignment public_id -> uuid
138
+ if ($request->has('vendor')) {
139
+ $input['vendor_uuid'] = Utils::getUuid('vendors', [
140
+ 'public_id' => $request->input('vendor'),
141
+ 'company_uuid' => session('company'),
142
+ ]);
143
+ }
144
+
145
+ // order|alias:job assignment public_id -> uuid
146
+ if ($request->has('job')) {
147
+ $input['current_job_uuid'] = Utils::getUuid('orders', [
148
+ 'public_id' => $request->input('job'),
149
+ 'company_uuid' => session('company'),
150
+ ]);
151
+ }
152
+
153
+ // create the driver
154
+ $driver->update($input);
155
+ $driver->flushAttributesCache();
156
+
157
+ // load user
158
+ $driver = $driver->load(['user', 'vehicle', 'vendor', 'currentJob']);
159
+
160
+ // response the driver resource
161
+ return new DriverResource($driver);
162
+ }
163
+
164
+ /**
165
+ * Query for Fleetbase Driver resources.
166
+ *
167
+ * @return \Fleetbase\Http\Resources\DriverCollection
168
+ */
169
+ public function query(Request $request)
170
+ {
171
+ $results = Driver::queryWithRequest(
172
+ $request,
173
+ function (&$query, $request) {
174
+ if ($request->has('vendor')) {
175
+ $query->whereHas('vendor', function ($q) use ($request) {
176
+ $q->where('public_id', $request->input('vendor'));
177
+ });
178
+ }
179
+ }
180
+ );
181
+
182
+ return DriverResource::collection($results);
183
+ }
184
+
185
+ /**
186
+ * Finds a single Fleetbase Driver resources.
187
+ *
188
+ * @param string $id
189
+ *
190
+ * @return \Fleetbase\Http\Resources\DriverCollection
191
+ */
192
+ public function find($id)
193
+ {
194
+ // find for the driver
195
+ try {
196
+ $driver = Driver::findRecordOrFail($id, ['user', 'vehicle', 'vendor', 'currentJob']);
197
+ } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
198
+ return response()->json(
199
+ [
200
+ 'error' => 'Driver resource not found.',
201
+ ],
202
+ 404
203
+ );
204
+ }
205
+
206
+ // response the driver resource
207
+ return new DriverResource($driver);
208
+ }
209
+
210
+ /**
211
+ * Deletes a Fleetbase Driver resources.
212
+ *
213
+ * @param string $id
214
+ *
215
+ * @return \Fleetbase\Http\Resources\DriverCollection
216
+ */
217
+ public function delete($id, Request $request)
218
+ {
219
+ // find for the driver
220
+ try {
221
+ $driver = Driver::findRecordOrFail($id, ['user', 'vehicle', 'vendor', 'currentJob']);
222
+ } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
223
+ return response()->json(
224
+ [
225
+ 'error' => 'Driver resource not found.',
226
+ ],
227
+ 404
228
+ );
229
+ }
230
+
231
+ // delete the driver
232
+ $driver->delete();
233
+
234
+ // response the driver resource
235
+ return new DeletedResource($driver);
236
+ }
237
+
238
+ /**
239
+ * Update drivers geolocation data.
240
+ *
241
+ * @return \Illuminate\Http\Response
242
+ */
243
+ public function track(string $id, Request $request)
244
+ {
245
+ $latitude = $request->input('latitude');
246
+ $longitude = $request->input('longitude');
247
+ $altitude = $request->input('altitude');
248
+ $heading = $request->input('heading');
249
+ $speed = $request->input('speed');
250
+
251
+ try {
252
+ $driver = Driver::findRecordOrFail($id);
253
+ } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
254
+ return response()->json(
255
+ [
256
+ 'error' => 'Driver resource not found.',
257
+ ],
258
+ 404
259
+ );
260
+ }
261
+
262
+ // check if driver needs a geocoded update to set city and country they are currently in
263
+ $isGeocodable = Carbon::parse($driver->updated_at)->diffInMinutes(Carbon::now(), false) > 10 || empty($driver->country) || empty($driver->city);
264
+
265
+ $driver->update([
266
+ 'location' => new Point($latitude, $longitude),
267
+ 'altitude' => $altitude,
268
+ 'heading' => $heading,
269
+ 'speed' => $speed,
270
+ ]);
271
+
272
+ if ($isGeocodable) {
273
+ // attempt to geocode and fill country and city
274
+ $geocoded = Geocoder::reverse($latitude, $longitude)->get()->first();
275
+
276
+ if ($geocoded) {
277
+ $driver->update([
278
+ 'city' => $geocoded->getLocality(),
279
+ 'country' => $geocoded->getCountry()->getCode(),
280
+ ]);
281
+ }
282
+ }
283
+
284
+ broadcast(new DriverLocationChanged($driver));
285
+
286
+ $driver->updatePosition();
287
+ $driver->refresh();
288
+
289
+ return new DriverResource($driver);
290
+ }
291
+
292
+ /**
293
+ * Register device to the driver.
294
+ *
295
+ * @return \Illuminate\Http\Response
296
+ */
297
+ public function registerDevice(string $id, Request $request)
298
+ {
299
+ try {
300
+ $driver = Driver::findRecordOrFail($id);
301
+ } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
302
+ return response()->json(
303
+ [
304
+ 'error' => 'Driver resource not found.',
305
+ ],
306
+ 404
307
+ );
308
+ }
309
+
310
+ $token = $request->input('token');
311
+ $platform = $request->or(['platform', 'os']);
312
+
313
+ if (!$token) {
314
+ return response()->error('Token is required to register device.');
315
+ }
316
+
317
+ if (!$platform) {
318
+ return response()->error('Platform is required to register device.');
319
+ }
320
+
321
+ $device = UserDevice::firstOrCreate(
322
+ [
323
+ 'token' => $token,
324
+ 'platform' => $platform,
325
+ ],
326
+ [
327
+ 'user_uuid' => $driver->user_uuid,
328
+ 'platform' => $platform,
329
+ 'token' => $token,
330
+ 'status' => 'active',
331
+ ]
332
+ );
333
+
334
+ return response()->json([
335
+ 'device' => $device->public_id,
336
+ ]);
337
+ }
338
+
339
+ /**
340
+ * Authenticates customer using login credentials and returns with auth token.
341
+ *
342
+ * @return \Fleetbase\FleetOps\Http\Resources\v1\Driver
343
+ */
344
+ public function login(Request $request)
345
+ {
346
+ $identity = $request->input('identity');
347
+ $password = $request->input('password');
348
+ $attrs = $request->input(['name', 'phone', 'email']);
349
+
350
+ $user = User::where('email', $identity)->orWhere('phone', static::phone($identity))->first();
351
+
352
+ if (!Hash::check($password, $user->password)) {
353
+ return response()->error('Authentication failed using password provided.', 401);
354
+ }
355
+
356
+ // get the current company session
357
+ $company = Flow::getCompanySessionForUser($user);
358
+
359
+ // get driver record
360
+ $driver = Driver::firstOrCreate(
361
+ [
362
+ 'user_uuid' => $user->uuid,
363
+ 'company_uuid' => $company->uuid,
364
+ ],
365
+ [
366
+ 'user_uuid' => $user->uuid,
367
+ 'company_uuid' => $company->uuid,
368
+ 'name' => $attrs['name'] ?? $user->name,
369
+ 'phone' => $attrs['phone'] ?? $user->phone,
370
+ 'email' => $attrs['email'] ?? $user->email,
371
+ ]
372
+ );
373
+
374
+ // generate auth token
375
+ try {
376
+ $token = $user->createToken($driver->uuid);
377
+ } catch (\Exception $e) {
378
+ return response()->error($e->getMessage());
379
+ }
380
+
381
+ $driver->token = $token->plainTextToken;
382
+
383
+ return new DriverResource($driver);
384
+ }
385
+
386
+ /**
387
+ * Attempts authentication with phone number via SMS verification.
388
+ *
389
+ * @return \Illuminate\Http\Response
390
+ */
391
+ public function loginWithPhone()
392
+ {
393
+ $phone = static::phone();
394
+
395
+ // check if user exists
396
+ $user = User::where('phone', $phone)->whereNull('deleted_at')->withoutGlobalScopes()->first();
397
+
398
+ if (!$user) {
399
+ return response()->error('No driver with this phone # found.');
400
+ }
401
+
402
+ // get the current company session
403
+ $company = Flow::getCompanySessionForUser($user);
404
+
405
+ // generate verification token
406
+ try {
407
+ VerificationCode::generateSmsVerificationFor($user, 'driver_login', function ($verification) use ($company) {
408
+ return "Your {$company->name} verification code is {$verification->code}";
409
+ });
410
+ } catch (\Throwable $e) {
411
+ return response()->error($e->getMessage());
412
+ }
413
+
414
+ return response()->json(['status' => 'OK']);
415
+ }
416
+
417
+ /**
418
+ * Verifys SMS code and sends auth token with customer resource.
419
+ *
420
+ * @return \Fleetbase\FleetOps\Http\Resources\v1\Driver
421
+ */
422
+ public function verifyCode(Request $request)
423
+ {
424
+ $identity = Utils::isEmail($request->identity) ? $request->identity : static::phone($request->identity);
425
+ $code = $request->input('code');
426
+ $for = $request->input('for', 'driver_login');
427
+ $attrs = $request->input(['name', 'phone', 'email']);
428
+
429
+ if ($for === 'create_driver') {
430
+ return $this->create($request);
431
+ }
432
+
433
+ // check if user exists
434
+ $user = User::where('phone', $identity)->orWhere('email', $identity)->first();
435
+
436
+ if (!$user) {
437
+ return response()->error('Unable to verify code.');
438
+ }
439
+
440
+ // find and verify code
441
+ $verificationCode = VerificationCode::where(['subject_uuid' => $user->uuid, 'code' => $code, 'for' => $for])->exists();
442
+
443
+ if (!$verificationCode && $code !== '999000') {
444
+ return response()->error('Invalid verification code!');
445
+ }
446
+
447
+ // get the current company session
448
+ $company = Flow::getCompanySessionForUser($user);
449
+
450
+ // get driver record
451
+ $driver = Driver::firstOrCreate(
452
+ [
453
+ 'user_uuid' => $user->uuid,
454
+ 'company_uuid' => $company->uuid,
455
+ ],
456
+ [
457
+ 'user_uuid' => $user->uuid,
458
+ 'company_uuid' => $company->uuid,
459
+ 'name' => $attrs['name'] ?? $user->name,
460
+ 'phone' => $attrs['phone'] ?? $user->phone,
461
+ 'email' => $attrs['email'] ?? $user->email,
462
+ 'location' => new Point(0, 0),
463
+ ]
464
+ );
465
+
466
+ // generate auth token
467
+ try {
468
+ $token = $user->createToken($driver->uuid);
469
+ } catch (\Exception $e) {
470
+ return response()->error($e->getMessage());
471
+ }
472
+
473
+ // $driver->update(['auth_token' => $token->plainTextToken]);
474
+ $driver->token = $token->plainTextToken;
475
+
476
+ return new DriverResource($driver);
477
+ }
478
+
479
+ /**
480
+ * Patches phone number with international code.
481
+ */
482
+ public static function phone(string $phone = null): string
483
+ {
484
+ if ($phone === null) {
485
+ $phone = request()->input('phone');
486
+ }
487
+
488
+ if (!Str::startsWith($phone, '+')) {
489
+ $phone = '+' . $phone;
490
+ }
491
+
492
+ return $phone;
493
+ }
494
+
495
+ /**
496
+ * List organizations that driver is apart of.
497
+ *
498
+ * @return \Fleetbase\Http\Resources\Organization
499
+ */
500
+ public function listOrganizations(string $id, Request $request)
501
+ {
502
+ try {
503
+ $driver = Driver::findRecordOrFail($id, ['user.companies']);
504
+ } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
505
+ return response()->json(
506
+ [
507
+ 'error' => 'Driver resource not found.',
508
+ ],
509
+ 404
510
+ );
511
+ }
512
+
513
+ $companies = Company::whereHas('users', function ($q) use ($driver) {
514
+ $q->where('users.uuid', $driver->user_uuid);
515
+ })->get();
516
+
517
+ return Organization::collection($companies);
518
+ }
519
+
520
+ /**
521
+ * Allow driver to switch organization.
522
+ *
523
+ * @return \Fleetbase\Http\Resources\Organization
524
+ */
525
+ public function switchOrganization(string $id, SwitchOrganizationRequest $request)
526
+ {
527
+ $nextOrganization = $request->input('next');
528
+
529
+ try {
530
+ $driver = Driver::findRecordOrFail($id, ['user']);
531
+ } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
532
+ return response()->json(
533
+ [
534
+ 'error' => 'Driver resource not found.',
535
+ ],
536
+ 404
537
+ );
538
+ }
539
+
540
+ // get the next organization
541
+ $company = Company::where('public_id', $nextOrganization)->first();
542
+
543
+ if ($company->uuid === $driver->user->company_uuid) {
544
+ return response()->json([
545
+ 'error' => 'Driver is already on this organizations session',
546
+ ]);
547
+ }
548
+
549
+ if (!CompanyUser::where(['user_uuid' => $driver->user_uuid, 'company_uuid' => $company->uuid])->exists()) {
550
+ return response()->json([
551
+ 'errors' => ['You do not belong to this organization'],
552
+ ]);
553
+ }
554
+
555
+ $driver->user->assignCompany($company);
556
+ Auth::setSession($driver->user);
557
+
558
+ return new Organization($company);
559
+ }
560
+
561
+ /**
562
+ * This route can help to simulate certain actions for a driver.
563
+ * Actions:
564
+ * - Drive
565
+ * - Order.
566
+ *
567
+ * @param \Fleetbase\Http\Requests\DriverSimulationRequest $request
568
+ *
569
+ * @return \Illuminate\Http\Response
570
+ */
571
+ public function simulate(string $id, DriverSimulationRequest $request)
572
+ {
573
+ $start = $request->input('start');
574
+ $end = $request->input('end');
575
+ $order = $request->input('order');
576
+
577
+ try {
578
+ /** @var \Fleetbase\FleetOps\Models\Driver $driver */
579
+ $driver = Driver::findRecordOrFail($id, ['user']);
580
+ } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
581
+ return response()->json(
582
+ [
583
+ 'error' => 'Driver resource not found.',
584
+ ],
585
+ 404
586
+ );
587
+ }
588
+
589
+ if ($order) {
590
+ try {
591
+ /** @var \Fleetbase\FleetOps\Models\Order $order */
592
+ $order = Order::findRecordOrFail($order, ['payload']);
593
+ } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
594
+ return response()->json(
595
+ [
596
+ 'error' => 'Order resource not found.',
597
+ ],
598
+ 404
599
+ );
600
+ }
601
+
602
+ return $this->simulateDrivingForOrder($driver, $order);
603
+ }
604
+
605
+ return $this->simulateDrivingForRoute($driver, $start, $end);
606
+ }
607
+
608
+ /**
609
+ * Simulates a driving route for a given driver between a start and end point.
610
+ *
611
+ * @param Driver $driver the driver for whom the route is being simulated
612
+ * @param mixed $start the starting point of the route, can be a Point object or other representation
613
+ * @param mixed $end the ending point of the route, can be a Point object or other representation
614
+ *
615
+ * @return \Illuminate\Http\JsonResponse the response containing the route information
616
+ *
617
+ * @throws \Exception if there is an error in resolving the points or interacting with the OSRM API
618
+ */
619
+ public function simulateDrivingForRoute(Driver $driver, $start, $end)
620
+ {
621
+ // Resolve Point's from start/end
622
+ $start = Utils::getPointFromMixed($start);
623
+ $end = Utils::getPointFromMixed($end);
624
+
625
+ // Send points to OSRM
626
+ $route = OSRM::getRoute($start, $end);
627
+
628
+ // Create simulation events
629
+ if (isset($route['code']) && $route['code'] === 'Ok') {
630
+ // Get the route geometry to decode
631
+ $routeGeometry = data_get($route, 'routes.0.geometry');
632
+
633
+ // Decode the waypoints if needed
634
+ $waypoints = OSRM::decodePolyline($routeGeometry);
635
+
636
+ // Dispatch the job for each waypoint
637
+ SimulateDrivingRoute::dispatchIf(Arr::first($waypoints) instanceof Point, $driver, $waypoints);
638
+ }
639
+
640
+ return response()->json($route);
641
+ }
642
+
643
+ /**
644
+ * Simulates a driving route for a given driver based on an order's pickup and dropoff waypoints.
645
+ *
646
+ * @param Driver $driver the driver for whom the route is being simulated
647
+ * @param Order $order the order containing the pickup and dropoff waypoints
648
+ *
649
+ * @return \Illuminate\Http\JsonResponse the response containing the route information
650
+ *
651
+ * @throws \Exception if there is an error in resolving the points, validating the waypoints, or interacting with the OSRM API
652
+ */
653
+ public function simulateDrivingForOrder(Driver $driver, Order $order)
654
+ {
655
+ // Get the order Pickup and Dropoff Waypoints
656
+ $pickup = $order->payload->getPickupOrFirstWaypoint();
657
+ $dropoff = $order->payload->getDropoffOrLastWaypoint();
658
+
659
+ // Convert order Pickup/Dropoff Place Waypoint's to Point's
660
+ $start = Utils::getPointFromMixed($pickup);
661
+ $end = Utils::getPointFromMixed($dropoff);
662
+
663
+ // Send points to OSRM
664
+ $route = OSRM::getRoute($start, $end);
665
+
666
+ // Create simulation events
667
+ if (isset($route['code']) && $route['code'] === 'Ok') {
668
+ // Get the route geometry to decode
669
+ $routeGeometry = data_get($route, 'routes.0.geometry');
670
+
671
+ // Decode the waypoints if needed
672
+ $waypoints = OSRM::decodePolyline($routeGeometry);
673
+
674
+ // Loop through waypoints to calculate the heading for each point
675
+ for ($i = 0; $i < count($waypoints) - 1; $i++) {
676
+ $point1 = $waypoints[$i];
677
+ $point2 = $waypoints[$i + 1];
678
+
679
+ $heading = Utils::calculateHeading($point1, $point2);
680
+
681
+ // Directly add the 'heading' property to the Point object
682
+ $point1->heading = $heading;
683
+ }
684
+
685
+ // Dispatch the job for each waypoint
686
+ SimulateDrivingRoute::dispatchIf(Arr::first($waypoints) instanceof Point, $driver, $waypoints);
687
+ }
688
+
689
+ return response()->json($route);
690
+ }
691
+ }