@fleetbase/fleetops-engine 0.6.48 → 0.6.50

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 (266) hide show
  1. package/addon/components/customer/create-order-form.hbs +2 -2
  2. package/addon/components/customer/form.hbs +2 -2
  3. package/addon/components/customer/order-form.hbs +2 -2
  4. package/addon/components/customer/orders.hbs +2 -2
  5. package/addon/components/display-place.hbs +2 -2
  6. package/addon/components/driver/details.hbs +5 -1
  7. package/addon/components/driver/form.hbs +11 -1
  8. package/addon/components/fleet-listing-panel.hbs +2 -2
  9. package/addon/components/fleet-listing-panel.js +10 -0
  10. package/addon/components/map/google-live-map.js +18 -75
  11. package/addon/components/map/leaflet-live-map.hbs +187 -37
  12. package/addon/components/map/leaflet-live-map.js +184 -20
  13. package/addon/components/modals/order-change-destination.hbs +46 -0
  14. package/addon/components/modals/order-change-destination.js +106 -0
  15. package/addon/components/modals/stop-activity.hbs +28 -0
  16. package/addon/components/modals/stop-activity.js +52 -0
  17. package/addon/components/modals/update-order-activity.hbs +45 -3
  18. package/addon/components/modals/update-order-activity.js +143 -5
  19. package/addon/components/orchestrator/phase-builder.hbs +21 -0
  20. package/addon/components/orchestrator/phase-builder.js +13 -0
  21. package/addon/components/orchestrator/resource-panel.hbs +0 -10
  22. package/addon/components/orchestrator/resource-panel.js +2 -4
  23. package/addon/components/orchestrator-workbench.js +1 -0
  24. package/addon/components/order/activity-list.hbs +2 -2
  25. package/addon/components/order/activity-timeline.hbs +31 -29
  26. package/addon/components/order/details/activity.hbs +3 -3
  27. package/addon/components/order/details/activity.js +11 -0
  28. package/addon/components/order/details/documents.js +2 -0
  29. package/addon/components/order/details/purchase-rate.hbs +2 -2
  30. package/addon/components/order/details/route.hbs +11 -3
  31. package/addon/components/order/details/route.js +91 -14
  32. package/addon/components/order/details/tracking.hbs +101 -72
  33. package/addon/components/order/details/tracking.js +149 -2
  34. package/addon/components/order/form/details.hbs +3 -3
  35. package/addon/components/order/form/documents.js +11 -4
  36. package/addon/components/order/form/route.hbs +108 -104
  37. package/addon/components/order/form/route.js +37 -1
  38. package/addon/components/order/form/service-rate.hbs +2 -2
  39. package/addon/components/order/form.hbs +2 -2
  40. package/addon/components/order-config-manager/activity-flow.hbs +4 -1
  41. package/addon/components/order-config-manager/activity-flow.js +178 -12
  42. package/addon/components/place/address.js +1 -1
  43. package/addon/components/route-list.hbs +17 -17
  44. package/addon/components/route-list.js +42 -10
  45. package/addon/components/service-rate/details.hbs +41 -0
  46. package/addon/components/service-rate/form.hbs +118 -0
  47. package/addon/components/service-rate/form.js +55 -0
  48. package/addon/components/vehicle/form.js +1 -1
  49. package/addon/components/vehicle/pill.hbs +1 -1
  50. package/addon/components/widget/fleet-ops-key-metrics.hbs +19 -17
  51. package/addon/components/widget/fleet-ops-key-metrics.js +26 -0
  52. package/addon/components/widget/fuel-efficiency.hbs +26 -0
  53. package/addon/components/widget/fuel-efficiency.js +43 -0
  54. package/addon/components/widget/geofence-violations.hbs +44 -0
  55. package/addon/components/widget/geofence-violations.js +55 -0
  56. package/addon/components/widget/issues-insights.hbs +43 -0
  57. package/addon/components/widget/issues-insights.js +62 -0
  58. package/addon/components/widget/kpi-active-orders.hbs +10 -0
  59. package/addon/components/widget/kpi-active-orders.js +5 -0
  60. package/addon/components/widget/kpi-aov.hbs +10 -0
  61. package/addon/components/widget/kpi-aov.js +5 -0
  62. package/addon/components/widget/kpi-distance.hbs +10 -0
  63. package/addon/components/widget/kpi-distance.js +5 -0
  64. package/addon/components/widget/kpi-drivers-online.hbs +10 -0
  65. package/addon/components/widget/kpi-drivers-online.js +5 -0
  66. package/addon/components/widget/kpi-earnings.hbs +10 -0
  67. package/addon/components/widget/kpi-earnings.js +5 -0
  68. package/addon/components/widget/kpi-open-issues.hbs +11 -0
  69. package/addon/components/widget/kpi-open-issues.js +5 -0
  70. package/addon/components/widget/kpi-tile.hbs +59 -0
  71. package/addon/components/widget/kpi-tile.js +168 -0
  72. package/addon/components/widget/live-fleet.hbs +122 -0
  73. package/addon/components/widget/live-fleet.js +365 -0
  74. package/addon/components/widget/maintenance-overview.hbs +45 -0
  75. package/addon/components/widget/maintenance-overview.js +40 -0
  76. package/addon/components/widget/on-time-delivery.hbs +27 -0
  77. package/addon/components/widget/on-time-delivery.js +73 -0
  78. package/addon/components/widget/operations-pulse.hbs +51 -0
  79. package/addon/components/widget/operations-pulse.js +173 -0
  80. package/addon/components/widget/orders-by-status.hbs +26 -0
  81. package/addon/components/widget/orders-by-status.js +54 -0
  82. package/addon/components/widget/revenue-trend.hbs +34 -0
  83. package/addon/components/widget/revenue-trend.js +67 -0
  84. package/addon/components/widget/top-drivers.hbs +44 -0
  85. package/addon/components/widget/top-drivers.js +54 -0
  86. package/addon/controllers/management/vehicles/index/new.js +1 -1
  87. package/addon/controllers/operations/orders/index/details.js +4 -4
  88. package/addon/controllers/operations/orders/index.js +14 -0
  89. package/addon/controllers/settings/routing.js +26 -0
  90. package/addon/extension.js +172 -3
  91. package/addon/helpers/place-address-html.js +2 -2
  92. package/addon/routes/operations/service-rates/index.js +1 -1
  93. package/addon/services/geofence.js +163 -19
  94. package/addon/services/leaflet-contextmenu-manager.js +27 -0
  95. package/addon/services/map-adapter/google.js +13 -2
  96. package/addon/services/vehicle-actions.js +1 -1
  97. package/addon/styles/fleetops-engine.css +205 -88
  98. package/addon/templates/maintenance/equipment/index.hbs +1 -1
  99. package/addon/templates/maintenance/parts/index.hbs +1 -1
  100. package/addon/templates/maintenance/schedules/index.hbs +1 -1
  101. package/addon/templates/management/vehicles/index.hbs +1 -1
  102. package/addon/templates/settings/avatars.hbs +1 -1
  103. package/addon/templates/settings/custom-fields.hbs +1 -1
  104. package/addon/templates/settings/map.hbs +1 -1
  105. package/addon/templates/settings/navigator-app.hbs +1 -1
  106. package/addon/templates/settings/notifications.hbs +1 -1
  107. package/addon/templates/settings/orchestrator.hbs +1 -1
  108. package/addon/templates/settings/payments/index.hbs +1 -1
  109. package/addon/templates/settings/payments/onboard.hbs +1 -1
  110. package/addon/templates/settings/routing.hbs +22 -2
  111. package/addon/templates/settings/scheduling.hbs +1 -1
  112. package/addon/utils/fleet-ops-options.js +2 -1
  113. package/addon/utils/live-map-card-content.js +171 -0
  114. package/addon/utils/normalize-order-config-flow.js +41 -0
  115. package/addon/utils/place-address-html.js +3 -2
  116. package/addon/utils/route-visualization.js +54 -7
  117. package/app/components/modals/order-change-destination.js +1 -0
  118. package/app/components/modals/stop-activity.js +1 -0
  119. package/app/components/widget/fuel-efficiency.js +1 -0
  120. package/app/components/widget/geofence-violations.js +1 -0
  121. package/app/components/widget/issues-insights.js +1 -0
  122. package/app/components/widget/kpi-active-orders.js +1 -0
  123. package/app/components/widget/kpi-aov.js +1 -0
  124. package/app/components/widget/kpi-distance.js +1 -0
  125. package/app/components/widget/kpi-drivers-online.js +1 -0
  126. package/app/components/widget/kpi-earnings.js +1 -0
  127. package/app/components/widget/kpi-open-issues.js +1 -0
  128. package/app/components/widget/kpi-tile.js +1 -0
  129. package/app/components/widget/live-fleet.js +1 -0
  130. package/app/components/widget/maintenance-overview.js +1 -0
  131. package/app/components/widget/on-time-delivery.js +1 -0
  132. package/app/components/widget/operations-pulse.js +1 -0
  133. package/app/components/widget/orders-by-status.js +1 -0
  134. package/app/components/widget/revenue-trend.js +1 -0
  135. package/app/components/widget/top-drivers.js +1 -0
  136. package/app/utils/live-map-card-content.js +1 -0
  137. package/composer.json +1 -1
  138. package/extension.json +1 -1
  139. package/package.json +3 -3
  140. package/pnpm-workspace.yaml +1 -0
  141. package/server/config/telematics.php +111 -1
  142. package/server/migrations/2026_05_18_000001_add_license_expiry_to_drivers_table.php +25 -0
  143. package/server/migrations/2026_05_21_000001_add_geographic_rules_to_service_rate_fees_table.php +37 -0
  144. package/server/migrations/2026_05_25_000001_add_endpoint_tracking_refs_to_payloads_table.php +50 -0
  145. package/server/migrations/2026_05_27_000001_default_driver_vehicle_statuses_to_available.php +48 -0
  146. package/server/resources/views/labels/default.php +57 -49
  147. package/server/resources/views/labels/waypoint-label.php +27 -20
  148. package/server/seeders/Testing/Concerns/SeedsTestingData.php +183 -0
  149. package/server/seeders/Testing/ConnectivitySeeder.php +213 -0
  150. package/server/seeders/Testing/FleetSeeder.php +341 -0
  151. package/server/seeders/Testing/MaintenanceSeeder.php +238 -0
  152. package/server/seeders/Testing/NetworkSeeder.php +250 -0
  153. package/server/seeders/Testing/OrdersSeeder.php +198 -0
  154. package/server/seeders/Testing/TestingSeeder.php +40 -0
  155. package/server/seeders/{VroomOrchestrationSeeder.php → Testing/VroomOrchestrationSeeder.php} +29 -22
  156. package/server/src/Console/Commands/AuditCustomerUserConflicts.php +75 -0
  157. package/server/src/Console/Commands/ProcessOperationalAlerts.php +279 -0
  158. package/server/src/Exceptions/CustomerUserConflictException.php +13 -0
  159. package/server/src/Http/Controllers/Api/v1/ContactController.php +17 -2
  160. package/server/src/Http/Controllers/Api/v1/CustomerController.php +876 -0
  161. package/server/src/Http/Controllers/Api/v1/DriverController.php +1 -1
  162. package/server/src/Http/Controllers/Api/v1/OrderConfigController.php +54 -0
  163. package/server/src/Http/Controllers/Api/v1/OrderController.php +98 -70
  164. package/server/src/Http/Controllers/Api/v1/ServiceAreaController.php +2 -2
  165. package/server/src/Http/Controllers/Api/v1/VehicleController.php +20 -3
  166. package/server/src/Http/Controllers/Internal/v1/AnalyticsController.php +119 -0
  167. package/server/src/Http/Controllers/Internal/v1/ContactController.php +19 -0
  168. package/server/src/Http/Controllers/Internal/v1/LiveController.php +101 -66
  169. package/server/src/Http/Controllers/Internal/v1/MetricsController.php +82 -3
  170. package/server/src/Http/Controllers/Internal/v1/OrderController.php +441 -32
  171. package/server/src/Http/Controllers/Internal/v1/ServiceQuoteController.php +1 -1
  172. package/server/src/Http/Controllers/Internal/v1/SettingController.php +46 -1
  173. package/server/src/Http/Controllers/Internal/v1/VehicleController.php +54 -1
  174. package/server/src/Http/Middleware/AuthenticateCustomerToken.php +34 -0
  175. package/server/src/Http/Requests/CreateCustomerOrderRequest.php +63 -0
  176. package/server/src/Http/Requests/CreateCustomerRequest.php +48 -0
  177. package/server/src/Http/Requests/CreateDriverRequest.php +1 -1
  178. package/server/src/Http/Requests/CreateVehicleRequest.php +25 -1
  179. package/server/src/Http/Requests/Internal/CreateDriverRequest.php +1 -1
  180. package/server/src/Http/Requests/VerifyCreateCustomerRequest.php +29 -0
  181. package/server/src/Http/Resources/Internal/v1/OrderConfig.php +41 -0
  182. package/server/src/Http/Resources/v1/Customer.php +79 -0
  183. package/server/src/Http/Resources/v1/Driver.php +2 -0
  184. package/server/src/Http/Resources/v1/Fleet.php +4 -0
  185. package/server/src/Http/Resources/v1/Index/Driver.php +48 -0
  186. package/server/src/Http/Resources/v1/Index/Vehicle.php +74 -1
  187. package/server/src/Http/Resources/v1/OrderConfig.php +74 -0
  188. package/server/src/Http/Resources/v1/Payload.php +23 -20
  189. package/server/src/Http/Resources/v1/ServiceArea.php +33 -19
  190. package/server/src/Http/Resources/v1/ServiceRateFee.php +7 -0
  191. package/server/src/Listeners/HandleOrderDispatched.php +2 -2
  192. package/server/src/Models/Contact.php +92 -15
  193. package/server/src/Models/Customer.php +64 -0
  194. package/server/src/Models/Driver.php +14 -3
  195. package/server/src/Models/Entity.php +2 -2
  196. package/server/src/Models/Order.php +29 -4
  197. package/server/src/Models/OrderConfig.php +14 -11
  198. package/server/src/Models/Payload.php +17 -1
  199. package/server/src/Models/ServiceRate.php +273 -1
  200. package/server/src/Models/ServiceRateFee.php +39 -9
  201. package/server/src/Models/TrackingNumber.php +8 -2
  202. package/server/src/Models/Vehicle.php +18 -2
  203. package/server/src/Models/Waypoint.php +2 -2
  204. package/server/src/Notifications/LateDeparture.php +48 -0
  205. package/server/src/Notifications/ProlongedStoppage.php +48 -0
  206. package/server/src/Notifications/RouteDeviation.php +48 -0
  207. package/server/src/Observers/ContactObserver.php +2 -0
  208. package/server/src/Observers/ServiceRateObserver.php +6 -6
  209. package/server/src/Orchestration/Engines/VroomOrchestrationEngine.php +29 -2
  210. package/server/src/Providers/FleetOpsServiceProvider.php +6 -0
  211. package/server/src/Providers/NotificationServiceProvider.php +3 -0
  212. package/server/src/Support/Analytics/AbstractAnalytics.php +77 -0
  213. package/server/src/Support/Analytics/FuelEfficiency.php +83 -0
  214. package/server/src/Support/Analytics/GeofenceViolations.php +63 -0
  215. package/server/src/Support/Analytics/IssuesInsights.php +67 -0
  216. package/server/src/Support/Analytics/LiveFleet.php +127 -0
  217. package/server/src/Support/Analytics/MaintenanceOverview.php +70 -0
  218. package/server/src/Support/Analytics/OnTimeDelivery.php +75 -0
  219. package/server/src/Support/Analytics/OperationsPulse.php +86 -0
  220. package/server/src/Support/Analytics/OrdersByStatus.php +64 -0
  221. package/server/src/Support/Analytics/RevenueTrend.php +78 -0
  222. package/server/src/Support/Analytics/TopDrivers.php +92 -0
  223. package/server/src/Support/CustomerAuth.php +98 -0
  224. package/server/src/Support/LabelPdf.php +52 -0
  225. package/server/src/Support/Metrics/AbstractMetric.php +170 -0
  226. package/server/src/Support/Metrics/ActiveLiveOrdersMetric.php +28 -0
  227. package/server/src/Support/Metrics/AvgOrderValueMetric.php +53 -0
  228. package/server/src/Support/Metrics/DriversOnlineMetric.php +30 -0
  229. package/server/src/Support/Metrics/EarningsMetric.php +30 -0
  230. package/server/src/Support/Metrics/FuelCostsMetric.php +30 -0
  231. package/server/src/Support/Metrics/MoneyMetric.php +30 -0
  232. package/server/src/Support/Metrics/OpenIssuesMetric.php +35 -0
  233. package/server/src/Support/Metrics/OrdersCanceledMetric.php +35 -0
  234. package/server/src/Support/Metrics/OrdersCompletedMetric.php +35 -0
  235. package/server/src/Support/Metrics/OrdersInProgressMetric.php +51 -0
  236. package/server/src/Support/Metrics/OrdersScheduledMetric.php +37 -0
  237. package/server/src/Support/Metrics/Registry.php +46 -0
  238. package/server/src/Support/Metrics/ResolvedIssuesMetric.php +35 -0
  239. package/server/src/Support/Metrics/TotalCustomersMetric.php +29 -0
  240. package/server/src/Support/Metrics/TotalDistanceTraveledMetric.php +35 -0
  241. package/server/src/Support/Metrics/TotalDriversMetric.php +28 -0
  242. package/server/src/Support/Metrics/TotalTimeTraveledMetric.php +35 -0
  243. package/server/src/Support/Metrics.php +46 -249
  244. package/server/src/Support/ResolvesOrderServiceStops.php +512 -0
  245. package/server/src/Support/Telematics/Providers/AfaqyProvider.php +290 -0
  246. package/server/src/Support/Telematics/Providers/SafeeProvider.php +333 -0
  247. package/server/src/Tracking/TrackingContextBuilder.php +41 -38
  248. package/server/src/Tracking/TrackingIntelligenceService.php +109 -9
  249. package/server/src/Tracking/TrackingStop.php +13 -11
  250. package/server/src/routes.php +50 -0
  251. package/server/tests/AnalyticsRoutesTest.php +41 -0
  252. package/server/tests/CapacityAllocationEngineTest.php +10 -10
  253. package/server/tests/CustomerContactIdentitySafetyTest.php +54 -0
  254. package/server/tests/CustomerEndpointTest.php +199 -0
  255. package/server/tests/DriverVehicleStatusDefaultTest.php +39 -0
  256. package/server/tests/LabelPdfRenderingTest.php +23 -0
  257. package/server/tests/LiveControllerViewportTest.php +60 -0
  258. package/server/tests/MetricsRegistryTest.php +84 -0
  259. package/server/tests/OrchestrationPayloadBuilderTest.php +2 -2
  260. package/server/tests/OrderConfigEndpointTest.php +86 -0
  261. package/server/tests/OrderFileAttachmentTest.php +20 -0
  262. package/server/tests/ServiceAreaZoneApiShapeTest.php +34 -0
  263. package/server/tests/VehicleDriverAssignmentTest.php +18 -0
  264. package/server/tests/VroomOrchestrationEngineTest.php +91 -0
  265. package/translations/en-us.yaml +38 -0
  266. package/server/migrations/2026_05_13_000001_repair_customer_contact_user_types.php +0 -86
@@ -0,0 +1,35 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Support\Metrics;
4
+
5
+ use Fleetbase\FleetOps\Models\Order;
6
+
7
+ class TotalDistanceTraveledMetric extends AbstractMetric
8
+ {
9
+ public static function slug(): string
10
+ {
11
+ return 'total_distance_traveled';
12
+ }
13
+
14
+ public function format(): string
15
+ {
16
+ return 'meters';
17
+ }
18
+
19
+ protected function query(?\DateTimeInterface $start, ?\DateTimeInterface $end)
20
+ {
21
+ $query = Order::where('company_uuid', $this->company->uuid)
22
+ ->where('status', 'completed');
23
+
24
+ if ($start && $end) {
25
+ $query->whereBetween('created_at', [$start, $end]);
26
+ }
27
+
28
+ return $query;
29
+ }
30
+
31
+ protected function aggregate($query): float
32
+ {
33
+ return (float) $query->sum('distance');
34
+ }
35
+ }
@@ -0,0 +1,28 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Support\Metrics;
4
+
5
+ use Fleetbase\FleetOps\Models\Driver;
6
+
7
+ class TotalDriversMetric extends AbstractMetric
8
+ {
9
+ public static function slug(): string
10
+ {
11
+ return 'total_drivers';
12
+ }
13
+
14
+ public function format(): string
15
+ {
16
+ return 'count';
17
+ }
18
+
19
+ protected function query(?\DateTimeInterface $start, ?\DateTimeInterface $end)
20
+ {
21
+ return Driver::where('company_uuid', $this->company->uuid);
22
+ }
23
+
24
+ protected function aggregate($query): int
25
+ {
26
+ return (int) $query->count();
27
+ }
28
+ }
@@ -0,0 +1,35 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Support\Metrics;
4
+
5
+ use Fleetbase\FleetOps\Models\Order;
6
+
7
+ class TotalTimeTraveledMetric extends AbstractMetric
8
+ {
9
+ public static function slug(): string
10
+ {
11
+ return 'total_time_traveled';
12
+ }
13
+
14
+ public function format(): string
15
+ {
16
+ return 'duration';
17
+ }
18
+
19
+ protected function query(?\DateTimeInterface $start, ?\DateTimeInterface $end)
20
+ {
21
+ $query = Order::where('company_uuid', $this->company->uuid)
22
+ ->where('status', 'completed');
23
+
24
+ if ($start && $end) {
25
+ $query->whereBetween('created_at', [$start, $end]);
26
+ }
27
+
28
+ return $query;
29
+ }
30
+
31
+ protected function aggregate($query): int
32
+ {
33
+ return (int) $query->sum('time') * 60;
34
+ }
35
+ }
@@ -2,21 +2,26 @@
2
2
 
3
3
  namespace Fleetbase\FleetOps\Support;
4
4
 
5
- use Fleetbase\FleetOps\Models\Contact;
6
- use Fleetbase\FleetOps\Models\Driver;
7
- use Fleetbase\FleetOps\Models\FuelReport;
8
- use Fleetbase\FleetOps\Models\Issue;
9
- use Fleetbase\FleetOps\Models\Order;
5
+ use Fleetbase\FleetOps\Support\Metrics\AbstractMetric;
6
+ use Fleetbase\FleetOps\Support\Metrics\Registry;
10
7
  use Fleetbase\Models\Company;
11
- use Fleetbase\Models\Transaction;
12
8
  use Illuminate\Support\Carbon;
13
9
  use Illuminate\Support\Str;
14
10
 
15
11
  /**
16
- * Metrics service to pull analyitcs and metrics from FleetOps.
12
+ * Thin facade over Support/Metrics/* — preserves the legacy chainable API
13
+ * (Metrics::new($co)->withEarnings()->withFuelCosts()->get()) for one release
14
+ * while the new per-slug pattern is preferred:
17
15
  *
18
- * Ex:
19
- * $metrics = Metrics::new($company)->withEarnings()->withFuelCosts()->get();
16
+ * Metrics::forCompany($co)->between($s, $e)->resolve('earnings')->get()
17
+ *
18
+ * The 7 documented bugs in the previous monolithic implementation are fixed
19
+ * by the per-metric classes:
20
+ * - totalTimeTraveled now sums `time`, not `distance`
21
+ * - openIssues/resolvedIssues use $this->company->uuid (not session)
22
+ * - earnings/fuelCosts return float, currency-filtered
23
+ * - ordersInProgress uses explicit allowlist
24
+ * - metric discovery uses explicit Registry (not array_slice + reflection)
20
25
  */
21
26
  class Metrics
22
27
  {
@@ -57,264 +62,56 @@ class Metrics
57
62
  return $this->start($start)->end($end);
58
63
  }
59
64
 
60
- private function setCompany(Company $company): Metrics
65
+ /**
66
+ * Resolve a single metric by slug. New preferred entry point.
67
+ */
68
+ public function resolve(string $slug): ?AbstractMetric
61
69
  {
62
- $this->company = $company;
63
-
64
- return $this;
65
- }
70
+ $class = Registry::resolve($slug);
66
71
 
67
- private function set($key, $value = null): Metrics
68
- {
69
- if (is_array($key)) {
70
- foreach ($key as $k => $v) {
71
- $this->set($k, $v);
72
- }
73
-
74
- return $this;
72
+ if ($class === null) {
73
+ return null;
75
74
  }
76
75
 
77
- $this->metrics = data_set($this->metrics, $key, $value);
78
-
79
- return $this;
80
- }
81
-
82
- public function get()
83
- {
84
- return $this->metrics;
76
+ return $class::forCompany($this->company)->between($this->start, $this->end);
85
77
  }
86
78
 
87
- public function with(?array $metrics = [])
79
+ /**
80
+ * Legacy bulk API: invoke a set of metrics and collect their scalar values
81
+ * in the same shape the old endpoint returned. Empty $metrics means "all".
82
+ *
83
+ * @param array<string> $metrics slugs or camelCase method names accepted for back-compat
84
+ */
85
+ public function with(?array $metrics = []): Metrics
88
86
  {
89
87
  if (empty($metrics)) {
90
- $metrics = array_slice(get_class_methods($this), 9);
91
- }
92
-
93
- $metrics = array_map(
94
- function ($metric) {
95
- return Str::camel($metric);
96
- },
97
- $metrics
98
- );
99
-
100
- foreach ($metrics as $metric) {
101
- if (method_exists($this, $metric)) {
102
- $this->{$metric}();
88
+ $slugs = Registry::slugs();
89
+ } else {
90
+ $slugs = array_map(
91
+ fn ($m) => Str::snake($m),
92
+ $metrics
93
+ );
94
+ }
95
+
96
+ foreach ($slugs as $slug) {
97
+ $metric = $this->resolve($slug);
98
+ if ($metric !== null) {
99
+ $this->metrics[$slug] = $metric->value();
103
100
  }
104
101
  }
105
102
 
106
103
  return $this;
107
104
  }
108
105
 
109
- public function earnings(?callable $callback = null): Metrics
110
- {
111
- $query = Transaction::where('company_uuid', $this->company->uuid)->whereBetween('created_at', [$this->start, $this->end]);
112
-
113
- if (is_callable($callback)) {
114
- $callback($query);
115
- }
116
-
117
- $data = $query->sum('amount');
118
-
119
- return $this->set('earnings', (int) $data);
120
- }
121
-
122
- public function fuelCosts(?callable $callback = null): Metrics
106
+ public function get(): array
123
107
  {
124
- $query = FuelReport::where('company_uuid', $this->company->uuid)->whereBetween('created_at', [$this->start, $this->end]);
125
-
126
- if (is_callable($callback)) {
127
- $callback($query);
128
- }
129
-
130
- $data = $query->sum('amount');
131
-
132
- return $this->set('fuel_costs', (int) $data);
133
- }
134
-
135
- public function totalDistanceTraveled(?callable $callback = null): Metrics
136
- {
137
- $query = Order::where(
138
- [
139
- 'company_uuid' => $this->company->uuid,
140
- 'status' => 'completed',
141
- ]
142
- )
143
- ->whereBetween('created_at', [$this->start, $this->end]);
144
-
145
- if (is_callable($callback)) {
146
- $callback($query);
147
- }
148
-
149
- $data = $query->sum('distance');
150
-
151
- return $this->set('total_distance_traveled', (int) $data);
152
- }
153
-
154
- public function totalTimeTraveled(?callable $callback = null): Metrics
155
- {
156
- $query = Order::where(
157
- [
158
- 'company_uuid' => $this->company->uuid,
159
- 'status' => 'completed',
160
- ]
161
- )
162
- ->whereBetween('created_at', [$this->start, $this->end]);
163
-
164
- if (is_callable($callback)) {
165
- $callback($query);
166
- }
167
-
168
- $data = $query->sum('distance');
169
-
170
- return $this->set('total_distance_traveled', (int) $data);
171
- }
172
-
173
- public function ordersCanceled(?callable $callback = null): Metrics
174
- {
175
- $query = Order::where('company_uuid', $this->company->uuid)
176
- ->whereBetween('created_at', [$this->start, $this->end])
177
- ->where('status', 'canceled');
178
-
179
- if (is_callable($callback)) {
180
- $callback($query);
181
- }
182
-
183
- $data = $query->count();
184
-
185
- return $this->set('orders_canceled', $data);
186
- }
187
-
188
- public function ordersCompleted(?callable $callback = null): Metrics
189
- {
190
- $query = Order::where('company_uuid', $this->company->uuid)
191
- ->whereBetween('created_at', [$this->start, $this->end])
192
- ->where('status', 'completed');
193
-
194
- if (is_callable($callback)) {
195
- $callback($query);
196
- }
197
-
198
- $data = $query->count();
199
-
200
- return $this->set('orders_completed', $data);
201
- }
202
-
203
- public function ordersInProgress(?callable $callback = null): Metrics
204
- {
205
- $query = Order::where('company_uuid', $this->company->uuid)
206
- ->whereBetween('created_at', [$this->start, $this->end])
207
- ->whereNotIn('status', ['completed', 'created', 'pending', 'canceled']);
208
-
209
- if (is_callable($callback)) {
210
- $callback($query);
211
- }
212
-
213
- $data = $query->count();
214
-
215
- return $this->set('orders_in_progress', $data);
216
- }
217
-
218
- public function activeLiveOrders(?callable $callback = null): Metrics
219
- {
220
- $query = LiveOrderQuery::make($this->company->uuid, [
221
- 'active' => true,
222
- ]);
223
-
224
- if (is_callable($callback)) {
225
- $callback($query);
226
- }
227
-
228
- $data = $query->count();
229
-
230
- return $this->set('active_live_orders', $data);
231
- }
232
-
233
- public function ordersScheduled(?callable $callback = null): Metrics
234
- {
235
- $query = Order::where('company_uuid', $this->company->uuid)
236
- ->whereBetween('created_at', [$this->start, $this->end])
237
- ->where('status', 'created')
238
- ->whereDate('scheduled_at', '>', Carbon::now());
239
-
240
- if (is_callable($callback)) {
241
- $callback($query);
242
- }
243
-
244
- $data = $query->count();
245
-
246
- return $this->set('orders_scheduled', $data);
247
- }
248
-
249
- public function driversOnline(?callable $callback = null): Metrics
250
- {
251
- $query = Driver::where('company_uuid', $this->company->uuid)
252
- ->where('online', true)
253
- ->whereNotNull('current_job_uuid');
254
-
255
- if (is_callable($callback)) {
256
- $callback($query);
257
- }
258
-
259
- $data = $query->count();
260
-
261
- return $this->set('drivers_online', $data);
262
- }
263
-
264
- public function totalDrivers(?callable $callback = null): Metrics
265
- {
266
- $query = Driver::where('company_uuid', $this->company->uuid);
267
-
268
- if (is_callable($callback)) {
269
- $callback($query);
270
- }
271
-
272
- $data = $query->count();
273
-
274
- return $this->set('total_drivers', $data);
275
- }
276
-
277
- public function totalCustomers(?callable $callback = null): Metrics
278
- {
279
- $query = Contact::where('company_uuid', $this->company->uuid)
280
- ->where('type', 'customer');
281
-
282
- if (is_callable($callback)) {
283
- $callback($query);
284
- }
285
-
286
- $data = $query->count();
287
-
288
- return $this->set('total_customers', $data);
289
- }
290
-
291
- public function openIssues(?callable $callback = null): Metrics
292
- {
293
- $query = Issue::where('company_uuid', session('company'))
294
- ->whereBetween('created_at', [$this->start, $this->end])
295
- ->where('status', 'pending');
296
-
297
- if (is_callable($callback)) {
298
- $callback($query);
299
- }
300
-
301
- $data = $query->count();
302
-
303
- return $this->set('open_issues', $data);
108
+ return $this->metrics;
304
109
  }
305
110
 
306
- public function resolvedIssues(?callable $callback = null): Metrics
111
+ private function setCompany(Company $company): Metrics
307
112
  {
308
- $query = Issue::where('company_uuid', session('company'))
309
- ->whereBetween('created_at', [$this->start, $this->end])
310
- ->whereNotNull('resolved_at');
311
-
312
- if (is_callable($callback)) {
313
- $callback($query);
314
- }
315
-
316
- $data = $query->count();
113
+ $this->company = $company;
317
114
 
318
- return $this->set('resolved_issues', $data);
115
+ return $this;
319
116
  }
320
117
  }