@fleetbase/fleetops-engine 0.2.5 → 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 (325) 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/addon/components/admin/visibility-controls.hbs +12 -0
  7. package/addon/components/admin/visibility-controls.js +82 -0
  8. package/addon/components/fleet-panel.js +13 -4
  9. package/addon/components/fleet-vehicle-listing.hbs +1 -1
  10. package/addon/components/layout/fleet-ops-sidebar.hbs +26 -0
  11. package/addon/components/layout/fleet-ops-sidebar.js +129 -0
  12. package/addon/engine.js +19 -0
  13. package/addon/helpers/is-section-visible.js +5 -0
  14. package/addon/routes/application.js +6 -2
  15. package/addon/routes/virtual.js +10 -0
  16. package/addon/routes.js +1 -0
  17. package/addon/templates/application.hbs +1 -19
  18. package/addon/templates/virtual.hbs +9 -0
  19. package/app/components/admin/visibility-controls.js +1 -0
  20. package/app/components/layout/fleet-ops-sidebar.js +1 -0
  21. package/app/helpers/is-section-visible.js +1 -0
  22. package/app/routes/virtual.js +1 -0
  23. package/app/templates/virtual.js +1 -0
  24. package/composer.json +85 -0
  25. package/extension.json +10 -0
  26. package/package.json +6 -6
  27. package/phpstan.neon.dist +8 -0
  28. package/phpunit.xml.dist +16 -0
  29. package/server/config/api.php +765 -0
  30. package/server/config/cache.stores.php +18 -0
  31. package/server/config/dompdf.php +242 -0
  32. package/server/config/fleetops.php +19 -0
  33. package/server/config/geocoder.php +108 -0
  34. package/server/data/globe.json +261 -0
  35. package/server/migrations/2023_04_27_053456_create_contacts_table.php +49 -0
  36. package/server/migrations/2023_04_27_053456_create_drivers_table.php +62 -0
  37. package/server/migrations/2023_04_27_053456_create_entities_table.php +67 -0
  38. package/server/migrations/2023_04_27_053456_create_fleet_drivers_table.php +39 -0
  39. package/server/migrations/2023_04_27_053456_create_fleets_table.php +47 -0
  40. package/server/migrations/2023_04_27_053456_create_fuel_reports_table.php +50 -0
  41. package/server/migrations/2023_04_27_053456_create_integrated_vendors_table.php +44 -0
  42. package/server/migrations/2023_04_27_053456_create_issues_table.php +53 -0
  43. package/server/migrations/2023_04_27_053456_create_orders_table.php +70 -0
  44. package/server/migrations/2023_04_27_053456_create_payloads_table.php +51 -0
  45. package/server/migrations/2023_04_27_053456_create_places_table.php +62 -0
  46. package/server/migrations/2023_04_27_053456_create_positions_table.php +46 -0
  47. package/server/migrations/2023_04_27_053456_create_proofs_table.php +44 -0
  48. package/server/migrations/2023_04_27_053456_create_purchase_rates_table.php +46 -0
  49. package/server/migrations/2023_04_27_053456_create_routes_table.php +40 -0
  50. package/server/migrations/2023_04_27_053456_create_service_areas_table.php +47 -0
  51. package/server/migrations/2023_04_27_053456_create_service_quote_items_table.php +42 -0
  52. package/server/migrations/2023_04_27_053456_create_service_quotes_table.php +47 -0
  53. package/server/migrations/2023_04_27_053456_create_service_rate_fees_table.php +45 -0
  54. package/server/migrations/2023_04_27_053456_create_service_rate_parcel_fees_table.php +47 -0
  55. package/server/migrations/2023_04_27_053456_create_service_rates_table.php +61 -0
  56. package/server/migrations/2023_04_27_053456_create_tracking_numbers_table.php +46 -0
  57. package/server/migrations/2023_04_27_053456_create_tracking_statuses_table.php +54 -0
  58. package/server/migrations/2023_04_27_053456_create_vehicles_table.php +84 -0
  59. package/server/migrations/2023_04_27_053456_create_vendors_table.php +56 -0
  60. package/server/migrations/2023_04_27_053456_create_waypoints_table.php +45 -0
  61. package/server/migrations/2023_04_27_053456_create_zones_table.php +46 -0
  62. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_companies_table.php +32 -0
  63. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_contacts_table.php +34 -0
  64. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_drivers_table.php +40 -0
  65. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_entities_table.php +40 -0
  66. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_fleet_drivers_table.php +34 -0
  67. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_fleets_table.php +36 -0
  68. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_fuel_reports_table.php +36 -0
  69. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_integrated_vendors_table.php +34 -0
  70. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_issues_table.php +38 -0
  71. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_orders_table.php +48 -0
  72. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_payloads_table.php +40 -0
  73. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_places_table.php +32 -0
  74. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_positions_table.php +36 -0
  75. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_proofs_table.php +34 -0
  76. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_purchase_rates_table.php +38 -0
  77. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_routes_table.php +34 -0
  78. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_areas_table.php +34 -0
  79. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_quote_items_table.php +32 -0
  80. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_quotes_table.php +38 -0
  81. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_rate_fees_table.php +32 -0
  82. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_rate_parcel_fees_table.php +32 -0
  83. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_rates_table.php +36 -0
  84. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_tracking_numbers_table.php +34 -0
  85. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_tracking_statuses_table.php +34 -0
  86. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_vehicles_table.php +36 -0
  87. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_vendors_table.php +40 -0
  88. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_waypoints_table.php +38 -0
  89. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_zones_table.php +34 -0
  90. package/server/migrations/2023_09_14_074512_update_vehicles_table.php +100 -0
  91. package/server/migrations/2023_09_14_074619_create_vehicle_devices_table.php +44 -0
  92. package/server/migrations/2023_09_26_071205_add_online_column_to_vehicles_table.php +32 -0
  93. package/server/migrations/2023_09_26_083957_create_fleet_vehicles_table.php +45 -0
  94. package/server/migrations/2023_09_27_023757_add_column_to_fleets_table.php +46 -0
  95. package/server/migrations/2023_10_05_074811_update_vehicle.php +42 -0
  96. package/server/resources/views/labels/default.php +165 -0
  97. package/server/src/Auth/Schemas/FleetOps.php +75 -0
  98. package/server/src/Casts/MultiPolygon.php +50 -0
  99. package/server/src/Casts/Point.php +109 -0
  100. package/server/src/Casts/Polygon.php +46 -0
  101. package/server/src/Console/Commands/DispatchAdhocOrders.php +137 -0
  102. package/server/src/Console/Commands/DispatchOrders.php +71 -0
  103. package/server/src/Console/Commands/TrackOrderDistanceAndTime.php +62 -0
  104. package/server/src/Events/DriverLocationChanged.php +174 -0
  105. package/server/src/Events/DriverSimulatedLocationChanged.php +183 -0
  106. package/server/src/Events/EntityDriverAssigned.php +36 -0
  107. package/server/src/Events/OrderCanceled.php +15 -0
  108. package/server/src/Events/OrderCompleted.php +15 -0
  109. package/server/src/Events/OrderDispatchFailed.php +42 -0
  110. package/server/src/Events/OrderDispatched.php +15 -0
  111. package/server/src/Events/OrderDriverAssigned.php +15 -0
  112. package/server/src/Events/OrderReady.php +15 -0
  113. package/server/src/Events/OrderStarted.php +15 -0
  114. package/server/src/Exceptions/IntegratedVendorException.php +18 -0
  115. package/server/src/Expansions/UserExpansion.php +63 -0
  116. package/server/src/Exports/ContactExport.php +56 -0
  117. package/server/src/Exports/DriverExport.php +61 -0
  118. package/server/src/Exports/FleetExport.php +53 -0
  119. package/server/src/Exports/PlaceExport.php +55 -0
  120. package/server/src/Exports/ServiceAreaExport.php +58 -0
  121. package/server/src/Exports/VehicleExport.php +57 -0
  122. package/server/src/Exports/VendorExport.php +57 -0
  123. package/server/src/Http/Controllers/Api/v1/ContactController.php +133 -0
  124. package/server/src/Http/Controllers/Api/v1/DriverController.php +691 -0
  125. package/server/src/Http/Controllers/Api/v1/EntityController.php +230 -0
  126. package/server/src/Http/Controllers/Api/v1/FleetController.php +146 -0
  127. package/server/src/Http/Controllers/Api/v1/LabelController.php +63 -0
  128. package/server/src/Http/Controllers/Api/v1/OrderController.php +1114 -0
  129. package/server/src/Http/Controllers/Api/v1/PayloadController.php +195 -0
  130. package/server/src/Http/Controllers/Api/v1/PlaceController.php +333 -0
  131. package/server/src/Http/Controllers/Api/v1/PurchaseRateController.php +199 -0
  132. package/server/src/Http/Controllers/Api/v1/ServiceAreaController.php +133 -0
  133. package/server/src/Http/Controllers/Api/v1/ServiceQuoteController.php +381 -0
  134. package/server/src/Http/Controllers/Api/v1/ServiceRateController.php +223 -0
  135. package/server/src/Http/Controllers/Api/v1/TrackingNumberController.php +146 -0
  136. package/server/src/Http/Controllers/Api/v1/TrackingStatusController.php +138 -0
  137. package/server/src/Http/Controllers/Api/v1/VehicleController.php +191 -0
  138. package/server/src/Http/Controllers/Api/v1/VendorController.php +159 -0
  139. package/server/src/Http/Controllers/Api/v1/ZoneController.php +146 -0
  140. package/server/src/Http/Controllers/FleetOpsController.php +13 -0
  141. package/server/src/Http/Controllers/Internal/v1/ContactController.php +69 -0
  142. package/server/src/Http/Controllers/Internal/v1/DriverController.php +261 -0
  143. package/server/src/Http/Controllers/Internal/v1/EntityController.php +15 -0
  144. package/server/src/Http/Controllers/Internal/v1/FleetController.php +152 -0
  145. package/server/src/Http/Controllers/Internal/v1/FleetOpsLookupController.php +80 -0
  146. package/server/src/Http/Controllers/Internal/v1/FuelReportController.php +15 -0
  147. package/server/src/Http/Controllers/Internal/v1/GeocoderController.php +96 -0
  148. package/server/src/Http/Controllers/Internal/v1/IntegratedVendorController.php +63 -0
  149. package/server/src/Http/Controllers/Internal/v1/IssueController.php +15 -0
  150. package/server/src/Http/Controllers/Internal/v1/LiveController.php +127 -0
  151. package/server/src/Http/Controllers/Internal/v1/MetricsController.php +75 -0
  152. package/server/src/Http/Controllers/Internal/v1/MorphController.php +77 -0
  153. package/server/src/Http/Controllers/Internal/v1/OrderConfigController.php +269 -0
  154. package/server/src/Http/Controllers/Internal/v1/OrderController.php +564 -0
  155. package/server/src/Http/Controllers/Internal/v1/PayloadController.php +15 -0
  156. package/server/src/Http/Controllers/Internal/v1/PlaceController.php +163 -0
  157. package/server/src/Http/Controllers/Internal/v1/ProofController.php +139 -0
  158. package/server/src/Http/Controllers/Internal/v1/PurchaseRateController.php +15 -0
  159. package/server/src/Http/Controllers/Internal/v1/RouteController.php +15 -0
  160. package/server/src/Http/Controllers/Internal/v1/ServiceAreaController.php +32 -0
  161. package/server/src/Http/Controllers/Internal/v1/ServiceQuoteController.php +345 -0
  162. package/server/src/Http/Controllers/Internal/v1/ServiceRateController.php +47 -0
  163. package/server/src/Http/Controllers/Internal/v1/SettingController.php +30 -0
  164. package/server/src/Http/Controllers/Internal/v1/TrackingNumberController.php +15 -0
  165. package/server/src/Http/Controllers/Internal/v1/TrackingStatusController.php +15 -0
  166. package/server/src/Http/Controllers/Internal/v1/VehicleController.php +65 -0
  167. package/server/src/Http/Controllers/Internal/v1/VehicleDeviceController.php +15 -0
  168. package/server/src/Http/Controllers/Internal/v1/VendorController.php +120 -0
  169. package/server/src/Http/Controllers/Internal/v1/ZoneController.php +15 -0
  170. package/server/src/Http/Filter/ContactFilter.php +86 -0
  171. package/server/src/Http/Filter/DriverFilter.php +148 -0
  172. package/server/src/Http/Filter/FleetFilter.php +108 -0
  173. package/server/src/Http/Filter/IntegratedVendorFilter.php +13 -0
  174. package/server/src/Http/Filter/OrderFilter.php +242 -0
  175. package/server/src/Http/Filter/PlaceFilter.php +111 -0
  176. package/server/src/Http/Filter/ServiceAreaFilter.php +13 -0
  177. package/server/src/Http/Filter/ServiceQuoteFilter.php +13 -0
  178. package/server/src/Http/Filter/ServiceRateFilter.php +33 -0
  179. package/server/src/Http/Filter/TrackingStatusFilter.php +43 -0
  180. package/server/src/Http/Filter/VehicleFilter.php +91 -0
  181. package/server/src/Http/Filter/VendorFilter.php +83 -0
  182. package/server/src/Http/Filter/ZoneFilter.php +13 -0
  183. package/server/src/Http/Requests/CancelOrderRequest.php +31 -0
  184. package/server/src/Http/Requests/CreateContactRequest.php +33 -0
  185. package/server/src/Http/Requests/CreateDriverRequest.php +55 -0
  186. package/server/src/Http/Requests/CreateEntityRequest.php +43 -0
  187. package/server/src/Http/Requests/CreateFleetRequest.php +32 -0
  188. package/server/src/Http/Requests/CreateOrderRequest.php +66 -0
  189. package/server/src/Http/Requests/CreatePayloadRequest.php +37 -0
  190. package/server/src/Http/Requests/CreatePlaceRequest.php +38 -0
  191. package/server/src/Http/Requests/CreatePurchaseRateRequest.php +33 -0
  192. package/server/src/Http/Requests/CreateServiceAreaRequest.php +35 -0
  193. package/server/src/Http/Requests/CreateServiceQuoteRequest.php +29 -0
  194. package/server/src/Http/Requests/CreateServiceRateRequest.php +56 -0
  195. package/server/src/Http/Requests/CreateTrackingNumberRequest.php +34 -0
  196. package/server/src/Http/Requests/CreateTrackingStatusRequest.php +42 -0
  197. package/server/src/Http/Requests/CreateVehicleRequest.php +32 -0
  198. package/server/src/Http/Requests/CreateVendorRequest.php +35 -0
  199. package/server/src/Http/Requests/CreateZoneRequest.php +35 -0
  200. package/server/src/Http/Requests/DecodeTrackingNumberQR.php +30 -0
  201. package/server/src/Http/Requests/DriverSimulationRequest.php +46 -0
  202. package/server/src/Http/Requests/Internal/AssignOrderRequest.php +31 -0
  203. package/server/src/Http/Requests/Internal/CreateDriverRequest.php +42 -0
  204. package/server/src/Http/Requests/Internal/FleetActionRequest.php +32 -0
  205. package/server/src/Http/Requests/Internal/UpdateDriverRequest.php +7 -0
  206. package/server/src/Http/Requests/QueryServiceQuotesRequest.php +41 -0
  207. package/server/src/Http/Requests/UpdateContactRequest.php +20 -0
  208. package/server/src/Http/Requests/UpdateDriverRequest.php +7 -0
  209. package/server/src/Http/Requests/UpdateEntityRequest.php +7 -0
  210. package/server/src/Http/Requests/UpdateFleetRequest.php +7 -0
  211. package/server/src/Http/Requests/UpdateOrderRequest.php +7 -0
  212. package/server/src/Http/Requests/UpdatePayloadRequest.php +7 -0
  213. package/server/src/Http/Requests/UpdatePlaceRequest.php +7 -0
  214. package/server/src/Http/Requests/UpdatePurchaseRateRequest.php +7 -0
  215. package/server/src/Http/Requests/UpdateServiceAreaRequest.php +29 -0
  216. package/server/src/Http/Requests/UpdateServiceQuoteRequest.php +29 -0
  217. package/server/src/Http/Requests/UpdateServiceRateRequest.php +29 -0
  218. package/server/src/Http/Requests/UpdateTrackingNumberRequest.php +7 -0
  219. package/server/src/Http/Requests/UpdateTrackingStatusRequest.php +32 -0
  220. package/server/src/Http/Requests/UpdateVehicleRequest.php +7 -0
  221. package/server/src/Http/Requests/UpdateVendorRequest.php +7 -0
  222. package/server/src/Http/Requests/UpdateZoneRequest.php +7 -0
  223. package/server/src/Http/Resources/Internal/v1/IntegratedVendorFacilitator.php +37 -0
  224. package/server/src/Http/Resources/Internal/v1/Vehicle.php +33 -0
  225. package/server/src/Http/Resources/Internal/v1/Waypoint.php +34 -0
  226. package/server/src/Http/Resources/v1/Contact.php +62 -0
  227. package/server/src/Http/Resources/v1/CurrentJob.php +36 -0
  228. package/server/src/Http/Resources/v1/DeletedResource.php +61 -0
  229. package/server/src/Http/Resources/v1/Driver.php +89 -0
  230. package/server/src/Http/Resources/v1/Entity.php +107 -0
  231. package/server/src/Http/Resources/v1/Fleet.php +60 -0
  232. package/server/src/Http/Resources/v1/FuelReport.php +67 -0
  233. package/server/src/Http/Resources/v1/Order.php +131 -0
  234. package/server/src/Http/Resources/v1/Payload.php +94 -0
  235. package/server/src/Http/Resources/v1/Place.php +84 -0
  236. package/server/src/Http/Resources/v1/Proof.php +36 -0
  237. package/server/src/Http/Resources/v1/PurchaseRate.php +77 -0
  238. package/server/src/Http/Resources/v1/ServiceArea.php +55 -0
  239. package/server/src/Http/Resources/v1/ServiceQuote.php +57 -0
  240. package/server/src/Http/Resources/v1/ServiceRate.php +94 -0
  241. package/server/src/Http/Resources/v1/ServiceRateFee.php +58 -0
  242. package/server/src/Http/Resources/v1/ServiceRateParcelFee.php +48 -0
  243. package/server/src/Http/Resources/v1/TrackingNumber.php +62 -0
  244. package/server/src/Http/Resources/v1/TrackingStatus.php +84 -0
  245. package/server/src/Http/Resources/v1/Vehicle.php +75 -0
  246. package/server/src/Http/Resources/v1/VehicleDevice.php +44 -0
  247. package/server/src/Http/Resources/v1/VehicleWithoutDriver.php +72 -0
  248. package/server/src/Http/Resources/v1/Vendor.php +72 -0
  249. package/server/src/Http/Resources/v1/Zone.php +60 -0
  250. package/server/src/Imports/OrdersImport.php +18 -0
  251. package/server/src/Integrations/Lalamove/Lalamove.php +678 -0
  252. package/server/src/Integrations/Lalamove/LalamoveDeliveryStop.php +97 -0
  253. package/server/src/Integrations/Lalamove/LalamoveMarket.php +123 -0
  254. package/server/src/Integrations/Lalamove/LalamoveServiceType.php +161 -0
  255. package/server/src/Jobs/SimulateDrivingRoute.php +81 -0
  256. package/server/src/Jobs/SimulateWaypointReached.php +79 -0
  257. package/server/src/Listeners/HandleOrderCanceled.php +46 -0
  258. package/server/src/Listeners/HandleOrderCreated.php +23 -0
  259. package/server/src/Listeners/HandleOrderDispatchFailed.php +35 -0
  260. package/server/src/Listeners/HandleOrderDispatched.php +108 -0
  261. package/server/src/Listeners/HandleOrderDriverAssigned.php +42 -0
  262. package/server/src/Listeners/HandleOrderReady.php +27 -0
  263. package/server/src/Listeners/HandleUserRemovedFromCompany.php +31 -0
  264. package/server/src/Models/Contact.php +239 -0
  265. package/server/src/Models/Driver.php +543 -0
  266. package/server/src/Models/Entity.php +416 -0
  267. package/server/src/Models/Fleet.php +203 -0
  268. package/server/src/Models/FleetDriver.php +73 -0
  269. package/server/src/Models/FleetVehicle.php +73 -0
  270. package/server/src/Models/FuelReport.php +125 -0
  271. package/server/src/Models/IntegratedVendor.php +219 -0
  272. package/server/src/Models/Issue.php +111 -0
  273. package/server/src/Models/Order.php +1132 -0
  274. package/server/src/Models/Payload.php +699 -0
  275. package/server/src/Models/Place.php +656 -0
  276. package/server/src/Models/Position.php +119 -0
  277. package/server/src/Models/Proof.php +94 -0
  278. package/server/src/Models/PurchaseRate.php +208 -0
  279. package/server/src/Models/Route.php +128 -0
  280. package/server/src/Models/ServiceArea.php +161 -0
  281. package/server/src/Models/ServiceQuote.php +207 -0
  282. package/server/src/Models/ServiceQuoteItem.php +46 -0
  283. package/server/src/Models/ServiceRate.php +953 -0
  284. package/server/src/Models/ServiceRateFee.php +96 -0
  285. package/server/src/Models/ServiceRateParcelFee.php +116 -0
  286. package/server/src/Models/TrackingNumber.php +310 -0
  287. package/server/src/Models/TrackingStatus.php +177 -0
  288. package/server/src/Models/Vehicle.php +452 -0
  289. package/server/src/Models/VehicleDevice.php +79 -0
  290. package/server/src/Models/Vendor.php +244 -0
  291. package/server/src/Models/Waypoint.php +226 -0
  292. package/server/src/Models/Zone.php +95 -0
  293. package/server/src/Notifications/OrderAssigned.php +140 -0
  294. package/server/src/Notifications/OrderCanceled.php +129 -0
  295. package/server/src/Notifications/OrderDispatchFailed.php +81 -0
  296. package/server/src/Notifications/OrderDispatched.php +173 -0
  297. package/server/src/Notifications/OrderPing.php +162 -0
  298. package/server/src/Notifications/OrderSplit.php +56 -0
  299. package/server/src/Observers/DriverObserver.php +34 -0
  300. package/server/src/Observers/OrderObserver.php +34 -0
  301. package/server/src/Observers/PayloadObserver.php +30 -0
  302. package/server/src/Observers/PlaceObserver.php +26 -0
  303. package/server/src/Observers/PurchaseRateObserver.php +61 -0
  304. package/server/src/Observers/ServiceAreaObserver.php +35 -0
  305. package/server/src/Observers/ServiceRateObserver.php +78 -0
  306. package/server/src/Observers/TrackingNumberObserver.php +44 -0
  307. package/server/src/Observers/UserObserver.php +20 -0
  308. package/server/src/Observers/VehicleObserver.php +66 -0
  309. package/server/src/Providers/EventServiceProvider.php +30 -0
  310. package/server/src/Providers/FleetOpsServiceProvider.php +94 -0
  311. package/server/src/Rules/ResolvablePoint.php +37 -0
  312. package/server/src/Scopes/DriverScope.php +21 -0
  313. package/server/src/Support/Algo.php +55 -0
  314. package/server/src/Support/DistanceMatrix.php +27 -0
  315. package/server/src/Support/Encoding/Polyline.php +168 -0
  316. package/server/src/Support/Flow.php +622 -0
  317. package/server/src/Support/Geocoding.php +216 -0
  318. package/server/src/Support/IntegratedVendors.php +287 -0
  319. package/server/src/Support/Metrics.php +305 -0
  320. package/server/src/Support/OSRM.php +191 -0
  321. package/server/src/Support/ParsePhone.php +21 -0
  322. package/server/src/Support/Utils.php +1145 -0
  323. package/server/src/Traits/HasTrackingNumber.php +185 -0
  324. package/server/src/routes.php +381 -0
  325. package/server/tests/Feature.php +5 -0
@@ -0,0 +1,18 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Imports;
4
+
5
+ use Illuminate\Support\Collection;
6
+ use Maatwebsite\Excel\Concerns\ToCollection;
7
+ use Maatwebsite\Excel\Concerns\WithHeadingRow;
8
+
9
+ class OrdersImport implements ToCollection, WithHeadingRow
10
+ {
11
+ /**
12
+ * @return \Illuminate\Support\Collection
13
+ */
14
+ public function collection(Collection $rows)
15
+ {
16
+ return $rows;
17
+ }
18
+ }
@@ -0,0 +1,678 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Integrations\Lalamove;
4
+
5
+ use Fleetbase\FleetOps\Exceptions\IntegratedVendorException;
6
+ use Fleetbase\FleetOps\Models\Contact;
7
+ use Fleetbase\FleetOps\Models\IntegratedVendor;
8
+ use Fleetbase\FleetOps\Models\Order;
9
+ use Fleetbase\FleetOps\Models\Payload;
10
+ use Fleetbase\FleetOps\Models\Place;
11
+ use Fleetbase\FleetOps\Models\ServiceQuote;
12
+ use Fleetbase\FleetOps\Models\ServiceQuoteItem;
13
+ use Fleetbase\FleetOps\Support\ParsePhone;
14
+ use Fleetbase\FleetOps\Support\Utils;
15
+ use Fleetbase\Support\Auth;
16
+ use GuzzleHttp\Client;
17
+ use Illuminate\Http\Request;
18
+ use Illuminate\Support\Arr;
19
+ use Illuminate\Support\Carbon;
20
+ use Illuminate\Support\Str;
21
+
22
+ class Lalamove
23
+ {
24
+ /**
25
+ * API Host URL.
26
+ */
27
+ private string $host = 'https://rest.lalamove.com/';
28
+
29
+ /**
30
+ * API Sandbox Host URL.
31
+ */
32
+ private string $sandboxHost = 'https://rest.sandbox.lalamove.com/';
33
+
34
+ /**
35
+ * API Namespace.
36
+ */
37
+ private string $namespace = 'v3';
38
+
39
+ /**
40
+ * Determines if instance is sandbox instance.
41
+ */
42
+ private bool $isSandbox = false;
43
+
44
+ /**
45
+ * API Key.
46
+ */
47
+ private string $apiKey;
48
+
49
+ /**
50
+ * API Secret.
51
+ */
52
+ private string $apiSecret;
53
+
54
+ /**
55
+ * Applicable request ID.
56
+ */
57
+ private string $requestId;
58
+
59
+ /**
60
+ * Applicable options.
61
+ */
62
+ private array $options = [];
63
+
64
+ /**
65
+ * HTTP Client Instance.
66
+ */
67
+ private Client $client;
68
+
69
+ /**
70
+ * The current Lalamove Market.
71
+ */
72
+ private LalamoveMarket $market;
73
+
74
+ /**
75
+ * The current integrated vendor accessing instance.
76
+ */
77
+ private ?IntegratedVendor $integratedVendor = null;
78
+
79
+ public function __construct(string $apiKey = null, string $apiSecret = null, bool $sandbox = false, $market = null)
80
+ {
81
+ if ($apiKey === null) {
82
+ $apiKey = config('services.lalamove.key');
83
+ }
84
+
85
+ if ($apiSecret === null) {
86
+ $apiSecret = config('services.lalamove.secret');
87
+ }
88
+
89
+ if ($market === null) {
90
+ // check company session first
91
+ $company = Auth::getCompany(['uuid', 'country']);
92
+
93
+ if ($company && is_string($company->country) && LalamoveMarket::codes()->contains(strtoupper($company->country))) {
94
+ $market = strtoupper($company->country);
95
+ } else {
96
+ $market = config('services.lalamove.market', 'SG');
97
+ }
98
+ }
99
+
100
+ $this->isSandbox = $sandbox;
101
+ $this->apiKey = $apiKey;
102
+ $this->apiSecret = $apiSecret;
103
+ $this->setMarket($market);
104
+
105
+ $this->client = new Client(
106
+ [
107
+ 'base_uri' => $this->buildRequestUrl(),
108
+ ]
109
+ );
110
+ }
111
+
112
+ public static function instance(string $apiKey = null, string $apiSecret = null, bool $sandbox = false, $market = null): Lalamove
113
+ {
114
+ return new static($apiKey, $apiSecret, $market, $sandbox);
115
+ }
116
+
117
+ public static function __callStatic($name, $arguments)
118
+ {
119
+ if ($name === 'instance') {
120
+ return static::instance(...$arguments);
121
+ }
122
+
123
+ $sandbox = false;
124
+
125
+ if (Str::contains($name, 'FromSandbox')) {
126
+ $name = lcfirst(Str::replaceLast('FromSandbox', '', $name));
127
+ $sandbox = true;
128
+ } else {
129
+ $name = Str::replaceFirst('fromHost', '', $name);
130
+ }
131
+
132
+ $instance = static::instance(null, null, $sandbox, null);
133
+
134
+ if (method_exists($instance, $name)) {
135
+ return $instance->{$name}(...$arguments);
136
+ }
137
+
138
+ return null;
139
+ }
140
+
141
+ public static function asCents($number)
142
+ {
143
+ return Utils::numbersOnly((string) $number * 100);
144
+ }
145
+
146
+ public function setRequestId(?string $requestId): Lalamove
147
+ {
148
+ $this->requestId = $requestId;
149
+
150
+ return $this;
151
+ }
152
+
153
+ public function setOptions(?array $options = []): Lalamove
154
+ {
155
+ $this->options = array_merge($this->options, $options);
156
+
157
+ return $this;
158
+ }
159
+
160
+ public function getOptions(): array
161
+ {
162
+ return $this->options;
163
+ }
164
+
165
+ public function setIntegratedVendor(IntegratedVendor $integratedVendor): Lalamove
166
+ {
167
+ $this->integratedVendor = $integratedVendor;
168
+
169
+ return $this;
170
+ }
171
+
172
+ public static function createServiceQuoteFromQuotation($quotation, $requestId = null, $integratedVendor = null, Payload $payload = null): ServiceQuote
173
+ {
174
+ $serviceQuote = static::serviceQuoteFromQuotation($quotation, $requestId, $integratedVendor, $payload);
175
+ $serviceQuote->save();
176
+
177
+ foreach ($serviceQuote->items as $serviceQuoteItem) {
178
+ $serviceQuoteItem->service_quote_uuid = $serviceQuote->uuid;
179
+ $serviceQuoteItem->save();
180
+ }
181
+
182
+ return $serviceQuote->load(['items']);
183
+ }
184
+
185
+ public static function serviceQuoteFromQuotation($quotation = null, $requestId = null, $integratedVendor = null, Payload $payload = null): ServiceQuote
186
+ {
187
+ if (!$quotation) {
188
+ return null;
189
+ }
190
+
191
+ if (isset($quotation->data)) {
192
+ return static::serviceQuoteFromQuotation($quotation->data, $requestId, $integratedVendor, $payload);
193
+ }
194
+
195
+ $id = ServiceQuote::generateUuid();
196
+ $currency = $quotation->priceBreakdown->currency;
197
+
198
+ $serviceQuote = new ServiceQuote(
199
+ [
200
+ 'uuid' => $id,
201
+ 'request_id' => $requestId,
202
+ 'company_uuid' => session('company'),
203
+ 'payload_uuid' => $payload instanceof Payload ? $payload->uuid : null,
204
+ 'amount' => static::asCents($quotation->priceBreakdown->total),
205
+ 'currency' => $currency,
206
+ 'meta' => [
207
+ 'provider' => 'lalamove',
208
+ 'data' => $quotation,
209
+ ],
210
+ ]
211
+ );
212
+
213
+ // set integrated vendor to meta if applicable
214
+ if ($integratedVendor instanceof IntegratedVendor) {
215
+ $serviceQuote->integrated_vendor_uuid = $integratedVendor->uuid;
216
+ $serviceQuote->setMeta('from_integrated_vendor', $integratedVendor->public_id);
217
+ }
218
+
219
+ // create service quote items
220
+ $serviceQuoteItemKeys = ['base', 'extraMileage', 'vat'];
221
+ $items = [];
222
+
223
+ foreach ($serviceQuoteItemKeys as $itemKey) {
224
+ if (empty($quotation->priceBreakdown->{$itemKey})) {
225
+ continue;
226
+ }
227
+
228
+ $items[] = new ServiceQuoteItem(
229
+ [
230
+ 'service_quote_uuid' => $id,
231
+ 'amount' => static::asCents($quotation->priceBreakdown->{$itemKey}),
232
+ 'currency' => $currency,
233
+ 'details' => Utils::humanize($itemKey) . ' fee',
234
+ 'code' => strtoupper(Str::snake($itemKey . 'Fee')),
235
+ ]
236
+ );
237
+ }
238
+
239
+ $serviceQuote->setRelation('items', $items);
240
+
241
+ return $serviceQuote;
242
+ }
243
+
244
+ public static function getServiceType($key): ?LalamoveServiceType
245
+ {
246
+ if ($key instanceof LalamoveServiceType) {
247
+ return $key;
248
+ }
249
+
250
+ return LalamoveServiceType::find($key);
251
+ }
252
+
253
+ public static function getMarket($key): ?LalamoveMarket
254
+ {
255
+ if ($key instanceof LalamoveMarket) {
256
+ return $key;
257
+ }
258
+
259
+ return LalamoveMarket::find($key);
260
+ }
261
+
262
+ public function setMarket($market)
263
+ {
264
+ if ($market instanceof LalamoveMarket) {
265
+ $this->market = $market;
266
+ }
267
+
268
+ if (is_string($market)) {
269
+ $this->market = LalamoveMarket::find($market);
270
+ }
271
+
272
+ return $this;
273
+ }
274
+
275
+ private static function sign($timestamp, string $apiSecret, string $requestMethod, string $requestPath, string $requestBody)
276
+ {
277
+ $requestMethod = strtoupper($requestMethod);
278
+ $rawSignature = "$timestamp\r\n$requestMethod\r\n$requestPath\r\n\r\n$requestBody";
279
+ $signature = hash_hmac('sha256', $rawSignature, $apiSecret);
280
+
281
+ return $signature;
282
+ }
283
+
284
+ private function createSignature($timestamp, string $requestMethod, string $requestPath, string $requestBody)
285
+ {
286
+ $requestPath = '/' . $this->namespace . '/' . $requestPath;
287
+ $apiSecret = $this->apiSecret;
288
+
289
+ return static::sign($timestamp, $apiSecret, $requestMethod, $requestPath, $requestBody);
290
+ }
291
+
292
+ private function getAuthorizationKey(string $method, string $path, string $body)
293
+ {
294
+ $key = $this->apiKey;
295
+ $timestamp = floor(microtime(true) * 1000);
296
+ $signature = $this->createSignature($timestamp, $method, $path, $body);
297
+
298
+ return "$key:$timestamp:$signature";
299
+ }
300
+
301
+ private function throwError($errors = [], $triggerMethod = null)
302
+ {
303
+ $firstError = Arr::first($errors);
304
+
305
+ $errorMessage = 'Lalamove: ';
306
+
307
+ if (isset($firstError->id)) {
308
+ $errorMessage .= $firstError->id . ' ';
309
+ }
310
+
311
+ if (isset($firstError->message)) {
312
+ $errorMessage .= $firstError->message;
313
+ }
314
+
315
+ if (isset($firstError->detail)) {
316
+ $errorMessage .= ' (' . $firstError->detail . ')';
317
+ }
318
+
319
+ throw new IntegratedVendorException($errorMessage, $this->integratedVendor, $triggerMethod);
320
+ }
321
+
322
+ private function buildRequestUrl(string $path = ''): string
323
+ {
324
+ $host = $this->isSandbox ? $this->sandboxHost : $this->host;
325
+ $url = trim($host . $this->namespace . '/' . $path);
326
+
327
+ return $url;
328
+ }
329
+
330
+ private function request(string $method, string $path, array $options = [])
331
+ {
332
+ $options['headers'] = [
333
+ 'Content-Type' => 'application/json',
334
+ 'Authorization' => 'hmac ' . $this->getAuthorizationKey($method, $path, isset($options['json']) ? json_encode($options['json']) : ''),
335
+ 'Market' => $this->market->getCode(),
336
+ 'Request-ID' => (string) Str::uuid(),
337
+ ];
338
+
339
+ $response = $this->client->request($method, $path, $options);
340
+ $body = $response->getBody();
341
+ $contents = $body->getContents();
342
+ $json = json_decode($contents);
343
+
344
+ return $json;
345
+ }
346
+
347
+ private function post(string $path, array $options = [])
348
+ {
349
+ $options = array_merge($options, [
350
+ 'http_errors' => false,
351
+ ]);
352
+
353
+ return $this->request('POST', $path, $options);
354
+ }
355
+
356
+ private function patch(string $path, array $options = [])
357
+ {
358
+ $options = array_merge($options, [
359
+ 'http_errors' => false,
360
+ ]);
361
+
362
+ return $this->request('PATCH', $path, $options);
363
+ }
364
+
365
+ private function delete(string $path, array $options = [])
366
+ {
367
+ $options = array_merge($options, [
368
+ 'http_errors' => false,
369
+ ]);
370
+
371
+ return $this->request('DELETE', $path, $options);
372
+ }
373
+
374
+ public function getQuotations($serviceType, $stops = [], $scheduleAt = null, array $specialRequests = [], $isRouteOptimized = true, $item = [], array $cashOnDelivery = [])
375
+ {
376
+ $serviceType = static::getServiceType($serviceType);
377
+ $stops = collect($stops)
378
+ ->mapInto(LalamoveDeliveryStop::class)->map(
379
+ function ($stop) {
380
+ return $stop->toArray();
381
+ }
382
+ )
383
+ ->values()
384
+ ->toArray();
385
+
386
+ $language = Arr::first($this->market->getLanguages());
387
+
388
+ $options = [
389
+ 'json' => [
390
+ 'data' => [
391
+ 'serviceType' => $serviceType->getKey(),
392
+ 'stops' => $stops,
393
+ 'language' => $language,
394
+ 'isRouteOptimized' => $isRouteOptimized,
395
+ 'specialRequests' => $specialRequests,
396
+ ],
397
+ ],
398
+ ];
399
+
400
+ if (!empty($item)) {
401
+ $options['json']['data']['item'] = $item;
402
+ }
403
+
404
+ if (!empty($specialRequests)) {
405
+ $options['json']['data']['specialRequests'] = $specialRequests;
406
+ }
407
+
408
+ if (!empty($cashOnDelivery)) {
409
+ $options['json']['data']['cashOnDelivery'] = $cashOnDelivery;
410
+ }
411
+
412
+ if ($scheduleAt) {
413
+ $scheduleAt = Carbon::parse($scheduleAt);
414
+
415
+ if ($scheduleAt->isValid()) {
416
+ $options['json']['data']['scheduleAt'] = $scheduleAt->toISOString();
417
+ }
418
+ }
419
+
420
+ return $this->post('quotations', $options);
421
+ }
422
+
423
+ public function getQuoteFromPayload(Payload $payload, $serviceType = null, $scheduledAt = null, $isRouteOptimized = true, ?array $specialRequests = []): ServiceQuote
424
+ {
425
+ $market = $payload->getCountryCode();
426
+ $stops = $payload->getAllStops()->toArray();
427
+ $serviceType = $serviceType ?? 'MOTORCYCLE';
428
+
429
+ $response = $this->setMarket($market)->getQuotations($serviceType, $stops, $scheduledAt, $specialRequests, $isRouteOptimized);
430
+
431
+ if (isset($response->errors)) {
432
+ return $this->throwError($response->errors, __FUNCTION__);
433
+ }
434
+
435
+ return static::createServiceQuoteFromQuotation($response, $this->requestId, $this->integratedVendor, $payload);
436
+ }
437
+
438
+ public function getQuoteFromPreliminaryPayload($stops, $entities, $serviceType, $scheduledAt, $isRouteOptimized = true, ?array $specialRequests = []): ServiceQuote
439
+ {
440
+ $firstStop = Arr::first($stops);
441
+ $lastStop = Arr::last($stops);
442
+ $market = $firstStop->country ?? $lastStop->country ?? data_get(request()->user(), 'company.country');
443
+ $serviceType = $serviceType ?? 'MOTORCYCLE';
444
+
445
+ $response = $this->setMarket($market)->getQuotations($serviceType, $stops, $scheduledAt, $specialRequests, $isRouteOptimized);
446
+
447
+ if (isset($response->errors)) {
448
+ return $this->throwError($response->errors, __FUNCTION__);
449
+ }
450
+
451
+ return static::createServiceQuoteFromQuotation($response, $this->requestId, $this->integratedVendor);
452
+ }
453
+
454
+ public static function getQuotationForMarket($market, ...$params)
455
+ {
456
+ $instance = static::instance(null, null, $market);
457
+
458
+ return $instance->getQuotations(...$params);
459
+ }
460
+
461
+ public function cancelOrder(string $orderId)
462
+ {
463
+ $response = $this->delete('orders/' . $orderId);
464
+
465
+ if (isset($response->errors)) {
466
+ $this->throwError($response->errors, __FUNCTION__);
467
+ }
468
+
469
+ return $response;
470
+ }
471
+
472
+ public function cancelFromFleetbaseOrder(Order $order)
473
+ {
474
+ $orderId = $order->getMeta('integrated_vendor_order.orderId');
475
+
476
+ return $this->cancelOrder($orderId);
477
+ }
478
+
479
+ public function createOrder(string $quotationId, $sender = [], $recipients = [], $isRecipientSMSEnabled = false, $isPODEnabled = false, array $metadata = [])
480
+ {
481
+ if ($sender instanceof Contact) {
482
+ $sender = [
483
+ 'name' => $sender->name,
484
+ 'phone' => $sender->phone,
485
+ ];
486
+ }
487
+
488
+ $options = [
489
+ 'json' => [
490
+ 'data' => [
491
+ 'quotationId' => $quotationId,
492
+ 'sender' => $sender,
493
+ 'recipients' => $recipients,
494
+ 'isRecipientSMSEnabled' => $isRecipientSMSEnabled,
495
+ 'isPODEnabled' => $isPODEnabled,
496
+ 'metadata' => $metadata,
497
+ ],
498
+ ],
499
+ ];
500
+
501
+ $response = $this->post('orders', $options);
502
+
503
+ if (isset($response->errors)) {
504
+ return $this->throwError($response->errors, __FUNCTION__);
505
+ }
506
+
507
+ if (isset($response->data)) {
508
+ return $response->data;
509
+ }
510
+
511
+ return $response;
512
+ }
513
+
514
+ public function createOrderFromServiceQuote(ServiceQuote $serviceQuote, Request $request)
515
+ {
516
+ // get quotation id from service quote
517
+ $quotationId = $serviceQuote->getMeta('data.quotationId');
518
+ $stops = $serviceQuote->getMeta('data.stops');
519
+ $companyPhone = ParsePhone::fromCompany($serviceQuote->company);
520
+
521
+ // hack use test phone phone
522
+ if (empty($companyPhone)) {
523
+ $companyPhone = '+18004444444';
524
+ }
525
+
526
+ // create sender from request
527
+ // sender will always be the org
528
+ $sender = [
529
+ 'stopId' => data_get(Arr::first($stops), 'stopId'),
530
+ 'name' => $serviceQuote->company->name,
531
+ 'phone' => $companyPhone,
532
+ ];
533
+
534
+ $pickup = null;
535
+ $dropoff = null;
536
+ $waypoints = [];
537
+ $phoneOptions = [];
538
+
539
+ // recipient will be the customer if applicable
540
+ // if no customer, then use the destination dropoff values
541
+ // if no dropoff create multiple recipients from waypoint data
542
+ if ($request->hasAny(['order.payload', 'payload', 'pickup', 'waypoints'])) {
543
+ $pickup = $request->or(['order.payload.pickup', 'payload.pickup', 'pickup']);
544
+ $dropoff = $request->or(['order.payload.dropoff', 'payload.dropoff', 'dropoff']);
545
+ $waypoints = $request->or(['order.payload.waypoints', 'payload.waypoints', 'waypoints']);
546
+ }
547
+
548
+ // If service quote is created from preliminary data
549
+ // use preliminary data to fill route variables
550
+ if ($serviceQuote->hasMeta('preliminary_data')) {
551
+ $preliminaryData = $serviceQuote->getMeta('preliminary_data');
552
+ $pickup = data_get($preliminaryData, 'pickup');
553
+ $dropoff = data_get($preliminaryData, 'dropoff');
554
+ $waypoints = data_get($preliminaryData, 'waypoints', []);
555
+ }
556
+
557
+ // create phone lookup options from service quote
558
+ if ($serviceQuote instanceof ServiceQuote) {
559
+ $phoneOptions['currency'] = $serviceQuote->currency;
560
+ }
561
+
562
+ // Check if ServiceQuote has an origin and destination
563
+ // If from network cart origin will be an array of storeLocations[]
564
+ if ($serviceQuote->hasMeta('origin') && $serviceQuote->hasMeta('destination')) {
565
+ $origin = $serviceQuote->getMeta('origin');
566
+ $destination = $serviceQuote->getMeta('destination');
567
+
568
+ if (is_array($origin)) {
569
+ $waypoints = $origin;
570
+ } else {
571
+ $pickup = $origin;
572
+ }
573
+
574
+ $dropoff = $destination;
575
+ }
576
+
577
+ // If service quote is created with payload, then use payload to
578
+ // fill route variables
579
+ if ($serviceQuote->payload instanceof Payload) {
580
+ $pickup = $serviceQuote->payload->pickup;
581
+ $dropoff = $serviceQuote->payload->dropoff;
582
+ $waypoints = $serviceQuote->payload->waypoints;
583
+ }
584
+
585
+ // track all markets
586
+ $allWaypoints = collect([$pickup, ...$waypoints, $dropoff])
587
+ ->filter()
588
+ ->map(
589
+ function ($waypoint) {
590
+ if (isset($waypoint['place'])) {
591
+ return Place::createFromMixed($waypoint['place']);
592
+ }
593
+
594
+ return Place::createFromMixed($waypoint);
595
+ }
596
+ )
597
+ ->values();
598
+
599
+ // get first waypoin as sender
600
+ $senderWaypoint = $allWaypoints->first();
601
+
602
+ // update sender phone number
603
+ $senderName = $senderWaypoint instanceof Place ? Utils::or($senderWaypoint, ['name', 'street1']) : null;
604
+ $sender['name'] = $senderName ?? $sender['name'];
605
+ $senderPhone = $senderWaypoint instanceof Place ? ParsePhone::fromPlace($senderWaypoint, $phoneOptions) : null;
606
+ $sender['phone'] = $senderPhone ?? $sender['phone'];
607
+
608
+ // get market from integrated vendor option, otherwise fallback to waypoint
609
+ if ($serviceQuote->integratedVendor instanceof IntegratedVendor) {
610
+ $market = $serviceQuote->integratedVendor->getOption('market');
611
+ }
612
+
613
+ if (!$market) {
614
+ $market = $allWaypoints->pluck('country')->filter()->first();
615
+ }
616
+
617
+ // set market
618
+ $this->setMarket($market);
619
+
620
+ $recipients = $allWaypoints
621
+ ->filter(
622
+ function ($waypoint, $index) {
623
+ return $index > 0;
624
+ }
625
+ )
626
+ ->map(
627
+ function ($waypoint, $index) use ($stops, $companyPhone, $phoneOptions) {
628
+ return [
629
+ 'stopId' => data_get($stops[$index], 'stopId'),
630
+ 'name' => Utils::or($waypoint, ['name', 'street1']),
631
+ 'phone' => ParsePhone::fromPlace($waypoint, $phoneOptions) ?? $companyPhone,
632
+ 'remarks' => $waypoint->remarks ?? '',
633
+ ];
634
+ }
635
+ )
636
+ ->values()
637
+ ->toArray();
638
+
639
+ // check order for POD enabled
640
+ $isPODEnabled = $request->boolean('order.pod_required');
641
+
642
+ // set metadata from the service quote
643
+ // metadata[] should inclue 'company public id', 'service quote public id'
644
+ $metadata = [
645
+ 'company' => $serviceQuote->company->public_id,
646
+ 'service_quote' => $serviceQuote->public_id,
647
+ 'integrated_vendor' => data_get($this->integratedVendor, 'public_id'),
648
+ 'platform' => 'fleetbase',
649
+ ];
650
+
651
+ return $this->createOrder($quotationId, $sender, $recipients, false, $isPODEnabled, $metadata);
652
+ }
653
+
654
+ public function setWebhook(string $webhookUrl = null)
655
+ {
656
+ if (!is_string($webhookUrl)) {
657
+ return;
658
+ }
659
+
660
+ $options['json'] = [
661
+ 'data' => [
662
+ 'url' => $webhookUrl,
663
+ ],
664
+ ];
665
+
666
+ $response = $this->patch('webhook', $options);
667
+
668
+ if (isset($response->errors)) {
669
+ return $this->throwError($response->errors, __FUNCTION__);
670
+ }
671
+
672
+ if (isset($response->data)) {
673
+ return $response->data;
674
+ }
675
+
676
+ return $response;
677
+ }
678
+ }