@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
@@ -6,7 +6,10 @@ use Fleetbase\FleetOps\Events\GeofenceEntered;
6
6
  use Fleetbase\FleetOps\Flow\Activity;
7
7
  use Fleetbase\FleetOps\Models\GeofenceEventLog;
8
8
  use Fleetbase\FleetOps\Models\Order;
9
+ use Fleetbase\FleetOps\Models\Payload;
10
+ use Fleetbase\FleetOps\Models\Place;
9
11
  use Fleetbase\FleetOps\Notifications\DriverArrivedAtGeofence;
12
+ use Fleetbase\FleetOps\Support\ResolvesOrderServiceStops;
10
13
  use Illuminate\Contracts\Queue\ShouldQueue;
11
14
  use Illuminate\Queue\InteractsWithQueue;
12
15
  use Illuminate\Support\Facades\Log;
@@ -24,6 +27,7 @@ use Illuminate\Support\Str;
24
27
  class HandleGeofenceEntered implements ShouldQueue
25
28
  {
26
29
  use InteractsWithQueue;
30
+ use ResolvesOrderServiceStops;
27
31
 
28
32
  /**
29
33
  * The number of times the job may be attempted.
@@ -89,10 +93,11 @@ class HandleGeofenceEntered implements ShouldQueue
89
93
  return;
90
94
  }
91
95
 
92
- // Get the current destination waypoint
93
- $destination = null;
96
+ // Resolve the stop the driver is currently heading to: the pickup
97
+ // until it is completed, then the next waypoint or the dropoff.
98
+ $place = null;
94
99
  try {
95
- $destination = $order->payload?->getPickupOrCurrentWaypoint();
100
+ $place = $this->currentDestination($order);
96
101
  } catch (\Throwable $e) {
97
102
  Log::warning('GeofenceEntered: Could not resolve order destination', [
98
103
  'order_uuid' => $order->uuid,
@@ -103,18 +108,6 @@ class HandleGeofenceEntered implements ShouldQueue
103
108
  return;
104
109
  }
105
110
 
106
- if (!$destination) {
107
- return;
108
- }
109
-
110
- // Resolve the destination place
111
- $place = null;
112
- try {
113
- $place = $destination->place ?? $destination->getPlace();
114
- } catch (\Throwable $e) {
115
- return;
116
- }
117
-
118
111
  if (!$place || !$place->location) {
119
112
  return;
120
113
  }
@@ -171,6 +164,29 @@ class HandleGeofenceEntered implements ShouldQueue
171
164
  }
172
165
  }
173
166
 
167
+ /**
168
+ * Resolve the place of the order's current destination stop.
169
+ *
170
+ * Uses the payload's current service stop (pickup, waypoints, dropoff in
171
+ * sequence, tracked by `current_waypoint_uuid`). When that stop has
172
+ * already been completed but the pointer was not advanced, the next
173
+ * incomplete stop is the destination instead.
174
+ */
175
+ protected function currentDestination(Order $order): ?Place
176
+ {
177
+ $payload = $order->payload;
178
+ if (!$payload instanceof Payload) {
179
+ return null;
180
+ }
181
+
182
+ $stop = $this->payloadCurrentServiceStop($payload);
183
+ if ($stop && $this->serviceStopIsComplete($order, $payload, $stop)) {
184
+ $stop = $this->nextIncompleteServiceStop($order, $payload);
185
+ }
186
+
187
+ return $stop['place'] ?? null;
188
+ }
189
+
174
190
  /**
175
191
  * Calculate the haversine distance in metres between two lat/lng points.
176
192
  *
@@ -12,6 +12,11 @@ class HandleOrderCanceled implements ShouldQueue
12
12
  {
13
13
  use InteractsWithQueue;
14
14
 
15
+ /**
16
+ * The reason the order being handled was canceled.
17
+ */
18
+ protected string $reason = '';
19
+
15
20
  /**
16
21
  * Handle the event.
17
22
  *
@@ -21,6 +26,9 @@ class HandleOrderCanceled implements ShouldQueue
21
26
  */
22
27
  public function handle(OrderCanceled $event)
23
28
  {
29
+ // the cancellation reason travels as the canceled activity's details
30
+ $this->reason = (string) ($event->activity ? $event->activity->get('details', '') : '');
31
+
24
32
  /** @var \Fleetbase\FleetOps\Models\Order $order */
25
33
  $order = $event->getModelRecord();
26
34
  if ($order->isIntegratedVendorOrder()) {
@@ -50,6 +58,6 @@ class HandleOrderCanceled implements ShouldQueue
50
58
 
51
59
  protected function notifyAssignedDriver(Driver $driver, $order): void
52
60
  {
53
- $driver->notify(new OrderCanceledNotification($order));
61
+ $driver->notify(new OrderCanceledNotification($order, $this->reason));
54
62
  }
55
63
  }
@@ -26,7 +26,8 @@ class HandleUserRemovedFromCompany implements ShouldQueue
26
26
 
27
27
  protected function deleteDriversForCompanyUser(string $companyUuid, string $userUuid): void
28
28
  {
29
- $this->driverQueryForCompanyUser($companyUuid, $userUuid)->delete();
29
+ // Delete each driver through the model so DriverObserver cleans up after it
30
+ $this->driverQueryForCompanyUser($companyUuid, $userUuid)->get()->each->delete();
30
31
  }
31
32
 
32
33
  protected function driverQueryForCompanyUser(string $companyUuid, string $userUuid): mixed
@@ -0,0 +1,27 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Listeners;
4
+
5
+ use Fleetbase\FleetOps\Support\TrackingPublisher;
6
+
7
+ /**
8
+ * Queues public tracking updates when a waypoint's or an entity's activity changes.
9
+ *
10
+ * Runs synchronously but only looks up the order and queues a job, and does nothing at all
11
+ * while socket authentication is off.
12
+ */
13
+ class PublishTrackingUpdates
14
+ {
15
+ public function __construct(protected ?TrackingPublisher $publisher = null)
16
+ {
17
+ $this->publisher ??= app(TrackingPublisher::class);
18
+ }
19
+
20
+ /**
21
+ * @param \Fleetbase\FleetOps\Events\WaypointActivityChanged|\Fleetbase\FleetOps\Events\WaypointCompleted|\Fleetbase\FleetOps\Events\EntityActivityChanged|\Fleetbase\FleetOps\Events\EntityCompleted $event
22
+ */
23
+ public function handle(object $event): bool
24
+ {
25
+ return $this->publisher->stopChanged($event->waypoint ?? $event->entity ?? null);
26
+ }
27
+ }
@@ -73,8 +73,10 @@ class CustomerCredentialsMail extends Mailable
73
73
  private function getCustomerPortalAccessUrl(): string
74
74
  {
75
75
  $customerPortalConfig = Setting::lookupForCompany($this->customer->company_uuid, 'customer-portal-config');
76
- $accessUrlSlug = data_get($customerPortalConfig, 'accessUrlSlug', 'customer-portal');
76
+ $accessUrlSlug = data_get($customerPortalConfig, 'accessUrlSlug');
77
77
 
78
- return Utils::consoleUrl($accessUrlSlug ?: 'customer-portal');
78
+ // The portal resolves a company's access slug under /customer-access/{slug};
79
+ // without one, send the customer to the portal's own sign-in route.
80
+ return Utils::consoleUrl($accessUrlSlug ? 'customer-access/' . $accessUrlSlug : 'customer-portal');
79
81
  }
80
82
  }
@@ -5,6 +5,7 @@ namespace Fleetbase\FleetOps\Models;
5
5
  use Fleetbase\Casts\Json;
6
6
  use Fleetbase\Casts\PolymorphicType;
7
7
  use Fleetbase\Models\Model;
8
+ use Fleetbase\Traits\HasApiModelCache;
8
9
  use Fleetbase\Traits\HasPublicId;
9
10
  use Fleetbase\Traits\HasUuid;
10
11
  use Illuminate\Database\Eloquent\Relations\BelongsTo;
@@ -14,6 +15,8 @@ use Illuminate\Database\Eloquent\SoftDeletes;
14
15
  class AssetConnection extends Model
15
16
  {
16
17
  use HasUuid;
18
+ // Writes bump the asset_connections API cache version, which cached vehicle lists filter on.
19
+ use HasApiModelCache;
17
20
  use HasPublicId;
18
21
  use SoftDeletes;
19
22
 
@@ -417,6 +417,7 @@ class Contact extends Model
417
417
  ]);
418
418
  $user->forceFill(['type' => 'customer'])->saveQuietly();
419
419
  $this->forceFill(['user_uuid' => $user->uuid])->saveQuietly();
420
+ $this->invalidateApiCache();
420
421
  } else {
421
422
  $user = $this->createUser();
422
423
  }
@@ -645,6 +646,8 @@ class Contact extends Model
645
646
  return null;
646
647
  }
647
648
 
649
+ ProfileAccountManager::copyAccountToSandbox($user, $contact->company->uuid);
650
+
648
651
  $role = $contact->isCustomer() ? 'Fleet-Ops Customer' : 'Fleet-Ops Contact';
649
652
  $companyUser = $contact->company->addUser($user, $role);
650
653
 
@@ -56,6 +56,18 @@ class Device extends Model
56
56
  */
57
57
  protected $table = 'devices';
58
58
 
59
+ /**
60
+ * Relation paths and tables the cached device lists embed (fleetbase/core-api#301).
61
+ *
62
+ * Lists load telematic, warranty and attachable and count sensors.
63
+ * attachable is a morphTo to a vehicle or trailer, so its tables are named.
64
+ * photo (public list) is left out: files is written by every upload, and a
65
+ * new photo is set by writing the device's own photo_uuid.
66
+ *
67
+ * @var string[]
68
+ */
69
+ protected $apiCacheDependencies = ['telematic', 'warranty', 'sensors', 'vehicles', 'assets'];
70
+
59
71
  /**
60
72
  * The type of public Id to generate.
61
73
  *
@@ -453,6 +465,10 @@ class Device extends Model
453
465
  });
454
466
 
455
467
  if ($updated) {
468
+ // Cached vehicle and trailer lists filter on attached devices without depending on
469
+ // the device table, which telemetry writes on every ping
470
+ static::invalidateAttachableApiCache($attachable, $this->company_uuid);
471
+
456
472
  activity('device_attached')
457
473
  ->performedOn($this)
458
474
  ->withProperties([
@@ -466,6 +482,14 @@ class Device extends Model
466
482
  return $updated;
467
483
  }
468
484
 
485
+ /**
486
+ * Invalidate the cached lists of the attached model's table (vehicles or trailers).
487
+ */
488
+ protected static function invalidateAttachableApiCache(\Illuminate\Database\Eloquent\Model $attachable, ?string $companyUuid): void
489
+ {
490
+ \Fleetbase\Support\ApiModelCache::invalidateModelCache($attachable, $companyUuid);
491
+ }
492
+
469
493
  /**
470
494
  * Detach the device from its current attachment.
471
495
  */
@@ -483,6 +507,10 @@ class Device extends Model
483
507
  return $this->update(['attachable_type' => null, 'attachable_uuid' => null]);
484
508
  });
485
509
 
510
+ if ($updated && $oldAttachableType && is_a($oldAttachableType, \Illuminate\Database\Eloquent\Model::class, true)) {
511
+ static::invalidateAttachableApiCache(new $oldAttachableType(), $this->company_uuid);
512
+ }
513
+
486
514
  if ($updated) {
487
515
  activity('device_detached')
488
516
  ->performedOn($this)
@@ -46,6 +46,13 @@ class DeviceEvent extends Model
46
46
  */
47
47
  protected $table = 'device_events';
48
48
 
49
+ /**
50
+ * Relation paths the cached device event lists embed (fleetbase/core-api#301).
51
+ *
52
+ * @var string[]
53
+ */
54
+ protected $apiCacheDependencies = ['device', 'device.telematic'];
55
+
49
56
  /**
50
57
  * The type of public Id to generate.
51
58
  *
@@ -171,6 +171,17 @@ class Driver extends Model
171
171
  */
172
172
  protected $with = [];
173
173
 
174
+ /**
175
+ * Relation paths the cached driver lists depend on (fleetbase/core-api#301).
176
+ *
177
+ * Lists eager load nothing, but which drivers they hold depends on the
178
+ * user (existence, name, email and phone search), the vehicle (vehicle
179
+ * search) and the fleets (fleet filter, through fleet_drivers).
180
+ *
181
+ * @var string[]
182
+ */
183
+ protected $apiCacheDependencies = ['user', 'vehicle', 'fleets'];
184
+
174
185
  /**
175
186
  * Dynamic attributes that are appended to object.
176
187
  *
@@ -272,10 +283,7 @@ class Driver extends Model
272
283
  return $this->belongsTo(\Fleetbase\Models\Company::class);
273
284
  }
274
285
 
275
- /**
276
- * @return BelongsTo
277
- */
278
- public function vehicle()
286
+ public function vehicle(): BelongsTo
279
287
  {
280
288
  return $this->belongsTo(Vehicle::class)->select([
281
289
  'uuid',
@@ -431,7 +439,8 @@ class Driver extends Model
431
439
  return static::getAvatar($value);
432
440
  }
433
441
 
434
- return $value;
442
+ // legacy rows hold an absolute URL; re-sign it if it points into the private media bucket
443
+ return Utils::signStoredFileUrl($value);
435
444
  }
436
445
 
437
446
  /**
@@ -669,8 +678,12 @@ class Driver extends Model
669
678
  */
670
679
  public function assignVehicle(Vehicle $vehicle): self
671
680
  {
672
- // Unassign vehicle from other drivers
673
- static::where('vehicle_uuid', $vehicle->uuid)->update(['vehicle_uuid' => null]);
681
+ // Unassign vehicle from other drivers. This driver is skipped: when it already holds the
682
+ // vehicle the save below isn't dirty, so it would not write the vehicle back
683
+ static::where('vehicle_uuid', $vehicle->uuid)
684
+ ->when($this->uuid, fn ($query) => $query->where('uuid', '!=', $this->uuid))
685
+ ->update(['vehicle_uuid' => null]);
686
+ static::invalidateApiCacheManually($vehicle->company_uuid ?? $this->company_uuid);
674
687
 
675
688
  // Set this vehicle to the driver instance
676
689
  $this->setVehicle($vehicle);
@@ -9,6 +9,7 @@ use Fleetbase\FleetOps\Support\Utils;
9
9
  use Fleetbase\FleetOps\Traits\HasTrackingNumber;
10
10
  use Fleetbase\FleetOps\Traits\PayloadAccessors;
11
11
  use Fleetbase\Models\Model;
12
+ use Fleetbase\Support\ApiModelCache;
12
13
  use Fleetbase\Traits\HasApiModelBehavior;
13
14
  use Fleetbase\Traits\HasCustomFields;
14
15
  use Fleetbase\Traits\HasInternalId;
@@ -437,6 +438,7 @@ class Entity extends Model
437
438
  Entity::where('uuid', $values['uuid'])->update([
438
439
  'payload_uuid' => $payload->uuid,
439
440
  ]);
441
+ ApiModelCache::invalidateModelCache(new static(), $payload->company_uuid ?? session('company'));
440
442
 
441
443
  return $values['uuid'];
442
444
  }
@@ -471,16 +473,22 @@ class Entity extends Model
471
473
  if ($result && $payload) {
472
474
  // create tracking number for entity
473
475
  $trackingNumberId = TrackingNumber::insertGetUuid([
474
- 'owner_uuid' => $uuid,
475
- 'owner_type' => Utils::getModelClassName('entity'),
476
- 'region' => $payload->getPickupRegion(),
477
- 'location' => Utils::parsePointToWkt($payload->getPickupLocation()),
476
+ 'owner_uuid' => $uuid,
477
+ 'owner_type' => Utils::getModelClassName('entity'),
478
+ 'owner_public_id' => $values['public_id'],
479
+ 'region' => $payload->getPickupRegion(),
480
+ 'location' => Utils::parsePointToWkt($payload->getPickupLocation()),
478
481
  ]);
479
482
 
480
483
  // set tracking number
481
484
  static::where('uuid', $uuid)->update(['tracking_number_uuid' => $trackingNumberId]);
482
485
  }
483
486
 
487
+ // Inserted and updated without model events
488
+ if ($result) {
489
+ ApiModelCache::invalidateModelCache($instance, $values['company_uuid']);
490
+ }
491
+
484
492
  return $result ? $uuid : false;
485
493
  }
486
494
 
@@ -11,6 +11,9 @@ use Fleetbase\Traits\HasUuid;
11
11
  use Fleetbase\Traits\Searchable;
12
12
  use Fleetbase\Traits\SendsWebhooks;
13
13
  use Fleetbase\Traits\TracksApiCredential;
14
+ use Illuminate\Database\Eloquent\Relations\BelongsTo;
15
+ use Illuminate\Database\Eloquent\Relations\HasMany;
16
+ use Illuminate\Database\Eloquent\Relations\HasManyThrough;
14
17
  use Illuminate\Notifications\Notifiable;
15
18
  use Spatie\Activitylog\LogOptions;
16
19
  use Spatie\Activitylog\Traits\LogsActivity;
@@ -105,66 +108,42 @@ class Fleet extends Model
105
108
  */
106
109
  protected $hidden = [];
107
110
 
108
- /**
109
- * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
110
- */
111
- public function photo()
111
+ public function photo(): BelongsTo
112
112
  {
113
113
  return $this->belongsTo(\Fleetbase\Models\File::class, 'image_uuid', 'uuid');
114
114
  }
115
115
 
116
- /**
117
- * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
118
- */
119
- public function serviceArea()
116
+ public function serviceArea(): BelongsTo
120
117
  {
121
118
  return $this->belongsTo(ServiceArea::class)->select(['uuid', 'public_id', 'name', 'type', 'border']);
122
119
  }
123
120
 
124
- /**
125
- * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
126
- */
127
- public function zone()
121
+ public function zone(): BelongsTo
128
122
  {
129
123
  return $this->belongsTo(Zone::class)->select(['uuid', 'public_id', 'name', 'border']);
130
124
  }
131
125
 
132
- /**
133
- * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
134
- */
135
- public function vendor()
126
+ public function vendor(): BelongsTo
136
127
  {
137
128
  return $this->belongsTo(Vendor::class)->select(['uuid', 'public_id', 'name']);
138
129
  }
139
130
 
140
- /**
141
- * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
142
- */
143
- public function parentFleet()
131
+ public function parentFleet(): BelongsTo
144
132
  {
145
133
  return $this->belongsTo(Fleet::class)->without(['subFleets']);
146
134
  }
147
135
 
148
- /**
149
- * @return \Illuminate\Database\Eloquent\Relations\HasMany
150
- */
151
- public function subFleets()
136
+ public function subFleets(): HasMany
152
137
  {
153
138
  return $this->hasMany(Fleet::class, 'parent_fleet_uuid', 'uuid')->without(['parentFleet']);
154
139
  }
155
140
 
156
- /**
157
- * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
158
- */
159
- public function drivers()
141
+ public function drivers(): HasManyThrough
160
142
  {
161
143
  return $this->hasManyThrough(Driver::class, FleetDriver::class, 'fleet_uuid', 'uuid', 'uuid', 'driver_uuid');
162
144
  }
163
145
 
164
- /**
165
- * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
166
- */
167
- public function vehicles()
146
+ public function vehicles(): HasManyThrough
168
147
  {
169
148
  return $this->hasManyThrough(Vehicle::class, FleetVehicle::class, 'fleet_uuid', 'uuid', 'uuid', 'vehicle_uuid');
170
149
  }
@@ -3,12 +3,15 @@
3
3
  namespace Fleetbase\FleetOps\Models;
4
4
 
5
5
  use Fleetbase\Models\Model;
6
+ use Fleetbase\Traits\HasApiModelCache;
6
7
  use Fleetbase\Traits\HasUuid;
7
8
  use Illuminate\Database\Eloquent\Relations\BelongsTo;
8
9
 
9
10
  class FleetDriver extends Model
10
11
  {
11
12
  use HasUuid;
13
+ // Writes bump the fleet_drivers API cache version, which cached driver lists filter on.
14
+ use HasApiModelCache;
12
15
 
13
16
  /**
14
17
  * The database table used by the model.
@@ -3,12 +3,15 @@
3
3
  namespace Fleetbase\FleetOps\Models;
4
4
 
5
5
  use Fleetbase\Models\Model;
6
+ use Fleetbase\Traits\HasApiModelCache;
6
7
  use Fleetbase\Traits\HasUuid;
7
8
  use Illuminate\Database\Eloquent\Relations\BelongsTo;
8
9
 
9
10
  class FleetVehicle extends Model
10
11
  {
11
12
  use HasUuid;
13
+ // Writes bump the fleet_vehicles API cache version, which cached vehicle lists filter on.
14
+ use HasApiModelCache;
12
15
 
13
16
  /**
14
17
  * The database table used by the model.
@@ -16,6 +16,7 @@ use Fleetbase\Traits\HasPublicId;
16
16
  use Fleetbase\Traits\HasUuid;
17
17
  use Fleetbase\Traits\Searchable;
18
18
  use Fleetbase\Traits\TracksApiCredential;
19
+ use Illuminate\Database\Eloquent\Relations\BelongsTo;
19
20
 
20
21
  class FuelReport extends Model
21
22
  {
@@ -118,34 +119,25 @@ class FuelReport extends Model
118
119
  $this->attributes['amount'] = Utils::numbersOnly($value);
119
120
  }
120
121
 
121
- /**
122
- * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
123
- */
124
- public function driver()
122
+ public function driver(): BelongsTo
125
123
  {
126
124
  return $this->belongsTo(Driver::class)->without(['vehicle']);
127
125
  }
128
126
 
129
- /**
130
- * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
131
- */
132
- public function vehicle()
127
+ public function vehicle(): BelongsTo
133
128
  {
134
129
  return $this->belongsTo(Vehicle::class)->without(['driver']);
135
130
  }
136
131
 
137
132
  /**
138
- * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
133
+ * @return BelongsTo
139
134
  */
140
135
  public function reportedBy()
141
136
  {
142
137
  return $this->belongsTo(User::class);
143
138
  }
144
139
 
145
- /**
146
- * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
147
- */
148
- public function reporter()
140
+ public function reporter(): BelongsTo
149
141
  {
150
142
  return $this->belongsTo(User::class, 'reported_by_uuid');
151
143
  }
@@ -152,10 +152,7 @@ class Issue extends Model
152
152
  return $this->belongsTo(User::class);
153
153
  }
154
154
 
155
- /**
156
- * @return BelongsTo
157
- */
158
- public function reporter()
155
+ public function reporter(): BelongsTo
159
156
  {
160
157
  return $this->belongsTo(User::class, 'reported_by_uuid');
161
158
  }
@@ -168,26 +165,17 @@ class Issue extends Model
168
165
  return $this->belongsTo(User::class);
169
166
  }
170
167
 
171
- /**
172
- * @return BelongsTo
173
- */
174
- public function assignee()
168
+ public function assignee(): BelongsTo
175
169
  {
176
170
  return $this->belongsTo(User::class, 'assigned_to_uuid');
177
171
  }
178
172
 
179
- /**
180
- * @return BelongsTo
181
- */
182
- public function vehicle()
173
+ public function vehicle(): BelongsTo
183
174
  {
184
175
  return $this->belongsTo(Vehicle::class);
185
176
  }
186
177
 
187
- /**
188
- * @return BelongsTo
189
- */
190
- public function driver()
178
+ public function driver(): BelongsTo
191
179
  {
192
180
  return $this->belongsTo(Driver::class);
193
181
  }