@fleetbase/fleetops-engine 0.6.47 → 0.6.49

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 (223) hide show
  1. package/addon/components/admin/routing-settings.hbs +71 -0
  2. package/addon/components/admin/routing-settings.js +124 -0
  3. package/addon/components/customer/orders.js +1 -1
  4. package/addon/components/display-place.hbs +1 -1
  5. package/addon/components/driver/details.hbs +5 -1
  6. package/addon/components/driver/form.hbs +11 -1
  7. package/addon/components/fleet-listing-panel.hbs +2 -2
  8. package/addon/components/fleet-listing-panel.js +10 -0
  9. package/addon/components/map/google-live-map.js +12 -73
  10. package/addon/components/map/leaflet-live-map.hbs +149 -33
  11. package/addon/components/map/order-list-overlay/order.hbs +18 -3
  12. package/addon/components/map/toolbar.hbs +2 -2
  13. package/addon/components/map/toolbar.js +10 -2
  14. package/addon/components/orchestrator/phase-builder.hbs +49 -5
  15. package/addon/components/orchestrator/phase-builder.js +34 -1
  16. package/addon/components/orchestrator/resource-panel.hbs +19 -1
  17. package/addon/components/orchestrator/resource-panel.js +4 -0
  18. package/addon/components/orchestrator-workbench.js +4 -1
  19. package/addon/components/order/details/purchase-rate.hbs +19 -22
  20. package/addon/components/order/details/route.hbs +26 -1
  21. package/addon/components/order/details/route.js +50 -0
  22. package/addon/components/order/details/tracking.hbs +171 -27
  23. package/addon/components/order/details/tracking.js +457 -0
  24. package/addon/components/order/form.hbs +2 -2
  25. package/addon/components/order/kanban-card.hbs +18 -3
  26. package/addon/components/order-list-overlay/order.hbs +18 -3
  27. package/addon/components/order-progress-card.hbs +21 -6
  28. package/addon/components/order-tracking-lookup.hbs +7 -7
  29. package/addon/components/order-tracking-lookup.js +1 -1
  30. package/addon/components/route-list.hbs +78 -8
  31. package/addon/components/route-list.js +48 -6
  32. package/addon/components/tracking-stop-progress.hbs +45 -0
  33. package/addon/components/tracking-stop-progress.js +79 -0
  34. package/addon/components/widget/fleet-ops-key-metrics.hbs +19 -17
  35. package/addon/components/widget/fleet-ops-key-metrics.js +26 -0
  36. package/addon/components/widget/fuel-efficiency.hbs +26 -0
  37. package/addon/components/widget/fuel-efficiency.js +43 -0
  38. package/addon/components/widget/geofence-violations.hbs +44 -0
  39. package/addon/components/widget/geofence-violations.js +55 -0
  40. package/addon/components/widget/issues-insights.hbs +43 -0
  41. package/addon/components/widget/issues-insights.js +62 -0
  42. package/addon/components/widget/kpi-active-orders.hbs +10 -0
  43. package/addon/components/widget/kpi-active-orders.js +5 -0
  44. package/addon/components/widget/kpi-aov.hbs +10 -0
  45. package/addon/components/widget/kpi-aov.js +5 -0
  46. package/addon/components/widget/kpi-distance.hbs +10 -0
  47. package/addon/components/widget/kpi-distance.js +5 -0
  48. package/addon/components/widget/kpi-drivers-online.hbs +10 -0
  49. package/addon/components/widget/kpi-drivers-online.js +5 -0
  50. package/addon/components/widget/kpi-earnings.hbs +10 -0
  51. package/addon/components/widget/kpi-earnings.js +5 -0
  52. package/addon/components/widget/kpi-open-issues.hbs +11 -0
  53. package/addon/components/widget/kpi-open-issues.js +5 -0
  54. package/addon/components/widget/kpi-tile.hbs +59 -0
  55. package/addon/components/widget/kpi-tile.js +168 -0
  56. package/addon/components/widget/live-fleet.hbs +122 -0
  57. package/addon/components/widget/live-fleet.js +365 -0
  58. package/addon/components/widget/maintenance-overview.hbs +45 -0
  59. package/addon/components/widget/maintenance-overview.js +40 -0
  60. package/addon/components/widget/on-time-delivery.hbs +27 -0
  61. package/addon/components/widget/on-time-delivery.js +73 -0
  62. package/addon/components/widget/operations-pulse.hbs +51 -0
  63. package/addon/components/widget/operations-pulse.js +173 -0
  64. package/addon/components/widget/orders-by-status.hbs +26 -0
  65. package/addon/components/widget/orders-by-status.js +54 -0
  66. package/addon/components/widget/revenue-trend.hbs +34 -0
  67. package/addon/components/widget/revenue-trend.js +67 -0
  68. package/addon/components/widget/top-drivers.hbs +44 -0
  69. package/addon/components/widget/top-drivers.js +54 -0
  70. package/addon/controllers/settings/routing.js +124 -1
  71. package/addon/extension.js +172 -3
  72. package/addon/helpers/format-duration.js +38 -0
  73. package/addon/routes/application.js +6 -0
  74. package/addon/services/map-adapter/google.js +13 -2
  75. package/addon/services/order-list-overlay.js +2 -2
  76. package/addon/styles/fleetops-engine.css +806 -46
  77. package/addon/templates/maintenance/equipment/index.hbs +1 -1
  78. package/addon/templates/maintenance/parts/index.hbs +1 -1
  79. package/addon/templates/maintenance/schedules/index.hbs +1 -1
  80. package/addon/templates/management/vehicles/index.hbs +1 -1
  81. package/addon/templates/settings/avatars.hbs +1 -1
  82. package/addon/templates/settings/custom-fields.hbs +1 -1
  83. package/addon/templates/settings/map.hbs +1 -1
  84. package/addon/templates/settings/navigator-app.hbs +1 -1
  85. package/addon/templates/settings/notifications.hbs +1 -1
  86. package/addon/templates/settings/orchestrator.hbs +1 -1
  87. package/addon/templates/settings/payments/index.hbs +1 -1
  88. package/addon/templates/settings/payments/onboard.hbs +1 -1
  89. package/addon/templates/settings/routing.hbs +82 -4
  90. package/addon/templates/settings/scheduling.hbs +1 -1
  91. package/addon/utils/live-map-card-content.js +171 -0
  92. package/app/components/tracking-stop-progress.js +1 -0
  93. package/app/components/widget/fuel-efficiency.js +1 -0
  94. package/app/components/widget/geofence-violations.js +1 -0
  95. package/app/components/widget/issues-insights.js +1 -0
  96. package/app/components/widget/kpi-active-orders.js +1 -0
  97. package/app/components/widget/kpi-aov.js +1 -0
  98. package/app/components/widget/kpi-distance.js +1 -0
  99. package/app/components/widget/kpi-drivers-online.js +1 -0
  100. package/app/components/widget/kpi-earnings.js +1 -0
  101. package/app/components/widget/kpi-open-issues.js +1 -0
  102. package/app/components/widget/kpi-tile.js +1 -0
  103. package/app/components/widget/live-fleet.js +1 -0
  104. package/app/components/widget/maintenance-overview.js +1 -0
  105. package/app/components/widget/on-time-delivery.js +1 -0
  106. package/app/components/widget/operations-pulse.js +1 -0
  107. package/app/components/widget/orders-by-status.js +1 -0
  108. package/app/components/widget/revenue-trend.js +1 -0
  109. package/app/components/widget/top-drivers.js +1 -0
  110. package/app/helpers/format-duration.js +1 -0
  111. package/app/utils/live-map-card-content.js +1 -0
  112. package/composer.json +1 -1
  113. package/extension.json +1 -1
  114. package/package.json +3 -3
  115. package/pnpm-workspace.yaml +1 -0
  116. package/server/config/fleetops.php +32 -11
  117. package/server/config/telematics.php +111 -1
  118. package/server/migrations/2026_05_13_000001_repair_customer_contact_user_types.php +86 -0
  119. package/server/migrations/2026_05_18_000001_add_license_expiry_to_drivers_table.php +25 -0
  120. package/server/seeders/Testing/Concerns/SeedsTestingData.php +183 -0
  121. package/server/seeders/Testing/ConnectivitySeeder.php +212 -0
  122. package/server/seeders/Testing/FleetSeeder.php +341 -0
  123. package/server/seeders/Testing/MaintenanceSeeder.php +238 -0
  124. package/server/seeders/Testing/NetworkSeeder.php +250 -0
  125. package/server/seeders/Testing/OrdersSeeder.php +214 -0
  126. package/server/seeders/Testing/TestingSeeder.php +40 -0
  127. package/server/seeders/Testing/VroomOrchestrationSeeder.php +409 -0
  128. package/server/src/Console/Commands/ProcessOperationalAlerts.php +279 -0
  129. package/server/src/Http/Controllers/Api/v1/OrchestrationController.php +64 -0
  130. package/server/src/Http/Controllers/Api/v1/OrderController.php +26 -26
  131. package/server/src/Http/Controllers/Api/v1/PayloadController.php +10 -10
  132. package/server/src/Http/Controllers/Api/v1/ServiceQuoteController.php +1 -1
  133. package/server/src/Http/Controllers/Internal/v1/AnalyticsController.php +119 -0
  134. package/server/src/Http/Controllers/Internal/v1/ContactController.php +41 -0
  135. package/server/src/Http/Controllers/Internal/v1/LiveController.php +6 -42
  136. package/server/src/Http/Controllers/Internal/v1/MetricsController.php +82 -3
  137. package/server/src/Http/Controllers/Internal/v1/OrchestrationController.php +1 -1
  138. package/server/src/Http/Controllers/Internal/v1/OrderController.php +52 -21
  139. package/server/src/Http/Controllers/Internal/v1/ServiceQuoteController.php +1 -1
  140. package/server/src/Http/Controllers/Internal/v1/SettingController.php +164 -12
  141. package/server/src/Http/Resources/v1/Driver.php +2 -0
  142. package/server/src/Http/Resources/v1/Fleet.php +4 -0
  143. package/server/src/Http/Resources/v1/Index/Driver.php +48 -0
  144. package/server/src/Http/Resources/v1/Index/Payload.php +2 -2
  145. package/server/src/Http/Resources/v1/Index/Vehicle.php +74 -1
  146. package/server/src/Models/Contact.php +122 -13
  147. package/server/src/Models/Driver.php +2 -0
  148. package/server/src/Models/Order.php +1 -1
  149. package/server/src/Models/OrderConfig.php +14 -11
  150. package/server/src/Models/Payload.php +8 -8
  151. package/server/src/Models/Place.php +0 -3
  152. package/server/src/Models/ServiceRate.php +1 -1
  153. package/server/src/Notifications/LateDeparture.php +48 -0
  154. package/server/src/Notifications/ProlongedStoppage.php +48 -0
  155. package/server/src/Notifications/RouteDeviation.php +48 -0
  156. package/server/src/Observers/ContactObserver.php +8 -0
  157. package/server/src/Orchestration/Engines/CapacityAllocationEngine.php +220 -0
  158. package/server/src/Orchestration/Engines/VroomOrchestrationEngine.php +357 -38
  159. package/server/src/Orchestration/Support/OrchestrationPayloadBuilder.php +259 -51
  160. package/server/src/Providers/FleetOpsServiceProvider.php +32 -0
  161. package/server/src/Providers/NotificationServiceProvider.php +3 -0
  162. package/server/src/Support/Analytics/AbstractAnalytics.php +77 -0
  163. package/server/src/Support/Analytics/FuelEfficiency.php +83 -0
  164. package/server/src/Support/Analytics/GeofenceViolations.php +63 -0
  165. package/server/src/Support/Analytics/IssuesInsights.php +67 -0
  166. package/server/src/Support/Analytics/LiveFleet.php +127 -0
  167. package/server/src/Support/Analytics/MaintenanceOverview.php +70 -0
  168. package/server/src/Support/Analytics/OnTimeDelivery.php +75 -0
  169. package/server/src/Support/Analytics/OperationsPulse.php +86 -0
  170. package/server/src/Support/Analytics/OrdersByStatus.php +64 -0
  171. package/server/src/Support/Analytics/RevenueTrend.php +79 -0
  172. package/server/src/Support/Analytics/TopDrivers.php +92 -0
  173. package/server/src/Support/LiveOrderQuery.php +75 -0
  174. package/server/src/Support/Metrics/AbstractMetric.php +170 -0
  175. package/server/src/Support/Metrics/ActiveLiveOrdersMetric.php +28 -0
  176. package/server/src/Support/Metrics/AvgOrderValueMetric.php +53 -0
  177. package/server/src/Support/Metrics/DriversOnlineMetric.php +30 -0
  178. package/server/src/Support/Metrics/EarningsMetric.php +30 -0
  179. package/server/src/Support/Metrics/FuelCostsMetric.php +30 -0
  180. package/server/src/Support/Metrics/MoneyMetric.php +30 -0
  181. package/server/src/Support/Metrics/OpenIssuesMetric.php +35 -0
  182. package/server/src/Support/Metrics/OrdersCanceledMetric.php +35 -0
  183. package/server/src/Support/Metrics/OrdersCompletedMetric.php +35 -0
  184. package/server/src/Support/Metrics/OrdersInProgressMetric.php +51 -0
  185. package/server/src/Support/Metrics/OrdersScheduledMetric.php +37 -0
  186. package/server/src/Support/Metrics/Registry.php +46 -0
  187. package/server/src/Support/Metrics/ResolvedIssuesMetric.php +35 -0
  188. package/server/src/Support/Metrics/TotalCustomersMetric.php +29 -0
  189. package/server/src/Support/Metrics/TotalDistanceTraveledMetric.php +35 -0
  190. package/server/src/Support/Metrics/TotalDriversMetric.php +28 -0
  191. package/server/src/Support/Metrics/TotalTimeTraveledMetric.php +35 -0
  192. package/server/src/Support/Metrics.php +46 -234
  193. package/server/src/Support/OSRM.php +11 -6
  194. package/server/src/Support/OrderTracker.php +7 -582
  195. package/server/src/Support/Telematics/Providers/AfaqyProvider.php +290 -0
  196. package/server/src/Support/Telematics/Providers/SafeeProvider.php +333 -0
  197. package/server/src/Support/Utils.php +1 -1
  198. package/server/src/Tracking/Contracts/TrackingProviderInterface.php +19 -0
  199. package/server/src/Tracking/Providers/CalculatedTrackingProvider.php +65 -0
  200. package/server/src/Tracking/Providers/GoogleRoutesTrackingProvider.php +118 -0
  201. package/server/src/Tracking/Providers/OsrmTrackingProvider.php +71 -0
  202. package/server/src/Tracking/README.md +25 -0
  203. package/server/src/Tracking/Support/FakeTrackingProvider.php +42 -0
  204. package/server/src/Tracking/TrackingContext.php +63 -0
  205. package/server/src/Tracking/TrackingContextBuilder.php +204 -0
  206. package/server/src/Tracking/TrackingIntelligenceService.php +180 -0
  207. package/server/src/Tracking/TrackingOptions.php +49 -0
  208. package/server/src/Tracking/TrackingProviderCapabilities.php +30 -0
  209. package/server/src/Tracking/TrackingProviderManager.php +89 -0
  210. package/server/src/Tracking/TrackingProviderRegistry.php +35 -0
  211. package/server/src/Tracking/TrackingProviderResult.php +20 -0
  212. package/server/src/Tracking/TrackingStop.php +59 -0
  213. package/server/src/routes.php +27 -0
  214. package/server/tests/AnalyticsRoutesTest.php +41 -0
  215. package/server/tests/CapacityAllocationEngineTest.php +108 -0
  216. package/server/tests/LiveOrderQueryTest.php +34 -0
  217. package/server/tests/MetricsRegistryTest.php +88 -0
  218. package/server/tests/OrchestrationPayloadBuilderTest.php +132 -0
  219. package/server/tests/OrchestratorConsumableApiTest.php +74 -0
  220. package/server/tests/PingDriverEndpointTest.php +19 -0
  221. package/server/tests/TrackingIntelligenceTest.php +176 -0
  222. package/server/tests/VroomOrchestrationEngineTest.php +250 -0
  223. package/translations/en-us.yaml +41 -0
@@ -0,0 +1,35 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Support\Metrics;
4
+
5
+ use Fleetbase\FleetOps\Models\Issue;
6
+
7
+ class ResolvedIssuesMetric extends AbstractMetric
8
+ {
9
+ public static function slug(): string
10
+ {
11
+ return 'resolved_issues';
12
+ }
13
+
14
+ public function format(): string
15
+ {
16
+ return 'count';
17
+ }
18
+
19
+ protected function query(?\DateTimeInterface $start, ?\DateTimeInterface $end)
20
+ {
21
+ $query = Issue::where('company_uuid', $this->company->uuid)
22
+ ->whereNotNull('resolved_at');
23
+
24
+ if ($start && $end) {
25
+ $query->whereBetween('resolved_at', [$start, $end]);
26
+ }
27
+
28
+ return $query;
29
+ }
30
+
31
+ protected function aggregate($query): int
32
+ {
33
+ return (int) $query->count();
34
+ }
35
+ }
@@ -0,0 +1,29 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Support\Metrics;
4
+
5
+ use Fleetbase\FleetOps\Models\Contact;
6
+
7
+ class TotalCustomersMetric extends AbstractMetric
8
+ {
9
+ public static function slug(): string
10
+ {
11
+ return 'total_customers';
12
+ }
13
+
14
+ public function format(): string
15
+ {
16
+ return 'count';
17
+ }
18
+
19
+ protected function query(?\DateTimeInterface $start, ?\DateTimeInterface $end)
20
+ {
21
+ return Contact::where('company_uuid', $this->company->uuid)
22
+ ->where('type', 'customer');
23
+ }
24
+
25
+ protected function aggregate($query): int
26
+ {
27
+ return (int) $query->count();
28
+ }
29
+ }
@@ -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,249 +62,56 @@ class Metrics
57
62
  return $this->start($start)->end($end);
58
63
  }
59
64
 
60
- private function setCompany(Company $company): Metrics
61
- {
62
- $this->company = $company;
63
-
64
- return $this;
65
- }
66
-
67
- private function set($key, $value = null): Metrics
65
+ /**
66
+ * Resolve a single metric by slug. New preferred entry point.
67
+ */
68
+ public function resolve(string $slug): ?AbstractMetric
68
69
  {
69
- if (is_array($key)) {
70
- foreach ($key as $k => $v) {
71
- $this->set($k, $v);
72
- }
70
+ $class = Registry::resolve($slug);
73
71
 
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;
76
+ return $class::forCompany($this->company)->between($this->start, $this->end);
80
77
  }
81
78
 
82
- public function get()
83
- {
84
- return $this->metrics;
85
- }
86
-
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
123
- {
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
106
+ public function get(): array
189
107
  {
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 ordersScheduled(?callable $callback = null): Metrics
219
- {
220
- $query = Order::where('company_uuid', $this->company->uuid)
221
- ->whereBetween('created_at', [$this->start, $this->end])
222
- ->where('status', 'created')
223
- ->whereDate('scheduled_at', '>', Carbon::now());
224
-
225
- if (is_callable($callback)) {
226
- $callback($query);
227
- }
228
-
229
- $data = $query->count();
230
-
231
- return $this->set('orders_scheduled', $data);
232
- }
233
-
234
- public function driversOnline(?callable $callback = null): Metrics
235
- {
236
- $query = Driver::where('company_uuid', $this->company->uuid)
237
- ->where('online', true)
238
- ->whereNotNull('current_job_uuid');
239
-
240
- if (is_callable($callback)) {
241
- $callback($query);
242
- }
243
-
244
- $data = $query->count();
245
-
246
- return $this->set('drivers_online', $data);
247
- }
248
-
249
- public function totalDrivers(?callable $callback = null): Metrics
250
- {
251
- $query = Driver::where('company_uuid', $this->company->uuid);
252
-
253
- if (is_callable($callback)) {
254
- $callback($query);
255
- }
256
-
257
- $data = $query->count();
258
-
259
- return $this->set('total_drivers', $data);
260
- }
261
-
262
- public function totalCustomers(?callable $callback = null): Metrics
263
- {
264
- $query = Contact::where('company_uuid', $this->company->uuid)
265
- ->where('type', 'customer');
266
-
267
- if (is_callable($callback)) {
268
- $callback($query);
269
- }
270
-
271
- $data = $query->count();
272
-
273
- return $this->set('total_customers', $data);
274
- }
275
-
276
- public function openIssues(?callable $callback = null): Metrics
277
- {
278
- $query = Issue::where('company_uuid', session('company'))
279
- ->whereBetween('created_at', [$this->start, $this->end])
280
- ->where('status', 'pending');
281
-
282
- if (is_callable($callback)) {
283
- $callback($query);
284
- }
285
-
286
- $data = $query->count();
287
-
288
- return $this->set('open_issues', $data);
108
+ return $this->metrics;
289
109
  }
290
110
 
291
- public function resolvedIssues(?callable $callback = null): Metrics
111
+ private function setCompany(Company $company): Metrics
292
112
  {
293
- $query = Issue::where('company_uuid', session('company'))
294
- ->whereBetween('created_at', [$this->start, $this->end])
295
- ->whereNotNull('resolved_at');
296
-
297
- if (is_callable($callback)) {
298
- $callback($query);
299
- }
300
-
301
- $data = $query->count();
113
+ $this->company = $company;
302
114
 
303
- return $this->set('resolved_issues', $data);
115
+ return $this;
304
116
  }
305
117
  }
@@ -88,7 +88,7 @@ class OSRM
88
88
  $cacheKey = 'getRouteFromCoordinatesString:' . md5($coordinates . serialize($queryParameters));
89
89
 
90
90
  try {
91
- $url = self::$baseUrl . "/route/v1/driving/{$coordinates}";
91
+ $url = static::baseUrl() . "/route/v1/driving/{$coordinates}";
92
92
  $response = Http::timeout(1)->get($url, $queryParameters);
93
93
  $data = $response->json();
94
94
 
@@ -130,7 +130,7 @@ class OSRM
130
130
  }
131
131
 
132
132
  $coordinates = "{$location->getLng()},{$location->getLat()}";
133
- $url = self::$baseUrl . "/nearest/v1/driving/{$coordinates}";
133
+ $url = static::baseUrl() . "/nearest/v1/driving/{$coordinates}";
134
134
  $response = Http::timeout(1)->get($url, $queryParameters);
135
135
  $result = $response->json();
136
136
 
@@ -163,7 +163,7 @@ class OSRM
163
163
  return "{$point->getLng()},{$point->getLat()}";
164
164
  }, $points));
165
165
 
166
- $url = self::$baseUrl . "/table/v1/driving/{$coordinates}";
166
+ $url = static::baseUrl() . "/table/v1/driving/{$coordinates}";
167
167
  $response = Http::timeout(1)->get($url, $queryParameters);
168
168
  $result = $response->json();
169
169
 
@@ -196,7 +196,7 @@ class OSRM
196
196
  return "{$point->getLng()},{$point->getLat()}";
197
197
  }, $points));
198
198
 
199
- $url = self::$baseUrl . "/trip/v1/driving/{$coordinates}";
199
+ $url = static::baseUrl() . "/trip/v1/driving/{$coordinates}";
200
200
  $response = Http::timeout(1)->get($url, $queryParameters);
201
201
  $data = $response->json();
202
202
 
@@ -222,7 +222,7 @@ class OSRM
222
222
 
223
223
  return "{$point->getLng()},{$point->getLat()}";
224
224
  }, $points));
225
- $url = self::$baseUrl . "/match/v1/driving/{$coordinates}";
225
+ $url = static::baseUrl() . "/match/v1/driving/{$coordinates}";
226
226
 
227
227
  $response = Http::timeout(1)->get($url, $queryParameters);
228
228
 
@@ -241,7 +241,7 @@ class OSRM
241
241
  */
242
242
  public static function getTile(int $z, int $x, int $y, array $queryParameters = [])
243
243
  {
244
- $url = self::$baseUrl . "/tile/v1/car/{$z}/{$x}/{$y}.mvt";
244
+ $url = static::baseUrl() . "/tile/v1/car/{$z}/{$x}/{$y}.mvt";
245
245
 
246
246
  $response = Http::timeout(1)->get($url, $queryParameters);
247
247
 
@@ -259,4 +259,9 @@ class OSRM
259
259
  {
260
260
  return Polyline::decode($polyline);
261
261
  }
262
+
263
+ protected static function baseUrl(): string
264
+ {
265
+ return rtrim(config('fleetops.osrm.host', static::$baseUrl), '/');
266
+ }
262
267
  }