@fleetbase/fleetops-engine 0.6.58 → 0.6.59

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 (685) hide show
  1. package/README.md +3 -0
  2. package/addon/components/customer/form.hbs +0 -49
  3. package/addon/components/entity/card.hbs +1 -0
  4. package/addon/components/modals/order-label.hbs +1 -1
  5. package/addon/components/place/form.hbs +1 -1
  6. package/addon/services/entity-actions.js +32 -0
  7. package/addon/styles/fleetops-engine.css +0 -1
  8. package/composer.json +8 -3
  9. package/extension.json +1 -1
  10. package/index.js +7 -1
  11. package/package.json +2 -1
  12. package/scripts/coverage-file-runner.php +240 -0
  13. package/scripts/coverage-runner.php +2 -1
  14. package/scripts/coverage-summary.php +41 -2
  15. package/scripts/pest-bootstrap.php +237 -3
  16. package/scripts/pest-file-runner.php +13 -1
  17. package/scripts/pest-runner.php +57 -2
  18. package/server/resources/views/labels/entity-label.php +4 -4
  19. package/server/src/Casts/MultiPolygon.php +8 -3
  20. package/server/src/Casts/OrderConfigEntities.php +10 -3
  21. package/server/src/Casts/Point.php +10 -6
  22. package/server/src/Casts/Polygon.php +5 -2
  23. package/server/src/Console/Commands/AssignCustomerRoles.php +28 -6
  24. package/server/src/Console/Commands/AssignDriverRoles.php +36 -6
  25. package/server/src/Console/Commands/AuditCustomerUserConflicts.php +6 -1
  26. package/server/src/Console/Commands/DispatchAdhocOrders.php +12 -2
  27. package/server/src/Console/Commands/FixCustomerCompanies.php +46 -11
  28. package/server/src/Console/Commands/FixDriverCompanies.php +18 -3
  29. package/server/src/Console/Commands/FixLegacyOrderConfigs.php +31 -6
  30. package/server/src/Console/Commands/ProcessMaintenanceTriggers.php +94 -42
  31. package/server/src/Console/Commands/PurgeUnpurchasedServiceQuotes.php +42 -12
  32. package/server/src/Console/Commands/ReplayVehicleLocations.php +120 -55
  33. package/server/src/Console/Commands/SendDriverNotification.php +25 -4
  34. package/server/src/Console/Commands/SendMaintenanceReminders.php +43 -23
  35. package/server/src/Console/Commands/SimulateOrderRouteNavigation.php +36 -6
  36. package/server/src/Console/Commands/TrackOrderDistanceAndTime.php +6 -1
  37. package/server/src/Events/DriverLocationChanged.php +1 -1
  38. package/server/src/Events/DriverSimulatedLocationChanged.php +1 -1
  39. package/server/src/Events/EntityActivityChanged.php +1 -1
  40. package/server/src/Events/EntityCompleted.php +1 -1
  41. package/server/src/Events/EntityDriverAssigned.php +1 -1
  42. package/server/src/Events/FuelProviderTransactionImported.php +1 -1
  43. package/server/src/Events/FuelProviderTransactionMatched.php +1 -1
  44. package/server/src/Events/FuelProviderTransactionUnmatched.php +1 -1
  45. package/server/src/Events/FuelReportCreatedFromProvider.php +1 -1
  46. package/server/src/Events/GeofenceDwelled.php +1 -1
  47. package/server/src/Events/GeofenceEntered.php +1 -1
  48. package/server/src/Events/GeofenceExited.php +1 -1
  49. package/server/src/Events/VehicleLocationChanged.php +1 -1
  50. package/server/src/Events/WaypointActivityChanged.php +1 -1
  51. package/server/src/Events/WaypointCompleted.php +1 -1
  52. package/server/src/Exceptions/IntegratedVendorException.php +2 -2
  53. package/server/src/Exceptions/TelematicRateLimitExceededException.php +1 -1
  54. package/server/src/Http/Controllers/Api/v1/ContactController.php +89 -22
  55. package/server/src/Http/Controllers/Api/v1/CustomerController.php +296 -97
  56. package/server/src/Http/Controllers/Api/v1/DeviceController.php +48 -14
  57. package/server/src/Http/Controllers/Api/v1/DriverController.php +168 -63
  58. package/server/src/Http/Controllers/Api/v1/EntityController.php +112 -66
  59. package/server/src/Http/Controllers/Api/v1/EquipmentController.php +40 -10
  60. package/server/src/Http/Controllers/Api/v1/FleetController.php +54 -14
  61. package/server/src/Http/Controllers/Api/v1/FuelReportController.php +54 -14
  62. package/server/src/Http/Controllers/Api/v1/FuelTransactionController.php +36 -11
  63. package/server/src/Http/Controllers/Api/v1/GeofenceController.php +39 -21
  64. package/server/src/Http/Controllers/Api/v1/IssueController.php +54 -14
  65. package/server/src/Http/Controllers/Api/v1/LabelController.php +61 -22
  66. package/server/src/Http/Controllers/Api/v1/NavigatorController.php +21 -5
  67. package/server/src/Http/Controllers/Api/v1/OrderConfigController.php +35 -5
  68. package/server/src/Http/Controllers/Api/v1/OrderController.php +388 -203
  69. package/server/src/Http/Controllers/Api/v1/PartController.php +40 -10
  70. package/server/src/Http/Controllers/Api/v1/PayloadController.php +90 -30
  71. package/server/src/Http/Controllers/Api/v1/PlaceController.php +188 -91
  72. package/server/src/Http/Controllers/Api/v1/PurchaseRateController.php +100 -36
  73. package/server/src/Http/Controllers/Api/v1/ServiceAreaController.php +96 -26
  74. package/server/src/Http/Controllers/Api/v1/ServiceQuoteController.php +169 -81
  75. package/server/src/Http/Controllers/Api/v1/ServiceRateController.php +104 -75
  76. package/server/src/Http/Controllers/Api/v1/TrackingNumberController.php +83 -14
  77. package/server/src/Http/Controllers/Api/v1/TrackingStatusController.php +66 -16
  78. package/server/src/Http/Controllers/Api/v1/VehicleController.php +121 -67
  79. package/server/src/Http/Controllers/Api/v1/VendorController.php +54 -14
  80. package/server/src/Http/Controllers/Api/v1/WorkOrderController.php +47 -12
  81. package/server/src/Http/Controllers/Api/v1/ZoneController.php +84 -24
  82. package/server/src/Http/Controllers/Internal/v1/AnalyticsController.php +15 -5
  83. package/server/src/Http/Controllers/Internal/v1/ContactController.php +113 -28
  84. package/server/src/Http/Controllers/Internal/v1/CustomerController.php +36 -11
  85. package/server/src/Http/Controllers/Internal/v1/DeviceController.php +9 -4
  86. package/server/src/Http/Controllers/Internal/v1/DriverController.php +167 -69
  87. package/server/src/Http/Controllers/Internal/v1/EquipmentController.php +18 -3
  88. package/server/src/Http/Controllers/Internal/v1/FleetController.php +137 -60
  89. package/server/src/Http/Controllers/Internal/v1/FleetOpsLookupController.php +24 -9
  90. package/server/src/Http/Controllers/Internal/v1/FuelReportController.php +18 -3
  91. package/server/src/Http/Controllers/Internal/v1/GeocoderController.php +26 -8
  92. package/server/src/Http/Controllers/Internal/v1/GettingStartedController.php +12 -2
  93. package/server/src/Http/Controllers/Internal/v1/IntegratedVendorController.php +27 -6
  94. package/server/src/Http/Controllers/Internal/v1/IssueController.php +82 -29
  95. package/server/src/Http/Controllers/Internal/v1/MaintenanceController.php +34 -26
  96. package/server/src/Http/Controllers/Internal/v1/MaintenanceScheduleController.php +141 -97
  97. package/server/src/Http/Controllers/Internal/v1/ManifestController.php +28 -8
  98. package/server/src/Http/Controllers/Internal/v1/MetricsController.php +21 -12
  99. package/server/src/Http/Controllers/Internal/v1/MorphController.php +90 -18
  100. package/server/src/Http/Controllers/Internal/v1/NavigatorController.php +88 -35
  101. package/server/src/Http/Controllers/Internal/v1/OrchestrationController.php +149 -39
  102. package/server/src/Http/Controllers/Internal/v1/OrderConfigController.php +54 -18
  103. package/server/src/Http/Controllers/Internal/v1/OrderController.php +298 -86
  104. package/server/src/Http/Controllers/Internal/v1/PartController.php +18 -3
  105. package/server/src/Http/Controllers/Internal/v1/PaymentController.php +46 -14
  106. package/server/src/Http/Controllers/Internal/v1/PlaceController.php +31 -5
  107. package/server/src/Http/Controllers/Internal/v1/ProofController.php +88 -48
  108. package/server/src/Http/Controllers/Internal/v1/SearchController.php +1 -1
  109. package/server/src/Http/Controllers/Internal/v1/SensorController.php +6 -1
  110. package/server/src/Http/Controllers/Internal/v1/ServiceAreaController.php +6 -1
  111. package/server/src/Http/Controllers/Internal/v1/ServiceQuoteController.php +255 -105
  112. package/server/src/Http/Controllers/Internal/v1/SettingController.php +88 -35
  113. package/server/src/Http/Controllers/Internal/v1/TelematicController.php +1 -4
  114. package/server/src/Http/Controllers/Internal/v1/Traits/DriverSchedulingTrait.php +42 -14
  115. package/server/src/Http/Controllers/Internal/v1/VendorController.php +103 -33
  116. package/server/src/Http/Controllers/Internal/v1/WorkOrderController.php +42 -12
  117. package/server/src/Http/Filter/DriverFilter.php +2 -2
  118. package/server/src/Http/Filter/OrderFilter.php +1 -1
  119. package/server/src/Http/Filter/VehicleFilter.php +21 -7
  120. package/server/src/Http/Middleware/AuthenticateCustomerToken.php +12 -2
  121. package/server/src/Http/Requests/BulkDispatchRequest.php +3 -9
  122. package/server/src/Http/Requests/CancelOrderRequest.php +2 -6
  123. package/server/src/Http/Requests/CreateContactRequest.php +2 -6
  124. package/server/src/Http/Requests/CreateDeviceRequest.php +2 -2
  125. package/server/src/Http/Requests/CreateDriverRequest.php +3 -9
  126. package/server/src/Http/Requests/CreateEntityRequest.php +2 -6
  127. package/server/src/Http/Requests/CreateEquipmentRequest.php +2 -2
  128. package/server/src/Http/Requests/CreateFleetRequest.php +2 -6
  129. package/server/src/Http/Requests/CreateFuelReportRequest.php +2 -6
  130. package/server/src/Http/Requests/CreateFuelTransactionRequest.php +2 -2
  131. package/server/src/Http/Requests/CreateIssueRequest.php +2 -6
  132. package/server/src/Http/Requests/CreateOrderRequest.php +7 -8
  133. package/server/src/Http/Requests/CreatePartRequest.php +2 -2
  134. package/server/src/Http/Requests/CreatePayloadRequest.php +7 -9
  135. package/server/src/Http/Requests/CreatePlaceRequest.php +2 -6
  136. package/server/src/Http/Requests/CreatePurchaseRateRequest.php +2 -6
  137. package/server/src/Http/Requests/CreateSensorRequest.php +2 -2
  138. package/server/src/Http/Requests/CreateServiceAreaRequest.php +2 -6
  139. package/server/src/Http/Requests/CreateServiceQuoteRequest.php +2 -6
  140. package/server/src/Http/Requests/CreateServiceRateRequest.php +2 -6
  141. package/server/src/Http/Requests/CreateTrackingNumberRequest.php +2 -6
  142. package/server/src/Http/Requests/CreateTrackingStatusRequest.php +2 -6
  143. package/server/src/Http/Requests/CreateVehicleRequest.php +2 -6
  144. package/server/src/Http/Requests/CreateVendorRequest.php +2 -6
  145. package/server/src/Http/Requests/CreateWorkOrderRequest.php +2 -2
  146. package/server/src/Http/Requests/CreateZoneRequest.php +2 -6
  147. package/server/src/Http/Requests/DecodeTrackingNumberQR.php +2 -6
  148. package/server/src/Http/Requests/DriverSimulationRequest.php +2 -6
  149. package/server/src/Http/Requests/Internal/AssignOrderRequest.php +3 -7
  150. package/server/src/Http/Requests/Internal/CreateDriverRequest.php +4 -12
  151. package/server/src/Http/Requests/Internal/CreateOrderConfigRequest.php +2 -6
  152. package/server/src/Http/Requests/Internal/CreateOrderRequest.php +7 -8
  153. package/server/src/Http/Requests/Internal/FleetActionRequest.php +18 -12
  154. package/server/src/Http/Requests/Internal/UpdateDriverRequest.php +6 -3
  155. package/server/src/Http/Requests/QueryServiceQuotesRequest.php +2 -6
  156. package/server/src/Http/Requests/ScheduleOrderRequest.php +2 -6
  157. package/server/src/Http/Requests/UpdateIssueRequest.php +1 -3
  158. package/server/src/Http/Resources/v1/Customer.php +2 -2
  159. package/server/src/Http/Resources/v1/Maintenance.php +3 -4
  160. package/server/src/Http/Resources/v1/MaintenanceSchedule.php +3 -4
  161. package/server/src/Http/Resources/v1/Order.php +3 -7
  162. package/server/src/Http/Resources/v1/PurchaseRate.php +4 -6
  163. package/server/src/Http/Resources/v1/TrackingStatus.php +4 -6
  164. package/server/src/Http/Resources/v1/WorkOrder.php +3 -4
  165. package/server/src/Imports/ContactImport.php +10 -1
  166. package/server/src/Imports/DriverImport.php +10 -1
  167. package/server/src/Imports/EquipmentImport.php +6 -1
  168. package/server/src/Imports/FleetImport.php +10 -1
  169. package/server/src/Imports/FuelReportImport.php +10 -1
  170. package/server/src/Imports/IssueImport.php +10 -1
  171. package/server/src/Imports/MaintenanceImport.php +6 -1
  172. package/server/src/Imports/MaintenanceScheduleImport.php +6 -1
  173. package/server/src/Imports/PartImport.php +6 -1
  174. package/server/src/Imports/PlaceImport.php +10 -1
  175. package/server/src/Imports/VehicleImport.php +10 -1
  176. package/server/src/Imports/VendorImport.php +10 -1
  177. package/server/src/Imports/WorkOrderImport.php +6 -1
  178. package/server/src/Integrations/Lalamove/Lalamove.php +3 -7
  179. package/server/src/Integrations/Lalamove/LalamoveServiceType.php +5 -8
  180. package/server/src/Jobs/CheckGeofenceDwell.php +41 -16
  181. package/server/src/Jobs/FinalizeApiOrderCreation.php +17 -2
  182. package/server/src/Jobs/FinalizeInternalOrderCreation.php +11 -1
  183. package/server/src/Jobs/NotifyBulkAssignedDriver.php +29 -16
  184. package/server/src/Jobs/ProcessAllocationJob.php +59 -25
  185. package/server/src/Jobs/ReplayPositions.php +17 -10
  186. package/server/src/Jobs/SendPositionReplay.php +18 -7
  187. package/server/src/Jobs/SimulateDrivingRoute.php +14 -3
  188. package/server/src/Jobs/SyncFuelProviderTransactionsJob.php +12 -2
  189. package/server/src/Listeners/HandleDeliveryCompletion.php +11 -1
  190. package/server/src/Listeners/HandleGeofenceDwelled.php +6 -1
  191. package/server/src/Listeners/HandleGeofenceEntered.php +4 -2
  192. package/server/src/Listeners/HandleGeofenceExited.php +6 -1
  193. package/server/src/Listeners/HandleOrderCanceled.php +18 -3
  194. package/server/src/Listeners/HandleOrderDispatchFailed.php +12 -2
  195. package/server/src/Listeners/HandleOrderDispatched.php +61 -26
  196. package/server/src/Listeners/HandleOrderDriverAssigned.php +12 -2
  197. package/server/src/Listeners/HandleUserRemovedFromCompany.php +19 -6
  198. package/server/src/Listeners/NotifyDriverOnShiftChange.php +24 -4
  199. package/server/src/Listeners/NotifyOrderEvent.php +11 -6
  200. package/server/src/Models/Contact.php +6 -7
  201. package/server/src/Models/Device.php +26 -3
  202. package/server/src/Models/Driver.php +0 -6
  203. package/server/src/Models/Entity.php +4 -4
  204. package/server/src/Models/Equipment.php +1 -1
  205. package/server/src/Models/FuelReport.php +5 -1
  206. package/server/src/Models/IntegratedVendor.php +2 -2
  207. package/server/src/Models/Issue.php +5 -1
  208. package/server/src/Models/MaintenanceSchedule.php +25 -10
  209. package/server/src/Models/Order.php +18 -15
  210. package/server/src/Models/OrderConfig.php +1 -1
  211. package/server/src/Models/Payload.php +9 -16
  212. package/server/src/Models/Place.php +20 -13
  213. package/server/src/Models/ServiceArea.php +3 -6
  214. package/server/src/Models/ServiceQuote.php +5 -0
  215. package/server/src/Models/ServiceRate.php +13 -6
  216. package/server/src/Models/Telematic.php +2 -2
  217. package/server/src/Models/TrackingNumber.php +55 -10
  218. package/server/src/Models/TrackingStatus.php +24 -4
  219. package/server/src/Models/Waypoint.php +44 -10
  220. package/server/src/Models/Zone.php +3 -6
  221. package/server/src/Notifications/DriverArrivedAtGeofence.php +1 -1
  222. package/server/src/Notifications/OrderDispatched.php +3 -9
  223. package/server/src/Notifications/OrderPing.php +3 -9
  224. package/server/src/Observers/CategoryObserver.php +6 -1
  225. package/server/src/Observers/CompanyObserver.php +5 -0
  226. package/server/src/Observers/CompanyUserObserver.php +12 -2
  227. package/server/src/Observers/DriverObserver.php +19 -4
  228. package/server/src/Observers/FleetObserver.php +6 -1
  229. package/server/src/Observers/PurchaseRateObserver.php +66 -11
  230. package/server/src/Observers/ServiceAreaObserver.php +12 -2
  231. package/server/src/Observers/ServiceRateObserver.php +21 -6
  232. package/server/src/Observers/TrackingNumberObserver.php +19 -4
  233. package/server/src/Observers/UserObserver.php +6 -1
  234. package/server/src/Observers/VehicleObserver.php +27 -7
  235. package/server/src/Observers/WorkOrderObserver.php +27 -7
  236. package/server/src/Orchestration/Engines/DriverAssignmentEngine.php +8 -3
  237. package/server/src/Orchestration/Support/OrchestrationPayloadBuilder.php +2 -2
  238. package/server/src/Providers/FleetOpsServiceProvider.php +12 -0
  239. package/server/src/Providers/NotificationServiceProvider.php +6 -0
  240. package/server/src/Support/Ai/Capabilities/AssetStatusCapability.php +36 -26
  241. package/server/src/Support/Ai/Capabilities/CreateOrderPreviewCapability.php +18 -5
  242. package/server/src/Support/Ai/Capabilities/OrderInsightsCapability.php +6 -1
  243. package/server/src/Support/Ai/Capabilities/SearchResourcesCapability.php +26 -6
  244. package/server/src/Support/Analytics/FuelEfficiency.php +9 -3
  245. package/server/src/Support/Analytics/FuelProviderSummary.php +14 -5
  246. package/server/src/Support/Analytics/GeofenceViolations.php +40 -20
  247. package/server/src/Support/Analytics/IssuesInsights.php +38 -18
  248. package/server/src/Support/Analytics/MaintenanceOverview.php +51 -21
  249. package/server/src/Support/Analytics/OnTimeDelivery.php +3 -2
  250. package/server/src/Support/Analytics/OperationsPulse.php +59 -35
  251. package/server/src/Support/Analytics/OrdersByStatus.php +12 -7
  252. package/server/src/Support/Analytics/RevenueTrend.php +16 -6
  253. package/server/src/Support/Analytics/TopDrivers.php +3 -2
  254. package/server/src/Support/FleetOps.php +109 -104
  255. package/server/src/Support/Geocoding.php +52 -14
  256. package/server/src/Support/GeofenceIntersectionService.php +47 -27
  257. package/server/src/Support/LiveOrderQuery.php +6 -1
  258. package/server/src/Support/Metrics/ActiveRevenueQuery.php +3 -2
  259. package/server/src/Support/Metrics/FuelCostsMetric.php +6 -1
  260. package/server/src/Support/ResolvesOrderServiceStops.php +10 -0
  261. package/server/src/Support/Telematics/Providers/GeotabProvider.php +9 -4
  262. package/server/src/Support/Utils.php +122 -16
  263. package/server/src/Tracking/Providers/GoogleRoutesTrackingProvider.php +6 -1
  264. package/server/src/Tracking/Providers/OsrmTrackingProvider.php +11 -6
  265. package/server/src/Tracking/TrackingProviderManager.php +2 -3
  266. package/server/src/Tracking/TrackingProviderRegistry.php +8 -4
  267. package/server/src/Traits/PayloadAccessors.php +6 -1
  268. package/server/src/routes.php +23 -16
  269. package/server/tests/AiOperationalQueryCapabilityTest.php +457 -1
  270. package/server/tests/AiPreviewCapabilityContractsTest.php +180 -0
  271. package/server/tests/AnalyticsRoutesTest.php +380 -1
  272. package/server/tests/AnalyticsWidgetContractsTest.php +740 -0
  273. package/server/tests/ApiContactControllerContractsTest.php +284 -0
  274. package/server/tests/ApiCustomerControllerContractsTest.php +962 -0
  275. package/server/tests/ApiDriverControllerContractsTest.php +571 -0
  276. package/server/tests/ApiEntityControllerContractsTest.php +329 -0
  277. package/server/tests/ApiEquipmentControllerContractsTest.php +239 -0
  278. package/server/tests/ApiFleetControllerContractsTest.php +176 -0
  279. package/server/tests/ApiFuelReportControllerContractsTest.php +217 -0
  280. package/server/tests/ApiIssueControllerContractsTest.php +217 -0
  281. package/server/tests/ApiOrderControllerContractsTest.php +1030 -0
  282. package/server/tests/ApiPartControllerContractsTest.php +251 -0
  283. package/server/tests/ApiPayloadControllerContractsTest.php +314 -0
  284. package/server/tests/ApiPlaceControllerContractsTest.php +541 -0
  285. package/server/tests/ApiPurchaseRateControllerContractsTest.php +283 -0
  286. package/server/tests/ApiServiceAreaZoneControllerContractsTest.php +442 -0
  287. package/server/tests/ApiServiceQuoteControllerContractsTest.php +322 -0
  288. package/server/tests/ApiTrackingNumberControllerContractsTest.php +225 -0
  289. package/server/tests/ApiTrackingStatusControllerContractsTest.php +254 -0
  290. package/server/tests/ApiVehicleControllerContractsTest.php +368 -0
  291. package/server/tests/ApiVendorControllerContractsTest.php +199 -0
  292. package/server/tests/AssetAndPlaceSearchContractsTest.php +220 -0
  293. package/server/tests/BackendSmallModelContractsTest.php +354 -0
  294. package/server/tests/CapacityAllocationEngineTest.php +56 -0
  295. package/server/tests/CommandContractsTest.php +2695 -0
  296. package/server/tests/CompactResourceSerializationTest.php +2745 -0
  297. package/server/tests/ControllerFilterContractsTest.php +1273 -0
  298. package/server/tests/ControllerHelperContractsTest.php +1740 -0
  299. package/server/tests/ControllerSerializationContractsTest.php +141 -0
  300. package/server/tests/CoverageSummaryScriptTest.php +93 -0
  301. package/server/tests/CustomerContactIdentitySafetyTest.php +1 -6
  302. package/server/tests/CustomerEndpointTest.php +165 -1
  303. package/server/tests/DriverFilterExecutionTest.php +263 -0
  304. package/server/tests/DriverGeofenceProcessingTest.php +153 -0
  305. package/server/tests/DriverResourceSerializationTest.php +245 -0
  306. package/server/tests/DriverSchedulingTraitContractsTest.php +259 -0
  307. package/server/tests/EventContractsTest.php +1259 -0
  308. package/server/tests/ExceptionContractsTest.php +81 -0
  309. package/server/tests/ExpansionContractsTest.php +242 -0
  310. package/server/tests/ExportCoverageTest.php +116 -0
  311. package/server/tests/Feature/Http/Api/ContactControllerPhotoAndDeleteTest.php +199 -0
  312. package/server/tests/Feature/Http/Api/CustomerControllerHelperSeamsTest.php +831 -0
  313. package/server/tests/Feature/Http/Api/DeviceControllerContractsTest.php +347 -0
  314. package/server/tests/Feature/Http/Api/DeviceControllerCrudTest.php +176 -0
  315. package/server/tests/Feature/Http/Api/DriverControllerAuthFlowsTest.php +451 -0
  316. package/server/tests/Feature/Http/Api/DriverControllerHelpersTest.php +240 -0
  317. package/server/tests/Feature/Http/Api/DriverControllerLookupTest.php +186 -0
  318. package/server/tests/Feature/Http/Api/DriverControllerOrganizationsTest.php +112 -0
  319. package/server/tests/Feature/Http/Api/DriverControllerSessionHelpersTest.php +207 -0
  320. package/server/tests/Feature/Http/Api/DriverControllerSwitchOrgAndGeofenceTest.php +329 -0
  321. package/server/tests/Feature/Http/Api/DriverControllerTrackTest.php +383 -0
  322. package/server/tests/Feature/Http/Api/EntityControllerHelpersTest.php +150 -0
  323. package/server/tests/Feature/Http/Api/FuelTransactionControllerContractsTest.php +352 -0
  324. package/server/tests/Feature/Http/Api/GeofenceControllerContractsTest.php +364 -0
  325. package/server/tests/Feature/Http/Api/LabelControllerSubjectsTest.php +148 -0
  326. package/server/tests/Feature/Http/Api/OrderConfigControllerTest.php +112 -0
  327. package/server/tests/Feature/Http/Api/OrderControllerCreateTest.php +279 -0
  328. package/server/tests/Feature/Http/Api/OrderControllerIntegratedVendorTest.php +295 -0
  329. package/server/tests/Feature/Http/Api/OrderControllerLifecycleActionsTest.php +279 -0
  330. package/server/tests/Feature/Http/Api/OrderControllerLookupHelpersTest.php +207 -0
  331. package/server/tests/Feature/Http/Api/OrderControllerNearbyFiltersTest.php +282 -0
  332. package/server/tests/Feature/Http/Api/OrderControllerPersistenceHelpersTest.php +216 -0
  333. package/server/tests/Feature/Http/Api/OrderControllerQueryFiltersTest.php +184 -0
  334. package/server/tests/Feature/Http/Api/OrderControllerStartActivityTest.php +663 -0
  335. package/server/tests/Feature/Http/Api/PayloadControllerHelpersTest.php +134 -0
  336. package/server/tests/Feature/Http/Api/PlaceAndServiceQuoteSeamsTest.php +479 -0
  337. package/server/tests/Feature/Http/Api/PurchaseRateControllerHelpersTest.php +176 -0
  338. package/server/tests/Feature/Http/Api/PurchaseRateControllerOrderCreationTest.php +268 -0
  339. package/server/tests/Feature/Http/Api/SensorControllerCrudTest.php +239 -0
  340. package/server/tests/Feature/Http/Api/ServiceAreaControllerBorderAndSeamsTest.php +187 -0
  341. package/server/tests/Feature/Http/Api/ServiceQuoteControllerQueryTest.php +405 -0
  342. package/server/tests/Feature/Http/Api/ServiceQuoteControllerVendorBridgeTest.php +212 -0
  343. package/server/tests/Feature/Http/Api/ServiceRateControllerContractsTest.php +263 -0
  344. package/server/tests/Feature/Http/Api/SmallApiControllerHelpersTest.php +272 -0
  345. package/server/tests/Feature/Http/Api/TrackingNumberControllerHelpersTest.php +154 -0
  346. package/server/tests/Feature/Http/Api/TrackingStatusControllerHelpersTest.php +165 -0
  347. package/server/tests/Feature/Http/Api/VehicleControllerTrackingTest.php +483 -0
  348. package/server/tests/Feature/Http/Api/WorkOrderControllerContractsTest.php +326 -0
  349. package/server/tests/Feature/Http/Api/WorkOrderControllerHelpersTest.php +130 -0
  350. package/server/tests/Feature/Http/Api/ZoneControllerBordersAndSeamsTest.php +294 -0
  351. package/server/tests/Feature/Http/FleetOpsRouteRegistrationTest.php +189 -0
  352. package/server/tests/Feature/Http/Internal/AnalyticsControllerSeamsTest.php +53 -0
  353. package/server/tests/Feature/Http/Internal/ContactControllerContractsTest.php +240 -0
  354. package/server/tests/Feature/Http/Internal/ContactControllerCustomerGuardsTest.php +128 -0
  355. package/server/tests/Feature/Http/Internal/ContactControllerEndpointsTest.php +294 -0
  356. package/server/tests/Feature/Http/Internal/CustomerControllerCredentialsTest.php +196 -0
  357. package/server/tests/Feature/Http/Internal/DeviceControllerContractsTest.php +370 -0
  358. package/server/tests/Feature/Http/Internal/DeviceControllerExportAndFiltersTest.php +151 -0
  359. package/server/tests/Feature/Http/Internal/DriverControllerContractsTest.php +1109 -0
  360. package/server/tests/Feature/Http/Internal/DriverControllerCreateRecordTest.php +233 -0
  361. package/server/tests/Feature/Http/Internal/DriverControllerExistingUserAdoptionTest.php +710 -0
  362. package/server/tests/Feature/Http/Internal/DriverControllerHelpersTest.php +218 -0
  363. package/server/tests/Feature/Http/Internal/FleetAssignmentsAndTriggersTest.php +198 -0
  364. package/server/tests/Feature/Http/Internal/FleetOpsLookupControllerDbTest.php +90 -0
  365. package/server/tests/Feature/Http/Internal/HubControllerTest.php +206 -0
  366. package/server/tests/Feature/Http/Internal/IssueControllerContractsTest.php +404 -0
  367. package/server/tests/Feature/Http/Internal/IssueControllerExportImportTest.php +118 -0
  368. package/server/tests/Feature/Http/Internal/LiveControllerEndpointsTest.php +246 -0
  369. package/server/tests/Feature/Http/Internal/LiveControllerTest.php +778 -0
  370. package/server/tests/Feature/Http/Internal/MaintenanceScheduleControllerContractsTest.php +263 -0
  371. package/server/tests/Feature/Http/Internal/MaintenanceScheduleControllerSurfacesTest.php +214 -0
  372. package/server/tests/Feature/Http/Internal/MetricsControllerContractsTest.php +249 -0
  373. package/server/tests/Feature/Http/Internal/MetricsControllerHelpersTest.php +66 -0
  374. package/server/tests/Feature/Http/Internal/MorphControllerHelpersTest.php +125 -0
  375. package/server/tests/Feature/Http/Internal/NavigatorControllerHelpersTest.php +201 -0
  376. package/server/tests/Feature/Http/Internal/OrchestrationControllerContractsTest.php +928 -0
  377. package/server/tests/Feature/Http/Internal/OrchestrationControllerHelpersTest.php +214 -0
  378. package/server/tests/Feature/Http/Internal/OrchestrationControllerImportOrdersTest.php +340 -0
  379. package/server/tests/Feature/Http/Internal/OrderConfigControllerContractsTest.php +314 -0
  380. package/server/tests/Feature/Http/Internal/OrderControllerActivityFlowsTest.php +663 -0
  381. package/server/tests/Feature/Http/Internal/OrderControllerCapturePhotoTest.php +507 -0
  382. package/server/tests/Feature/Http/Internal/OrderControllerContractsTest.php +1742 -0
  383. package/server/tests/Feature/Http/Internal/OrderControllerCreateRecordTest.php +488 -0
  384. package/server/tests/Feature/Http/Internal/OrderControllerHelperSeamsTest.php +298 -0
  385. package/server/tests/Feature/Http/Internal/OrderControllerHelpersTest.php +267 -0
  386. package/server/tests/Feature/Http/Internal/OrderControllerImportFromFilesTest.php +179 -0
  387. package/server/tests/Feature/Http/Internal/OrderControllerUpstreamNotFoundTest.php +80 -0
  388. package/server/tests/Feature/Http/Internal/PaymentControllerPaymentsTest.php +154 -0
  389. package/server/tests/Feature/Http/Internal/PlaceControllerTest.php +252 -0
  390. package/server/tests/Feature/Http/Internal/PositionControllerReplayMetricsTest.php +163 -0
  391. package/server/tests/Feature/Http/Internal/ProofControllerContractsTest.php +219 -0
  392. package/server/tests/Feature/Http/Internal/SearchControllerEndpointTest.php +151 -0
  393. package/server/tests/Feature/Http/Internal/ServiceQuoteControllerHelpersTest.php +208 -0
  394. package/server/tests/Feature/Http/Internal/ServiceQuoteControllerQueryRecordTest.php +217 -0
  395. package/server/tests/Feature/Http/Internal/ServiceQuoteControllerVendorBridgeTest.php +239 -0
  396. package/server/tests/Feature/Http/Internal/ServiceQuotePreliminaryQueryTest.php +271 -0
  397. package/server/tests/Feature/Http/Internal/SettingControllerHelpersTest.php +133 -0
  398. package/server/tests/Feature/Http/Internal/SmallInternalControllersTest.php +180 -0
  399. package/server/tests/Feature/Http/Internal/TelematicControllerEndpointsTest.php +417 -0
  400. package/server/tests/Feature/Http/Internal/VehicleControllerEndpointsTest.php +361 -0
  401. package/server/tests/Feature/Http/Internal/VendorControllerEndpointsTest.php +203 -0
  402. package/server/tests/Feature/Http/Internal/WorkOrderAndConfigSurfacesTest.php +289 -0
  403. package/server/tests/Feature/Http/Internal/WorkOrderControllerContractsTest.php +199 -0
  404. package/server/tests/Feature/Http/TelematicWebhookIngestTest.php +343 -0
  405. package/server/tests/Feature/Http/Telematics/TelematicWebhookControllerProcessingTest.php +254 -0
  406. package/server/tests/FleetOpsSupportContractsTest.php +187 -0
  407. package/server/tests/FlespiProviderContractsTest.php +244 -0
  408. package/server/tests/FlowResourceTest.php +295 -0
  409. package/server/tests/FuelProviderConnectionControllerContractsTest.php +303 -0
  410. package/server/tests/FuelProviderImplementationTest.php +753 -0
  411. package/server/tests/FuelProviderResourceContractsTest.php +171 -0
  412. package/server/tests/FuelProviderTransactionControllerContractsTest.php +181 -0
  413. package/server/tests/GeofenceIntersectionServiceContractsTest.php +164 -0
  414. package/server/tests/HOSConstraintContractsTest.php +128 -0
  415. package/server/tests/HubAndGettingStartedContractsTest.php +158 -0
  416. package/server/tests/ImportContractsTest.php +191 -0
  417. package/server/tests/InternalCustomerControllerContractsTest.php +238 -0
  418. package/server/tests/InternalFleetControllerContractsTest.php +389 -0
  419. package/server/tests/InternalImportExportControllerContractsTest.php +289 -0
  420. package/server/tests/InternalMetricsControllerContractsTest.php +69 -0
  421. package/server/tests/InternalPlaceWorkOrderControllerContractsTest.php +207 -0
  422. package/server/tests/InternalServiceQuoteCheckoutControllerContractsTest.php +470 -0
  423. package/server/tests/InternalVendorControllerContractsTest.php +331 -0
  424. package/server/tests/InventoryTelemetryModelContractsTest.php +516 -0
  425. package/server/tests/IssueTimelineContractsTest.php +191 -0
  426. package/server/tests/LabelPdfRenderingTest.php +57 -0
  427. package/server/tests/LalamoveIntegrationContractsTest.php +167 -0
  428. package/server/tests/LiveOrderQueryTest.php +145 -18
  429. package/server/tests/LookupAndGeocoderControllerContractsTest.php +357 -0
  430. package/server/tests/MaintainableTraitContractsTest.php +245 -0
  431. package/server/tests/MaintenanceScheduleControllerContractsTest.php +101 -0
  432. package/server/tests/MaintenanceWarrantyContractsTest.php +237 -0
  433. package/server/tests/ManifestControllerContractsTest.php +310 -0
  434. package/server/tests/MetricsRegistryTest.php +596 -10
  435. package/server/tests/MiddlewareContractsTest.php +150 -0
  436. package/server/tests/ModelAccessorContractsTest.php +3201 -0
  437. package/server/tests/MorphControllerContractsTest.php +410 -0
  438. package/server/tests/NavigatorControllerContractsTest.php +206 -0
  439. package/server/tests/NotificationAndMailContractsTest.php +677 -0
  440. package/server/tests/ObserverContractsTest.php +1414 -0
  441. package/server/tests/OperationalAlgorithmContractsTest.php +852 -0
  442. package/server/tests/OperationsMonitorEndpointTest.php +2 -1
  443. package/server/tests/OrchestrationPayloadBuilderTest.php +87 -0
  444. package/server/tests/OrderActivityFlowRegressionTest.php +354 -7
  445. package/server/tests/OrderDispatchListenerContractsTest.php +577 -0
  446. package/server/tests/OrderFilterExecutionTest.php +244 -0
  447. package/server/tests/OrderQueuedClosureRegressionTest.php +2 -1
  448. package/server/tests/PaymentControllerContractsTest.php +199 -0
  449. package/server/tests/PointResolutionTest.php +54 -0
  450. package/server/tests/ProcessAllocationJobContractsTest.php +224 -0
  451. package/server/tests/ProofAndSensorControllerContractsTest.php +44 -0
  452. package/server/tests/ProviderContractsTest.php +409 -0
  453. package/server/tests/PublicApiControllerInputContractsTest.php +294 -0
  454. package/server/tests/QueueJobContractsTest.php +764 -0
  455. package/server/tests/ReportSchemaContractsTest.php +271 -0
  456. package/server/tests/RequestContractsTest.php +966 -0
  457. package/server/tests/RouteRegistrationExecutionTest.php +178 -0
  458. package/server/tests/RouteSequencingEngineTest.php +179 -0
  459. package/server/tests/RulesAndCastsTest.php +246 -0
  460. package/server/tests/SamsaraProviderContractsTest.php +272 -0
  461. package/server/tests/SearchControllerContractsTest.php +311 -0
  462. package/server/tests/ServiceRateRouteValidationTest.php +76 -0
  463. package/server/tests/SettingControllerContractsTest.php +410 -0
  464. package/server/tests/SmallControllerContractsTest.php +456 -0
  465. package/server/tests/SupportAnalyticsCustomerAuthContractsTest.php +221 -0
  466. package/server/tests/SupportJobAndAiCoverageTest.php +812 -0
  467. package/server/tests/SupportServiceContractsTest.php +287 -0
  468. package/server/tests/SupportValueObjectsTest.php +155 -0
  469. package/server/tests/TelematicControllerContractsTest.php +185 -0
  470. package/server/tests/TelematicProviderRegistryTest.php +167 -0
  471. package/server/tests/TelematicServiceHelperContractsTest.php +315 -0
  472. package/server/tests/TelematicWebhookControllerContractsTest.php +253 -0
  473. package/server/tests/TelematicsHardeningTest.php +642 -86
  474. package/server/tests/TrackingIntelligenceTest.php +644 -1
  475. package/server/tests/TrackingNumberTraitContractsTest.php +106 -0
  476. package/server/tests/Unit/Casts/SpatialCastBranchesTest.php +75 -0
  477. package/server/tests/Unit/Console/AssignCustomerRolesCommandTest.php +102 -0
  478. package/server/tests/Unit/Console/AssignDriverRolesCommandTest.php +113 -0
  479. package/server/tests/Unit/Console/Commands/FixLegacyOrderConfigsHelpersTest.php +108 -0
  480. package/server/tests/Unit/Console/Commands/ProcessOperationalAlertsCommandTest.php +265 -0
  481. package/server/tests/Unit/Console/Commands/ReplayVehicleLocationsCommandTest.php +320 -0
  482. package/server/tests/Unit/Console/Commands/SimulateGeofenceEventsCommandTest.php +207 -0
  483. package/server/tests/Unit/Console/FixCommandsAndMaintenanceControllerTest.php +256 -0
  484. package/server/tests/Unit/Console/FleetOpsCommandsTest.php +198 -0
  485. package/server/tests/Unit/Console/ReplayVehicleLocationsCommandTest.php +252 -0
  486. package/server/tests/Unit/Console/SendMaintenanceRemindersTest.php +212 -0
  487. package/server/tests/Unit/Console/SimulateGeofenceEventsCommandTest.php +232 -0
  488. package/server/tests/Unit/Console/SyncTelematicsCommandTest.php +136 -0
  489. package/server/tests/Unit/Constraints/HOSConstraintTest.php +158 -0
  490. package/server/tests/Unit/Events/EventModelRecordTest.php +93 -0
  491. package/server/tests/Unit/Events/OrderDispatchFailedTest.php +34 -0
  492. package/server/tests/Unit/Exports/ExportCollectionsTest.php +142 -0
  493. package/server/tests/Unit/Exports/OperationalExportMappingTest.php +651 -0
  494. package/server/tests/Unit/Exports/VehicleExportTest.php +284 -0
  495. package/server/tests/Unit/Flow/EventFiringTest.php +95 -0
  496. package/server/tests/Unit/Http/Api/QueryWithRequestSeamsTest.php +198 -0
  497. package/server/tests/Unit/Http/Api/SensorInputTest.php +95 -0
  498. package/server/tests/Unit/Http/Filter/DeviceFilterTest.php +199 -0
  499. package/server/tests/Unit/Http/Filter/EmptyValueGuardsTest.php +66 -0
  500. package/server/tests/Unit/Http/Filter/FilterDateRangesTest.php +72 -0
  501. package/server/tests/Unit/Http/Filter/FuelProviderTransactionFilterTest.php +172 -0
  502. package/server/tests/Unit/Http/Filter/InternalRelationUuidLookupTest.php +135 -0
  503. package/server/tests/Unit/Http/Filter/IssueFilterTest.php +129 -0
  504. package/server/tests/Unit/Http/Filter/PartFilterTest.php +173 -0
  505. package/server/tests/Unit/Http/Internal/ControllerDelegationSeamsTest.php +136 -0
  506. package/server/tests/Unit/Http/Internal/ControllerExcelSeamsTest.php +89 -0
  507. package/server/tests/Unit/Http/Middleware/SetupDriverSessionTest.php +32 -0
  508. package/server/tests/Unit/Http/Requests/CreateFuelReportRequestTest.php +47 -0
  509. package/server/tests/Unit/Http/Requests/FleetActionRequestTest.php +80 -0
  510. package/server/tests/Unit/Http/Requests/RequestAuthorizationTest.php +50 -0
  511. package/server/tests/Unit/Http/Resources/CustomerResourceTest.php +108 -0
  512. package/server/tests/Unit/Http/Resources/EntityCustomerTypeTest.php +35 -0
  513. package/server/tests/Unit/Http/Resources/FleetResourceTest.php +102 -0
  514. package/server/tests/Unit/Http/Resources/IndexOrderResourceTest.php +210 -0
  515. package/server/tests/Unit/Http/Resources/IndexVehicleResourceTest.php +194 -0
  516. package/server/tests/Unit/Http/Resources/MaintenanceResourcesTest.php +182 -0
  517. package/server/tests/Unit/Http/Resources/OrderAndDriverResourceTest.php +121 -0
  518. package/server/tests/Unit/Http/Resources/OrderConfigResourceTest.php +47 -0
  519. package/server/tests/Unit/Http/Resources/PayloadResourceTest.php +111 -0
  520. package/server/tests/Unit/Http/Resources/RelationResourceFallbacksTest.php +32 -0
  521. package/server/tests/Unit/Http/Resources/ResourceRelationResolutionTest.php +55 -0
  522. package/server/tests/Unit/Http/Resources/TrackingNumberResourceTest.php +174 -0
  523. package/server/tests/Unit/Http/Resources/WaypointResourceTest.php +295 -0
  524. package/server/tests/Unit/Http/Resources/WorkOrderResourceTest.php +164 -0
  525. package/server/tests/Unit/Imports/ImportDelegationTest.php +151 -0
  526. package/server/tests/Unit/Integrations/Lalamove/LalamoveDeliveryStopTest.php +79 -0
  527. package/server/tests/Unit/Integrations/Lalamove/LalamoveLifecycleTest.php +211 -0
  528. package/server/tests/Unit/Integrations/Lalamove/LalamoveQuoteAndServiceOrderTest.php +381 -0
  529. package/server/tests/Unit/Integrations/Lalamove/LalamoveServiceTypeTest.php +51 -0
  530. package/server/tests/Unit/Integrations/LalamoveQuotationTest.php +194 -0
  531. package/server/tests/Unit/Integrations/LalamoveResponseHandlingTest.php +58 -0
  532. package/server/tests/Unit/Jobs/GeofenceDwellAndBulkNotifyTest.php +183 -0
  533. package/server/tests/Unit/Jobs/ReplayPositionsTest.php +57 -0
  534. package/server/tests/Unit/Jobs/SimulateWaypointReachedTest.php +92 -0
  535. package/server/tests/Unit/Listeners/HandleGeofenceEnteredTest.php +256 -0
  536. package/server/tests/Unit/Listeners/HandleOrderDispatchFailedListenerTest.php +101 -0
  537. package/server/tests/Unit/Listeners/HandleOrderDispatchedConcreteTest.php +203 -0
  538. package/server/tests/Unit/Listeners/HandleOrderDispatchedHelpersTest.php +186 -0
  539. package/server/tests/Unit/Listeners/HandleUserRemovedFromCompanyTest.php +65 -0
  540. package/server/tests/Unit/Listeners/ListenerDelegationSeamsTest.php +83 -0
  541. package/server/tests/Unit/Models/AssetTest.php +469 -0
  542. package/server/tests/Unit/Models/ContactCustomerUserTest.php +370 -0
  543. package/server/tests/Unit/Models/ContactTest.php +577 -0
  544. package/server/tests/Unit/Models/DeviceEventTest.php +481 -0
  545. package/server/tests/Unit/Models/DeviceLastPositionDefaultTest.php +128 -0
  546. package/server/tests/Unit/Models/DriverModelHelpersTest.php +268 -0
  547. package/server/tests/Unit/Models/DriverTest.php +401 -0
  548. package/server/tests/Unit/Models/EntityTest.php +171 -0
  549. package/server/tests/Unit/Models/EquipmentTest.php +434 -0
  550. package/server/tests/Unit/Models/FleetTest.php +153 -0
  551. package/server/tests/Unit/Models/FuelProviderTransactionTest.php +82 -0
  552. package/server/tests/Unit/Models/FuelReportImportAndLabelsTest.php +193 -0
  553. package/server/tests/Unit/Models/ImportRowFallbackSeamsTest.php +100 -0
  554. package/server/tests/Unit/Models/IntegratedVendorLifecycleTest.php +203 -0
  555. package/server/tests/Unit/Models/IntegratedVendorTest.php +135 -0
  556. package/server/tests/Unit/Models/IssueTest.php +160 -0
  557. package/server/tests/Unit/Models/MaintenanceScheduleTest.php +319 -0
  558. package/server/tests/Unit/Models/MaintenanceTest.php +277 -0
  559. package/server/tests/Unit/Models/MaintenanceWorkOrderImportTest.php +161 -0
  560. package/server/tests/Unit/Models/ManifestStopTest.php +121 -0
  561. package/server/tests/Unit/Models/ManifestTest.php +163 -0
  562. package/server/tests/Unit/Models/ModelLookupFallbackSeamsTest.php +149 -0
  563. package/server/tests/Unit/Models/OrderConfigTest.php +341 -0
  564. package/server/tests/Unit/Models/OrderDynamicContractsTest.php +190 -0
  565. package/server/tests/Unit/Models/OrderPayloadConfigAndDistanceTest.php +426 -0
  566. package/server/tests/Unit/Models/OrderPayloadRouteTest.php +227 -0
  567. package/server/tests/Unit/Models/OrderPurchaseAndDriversTest.php +188 -0
  568. package/server/tests/Unit/Models/OrderTest.php +917 -0
  569. package/server/tests/Unit/Models/PartTest.php +399 -0
  570. package/server/tests/Unit/Models/PayloadTest.php +710 -0
  571. package/server/tests/Unit/Models/PayloadWaypointsAndEntitiesTest.php +317 -0
  572. package/server/tests/Unit/Models/PlaceCreationAndImportTest.php +384 -0
  573. package/server/tests/Unit/Models/PlaceGeocodingResultsTest.php +253 -0
  574. package/server/tests/Unit/Models/PlaceSharedAndGeocodingTest.php +271 -0
  575. package/server/tests/Unit/Models/PlaceTest.php +589 -0
  576. package/server/tests/Unit/Models/PositionTest.php +49 -0
  577. package/server/tests/Unit/Models/RouteTest.php +55 -0
  578. package/server/tests/Unit/Models/SensorReadingsTest.php +168 -0
  579. package/server/tests/Unit/Models/SensorTest.php +284 -0
  580. package/server/tests/Unit/Models/ServiceAreaGeometryTest.php +129 -0
  581. package/server/tests/Unit/Models/ServiceAreaTest.php +125 -0
  582. package/server/tests/Unit/Models/ServiceQuoteTest.php +617 -0
  583. package/server/tests/Unit/Models/ServiceRateFeeTest.php +73 -0
  584. package/server/tests/Unit/Models/ServiceRatePersistenceAndServicabilityTest.php +428 -0
  585. package/server/tests/Unit/Models/ServiceRateTest.php +533 -0
  586. package/server/tests/Unit/Models/SmallModelSurfacesTest.php +294 -0
  587. package/server/tests/Unit/Models/TrackingNumberTest.php +199 -0
  588. package/server/tests/Unit/Models/TrackingStatusTest.php +131 -0
  589. package/server/tests/Unit/Models/VehicleDeviceTest.php +115 -0
  590. package/server/tests/Unit/Models/VehiclePositionsAndImportTest.php +220 -0
  591. package/server/tests/Unit/Models/VehicleTest.php +266 -0
  592. package/server/tests/Unit/Models/VendorRelationsAndImportTest.php +107 -0
  593. package/server/tests/Unit/Models/WarrantyTest.php +187 -0
  594. package/server/tests/Unit/Models/WaypointTest.php +366 -0
  595. package/server/tests/Unit/Models/WorkOrderTest.php +272 -0
  596. package/server/tests/Unit/Models/ZoneTest.php +83 -0
  597. package/server/tests/Unit/Notifications/MonitoringNotificationsTest.php +136 -0
  598. package/server/tests/Unit/Notifications/OrderAssignedChannelsTest.php +53 -0
  599. package/server/tests/Unit/Notifications/OrderDispatchedChannelsTest.php +81 -0
  600. package/server/tests/Unit/Notifications/OrderFailedChannelsTest.php +73 -0
  601. package/server/tests/Unit/Notifications/OrderPingChannelsTest.php +69 -0
  602. package/server/tests/Unit/Notifications/TerminalOrderNotificationsTest.php +185 -0
  603. package/server/tests/Unit/Observers/FleetOpsCompanyUserAndServiceAreaObserversTest.php +133 -0
  604. package/server/tests/Unit/Observers/ObserverHelperExecutionTest.php +135 -0
  605. package/server/tests/Unit/Observers/ObserverListenerSeamsTest.php +267 -0
  606. package/server/tests/Unit/Observers/PurchaseRateObserverAndOrderJobsTest.php +169 -0
  607. package/server/tests/Unit/Orchestration/Engines/DriverAssignmentEngineTest.php +393 -0
  608. package/server/tests/Unit/Orchestration/Engines/VroomOrchestrationEngineLifecycleTest.php +397 -0
  609. package/server/tests/Unit/Orchestration/OrchestrationEngineRegistryTest.php +45 -0
  610. package/server/tests/Unit/Orchestration/VroomEngineTransportAndSettingsTest.php +253 -0
  611. package/server/tests/Unit/Providers/FleetOpsAiRegistrationTest.php +59 -0
  612. package/server/tests/Unit/Rules/ResolvableVehicleTest.php +85 -0
  613. package/server/tests/Unit/Support/Ai/AssetStatusCapabilityQueriesTest.php +120 -0
  614. package/server/tests/Unit/Support/Ai/Capabilities/CreateOrderPreviewCapabilityTest.php +385 -0
  615. package/server/tests/Unit/Support/Ai/Capabilities/OrderInsightsCapabilityTest.php +226 -0
  616. package/server/tests/Unit/Support/Ai/Capabilities/SearchResourcesCapabilityTest.php +237 -0
  617. package/server/tests/Unit/Support/AiCapabilityPermissionsTest.php +124 -0
  618. package/server/tests/Unit/Support/AlgoEdgeBranchesTest.php +24 -0
  619. package/server/tests/Unit/Support/Analytics/GeofenceViolationsTest.php +109 -0
  620. package/server/tests/Unit/Support/Analytics/LiveFleetTest.php +205 -0
  621. package/server/tests/Unit/Support/Analytics/MaintenanceOverviewTest.php +236 -0
  622. package/server/tests/Unit/Support/Analytics/OnTimeDeliveryAndTopDriversTest.php +250 -0
  623. package/server/tests/Unit/Support/CreateOrderPreviewDraftingTest.php +235 -0
  624. package/server/tests/Unit/Support/CustomerAuthTest.php +132 -0
  625. package/server/tests/Unit/Support/FuelEfficiencyAndCanceledHandlersTest.php +164 -0
  626. package/server/tests/Unit/Support/FuelProviderRegistryResolutionTest.php +51 -0
  627. package/server/tests/Unit/Support/FuelProviderServiceMatchingTest.php +280 -0
  628. package/server/tests/Unit/Support/GeocodingInjectedClientTest.php +268 -0
  629. package/server/tests/Unit/Support/GeocodingLocateTest.php +32 -0
  630. package/server/tests/Unit/Support/GeofenceIntersectionServiceTest.php +188 -0
  631. package/server/tests/Unit/Support/GettingStartedTest.php +164 -0
  632. package/server/tests/Unit/Support/GuardReturnSeamsTest.php +172 -0
  633. package/server/tests/Unit/Support/IntegratedVendorsResolverTest.php +250 -0
  634. package/server/tests/Unit/Support/IssuesInsightsAndAllocationJobTest.php +156 -0
  635. package/server/tests/Unit/Support/MagicAccessorSeamsTest.php +54 -0
  636. package/server/tests/Unit/Support/MaintainableAndOperationalAlertsTest.php +215 -0
  637. package/server/tests/Unit/Support/Metrics/AvgOrderValueMetricTest.php +308 -0
  638. package/server/tests/Unit/Support/Metrics/CountMetricsTest.php +280 -0
  639. package/server/tests/Unit/Support/Metrics/FuelCostsMetricTest.php +102 -0
  640. package/server/tests/Unit/Support/Metrics/MetricQuerySeamsTest.php +129 -0
  641. package/server/tests/Unit/Support/Metrics/OrdersScheduledMetricTest.php +146 -0
  642. package/server/tests/Unit/Support/MoreQuerySeamsTest.php +410 -0
  643. package/server/tests/Unit/Support/OperationalQueryDistributionTest.php +152 -0
  644. package/server/tests/Unit/Support/OperationsPulseTest.php +130 -0
  645. package/server/tests/Unit/Support/OptimizeOrderRouteCapabilityTest.php +147 -0
  646. package/server/tests/Unit/Support/OrchestrationPayloadBuilderTest.php +135 -0
  647. package/server/tests/Unit/Support/OrchestrationRouteAndVehicleTasksTest.php +254 -0
  648. package/server/tests/Unit/Support/OsrmProofAndIssueFilterTest.php +247 -0
  649. package/server/tests/Unit/Support/PetroAppFuelProviderTest.php +165 -0
  650. package/server/tests/Unit/Support/PlaceSearchRankingTest.php +191 -0
  651. package/server/tests/Unit/Support/QuerySeamsTest.php +309 -0
  652. package/server/tests/Unit/Support/ResolvesOrderServiceStopsDbTest.php +303 -0
  653. package/server/tests/Unit/Support/ResolvesOrderServiceStopsTest.php +382 -0
  654. package/server/tests/Unit/Support/SkipAndFallbackGuardsTest.php +70 -0
  655. package/server/tests/Unit/Support/TelematicCredentialResolutionTest.php +31 -0
  656. package/server/tests/Unit/Support/TelematicServiceTest.php +256 -0
  657. package/server/tests/Unit/Support/Telematics/Providers/AbstractProviderTest.php +154 -0
  658. package/server/tests/Unit/Support/Telematics/Providers/AfaqyProviderTest.php +191 -0
  659. package/server/tests/Unit/Support/Telematics/Providers/AfaqyProviderTransportTest.php +138 -0
  660. package/server/tests/Unit/Support/Telematics/Providers/GeotabProviderTest.php +329 -0
  661. package/server/tests/Unit/Support/Telematics/Providers/ProviderTransportSeamsTest.php +133 -0
  662. package/server/tests/Unit/Support/Telematics/Providers/SafeeProviderTest.php +487 -0
  663. package/server/tests/Unit/Support/Telematics/TelematicProviderRegistryTest.php +39 -0
  664. package/server/tests/Unit/Support/Telematics/TelematicServiceLifecycleTest.php +711 -0
  665. package/server/tests/Unit/Support/Telematics/TelematicServiceTelemetryTest.php +364 -0
  666. package/server/tests/Unit/Support/UtilsAdditionalTest.php +256 -0
  667. package/server/tests/Unit/Support/UtilsGeoMatrixAndVendorTest.php +382 -0
  668. package/server/tests/Unit/Tracking/TrackingContextTest.php +114 -0
  669. package/server/tests/Unit/Tracking/TrackingIntelligenceAndContextTest.php +477 -0
  670. package/server/tests/Unit/Tracking/TrackingProviderManagerFallbacksTest.php +208 -0
  671. package/server/tests/Unit/Traits/HasTrackingNumberTest.php +303 -0
  672. package/server/tests/Unit/Traits/PayloadAccessorsTest.php +150 -0
  673. package/server/tests/UtilsContractsTest.php +244 -0
  674. package/server/tests/VehicleControllerHelperContractsTest.php +488 -0
  675. package/server/tests/VehicleDataParsingTest.php +45 -0
  676. package/server/tests/VehicleResourceContractsTest.php +313 -0
  677. package/translations/bg-bg.yaml +2 -0
  678. package/translations/en-us.yaml +2 -0
  679. package/translations/es-pa.yaml +2 -0
  680. package/translations/fr-fr.yaml +2 -0
  681. package/translations/mn-mn.yaml +2 -0
  682. package/translations/pt-br.yaml +2 -0
  683. package/translations/ru-ru.yaml +2 -0
  684. package/server/tests/DeviceFilterTest.php +0 -44
  685. package/server/tests/LiveControllerViewportTest.php +0 -52
@@ -36,7 +36,7 @@ class NotifyDriverOnShiftChange implements ShouldQueue
36
36
 
37
37
  // Load the parent schedule to find the subject (driver)
38
38
  /** @var Schedule|null $schedule */
39
- $schedule = $scheduleItem->schedule()->with('subject')->first();
39
+ $schedule = $this->getSchedule($scheduleItem);
40
40
  if (!$schedule) {
41
41
  return;
42
42
  }
@@ -48,16 +48,36 @@ class NotifyDriverOnShiftChange implements ShouldQueue
48
48
  }
49
49
 
50
50
  // Check the company-level scheduling setting
51
- $settings = Setting::lookupFromCompany('fleet-ops.scheduling-settings', []);
51
+ $settings = $this->getSchedulingSettings();
52
52
  $shouldNotify = (bool) data_get($settings, 'notify_drivers_on_shift_change', false);
53
53
  if (!$shouldNotify) {
54
54
  return;
55
55
  }
56
56
 
57
57
  // Determine if this is a new shift or an update
58
- $isNew = $event instanceof \Fleetbase\Events\ScheduleItemCreated;
58
+ $isNew = $this->isCreatedEvent($event);
59
59
 
60
60
  // Send the notification to the driver
61
- $subject->notify(new DriverShiftChanged($scheduleItem, $isNew));
61
+ $this->notifyDriver($subject, new DriverShiftChanged($scheduleItem, $isNew));
62
+ }
63
+
64
+ protected function getSchedule(ScheduleItem $scheduleItem): ?Schedule
65
+ {
66
+ return $scheduleItem->schedule()->with('subject')->first();
67
+ }
68
+
69
+ protected function getSchedulingSettings(): array
70
+ {
71
+ return Setting::lookupFromCompany('fleet-ops.scheduling-settings', []);
72
+ }
73
+
74
+ protected function isCreatedEvent(object $event): bool
75
+ {
76
+ return $event instanceof \Fleetbase\Events\ScheduleItemCreated;
77
+ }
78
+
79
+ protected function notifyDriver(Driver $driver, DriverShiftChanged $notification): void
80
+ {
81
+ $driver->notify($notification);
62
82
  }
63
83
  }
@@ -32,29 +32,34 @@ class NotifyOrderEvent implements ShouldQueue
32
32
  // Send a notification for order events
33
33
  if ($event instanceof \Fleetbase\FleetOps\Events\OrderCanceled) {
34
34
  $reason = $event->activity ? $event->activity->get('details') : '';
35
- NotificationRegistry::notify(OrderCanceled::class, $order, $reason, $event->waypoint);
35
+ $this->notify(OrderCanceled::class, $order, $reason, $event->waypoint);
36
36
  }
37
37
 
38
38
  if ($event instanceof \Fleetbase\FleetOps\Events\OrderCompleted) {
39
- NotificationRegistry::notify(OrderCompleted::class, $order, $event->waypoint);
39
+ $this->notify(OrderCompleted::class, $order, $event->waypoint);
40
40
  }
41
41
 
42
42
  if ($event instanceof \Fleetbase\FleetOps\Events\OrderFailed) {
43
43
  $reason = $event->activity ? $event->activity->get('details') : '';
44
- NotificationRegistry::notify(OrderFailed::class, $order, $reason, $event->waypoint);
44
+ $this->notify(OrderFailed::class, $order, $reason, $event->waypoint);
45
45
  }
46
46
 
47
47
  if ($event instanceof \Fleetbase\FleetOps\Events\OrderDispatchFailed) {
48
- NotificationRegistry::notify(OrderDispatchFailed::class, $order);
48
+ $this->notify(OrderDispatchFailed::class, $order);
49
49
  }
50
50
 
51
51
  if ($event instanceof \Fleetbase\FleetOps\Events\OrderDispatched) {
52
- NotificationRegistry::notify(OrderDispatched::class, $order, $event->waypoint);
52
+ $this->notify(OrderDispatched::class, $order, $event->waypoint);
53
53
  }
54
54
 
55
55
  if ($event instanceof \Fleetbase\FleetOps\Events\OrderDriverAssigned) {
56
- NotificationRegistry::notify(OrderAssigned::class, $order);
56
+ $this->notify(OrderAssigned::class, $order);
57
57
  }
58
58
  }
59
59
  }
60
+
61
+ protected function notify(string $notificationClass, mixed ...$arguments): void
62
+ {
63
+ NotificationRegistry::notify($notificationClass, ...$arguments);
64
+ }
60
65
  }
@@ -348,14 +348,13 @@ class Contact extends Model
348
348
  $existingUserContact = Contact::where(['user_uuid' => $existingUser->uuid, 'company_uuid' => $contact->company_uuid])->whereHas('user')->first();
349
349
  if ($existingUserContact) {
350
350
  throw new UserAlreadyExistsException('User already exists, try to assigning the user to this contact.', $existingUser);
351
- } else {
352
- // Assign the user to this contact instead
353
- $contact->setAttribute('user_uuid', $existingUser->uuid);
354
- if ($update) {
355
- $contact->update(['user_uuid' => $existingUser->uuid]);
356
- }
357
- $contact->setRelation('user', $existingUser);
358
351
  }
352
+ // Assign the user to this contact instead
353
+ $contact->setAttribute('user_uuid', $existingUser->uuid);
354
+ if ($update) {
355
+ $contact->update(['user_uuid' => $existingUser->uuid]);
356
+ }
357
+ $contact->setRelation('user', $existingUser);
359
358
 
360
359
  return $existingUser;
361
360
  }
@@ -175,6 +175,24 @@ class Device extends Model
175
175
  'attachable_type' => PolymorphicType::class,
176
176
  ];
177
177
 
178
+ /**
179
+ * Bootstrap the model.
180
+ *
181
+ * Devices require a non-null spatial `last_position` (the column is NOT NULL
182
+ * to support its spatial index), so default it to POINT(0,0) on create when
183
+ * the caller hasn't provided a position.
184
+ */
185
+ protected static function boot()
186
+ {
187
+ parent::boot();
188
+
189
+ static::creating(function (self $device) {
190
+ if (empty($device->last_position)) {
191
+ $device->last_position = new SpatialPoint(0, 0);
192
+ }
193
+ });
194
+ }
195
+
178
196
  /**
179
197
  * Properties which activity needs to be logged.
180
198
  *
@@ -345,9 +363,9 @@ class Device extends Model
345
363
  return 'recently_offline';
346
364
  } elseif ($minutesOffline <= 1440) { // 24 hours
347
365
  return 'offline';
348
- } else {
349
- return 'long_offline';
350
366
  }
367
+
368
+ return 'long_offline';
351
369
  }
352
370
 
353
371
  /**
@@ -510,12 +528,17 @@ class Device extends Model
510
528
  */
511
529
  public function getRecentEvents(int $limit = 10)
512
530
  {
513
- return $this->events()
531
+ return $this->recentEventsQuery()
514
532
  ->orderBy('created_at', 'desc')
515
533
  ->limit($limit)
516
534
  ->get();
517
535
  }
518
536
 
537
+ protected function recentEventsQuery()
538
+ {
539
+ return $this->events();
540
+ }
541
+
519
542
  /**
520
543
  * Creates a new position for the vehicle.
521
544
  */
@@ -41,7 +41,6 @@ use Spatie\Activitylog\Traits\CausesActivity;
41
41
  use Spatie\Activitylog\Traits\LogsActivity;
42
42
  use Spatie\Sluggable\HasSlug;
43
43
  use Spatie\Sluggable\SlugOptions;
44
- use WebSocket\Message\Ping;
45
44
 
46
45
  class Driver extends Model
47
46
  {
@@ -329,11 +328,6 @@ class Driver extends Model
329
328
  return $this->hasMany(Order::class, 'driver_assigned_uuid')->without(['driver']);
330
329
  }
331
330
 
332
- public function pings(): HasMany
333
- {
334
- return $this->hasMany(Ping::class);
335
- }
336
-
337
331
  public function positions(): HasMany
338
332
  {
339
333
  return $this->hasMany(Position::class, 'subject_uuid');
@@ -414,10 +414,10 @@ class Entity extends Model
414
414
  }
415
415
  }
416
416
 
417
- // confirm destination_uuid is indeed a place record
418
- if (isset($attributes['destination_uuid']) && Place::where('uuid', $attributes['destination_uuid'])->doesntExist()) {
419
- // search waypoints for search_uuid if any
420
- $destination = Place::where('meta->search_uuid', $attributes['destination_uuid'])->first();
417
+ // confirm the resolved destination is indeed a place record — temp
418
+ // search uuids from imports resolve through place metadata
419
+ if ($this->destination_uuid === null && Str::isUuid($destinationKey)) {
420
+ $destination = Place::where('meta->search_uuid', $destinationKey)->first();
421
421
 
422
422
  if ($destination instanceof Place) {
423
423
  $this->destination_uuid = $destination->uuid;
@@ -243,7 +243,7 @@ class Equipment extends Model
243
243
  $this->attributes['equipable_type'] = match ($type) {
244
244
  'fleet-ops:vehicle', 'vehicle' => Utils::getMutationType('fleet-ops:vehicle'),
245
245
  'fleet-ops:driver', 'driver' => Utils::getMutationType('fleet-ops:driver'),
246
- default => $type,
246
+ default => $type,
247
247
  };
248
248
  }
249
249
 
@@ -213,10 +213,14 @@ class FuelReport extends Model
213
213
  $latitude = Utils::or($row, ['latitude', 'lat']);
214
214
  $longitude = Utils::or($row, ['longitude', 'lng', 'long']);
215
215
 
216
+ $locationValue = data_get($row, 'location');
216
217
  if ($latitude && $longitude) {
217
218
  $location = new Point($latitude, $longitude);
219
+ } elseif (filled($locationValue)) {
220
+ $location = Utils::getPointFromMixed(Utils::arrayFrom($locationValue));
218
221
  } else {
219
- $location = Utils::getPointFromMixed(Utils::arrayFrom(data_get($row, 'location')));
222
+ // Rows without any location column fall back to the empty point below
223
+ $location = null;
220
224
  }
221
225
 
222
226
  // Resolve relations
@@ -117,7 +117,7 @@ class IntegratedVendor extends Model
117
117
  function ($model) {
118
118
  $provider = $model->provider();
119
119
 
120
- if ($provider && method_exists($provider, 'onUpdated')) {
120
+ if ($provider && method_exists($provider, 'callback')) {
121
121
  $provider->callback('onUpdated');
122
122
  }
123
123
  }
@@ -127,7 +127,7 @@ class IntegratedVendor extends Model
127
127
  function ($model) {
128
128
  $provider = $model->provider();
129
129
 
130
- if ($provider && method_exists($provider, 'onDeleted')) {
130
+ if ($provider && method_exists($provider, 'callback')) {
131
131
  $provider->callback('onDeleted');
132
132
  }
133
133
  }
@@ -331,10 +331,14 @@ class Issue extends Model
331
331
  $latitude = Utils::or($row, ['latitude', 'lat']);
332
332
  $longitude = Utils::or($row, ['longitude', 'lng', 'long']);
333
333
 
334
+ $locationValue = data_get($row, 'location');
334
335
  if ($latitude && $longitude) {
335
336
  $location = new Point($latitude, $longitude);
337
+ } elseif (filled($locationValue)) {
338
+ $location = Utils::getPointFromMixed(Utils::arrayFrom($locationValue));
336
339
  } else {
337
- $location = Utils::getPointFromMixed(Utils::arrayFrom(data_get($row, 'location')));
340
+ // Rows without any location column fall back to the empty point below
341
+ $location = null;
338
342
  }
339
343
 
340
344
  // Create issue
@@ -315,17 +315,12 @@ class MaintenanceSchedule extends Model
315
315
 
316
316
  // Attempt to resolve the subject (vehicle or equipment) by identifier
317
317
  if ($vehicleName) {
318
- $vehicle = Vehicle::findByName($vehicleName);
318
+ $vehicle = static::findImportVehicle($vehicleName);
319
319
  if ($vehicle) {
320
320
  $schedule->subject_type = Vehicle::class;
321
321
  $schedule->subject_uuid = $vehicle->uuid;
322
322
  } else {
323
- $equipment = Equipment::where('company_uuid', session('company'))
324
- ->where(function ($q) use ($vehicleName) {
325
- $q->where('name', 'like', '%' . $vehicleName . '%')
326
- ->orWhere('public_id', $vehicleName)
327
- ->orWhere('serial_number', $vehicleName);
328
- })->first();
323
+ $equipment = static::findImportEquipment($vehicleName);
329
324
  if ($equipment) {
330
325
  $schedule->subject_type = Equipment::class;
331
326
  $schedule->subject_uuid = $equipment->uuid;
@@ -335,9 +330,7 @@ class MaintenanceSchedule extends Model
335
330
 
336
331
  // Attempt to resolve default assignee (vendor) by name
337
332
  if ($vendorName) {
338
- $vendor = Vendor::where('company_uuid', session('company'))
339
- ->where('name', 'like', '%' . $vendorName . '%')
340
- ->first();
333
+ $vendor = static::findImportVendor($vendorName);
341
334
  if ($vendor) {
342
335
  $schedule->default_assignee_type = Vendor::class;
343
336
  $schedule->default_assignee_uuid = $vendor->uuid;
@@ -350,4 +343,26 @@ class MaintenanceSchedule extends Model
350
343
 
351
344
  return $schedule;
352
345
  }
346
+
347
+ protected static function findImportVehicle(string $vehicleName): ?Vehicle
348
+ {
349
+ return Vehicle::findByName($vehicleName);
350
+ }
351
+
352
+ protected static function findImportEquipment(string $vehicleName): ?Equipment
353
+ {
354
+ return Equipment::where('company_uuid', session('company'))
355
+ ->where(function ($q) use ($vehicleName) {
356
+ $q->where('name', 'like', '%' . $vehicleName . '%')
357
+ ->orWhere('public_id', $vehicleName)
358
+ ->orWhere('serial_number', $vehicleName);
359
+ })->first();
360
+ }
361
+
362
+ protected static function findImportVendor(string $vendorName): ?Vendor
363
+ {
364
+ return Vendor::where('company_uuid', session('company'))
365
+ ->where('name', 'like', '%' . $vendorName . '%')
366
+ ->first();
367
+ }
353
368
  }
@@ -932,9 +932,15 @@ class Order extends Model
932
932
 
933
933
  $result = Payload::insert($attributes);
934
934
 
935
+ // Unreachable: Laravel's connector forces PDO::ERRMODE_EXCEPTION and
936
+ // nothing here overrides it, so the insert either succeeds or throws —
937
+ // it never returns false. The fallback itself is sound (insertPayload
938
+ // regenerates the uuid and public id before delegating), just unreached.
939
+ // @codeCoverageIgnoreStart
935
940
  if (!$result) {
936
941
  return $this->createPayload($attributes);
937
942
  }
943
+ // @codeCoverageIgnoreEnd
938
944
 
939
945
  $payload = Payload::find($uuid);
940
946
 
@@ -1003,14 +1009,14 @@ class Order extends Model
1003
1009
  *
1004
1010
  * @return self the Order instance for method chaining
1005
1011
  */
1006
- public function setRoute(?array $attributes = [])
1012
+ public function setRoute(Route|array|null $attributes = [])
1007
1013
  {
1008
1014
  if (!$attributes) {
1009
1015
  return $this;
1010
1016
  }
1011
1017
 
1012
1018
  if ($attributes instanceof Route) {
1013
- $attributes->set('order_uuid', $this->order_uuid);
1019
+ $attributes->setAttribute('order_uuid', $this->uuid);
1014
1020
  $attributes->save();
1015
1021
 
1016
1022
  return $this;
@@ -1243,7 +1249,7 @@ class Order extends Model
1243
1249
  $min = Carbon::now()->subMinutes($precision);
1244
1250
  $max = Carbon::now()->addMinutes($precision);
1245
1251
 
1246
- return !$this->dispatched && Carbon::fromString($this->scheduled_at)->between($min, $max);
1252
+ return !$this->dispatched && Carbon::parse($this->scheduled_at)->between($min, $max);
1247
1253
  }
1248
1254
 
1249
1255
  /**
@@ -1734,10 +1740,16 @@ class Order extends Model
1734
1740
  }
1735
1741
 
1736
1742
  // Fetch distance/time — bail early if external call fails
1743
+ //
1744
+ // Unreachable: `getDrivingDistanceAndTime()` is typed `: DistanceMatrix`
1745
+ // and every provider path casts both fields to float before constructing
1746
+ // it, so neither the null check nor the isset check can fail.
1737
1747
  $matrix = Utils::getDrivingDistanceAndTime($origin, $destination, $options);
1748
+ // @codeCoverageIgnoreStart
1738
1749
  if (!$matrix || !isset($matrix->distance, $matrix->time)) {
1739
1750
  return $this;
1740
1751
  }
1752
+ // @codeCoverageIgnoreEnd
1741
1753
 
1742
1754
  // Only update if values changed to prevent redundant writes
1743
1755
  if ($this->distance !== $matrix->distance || $this->time !== $matrix->time) {
@@ -1777,9 +1789,9 @@ class Order extends Model
1777
1789
  * This function first attempts to load the 'orderConfig' relationship.
1778
1790
  * If 'orderConfig' is already loaded and is an instance of OrderConfig,
1779
1791
  * it returns this instance. If not, and if the 'order_config_uuid' is
1780
- * a valid UUID, it attempts to retrieve the OrderConfig by this UUID,
1781
- * including any trashed instances. If none of these conditions are met,
1782
- * it returns null.
1792
+ * The orderConfig relation already includes trashed instances, so a
1793
+ * soft-deleted config still resolves. Otherwise the company's default
1794
+ * transport config is used, and null is returned when none can be made.
1783
1795
  *
1784
1796
  * @return OrderConfig|null the OrderConfig associated with this order, or null if not found
1785
1797
  *
@@ -1795,15 +1807,6 @@ class Order extends Model
1795
1807
  return $this->orderConfig;
1796
1808
  }
1797
1809
 
1798
- if (Str::isUuid($this->order_config_uuid)) {
1799
- $orderConfig = OrderConfig::where('uuid', $this->order_config_uuid)->withTrashed()->first();
1800
- if ($orderConfig instanceof OrderConfig) {
1801
- $orderConfig->setOrderContext($this);
1802
-
1803
- return $orderConfig;
1804
- }
1805
- }
1806
-
1807
1810
  $company = $this->relationLoaded('company') ? $this->company : $this->company()->first();
1808
1811
  $orderConfig = OrderConfig::defaultOrCreate($company);
1809
1812
  if ($orderConfig instanceof OrderConfig) {
@@ -498,7 +498,7 @@ class OrderConfig extends Model
498
498
  /**
499
499
  * Get the default order config.
500
500
  */
501
- public static function default(?Company $company = null): self
501
+ public static function default(?Company $company = null): ?self
502
502
  {
503
503
  return static::where(['namespace' => 'system:order-config:transport', 'company_uuid' => $company ? $company->uuid : session('company')])->first();
504
504
  }
@@ -911,14 +911,10 @@ class Payload extends Model
911
911
  $save = data_get($options, 'save', false);
912
912
  $callback = data_get($options, 'callback', false);
913
913
 
914
- if ($instance) {
915
- if (Str::isUuid($instance)) {
916
- $this->setAttribute($attr, $instance);
917
- } elseif ($instance instanceof Model) {
918
- $this->setAttribute($attr, $instance->uuid);
919
- } else {
920
- $this->setAttribute($attr, $instance);
921
- }
914
+ // createFromMixed() returns a Place or null, so a resolved instance is
915
+ // always a model — the uuid-string and passthrough cases cannot occur
916
+ if ($instance instanceof Model) {
917
+ $this->setAttribute($attr, $instance->uuid);
922
918
  }
923
919
 
924
920
  // Get the ID property
@@ -1148,19 +1144,16 @@ class Payload extends Model
1148
1144
  }
1149
1145
  }
1150
1146
 
1151
- // confirm destination_uuid is indeed a place record
1152
- if (isset($attributes['destination_uuid']) && Place::where('uuid', $attributes['destination_uuid'])->doesntExist()) {
1153
- // search waypoints for search_uuid if any
1154
- $destination = Place::where('meta->search_uuid', $attributes['destination_uuid'])->first();
1147
+ // confirm the key is indeed a place record, otherwise fall back to
1148
+ // search-uuid metadata left by console place searches
1149
+ if (Place::where('uuid', $destinationKey)->doesntExist()) {
1150
+ $destination = Place::where('meta->search_uuid', $destinationKey)->first();
1155
1151
 
1156
1152
  if ($destination instanceof Place) {
1157
1153
  return $destination;
1158
1154
  }
1159
- }
1160
1155
 
1161
- // Validate destination actually exists
1162
- if (isset($attributes['destination_uuid']) && Place::where('uuid', $attributes['destination_uuid'])->doesntExist()) {
1163
- $destination = $this->_findCorrectDestinationForEntity($attributes);
1156
+ $destination = $this->_findCorrectDestinationForEntity(['destination_uuid' => $destinationKey]);
1164
1157
 
1165
1158
  if ($destination instanceof Place) {
1166
1159
  return $destination;
@@ -394,6 +394,16 @@ class Place extends Model
394
394
  return static::getGoogleAddressArray($results->first());
395
395
  }
396
396
 
397
+ /**
398
+ * Inserts a new place into the database from a geocoding lookup on an address.
399
+ *
400
+ * @return string|bool the UUID of the newly created place or false if the place was not created
401
+ */
402
+ public static function insertFromGeocodingLookup(string $address)
403
+ {
404
+ return static::insertGetUuid(static::getValuesFromGeocodingLookup($address));
405
+ }
406
+
397
407
  /**
398
408
  * Compose a fuller geocoding query from structured place attributes.
399
409
  */
@@ -644,7 +654,7 @@ class Place extends Model
644
654
 
645
655
  $results = \Geocoder\Laravel\Facades\Geocoder::reverse($latitude, $longitude)->get();
646
656
 
647
- if (!$results->count() === 0) {
657
+ if ($results->count() === 0) {
648
658
  return false;
649
659
  }
650
660
 
@@ -703,11 +713,6 @@ class Place extends Model
703
713
  }
704
714
  // If $place is an array
705
715
  elseif (is_array($place)) {
706
- // If $place is an array of coordinates, create a new Place object
707
- if (Utils::isCoordinatesStrict($place)) {
708
- return static::createFromCoordinates($place, $attributes, $saveInstance);
709
- }
710
-
711
716
  // Get uuid if set
712
717
  $uuid = data_get($place, 'uuid');
713
718
 
@@ -782,12 +787,11 @@ class Place extends Model
782
787
  }
783
788
  }
784
789
 
785
- // handle address if set
786
- if (!empty($place['address'])) {
787
- return static::insertFromGeocodingLookup($place['address']);
788
- }
789
-
790
790
  return static::insertFromGeocodingLookup($place);
791
+ } elseif ($place instanceof \Geocoder\Provider\GoogleMaps\Model\GoogleAddress) {
792
+ // Must be tested before the array/object arm below, which would
793
+ // otherwise swallow it and flatten it to an array
794
+ return static::insertFromGoogleAddress($place);
791
795
  } elseif (is_array($place) || is_object($place)) {
792
796
  // if place already exists just return uuid
793
797
  if (static::isValidPlaceUuid(data_get($place, 'uuid'))) {
@@ -805,14 +809,17 @@ class Place extends Model
805
809
 
806
810
  $values = is_array($place) ? $place : (array) $place;
807
811
 
812
+ // handle address if set
813
+ if (!empty($values['address'])) {
814
+ return static::insertFromGeocodingLookup($values['address']);
815
+ }
816
+
808
817
  if ($existingPlace = static::findExistingSharedPlace($values)) {
809
818
  return $existingPlace->uuid;
810
819
  }
811
820
 
812
821
  // create a new place
813
822
  return static::insertGetUuid((array) $values);
814
- } elseif ($place instanceof \Geocoder\Provider\GoogleMaps\Model\GoogleAddress) {
815
- return static::insertFromGoogleAddress($place);
816
823
  }
817
824
  }
818
825
 
@@ -180,13 +180,10 @@ class ServiceArea extends Model
180
180
  */
181
181
  public static function createMultiPolygonFromPoint(Point $point, int $meters = 500): MultiPolygon
182
182
  {
183
+ // coordsToCircle() already closes the ring, so first and last are
184
+ // equivalent on arrival and no re-closing is needed here
183
185
  $coordinates = Utils::coordsToCircle($point->getLat(), $point->getLng(), $meters);
184
186
 
185
- // first and last positions should be equivalent
186
- if (Arr::first($coordinates) !== Arr::last($coordinates)) {
187
- $coordinates[] = Arr::first($coordinates);
188
- }
189
-
190
187
  // conver the coordinate pairs to points
191
188
  $coordinates = array_map(
192
189
  function ($coord) {
@@ -380,7 +377,7 @@ class ServiceArea extends Model
380
377
  */
381
378
  public function getCentroid(): \Brick\Geo\Point
382
379
  {
383
- $geometryEngine = new \Brick\Geo\Engine\GEOSEngine();
380
+ $geometryEngine = Utils::resolveGeometryEngine();
384
381
  $borderAsMultiPolygon = $this->toGeosMultiPolygon();
385
382
 
386
383
  if ($borderAsMultiPolygon instanceof \Brick\Geo\Geometry) {
@@ -211,7 +211,12 @@ class ServiceQuote extends Model
211
211
  return $product;
212
212
  }
213
213
 
214
+ // Unreachable: `Payment::getStripeClient()` is `?StripeClient` in its
215
+ // signature only — it unconditionally returns `new StripeClient([...])`,
216
+ // so the guard above never falls through.
217
+ // @codeCoverageIgnoreStart
214
218
  return null;
219
+ // @codeCoverageIgnoreEnd
215
220
  }
216
221
 
217
222
  /**
@@ -856,7 +856,7 @@ class ServiceRate extends Model
856
856
 
857
857
  // if no distance fee use the last
858
858
  if ($serviceParcelFee === null) {
859
- $serviceParcelFee = $this->parcelFees->sortByDesc()->first();
859
+ $serviceParcelFee = $this->parcelFees->sortByDesc('fee')->first();
860
860
  }
861
861
 
862
862
  $subTotal += $serviceParcelFee->fee;
@@ -1050,7 +1050,7 @@ class ServiceRate extends Model
1050
1050
 
1051
1051
  // if no distance fee use the last
1052
1052
  if ($serviceParcelFee === null) {
1053
- $serviceParcelFee = $this->parcelFees->sortByDesc()->first();
1053
+ $serviceParcelFee = $this->parcelFees->sortByDesc('fee')->first();
1054
1054
  }
1055
1055
 
1056
1056
  $subTotal += $serviceParcelFee->fee;
@@ -1213,10 +1213,15 @@ class ServiceRate extends Model
1213
1213
  $subTotal = 0;
1214
1214
 
1215
1215
  foreach ($pricedDistances as $entry) {
1216
+ // Unreachable: calculateMultiZoneDistances() only ever emits entries
1217
+ // whose rule is a ServiceRateFee — both its early returns are gated
1218
+ // on a non-null $fallbackRule and its accumulator guards the type.
1216
1219
  $rule = $entry['rule'];
1220
+ // @codeCoverageIgnoreStart
1217
1221
  if (!$rule instanceof ServiceRateFee) {
1218
1222
  continue;
1219
1223
  }
1224
+ // @codeCoverageIgnoreEnd
1220
1225
 
1221
1226
  $distanceInMeters = (float) ($entry['distance_m'] ?? 0);
1222
1227
  if ($distanceInMeters <= 0) {
@@ -1274,12 +1279,16 @@ class ServiceRate extends Model
1274
1279
  $sampledTotal = 0;
1275
1280
 
1276
1281
  for ($i = 0; $i < $places->count() - 1; $i++) {
1282
+ // Unreachable: $places is filtered to Place instances above, and
1283
+ // getLngLatFromPlace() only returns null for a non-Place.
1277
1284
  $start = $this->getLngLatFromPlace($places[$i]);
1278
1285
  $end = $this->getLngLatFromPlace($places[$i + 1]);
1279
1286
 
1287
+ // @codeCoverageIgnoreStart
1280
1288
  if (!$start || !$end) {
1281
1289
  continue;
1282
1290
  }
1291
+ // @codeCoverageIgnoreEnd
1283
1292
 
1284
1293
  $legDistance = $this->haversineDistanceInMeters($start['lat'], $start['lng'], $end['lat'], $end['lng']);
1285
1294
  $steps = max(1, min(500, (int) ceil($legDistance / 1000)));
@@ -1367,12 +1376,10 @@ class ServiceRate extends Model
1367
1376
  return null;
1368
1377
  }
1369
1378
 
1379
+ // getLocationAsPoint() is typed `: SpatialPoint`, which always exposes
1380
+ // getLat()/getLng(), so no further guarding is possible here
1370
1381
  $point = $place->getLocationAsPoint();
1371
1382
 
1372
- if (!$point || !method_exists($point, 'getLat') || !method_exists($point, 'getLng')) {
1373
- return null;
1374
- }
1375
-
1376
1383
  return ['lat' => (float) $point->getLat(), 'lng' => (float) $point->getLng()];
1377
1384
  }
1378
1385
 
@@ -385,9 +385,9 @@ class Telematic extends Model
385
385
  return 'recently_offline';
386
386
  } elseif ($minutesOffline <= 1440) { // 24 hours
387
387
  return 'offline';
388
- } else {
389
- return 'long_offline';
390
388
  }
389
+
390
+ return 'long_offline';
391
391
  }
392
392
 
393
393
  /**