@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
@@ -35,7 +35,6 @@ use Fleetbase\FleetOps\Notifications\OrderPing;
35
35
  use Fleetbase\FleetOps\Support\ResolvesOrderServiceStops;
36
36
  use Fleetbase\FleetOps\Support\Utils;
37
37
  use Fleetbase\Http\Requests\ExportRequest;
38
- use Fleetbase\Http\Requests\Internal\BulkActionRequest;
39
38
  use Fleetbase\Models\File;
40
39
  use Fleetbase\Models\Type;
41
40
  use Fleetbase\Support\Auth;
@@ -215,6 +214,11 @@ class OrderController extends FleetOpsController
215
214
  }
216
215
  );
217
216
 
217
+ // Surface early error responses (e.g. integrated vendor failures) as-is
218
+ if ($record instanceof \Illuminate\Http\JsonResponse) {
219
+ return $record;
220
+ }
221
+
218
222
  // Reload payload and tracking number
219
223
  $record->load(['payload', 'trackingNumber']);
220
224
 
@@ -274,9 +278,9 @@ class OrderController extends FleetOpsController
274
278
  $hasWaypointsInput = $request->exists('waypoints');
275
279
 
276
280
  // Get the order
277
- $order = Order::where('uuid', $id)->with(['payload'])->first();
281
+ $order = $this->findOrderRouteForEdit($id);
278
282
  if (!$order) {
279
- return response()->error('Unable to find order to update route for.');
283
+ return $this->errorResponse('Unable to find order to update route for.');
280
284
  }
281
285
 
282
286
  if ($hasPickupInput) {
@@ -324,7 +328,7 @@ class OrderController extends FleetOpsController
324
328
 
325
329
  $order->load(['payload.pickup', 'payload.dropoff', 'payload.return', 'payload.waypoints']);
326
330
 
327
- return ['order' => new $this->resource($order)];
331
+ return $this->orderResponse($order);
328
332
  }
329
333
 
330
334
  /**
@@ -403,10 +407,14 @@ class OrderController extends FleetOpsController
403
407
  *
404
408
  * @return \Illuminate\Http\Response
405
409
  */
406
- public function bulkCancel(BulkActionRequest $request)
410
+ public function bulkCancel(Request $request)
407
411
  {
412
+ $request->validate([
413
+ 'ids' => ['required', 'array'],
414
+ ]);
415
+
408
416
  /** @var \Illuminate\Database\Eloquent\Collection $orders */
409
- $orders = Order::whereIn('uuid', $request->input('ids'))->get();
417
+ $orders = $this->ordersByUuid($request->input('ids'));
410
418
 
411
419
  $count = $orders->count();
412
420
  $failed = [];
@@ -418,7 +426,7 @@ class OrderController extends FleetOpsController
418
426
  continue;
419
427
  }
420
428
 
421
- $trackingStatusExists = TrackingStatus::where(['tracking_number_uuid' => $order->tracking_number_uuid, 'code' => 'CANCELED'])->exists();
429
+ $trackingStatusExists = $this->trackingStatusExists($order->tracking_number_uuid, 'CANCELED');
422
430
  if ($trackingStatusExists) {
423
431
  $failed[] = $order->uuid;
424
432
  continue;
@@ -428,7 +436,7 @@ class OrderController extends FleetOpsController
428
436
  $successful[] = $order->uuid;
429
437
  }
430
438
 
431
- return response()->json(
439
+ return $this->jsonResponse(
432
440
  [
433
441
  'status' => 'OK',
434
442
  'message' => 'Canceled ' . $count . ' orders',
@@ -447,7 +455,7 @@ class OrderController extends FleetOpsController
447
455
  public function bulkDispatch(BulkDispatchRequest $request)
448
456
  {
449
457
  /** @var Order */
450
- $orders = Order::whereIn('uuid', $request->input('ids'))->get();
458
+ $orders = $this->ordersByUuid($request->input('ids'));
451
459
 
452
460
  $count = $orders->count();
453
461
  $failed = [];
@@ -459,7 +467,7 @@ class OrderController extends FleetOpsController
459
467
  continue;
460
468
  }
461
469
 
462
- $trackingStatusExists = TrackingStatus::where(['tracking_number_uuid' => $order->tracking_number_uuid, 'code' => 'CANCELED'])->exists();
470
+ $trackingStatusExists = $this->trackingStatusExists($order->tracking_number_uuid, 'CANCELED');
463
471
  if ($trackingStatusExists) {
464
472
  $failed[] = $order->uuid;
465
473
  continue;
@@ -469,7 +477,7 @@ class OrderController extends FleetOpsController
469
477
  $successful[] = $order->uuid;
470
478
  }
471
479
 
472
- return response()->json(
480
+ return $this->jsonResponse(
473
481
  [
474
482
  'status' => 'OK',
475
483
  'message' => 'Dispatched ' . $count . ' orders',
@@ -486,49 +494,42 @@ class OrderController extends FleetOpsController
486
494
  * The queued closure keeps payloads lean (just two UUID strings) and
487
495
  * prevents the HTTP request from blocking on network‑bound notification work.
488
496
  *
489
- * @param BulkActionRequest $request Validated request with:
490
- * - ids : string[] list of order UUIDs
491
- * - driver : string driver UUID
497
+ * @param Request $request Validated request with:
498
+ * - ids : string[] list of order UUIDs
499
+ * - driver : string driver UUID
492
500
  *
493
501
  * @return \Illuminate\Http\Response
494
502
  */
495
- public function bulkAssignDriver(BulkActionRequest $request)
503
+ public function bulkAssignDriver(Request $request)
496
504
  {
497
505
  // Validate Inputs
498
- $data = $request->validate([
499
- 'ids' => 'required|array',
500
- 'ids.*' => 'uuid',
501
- 'driver' => 'required|uuid',
502
- ]);
506
+ $data = $this->validateBulkAssignDriverRequest($request);
503
507
 
504
508
  // Resolve Driver
505
509
  /** @var Driver|null $driver */
506
- $driver = Driver::whereUuid($data['driver'])->first();
510
+ $driver = $this->findDriverByUuid($data['driver']);
507
511
  if (!$driver) {
508
- return response()->error('Invalid driver selected to assign orders to.');
512
+ return $this->errorResponse('Invalid driver selected to assign orders to.');
509
513
  }
510
514
 
511
515
  // Prepare Order UUID Collection
512
516
  $orderUuids = collect($data['ids'])->unique()->values();
513
517
 
514
518
  // Bulk Update Inside A Transaction
515
- DB::transaction(function () use ($orderUuids, $driver): void {
516
- Order::whereIn('uuid', $orderUuids)->update([
517
- 'driver_assigned_uuid' => $driver->uuid,
518
- 'updated_at' => now(),
519
- ]);
519
+ $this->runTransaction(function () use ($orderUuids, $driver): void {
520
+ $this->assignDriverToOrders($orderUuids, $driver);
520
521
  });
521
522
 
522
523
  // Queue Per‑Order Notifications
523
524
  if (!$request->boolean('silent')) {
524
- NotifyBulkAssignedDriver::dispatch($orderUuids->all(), $driver->uuid)->afterCommit();
525
+ $this->dispatchBulkAssignedDriverNotification($orderUuids->all(), $driver);
525
526
  }
526
527
 
527
- return response()->json([
528
+ return $this->jsonResponse([
528
529
  'status' => 'OK',
529
530
  'message' => sprintf(
530
531
  'Queued assignment of driver (%s) to %d orders',
531
- $driver->name,
532
+ $this->driverDisplayName($driver),
532
533
  $orderUuids->count()
533
534
  ),
534
535
  'count' => $orderUuids->count(),
@@ -545,11 +546,11 @@ class OrderController extends FleetOpsController
545
546
  public function cancel(CancelOrderRequest $request)
546
547
  {
547
548
  /** @var Order */
548
- $order = Order::where('uuid', $request->input('order'))->first();
549
+ $order = $this->findOrderByUuid($request->input('order'));
549
550
 
550
551
  $order->cancel();
551
552
 
552
- return response()->json(
553
+ return $this->jsonResponse(
553
554
  [
554
555
  'status' => 'OK',
555
556
  'message' => 'Order was canceled',
@@ -568,28 +569,28 @@ class OrderController extends FleetOpsController
568
569
  /**
569
570
  * @var Order
570
571
  */
571
- $order = Order::findById($request->input('order'), ['orderConfig', 'driverAssigned']);
572
+ $order = $this->findOrderById($request->input('order'), ['orderConfig', 'driverAssigned']);
572
573
  if (!$order) {
573
- return response()->error('No order found to dispatch.');
574
+ return $this->errorResponse('No order found to dispatch.');
574
575
  }
575
576
 
576
577
  // Ensure the order is normalized onto a real order config before
577
578
  // dispatching activities.
578
579
  if (!$order->ensureOrderConfig()) {
579
- return response()->error('No order config found for dispatch.');
580
+ return $this->errorResponse('No order config found for dispatch.');
580
581
  }
581
582
 
582
583
  if (!$order->hasDriverAssigned && !$order->adhoc) {
583
- return response()->error('No driver assigned to dispatch!');
584
+ return $this->errorResponse('No driver assigned to dispatch!');
584
585
  }
585
586
 
586
587
  if ($order->dispatched) {
587
- return response()->error('Order has already been dispatched!');
588
+ return $this->errorResponse('Order has already been dispatched!');
588
589
  }
589
590
 
590
591
  $order->dispatchWithActivity();
591
592
 
592
- return response()->json(
593
+ return $this->jsonResponse(
593
594
  [
594
595
  'status' => 'OK',
595
596
  'message' => 'Order was dispatched',
@@ -598,6 +599,83 @@ class OrderController extends FleetOpsController
598
599
  );
599
600
  }
600
601
 
602
+ protected function ordersByUuid(array $ids)
603
+ {
604
+ return Order::whereIn('uuid', $ids)->get();
605
+ }
606
+
607
+ protected function trackingStatusExists(?string $trackingNumberUuid, string $code): bool
608
+ {
609
+ return TrackingStatus::where(['tracking_number_uuid' => $trackingNumberUuid, 'code' => $code])->exists();
610
+ }
611
+
612
+ protected function findDriverByUuid(string $uuid): ?Driver
613
+ {
614
+ return Driver::whereUuid($uuid)->first();
615
+ }
616
+
617
+ protected function driverDisplayName(Driver $driver): string
618
+ {
619
+ return (string) $driver->name;
620
+ }
621
+
622
+ protected function validateBulkAssignDriverRequest(Request $request): array
623
+ {
624
+ return $request->validate([
625
+ 'ids' => 'required|array',
626
+ 'ids.*' => 'uuid',
627
+ 'driver' => 'required|uuid',
628
+ ]);
629
+ }
630
+
631
+ protected function findOrderByUuid(string $uuid): ?Order
632
+ {
633
+ return Order::where('uuid', $uuid)->first();
634
+ }
635
+
636
+ protected function findOrderById(string $id, array $with = []): ?Order
637
+ {
638
+ return Order::findById($id, $with);
639
+ }
640
+
641
+ protected function findOrderRouteForEdit(string $uuid): ?Order
642
+ {
643
+ return Order::where('uuid', $uuid)->with(['payload'])->first();
644
+ }
645
+
646
+ protected function orderResponse(Order $order): array
647
+ {
648
+ return ['order' => new $this->resource($order)];
649
+ }
650
+
651
+ protected function assignDriverToOrders($orderUuids, Driver $driver): void
652
+ {
653
+ Order::whereIn('uuid', $orderUuids)->update([
654
+ 'driver_assigned_uuid' => $driver->uuid,
655
+ 'updated_at' => now(),
656
+ ]);
657
+ }
658
+
659
+ protected function dispatchBulkAssignedDriverNotification(array $orderUuids, Driver $driver): void
660
+ {
661
+ NotifyBulkAssignedDriver::dispatch($orderUuids, $driver->uuid)->afterCommit();
662
+ }
663
+
664
+ protected function runTransaction(callable $callback): mixed
665
+ {
666
+ return DB::transaction($callback);
667
+ }
668
+
669
+ protected function jsonResponse(array $payload)
670
+ {
671
+ return response()->json($payload);
672
+ }
673
+
674
+ protected function errorResponse(string $message, int $status = 400)
675
+ {
676
+ return response()->error($message, $status);
677
+ }
678
+
601
679
  /**
602
680
  * Internal request for driver to start order.
603
681
  *
@@ -608,7 +686,7 @@ class OrderController extends FleetOpsController
608
686
  /**
609
687
  * @var Order
610
688
  */
611
- $order = Order::where('uuid', $request->input('order'))->withoutGlobalScopes()->first();
689
+ $order = $this->findOrderForStart($request->input('order'));
612
690
 
613
691
  if (!$order) {
614
692
  return response()->error('Unable to find order to start.');
@@ -621,12 +699,12 @@ class OrderController extends FleetOpsController
621
699
  /**
622
700
  * @var Driver
623
701
  */
624
- $driver = Driver::where('uuid', $order->driver_assigned_uuid)->withoutGlobalScopes()->first();
702
+ $driver = $this->findDriverForStart($order->driver_assigned_uuid);
625
703
 
626
704
  /**
627
705
  * @var Payload
628
706
  */
629
- $payload = Payload::where('uuid', $order->payload_uuid)->withoutGlobalScopes()->with(['waypoints', 'waypointMarkers', 'entities'])->first();
707
+ $payload = $this->findPayloadForStart($order->payload_uuid);
630
708
 
631
709
  if (!$driver) {
632
710
  return response()->error('No driver assigned to order.');
@@ -638,7 +716,7 @@ class OrderController extends FleetOpsController
638
716
  $order->save();
639
717
 
640
718
  // trigger start event
641
- event(new OrderStarted($order));
719
+ $this->dispatchDomainEvent($this->orderStartedEvent($order));
642
720
 
643
721
  // set order as drivers current order
644
722
  $driver->current_job_uuid = $order->uuid;
@@ -659,6 +737,33 @@ class OrderController extends FleetOpsController
659
737
  return $this->updateActivity($order->uuid, $updateActivityRequest);
660
738
  }
661
739
 
740
+ protected function findOrderForStart(?string $uuid): ?Order
741
+ {
742
+ return Order::where('uuid', $uuid)->withoutGlobalScopes()->first();
743
+ }
744
+
745
+ protected function findDriverForStart(?string $uuid): ?Driver
746
+ {
747
+ return Driver::where('uuid', $uuid)->withoutGlobalScopes()->first();
748
+ }
749
+
750
+ protected function findPayloadForStart(?string $uuid): ?Payload
751
+ {
752
+ return Payload::where('uuid', $uuid)->withoutGlobalScopes()->with(['waypoints', 'waypointMarkers', 'entities'])->first();
753
+ }
754
+
755
+ protected function dispatchDomainEvent(object $event): object
756
+ {
757
+ event($event);
758
+
759
+ return $event;
760
+ }
761
+
762
+ protected function orderStartedEvent(Order $order): object
763
+ {
764
+ return new OrderStarted($order);
765
+ }
766
+
662
767
  /**
663
768
  * Update an order activity.
664
769
  *
@@ -923,9 +1028,14 @@ class OrderController extends FleetOpsController
923
1028
  $remarks = $request->input('remarks', 'Verified by Photo');
924
1029
  $data = $metadata;
925
1030
 
1031
+ // Unreachable: the validate() above already requires `photos` to be a
1032
+ // non-empty array, so an empty payload is rejected before this point.
1033
+ // Kept as defence in depth against the rules being loosened.
1034
+ // @codeCoverageIgnoreStart
926
1035
  if (empty($incoming)) {
927
1036
  return response()->error('No photo data to capture.', 422);
928
1037
  }
1038
+ // @codeCoverageIgnoreEnd
929
1039
 
930
1040
  foreach ($incoming as $item) {
931
1041
  $proof = Proof::create([
@@ -1251,22 +1361,22 @@ class OrderController extends FleetOpsController
1251
1361
  */
1252
1362
  public function trackerInfo(Request $request, string $id)
1253
1363
  {
1254
- $order = Order::findById($id);
1364
+ $order = $this->findOrderById($id);
1255
1365
  if (!$order) {
1256
- return response()->error('No order found.');
1366
+ return $this->errorResponse('No order found.');
1257
1367
  }
1258
1368
 
1259
- return response()->json($order->tracker()->toArray($request->only(['provider', 'fallbacks', 'traffic_enabled'])));
1369
+ return $this->jsonResponse($order->tracker()->toArray($request->only(['provider', 'fallbacks', 'traffic_enabled'])));
1260
1370
  }
1261
1371
 
1262
1372
  public function waypointEtas(Request $request, string $id)
1263
1373
  {
1264
- $order = Order::findById($id);
1374
+ $order = $this->findOrderById($id);
1265
1375
  if (!$order) {
1266
- return response()->error('No order found.');
1376
+ return $this->errorResponse('No order found.');
1267
1377
  }
1268
1378
 
1269
- return response()->json($order->tracker()->eta($request->only(['provider', 'fallbacks', 'traffic_enabled'])));
1379
+ return $this->jsonResponse($order->tracker()->eta($request->only(['provider', 'fallbacks', 'traffic_enabled'])));
1270
1380
  }
1271
1381
 
1272
1382
  /**
@@ -1276,12 +1386,12 @@ class OrderController extends FleetOpsController
1276
1386
  */
1277
1387
  public function pingDriver(string $id)
1278
1388
  {
1279
- if (!Auth::can('fleet-ops update order')) {
1389
+ if (!$this->canPingDriver()) {
1280
1390
  return response()->error('Unauthorized.', 403);
1281
1391
  }
1282
1392
 
1283
1393
  try {
1284
- $order = Order::findByIdOrFail($id, ['driverAssigned']);
1394
+ $order = $this->findOrderForDriverPing($id);
1285
1395
  } catch (ModelNotFoundException $e) {
1286
1396
  return response()->error('Order resource not found.', 404);
1287
1397
  }
@@ -1291,7 +1401,7 @@ class OrderController extends FleetOpsController
1291
1401
  }
1292
1402
 
1293
1403
  try {
1294
- $order->driverAssigned->notify(new OrderPing($order));
1404
+ $this->sendDriverPing($order->driverAssigned, $order);
1295
1405
 
1296
1406
  return response()->json([
1297
1407
  'status' => 'ok',
@@ -1302,6 +1412,21 @@ class OrderController extends FleetOpsController
1302
1412
  }
1303
1413
  }
1304
1414
 
1415
+ protected function canPingDriver(): bool
1416
+ {
1417
+ return Auth::can('fleet-ops update order');
1418
+ }
1419
+
1420
+ protected function findOrderForDriverPing(string $id): Order
1421
+ {
1422
+ return Order::findByIdOrFail($id, ['driverAssigned']);
1423
+ }
1424
+
1425
+ protected function sendDriverPing(Driver $driver, Order $order): void
1426
+ {
1427
+ $driver->notify(new OrderPing($order));
1428
+ }
1429
+
1305
1430
  /**
1306
1431
  * Return distinct order statuses (and optionally activity codes) for a company,
1307
1432
  * filtered by order_config_uuid or order_config_key if provided.
@@ -1369,10 +1494,6 @@ class OrderController extends FleetOpsController
1369
1494
  ->get();
1370
1495
 
1371
1496
  foreach ($orderConfigs as $config) {
1372
- if (!method_exists($config, 'activities')) {
1373
- continue;
1374
- }
1375
-
1376
1497
  $activities = $config->activities();
1377
1498
 
1378
1499
  // Handle Collection/array gracefully
@@ -1406,12 +1527,12 @@ class OrderController extends FleetOpsController
1406
1527
  */
1407
1528
  public function types()
1408
1529
  {
1409
- $defaultTypes = collect(config('api.types.order', []))->map(
1530
+ $defaultTypes = collect($this->defaultOrderTypeConfig())->map(
1410
1531
  function ($attributes) {
1411
1532
  return new Type($attributes);
1412
1533
  }
1413
1534
  );
1414
- $customTypes = Type::where('for', 'order')->get();
1535
+ $customTypes = $this->customOrderTypes();
1415
1536
 
1416
1537
  $results = collect([...$customTypes, ...$defaultTypes])
1417
1538
  ->unique('key')
@@ -1420,6 +1541,16 @@ class OrderController extends FleetOpsController
1420
1541
  return response()->json($results);
1421
1542
  }
1422
1543
 
1544
+ protected function defaultOrderTypeConfig(): array
1545
+ {
1546
+ return config('api.types.order', []);
1547
+ }
1548
+
1549
+ protected function customOrderTypes()
1550
+ {
1551
+ return Type::where('for', 'order')->get();
1552
+ }
1553
+
1423
1554
  /**
1424
1555
  * Sends back the PDF stream for an order label file.
1425
1556
  *
@@ -1433,15 +1564,15 @@ class OrderController extends FleetOpsController
1433
1564
 
1434
1565
  switch ($type) {
1435
1566
  case 'order':
1436
- $subject = Order::where('public_id', $publicId)->orWhere('uuid', $publicId)->withoutGlobalScopes()->first();
1567
+ $subject = $this->findOrderLabelSubject($publicId);
1437
1568
  break;
1438
1569
 
1439
1570
  case 'waypoint':
1440
- $subject = Waypoint::where('public_id', $publicId)->orWhere('uuid', $publicId)->withoutGlobalScopes()->first();
1571
+ $subject = $this->findWaypointLabelSubject($publicId);
1441
1572
  break;
1442
1573
 
1443
1574
  case 'entity':
1444
- $subject = Entity::where('public_id', $publicId)->orWhere('uuid', $publicId)->withoutGlobalScopes()->first();
1575
+ $subject = $this->findEntityLabelSubject($publicId);
1445
1576
  break;
1446
1577
  }
1447
1578
 
@@ -1460,7 +1591,7 @@ class OrderController extends FleetOpsController
1460
1591
  case 'text':
1461
1592
  $text = $subject->pdfLabel()->output();
1462
1593
 
1463
- return response()->make($text);
1594
+ return $this->makeTextResponse($text);
1464
1595
 
1465
1596
  case 'base64':
1466
1597
  $base64 = base64_encode($subject->pdfLabel()->output());
@@ -1471,6 +1602,50 @@ class OrderController extends FleetOpsController
1471
1602
  return response()->error('Unable to render label.');
1472
1603
  }
1473
1604
 
1605
+ protected function makeTextResponse(string $text)
1606
+ {
1607
+ return response()->make($text);
1608
+ }
1609
+
1610
+ protected function findOrderLabelSubject(string $id): ?Order
1611
+ {
1612
+ return $this->findLabelSubjectFor(Order::class, $id);
1613
+ }
1614
+
1615
+ protected function findWaypointLabelSubject(string $id): ?Waypoint
1616
+ {
1617
+ return $this->findLabelSubjectFor(Waypoint::class, $id);
1618
+ }
1619
+
1620
+ protected function findEntityLabelSubject(string $id): ?Entity
1621
+ {
1622
+ return $this->findLabelSubjectFor(Entity::class, $id);
1623
+ }
1624
+
1625
+ /**
1626
+ * Resolves a label subject by public id or uuid, constrained to the current company.
1627
+ *
1628
+ * The identifier match is grouped so the company constraint applies to both arms —
1629
+ * without the closure it would read as `public_id = ? OR (uuid = ? AND company_uuid = ?)`
1630
+ * and leak labels across organizations.
1631
+ */
1632
+ protected function findLabelSubjectFor(string $model, string $id): mixed
1633
+ {
1634
+ $companyUuid = $this->sessionCompany();
1635
+ if (!$companyUuid) {
1636
+ return null;
1637
+ }
1638
+
1639
+ return $model::where(function ($query) use ($id) {
1640
+ $query->where('public_id', $id)->orWhere('uuid', $id);
1641
+ })->where('company_uuid', $companyUuid)->withoutGlobalScopes()->first();
1642
+ }
1643
+
1644
+ protected function sessionCompany(): ?string
1645
+ {
1646
+ return session('company');
1647
+ }
1648
+
1474
1649
  /**
1475
1650
  * Retrieve proof of delivery resources associated with a given order and optional subject.
1476
1651
  *
@@ -1488,7 +1663,7 @@ class OrderController extends FleetOpsController
1488
1663
  public function proofs(Request $request, string $id, ?string $subjectId = null)
1489
1664
  {
1490
1665
  try {
1491
- $order = Order::where('uuid', $id)->first();
1666
+ $order = $this->findOrderForProofs($id);
1492
1667
  } catch (ModelNotFoundException $e) {
1493
1668
  return response()->error('Order resource not found.', 404);
1494
1669
  }
@@ -1499,15 +1674,8 @@ class OrderController extends FleetOpsController
1499
1674
  $type = strtok($subjectId, '_');
1500
1675
 
1501
1676
  $subject = match ($type) {
1502
- 'place', 'waypoint' => Waypoint::where('payload_uuid', $order->payload_uuid)
1503
- ->where(function ($query) use ($subjectId) {
1504
- $query->whereHas('place', fn ($q) => $q->where('uuid', $subjectId))
1505
- ->orWhere('uuid', $subjectId);
1506
- })
1507
- ->withoutGlobalScopes()
1508
- ->first(),
1509
-
1510
- 'entity' => Entity::where('uuid', $subjectId)->withoutGlobalScopes()->first(),
1677
+ 'place', 'waypoint' => $this->findWaypointProofSubject($order, $subjectId),
1678
+ 'entity' => $this->findEntityProofSubject($subjectId),
1511
1679
 
1512
1680
  default => $order,
1513
1681
  };
@@ -1517,20 +1685,44 @@ class OrderController extends FleetOpsController
1517
1685
  return response()->error('Unable to retrieve proof of delivery for subject.');
1518
1686
  }
1519
1687
 
1688
+ $proofs = $this->proofsForSubject($order, $subject);
1689
+
1690
+ return ProofResource::collection($proofs);
1691
+ }
1692
+
1693
+ protected function findOrderForProofs(string $id): ?Order
1694
+ {
1695
+ return Order::where('uuid', $id)->first();
1696
+ }
1697
+
1698
+ protected function findWaypointProofSubject(Order $order, string $subjectId): ?Waypoint
1699
+ {
1700
+ return Waypoint::where('payload_uuid', $order->payload_uuid)
1701
+ ->where(function ($query) use ($subjectId) {
1702
+ $query->whereHas('place', fn ($q) => $q->where('uuid', $subjectId))
1703
+ ->orWhere('uuid', $subjectId);
1704
+ })
1705
+ ->withoutGlobalScopes()
1706
+ ->first();
1707
+ }
1708
+
1709
+ protected function findEntityProofSubject(string $subjectId): ?Entity
1710
+ {
1711
+ return Entity::where('uuid', $subjectId)->withoutGlobalScopes()->first();
1712
+ }
1713
+
1714
+ protected function proofsForSubject(Order $order, Order|Waypoint|Entity $subject)
1715
+ {
1520
1716
  $proofsQuery = Proof::where([
1521
1717
  'company_uuid' => session('company'),
1522
1718
  'order_uuid' => $order->uuid,
1523
1719
  ]);
1524
1720
 
1525
- // if subject is not the order then filter by subject
1526
1721
  if ($order->uuid !== $subject->uuid) {
1527
1722
  $proofsQuery->where('subject_uuid', $subject->uuid);
1528
1723
  }
1529
1724
 
1530
- // get proofs
1531
- $proofs = $proofsQuery->get();
1532
-
1533
- return ProofResource::collection($proofs);
1725
+ return $proofsQuery->get();
1534
1726
  }
1535
1727
 
1536
1728
  /**
@@ -1544,6 +1736,11 @@ class OrderController extends FleetOpsController
1544
1736
  $selections = $request->array('selections');
1545
1737
  $fileName = trim(Str::slug('order-' . date('Y-m-d-H:i')) . '.' . $format);
1546
1738
 
1739
+ return $this->downloadOrderExport($selections, $fileName);
1740
+ }
1741
+
1742
+ protected function downloadOrderExport(array $selections, string $fileName)
1743
+ {
1547
1744
  return Excel::download(new OrderExport($selections), $fileName);
1548
1745
  }
1549
1746
 
@@ -1559,12 +1756,7 @@ class OrderController extends FleetOpsController
1559
1756
  return response()->error('No tracking number provided for lookup.');
1560
1757
  }
1561
1758
 
1562
- $order = Order::whereHas(
1563
- 'trackingNumber',
1564
- function ($query) use ($trackingNumber) {
1565
- $query->where('tracking_number', $trackingNumber);
1566
- }
1567
- )->first();
1759
+ $order = $this->findOrderByTrackingNumber($trackingNumber);
1568
1760
 
1569
1761
  if (!$order) {
1570
1762
  return response()->error('No order found using tracking number provided.');
@@ -1580,6 +1772,16 @@ class OrderController extends FleetOpsController
1580
1772
  return new OrderResource($order);
1581
1773
  }
1582
1774
 
1775
+ protected function findOrderByTrackingNumber(string $trackingNumber): ?Order
1776
+ {
1777
+ return Order::whereHas(
1778
+ 'trackingNumber',
1779
+ function ($query) use ($trackingNumber) {
1780
+ $query->where('tracking_number', $trackingNumber);
1781
+ }
1782
+ )->first();
1783
+ }
1784
+
1583
1785
  /**
1584
1786
  * Schedule an order: set scheduled_at and optionally assign a driver.
1585
1787
  * This endpoint intentionally does NOT trigger dispatch or change the
@@ -1593,7 +1795,7 @@ class OrderController extends FleetOpsController
1593
1795
  $scheduledAt = $request->input('scheduled_at');
1594
1796
  $driverId = $request->input('driver_id');
1595
1797
 
1596
- $order = Order::findById($orderId);
1798
+ $order = $this->findOrderForSchedule($orderId);
1597
1799
  if (!$order) {
1598
1800
  return response()->error('No order found to schedule.');
1599
1801
  }
@@ -1604,9 +1806,7 @@ class OrderController extends FleetOpsController
1604
1806
 
1605
1807
  if ($driverId) {
1606
1808
  // Resolve by uuid or public_id
1607
- $driver = Driver::where('uuid', $driverId)
1608
- ->orWhere('public_id', $driverId)
1609
- ->first();
1809
+ $driver = $this->findDriverForSchedule($driverId);
1610
1810
  if ($driver) {
1611
1811
  $order->driver_assigned_uuid = $driver->uuid;
1612
1812
  }
@@ -1621,4 +1821,16 @@ class OrderController extends FleetOpsController
1621
1821
  'scheduled_at' => $order->scheduled_at,
1622
1822
  ]);
1623
1823
  }
1824
+
1825
+ protected function findOrderForSchedule(?string $id): ?Order
1826
+ {
1827
+ return Order::findById($id);
1828
+ }
1829
+
1830
+ protected function findDriverForSchedule(string $id): ?Driver
1831
+ {
1832
+ return Driver::where('uuid', $id)
1833
+ ->orWhere('public_id', $id)
1834
+ ->first();
1835
+ }
1624
1836
  }