@fleetbase/fleetops-engine 0.6.58 → 0.6.60

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 (701) hide show
  1. package/README.md +3 -0
  2. package/RELEASE.md +36 -0
  3. package/addon/components/customer/form.hbs +0 -49
  4. package/addon/components/entity/card.hbs +1 -0
  5. package/addon/components/modals/order-label.hbs +1 -1
  6. package/addon/components/place/form.hbs +1 -1
  7. package/addon/components/vehicle/details/schedules.hbs +2 -2
  8. package/addon/components/vehicle/details/schedules.js +7 -1
  9. package/addon/controllers/maintenance/schedules/index/edit.js +10 -1
  10. package/addon/services/entity-actions.js +32 -0
  11. package/addon/services/vehicle-actions.js +4 -2
  12. package/addon/styles/fleetops-engine.css +0 -1
  13. package/composer.json +8 -3
  14. package/extension.json +1 -1
  15. package/index.js +7 -1
  16. package/package.json +2 -1
  17. package/scripts/coverage-file-runner.php +240 -0
  18. package/scripts/coverage-runner.php +2 -1
  19. package/scripts/coverage-summary.php +41 -2
  20. package/scripts/pest-bootstrap.php +237 -3
  21. package/scripts/pest-file-runner.php +13 -1
  22. package/scripts/pest-runner.php +57 -2
  23. package/server/config/fleetops.php +44 -0
  24. package/server/config/geocoder.php +1 -1
  25. package/server/migrations/2026_08_08_000001_make_sku_and_provider_transaction_unique_indexes_soft_delete_aware.php +152 -0
  26. package/server/resources/views/labels/entity-label.php +4 -4
  27. package/server/src/Casts/MultiPolygon.php +8 -3
  28. package/server/src/Casts/OrderConfigEntities.php +10 -3
  29. package/server/src/Casts/Point.php +10 -6
  30. package/server/src/Casts/Polygon.php +5 -2
  31. package/server/src/Console/Commands/AssignCustomerRoles.php +28 -6
  32. package/server/src/Console/Commands/AssignDriverRoles.php +36 -6
  33. package/server/src/Console/Commands/AuditCustomerUserConflicts.php +6 -1
  34. package/server/src/Console/Commands/DispatchAdhocOrders.php +12 -2
  35. package/server/src/Console/Commands/FixCustomerCompanies.php +46 -11
  36. package/server/src/Console/Commands/FixDriverCompanies.php +18 -3
  37. package/server/src/Console/Commands/FixLegacyOrderConfigs.php +31 -6
  38. package/server/src/Console/Commands/ProcessMaintenanceTriggers.php +94 -42
  39. package/server/src/Console/Commands/PurgeUnpurchasedServiceQuotes.php +42 -12
  40. package/server/src/Console/Commands/ReplayVehicleLocations.php +120 -55
  41. package/server/src/Console/Commands/SendDriverNotification.php +25 -4
  42. package/server/src/Console/Commands/SendMaintenanceReminders.php +43 -23
  43. package/server/src/Console/Commands/SimulateOrderRouteNavigation.php +36 -6
  44. package/server/src/Console/Commands/TrackOrderDistanceAndTime.php +6 -1
  45. package/server/src/Events/DriverLocationChanged.php +1 -1
  46. package/server/src/Events/DriverSimulatedLocationChanged.php +1 -1
  47. package/server/src/Events/EntityActivityChanged.php +1 -1
  48. package/server/src/Events/EntityCompleted.php +1 -1
  49. package/server/src/Events/EntityDriverAssigned.php +1 -1
  50. package/server/src/Events/FuelProviderTransactionImported.php +1 -1
  51. package/server/src/Events/FuelProviderTransactionMatched.php +1 -1
  52. package/server/src/Events/FuelProviderTransactionUnmatched.php +1 -1
  53. package/server/src/Events/FuelReportCreatedFromProvider.php +1 -1
  54. package/server/src/Events/GeofenceDwelled.php +1 -1
  55. package/server/src/Events/GeofenceEntered.php +1 -1
  56. package/server/src/Events/GeofenceExited.php +1 -1
  57. package/server/src/Events/VehicleLocationChanged.php +1 -1
  58. package/server/src/Events/WaypointActivityChanged.php +1 -1
  59. package/server/src/Events/WaypointCompleted.php +1 -1
  60. package/server/src/Exceptions/IntegratedVendorException.php +2 -2
  61. package/server/src/Exceptions/TelematicRateLimitExceededException.php +1 -1
  62. package/server/src/Http/Controllers/Api/v1/ContactController.php +89 -22
  63. package/server/src/Http/Controllers/Api/v1/CustomerController.php +346 -101
  64. package/server/src/Http/Controllers/Api/v1/DeviceController.php +48 -14
  65. package/server/src/Http/Controllers/Api/v1/DriverController.php +224 -64
  66. package/server/src/Http/Controllers/Api/v1/EntityController.php +112 -66
  67. package/server/src/Http/Controllers/Api/v1/EquipmentController.php +40 -10
  68. package/server/src/Http/Controllers/Api/v1/FleetController.php +54 -14
  69. package/server/src/Http/Controllers/Api/v1/FuelReportController.php +54 -14
  70. package/server/src/Http/Controllers/Api/v1/FuelTransactionController.php +36 -11
  71. package/server/src/Http/Controllers/Api/v1/GeofenceController.php +73 -23
  72. package/server/src/Http/Controllers/Api/v1/IssueController.php +54 -14
  73. package/server/src/Http/Controllers/Api/v1/LabelController.php +61 -22
  74. package/server/src/Http/Controllers/Api/v1/NavigatorController.php +32 -15
  75. package/server/src/Http/Controllers/Api/v1/OrderConfigController.php +35 -5
  76. package/server/src/Http/Controllers/Api/v1/OrderController.php +388 -203
  77. package/server/src/Http/Controllers/Api/v1/PartController.php +40 -10
  78. package/server/src/Http/Controllers/Api/v1/PayloadController.php +90 -30
  79. package/server/src/Http/Controllers/Api/v1/PlaceController.php +188 -91
  80. package/server/src/Http/Controllers/Api/v1/PurchaseRateController.php +100 -36
  81. package/server/src/Http/Controllers/Api/v1/ServiceAreaController.php +96 -26
  82. package/server/src/Http/Controllers/Api/v1/ServiceQuoteController.php +169 -81
  83. package/server/src/Http/Controllers/Api/v1/ServiceRateController.php +104 -75
  84. package/server/src/Http/Controllers/Api/v1/TrackingNumberController.php +92 -14
  85. package/server/src/Http/Controllers/Api/v1/TrackingStatusController.php +66 -16
  86. package/server/src/Http/Controllers/Api/v1/VehicleController.php +121 -67
  87. package/server/src/Http/Controllers/Api/v1/VendorController.php +54 -14
  88. package/server/src/Http/Controllers/Api/v1/WorkOrderController.php +47 -12
  89. package/server/src/Http/Controllers/Api/v1/ZoneController.php +84 -24
  90. package/server/src/Http/Controllers/Concerns/ResolvesReviewAccountBypass.php +62 -0
  91. package/server/src/Http/Controllers/Internal/v1/AnalyticsController.php +15 -5
  92. package/server/src/Http/Controllers/Internal/v1/ContactController.php +113 -28
  93. package/server/src/Http/Controllers/Internal/v1/CustomerController.php +36 -11
  94. package/server/src/Http/Controllers/Internal/v1/DeviceController.php +9 -4
  95. package/server/src/Http/Controllers/Internal/v1/DriverController.php +168 -70
  96. package/server/src/Http/Controllers/Internal/v1/EquipmentController.php +18 -3
  97. package/server/src/Http/Controllers/Internal/v1/FleetController.php +137 -60
  98. package/server/src/Http/Controllers/Internal/v1/FleetOpsLookupController.php +24 -9
  99. package/server/src/Http/Controllers/Internal/v1/FuelReportController.php +18 -3
  100. package/server/src/Http/Controllers/Internal/v1/GeocoderController.php +26 -8
  101. package/server/src/Http/Controllers/Internal/v1/GettingStartedController.php +12 -2
  102. package/server/src/Http/Controllers/Internal/v1/IntegratedVendorController.php +27 -6
  103. package/server/src/Http/Controllers/Internal/v1/IssueController.php +82 -29
  104. package/server/src/Http/Controllers/Internal/v1/MaintenanceController.php +34 -26
  105. package/server/src/Http/Controllers/Internal/v1/MaintenanceScheduleController.php +141 -97
  106. package/server/src/Http/Controllers/Internal/v1/ManifestController.php +28 -8
  107. package/server/src/Http/Controllers/Internal/v1/MetricsController.php +21 -12
  108. package/server/src/Http/Controllers/Internal/v1/MorphController.php +90 -18
  109. package/server/src/Http/Controllers/Internal/v1/NavigatorController.php +88 -35
  110. package/server/src/Http/Controllers/Internal/v1/OrchestrationController.php +149 -39
  111. package/server/src/Http/Controllers/Internal/v1/OrderConfigController.php +54 -18
  112. package/server/src/Http/Controllers/Internal/v1/OrderController.php +298 -86
  113. package/server/src/Http/Controllers/Internal/v1/PartController.php +18 -3
  114. package/server/src/Http/Controllers/Internal/v1/PaymentController.php +46 -14
  115. package/server/src/Http/Controllers/Internal/v1/PlaceController.php +31 -5
  116. package/server/src/Http/Controllers/Internal/v1/ProofController.php +88 -48
  117. package/server/src/Http/Controllers/Internal/v1/SearchController.php +1 -1
  118. package/server/src/Http/Controllers/Internal/v1/SensorController.php +6 -1
  119. package/server/src/Http/Controllers/Internal/v1/ServiceAreaController.php +6 -1
  120. package/server/src/Http/Controllers/Internal/v1/ServiceQuoteController.php +255 -105
  121. package/server/src/Http/Controllers/Internal/v1/SettingController.php +88 -35
  122. package/server/src/Http/Controllers/Internal/v1/TelematicController.php +1 -4
  123. package/server/src/Http/Controllers/Internal/v1/Traits/DriverSchedulingTrait.php +42 -14
  124. package/server/src/Http/Controllers/Internal/v1/VendorController.php +103 -33
  125. package/server/src/Http/Controllers/Internal/v1/WorkOrderController.php +42 -12
  126. package/server/src/Http/Filter/DriverFilter.php +2 -2
  127. package/server/src/Http/Filter/MaintenanceScheduleFilter.php +40 -0
  128. package/server/src/Http/Filter/OrderFilter.php +1 -1
  129. package/server/src/Http/Filter/VehicleFilter.php +21 -7
  130. package/server/src/Http/Middleware/AuthenticateCustomerToken.php +12 -2
  131. package/server/src/Http/Requests/BulkDispatchRequest.php +3 -9
  132. package/server/src/Http/Requests/CancelOrderRequest.php +2 -6
  133. package/server/src/Http/Requests/CreateContactRequest.php +2 -6
  134. package/server/src/Http/Requests/CreateCustomerRequest.php +9 -1
  135. package/server/src/Http/Requests/CreateDeviceRequest.php +2 -2
  136. package/server/src/Http/Requests/CreateDriverRequest.php +3 -9
  137. package/server/src/Http/Requests/CreateEntityRequest.php +2 -6
  138. package/server/src/Http/Requests/CreateEquipmentRequest.php +2 -2
  139. package/server/src/Http/Requests/CreateFleetRequest.php +2 -6
  140. package/server/src/Http/Requests/CreateFuelReportRequest.php +16 -9
  141. package/server/src/Http/Requests/CreateFuelTransactionRequest.php +66 -3
  142. package/server/src/Http/Requests/CreateIssueRequest.php +2 -6
  143. package/server/src/Http/Requests/CreateOrderRequest.php +7 -8
  144. package/server/src/Http/Requests/CreatePartRequest.php +41 -3
  145. package/server/src/Http/Requests/CreatePayloadRequest.php +7 -9
  146. package/server/src/Http/Requests/CreatePlaceRequest.php +2 -6
  147. package/server/src/Http/Requests/CreatePurchaseRateRequest.php +2 -6
  148. package/server/src/Http/Requests/CreateSensorRequest.php +2 -2
  149. package/server/src/Http/Requests/CreateServiceAreaRequest.php +2 -6
  150. package/server/src/Http/Requests/CreateServiceQuoteRequest.php +2 -6
  151. package/server/src/Http/Requests/CreateServiceRateRequest.php +2 -6
  152. package/server/src/Http/Requests/CreateTrackingNumberRequest.php +2 -6
  153. package/server/src/Http/Requests/CreateTrackingStatusRequest.php +2 -6
  154. package/server/src/Http/Requests/CreateVehicleRequest.php +2 -6
  155. package/server/src/Http/Requests/CreateVendorRequest.php +2 -6
  156. package/server/src/Http/Requests/CreateWorkOrderRequest.php +2 -2
  157. package/server/src/Http/Requests/CreateZoneRequest.php +2 -6
  158. package/server/src/Http/Requests/DecodeTrackingNumberQR.php +2 -6
  159. package/server/src/Http/Requests/DriverSimulationRequest.php +2 -6
  160. package/server/src/Http/Requests/Internal/AssignOrderRequest.php +3 -7
  161. package/server/src/Http/Requests/Internal/CreateDriverRequest.php +4 -12
  162. package/server/src/Http/Requests/Internal/CreateOrderConfigRequest.php +2 -6
  163. package/server/src/Http/Requests/Internal/CreateOrderRequest.php +7 -8
  164. package/server/src/Http/Requests/Internal/FleetActionRequest.php +18 -12
  165. package/server/src/Http/Requests/Internal/UpdateDriverRequest.php +6 -3
  166. package/server/src/Http/Requests/QueryServiceQuotesRequest.php +2 -6
  167. package/server/src/Http/Requests/ScheduleOrderRequest.php +2 -6
  168. package/server/src/Http/Requests/UpdateIssueRequest.php +1 -3
  169. package/server/src/Http/Resources/v1/Customer.php +2 -2
  170. package/server/src/Http/Resources/v1/Maintenance.php +3 -4
  171. package/server/src/Http/Resources/v1/MaintenanceSchedule.php +3 -4
  172. package/server/src/Http/Resources/v1/Order.php +3 -7
  173. package/server/src/Http/Resources/v1/PurchaseRate.php +4 -6
  174. package/server/src/Http/Resources/v1/TrackingNumber.php +33 -0
  175. package/server/src/Http/Resources/v1/TrackingStatus.php +4 -6
  176. package/server/src/Http/Resources/v1/WorkOrder.php +3 -4
  177. package/server/src/Imports/ContactImport.php +10 -1
  178. package/server/src/Imports/DriverImport.php +10 -1
  179. package/server/src/Imports/EquipmentImport.php +6 -1
  180. package/server/src/Imports/FleetImport.php +10 -1
  181. package/server/src/Imports/FuelReportImport.php +10 -1
  182. package/server/src/Imports/IssueImport.php +10 -1
  183. package/server/src/Imports/MaintenanceImport.php +6 -1
  184. package/server/src/Imports/MaintenanceScheduleImport.php +6 -1
  185. package/server/src/Imports/PartImport.php +6 -1
  186. package/server/src/Imports/PlaceImport.php +10 -1
  187. package/server/src/Imports/VehicleImport.php +10 -1
  188. package/server/src/Imports/VendorImport.php +10 -1
  189. package/server/src/Imports/WorkOrderImport.php +6 -1
  190. package/server/src/Integrations/Lalamove/Lalamove.php +3 -7
  191. package/server/src/Integrations/Lalamove/LalamoveServiceType.php +5 -8
  192. package/server/src/Jobs/CheckGeofenceDwell.php +41 -16
  193. package/server/src/Jobs/FinalizeApiOrderCreation.php +17 -2
  194. package/server/src/Jobs/FinalizeInternalOrderCreation.php +11 -1
  195. package/server/src/Jobs/NotifyBulkAssignedDriver.php +29 -16
  196. package/server/src/Jobs/ProcessAllocationJob.php +59 -25
  197. package/server/src/Jobs/ReplayPositions.php +17 -10
  198. package/server/src/Jobs/SendPositionReplay.php +18 -7
  199. package/server/src/Jobs/SimulateDrivingRoute.php +14 -3
  200. package/server/src/Jobs/SyncFuelProviderTransactionsJob.php +12 -2
  201. package/server/src/Listeners/HandleDeliveryCompletion.php +11 -1
  202. package/server/src/Listeners/HandleGeofenceDwelled.php +6 -1
  203. package/server/src/Listeners/HandleGeofenceEntered.php +4 -2
  204. package/server/src/Listeners/HandleGeofenceExited.php +6 -1
  205. package/server/src/Listeners/HandleOrderCanceled.php +18 -3
  206. package/server/src/Listeners/HandleOrderDispatchFailed.php +12 -2
  207. package/server/src/Listeners/HandleOrderDispatched.php +61 -26
  208. package/server/src/Listeners/HandleOrderDriverAssigned.php +12 -2
  209. package/server/src/Listeners/HandleUserRemovedFromCompany.php +19 -6
  210. package/server/src/Listeners/NotifyDriverOnShiftChange.php +24 -4
  211. package/server/src/Listeners/NotifyOrderEvent.php +11 -6
  212. package/server/src/Models/Contact.php +6 -7
  213. package/server/src/Models/Device.php +26 -3
  214. package/server/src/Models/Driver.php +0 -6
  215. package/server/src/Models/Entity.php +4 -4
  216. package/server/src/Models/Equipment.php +1 -1
  217. package/server/src/Models/FuelReport.php +26 -1
  218. package/server/src/Models/IntegratedVendor.php +2 -2
  219. package/server/src/Models/Issue.php +5 -1
  220. package/server/src/Models/MaintenanceSchedule.php +25 -10
  221. package/server/src/Models/Order.php +18 -15
  222. package/server/src/Models/OrderConfig.php +1 -1
  223. package/server/src/Models/Payload.php +9 -16
  224. package/server/src/Models/Place.php +20 -13
  225. package/server/src/Models/Sensor.php +24 -0
  226. package/server/src/Models/ServiceArea.php +3 -6
  227. package/server/src/Models/ServiceQuote.php +5 -0
  228. package/server/src/Models/ServiceRate.php +13 -6
  229. package/server/src/Models/Telematic.php +2 -2
  230. package/server/src/Models/TrackingNumber.php +55 -10
  231. package/server/src/Models/TrackingStatus.php +24 -4
  232. package/server/src/Models/Waypoint.php +44 -10
  233. package/server/src/Models/Zone.php +3 -6
  234. package/server/src/Notifications/DriverArrivedAtGeofence.php +1 -1
  235. package/server/src/Notifications/OrderDispatched.php +3 -9
  236. package/server/src/Notifications/OrderPing.php +3 -9
  237. package/server/src/Observers/CategoryObserver.php +6 -1
  238. package/server/src/Observers/CompanyObserver.php +5 -0
  239. package/server/src/Observers/CompanyUserObserver.php +12 -2
  240. package/server/src/Observers/DriverObserver.php +19 -4
  241. package/server/src/Observers/FleetObserver.php +6 -1
  242. package/server/src/Observers/PurchaseRateObserver.php +66 -11
  243. package/server/src/Observers/ServiceAreaObserver.php +12 -2
  244. package/server/src/Observers/ServiceRateObserver.php +21 -6
  245. package/server/src/Observers/TrackingNumberObserver.php +19 -4
  246. package/server/src/Observers/UserObserver.php +6 -1
  247. package/server/src/Observers/VehicleObserver.php +27 -7
  248. package/server/src/Observers/WorkOrderObserver.php +27 -7
  249. package/server/src/Orchestration/Engines/DriverAssignmentEngine.php +8 -3
  250. package/server/src/Orchestration/Support/OrchestrationPayloadBuilder.php +2 -2
  251. package/server/src/Providers/FleetOpsServiceProvider.php +12 -0
  252. package/server/src/Providers/NotificationServiceProvider.php +6 -0
  253. package/server/src/Support/Ai/Capabilities/AssetStatusCapability.php +36 -26
  254. package/server/src/Support/Ai/Capabilities/CreateOrderPreviewCapability.php +18 -5
  255. package/server/src/Support/Ai/Capabilities/OrderInsightsCapability.php +6 -1
  256. package/server/src/Support/Ai/Capabilities/SearchResourcesCapability.php +26 -6
  257. package/server/src/Support/Analytics/FuelEfficiency.php +9 -3
  258. package/server/src/Support/Analytics/FuelProviderSummary.php +14 -5
  259. package/server/src/Support/Analytics/GeofenceViolations.php +40 -20
  260. package/server/src/Support/Analytics/IssuesInsights.php +38 -18
  261. package/server/src/Support/Analytics/MaintenanceOverview.php +51 -21
  262. package/server/src/Support/Analytics/OnTimeDelivery.php +3 -2
  263. package/server/src/Support/Analytics/OperationsPulse.php +59 -35
  264. package/server/src/Support/Analytics/OrdersByStatus.php +12 -7
  265. package/server/src/Support/Analytics/RevenueTrend.php +16 -6
  266. package/server/src/Support/Analytics/TopDrivers.php +3 -2
  267. package/server/src/Support/FleetOps.php +109 -104
  268. package/server/src/Support/FuelProviders/FuelProviderService.php +10 -1
  269. package/server/src/Support/Geocoding.php +52 -14
  270. package/server/src/Support/GeofenceIntersectionService.php +47 -27
  271. package/server/src/Support/LiveOrderQuery.php +6 -1
  272. package/server/src/Support/Metrics/ActiveRevenueQuery.php +3 -2
  273. package/server/src/Support/Metrics/FuelCostsMetric.php +6 -1
  274. package/server/src/Support/ResolvesOrderServiceStops.php +10 -0
  275. package/server/src/Support/Telematics/Providers/GeotabProvider.php +9 -4
  276. package/server/src/Support/Utils.php +122 -16
  277. package/server/src/Tracking/Providers/GoogleRoutesTrackingProvider.php +6 -1
  278. package/server/src/Tracking/Providers/OsrmTrackingProvider.php +11 -6
  279. package/server/src/Tracking/TrackingProviderManager.php +2 -3
  280. package/server/src/Tracking/TrackingProviderRegistry.php +8 -4
  281. package/server/src/Traits/PayloadAccessors.php +6 -1
  282. package/server/src/routes.php +24 -17
  283. package/server/tests/AiOperationalQueryCapabilityTest.php +457 -1
  284. package/server/tests/AiPreviewCapabilityContractsTest.php +180 -0
  285. package/server/tests/AnalyticsRoutesTest.php +380 -1
  286. package/server/tests/AnalyticsWidgetContractsTest.php +740 -0
  287. package/server/tests/ApiContactControllerContractsTest.php +284 -0
  288. package/server/tests/ApiCustomerControllerContractsTest.php +1130 -0
  289. package/server/tests/ApiDriverControllerContractsTest.php +603 -0
  290. package/server/tests/ApiEntityControllerContractsTest.php +329 -0
  291. package/server/tests/ApiEquipmentControllerContractsTest.php +239 -0
  292. package/server/tests/ApiFleetControllerContractsTest.php +176 -0
  293. package/server/tests/ApiFuelReportControllerContractsTest.php +217 -0
  294. package/server/tests/ApiIssueControllerContractsTest.php +217 -0
  295. package/server/tests/ApiOrderControllerContractsTest.php +1030 -0
  296. package/server/tests/ApiPartControllerContractsTest.php +251 -0
  297. package/server/tests/ApiPayloadControllerContractsTest.php +314 -0
  298. package/server/tests/ApiPlaceControllerContractsTest.php +541 -0
  299. package/server/tests/ApiPurchaseRateControllerContractsTest.php +283 -0
  300. package/server/tests/ApiServiceAreaZoneControllerContractsTest.php +442 -0
  301. package/server/tests/ApiServiceQuoteControllerContractsTest.php +322 -0
  302. package/server/tests/ApiTrackingNumberControllerContractsTest.php +225 -0
  303. package/server/tests/ApiTrackingStatusControllerContractsTest.php +254 -0
  304. package/server/tests/ApiVehicleControllerContractsTest.php +368 -0
  305. package/server/tests/ApiVendorControllerContractsTest.php +199 -0
  306. package/server/tests/AssetAndPlaceSearchContractsTest.php +220 -0
  307. package/server/tests/BackendSmallModelContractsTest.php +354 -0
  308. package/server/tests/CapacityAllocationEngineTest.php +56 -0
  309. package/server/tests/CommandContractsTest.php +2695 -0
  310. package/server/tests/CompactResourceSerializationTest.php +2838 -0
  311. package/server/tests/ControllerFilterContractsTest.php +1273 -0
  312. package/server/tests/ControllerHelperContractsTest.php +1740 -0
  313. package/server/tests/ControllerSerializationContractsTest.php +141 -0
  314. package/server/tests/CoverageSummaryScriptTest.php +93 -0
  315. package/server/tests/CustomerContactIdentitySafetyTest.php +1 -6
  316. package/server/tests/CustomerEndpointTest.php +169 -2
  317. package/server/tests/DriverFilterExecutionTest.php +263 -0
  318. package/server/tests/DriverGeofenceProcessingTest.php +153 -0
  319. package/server/tests/DriverResourceSerializationTest.php +245 -0
  320. package/server/tests/DriverSchedulingTraitContractsTest.php +259 -0
  321. package/server/tests/EventContractsTest.php +1259 -0
  322. package/server/tests/ExceptionContractsTest.php +81 -0
  323. package/server/tests/ExpansionContractsTest.php +242 -0
  324. package/server/tests/ExportCoverageTest.php +116 -0
  325. package/server/tests/Feature/Http/Api/ContactControllerPhotoAndDeleteTest.php +199 -0
  326. package/server/tests/Feature/Http/Api/CustomerControllerHelperSeamsTest.php +831 -0
  327. package/server/tests/Feature/Http/Api/DeviceControllerContractsTest.php +347 -0
  328. package/server/tests/Feature/Http/Api/DeviceControllerCrudTest.php +176 -0
  329. package/server/tests/Feature/Http/Api/DriverControllerAuthFlowsTest.php +530 -0
  330. package/server/tests/Feature/Http/Api/DriverControllerHelpersTest.php +240 -0
  331. package/server/tests/Feature/Http/Api/DriverControllerLookupTest.php +186 -0
  332. package/server/tests/Feature/Http/Api/DriverControllerOrganizationsTest.php +112 -0
  333. package/server/tests/Feature/Http/Api/DriverControllerSessionHelpersTest.php +207 -0
  334. package/server/tests/Feature/Http/Api/DriverControllerSwitchOrgAndGeofenceTest.php +329 -0
  335. package/server/tests/Feature/Http/Api/DriverControllerTrackTest.php +383 -0
  336. package/server/tests/Feature/Http/Api/EntityControllerHelpersTest.php +150 -0
  337. package/server/tests/Feature/Http/Api/FuelTransactionControllerContractsTest.php +352 -0
  338. package/server/tests/Feature/Http/Api/GeofenceControllerContractsTest.php +461 -0
  339. package/server/tests/Feature/Http/Api/LabelControllerSubjectsTest.php +148 -0
  340. package/server/tests/Feature/Http/Api/OrderConfigControllerTest.php +112 -0
  341. package/server/tests/Feature/Http/Api/OrderControllerCreateTest.php +279 -0
  342. package/server/tests/Feature/Http/Api/OrderControllerIntegratedVendorTest.php +295 -0
  343. package/server/tests/Feature/Http/Api/OrderControllerLifecycleActionsTest.php +279 -0
  344. package/server/tests/Feature/Http/Api/OrderControllerLookupHelpersTest.php +207 -0
  345. package/server/tests/Feature/Http/Api/OrderControllerNearbyFiltersTest.php +282 -0
  346. package/server/tests/Feature/Http/Api/OrderControllerPersistenceHelpersTest.php +216 -0
  347. package/server/tests/Feature/Http/Api/OrderControllerQueryFiltersTest.php +184 -0
  348. package/server/tests/Feature/Http/Api/OrderControllerStartActivityTest.php +663 -0
  349. package/server/tests/Feature/Http/Api/PayloadControllerHelpersTest.php +134 -0
  350. package/server/tests/Feature/Http/Api/PlaceAndServiceQuoteSeamsTest.php +479 -0
  351. package/server/tests/Feature/Http/Api/PurchaseRateControllerHelpersTest.php +176 -0
  352. package/server/tests/Feature/Http/Api/PurchaseRateControllerOrderCreationTest.php +268 -0
  353. package/server/tests/Feature/Http/Api/SensorControllerCrudTest.php +239 -0
  354. package/server/tests/Feature/Http/Api/ServiceAreaControllerBorderAndSeamsTest.php +187 -0
  355. package/server/tests/Feature/Http/Api/ServiceQuoteControllerQueryTest.php +405 -0
  356. package/server/tests/Feature/Http/Api/ServiceQuoteControllerVendorBridgeTest.php +212 -0
  357. package/server/tests/Feature/Http/Api/ServiceRateControllerContractsTest.php +263 -0
  358. package/server/tests/Feature/Http/Api/SmallApiControllerHelpersTest.php +272 -0
  359. package/server/tests/Feature/Http/Api/TrackingNumberControllerHelpersTest.php +160 -0
  360. package/server/tests/Feature/Http/Api/TrackingStatusControllerHelpersTest.php +165 -0
  361. package/server/tests/Feature/Http/Api/VehicleControllerTrackingTest.php +483 -0
  362. package/server/tests/Feature/Http/Api/WorkOrderControllerContractsTest.php +326 -0
  363. package/server/tests/Feature/Http/Api/WorkOrderControllerHelpersTest.php +130 -0
  364. package/server/tests/Feature/Http/Api/ZoneControllerBordersAndSeamsTest.php +294 -0
  365. package/server/tests/Feature/Http/FleetOpsRouteRegistrationTest.php +189 -0
  366. package/server/tests/Feature/Http/Internal/AnalyticsControllerSeamsTest.php +53 -0
  367. package/server/tests/Feature/Http/Internal/ContactControllerContractsTest.php +240 -0
  368. package/server/tests/Feature/Http/Internal/ContactControllerCustomerGuardsTest.php +128 -0
  369. package/server/tests/Feature/Http/Internal/ContactControllerEndpointsTest.php +294 -0
  370. package/server/tests/Feature/Http/Internal/CustomerControllerCredentialsTest.php +196 -0
  371. package/server/tests/Feature/Http/Internal/DeviceControllerContractsTest.php +370 -0
  372. package/server/tests/Feature/Http/Internal/DeviceControllerExportAndFiltersTest.php +151 -0
  373. package/server/tests/Feature/Http/Internal/DriverControllerContractsTest.php +1167 -0
  374. package/server/tests/Feature/Http/Internal/DriverControllerCreateRecordTest.php +233 -0
  375. package/server/tests/Feature/Http/Internal/DriverControllerExistingUserAdoptionTest.php +710 -0
  376. package/server/tests/Feature/Http/Internal/DriverControllerHelpersTest.php +218 -0
  377. package/server/tests/Feature/Http/Internal/FleetAssignmentsAndTriggersTest.php +198 -0
  378. package/server/tests/Feature/Http/Internal/FleetOpsLookupControllerDbTest.php +90 -0
  379. package/server/tests/Feature/Http/Internal/HubControllerTest.php +206 -0
  380. package/server/tests/Feature/Http/Internal/IssueControllerContractsTest.php +404 -0
  381. package/server/tests/Feature/Http/Internal/IssueControllerExportImportTest.php +118 -0
  382. package/server/tests/Feature/Http/Internal/LiveControllerEndpointsTest.php +246 -0
  383. package/server/tests/Feature/Http/Internal/LiveControllerTest.php +778 -0
  384. package/server/tests/Feature/Http/Internal/MaintenanceScheduleControllerContractsTest.php +263 -0
  385. package/server/tests/Feature/Http/Internal/MaintenanceScheduleControllerSurfacesTest.php +214 -0
  386. package/server/tests/Feature/Http/Internal/MetricsControllerContractsTest.php +249 -0
  387. package/server/tests/Feature/Http/Internal/MetricsControllerHelpersTest.php +66 -0
  388. package/server/tests/Feature/Http/Internal/MorphControllerHelpersTest.php +125 -0
  389. package/server/tests/Feature/Http/Internal/NavigatorControllerHelpersTest.php +201 -0
  390. package/server/tests/Feature/Http/Internal/OrchestrationControllerContractsTest.php +928 -0
  391. package/server/tests/Feature/Http/Internal/OrchestrationControllerHelpersTest.php +214 -0
  392. package/server/tests/Feature/Http/Internal/OrchestrationControllerImportOrdersTest.php +340 -0
  393. package/server/tests/Feature/Http/Internal/OrderConfigControllerContractsTest.php +314 -0
  394. package/server/tests/Feature/Http/Internal/OrderControllerActivityFlowsTest.php +663 -0
  395. package/server/tests/Feature/Http/Internal/OrderControllerCapturePhotoTest.php +507 -0
  396. package/server/tests/Feature/Http/Internal/OrderControllerContractsTest.php +1742 -0
  397. package/server/tests/Feature/Http/Internal/OrderControllerCreateRecordTest.php +488 -0
  398. package/server/tests/Feature/Http/Internal/OrderControllerHelperSeamsTest.php +298 -0
  399. package/server/tests/Feature/Http/Internal/OrderControllerHelpersTest.php +267 -0
  400. package/server/tests/Feature/Http/Internal/OrderControllerImportFromFilesTest.php +179 -0
  401. package/server/tests/Feature/Http/Internal/OrderControllerUpstreamNotFoundTest.php +80 -0
  402. package/server/tests/Feature/Http/Internal/PaymentControllerPaymentsTest.php +154 -0
  403. package/server/tests/Feature/Http/Internal/PlaceControllerTest.php +252 -0
  404. package/server/tests/Feature/Http/Internal/PositionControllerReplayMetricsTest.php +163 -0
  405. package/server/tests/Feature/Http/Internal/ProofControllerContractsTest.php +219 -0
  406. package/server/tests/Feature/Http/Internal/SearchControllerEndpointTest.php +151 -0
  407. package/server/tests/Feature/Http/Internal/ServiceQuoteControllerHelpersTest.php +208 -0
  408. package/server/tests/Feature/Http/Internal/ServiceQuoteControllerQueryRecordTest.php +217 -0
  409. package/server/tests/Feature/Http/Internal/ServiceQuoteControllerVendorBridgeTest.php +239 -0
  410. package/server/tests/Feature/Http/Internal/ServiceQuotePreliminaryQueryTest.php +271 -0
  411. package/server/tests/Feature/Http/Internal/SettingControllerHelpersTest.php +133 -0
  412. package/server/tests/Feature/Http/Internal/SmallInternalControllersTest.php +180 -0
  413. package/server/tests/Feature/Http/Internal/TelematicControllerEndpointsTest.php +417 -0
  414. package/server/tests/Feature/Http/Internal/VehicleControllerEndpointsTest.php +361 -0
  415. package/server/tests/Feature/Http/Internal/VendorControllerEndpointsTest.php +203 -0
  416. package/server/tests/Feature/Http/Internal/WorkOrderAndConfigSurfacesTest.php +289 -0
  417. package/server/tests/Feature/Http/Internal/WorkOrderControllerContractsTest.php +199 -0
  418. package/server/tests/Feature/Http/TelematicWebhookIngestTest.php +343 -0
  419. package/server/tests/Feature/Http/Telematics/TelematicWebhookControllerProcessingTest.php +254 -0
  420. package/server/tests/FleetOpsSupportContractsTest.php +187 -0
  421. package/server/tests/FlespiProviderContractsTest.php +244 -0
  422. package/server/tests/FlowResourceTest.php +295 -0
  423. package/server/tests/FuelProviderConnectionControllerContractsTest.php +303 -0
  424. package/server/tests/FuelProviderImplementationTest.php +753 -0
  425. package/server/tests/FuelProviderResourceContractsTest.php +171 -0
  426. package/server/tests/FuelProviderTransactionControllerContractsTest.php +198 -0
  427. package/server/tests/GeofenceIntersectionServiceContractsTest.php +164 -0
  428. package/server/tests/HOSConstraintContractsTest.php +128 -0
  429. package/server/tests/HubAndGettingStartedContractsTest.php +158 -0
  430. package/server/tests/ImportContractsTest.php +191 -0
  431. package/server/tests/InternalCustomerControllerContractsTest.php +238 -0
  432. package/server/tests/InternalFleetControllerContractsTest.php +389 -0
  433. package/server/tests/InternalImportExportControllerContractsTest.php +289 -0
  434. package/server/tests/InternalMetricsControllerContractsTest.php +69 -0
  435. package/server/tests/InternalPlaceWorkOrderControllerContractsTest.php +207 -0
  436. package/server/tests/InternalServiceQuoteCheckoutControllerContractsTest.php +470 -0
  437. package/server/tests/InternalVendorControllerContractsTest.php +331 -0
  438. package/server/tests/InventoryTelemetryModelContractsTest.php +516 -0
  439. package/server/tests/IssueTimelineContractsTest.php +191 -0
  440. package/server/tests/LabelPdfRenderingTest.php +57 -0
  441. package/server/tests/LalamoveIntegrationContractsTest.php +167 -0
  442. package/server/tests/LiveOrderQueryTest.php +145 -18
  443. package/server/tests/LookupAndGeocoderControllerContractsTest.php +357 -0
  444. package/server/tests/MaintainableTraitContractsTest.php +245 -0
  445. package/server/tests/MaintenanceScheduleControllerContractsTest.php +101 -0
  446. package/server/tests/MaintenanceWarrantyContractsTest.php +237 -0
  447. package/server/tests/ManifestControllerContractsTest.php +310 -0
  448. package/server/tests/MetricsRegistryTest.php +596 -10
  449. package/server/tests/MiddlewareContractsTest.php +150 -0
  450. package/server/tests/ModelAccessorContractsTest.php +3201 -0
  451. package/server/tests/MorphControllerContractsTest.php +410 -0
  452. package/server/tests/NavigatorControllerContractsTest.php +206 -0
  453. package/server/tests/NotificationAndMailContractsTest.php +677 -0
  454. package/server/tests/ObserverContractsTest.php +1414 -0
  455. package/server/tests/OperationalAlgorithmContractsTest.php +852 -0
  456. package/server/tests/OperationsMonitorEndpointTest.php +2 -1
  457. package/server/tests/OrchestrationPayloadBuilderTest.php +87 -0
  458. package/server/tests/OrderActivityFlowRegressionTest.php +354 -7
  459. package/server/tests/OrderDispatchListenerContractsTest.php +577 -0
  460. package/server/tests/OrderFilterExecutionTest.php +244 -0
  461. package/server/tests/OrderQueuedClosureRegressionTest.php +2 -1
  462. package/server/tests/PaymentControllerContractsTest.php +199 -0
  463. package/server/tests/PointResolutionTest.php +54 -0
  464. package/server/tests/ProcessAllocationJobContractsTest.php +224 -0
  465. package/server/tests/ProofAndSensorControllerContractsTest.php +44 -0
  466. package/server/tests/ProviderContractsTest.php +409 -0
  467. package/server/tests/PublicApiControllerInputContractsTest.php +294 -0
  468. package/server/tests/QueueJobContractsTest.php +764 -0
  469. package/server/tests/ReportSchemaContractsTest.php +271 -0
  470. package/server/tests/RequestContractsTest.php +1058 -0
  471. package/server/tests/RouteRegistrationExecutionTest.php +178 -0
  472. package/server/tests/RouteSequencingEngineTest.php +179 -0
  473. package/server/tests/RulesAndCastsTest.php +246 -0
  474. package/server/tests/SamsaraProviderContractsTest.php +272 -0
  475. package/server/tests/SearchControllerContractsTest.php +311 -0
  476. package/server/tests/ServiceRateRouteValidationTest.php +76 -0
  477. package/server/tests/SettingControllerContractsTest.php +410 -0
  478. package/server/tests/SmallControllerContractsTest.php +480 -0
  479. package/server/tests/SupportAnalyticsCustomerAuthContractsTest.php +221 -0
  480. package/server/tests/SupportJobAndAiCoverageTest.php +812 -0
  481. package/server/tests/SupportServiceContractsTest.php +287 -0
  482. package/server/tests/SupportValueObjectsTest.php +155 -0
  483. package/server/tests/TelematicControllerContractsTest.php +185 -0
  484. package/server/tests/TelematicProviderRegistryTest.php +167 -0
  485. package/server/tests/TelematicServiceHelperContractsTest.php +315 -0
  486. package/server/tests/TelematicWebhookControllerContractsTest.php +253 -0
  487. package/server/tests/TelematicsHardeningTest.php +642 -86
  488. package/server/tests/TrackingIntelligenceTest.php +644 -1
  489. package/server/tests/TrackingNumberTraitContractsTest.php +106 -0
  490. package/server/tests/Unit/Casts/SpatialCastBranchesTest.php +75 -0
  491. package/server/tests/Unit/Console/AssignCustomerRolesCommandTest.php +102 -0
  492. package/server/tests/Unit/Console/AssignDriverRolesCommandTest.php +113 -0
  493. package/server/tests/Unit/Console/Commands/FixLegacyOrderConfigsHelpersTest.php +108 -0
  494. package/server/tests/Unit/Console/Commands/ProcessOperationalAlertsCommandTest.php +265 -0
  495. package/server/tests/Unit/Console/Commands/ReplayVehicleLocationsCommandTest.php +320 -0
  496. package/server/tests/Unit/Console/Commands/SimulateGeofenceEventsCommandTest.php +207 -0
  497. package/server/tests/Unit/Console/FixCommandsAndMaintenanceControllerTest.php +256 -0
  498. package/server/tests/Unit/Console/FleetOpsCommandsTest.php +198 -0
  499. package/server/tests/Unit/Console/ReplayVehicleLocationsCommandTest.php +252 -0
  500. package/server/tests/Unit/Console/SendMaintenanceRemindersTest.php +212 -0
  501. package/server/tests/Unit/Console/SimulateGeofenceEventsCommandTest.php +232 -0
  502. package/server/tests/Unit/Console/SyncTelematicsCommandTest.php +136 -0
  503. package/server/tests/Unit/Constraints/HOSConstraintTest.php +158 -0
  504. package/server/tests/Unit/Events/EventModelRecordTest.php +93 -0
  505. package/server/tests/Unit/Events/OrderDispatchFailedTest.php +34 -0
  506. package/server/tests/Unit/Exports/ExportCollectionsTest.php +142 -0
  507. package/server/tests/Unit/Exports/OperationalExportMappingTest.php +651 -0
  508. package/server/tests/Unit/Exports/VehicleExportTest.php +284 -0
  509. package/server/tests/Unit/Flow/EventFiringTest.php +95 -0
  510. package/server/tests/Unit/Http/Api/QueryWithRequestSeamsTest.php +198 -0
  511. package/server/tests/Unit/Http/Api/SensorInputTest.php +95 -0
  512. package/server/tests/Unit/Http/Filter/DeviceFilterTest.php +199 -0
  513. package/server/tests/Unit/Http/Filter/EmptyValueGuardsTest.php +66 -0
  514. package/server/tests/Unit/Http/Filter/FilterDateRangesTest.php +72 -0
  515. package/server/tests/Unit/Http/Filter/FuelProviderTransactionFilterTest.php +172 -0
  516. package/server/tests/Unit/Http/Filter/InternalRelationUuidLookupTest.php +135 -0
  517. package/server/tests/Unit/Http/Filter/IssueFilterTest.php +129 -0
  518. package/server/tests/Unit/Http/Filter/MaintenanceScheduleFilterTest.php +69 -0
  519. package/server/tests/Unit/Http/Filter/PartFilterTest.php +173 -0
  520. package/server/tests/Unit/Http/Internal/ControllerDelegationSeamsTest.php +136 -0
  521. package/server/tests/Unit/Http/Internal/ControllerExcelSeamsTest.php +89 -0
  522. package/server/tests/Unit/Http/Middleware/SetupDriverSessionTest.php +32 -0
  523. package/server/tests/Unit/Http/Requests/CreateFuelReportRequestTest.php +68 -0
  524. package/server/tests/Unit/Http/Requests/FleetActionRequestTest.php +80 -0
  525. package/server/tests/Unit/Http/Requests/RequestAuthorizationTest.php +50 -0
  526. package/server/tests/Unit/Http/Resources/CustomerResourceTest.php +108 -0
  527. package/server/tests/Unit/Http/Resources/EntityCustomerTypeTest.php +35 -0
  528. package/server/tests/Unit/Http/Resources/FleetResourceTest.php +102 -0
  529. package/server/tests/Unit/Http/Resources/IndexOrderResourceTest.php +210 -0
  530. package/server/tests/Unit/Http/Resources/IndexVehicleResourceTest.php +194 -0
  531. package/server/tests/Unit/Http/Resources/MaintenanceResourcesTest.php +182 -0
  532. package/server/tests/Unit/Http/Resources/OrderAndDriverResourceTest.php +121 -0
  533. package/server/tests/Unit/Http/Resources/OrderConfigResourceTest.php +47 -0
  534. package/server/tests/Unit/Http/Resources/PayloadResourceTest.php +111 -0
  535. package/server/tests/Unit/Http/Resources/RelationResourceFallbacksTest.php +32 -0
  536. package/server/tests/Unit/Http/Resources/ResourceRelationResolutionTest.php +55 -0
  537. package/server/tests/Unit/Http/Resources/TrackingNumberResourceTest.php +174 -0
  538. package/server/tests/Unit/Http/Resources/WaypointResourceTest.php +295 -0
  539. package/server/tests/Unit/Http/Resources/WorkOrderResourceTest.php +164 -0
  540. package/server/tests/Unit/Imports/ImportDelegationTest.php +151 -0
  541. package/server/tests/Unit/Integrations/Lalamove/LalamoveDeliveryStopTest.php +79 -0
  542. package/server/tests/Unit/Integrations/Lalamove/LalamoveLifecycleTest.php +211 -0
  543. package/server/tests/Unit/Integrations/Lalamove/LalamoveQuoteAndServiceOrderTest.php +381 -0
  544. package/server/tests/Unit/Integrations/Lalamove/LalamoveServiceTypeTest.php +51 -0
  545. package/server/tests/Unit/Integrations/LalamoveQuotationTest.php +194 -0
  546. package/server/tests/Unit/Integrations/LalamoveResponseHandlingTest.php +58 -0
  547. package/server/tests/Unit/Jobs/GeofenceDwellAndBulkNotifyTest.php +190 -0
  548. package/server/tests/Unit/Jobs/ReplayPositionsTest.php +57 -0
  549. package/server/tests/Unit/Jobs/SimulateWaypointReachedTest.php +92 -0
  550. package/server/tests/Unit/Listeners/HandleGeofenceEnteredTest.php +256 -0
  551. package/server/tests/Unit/Listeners/HandleOrderDispatchFailedListenerTest.php +101 -0
  552. package/server/tests/Unit/Listeners/HandleOrderDispatchedConcreteTest.php +203 -0
  553. package/server/tests/Unit/Listeners/HandleOrderDispatchedHelpersTest.php +186 -0
  554. package/server/tests/Unit/Listeners/HandleUserRemovedFromCompanyTest.php +65 -0
  555. package/server/tests/Unit/Listeners/ListenerDelegationSeamsTest.php +83 -0
  556. package/server/tests/Unit/Models/AssetTest.php +469 -0
  557. package/server/tests/Unit/Models/ContactCustomerUserTest.php +370 -0
  558. package/server/tests/Unit/Models/ContactTest.php +577 -0
  559. package/server/tests/Unit/Models/DeviceEventTest.php +481 -0
  560. package/server/tests/Unit/Models/DeviceLastPositionDefaultTest.php +128 -0
  561. package/server/tests/Unit/Models/DriverModelHelpersTest.php +268 -0
  562. package/server/tests/Unit/Models/DriverTest.php +401 -0
  563. package/server/tests/Unit/Models/EntityTest.php +171 -0
  564. package/server/tests/Unit/Models/EquipmentTest.php +434 -0
  565. package/server/tests/Unit/Models/FleetTest.php +153 -0
  566. package/server/tests/Unit/Models/FuelProviderTransactionTest.php +82 -0
  567. package/server/tests/Unit/Models/FuelReportImportAndLabelsTest.php +193 -0
  568. package/server/tests/Unit/Models/ImportRowFallbackSeamsTest.php +100 -0
  569. package/server/tests/Unit/Models/IntegratedVendorLifecycleTest.php +203 -0
  570. package/server/tests/Unit/Models/IntegratedVendorTest.php +135 -0
  571. package/server/tests/Unit/Models/IssueTest.php +160 -0
  572. package/server/tests/Unit/Models/MaintenanceScheduleTest.php +319 -0
  573. package/server/tests/Unit/Models/MaintenanceTest.php +277 -0
  574. package/server/tests/Unit/Models/MaintenanceWorkOrderImportTest.php +161 -0
  575. package/server/tests/Unit/Models/ManifestStopTest.php +121 -0
  576. package/server/tests/Unit/Models/ManifestTest.php +163 -0
  577. package/server/tests/Unit/Models/ModelLookupFallbackSeamsTest.php +149 -0
  578. package/server/tests/Unit/Models/OrderConfigTest.php +341 -0
  579. package/server/tests/Unit/Models/OrderDynamicContractsTest.php +190 -0
  580. package/server/tests/Unit/Models/OrderPayloadConfigAndDistanceTest.php +426 -0
  581. package/server/tests/Unit/Models/OrderPayloadRouteTest.php +227 -0
  582. package/server/tests/Unit/Models/OrderPurchaseAndDriversTest.php +188 -0
  583. package/server/tests/Unit/Models/OrderTest.php +917 -0
  584. package/server/tests/Unit/Models/PartTest.php +399 -0
  585. package/server/tests/Unit/Models/PayloadTest.php +710 -0
  586. package/server/tests/Unit/Models/PayloadWaypointsAndEntitiesTest.php +317 -0
  587. package/server/tests/Unit/Models/PlaceCreationAndImportTest.php +384 -0
  588. package/server/tests/Unit/Models/PlaceGeocodingResultsTest.php +253 -0
  589. package/server/tests/Unit/Models/PlaceSharedAndGeocodingTest.php +271 -0
  590. package/server/tests/Unit/Models/PlaceTest.php +589 -0
  591. package/server/tests/Unit/Models/PositionTest.php +49 -0
  592. package/server/tests/Unit/Models/RouteTest.php +55 -0
  593. package/server/tests/Unit/Models/SensorLastPositionDefaultTest.php +130 -0
  594. package/server/tests/Unit/Models/SensorReadingsTest.php +168 -0
  595. package/server/tests/Unit/Models/SensorTest.php +284 -0
  596. package/server/tests/Unit/Models/ServiceAreaGeometryTest.php +129 -0
  597. package/server/tests/Unit/Models/ServiceAreaTest.php +125 -0
  598. package/server/tests/Unit/Models/ServiceQuoteTest.php +617 -0
  599. package/server/tests/Unit/Models/ServiceRateFeeTest.php +73 -0
  600. package/server/tests/Unit/Models/ServiceRatePersistenceAndServicabilityTest.php +428 -0
  601. package/server/tests/Unit/Models/ServiceRateTest.php +533 -0
  602. package/server/tests/Unit/Models/SmallModelSurfacesTest.php +294 -0
  603. package/server/tests/Unit/Models/TrackingNumberTest.php +199 -0
  604. package/server/tests/Unit/Models/TrackingStatusTest.php +131 -0
  605. package/server/tests/Unit/Models/VehicleDeviceTest.php +115 -0
  606. package/server/tests/Unit/Models/VehiclePositionsAndImportTest.php +220 -0
  607. package/server/tests/Unit/Models/VehicleTest.php +266 -0
  608. package/server/tests/Unit/Models/VendorRelationsAndImportTest.php +107 -0
  609. package/server/tests/Unit/Models/WarrantyTest.php +187 -0
  610. package/server/tests/Unit/Models/WaypointTest.php +366 -0
  611. package/server/tests/Unit/Models/WorkOrderTest.php +272 -0
  612. package/server/tests/Unit/Models/ZoneTest.php +83 -0
  613. package/server/tests/Unit/Notifications/MonitoringNotificationsTest.php +136 -0
  614. package/server/tests/Unit/Notifications/OrderAssignedChannelsTest.php +53 -0
  615. package/server/tests/Unit/Notifications/OrderDispatchedChannelsTest.php +81 -0
  616. package/server/tests/Unit/Notifications/OrderFailedChannelsTest.php +73 -0
  617. package/server/tests/Unit/Notifications/OrderPingChannelsTest.php +69 -0
  618. package/server/tests/Unit/Notifications/TerminalOrderNotificationsTest.php +185 -0
  619. package/server/tests/Unit/Observers/FleetOpsCompanyUserAndServiceAreaObserversTest.php +133 -0
  620. package/server/tests/Unit/Observers/ObserverHelperExecutionTest.php +135 -0
  621. package/server/tests/Unit/Observers/ObserverListenerSeamsTest.php +267 -0
  622. package/server/tests/Unit/Observers/PurchaseRateObserverAndOrderJobsTest.php +169 -0
  623. package/server/tests/Unit/Orchestration/Engines/DriverAssignmentEngineTest.php +393 -0
  624. package/server/tests/Unit/Orchestration/Engines/VroomOrchestrationEngineLifecycleTest.php +397 -0
  625. package/server/tests/Unit/Orchestration/OrchestrationEngineRegistryTest.php +45 -0
  626. package/server/tests/Unit/Orchestration/VroomEngineTransportAndSettingsTest.php +253 -0
  627. package/server/tests/Unit/Providers/FleetOpsAiRegistrationTest.php +59 -0
  628. package/server/tests/Unit/Rules/ResolvableVehicleTest.php +85 -0
  629. package/server/tests/Unit/Support/Ai/AssetStatusCapabilityQueriesTest.php +120 -0
  630. package/server/tests/Unit/Support/Ai/Capabilities/CreateOrderPreviewCapabilityTest.php +385 -0
  631. package/server/tests/Unit/Support/Ai/Capabilities/OrderInsightsCapabilityTest.php +226 -0
  632. package/server/tests/Unit/Support/Ai/Capabilities/SearchResourcesCapabilityTest.php +237 -0
  633. package/server/tests/Unit/Support/AiCapabilityPermissionsTest.php +124 -0
  634. package/server/tests/Unit/Support/AlgoEdgeBranchesTest.php +24 -0
  635. package/server/tests/Unit/Support/Analytics/GeofenceViolationsTest.php +109 -0
  636. package/server/tests/Unit/Support/Analytics/LiveFleetTest.php +205 -0
  637. package/server/tests/Unit/Support/Analytics/MaintenanceOverviewTest.php +236 -0
  638. package/server/tests/Unit/Support/Analytics/OnTimeDeliveryAndTopDriversTest.php +250 -0
  639. package/server/tests/Unit/Support/CreateOrderPreviewDraftingTest.php +235 -0
  640. package/server/tests/Unit/Support/CustomerAuthTest.php +132 -0
  641. package/server/tests/Unit/Support/FuelEfficiencyAndCanceledHandlersTest.php +164 -0
  642. package/server/tests/Unit/Support/FuelProviderRegistryResolutionTest.php +51 -0
  643. package/server/tests/Unit/Support/FuelProviderServiceMatchingTest.php +280 -0
  644. package/server/tests/Unit/Support/GeocodingInjectedClientTest.php +268 -0
  645. package/server/tests/Unit/Support/GeocodingLocateTest.php +32 -0
  646. package/server/tests/Unit/Support/GeofenceIntersectionServiceTest.php +188 -0
  647. package/server/tests/Unit/Support/GettingStartedTest.php +164 -0
  648. package/server/tests/Unit/Support/GuardReturnSeamsTest.php +172 -0
  649. package/server/tests/Unit/Support/IntegratedVendorsResolverTest.php +250 -0
  650. package/server/tests/Unit/Support/IssuesInsightsAndAllocationJobTest.php +156 -0
  651. package/server/tests/Unit/Support/MagicAccessorSeamsTest.php +54 -0
  652. package/server/tests/Unit/Support/MaintainableAndOperationalAlertsTest.php +215 -0
  653. package/server/tests/Unit/Support/Metrics/AvgOrderValueMetricTest.php +308 -0
  654. package/server/tests/Unit/Support/Metrics/CountMetricsTest.php +280 -0
  655. package/server/tests/Unit/Support/Metrics/FuelCostsMetricTest.php +102 -0
  656. package/server/tests/Unit/Support/Metrics/MetricQuerySeamsTest.php +129 -0
  657. package/server/tests/Unit/Support/Metrics/OrdersScheduledMetricTest.php +146 -0
  658. package/server/tests/Unit/Support/MoreQuerySeamsTest.php +410 -0
  659. package/server/tests/Unit/Support/OperationalQueryDistributionTest.php +152 -0
  660. package/server/tests/Unit/Support/OperationsPulseTest.php +130 -0
  661. package/server/tests/Unit/Support/OptimizeOrderRouteCapabilityTest.php +147 -0
  662. package/server/tests/Unit/Support/OrchestrationPayloadBuilderTest.php +135 -0
  663. package/server/tests/Unit/Support/OrchestrationRouteAndVehicleTasksTest.php +254 -0
  664. package/server/tests/Unit/Support/OsrmProofAndIssueFilterTest.php +247 -0
  665. package/server/tests/Unit/Support/PetroAppFuelProviderTest.php +165 -0
  666. package/server/tests/Unit/Support/PlaceSearchRankingTest.php +191 -0
  667. package/server/tests/Unit/Support/QuerySeamsTest.php +309 -0
  668. package/server/tests/Unit/Support/ResolvesOrderServiceStopsDbTest.php +303 -0
  669. package/server/tests/Unit/Support/ResolvesOrderServiceStopsTest.php +382 -0
  670. package/server/tests/Unit/Support/SkipAndFallbackGuardsTest.php +70 -0
  671. package/server/tests/Unit/Support/TelematicCredentialResolutionTest.php +31 -0
  672. package/server/tests/Unit/Support/TelematicServiceTest.php +256 -0
  673. package/server/tests/Unit/Support/Telematics/Providers/AbstractProviderTest.php +154 -0
  674. package/server/tests/Unit/Support/Telematics/Providers/AfaqyProviderTest.php +191 -0
  675. package/server/tests/Unit/Support/Telematics/Providers/AfaqyProviderTransportTest.php +138 -0
  676. package/server/tests/Unit/Support/Telematics/Providers/GeotabProviderTest.php +329 -0
  677. package/server/tests/Unit/Support/Telematics/Providers/ProviderTransportSeamsTest.php +133 -0
  678. package/server/tests/Unit/Support/Telematics/Providers/SafeeProviderTest.php +487 -0
  679. package/server/tests/Unit/Support/Telematics/TelematicProviderRegistryTest.php +39 -0
  680. package/server/tests/Unit/Support/Telematics/TelematicServiceLifecycleTest.php +711 -0
  681. package/server/tests/Unit/Support/Telematics/TelematicServiceTelemetryTest.php +364 -0
  682. package/server/tests/Unit/Support/UtilsAdditionalTest.php +256 -0
  683. package/server/tests/Unit/Support/UtilsGeoMatrixAndVendorTest.php +382 -0
  684. package/server/tests/Unit/Tracking/TrackingContextTest.php +114 -0
  685. package/server/tests/Unit/Tracking/TrackingIntelligenceAndContextTest.php +477 -0
  686. package/server/tests/Unit/Tracking/TrackingProviderManagerFallbacksTest.php +208 -0
  687. package/server/tests/Unit/Traits/HasTrackingNumberTest.php +303 -0
  688. package/server/tests/Unit/Traits/PayloadAccessorsTest.php +150 -0
  689. package/server/tests/UtilsContractsTest.php +244 -0
  690. package/server/tests/VehicleControllerHelperContractsTest.php +488 -0
  691. package/server/tests/VehicleDataParsingTest.php +45 -0
  692. package/server/tests/VehicleResourceContractsTest.php +313 -0
  693. package/translations/bg-bg.yaml +2 -0
  694. package/translations/en-us.yaml +2 -0
  695. package/translations/es-pa.yaml +2 -0
  696. package/translations/fr-fr.yaml +2 -0
  697. package/translations/mn-mn.yaml +2 -0
  698. package/translations/pt-br.yaml +2 -0
  699. package/translations/ru-ru.yaml +2 -0
  700. package/server/tests/DeviceFilterTest.php +0 -44
  701. package/server/tests/LiveControllerViewportTest.php +0 -52
@@ -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
 
@@ -147,6 +147,30 @@ class Sensor extends Model
147
147
  */
148
148
  protected $spatialFields = ['last_position'];
149
149
 
150
+ /**
151
+ * Bootstrap the model.
152
+ *
153
+ * The same migration that made devices.last_position NOT NULL did it to
154
+ * sensors.last_position too, but only Device got a default. Creating a sensor
155
+ * without a position therefore failed outright:
156
+ *
157
+ * SQLSTATE[HY000]: General error: 1364 Field 'last_position' doesn't have a
158
+ * default value
159
+ *
160
+ * Position is not something a caller has when registering a sensor, so default
161
+ * it to POINT(0,0) on create, exactly as Device does.
162
+ */
163
+ protected static function boot()
164
+ {
165
+ parent::boot();
166
+
167
+ static::creating(function (self $sensor) {
168
+ if (empty($sensor->last_position)) {
169
+ $sensor->last_position = new SpatialPoint(0, 0);
170
+ }
171
+ });
172
+ }
173
+
150
174
  /**
151
175
  * The attributes that should be cast to native types.
152
176
  *
@@ -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
  /**
@@ -264,10 +264,10 @@ class TrackingNumber extends Model
264
264
  }
265
265
  }
266
266
 
267
- $values['uuid'] = $uuid = static::generateUuid();
268
- $values['public_id'] = static::generatePublicId('track');
267
+ $values['uuid'] = $uuid = static::newUuid();
268
+ $values['public_id'] = static::newPublicId();
269
269
  $values['_key'] = session('api_key') ?? 'console';
270
- $values['created_at'] = Carbon::now()->toDateTimeString();
270
+ $values['created_at'] = static::currentTimestamp();
271
271
  $values['company_uuid'] = session('company');
272
272
 
273
273
  if ($owner) {
@@ -275,15 +275,15 @@ class TrackingNumber extends Model
275
275
  $values['owner_type'] = Utils::getMutationType($owner);
276
276
  }
277
277
 
278
- $values['tracking_number'] = TrackingNumber::generateNumber($values['region'] ?? 'SG');
279
- $values['qr_code'] = DNS2D::getBarcodePNG($values['owner_uuid'], 'QRCODE');
280
- $values['barcode'] = DNS2D::getBarcodePNG($values['owner_uuid'], 'PDF417');
278
+ $values['tracking_number'] = static::newTrackingNumber($values['region'] ?? 'SG');
279
+ $values['qr_code'] = static::newBarcode((string) ($values['owner_uuid'] ?? ''), 'QRCODE');
280
+ $values['barcode'] = static::newBarcode((string) ($values['owner_uuid'] ?? ''), 'PDF417');
281
281
 
282
282
  if (isset($values['meta']) && (is_object($values['meta']) || is_array($values['meta']))) {
283
283
  $values['meta'] = json_encode($values['meta']);
284
284
  }
285
285
 
286
- $result = static::insert($values);
286
+ $result = static::insertTrackingNumber($values);
287
287
 
288
288
  if (!$result) {
289
289
  return false;
@@ -292,7 +292,7 @@ class TrackingNumber extends Model
292
292
  $ownerTypeName = class_basename($values['owner_type']);
293
293
 
294
294
  // create initial status
295
- $trackingStatusId = TrackingStatus::insertGetUuid([
295
+ $trackingStatusId = static::createInitialTrackingStatus([
296
296
  'tracking_number_uuid' => $uuid,
297
297
  'status' => Str::title($ownerTypeName . ' created'),
298
298
  'details' => 'New ' . Str::lower($ownerTypeName) . ' created.',
@@ -301,7 +301,7 @@ class TrackingNumber extends Model
301
301
  ]);
302
302
 
303
303
  // update status of tracking number
304
- TrackingNumber::where('uuid', $uuid)->update(['status_uuid' => $trackingStatusId]);
304
+ static::updateTrackingStatusUuid($uuid, $trackingStatusId);
305
305
 
306
306
  // update owner status
307
307
  if ($owner && $owner instanceof Model && static::ownerHasStatusColumn($owner) && $owner->isFillable('status')) {
@@ -309,12 +309,57 @@ class TrackingNumber extends Model
309
309
  // $model->update([ 'status' => 'created' ]);
310
310
 
311
311
  // silent update
312
- DB::table($owner->getTable())->where('uuid', $owner->uuid)->update(['status' => 'created']);
312
+ static::updateOwnerStatusColumn($owner, 'created');
313
313
  }
314
314
 
315
315
  return $uuid;
316
316
  }
317
317
 
318
+ protected static function newUuid(): string
319
+ {
320
+ return static::generateUuid();
321
+ }
322
+
323
+ protected static function newPublicId(): string
324
+ {
325
+ return static::generatePublicId('track');
326
+ }
327
+
328
+ protected static function currentTimestamp(): string
329
+ {
330
+ return Carbon::now()->toDateTimeString();
331
+ }
332
+
333
+ protected static function newTrackingNumber(string $region): string
334
+ {
335
+ return static::generateNumber($region);
336
+ }
337
+
338
+ protected static function newBarcode(string $value, string $type): string
339
+ {
340
+ return DNS2D::getBarcodePNG($value, $type);
341
+ }
342
+
343
+ protected static function insertTrackingNumber(array $values): bool
344
+ {
345
+ return static::insert($values);
346
+ }
347
+
348
+ protected static function createInitialTrackingStatus(array $values)
349
+ {
350
+ return TrackingStatus::insertGetUuid($values);
351
+ }
352
+
353
+ protected static function updateTrackingStatusUuid(string $uuid, mixed $trackingStatusId): void
354
+ {
355
+ TrackingNumber::where('uuid', $uuid)->update(['status_uuid' => $trackingStatusId]);
356
+ }
357
+
358
+ protected static function updateOwnerStatusColumn(Model $owner, string $status): void
359
+ {
360
+ DB::table($owner->getTable())->where('uuid', $owner->uuid)->update(['status' => $status]);
361
+ }
362
+
318
363
  protected static function ownerHasStatusColumn(Model $owner): bool
319
364
  {
320
365
  return Schema::hasColumn($owner->getTable(), 'status');
@@ -159,10 +159,10 @@ class TrackingStatus extends Model
159
159
  }
160
160
  }
161
161
 
162
- $values['uuid'] = $uuid = (string) Str::uuid();
163
- $values['public_id'] = static::generatePublicId('status');
162
+ $values['uuid'] = $uuid = static::newUuid();
163
+ $values['public_id'] = static::newPublicId();
164
164
  $values['_key'] = session('api_key') ?? 'console';
165
- $values['created_at'] = Carbon::now()->toDateTimeString();
165
+ $values['created_at'] = static::currentTimestamp();
166
166
  $values['company_uuid'] = session('company');
167
167
 
168
168
  if ($trackingNumber) {
@@ -175,11 +175,31 @@ class TrackingStatus extends Model
175
175
  $values['meta'] = json_encode($values['meta']);
176
176
  }
177
177
 
178
- $result = static::insert($values);
178
+ $result = static::insertTrackingStatus($values);
179
179
 
180
180
  return $result ? $uuid : false;
181
181
  }
182
182
 
183
+ protected static function newUuid(): string
184
+ {
185
+ return (string) Str::uuid();
186
+ }
187
+
188
+ protected static function newPublicId(): string
189
+ {
190
+ return static::generatePublicId('status');
191
+ }
192
+
193
+ protected static function currentTimestamp(): string
194
+ {
195
+ return Carbon::now()->toDateTimeString();
196
+ }
197
+
198
+ protected static function insertTrackingStatus(array $values): bool
199
+ {
200
+ return static::insert($values);
201
+ }
202
+
183
203
  public function isComplete(): bool
184
204
  {
185
205
  return Utils::isTrue($this->complete);
@@ -203,10 +203,10 @@ class Waypoint extends Model
203
203
  }
204
204
  }
205
205
 
206
- $values['uuid'] = $uuid = static::generateUuid();
207
- $values['public_id'] = static::generatePublicId('waypoint');
206
+ $values['uuid'] = $uuid = static::newUuid();
207
+ $values['public_id'] = static::newPublicId();
208
208
  $values['_key'] = session('api_key') ?? 'console';
209
- $values['created_at'] = Carbon::now()->toDateTimeString();
209
+ $values['created_at'] = static::currentTimestamp();
210
210
  $values['company_uuid'] = session('company');
211
211
 
212
212
  if ($payload) {
@@ -217,23 +217,58 @@ class Waypoint extends Model
217
217
  $values['meta'] = json_encode($values['meta']);
218
218
  }
219
219
 
220
- $result = static::insert($values);
220
+ $result = static::insertWaypoint($values);
221
221
  if ($result && $payload) {
222
222
  // create tracking number for entity
223
- $trackingNumberId = TrackingNumber::insertGetUuid([
223
+ $trackingNumberId = static::createTrackingNumber([
224
224
  'owner_uuid' => $uuid,
225
225
  'owner_type' => Utils::getModelClassName('waypoint'),
226
226
  'region' => $payload->getPickupRegion(),
227
- 'location' => Utils::parsePointToWkt($payload->getPickupLocation()),
227
+ 'location' => static::pickupLocationWkt($payload),
228
228
  ]);
229
229
 
230
230
  // set tracking number
231
- static::where('uuid', $uuid)->update(['tracking_number_uuid' => $trackingNumberId]);
231
+ static::updateTrackingNumberUuid($uuid, $trackingNumberId);
232
232
  }
233
233
 
234
234
  return $result ? $uuid : false;
235
235
  }
236
236
 
237
+ protected static function newUuid(): string
238
+ {
239
+ return static::generateUuid();
240
+ }
241
+
242
+ protected static function newPublicId(): string
243
+ {
244
+ return static::generatePublicId('waypoint');
245
+ }
246
+
247
+ protected static function currentTimestamp(): string
248
+ {
249
+ return Carbon::now()->toDateTimeString();
250
+ }
251
+
252
+ protected static function insertWaypoint(array $values): bool
253
+ {
254
+ return static::insert($values);
255
+ }
256
+
257
+ protected static function createTrackingNumber(array $values)
258
+ {
259
+ return TrackingNumber::insertGetUuid($values);
260
+ }
261
+
262
+ protected static function pickupLocationWkt(Payload $payload)
263
+ {
264
+ return Utils::parsePointToWkt($payload->getPickupLocation());
265
+ }
266
+
267
+ protected static function updateTrackingNumberUuid(string $uuid, mixed $trackingNumberId): void
268
+ {
269
+ static::where('uuid', $uuid)->update(['tracking_number_uuid' => $trackingNumberId]);
270
+ }
271
+
237
272
  /**
238
273
  * Get this waypoint place record.
239
274
  */
@@ -269,9 +304,8 @@ class Waypoint extends Model
269
304
  array $columns = ['*'],
270
305
  ): ?self {
271
306
  $payloadId = match (true) {
272
- $order instanceof Order => $order->payload_uuid,
273
- $order instanceof Payload => $order->uuid,
274
- default => null,
307
+ $order instanceof Order => $order->payload_uuid,
308
+ default => $order->uuid,
275
309
  };
276
310
 
277
311
  if (!$payloadId) {
@@ -170,7 +170,7 @@ class Zone extends Model
170
170
  */
171
171
  public function getCentroid(): \Brick\Geo\Point
172
172
  {
173
- $geometryEngine = new \Brick\Geo\Engine\GEOSEngine();
173
+ $geometryEngine = Utils::resolveGeometryEngine();
174
174
  $borderAsPolygon = $this->toGeosPolygon();
175
175
 
176
176
  if ($borderAsPolygon instanceof \Brick\Geo\Geometry) {
@@ -232,13 +232,10 @@ class Zone extends Model
232
232
  */
233
233
  public static function createPolygonFromPoint(Point $point, int $meters = 500): Polygon
234
234
  {
235
+ // coordsToCircle() already closes the ring, so first and last are
236
+ // equivalent on arrival and no re-closing is needed here
235
237
  $coordinates = Utils::coordsToCircle($point->getLat(), $point->getLng(), $meters);
236
238
 
237
- // first and last positions should be equivalent
238
- if (Arr::first($coordinates) !== Arr::last($coordinates)) {
239
- $coordinates[] = Arr::first($coordinates);
240
- }
241
-
242
239
  // conver the coordinate pairs to points
243
240
  $coordinates = array_map(
244
241
  function ($coord) {
@@ -61,7 +61,7 @@ class DriverArrivedAtGeofence extends Notification
61
61
  ->greeting('Good news!')
62
62
  ->line("Your driver has arrived at {$geofenceName} for order #{$orderId}.")
63
63
  ->line('Please be ready to receive your delivery.')
64
- ->action('Track Your Order', url("/tracking/{$this->order->tracking_number}"))
64
+ ->action('Track Your Order', \url("/tracking/{$this->order->tracking_number}"))
65
65
  ->line('Thank you for using our service.');
66
66
  }
67
67
 
@@ -141,17 +141,11 @@ class OrderDispatched extends Notification implements ShouldQueue
141
141
  */
142
142
  public function toBroadcast($notifiable)
143
143
  {
144
+ // OrderResource declares toWebhookPayload(), so the fallback arms of the
145
+ // old method_exists() chain were never reachable
144
146
  $model = $this->order;
145
147
  $resource = new OrderResource($model);
146
- $resourceData = [];
147
-
148
- if ($resource) {
149
- if (method_exists($resource, 'toWebhookPayload')) {
150
- $resourceData = $resource->toWebhookPayload();
151
- } elseif (method_exists($resource, 'toArray')) {
152
- $resourceData = $resource->toArray(request());
153
- }
154
- }
148
+ $resourceData = $resource->toWebhookPayload();
155
149
 
156
150
  $resourceData = ResourceLifecycleEvent::transformResourceChildrenToId($resourceData);
157
151
 
@@ -148,17 +148,11 @@ class OrderPing extends Notification implements ShouldQueue
148
148
  */
149
149
  public function toBroadcast($notifiable)
150
150
  {
151
+ // OrderResource declares toWebhookPayload(), so the fallback arms of the
152
+ // old method_exists() chain were never reachable
151
153
  $model = $this->order;
152
154
  $resource = new OrderResource($model);
153
- $resourceData = [];
154
-
155
- if ($resource) {
156
- if (method_exists($resource, 'toWebhookPayload')) {
157
- $resourceData = $resource->toWebhookPayload();
158
- } elseif (method_exists($resource, 'toArray')) {
159
- $resourceData = $resource->toArray(request());
160
- }
161
- }
155
+ $resourceData = $resource->toWebhookPayload();
162
156
 
163
157
  $resourceData = ResourceLifecycleEvent::transformResourceChildrenToId($resourceData);
164
158
 
@@ -15,6 +15,11 @@ class CategoryObserver
15
15
  public function deleted(Category $category)
16
16
  {
17
17
  // if the category deleted was for "custom_field_group" - delete the custom fields belonging
18
- CustomField::where('category_uuid', $category->uuid)->delete();
18
+ $this->deleteCustomFields($category->uuid);
19
+ }
20
+
21
+ protected function deleteCustomFields(string $categoryUuid): void
22
+ {
23
+ CustomField::where('category_uuid', $categoryUuid)->delete();
19
24
  }
20
25
  }
@@ -15,6 +15,11 @@ class CompanyObserver
15
15
  public function created(Company $company)
16
16
  {
17
17
  // Add the default transport order config
18
+ $this->createTransportConfig($company);
19
+ }
20
+
21
+ protected function createTransportConfig(Company $company): void
22
+ {
18
23
  FleetOps::createTransportConfig($company);
19
24
  }
20
25
  }
@@ -15,7 +15,7 @@ class CompanyUserObserver
15
15
  public function deleted(CompanyUser $companyUser)
16
16
  {
17
17
  // if the company user deleted is a driver, delete their driver record to
18
- Driver::where('user_uuid', $companyUser->user_uuid)->delete();
18
+ $this->deleteDrivers($companyUser->user_uuid);
19
19
  }
20
20
 
21
21
  /**
@@ -26,9 +26,19 @@ class CompanyUserObserver
26
26
  public function updated(CompanyUser $companyUser)
27
27
  {
28
28
  // If the company user has any driver assosciated update status to same as company_users
29
- $driver = Driver::where('user_uuid', $companyUser->user_uuid)->first();
29
+ $driver = $this->findDriver($companyUser->user_uuid);
30
30
  if ($driver && $companyUser->wasChanged('status')) {
31
31
  $driver->update(['status' => $companyUser->status]);
32
32
  }
33
33
  }
34
+
35
+ protected function deleteDrivers(string $userUuid): void
36
+ {
37
+ Driver::where('user_uuid', $userUuid)->delete();
38
+ }
39
+
40
+ protected function findDriver(string $userUuid): ?Driver
41
+ {
42
+ return Driver::where('user_uuid', $userUuid)->first();
43
+ }
34
44
  }