@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.
- 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_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 +6 -1
- 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 +2 -0
- 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/WorkOrder.php +532 -0
- package/server/src/Support/Utils.php +5 -0
- package/server/src/Traits/Maintainable.php +307 -0
|
@@ -0,0 +1,413 @@
|
|
|
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\MorphTo;
|
|
17
|
+
use Spatie\Activitylog\LogOptions;
|
|
18
|
+
use Spatie\Activitylog\Traits\LogsActivity;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Class Warranty.
|
|
22
|
+
*
|
|
23
|
+
* Represents warranty coverage and terms for various items in the fleet management system.
|
|
24
|
+
* Warranties can be attached to assets, equipment, parts, or other entities.
|
|
25
|
+
*/
|
|
26
|
+
class Warranty extends Model
|
|
27
|
+
{
|
|
28
|
+
use HasUuid;
|
|
29
|
+
use HasPublicId;
|
|
30
|
+
use TracksApiCredential;
|
|
31
|
+
use HasApiModelBehavior;
|
|
32
|
+
use LogsActivity;
|
|
33
|
+
use HasMetaAttributes;
|
|
34
|
+
use Searchable;
|
|
35
|
+
use HasCustomFields;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The database table used by the model.
|
|
39
|
+
*
|
|
40
|
+
* @var string
|
|
41
|
+
*/
|
|
42
|
+
protected $table = 'warranties';
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The type of public Id to generate.
|
|
46
|
+
*
|
|
47
|
+
* @var string
|
|
48
|
+
*/
|
|
49
|
+
protected $publicIdType = 'warranty';
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The attributes that can be queried.
|
|
53
|
+
*
|
|
54
|
+
* @var array
|
|
55
|
+
*/
|
|
56
|
+
protected $searchableColumns = ['provider', 'policy_number', 'public_id'];
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The attributes that can be used for filtering.
|
|
60
|
+
*
|
|
61
|
+
* @var array
|
|
62
|
+
*/
|
|
63
|
+
protected $filterParams = ['provider', 'vendor_uuid', 'subject_type', 'start_date', 'end_date'];
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The attributes that are mass assignable.
|
|
67
|
+
*
|
|
68
|
+
* @var array
|
|
69
|
+
*/
|
|
70
|
+
protected $fillable = [
|
|
71
|
+
'company_uuid',
|
|
72
|
+
'subject_type',
|
|
73
|
+
'subject_uuid',
|
|
74
|
+
'provider',
|
|
75
|
+
'policy_number',
|
|
76
|
+
'start_date',
|
|
77
|
+
'end_date',
|
|
78
|
+
'coverage',
|
|
79
|
+
'terms',
|
|
80
|
+
'policy',
|
|
81
|
+
'vendor_uuid',
|
|
82
|
+
'meta',
|
|
83
|
+
'slug',
|
|
84
|
+
];
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Dynamic attributes that are appended to object.
|
|
88
|
+
*
|
|
89
|
+
* @var array
|
|
90
|
+
*/
|
|
91
|
+
protected $appends = [
|
|
92
|
+
'subject_name',
|
|
93
|
+
'vendor_name',
|
|
94
|
+
'is_active',
|
|
95
|
+
'is_expired',
|
|
96
|
+
'days_remaining',
|
|
97
|
+
'coverage_summary',
|
|
98
|
+
'status',
|
|
99
|
+
];
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* The attributes excluded from the model's JSON form.
|
|
103
|
+
*
|
|
104
|
+
* @var array
|
|
105
|
+
*/
|
|
106
|
+
protected $hidden = ['subject', 'vendor'];
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* The attributes that should be cast to native types.
|
|
110
|
+
*
|
|
111
|
+
* @var array
|
|
112
|
+
*/
|
|
113
|
+
protected $casts = [
|
|
114
|
+
'start_date' => 'date',
|
|
115
|
+
'end_date' => 'date',
|
|
116
|
+
'coverage' => Json::class,
|
|
117
|
+
'terms' => Json::class,
|
|
118
|
+
'meta' => Json::class,
|
|
119
|
+
];
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Properties which activity needs to be logged.
|
|
123
|
+
*
|
|
124
|
+
* @var array
|
|
125
|
+
*/
|
|
126
|
+
protected static $logAttributes = '*';
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Do not log empty changed.
|
|
130
|
+
*
|
|
131
|
+
* @var bool
|
|
132
|
+
*/
|
|
133
|
+
protected static $submitEmptyLogs = false;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* The name of the subject to log.
|
|
137
|
+
*
|
|
138
|
+
* @var string
|
|
139
|
+
*/
|
|
140
|
+
protected static $logName = 'warranty';
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Get the activity log options for the model.
|
|
144
|
+
*/
|
|
145
|
+
public function getActivitylogOptions(): LogOptions
|
|
146
|
+
{
|
|
147
|
+
return LogOptions::defaults()->logAll();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
public function vendor(): BelongsTo
|
|
151
|
+
{
|
|
152
|
+
return $this->belongsTo(Vendor::class, 'vendor_uuid', 'uuid');
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
public function createdBy(): BelongsTo
|
|
156
|
+
{
|
|
157
|
+
return $this->belongsTo(User::class, 'created_by_uuid', 'uuid');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
public function updatedBy(): BelongsTo
|
|
161
|
+
{
|
|
162
|
+
return $this->belongsTo(User::class, 'updated_by_uuid', 'uuid');
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
public function subject(): MorphTo
|
|
166
|
+
{
|
|
167
|
+
return $this->morphTo();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Get the subject name.
|
|
172
|
+
*/
|
|
173
|
+
public function getSubjectNameAttribute(): ?string
|
|
174
|
+
{
|
|
175
|
+
if ($this->subject) {
|
|
176
|
+
return $this->subject->name ?? $this->subject->display_name ?? null;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Get the vendor name.
|
|
184
|
+
*/
|
|
185
|
+
public function getVendorNameAttribute(): ?string
|
|
186
|
+
{
|
|
187
|
+
return $this->vendor?->name;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Check if the warranty is currently active.
|
|
192
|
+
*/
|
|
193
|
+
public function getIsActiveAttribute(): bool
|
|
194
|
+
{
|
|
195
|
+
$now = now()->toDateString();
|
|
196
|
+
|
|
197
|
+
if ($this->start_date && $this->start_date->toDateString() > $now) {
|
|
198
|
+
return false; // Not started yet
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if ($this->end_date && $this->end_date->toDateString() < $now) {
|
|
202
|
+
return false; // Expired
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Check if the warranty is expired.
|
|
210
|
+
*/
|
|
211
|
+
public function getIsExpiredAttribute(): bool
|
|
212
|
+
{
|
|
213
|
+
return $this->end_date && $this->end_date->isPast();
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Get the number of days remaining on the warranty.
|
|
218
|
+
*/
|
|
219
|
+
public function getDaysRemainingAttribute(): ?int
|
|
220
|
+
{
|
|
221
|
+
if (!$this->end_date) {
|
|
222
|
+
return null; // Lifetime warranty
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if ($this->is_expired) {
|
|
226
|
+
return 0;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return now()->diffInDays($this->end_date, false);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Get a summary of the coverage.
|
|
234
|
+
*/
|
|
235
|
+
public function getCoverageSummaryAttribute(): array
|
|
236
|
+
{
|
|
237
|
+
$coverage = $this->coverage ?? [];
|
|
238
|
+
|
|
239
|
+
return [
|
|
240
|
+
'parts' => $coverage['parts'] ?? false,
|
|
241
|
+
'labor' => $coverage['labor'] ?? false,
|
|
242
|
+
'roadside' => $coverage['roadside'] ?? false,
|
|
243
|
+
'towing' => $coverage['towing'] ?? false,
|
|
244
|
+
'rental' => $coverage['rental'] ?? false,
|
|
245
|
+
'limits' => $coverage['limits'] ?? null,
|
|
246
|
+
'deductible' => $coverage['deductible'] ?? null,
|
|
247
|
+
];
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Get the warranty status.
|
|
252
|
+
*/
|
|
253
|
+
public function getStatusAttribute(): string
|
|
254
|
+
{
|
|
255
|
+
if (!$this->start_date) {
|
|
256
|
+
return 'pending';
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if ($this->start_date->isFuture()) {
|
|
260
|
+
return 'not_started';
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if ($this->is_expired) {
|
|
264
|
+
return 'expired';
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if ($this->days_remaining && $this->days_remaining <= 30) {
|
|
268
|
+
return 'expiring_soon';
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return 'active';
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Scope to get active warranties.
|
|
276
|
+
*
|
|
277
|
+
* @param \Illuminate\Database\Eloquent\Builder $query
|
|
278
|
+
*
|
|
279
|
+
* @return \Illuminate\Database\Eloquent\Builder
|
|
280
|
+
*/
|
|
281
|
+
public function scopeActive($query)
|
|
282
|
+
{
|
|
283
|
+
return $query->where(function ($q) {
|
|
284
|
+
$q->whereNull('start_date')
|
|
285
|
+
->orWhere('start_date', '<=', now());
|
|
286
|
+
})->where(function ($q) {
|
|
287
|
+
$q->whereNull('end_date')
|
|
288
|
+
->orWhere('end_date', '>=', now());
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Scope to get expired warranties.
|
|
294
|
+
*
|
|
295
|
+
* @param \Illuminate\Database\Eloquent\Builder $query
|
|
296
|
+
*
|
|
297
|
+
* @return \Illuminate\Database\Eloquent\Builder
|
|
298
|
+
*/
|
|
299
|
+
public function scopeExpired($query)
|
|
300
|
+
{
|
|
301
|
+
return $query->whereNotNull('end_date')
|
|
302
|
+
->where('end_date', '<', now());
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Scope to get warranties expiring soon.
|
|
307
|
+
*
|
|
308
|
+
* @param \Illuminate\Database\Eloquent\Builder $query
|
|
309
|
+
*
|
|
310
|
+
* @return \Illuminate\Database\Eloquent\Builder
|
|
311
|
+
*/
|
|
312
|
+
public function scopeExpiringSoon($query, int $days = 30)
|
|
313
|
+
{
|
|
314
|
+
return $query->whereNotNull('end_date')
|
|
315
|
+
->whereBetween('end_date', [now(), now()->addDays($days)]);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Check if a specific coverage type is included.
|
|
320
|
+
*/
|
|
321
|
+
public function hasCoverage(string $coverageType): bool
|
|
322
|
+
{
|
|
323
|
+
$coverage = $this->coverage ?? [];
|
|
324
|
+
|
|
325
|
+
return $coverage[$coverageType] ?? false;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Get the coverage limit for a specific type.
|
|
330
|
+
*/
|
|
331
|
+
public function getCoverageLimit(string $coverageType)
|
|
332
|
+
{
|
|
333
|
+
$coverage = $this->coverage ?? [];
|
|
334
|
+
$limits = $coverage['limits'] ?? [];
|
|
335
|
+
|
|
336
|
+
return $limits[$coverageType] ?? null;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Check if the warranty covers a specific repair cost.
|
|
341
|
+
*/
|
|
342
|
+
public function coversAmount(string $coverageType, float $cost): bool
|
|
343
|
+
{
|
|
344
|
+
if (!$this->hasCoverage($coverageType)) {
|
|
345
|
+
return false;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
$limit = $this->getCoverageLimit($coverageType);
|
|
349
|
+
if ($limit && $cost > $limit) {
|
|
350
|
+
return false;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return true;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Get the deductible amount for a coverage type.
|
|
358
|
+
*/
|
|
359
|
+
public function getDeductible(string $coverageType): float
|
|
360
|
+
{
|
|
361
|
+
$coverage = $this->coverage ?? [];
|
|
362
|
+
$deductibles = $coverage['deductible'] ?? [];
|
|
363
|
+
|
|
364
|
+
if (is_array($deductibles)) {
|
|
365
|
+
return $deductibles[$coverageType] ?? 0;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
return $deductibles ?? 0;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Check if the warranty is transferable.
|
|
373
|
+
*/
|
|
374
|
+
public function isTransferable(): bool
|
|
375
|
+
{
|
|
376
|
+
$terms = $this->terms ?? [];
|
|
377
|
+
|
|
378
|
+
return $terms['transferable'] ?? false;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Transfer the warranty to a new subject.
|
|
383
|
+
*/
|
|
384
|
+
public function transferTo(Model $newSubject, array $transferData = []): bool
|
|
385
|
+
{
|
|
386
|
+
if (!$this->isTransferable()) {
|
|
387
|
+
return false;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
$oldSubjectType = $this->subject_type;
|
|
391
|
+
$oldSubjectUuid = $this->subject_uuid;
|
|
392
|
+
|
|
393
|
+
$updated = $this->update([
|
|
394
|
+
'subject_type' => get_class($newSubject),
|
|
395
|
+
'subject_uuid' => $newSubject->uuid,
|
|
396
|
+
]);
|
|
397
|
+
|
|
398
|
+
if ($updated) {
|
|
399
|
+
activity('warranty_transferred')
|
|
400
|
+
->performedOn($this)
|
|
401
|
+
->withProperties([
|
|
402
|
+
'from_subject_type' => $oldSubjectType,
|
|
403
|
+
'from_subject_uuid' => $oldSubjectUuid,
|
|
404
|
+
'to_subject_type' => get_class($newSubject),
|
|
405
|
+
'to_subject_uuid' => $newSubject->uuid,
|
|
406
|
+
'transfer_data' => $transferData,
|
|
407
|
+
])
|
|
408
|
+
->log('Warranty transferred');
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
return $updated;
|
|
412
|
+
}
|
|
413
|
+
}
|