@fleetbase/fleetops-engine 0.6.16 → 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.
- package/addon/components/layout/fleet-ops-sidebar.hbs +25 -0
- package/addon/templates/virtual.hbs +3 -3
- package/composer.json +3 -2
- package/extension.json +1 -1
- package/package.json +1 -1
- package/server/migrations/2025_08_11_170800_add_company_index_to_routes_table.php +21 -0
- package/server/migrations/2025_08_28_054920_create_warranties_table.php +56 -0
- package/server/migrations/2025_08_28_054921_create_telematics_table.php +60 -0
- package/server/migrations/2025_08_28_054922_create_assets_table.php +94 -0
- package/server/migrations/2025_08_28_054925_create_devices_table.php +190 -0
- package/server/migrations/2025_08_28_054926_create_device_events_table.php +99 -0
- package/server/migrations/2025_08_28_054926_create_sensors_table.php +62 -0
- package/server/migrations/2025_08_28_054927_create_parts_table.php +73 -0
- package/server/migrations/2025_08_28_054929_create_equipments_table.php +58 -0
- package/server/migrations/2025_08_28_054930_create_work_orders_table.php +85 -0
- package/server/migrations/2025_08_28_054931_create_maintenances_table.php +79 -0
- package/server/migrations/2025_08_28_082002_update_vehicles_table_telematics.php +60 -0
- package/server/src/Http/Controllers/Api/v1/OrderController.php +19 -1
- package/server/src/Http/Controllers/Internal/v1/OrderController.php +31 -8
- package/server/src/Http/Resources/v1/Order.php +111 -60
- package/server/src/Models/Asset.php +548 -0
- package/server/src/Models/Contact.php +2 -0
- package/server/src/Models/Device.php +435 -0
- package/server/src/Models/DeviceEvent.php +501 -0
- package/server/src/Models/Driver.php +2 -0
- package/server/src/Models/Entity.php +27 -50
- package/server/src/Models/Equipment.php +483 -0
- package/server/src/Models/Fleet.php +2 -0
- package/server/src/Models/FuelReport.php +2 -0
- package/server/src/Models/Issue.php +2 -0
- package/server/src/Models/Maintenance.php +549 -0
- package/server/src/Models/Order.php +32 -112
- package/server/src/Models/OrderConfig.php +8 -0
- package/server/src/Models/Part.php +502 -0
- package/server/src/Models/Payload.php +101 -20
- package/server/src/Models/Place.php +10 -4
- package/server/src/Models/Sensor.php +510 -0
- package/server/src/Models/ServiceArea.php +1 -1
- package/server/src/Models/Telematic.php +336 -0
- package/server/src/Models/Vehicle.php +45 -1
- package/server/src/Models/VehicleDevice.php +1 -1
- package/server/src/Models/Vendor.php +2 -0
- package/server/src/Models/Warranty.php +413 -0
- package/server/src/Models/Waypoint.php +2 -0
- package/server/src/Models/WorkOrder.php +532 -0
- package/server/src/Support/Utils.php +5 -0
- package/server/src/Traits/HasTrackingNumber.php +64 -10
- package/server/src/Traits/Maintainable.php +307 -0
- package/server/src/Traits/PayloadAccessors.php +126 -0
|
@@ -0,0 +1,435 @@
|
|
|
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\MorphTo;
|
|
18
|
+
use Spatie\Activitylog\LogOptions;
|
|
19
|
+
use Spatie\Activitylog\Traits\LogsActivity;
|
|
20
|
+
use Spatie\Sluggable\HasSlug;
|
|
21
|
+
use Spatie\Sluggable\SlugOptions;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Class Device.
|
|
25
|
+
*
|
|
26
|
+
* Represents a physical device that can be mounted or carried, using a telematic
|
|
27
|
+
* for connectivity. Examples include dashcams, OBD devices, hardwired blackboxes, tablets.
|
|
28
|
+
*/
|
|
29
|
+
class Device extends Model
|
|
30
|
+
{
|
|
31
|
+
use HasUuid;
|
|
32
|
+
use HasPublicId;
|
|
33
|
+
use TracksApiCredential;
|
|
34
|
+
use HasApiModelBehavior;
|
|
35
|
+
use HasSlug;
|
|
36
|
+
use LogsActivity;
|
|
37
|
+
use HasMetaAttributes;
|
|
38
|
+
use Searchable;
|
|
39
|
+
use HasCustomFields;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The database table used by the model.
|
|
43
|
+
*
|
|
44
|
+
* @var string
|
|
45
|
+
*/
|
|
46
|
+
protected $table = 'devices';
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The type of public Id to generate.
|
|
50
|
+
*
|
|
51
|
+
* @var string
|
|
52
|
+
*/
|
|
53
|
+
protected $publicIdType = 'device';
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The attributes that can be queried.
|
|
57
|
+
*
|
|
58
|
+
* @var array
|
|
59
|
+
*/
|
|
60
|
+
protected $searchableColumns = ['name', 'model', 'serial_number', 'public_id'];
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The attributes that can be used for filtering.
|
|
64
|
+
*
|
|
65
|
+
* @var array
|
|
66
|
+
*/
|
|
67
|
+
protected $filterParams = ['status', 'warranty_uuid', 'attachable_type'];
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The attributes that are mass assignable.
|
|
71
|
+
*
|
|
72
|
+
* @var array
|
|
73
|
+
*/
|
|
74
|
+
protected $fillable = [
|
|
75
|
+
'company_uuid',
|
|
76
|
+
'telematic_uuid',
|
|
77
|
+
'warranty_uuid',
|
|
78
|
+
'device_type',
|
|
79
|
+
'device_id',
|
|
80
|
+
'device_provider',
|
|
81
|
+
'device_name',
|
|
82
|
+
'device_model',
|
|
83
|
+
'device_location',
|
|
84
|
+
'manufacturer',
|
|
85
|
+
'serial_number',
|
|
86
|
+
'installation_date',
|
|
87
|
+
'last_maintenance_date',
|
|
88
|
+
'meta',
|
|
89
|
+
'data',
|
|
90
|
+
'options',
|
|
91
|
+
'online',
|
|
92
|
+
'status',
|
|
93
|
+
'data_frequency',
|
|
94
|
+
'notes',
|
|
95
|
+
'status',
|
|
96
|
+
'last_online_at',
|
|
97
|
+
'attachable_type',
|
|
98
|
+
'attachable_uuid',
|
|
99
|
+
'slug',
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Dynamic attributes that are appended to object.
|
|
104
|
+
*
|
|
105
|
+
* @var array
|
|
106
|
+
*/
|
|
107
|
+
protected $appends = [
|
|
108
|
+
'warranty_name',
|
|
109
|
+
'telematic_name',
|
|
110
|
+
'is_online',
|
|
111
|
+
'attached_to_name',
|
|
112
|
+
'connection_status',
|
|
113
|
+
];
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* The attributes excluded from the model's JSON form.
|
|
117
|
+
*
|
|
118
|
+
* @var array
|
|
119
|
+
*/
|
|
120
|
+
protected $hidden = ['warranty', 'telematic', 'attachable'];
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* The attributes that should be cast to native types.
|
|
124
|
+
*
|
|
125
|
+
* @var array
|
|
126
|
+
*/
|
|
127
|
+
protected $casts = [
|
|
128
|
+
'last_online_at' => 'datetime',
|
|
129
|
+
'meta' => Json::class,
|
|
130
|
+
'options' => Json::class,
|
|
131
|
+
];
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Properties which activity needs to be logged.
|
|
135
|
+
*
|
|
136
|
+
* @var array
|
|
137
|
+
*/
|
|
138
|
+
protected static $logAttributes = '*';
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Do not log empty changed.
|
|
142
|
+
*
|
|
143
|
+
* @var bool
|
|
144
|
+
*/
|
|
145
|
+
protected static $submitEmptyLogs = false;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* The name of the subject to log.
|
|
149
|
+
*
|
|
150
|
+
* @var string
|
|
151
|
+
*/
|
|
152
|
+
protected static $logName = 'device';
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Get the options for generating the slug.
|
|
156
|
+
*/
|
|
157
|
+
public function getSlugOptions(): SlugOptions
|
|
158
|
+
{
|
|
159
|
+
return SlugOptions::create()
|
|
160
|
+
->generateSlugsFrom(['name', 'serial_number'])
|
|
161
|
+
->saveSlugsTo('slug');
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Get the activity log options for the model.
|
|
166
|
+
*/
|
|
167
|
+
public function getActivitylogOptions(): LogOptions
|
|
168
|
+
{
|
|
169
|
+
return LogOptions::defaults()->logAll();
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
public function telematic(): BelongsTo
|
|
173
|
+
{
|
|
174
|
+
return $this->belongsTo(Telematic::class, 'telematic_uuid', 'uuid');
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
public function warranty(): BelongsTo
|
|
178
|
+
{
|
|
179
|
+
return $this->belongsTo(Warranty::class, 'warranty_uuid', 'uuid');
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
public function createdBy(): BelongsTo
|
|
183
|
+
{
|
|
184
|
+
return $this->belongsTo(User::class, 'created_by_uuid', 'uuid');
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
public function updatedBy(): BelongsTo
|
|
188
|
+
{
|
|
189
|
+
return $this->belongsTo(User::class, 'updated_by_uuid', 'uuid');
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
public function attachable(): MorphTo
|
|
193
|
+
{
|
|
194
|
+
return $this->morphTo();
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
public function events(): HasMany
|
|
198
|
+
{
|
|
199
|
+
return $this->hasMany(DeviceEvent::class, 'device_uuid', 'uuid');
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
public function sensors(): HasMany
|
|
203
|
+
{
|
|
204
|
+
return $this->hasMany(Sensor::class, 'device_uuid', 'uuid');
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Get the warranty name.
|
|
209
|
+
*/
|
|
210
|
+
public function getWarrantyNameAttribute(): ?string
|
|
211
|
+
{
|
|
212
|
+
return $this->warranty?->name;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Get the telematic name.
|
|
217
|
+
*/
|
|
218
|
+
public function getTelematicNameAttribute(): ?string
|
|
219
|
+
{
|
|
220
|
+
return $this->telematic?->name;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Check if the device is currently online.
|
|
225
|
+
*/
|
|
226
|
+
public function getIsOnlineAttribute(): bool
|
|
227
|
+
{
|
|
228
|
+
if (!$this->last_online_at) {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Consider online if last seen within 10 minutes
|
|
233
|
+
return $this->last_online_at->gt(now()->subMinutes(10));
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Get the name of what the device is attached to.
|
|
238
|
+
*/
|
|
239
|
+
public function getAttachedToNameAttribute(): ?string
|
|
240
|
+
{
|
|
241
|
+
if ($this->attachable) {
|
|
242
|
+
return $this->attachable->name ?? $this->attachable->display_name ?? null;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Get the connection status.
|
|
250
|
+
*/
|
|
251
|
+
public function getConnectionStatusAttribute(): string
|
|
252
|
+
{
|
|
253
|
+
if (!$this->last_online_at) {
|
|
254
|
+
return 'never_connected';
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
$minutesOffline = $this->last_online_at->diffInMinutes(now());
|
|
258
|
+
|
|
259
|
+
if ($minutesOffline <= 10) {
|
|
260
|
+
return 'online';
|
|
261
|
+
} elseif ($minutesOffline <= 60) {
|
|
262
|
+
return 'recently_offline';
|
|
263
|
+
} elseif ($minutesOffline <= 1440) { // 24 hours
|
|
264
|
+
return 'offline';
|
|
265
|
+
} else {
|
|
266
|
+
return 'long_offline';
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Scope to get online devices.
|
|
272
|
+
*
|
|
273
|
+
* @param \Illuminate\Database\Eloquent\Builder $query
|
|
274
|
+
*
|
|
275
|
+
* @return \Illuminate\Database\Eloquent\Builder
|
|
276
|
+
*/
|
|
277
|
+
public function scopeOnline($query)
|
|
278
|
+
{
|
|
279
|
+
return $query->where('last_online_at', '>=', now()->subMinutes(10));
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Scope to get offline devices.
|
|
284
|
+
*
|
|
285
|
+
* @param \Illuminate\Database\Eloquent\Builder $query
|
|
286
|
+
*
|
|
287
|
+
* @return \Illuminate\Database\Eloquent\Builder
|
|
288
|
+
*/
|
|
289
|
+
public function scopeOffline($query)
|
|
290
|
+
{
|
|
291
|
+
return $query->where(function ($q) {
|
|
292
|
+
$q->whereNull('last_online_at')
|
|
293
|
+
->orWhere('last_online_at', '<', now()->subMinutes(10));
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Scope to get devices attached to a specific type.
|
|
299
|
+
*
|
|
300
|
+
* @param \Illuminate\Database\Eloquent\Builder $query
|
|
301
|
+
*
|
|
302
|
+
* @return \Illuminate\Database\Eloquent\Builder
|
|
303
|
+
*/
|
|
304
|
+
public function scopeAttachedTo($query, string $type)
|
|
305
|
+
{
|
|
306
|
+
return $query->where('attachable_type', $type);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Update the last online timestamp.
|
|
311
|
+
*/
|
|
312
|
+
public function updateLastOnline(): bool
|
|
313
|
+
{
|
|
314
|
+
return $this->update(['last_online_at' => now()]);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Attach the device to an entity.
|
|
319
|
+
*/
|
|
320
|
+
public function attachTo(Model $attachable): bool
|
|
321
|
+
{
|
|
322
|
+
$updated = $this->update([
|
|
323
|
+
'attachable_type' => get_class($attachable),
|
|
324
|
+
'attachable_uuid' => $attachable->uuid,
|
|
325
|
+
]);
|
|
326
|
+
|
|
327
|
+
if ($updated) {
|
|
328
|
+
activity('device_attached')
|
|
329
|
+
->performedOn($this)
|
|
330
|
+
->withProperties([
|
|
331
|
+
'attached_to_type' => get_class($attachable),
|
|
332
|
+
'attached_to_uuid' => $attachable->uuid,
|
|
333
|
+
'attached_to_name' => $attachable->name ?? $attachable->display_name ?? null,
|
|
334
|
+
])
|
|
335
|
+
->log('Device attached');
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
return $updated;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Detach the device from its current attachment.
|
|
343
|
+
*/
|
|
344
|
+
public function detach(): bool
|
|
345
|
+
{
|
|
346
|
+
$oldAttachableType = $this->attachable_type;
|
|
347
|
+
$oldAttachableUuid = $this->attachable_uuid;
|
|
348
|
+
|
|
349
|
+
$updated = $this->update([
|
|
350
|
+
'attachable_type' => null,
|
|
351
|
+
'attachable_uuid' => null,
|
|
352
|
+
]);
|
|
353
|
+
|
|
354
|
+
if ($updated) {
|
|
355
|
+
activity('device_detached')
|
|
356
|
+
->performedOn($this)
|
|
357
|
+
->withProperties([
|
|
358
|
+
'previous_attached_to_type' => $oldAttachableType,
|
|
359
|
+
'previous_attached_to_uuid' => $oldAttachableUuid,
|
|
360
|
+
])
|
|
361
|
+
->log('Device detached');
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
return $updated;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Check if the device supports a specific feature.
|
|
369
|
+
*/
|
|
370
|
+
public function supportsFeature(string $feature): bool
|
|
371
|
+
{
|
|
372
|
+
$options = $this->options ?? [];
|
|
373
|
+
$features = $options['supported_features'] ?? [];
|
|
374
|
+
|
|
375
|
+
return in_array($feature, $features);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Get the device configuration.
|
|
380
|
+
*/
|
|
381
|
+
public function getConfiguration(): array
|
|
382
|
+
{
|
|
383
|
+
return $this->options ?? [];
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Update the device configuration.
|
|
388
|
+
*/
|
|
389
|
+
public function updateConfiguration(array $config): bool
|
|
390
|
+
{
|
|
391
|
+
$currentOptions = $this->options ?? [];
|
|
392
|
+
$newOptions = array_merge($currentOptions, $config);
|
|
393
|
+
|
|
394
|
+
return $this->update(['options' => $newOptions]);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Send a command to the device via its telematic.
|
|
399
|
+
*/
|
|
400
|
+
public function sendCommand(string $command, array $parameters = []): bool
|
|
401
|
+
{
|
|
402
|
+
if (!$this->telematic) {
|
|
403
|
+
return false;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Log the command for the device
|
|
407
|
+
activity('device_command')
|
|
408
|
+
->performedOn($this)
|
|
409
|
+
->withProperties([
|
|
410
|
+
'command' => $command,
|
|
411
|
+
'parameters' => $parameters,
|
|
412
|
+
'via_telematic' => $this->telematic->uuid,
|
|
413
|
+
'timestamp' => now(),
|
|
414
|
+
])
|
|
415
|
+
->log("Command '{$command}' sent to device");
|
|
416
|
+
|
|
417
|
+
// Delegate to telematic
|
|
418
|
+
return $this->telematic->sendCommand($command, array_merge($parameters, [
|
|
419
|
+
'target_device' => $this->uuid,
|
|
420
|
+
]));
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Get recent events for the device.
|
|
425
|
+
*
|
|
426
|
+
* @return \Illuminate\Database\Eloquent\Collection
|
|
427
|
+
*/
|
|
428
|
+
public function getRecentEvents(int $limit = 10)
|
|
429
|
+
{
|
|
430
|
+
return $this->events()
|
|
431
|
+
->orderBy('created_at', 'desc')
|
|
432
|
+
->limit($limit)
|
|
433
|
+
->get();
|
|
434
|
+
}
|
|
435
|
+
}
|