@fleetbase/fleetops-engine 0.6.17 → 0.6.18

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 (44) hide show
  1. package/addon/components/layout/fleet-ops-sidebar.hbs +25 -0
  2. package/addon/templates/virtual.hbs +3 -3
  3. package/composer.json +3 -2
  4. package/extension.json +1 -1
  5. package/package.json +1 -1
  6. package/server/migrations/2025_08_28_054920_create_warranties_table.php +56 -0
  7. package/server/migrations/2025_08_28_054921_create_telematics_table.php +60 -0
  8. package/server/migrations/2025_08_28_054922_create_assets_table.php +94 -0
  9. package/server/migrations/2025_08_28_054925_create_devices_table.php +190 -0
  10. package/server/migrations/2025_08_28_054926_create_device_events_table.php +99 -0
  11. package/server/migrations/2025_08_28_054926_create_sensors_table.php +62 -0
  12. package/server/migrations/2025_08_28_054927_create_parts_table.php +73 -0
  13. package/server/migrations/2025_08_28_054929_create_equipments_table.php +58 -0
  14. package/server/migrations/2025_08_28_054930_create_work_orders_table.php +85 -0
  15. package/server/migrations/2025_08_28_054931_create_maintenances_table.php +79 -0
  16. package/server/migrations/2025_08_28_082002_update_vehicles_table_telematics.php +60 -0
  17. package/server/src/Http/Controllers/Api/v1/OrderController.php +6 -1
  18. package/server/src/Http/Resources/v1/Order.php +111 -60
  19. package/server/src/Models/Asset.php +548 -0
  20. package/server/src/Models/Contact.php +2 -0
  21. package/server/src/Models/Device.php +435 -0
  22. package/server/src/Models/DeviceEvent.php +501 -0
  23. package/server/src/Models/Driver.php +2 -0
  24. package/server/src/Models/Entity.php +2 -0
  25. package/server/src/Models/Equipment.php +483 -0
  26. package/server/src/Models/Fleet.php +2 -0
  27. package/server/src/Models/FuelReport.php +2 -0
  28. package/server/src/Models/Issue.php +2 -0
  29. package/server/src/Models/Maintenance.php +549 -0
  30. package/server/src/Models/Order.php +32 -112
  31. package/server/src/Models/OrderConfig.php +8 -0
  32. package/server/src/Models/Part.php +502 -0
  33. package/server/src/Models/Payload.php +101 -20
  34. package/server/src/Models/Place.php +10 -4
  35. package/server/src/Models/Sensor.php +510 -0
  36. package/server/src/Models/ServiceArea.php +1 -1
  37. package/server/src/Models/Telematic.php +336 -0
  38. package/server/src/Models/Vehicle.php +45 -1
  39. package/server/src/Models/VehicleDevice.php +1 -1
  40. package/server/src/Models/Vendor.php +2 -0
  41. package/server/src/Models/Warranty.php +413 -0
  42. package/server/src/Models/WorkOrder.php +532 -0
  43. package/server/src/Support/Utils.php +5 -0
  44. package/server/src/Traits/Maintainable.php +307 -0
@@ -56,7 +56,7 @@ class ServiceArea extends Model
56
56
  *
57
57
  * @var array
58
58
  */
59
- protected $fillable = ['_key', 'company_uuid', 'name', 'type', 'parent_uuid', 'border', 'color', 'stroke_color', 'status'];
59
+ protected $fillable = ['_key', 'company_uuid', 'name', 'type', 'parent_uuid', 'border', 'color', 'stroke_color', 'status', 'country'];
60
60
 
61
61
  /**
62
62
  * The attributes that are spatial columns.
@@ -0,0 +1,336 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Models;
4
+
5
+ use Fleetbase\Casts\Json;
6
+ use Fleetbase\Models\Model;
7
+ use Fleetbase\Models\User;
8
+ use Fleetbase\Traits\HasApiModelBehavior;
9
+ use Fleetbase\Traits\HasCustomFields;
10
+ use Fleetbase\Traits\HasMetaAttributes;
11
+ use Fleetbase\Traits\HasPublicId;
12
+ use Fleetbase\Traits\HasUuid;
13
+ use Fleetbase\Traits\Searchable;
14
+ use Fleetbase\Traits\TracksApiCredential;
15
+ use Illuminate\Database\Eloquent\Relations\BelongsTo;
16
+ use Illuminate\Database\Eloquent\Relations\HasMany;
17
+ use Illuminate\Database\Eloquent\Relations\HasOne;
18
+ use Spatie\Activitylog\LogOptions;
19
+ use Spatie\Activitylog\Traits\LogsActivity;
20
+
21
+ /**
22
+ * Class Telematic.
23
+ *
24
+ * Represents a telematics device/modem that provides connectivity and data transmission
25
+ * capabilities for fleet assets. This is the "brain" that enables communication between
26
+ * physical devices and the fleet management system.
27
+ */
28
+ class Telematic extends Model
29
+ {
30
+ use HasUuid;
31
+ use HasPublicId;
32
+ use TracksApiCredential;
33
+ use HasApiModelBehavior;
34
+ use LogsActivity;
35
+ use HasMetaAttributes;
36
+ use Searchable;
37
+ use HasCustomFields;
38
+
39
+ /**
40
+ * The database table used by the model.
41
+ *
42
+ * @var string
43
+ */
44
+ protected $table = 'telematics';
45
+
46
+ /**
47
+ * The type of public Id to generate.
48
+ *
49
+ * @var string
50
+ */
51
+ protected $publicIdType = 'telematic';
52
+
53
+ /**
54
+ * The attributes that can be queried.
55
+ *
56
+ * @var array
57
+ */
58
+ protected $searchableColumns = ['name', 'provider', 'model', 'serial_number', 'imei', 'public_id'];
59
+
60
+ /**
61
+ * The attributes that can be used for filtering.
62
+ *
63
+ * @var array
64
+ */
65
+ protected $filterParams = ['provider', 'status', 'warranty_uuid'];
66
+
67
+ /**
68
+ * The attributes that are mass assignable.
69
+ *
70
+ * @var array
71
+ */
72
+ protected $fillable = [
73
+ 'company_uuid',
74
+ 'warranty_uuid',
75
+ 'name',
76
+ 'provider',
77
+ 'model',
78
+ 'serial_number',
79
+ 'firmware_version',
80
+ 'status',
81
+ 'imei',
82
+ 'iccid',
83
+ 'imsi',
84
+ 'msisdn',
85
+ 'last_seen_at',
86
+ 'last_metrics',
87
+ 'config',
88
+ 'meta',
89
+ 'slug',
90
+ ];
91
+
92
+ /**
93
+ * Dynamic attributes that are appended to object.
94
+ *
95
+ * @var array
96
+ */
97
+ protected $appends = ['warranty_name', 'is_online', 'signal_strength', 'last_location'];
98
+
99
+ /**
100
+ * The attributes excluded from the model's JSON form.
101
+ *
102
+ * @var array
103
+ */
104
+ protected $hidden = ['warranty'];
105
+
106
+ /**
107
+ * The attributes that should be cast to native types.
108
+ *
109
+ * @var array
110
+ */
111
+ protected $casts = [
112
+ 'last_seen_at' => 'datetime',
113
+ 'last_metrics' => Json::class,
114
+ 'config' => Json::class,
115
+ 'meta' => Json::class,
116
+ ];
117
+
118
+ /**
119
+ * Properties which activity needs to be logged.
120
+ *
121
+ * @var array
122
+ */
123
+ protected static $logAttributes = '*';
124
+
125
+ /**
126
+ * Do not log empty changed.
127
+ *
128
+ * @var bool
129
+ */
130
+ protected static $submitEmptyLogs = false;
131
+
132
+ /**
133
+ * The name of the subject to log.
134
+ *
135
+ * @var string
136
+ */
137
+ protected static $logName = 'telematic';
138
+
139
+ /**
140
+ * Get the activity log options for the model.
141
+ */
142
+ public function getActivitylogOptions(): LogOptions
143
+ {
144
+ return LogOptions::defaults()->logAll();
145
+ }
146
+
147
+ public function warranty(): BelongsTo
148
+ {
149
+ return $this->belongsTo(Warranty::class, 'warranty_uuid', 'uuid');
150
+ }
151
+
152
+ public function createdBy(): BelongsTo
153
+ {
154
+ return $this->belongsTo(User::class, 'created_by_uuid', 'uuid');
155
+ }
156
+
157
+ public function updatedBy(): BelongsTo
158
+ {
159
+ return $this->belongsTo(User::class, 'updated_by_uuid', 'uuid');
160
+ }
161
+
162
+ public function device(): HasOne
163
+ {
164
+ return $this->hasOne(Device::class, 'telematic_uuid', 'uuid');
165
+ }
166
+
167
+ public function assets(): HasMany
168
+ {
169
+ return $this->hasMany(Asset::class, 'telematic_uuid', 'uuid');
170
+ }
171
+
172
+ /**
173
+ * Get the warranty name.
174
+ */
175
+ public function getWarrantyNameAttribute(): ?string
176
+ {
177
+ return $this->warranty?->name;
178
+ }
179
+
180
+ /**
181
+ * Check if the telematic device is currently online.
182
+ */
183
+ public function getIsOnlineAttribute(): bool
184
+ {
185
+ if (!$this->last_seen_at) {
186
+ return false;
187
+ }
188
+
189
+ // Consider online if last seen within 5 minutes
190
+ return $this->last_seen_at->gt(now()->subMinutes(5));
191
+ }
192
+
193
+ /**
194
+ * Get the signal strength from last metrics.
195
+ */
196
+ public function getSignalStrengthAttribute(): ?int
197
+ {
198
+ return $this->last_metrics['signal_strength'] ?? null;
199
+ }
200
+
201
+ /**
202
+ * Get the last known location from metrics.
203
+ */
204
+ public function getLastLocationAttribute(): ?array
205
+ {
206
+ $metrics = $this->last_metrics;
207
+
208
+ if (isset($metrics['lat']) && isset($metrics['lng'])) {
209
+ return [
210
+ 'latitude' => $metrics['lat'],
211
+ 'longitude' => $metrics['lng'],
212
+ 'timestamp' => $this->last_seen_at?->toISOString(),
213
+ ];
214
+ }
215
+
216
+ return null;
217
+ }
218
+
219
+ /**
220
+ * Scope to get online telematics.
221
+ *
222
+ * @param \Illuminate\Database\Eloquent\Builder $query
223
+ *
224
+ * @return \Illuminate\Database\Eloquent\Builder
225
+ */
226
+ public function scopeOnline($query)
227
+ {
228
+ return $query->where('last_seen_at', '>=', now()->subMinutes(5));
229
+ }
230
+
231
+ /**
232
+ * Scope to get offline telematics.
233
+ *
234
+ * @param \Illuminate\Database\Eloquent\Builder $query
235
+ *
236
+ * @return \Illuminate\Database\Eloquent\Builder
237
+ */
238
+ public function scopeOffline($query)
239
+ {
240
+ return $query->where(function ($q) {
241
+ $q->whereNull('last_seen_at')
242
+ ->orWhere('last_seen_at', '<', now()->subMinutes(5));
243
+ });
244
+ }
245
+
246
+ /**
247
+ * Scope to get telematics by provider.
248
+ *
249
+ * @param \Illuminate\Database\Eloquent\Builder $query
250
+ *
251
+ * @return \Illuminate\Database\Eloquent\Builder
252
+ */
253
+ public function scopeByProvider($query, string $provider)
254
+ {
255
+ return $query->where('provider', $provider);
256
+ }
257
+
258
+ /**
259
+ * Update the last seen timestamp and metrics.
260
+ */
261
+ public function updateHeartbeat(array $metrics = []): bool
262
+ {
263
+ return $this->update([
264
+ 'last_seen_at' => now(),
265
+ 'last_metrics' => array_merge($this->last_metrics ?? [], $metrics),
266
+ ]);
267
+ }
268
+
269
+ /**
270
+ * Get the connection status based on last seen time.
271
+ */
272
+ public function getConnectionStatus(): string
273
+ {
274
+ if (!$this->last_seen_at) {
275
+ return 'never_connected';
276
+ }
277
+
278
+ $minutesOffline = $this->last_seen_at->diffInMinutes(now());
279
+
280
+ if ($minutesOffline <= 5) {
281
+ return 'online';
282
+ } elseif ($minutesOffline <= 60) {
283
+ return 'recently_offline';
284
+ } elseif ($minutesOffline <= 1440) { // 24 hours
285
+ return 'offline';
286
+ } else {
287
+ return 'long_offline';
288
+ }
289
+ }
290
+
291
+ /**
292
+ * Check if the telematic supports a specific feature.
293
+ */
294
+ public function supportsFeature(string $feature): bool
295
+ {
296
+ $config = $this->config ?? [];
297
+ $features = $config['supported_features'] ?? [];
298
+
299
+ return in_array($feature, $features);
300
+ }
301
+
302
+ /**
303
+ * Get the firmware update status.
304
+ */
305
+ public function getFirmwareStatus(): array
306
+ {
307
+ $config = $this->config ?? [];
308
+
309
+ return [
310
+ 'current_version' => $this->firmware_version,
311
+ 'latest_version' => $config['latest_firmware'] ?? null,
312
+ 'update_available' => isset($config['latest_firmware'])
313
+ && version_compare($this->firmware_version, $config['latest_firmware'], '<'),
314
+ ];
315
+ }
316
+
317
+ /**
318
+ * Send a command to the telematic device.
319
+ */
320
+ public function sendCommand(string $command, array $parameters = []): bool
321
+ {
322
+ // This would integrate with the actual telematic provider's API
323
+ // For now, we'll just log the command attempt
324
+
325
+ activity('telematic_command')
326
+ ->performedOn($this)
327
+ ->withProperties([
328
+ 'command' => $command,
329
+ 'parameters' => $parameters,
330
+ 'timestamp' => now(),
331
+ ])
332
+ ->log("Command '{$command}' sent to telematic device");
333
+
334
+ return true;
335
+ }
336
+ }
@@ -7,9 +7,11 @@ use Fleetbase\FleetOps\Casts\Point;
7
7
  use Fleetbase\FleetOps\Support\Utils;
8
8
  use Fleetbase\FleetOps\Support\VehicleData;
9
9
  use Fleetbase\LaravelMysqlSpatial\Eloquent\SpatialTrait;
10
+ use Fleetbase\Models\Category;
10
11
  use Fleetbase\Models\File;
11
12
  use Fleetbase\Models\Model;
12
13
  use Fleetbase\Traits\HasApiModelBehavior;
14
+ use Fleetbase\Traits\HasCustomFields;
13
15
  use Fleetbase\Traits\HasMetaAttributes;
14
16
  use Fleetbase\Traits\HasPublicId;
15
17
  use Fleetbase\Traits\HasUuid;
@@ -19,6 +21,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
19
21
  use Illuminate\Database\Eloquent\Relations\HasMany;
20
22
  use Illuminate\Database\Eloquent\Relations\HasManyThrough;
21
23
  use Illuminate\Database\Eloquent\Relations\HasOne;
24
+ use Illuminate\Database\Eloquent\Relations\MorphMany;
22
25
  use Illuminate\Support\Str;
23
26
  use Spatie\Activitylog\LogOptions;
24
27
  use Spatie\Activitylog\Traits\LogsActivity;
@@ -36,6 +39,7 @@ class Vehicle extends Model
36
39
  use HasSlug;
37
40
  use LogsActivity;
38
41
  use HasMetaAttributes;
42
+ use HasCustomFields;
39
43
 
40
44
  /**
41
45
  * The database table used by the model.
@@ -98,6 +102,8 @@ class Vehicle extends Model
98
102
  protected $fillable = [
99
103
  'company_uuid',
100
104
  'vendor_uuid',
105
+ 'category_uuid',
106
+ 'warranty_uuid',
101
107
  'photo_uuid',
102
108
  'avatar_url',
103
109
  'make',
@@ -176,6 +182,21 @@ class Vehicle extends Model
176
182
  return $this->hasOne(Driver::class)->without(['vehicle']);
177
183
  }
178
184
 
185
+ public function category(): BelongsTo
186
+ {
187
+ return $this->belongsTo(Category::class, 'category_uuid', 'uuid');
188
+ }
189
+
190
+ public function telematic(): BelongsTo
191
+ {
192
+ return $this->belongsTo(Telematic::class, 'telematic_uuid', 'uuid');
193
+ }
194
+
195
+ public function warranty(): BelongsTo
196
+ {
197
+ return $this->belongsTo(Warranty::class, 'warranty_uuid', 'uuid');
198
+ }
199
+
179
200
  public function vendor(): BelongsTo
180
201
  {
181
202
  return $this->belongsTo(Vendor::class);
@@ -188,7 +209,7 @@ class Vehicle extends Model
188
209
 
189
210
  public function devices(): HasMany
190
211
  {
191
- return $this->hasMany(VehicleDevice::class);
212
+ return $this->hasMany(Device::class, 'attachable_uuid');
192
213
  }
193
214
 
194
215
  public function positions(): HasMany
@@ -196,6 +217,29 @@ class Vehicle extends Model
196
217
  return $this->hasMany(Position::class, 'subject_uuid');
197
218
  }
198
219
 
220
+ public function equipments(): HasMany
221
+ {
222
+ return $this->hasMany(Equipment::class, 'equipable_uuid', 'uuid')
223
+ ->where('equipable_type', static::class);
224
+ }
225
+
226
+ public function maintenances(): HasMany
227
+ {
228
+ return $this->hasMany(Maintenance::class, 'maintainable_uuid', 'uuid')
229
+ ->where('maintainable_type', static::class);
230
+ }
231
+
232
+ public function sensors(): HasMany
233
+ {
234
+ return $this->hasMany(Sensor::class, 'sensorable_uuid', 'uuid')
235
+ ->where('sensorable_type', static::class);
236
+ }
237
+
238
+ public function parts(): MorphMany
239
+ {
240
+ return $this->morphMany(Part::class, 'asset');
241
+ }
242
+
199
243
  /**
200
244
  * Get avatar URL attribute.
201
245
  *
@@ -19,7 +19,7 @@ class VehicleDevice extends Model
19
19
  *
20
20
  * @var string
21
21
  */
22
- protected $table = 'vehicle_devices';
22
+ protected $table = 'devices';
23
23
 
24
24
  /**
25
25
  * Attributes that is filterable on this model.
@@ -6,6 +6,7 @@ use Fleetbase\Casts\Json;
6
6
  use Fleetbase\FleetOps\Support\Utils;
7
7
  use Fleetbase\Models\Model;
8
8
  use Fleetbase\Traits\HasApiModelBehavior;
9
+ use Fleetbase\Traits\HasCustomFields;
9
10
  use Fleetbase\Traits\HasInternalId;
10
11
  use Fleetbase\Traits\HasPublicId;
11
12
  use Fleetbase\Traits\HasUuid;
@@ -32,6 +33,7 @@ class Vendor extends Model
32
33
  use HasSlug;
33
34
  use LogsActivity;
34
35
  use Notifiable;
36
+ use HasCustomFields;
35
37
 
36
38
  /**
37
39
  * The database table used by the model.