@fleetbase/fleetops-engine 0.6.71 → 0.6.72

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 (378) hide show
  1. package/RELEASE.md +15 -18
  2. package/addon/components/admin/tracking-page-settings.hbs +56 -0
  3. package/addon/components/admin/tracking-page-settings.js +67 -0
  4. package/addon/components/device/form.hbs +2 -2
  5. package/addon/components/driver/details.hbs +1 -1
  6. package/addon/components/driver/form.hbs +1 -1
  7. package/addon/components/equipment/form.hbs +1 -1
  8. package/addon/components/layout/fleet-ops-sidebar.js +11 -3
  9. package/addon/components/maintenance/form.hbs +3 -3
  10. package/addon/components/map/google-live-map.js +2 -2
  11. package/addon/components/map/leaflet-live-map.js +45 -32
  12. package/addon/components/orchestrator/phase-builder.js +2 -1
  13. package/addon/components/orchestrator-workbench.hbs +7 -1
  14. package/addon/components/orchestrator-workbench.js +16 -2
  15. package/addon/components/order/form/route.hbs +1 -1
  16. package/addon/components/order/form/route.js +13 -1
  17. package/addon/components/service-rate/details.hbs +1 -1
  18. package/addon/components/service-rate/form.hbs +1 -1
  19. package/addon/components/tracking-page/full-view.hbs +276 -0
  20. package/addon/components/tracking-page/full-view.js +474 -0
  21. package/addon/components/tracking-page/locale-selector.js +30 -0
  22. package/addon/components/tracking-page/map.hbs +44 -0
  23. package/addon/components/tracking-page/map.js +328 -0
  24. package/addon/components/tracking-page/order-list.hbs +35 -0
  25. package/addon/components/tracking-page/public-view.hbs +60 -0
  26. package/addon/components/tracking-page/settings-preview.hbs +21 -0
  27. package/addon/components/tracking-page/settings-preview.js +23 -0
  28. package/addon/components/tracking-page/verify-panel.hbs +109 -0
  29. package/addon/components/tracking-page.hbs +142 -0
  30. package/addon/components/tracking-page.js +564 -0
  31. package/addon/components/trailer/form.hbs +2 -2
  32. package/addon/components/vehicle/form.hbs +3 -3
  33. package/addon/components/warranty/form.hbs +2 -2
  34. package/addon/components/widget/live-fleet.js +54 -6
  35. package/addon/components/widget/proof-of-delivery.hbs +49 -0
  36. package/addon/components/widget/proof-of-delivery.js +62 -0
  37. package/addon/components/work-order/form.hbs +3 -3
  38. package/addon/controllers/operations/orders/index/details.js +19 -3
  39. package/addon/controllers/operations/scheduler/index.js +45 -14
  40. package/addon/controllers/settings/index.js +6 -0
  41. package/addon/controllers/settings/map.js +75 -0
  42. package/addon/controllers/settings/orchestrator.js +8 -6
  43. package/addon/controllers/settings/tracking-page.js +212 -0
  44. package/addon/extension.js +65 -1
  45. package/addon/helpers/parcel-box-image.js +16 -0
  46. package/addon/routes/operations/orders/index/new.js +5 -4
  47. package/addon/routes/operations/scheduler/index.js +1 -1
  48. package/addon/routes/settings/tracking-page.js +31 -0
  49. package/addon/routes.js +1 -0
  50. package/addon/services/location.js +69 -21
  51. package/addon/services/map-settings.js +28 -0
  52. package/addon/services/order-allocation.js +1 -1
  53. package/addon/styles/fleetops-engine.css +1391 -0
  54. package/addon/templates/settings/map.hbs +46 -0
  55. package/addon/templates/settings/tracking-page.hbs +318 -0
  56. package/addon/utils/identity-cell-resource.js +2 -56
  57. package/addon/utils/map-default-view.js +132 -0
  58. package/addon/utils/placeholder-images.js +4 -69
  59. package/addon/utils/resource-descriptors/assets.js +2 -57
  60. package/addon/utils/resource-descriptors/helpers.js +23 -122
  61. package/addon/utils/resource-descriptors/operations.js +2 -61
  62. package/addon/utils/resource-descriptors/people.js +3 -142
  63. package/addon/utils/resource-descriptors/shared.js +18 -0
  64. package/addon/utils/tracking-live-source.js +123 -0
  65. package/addon/utils/tracking-page-theme.js +123 -0
  66. package/app/components/admin/tracking-page-settings.js +1 -0
  67. package/app/components/tracking-page/full-view.js +1 -0
  68. package/app/components/tracking-page/locale-selector.js +1 -0
  69. package/app/components/tracking-page/map.js +1 -0
  70. package/app/components/tracking-page/order-list.js +1 -0
  71. package/app/components/tracking-page/public-view.js +1 -0
  72. package/app/components/tracking-page/settings-preview.js +1 -0
  73. package/app/components/tracking-page/verify-panel.js +1 -0
  74. package/app/components/tracking-page.js +1 -0
  75. package/app/components/widget/proof-of-delivery.js +1 -0
  76. package/app/controllers/settings/tracking-page.js +1 -0
  77. package/app/helpers/parcel-box-image.js +1 -0
  78. package/app/routes/settings/tracking-page.js +1 -0
  79. package/app/templates/settings/tracking-page.js +1 -0
  80. package/app/utils/map-default-view.js +1 -0
  81. package/app/utils/tracking-live-source.js +1 -0
  82. package/app/utils/tracking-page-theme.js +1 -0
  83. package/composer.json +2 -2
  84. package/extension.json +1 -1
  85. package/package.json +4 -4
  86. package/scripts/pest-bootstrap.php +4 -0
  87. package/server/config/fleetops.php +4 -0
  88. package/server/migrations/2026_10_08_000001_create_tracking_sessions_tables.php +51 -0
  89. package/server/migrations/2026_10_10_000001_add_trashed_index_to_device_events.php +40 -0
  90. package/server/migrations/2026_10_10_000002_add_trashed_index_to_positions.php +40 -0
  91. package/server/migrations/2026_10_12_000001_add_deleted_at_to_tracking_sessions_tables.php +32 -0
  92. package/server/resources/views/labels/default.php +2 -2
  93. package/server/resources/views/labels/entity-label.php +2 -2
  94. package/server/resources/views/labels/waypoint-label.php +2 -2
  95. package/server/src/Auth/Schemas/FleetOps.php +5 -0
  96. package/server/src/Console/Commands/ProcessOperationalAlerts.php +1 -0
  97. package/server/src/Console/Commands/PruneTelematicsData.php +101 -26
  98. package/server/src/Events/OrderChanged.php +257 -0
  99. package/server/src/Events/OrderDriverUnassigned.php +68 -0
  100. package/server/src/Exceptions/OrderEditLockedException.php +32 -0
  101. package/server/src/Expansions/CompanyExpansion.php +3 -2
  102. package/server/src/Expansions/UserExpansion.php +12 -10
  103. package/server/src/Http/Controllers/Api/v1/CustomerController.php +108 -18
  104. package/server/src/Http/Controllers/Api/v1/DriverController.php +95 -10
  105. package/server/src/Http/Controllers/Api/v1/EntityController.php +66 -0
  106. package/server/src/Http/Controllers/Api/v1/FleetController.php +10 -4
  107. package/server/src/Http/Controllers/Api/v1/OrderController.php +139 -36
  108. package/server/src/Http/Controllers/Api/v1/PayloadController.php +76 -8
  109. package/server/src/Http/Controllers/Api/v1/PlaceController.php +3 -3
  110. package/server/src/Http/Controllers/Api/v1/TrackingNumberController.php +6 -32
  111. package/server/src/Http/Controllers/Api/v1/VehicleController.php +5 -0
  112. package/server/src/Http/Controllers/Internal/v1/ContactController.php +3 -0
  113. package/server/src/Http/Controllers/Internal/v1/DriverController.php +10 -0
  114. package/server/src/Http/Controllers/Internal/v1/FleetController.php +16 -2
  115. package/server/src/Http/Controllers/Internal/v1/InspectionSubmissionController.php +13 -8
  116. package/server/src/Http/Controllers/Internal/v1/IssueController.php +2 -0
  117. package/server/src/Http/Controllers/Internal/v1/MaintenanceController.php +4 -2
  118. package/server/src/Http/Controllers/Internal/v1/OrchestrationController.php +93 -11
  119. package/server/src/Http/Controllers/Internal/v1/OrderController.php +84 -24
  120. package/server/src/Http/Controllers/Internal/v1/PositionController.php +22 -0
  121. package/server/src/Http/Controllers/Internal/v1/ProofController.php +55 -4
  122. package/server/src/Http/Controllers/Internal/v1/SettingController.php +303 -10
  123. package/server/src/Http/Controllers/Internal/v1/TrailerController.php +1 -0
  124. package/server/src/Http/Controllers/Internal/v1/VehicleController.php +1 -0
  125. package/server/src/Http/Controllers/Public/TrackingController.php +518 -0
  126. package/server/src/Http/Filter/ContactFilter.php +1 -1
  127. package/server/src/Http/Filter/InspectionFormFilter.php +23 -0
  128. package/server/src/Http/Filter/InspectionSubmissionFilter.php +23 -0
  129. package/server/src/Http/Filter/MaintenanceFilter.php +23 -0
  130. package/server/src/Http/Filter/OrderFilter.php +39 -4
  131. package/server/src/Http/Filter/ProofFilter.php +18 -0
  132. package/server/src/Http/Filter/RouteFilter.php +18 -0
  133. package/server/src/Http/Filter/TelematicFilter.php +23 -0
  134. package/server/src/Http/Filter/WarrantyFilter.php +23 -0
  135. package/server/src/Http/Requests/CancelOrderRequest.php +2 -1
  136. package/server/src/Http/Resources/v1/Concerns/ResolvesPublicRelationFields.php +14 -1
  137. package/server/src/Http/Resources/v1/Index/Customer.php +18 -0
  138. package/server/src/Http/Resources/v1/Index/Order.php +11 -2
  139. package/server/src/Http/Resources/v1/PublicOrderTracking.php +153 -0
  140. package/server/src/Http/Resources/v1/TrackingNumber.php +8 -34
  141. package/server/src/Http/Resources/v1/Zone.php +31 -23
  142. package/server/src/Jobs/FinalizeApiOrderCreation.php +3 -1
  143. package/server/src/Jobs/ProcessAllocationJob.php +16 -6
  144. package/server/src/Jobs/PublishTrackingUpdate.php +50 -0
  145. package/server/src/Listeners/HandleGeofenceEntered.php +31 -15
  146. package/server/src/Listeners/HandleOrderCanceled.php +9 -1
  147. package/server/src/Listeners/HandleUserRemovedFromCompany.php +2 -1
  148. package/server/src/Listeners/PublishTrackingUpdates.php +27 -0
  149. package/server/src/Mail/CustomerCredentialsMail.php +4 -2
  150. package/server/src/Models/AssetConnection.php +3 -0
  151. package/server/src/Models/Contact.php +3 -0
  152. package/server/src/Models/Device.php +28 -0
  153. package/server/src/Models/DeviceEvent.php +7 -0
  154. package/server/src/Models/Driver.php +20 -7
  155. package/server/src/Models/Entity.php +12 -4
  156. package/server/src/Models/Fleet.php +11 -32
  157. package/server/src/Models/FleetDriver.php +3 -0
  158. package/server/src/Models/FleetVehicle.php +3 -0
  159. package/server/src/Models/FuelReport.php +5 -13
  160. package/server/src/Models/Issue.php +4 -16
  161. package/server/src/Models/Order.php +200 -9
  162. package/server/src/Models/Payload.php +227 -35
  163. package/server/src/Models/Place.php +7 -1
  164. package/server/src/Models/ServiceArea.php +7 -0
  165. package/server/src/Models/ServiceRate.php +7 -17
  166. package/server/src/Models/TrackingNumber.php +101 -2
  167. package/server/src/Models/TrackingSession.php +33 -0
  168. package/server/src/Models/TrackingSessionGrant.php +22 -0
  169. package/server/src/Models/TrackingStatus.php +6 -0
  170. package/server/src/Models/Vehicle.php +21 -2
  171. package/server/src/Models/Vendor.php +7 -0
  172. package/server/src/Models/Waypoint.php +13 -4
  173. package/server/src/Notifications/OrderAssigned.php +2 -1
  174. package/server/src/Notifications/OrderCanceled.php +7 -1
  175. package/server/src/Notifications/OrderChanged.php +87 -0
  176. package/server/src/Notifications/OrderCompleted.php +2 -1
  177. package/server/src/Notifications/OrderDispatchFailed.php +2 -1
  178. package/server/src/Notifications/OrderDispatched.php +2 -1
  179. package/server/src/Notifications/OrderFailed.php +2 -1
  180. package/server/src/Notifications/OrderUnassigned.php +66 -0
  181. package/server/src/Notifications/WaypointCompleted.php +2 -1
  182. package/server/src/Observers/CompanyUserObserver.php +8 -7
  183. package/server/src/Observers/DriverObserver.php +6 -1
  184. package/server/src/Observers/OrderObserver.php +141 -1
  185. package/server/src/Observers/TrackingNumberObserver.php +18 -6
  186. package/server/src/Observers/UserObserver.php +2 -1
  187. package/server/src/Observers/VehicleObserver.php +8 -3
  188. package/server/src/Orchestration/Engines/RouteSequencingEngine.php +21 -3
  189. package/server/src/Orchestration/Engines/VroomOrchestrationEngine.php +38 -8
  190. package/server/src/Orchestration/OrchestrationEngineRegistry.php +61 -1
  191. package/server/src/Orchestration/Support/OrchestratorSettings.php +61 -0
  192. package/server/src/Orchestration/Support/RouteMetrics.php +165 -0
  193. package/server/src/Providers/EventServiceProvider.php +11 -0
  194. package/server/src/Providers/FleetOpsServiceProvider.php +13 -0
  195. package/server/src/Support/ApiCacheThrottle.php +76 -0
  196. package/server/src/Support/LiveOrderQuery.php +3 -1
  197. package/server/src/Support/OrderEdit.php +365 -0
  198. package/server/src/Support/OrderEditPolicy.php +292 -0
  199. package/server/src/Support/ProfileAccountManager.php +54 -1
  200. package/server/src/Support/ResolvesOrderServiceStops.php +5 -0
  201. package/server/src/Support/SocketChannels.php +346 -0
  202. package/server/src/Support/Telematics/TelematicService.php +7 -2
  203. package/server/src/Support/Telematics/Telemetry/Inbox.php +8 -1
  204. package/server/src/Support/TrackingChannel.php +55 -0
  205. package/server/src/Support/TrackingCode.php +242 -0
  206. package/server/src/Support/TrackingPage/TrackingAccess.php +356 -0
  207. package/server/src/Support/TrackingPage/TrackingPageConfig.php +264 -0
  208. package/server/src/Support/TrackingPage/TrackingRecipient.php +111 -0
  209. package/server/src/Support/TrackingPage/TrackingResolver.php +201 -0
  210. package/server/src/Support/TrackingPage/TrackingTarget.php +40 -0
  211. package/server/src/Support/TrackingPage/TrackingView.php +543 -0
  212. package/server/src/Support/TrackingPublisher.php +261 -0
  213. package/server/src/Support/TrackingScope.php +182 -0
  214. package/server/src/Support/TrackingUpdate.php +402 -0
  215. package/server/src/Support/Utils.php +15 -3
  216. package/server/src/Traits/HasTrackingNumber.php +2 -0
  217. package/server/src/routes.php +39 -7
  218. package/server/tests/ApiCustomerControllerContractsTest.php +54 -7
  219. package/server/tests/ApiDriverPasswordContractsTest.php +25 -21
  220. package/server/tests/ApiEntityControllerContractsTest.php +84 -0
  221. package/server/tests/ApiOrderControllerContractsTest.php +245 -0
  222. package/server/tests/ApiPayloadControllerContractsTest.php +121 -0
  223. package/server/tests/ApiPlaceControllerContractsTest.php +1 -1
  224. package/server/tests/ApiTrackingNumberControllerContractsTest.php +6 -9
  225. package/server/tests/CompactResourceSerializationTest.php +23 -59
  226. package/server/tests/ControllerFilterContractsTest.php +1 -1
  227. package/server/tests/CustomerContactIdentitySafetyTest.php +1 -1
  228. package/server/tests/EventContractsTest.php +26 -60
  229. package/server/tests/ExpansionContractsTest.php +15 -2
  230. package/server/tests/Feature/Http/Api/CustomerControllerHelperSeamsTest.php +29 -3
  231. package/server/tests/Feature/Http/Api/DriverControllerAuthFlowsTest.php +23 -0
  232. package/server/tests/Feature/Http/Api/OrderControllerNearbyFiltersTest.php +16 -16
  233. package/server/tests/Feature/Http/Api/OrderControllerQueryFiltersTest.php +41 -14
  234. package/server/tests/Feature/Http/Api/TrackingNumberControllerHelpersTest.php +57 -22
  235. package/server/tests/Feature/Http/Internal/DriverControllerCreateRecordTest.php +23 -9
  236. package/server/tests/Feature/Http/Internal/OrchestrationControllerContractsTest.php +171 -1
  237. package/server/tests/Feature/Http/Internal/OrderControllerContractsTest.php +110 -14
  238. package/server/tests/Feature/Http/Internal/OrderControllerHelpersTest.php +7 -5
  239. package/server/tests/Feature/Http/Internal/PositionControllerReplayChannelTest.php +135 -0
  240. package/server/tests/Feature/Http/Internal/ProofControllerContractsTest.php +3 -3
  241. package/server/tests/Feature/Http/Internal/ProofControllerRecentTest.php +170 -0
  242. package/server/tests/Feature/Http/Public/TrackingControllerTest.php +495 -0
  243. package/server/tests/IndexCustomerPhotoTest.php +151 -0
  244. package/server/tests/ModelAccessorContractsTest.php +4 -3
  245. package/server/tests/NotificationAndMailContractsTest.php +5 -8
  246. package/server/tests/ObserverContractsTest.php +72 -10
  247. package/server/tests/OrderActivityFlowRegressionTest.php +3 -2
  248. package/server/tests/OrderFilterExecutionTest.php +167 -2
  249. package/server/tests/ProcessAllocationJobContractsTest.php +20 -0
  250. package/server/tests/PublicOrderTrackingResourceTest.php +221 -0
  251. package/server/tests/QueueJobContractsTest.php +2 -1
  252. package/server/tests/RequestContractsTest.php +1 -1
  253. package/server/tests/RouteRegistrationExecutionTest.php +26 -0
  254. package/server/tests/RouteSequencingEngineTest.php +17 -0
  255. package/server/tests/SettingControllerContractsTest.php +110 -0
  256. package/server/tests/Support/TrackingPageDatabase.php +200 -0
  257. package/server/tests/TenantScopingTest.php +206 -0
  258. package/server/tests/TrackingPageSettingsTest.php +343 -0
  259. package/server/tests/Unit/Console/PruneTelematicsDataCommandTest.php +51 -0
  260. package/server/tests/Unit/Http/Filter/ContactFilterAddressTest.php +61 -0
  261. package/server/tests/Unit/Http/Resources/IndexOrderResourceTest.php +30 -0
  262. package/server/tests/Unit/Jobs/FinalizeApiOrderCreationDispatchGuardTest.php +266 -0
  263. package/server/tests/Unit/Listeners/HandleGeofenceEnteredTest.php +182 -22
  264. package/server/tests/Unit/Listeners/HandleUserRemovedFromCompanyTest.php +5 -0
  265. package/server/tests/Unit/Models/DriverAssignVehicleTest.php +81 -0
  266. package/server/tests/Unit/Models/FleetTest.php +4 -3
  267. package/server/tests/Unit/Models/OrderCancelReasonTest.php +143 -0
  268. package/server/tests/Unit/Models/OrderPayloadConfigAndDistanceTest.php +60 -0
  269. package/server/tests/Unit/Models/OrderPayloadRouteTest.php +4 -2
  270. package/server/tests/Unit/Models/PayloadTest.php +18 -4
  271. package/server/tests/Unit/Models/ServiceRatePersistenceAndServicabilityTest.php +2 -2
  272. package/server/tests/Unit/Models/TrackingNumberTest.php +67 -6
  273. package/server/tests/Unit/Models/VehicleTest.php +16 -2
  274. package/server/tests/Unit/Models/WaypointTest.php +4 -3
  275. package/server/tests/Unit/Notifications/OrderChangeNotificationsTest.php +59 -0
  276. package/server/tests/Unit/Notifications/TerminalOrderNotificationsTest.php +3 -3
  277. package/server/tests/Unit/Observers/DriverDeletionCleanupTest.php +158 -0
  278. package/server/tests/Unit/Observers/FleetOpsCompanyUserAndServiceAreaObserversTest.php +20 -0
  279. package/server/tests/Unit/Observers/ObserverListenerSeamsTest.php +3 -3
  280. package/server/tests/Unit/Observers/OrderAssignmentObserverTest.php +100 -0
  281. package/server/tests/Unit/Observers/OrderDeleteCascadeTest.php +213 -0
  282. package/server/tests/Unit/Observers/VehicleObserverDeleteTest.php +67 -0
  283. package/server/tests/Unit/Orchestration/EngineSelectionAndRouteMetricsTest.php +336 -0
  284. package/server/tests/Unit/Orchestration/Engines/VroomOrchestrationEngineLifecycleTest.php +8 -1
  285. package/server/tests/Unit/Support/ApiCacheDependenciesTest.php +347 -0
  286. package/server/tests/Unit/Support/OrderEditPolicyTest.php +156 -0
  287. package/server/tests/Unit/Support/OrderOperationsTest.php +514 -0
  288. package/server/tests/Unit/Support/OsrmProofAndIssueFilterTest.php +4 -3
  289. package/server/tests/Unit/Support/ProfileAccountManagerTest.php +141 -0
  290. package/server/tests/Unit/Support/QuerySeamsTest.php +5 -1
  291. package/server/tests/Unit/Support/SocketChannelsTest.php +396 -0
  292. package/server/tests/Unit/Support/TrackingChannelTest.php +232 -0
  293. package/server/tests/Unit/Support/TrackingCodeTest.php +186 -0
  294. package/server/tests/Unit/Support/TrackingPage/TrackingAccessTest.php +200 -0
  295. package/server/tests/Unit/Support/TrackingPage/TrackingRecipientTest.php +51 -0
  296. package/server/tests/Unit/Support/TrackingPage/TrackingResolverTest.php +181 -0
  297. package/server/tests/Unit/Support/TrackingPage/TrackingViewTest.php +479 -0
  298. package/server/tests/Unit/Support/TrackingPublisherTest.php +425 -0
  299. package/server/tests/Unit/Support/TrackingUpdateTest.php +363 -0
  300. package/server/tests/Unit/Support/UtilsAdditionalTest.php +9 -0
  301. package/server/tests/Unit/Support/UtilsGeoMatrixAndVendorTest.php +25 -0
  302. package/server/tests/VehicleResourceContractsTest.php +46 -0
  303. package/server/tests/VroomOrchestrationEngineTest.php +34 -1
  304. package/server/tests/ZoneGeofenceSettingsResourceTest.php +121 -0
  305. package/translations/ar-ae.yml +274 -0
  306. package/translations/bg-bg.yaml +274 -0
  307. package/translations/en-us.yaml +287 -0
  308. package/translations/es-pa.yaml +274 -0
  309. package/translations/fr-fr.yaml +274 -0
  310. package/translations/mn-mn.yaml +274 -0
  311. package/translations/pt-br.yaml +274 -0
  312. package/translations/ru-ru.yaml +276 -2
  313. package/translations/uk-ua.yaml +275 -1
  314. package/translations/vi-vn.yaml +274 -0
  315. package/addon/components/cell/contact-identity.hbs +0 -1
  316. package/addon/components/cell/customer-identity.hbs +0 -1
  317. package/addon/components/cell/driver-identity.hbs +0 -1
  318. package/addon/components/cell/fleet-identity.hbs +0 -1
  319. package/addon/components/cell/order-identity.hbs +0 -1
  320. package/addon/components/cell/place-identity.hbs +0 -1
  321. package/addon/components/cell/vehicle-identity.hbs +0 -1
  322. package/addon/components/cell/vendor-identity.hbs +0 -1
  323. package/addon/components/contact/pill.hbs +0 -24
  324. package/addon/components/contact/summary.hbs +0 -1
  325. package/addon/components/customer/pill.hbs +0 -24
  326. package/addon/components/customer/summary.hbs +0 -1
  327. package/addon/components/driver/pill.hbs +0 -24
  328. package/addon/components/driver/summary.hbs +0 -1
  329. package/addon/components/fleet/pill.hbs +0 -24
  330. package/addon/components/fleet/summary.hbs +0 -1
  331. package/addon/components/order/pill.hbs +0 -24
  332. package/addon/components/order/summary.hbs +0 -1
  333. package/addon/components/place/pill.hbs +0 -24
  334. package/addon/components/place/summary.hbs +0 -1
  335. package/addon/components/select-option/contact.hbs +0 -12
  336. package/addon/components/select-option/customer.hbs +0 -12
  337. package/addon/components/select-option/driver.hbs +0 -12
  338. package/addon/components/select-option/fleet.hbs +0 -12
  339. package/addon/components/select-option/order.hbs +0 -12
  340. package/addon/components/select-option/place.hbs +0 -12
  341. package/addon/components/select-option/vehicle.hbs +0 -12
  342. package/addon/components/select-option/vendor.hbs +0 -12
  343. package/addon/components/vehicle/pill.hbs +0 -24
  344. package/addon/components/vehicle/summary.hbs +0 -1
  345. package/addon/components/vendor/pill.hbs +0 -24
  346. package/addon/components/vendor/summary.hbs +0 -1
  347. package/app/components/cell/contact-identity.js +0 -1
  348. package/app/components/cell/customer-identity.js +0 -1
  349. package/app/components/cell/driver-identity.js +0 -1
  350. package/app/components/cell/fleet-identity.js +0 -1
  351. package/app/components/cell/order-identity.js +0 -1
  352. package/app/components/cell/place-identity.js +0 -1
  353. package/app/components/cell/vehicle-identity.js +0 -1
  354. package/app/components/cell/vendor-identity.js +0 -1
  355. package/app/components/contact/pill.js +0 -1
  356. package/app/components/contact/summary.js +0 -1
  357. package/app/components/customer/pill.js +0 -1
  358. package/app/components/customer/summary.js +0 -1
  359. package/app/components/driver/pill.js +0 -1
  360. package/app/components/driver/summary.js +0 -1
  361. package/app/components/fleet/pill.js +0 -1
  362. package/app/components/fleet/summary.js +0 -1
  363. package/app/components/order/pill.js +0 -1
  364. package/app/components/order/summary.js +0 -1
  365. package/app/components/place/pill.js +0 -1
  366. package/app/components/place/summary.js +0 -1
  367. package/app/components/select-option/contact.js +0 -1
  368. package/app/components/select-option/customer.js +0 -1
  369. package/app/components/select-option/driver.js +0 -1
  370. package/app/components/select-option/fleet.js +0 -1
  371. package/app/components/select-option/order.js +0 -1
  372. package/app/components/select-option/place.js +0 -1
  373. package/app/components/select-option/vehicle.js +0 -1
  374. package/app/components/select-option/vendor.js +0 -1
  375. package/app/components/vehicle/pill.js +0 -1
  376. package/app/components/vehicle/summary.js +0 -1
  377. package/app/components/vendor/pill.js +0 -1
  378. package/app/components/vendor/summary.js +0 -1
@@ -0,0 +1,18 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Http\Filter;
4
+
5
+ use Fleetbase\Http\Filter\Filter;
6
+
7
+ class ProofFilter extends Filter
8
+ {
9
+ public function queryForInternal()
10
+ {
11
+ $this->builder->where('company_uuid', $this->session->get('company'));
12
+ }
13
+
14
+ public function queryForPublic()
15
+ {
16
+ $this->queryForInternal();
17
+ }
18
+ }
@@ -0,0 +1,18 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Http\Filter;
4
+
5
+ use Fleetbase\Http\Filter\Filter;
6
+
7
+ class RouteFilter extends Filter
8
+ {
9
+ public function queryForInternal()
10
+ {
11
+ $this->builder->where('company_uuid', $this->session->get('company'));
12
+ }
13
+
14
+ public function queryForPublic()
15
+ {
16
+ $this->queryForInternal();
17
+ }
18
+ }
@@ -0,0 +1,23 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Http\Filter;
4
+
5
+ use Fleetbase\Http\Filter\Filter;
6
+
7
+ class TelematicFilter extends Filter
8
+ {
9
+ public function queryForInternal()
10
+ {
11
+ $this->builder->where('company_uuid', $this->session->get('company'));
12
+ }
13
+
14
+ public function queryForPublic()
15
+ {
16
+ $this->queryForInternal();
17
+ }
18
+
19
+ public function query(?string $searchQuery)
20
+ {
21
+ $this->builder->search($searchQuery);
22
+ }
23
+ }
@@ -0,0 +1,23 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Http\Filter;
4
+
5
+ use Fleetbase\Http\Filter\Filter;
6
+
7
+ class WarrantyFilter extends Filter
8
+ {
9
+ public function queryForInternal()
10
+ {
11
+ $this->builder->where('company_uuid', $this->session->get('company'));
12
+ }
13
+
14
+ public function queryForPublic()
15
+ {
16
+ $this->queryForInternal();
17
+ }
18
+
19
+ public function query(?string $searchQuery)
20
+ {
21
+ $this->builder->search($searchQuery);
22
+ }
23
+ }
@@ -20,7 +20,8 @@ class CancelOrderRequest extends FleetbaseRequest
20
20
  public function rules(): array
21
21
  {
22
22
  return [
23
- 'order' => 'required|exists:orders,uuid',
23
+ 'order' => 'required|exists:orders,uuid',
24
+ 'reason' => 'nullable|string|max:1000',
24
25
  ];
25
26
  }
26
27
  }
@@ -3,6 +3,8 @@
3
3
  namespace Fleetbase\FleetOps\Http\Resources\v1\Concerns;
4
4
 
5
5
  use Fleetbase\Support\Http;
6
+ use Fleetbase\Support\RequestRelations;
7
+ use Illuminate\Database\Eloquent\Model;
6
8
  use Illuminate\Http\Resources\MissingValue;
7
9
 
8
10
  /**
@@ -30,6 +32,13 @@ trait ResolvesPublicRelationFields
30
32
  * model actually defines are kept — a parent's expansion must never reach
31
33
  * this model's loader, where it raises RelationNotFoundException.
32
34
  *
35
+ * The result is handed to `loadMissing()`, and Eloquent loads a name by
36
+ * calling it as a method on a blank model, so a name that is merely a
37
+ * method (`with=saveInstance`) would run it. When core's RequestRelations
38
+ * is available an Eloquent model keeps only declared relations, each
39
+ * segment named as the model's method (`service_area` → `serviceArea`).
40
+ * Older core releases without it keep the root-method check below.
41
+ *
33
42
  * @return array<int, string>
34
43
  */
35
44
  protected function requestedRelations($request): array
@@ -46,6 +55,10 @@ trait ResolvesPublicRelationFields
46
55
 
47
56
  $with = array_values(array_filter(array_map('strval', $with), 'strlen'));
48
57
 
58
+ if ($this->resource instanceof Model && class_exists(RequestRelations::class)) {
59
+ return RequestRelations::eagerLoads($this->resource, $with);
60
+ }
61
+
49
62
  return array_values(array_filter($with, fn (string $relation): bool => $this->definesRelation($relation)));
50
63
  }
51
64
 
@@ -77,7 +90,7 @@ trait ResolvesPublicRelationFields
77
90
  * loaded on the public endpoints, so the key was absent unless `with` named
78
91
  * it. Absent stays absent; it never becomes a string.
79
92
  *
80
- * @param array<int, string> $with camelCased relations the caller asked for
93
+ * @param array<int, string> $with the relation paths requestedRelations() kept, named as the model's methods
81
94
  */
82
95
  protected function publicRelationObject(string $relation, array $with, \Closure $resource): mixed
83
96
  {
@@ -2,8 +2,12 @@
2
2
 
3
3
  namespace Fleetbase\FleetOps\Http\Resources\v1\Index;
4
4
 
5
+ use Fleetbase\FleetOps\Models\Contact;
6
+ use Fleetbase\FleetOps\Models\Customer as CustomerModel;
7
+ use Fleetbase\FleetOps\Models\Vendor;
5
8
  use Fleetbase\Http\Resources\FleetbaseResource;
6
9
  use Fleetbase\Support\Http;
10
+ use Illuminate\Database\Eloquent\Relations\MorphTo;
7
11
 
8
12
  /**
9
13
  * Lightweight Customer resource for index views.
@@ -28,6 +32,20 @@ class Customer extends FleetbaseResource
28
32
  'name' => $this->name,
29
33
  'phone' => $this->phone ?? null,
30
34
  'email' => $this->email ?? null,
35
+ 'photo_url' => $this->resource instanceof Vendor ? $this->logo_url : ($this->photo_url ?? null),
31
36
  ];
32
37
  }
38
+
39
+ /**
40
+ * Eager loads the file each customer type's `photo_url` reads (a contact's
41
+ * photo, a vendor's logo), so listing orders does not query once per row.
42
+ */
43
+ public static function withPhoto(MorphTo $relation): MorphTo
44
+ {
45
+ return $relation->morphWith([
46
+ Contact::class => ['photo'],
47
+ CustomerModel::class => ['photo'],
48
+ Vendor::class => ['logo'],
49
+ ]);
50
+ }
33
51
  }
@@ -94,12 +94,12 @@ class Order extends FleetbaseResource
94
94
 
95
95
  // Latest status only, not full array
96
96
  'latest_status' => $this->whenLoaded('trackingStatuses', function () {
97
- $latest = $this->trackingStatuses->first();
97
+ $latest = $this->latestTrackingStatus();
98
98
 
99
99
  return $latest ? $latest->status : 'created';
100
100
  }),
101
101
  'latest_status_code' => $this->whenLoaded('trackingStatuses', function () {
102
- $latest = $this->trackingStatuses->first();
102
+ $latest = $this->latestTrackingStatus();
103
103
 
104
104
  return $latest ? $latest->code : null;
105
105
  }),
@@ -127,4 +127,13 @@ class Order extends FleetbaseResource
127
127
  ],
128
128
  ];
129
129
  }
130
+
131
+ /**
132
+ * The newest loaded tracking status. The relation has no order, so the
133
+ * statuses are sorted here, newest insert first within the same second.
134
+ */
135
+ protected function latestTrackingStatus(): mixed
136
+ {
137
+ return $this->trackingStatuses->sortBy([['created_at', 'desc'], ['id', 'desc']])->first();
138
+ }
130
139
  }
@@ -0,0 +1,153 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Http\Resources\v1;
4
+
5
+ use Fleetbase\FleetOps\Models\Order;
6
+ use Fleetbase\FleetOps\Support\Utils;
7
+ use Illuminate\Http\Resources\Json\JsonResource;
8
+
9
+ /**
10
+ * What the public Track Order page gets for a tracking number.
11
+ *
12
+ * The lookup has no session, so whoever holds the tracking number sees this.
13
+ * It carries only what `order-tracking-lookup` renders: status, the tracking
14
+ * timeline, ETA and progress, the stop coordinates the map routes between,
15
+ * and the item list. Notes, meta, internal ids, files, rates, and customer
16
+ * and facilitator details stay out. The driver's position is included only
17
+ * while the order is under way.
18
+ *
19
+ * It extends `JsonResource`, not `FleetbaseResource`, so transformers that
20
+ * other extensions register for resources cannot add fields to it. Records are
21
+ * keyed by public id, which Ember Data needs to build them, so the page never
22
+ * learns an internal uuid.
23
+ */
24
+ class PublicOrderTracking extends JsonResource
25
+ {
26
+ /**
27
+ * Never wrapped, whatever another resource set the shared wrapper to.
28
+ *
29
+ * @var string|null
30
+ */
31
+ public static $wrap;
32
+
33
+ /**
34
+ * Statuses after which the order is no longer under way.
35
+ */
36
+ public const FINISHED_STATUSES = ['completed', 'canceled', 'cancelled'];
37
+
38
+ /**
39
+ * Transform the resource into an array.
40
+ *
41
+ * @param \Illuminate\Http\Request $request
42
+ */
43
+ public function toArray($request): array
44
+ {
45
+ /** @var Order $order */
46
+ $order = $this->resource;
47
+ $trackingNumber = $order->trackingNumber;
48
+ $tracker = is_array($order->tracker_data) ? $order->tracker_data : [];
49
+
50
+ return [
51
+ 'uuid' => $order->public_id,
52
+ 'tracking' => data_get($trackingNumber, 'tracking_number'),
53
+ 'status' => $order->status,
54
+ 'has_driver_assigned' => (bool) $order->has_driver_assigned,
55
+ 'tracking_number' => $trackingNumber ? [
56
+ 'uuid' => $trackingNumber->public_id,
57
+ 'tracking_number' => $trackingNumber->tracking_number,
58
+ ] : null,
59
+ 'tracking_statuses' => collect($order->trackingStatuses)->map(fn ($status) => [
60
+ 'uuid' => $status->public_id,
61
+ 'status' => $status->status,
62
+ 'details' => $status->details,
63
+ 'created_at' => $status->created_at,
64
+ ])->values()->all(),
65
+ 'payload' => $this->payload($order->payload),
66
+ 'tracker_data' => $this->trackerData($tracker, static::isInProgress($order)),
67
+ 'created_at' => $order->created_at,
68
+ ];
69
+ }
70
+
71
+ /**
72
+ * Whether the order is under way: started, and not yet completed or canceled.
73
+ */
74
+ public static function isInProgress(Order $order): bool
75
+ {
76
+ return (bool) $order->started && !in_array(strtolower((string) $order->status), static::FINISHED_STATUSES, true);
77
+ }
78
+
79
+ /**
80
+ * The stops the map routes between and the items the page lists.
81
+ */
82
+ protected function payload($payload): ?array
83
+ {
84
+ if (!$payload) {
85
+ return null;
86
+ }
87
+
88
+ return [
89
+ 'uuid' => $payload->public_id,
90
+ 'pickup' => $this->place($payload->pickup),
91
+ 'dropoff' => $this->place($payload->dropoff),
92
+ 'waypoints' => collect($payload->waypoints)->map(fn ($place) => $this->place($place))->values()->all(),
93
+ 'entities' => collect($payload->entities)->map(fn ($entity) => [
94
+ 'uuid' => $entity->public_id,
95
+ 'name' => $entity->name,
96
+ 'description' => $entity->description,
97
+ 'tracking' => data_get($entity, 'tracking'),
98
+ 'price' => $entity->price,
99
+ 'currency' => $entity->currency,
100
+ 'photo_url' => data_get($entity, 'photo_url'),
101
+ ])->values()->all(),
102
+ ];
103
+ }
104
+
105
+ /**
106
+ * A stop as the map needs it: its coordinates, with no address or contact.
107
+ */
108
+ protected function place($place): ?array
109
+ {
110
+ if (!$place) {
111
+ return null;
112
+ }
113
+
114
+ return [
115
+ 'uuid' => $place->public_id,
116
+ 'location' => Utils::castPoint($place->location),
117
+ ];
118
+ }
119
+
120
+ /**
121
+ * The tracker fields the page reads; the driver's position only while under way.
122
+ */
123
+ protected function trackerData(array $tracker, bool $inProgress): array
124
+ {
125
+ return [
126
+ 'driver' => [
127
+ 'location' => $inProgress ? data_get($tracker, 'driver.location') : null,
128
+ ],
129
+ 'progress' => [
130
+ 'percentage' => data_get($tracker, 'progress.percentage'),
131
+ 'completed_stops' => data_get($tracker, 'progress.completed_stops'),
132
+ ],
133
+ 'eta' => [
134
+ 'active_stop_seconds' => data_get($tracker, 'eta.active_stop_seconds'),
135
+ 'completion_at' => data_get($tracker, 'eta.completion_at'),
136
+ ],
137
+ 'active_stop' => $this->stop(data_get($tracker, 'active_stop')),
138
+ 'next_stop' => $this->stop(data_get($tracker, 'next_stop')),
139
+ ];
140
+ }
141
+
142
+ /**
143
+ * A stop the page names under "Current/Next Destination".
144
+ */
145
+ protected function stop($stop): ?array
146
+ {
147
+ if (!is_array($stop)) {
148
+ return null;
149
+ }
150
+
151
+ return ['address' => data_get($stop, 'address')];
152
+ }
153
+ }
@@ -2,6 +2,7 @@
2
2
 
3
3
  namespace Fleetbase\FleetOps\Http\Resources\v1;
4
4
 
5
+ use Fleetbase\FleetOps\Support\TrackingCode;
5
6
  use Fleetbase\FleetOps\Support\Utils;
6
7
  use Fleetbase\Http\Resources\FleetbaseResource;
7
8
  use Fleetbase\Support\Http;
@@ -30,47 +31,20 @@ class TrackingNumber extends FleetbaseResource
30
31
  'status' => $this->last_status,
31
32
  'status_code' => $this->last_status_code,
32
33
  'qr_code' => $this->qr_code,
33
- // The raw text encoded inside qr_code, exposed ONLY in debug mode.
34
- //
35
- // qr_code is a base64 PNG generated from owner_uuid (TrackingNumber::newBarcode),
36
- // and the endpoints that consume a scanned code match on that uuid. A client
37
- // scans the image to obtain it; an automated contract run cannot, so debug
38
- // builds publish the value beside the image rather than the API growing a
39
- // decode endpoint or handing out uuids generally.
40
- //
41
- // `when()` omits the key entirely when false — it is absent, not null — so a
42
- // production response is byte-identical to before.
43
- 'qr_code_content' => $this->when(static::exposesQrCodeContent(), fn () => $this->owner_uuid),
34
+ // A value that scans as this tracking number: the QR content current labels
35
+ // print (see TrackingCode). It names the tracking number and the subject's
36
+ // public id, both already in this resource, so it is safe to publish, and lets
37
+ // clients that print their own labels, or cannot decode a PNG, use the code.
38
+ // Labels printed before it encode the owner uuid; resolvers accept both.
39
+ 'qr_code_content' => $this->when($this->tracking_number, fn () => TrackingCode::qrContent($this->tracking_number, Utils::get($this->owner, 'public_id'))),
44
40
  'barcode' => $this->barcode,
45
- 'url' => Utils::consoleUrl('track-order', ['order' => $this->tracking_number]),
41
+ 'url' => $this->when($this->tracking_number, fn () => TrackingCode::pageUrl($this->tracking_number, $this->company_uuid)),
46
42
  'type' => Utils::getTypeFromClassName($this->owner_type),
47
43
  'updated_at' => $this->updated_at,
48
44
  'created_at' => $this->created_at,
49
45
  ];
50
46
  }
51
47
 
52
- /**
53
- * Whether the QR code's decoded content may be published.
54
- *
55
- * Debug mode only, and fails closed: any failure to determine the debug state — no
56
- * container, an application without the accessor — answers false rather than
57
- * defaulting to exposure.
58
- */
59
- protected static function exposesQrCodeContent(): bool
60
- {
61
- try {
62
- $app = app();
63
-
64
- if (!is_object($app) || !method_exists($app, 'hasDebugModeEnabled')) {
65
- return false;
66
- }
67
-
68
- return (bool) $app->hasDebugModeEnabled();
69
- } catch (\Throwable $e) {
70
- return false;
71
- }
72
- }
73
-
74
48
  /**
75
49
  * Transform the resource into an webhook payload.
76
50
  *
@@ -17,19 +17,23 @@ class Zone extends FleetbaseResource
17
17
  public function toArray($request)
18
18
  {
19
19
  return $this->withCustomFields([
20
- 'id' => $this->when(Http::isInternalRequest(), $this->id, $this->public_id),
21
- 'public_id' => $this->when(Http::isInternalRequest(), $this->public_id),
22
- 'uuid' => $this->when(Http::isInternalRequest(), $this->uuid),
23
- 'service_area_uuid' => $this->when(Http::isInternalRequest(), $this->service_area_uuid),
24
- 'name' => $this->name,
25
- 'description' => $this->description,
26
- 'center' => $this->location,
27
- 'border' => $this->border,
28
- 'color' => $this->color,
29
- 'stroke_color' => $this->stroke_color,
30
- 'status' => $this->status,
31
- 'updated_at' => $this->updated_at,
32
- 'created_at' => $this->created_at,
20
+ 'id' => $this->when(Http::isInternalRequest(), $this->id, $this->public_id),
21
+ 'public_id' => $this->when(Http::isInternalRequest(), $this->public_id),
22
+ 'uuid' => $this->when(Http::isInternalRequest(), $this->uuid),
23
+ 'service_area_uuid' => $this->when(Http::isInternalRequest(), $this->service_area_uuid),
24
+ 'name' => $this->name,
25
+ 'description' => $this->description,
26
+ 'center' => $this->location,
27
+ 'border' => $this->border,
28
+ 'color' => $this->color,
29
+ 'stroke_color' => $this->stroke_color,
30
+ 'trigger_on_entry' => $this->trigger_on_entry,
31
+ 'trigger_on_exit' => $this->trigger_on_exit,
32
+ 'dwell_threshold_minutes' => $this->dwell_threshold_minutes,
33
+ 'speed_limit_kmh' => $this->speed_limit_kmh,
34
+ 'status' => $this->status,
35
+ 'updated_at' => $this->updated_at,
36
+ 'created_at' => $this->created_at,
33
37
  ]);
34
38
  }
35
39
 
@@ -41,16 +45,20 @@ class Zone extends FleetbaseResource
41
45
  public function toWebhookPayload()
42
46
  {
43
47
  return [
44
- 'id' => $this->public_id,
45
- 'name' => $this->name,
46
- 'description' => $this->description,
47
- 'center' => $this->location,
48
- 'border' => $this->border,
49
- 'color' => $this->color,
50
- 'stroke_color' => $this->stroke_color,
51
- 'status' => $this->status,
52
- 'updated_at' => $this->updated_at,
53
- 'created_at' => $this->created_at,
48
+ 'id' => $this->public_id,
49
+ 'name' => $this->name,
50
+ 'description' => $this->description,
51
+ 'center' => $this->location,
52
+ 'border' => $this->border,
53
+ 'color' => $this->color,
54
+ 'stroke_color' => $this->stroke_color,
55
+ 'trigger_on_entry' => $this->trigger_on_entry,
56
+ 'trigger_on_exit' => $this->trigger_on_exit,
57
+ 'dwell_threshold_minutes' => $this->dwell_threshold_minutes,
58
+ 'speed_limit_kmh' => $this->speed_limit_kmh,
59
+ 'status' => $this->status,
60
+ 'updated_at' => $this->updated_at,
61
+ 'created_at' => $this->created_at,
54
62
  ];
55
63
  }
56
64
  }
@@ -38,7 +38,9 @@ class FinalizeApiOrderCreation implements ShouldQueue
38
38
  $order->setPreliminaryDistanceAndTime();
39
39
  $order->purchaseServiceQuote($serviceQuote);
40
40
 
41
- if ($this->shouldDispatch) {
41
+ // The order may have been dispatched or started while this job waited in the
42
+ // queue; dispatching it again would move its status backwards.
43
+ if ($this->shouldDispatch && $order->isAwaitingDispatch()) {
42
44
  $order->dispatchWithActivity();
43
45
  }
44
46
 
@@ -6,7 +6,7 @@ use Fleetbase\FleetOps\Models\Driver;
6
6
  use Fleetbase\FleetOps\Models\Order;
7
7
  use Fleetbase\FleetOps\Models\Vehicle;
8
8
  use Fleetbase\FleetOps\Orchestration\OrchestrationEngineRegistry;
9
- use Fleetbase\Models\Setting;
9
+ use Fleetbase\FleetOps\Orchestration\Support\OrchestratorSettings;
10
10
  use Illuminate\Bus\Queueable;
11
11
  use Illuminate\Contracts\Queue\ShouldQueue;
12
12
  use Illuminate\Foundation\Bus\Dispatchable;
@@ -69,9 +69,17 @@ class ProcessAllocationJob implements ShouldQueue
69
69
  return;
70
70
  }
71
71
 
72
- $engine = $registry->resolve($this->engineId());
72
+ $result = $registry->allocateWithFallback($this->engineId(), $orders, $vehicles, $this->allocationOptions());
73
73
 
74
- $result = $engine->allocate($orders, $vehicles, $this->allocationOptions());
74
+ if (!empty($result['summary']['fallback_reason'])) {
75
+ $this->logInfo(sprintf(
76
+ '[ProcessAllocationJob] Used the %s engine instead of %s for company %s: %s',
77
+ $result['summary']['engine'],
78
+ $result['summary']['requested_engine'],
79
+ $this->companyUuid,
80
+ $result['summary']['fallback_reason']
81
+ ));
82
+ }
75
83
 
76
84
  foreach ($result['assignments'] as $assignment) {
77
85
  $order = $this->findOrderByPublicId($assignment['order_id']);
@@ -125,14 +133,16 @@ class ProcessAllocationJob implements ShouldQueue
125
133
 
126
134
  protected function engineId(): string
127
135
  {
128
- return Setting::lookup('fleetops.orchestrator_engine', 'greedy');
136
+ return OrchestratorSettings::engineForCompany($this->companyUuid);
129
137
  }
130
138
 
131
139
  protected function allocationOptions(): array
132
140
  {
141
+ $settings = OrchestratorSettings::forCompany($this->companyUuid);
142
+
133
143
  return [
134
- 'max_travel_time' => Setting::lookup('fleetops.allocation_max_travel_time', 3600),
135
- 'balance_workload' => Setting::lookup('fleetops.allocation_balance_workload', false),
144
+ 'max_travel_time' => (int) $settings['max_travel_time_seconds'],
145
+ 'balance_workload' => (bool) $settings['balance_workload'],
136
146
  ];
137
147
  }
138
148
 
@@ -0,0 +1,50 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Jobs;
4
+
5
+ use Fleetbase\FleetOps\Models\Order;
6
+ use Fleetbase\FleetOps\Support\TrackingPublisher;
7
+ use Fleetbase\FleetOps\Support\TrackingUpdate;
8
+ use Illuminate\Bus\Queueable;
9
+ use Illuminate\Contracts\Queue\ShouldQueue;
10
+ use Illuminate\Foundation\Bus\Dispatchable;
11
+ use Illuminate\Queue\InteractsWithQueue;
12
+ use Illuminate\Support\Facades\Cache;
13
+
14
+ /**
15
+ * Builds and publishes an order's public tracking updates off the request path.
16
+ *
17
+ * Location jobs publish the position only, except that at most once per ETA interval they
18
+ * publish the full update instead so that customers' ETAs follow the vehicle.
19
+ */
20
+ class PublishTrackingUpdate implements ShouldQueue
21
+ {
22
+ use Dispatchable;
23
+ use InteractsWithQueue;
24
+ use Queueable;
25
+
26
+ public $tries = 1;
27
+ public $timeout = 60;
28
+
29
+ public function __construct(public string $orderUuid, public string $reason = TrackingUpdate::REASON_STATUS, public ?string $dbConnection = null)
30
+ {
31
+ }
32
+
33
+ public function handle(TrackingPublisher $publisher): int
34
+ {
35
+ $order = Order::on($this->dbConnection)->where('uuid', $this->orderUuid)->first();
36
+ if (!$order) {
37
+ return 0;
38
+ }
39
+
40
+ if ($this->reason !== TrackingUpdate::REASON_LOCATION) {
41
+ return $publisher->publishOrder($order, $this->reason);
42
+ }
43
+
44
+ if (Cache::add('fleetops:tracking:eta:' . $order->uuid, 1, TrackingPublisher::ETA_INTERVAL)) {
45
+ return $publisher->publishOrder($order, TrackingUpdate::REASON_ETA);
46
+ }
47
+
48
+ return $publisher->publishLocation($order);
49
+ }
50
+ }