@fleetbase/fleetops-engine 0.6.34 → 0.6.36
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/avatar-manager.hbs +86 -0
- package/addon/components/avatar-manager.js +165 -0
- package/addon/components/customer/create-order-form.js +5 -0
- package/addon/components/layout/fleet-ops-sidebar.js +8 -0
- package/addon/components/order-progress-card.js +1 -1
- package/addon/controllers/analytics/reports/index/edit.js +2 -0
- package/addon/controllers/analytics/reports/index/new.js +2 -0
- package/addon/controllers/connectivity/devices/index/edit.js +2 -0
- package/addon/controllers/connectivity/devices/index/new.js +2 -0
- package/addon/controllers/connectivity/sensors/index/edit.js +2 -0
- package/addon/controllers/connectivity/sensors/index/new.js +2 -0
- package/addon/controllers/connectivity/telematics/index/edit.js +2 -0
- package/addon/controllers/connectivity/telematics/index/new.js +2 -0
- package/addon/controllers/management/contacts/customers/edit.js +2 -0
- package/addon/controllers/management/contacts/customers/new.js +2 -0
- package/addon/controllers/management/contacts/index/edit.js +2 -0
- package/addon/controllers/management/contacts/index/new.js +2 -0
- package/addon/controllers/management/drivers/index/edit.js +2 -0
- package/addon/controllers/management/drivers/index/new.js +2 -0
- package/addon/controllers/management/fleets/index/edit.js +2 -0
- package/addon/controllers/management/fleets/index/new.js +2 -0
- package/addon/controllers/management/fuel-reports/index/edit.js +2 -0
- package/addon/controllers/management/fuel-reports/index/new.js +2 -0
- package/addon/controllers/management/issues/index/edit.js +2 -0
- package/addon/controllers/management/issues/index/new.js +2 -0
- package/addon/controllers/management/places/index/edit.js +2 -0
- package/addon/controllers/management/places/index/new.js +2 -0
- package/addon/controllers/management/vehicles/index/edit.js +2 -0
- package/addon/controllers/management/vehicles/index/new.js +2 -0
- package/addon/controllers/management/vendors/index/edit.js +2 -0
- package/addon/controllers/management/vendors/index/new.js +2 -0
- package/addon/controllers/operations/orders/index/new.js +2 -0
- package/addon/controllers/operations/routes/index/new.js +1 -0
- package/addon/controllers/operations/service-rates/index/edit.js +2 -0
- package/addon/controllers/operations/service-rates/index/new.js +2 -0
- package/addon/controllers/settings/avatars.js +3 -0
- package/addon/extension.js +0 -5
- package/addon/routes/settings/avatars.js +3 -0
- package/addon/routes.js +1 -0
- package/addon/templates/operations/orders/index/new.hbs +1 -0
- package/addon/templates/settings/avatars.hbs +10 -0
- package/app/components/avatar-manager.js +1 -0
- package/app/controllers/settings/avatars.js +1 -0
- package/app/routes/settings/avatars.js +1 -0
- package/app/templates/settings/avatars.js +1 -0
- package/composer.json +1 -1
- package/extension.json +1 -1
- package/package.json +3 -3
- package/server/config/fleetops.php +1 -1
- package/server/src/Auth/Schemas/FleetOps.php +4 -0
- package/server/src/Expansions/UserFilterExpansion.php +31 -0
- package/server/src/Http/Controllers/Api/v1/OrderController.php +8 -11
- package/server/src/Http/Controllers/Internal/v1/ContactController.php +5 -2
- package/server/src/Http/Controllers/Internal/v1/DriverController.php +13 -2
- package/server/src/Http/Controllers/Internal/v1/FleetController.php +5 -2
- package/server/src/Http/Controllers/Internal/v1/FuelReportController.php +5 -2
- package/server/src/Http/Controllers/Internal/v1/IssueController.php +5 -2
- package/server/src/Http/Controllers/Internal/v1/PlaceController.php +5 -2
- package/server/src/Http/Controllers/Internal/v1/VehicleController.php +8 -3
- package/server/src/Http/Controllers/Internal/v1/VendorController.php +5 -2
- package/server/src/Imports/ContactImport.php +6 -0
- package/server/src/Imports/DriverImport.php +6 -0
- package/server/src/Imports/FleetImport.php +6 -0
- package/server/src/Imports/FuelReportImport.php +6 -0
- package/server/src/Imports/IssueImport.php +6 -0
- package/server/src/Imports/PlaceImport.php +6 -0
- package/server/src/Imports/VehicleImport.php +6 -0
- package/server/src/Imports/VendorImport.php +6 -0
- package/server/src/Models/Vehicle.php +9 -2
- package/server/src/Support/Reporting/FleetOpsReportSchema.php +129 -1
- package/translations/en-us.yaml +2 -0
- package/DRIVER_SCHEDULING.md +0 -186
|
@@ -9,6 +9,11 @@ use Maatwebsite\Excel\Concerns\WithHeadingRow;
|
|
|
9
9
|
|
|
10
10
|
class IssueImport implements ToCollection, WithHeadingRow
|
|
11
11
|
{
|
|
12
|
+
/**
|
|
13
|
+
* Counter for successfully imported rows.
|
|
14
|
+
*/
|
|
15
|
+
public int $imported = 0;
|
|
16
|
+
|
|
12
17
|
/**
|
|
13
18
|
* @return Collection
|
|
14
19
|
*/
|
|
@@ -20,6 +25,7 @@ class IssueImport implements ToCollection, WithHeadingRow
|
|
|
20
25
|
}
|
|
21
26
|
|
|
22
27
|
Issue::createFromImport($row, true);
|
|
28
|
+
$this->imported++;
|
|
23
29
|
}
|
|
24
30
|
}
|
|
25
31
|
}
|
|
@@ -9,6 +9,11 @@ use Maatwebsite\Excel\Concerns\WithHeadingRow;
|
|
|
9
9
|
|
|
10
10
|
class PlaceImport implements ToCollection, WithHeadingRow
|
|
11
11
|
{
|
|
12
|
+
/**
|
|
13
|
+
* Counter for successfully imported rows.
|
|
14
|
+
*/
|
|
15
|
+
public int $imported = 0;
|
|
16
|
+
|
|
12
17
|
/**
|
|
13
18
|
* @return Collection
|
|
14
19
|
*/
|
|
@@ -20,6 +25,7 @@ class PlaceImport implements ToCollection, WithHeadingRow
|
|
|
20
25
|
}
|
|
21
26
|
|
|
22
27
|
Place::createFromImport($row, true);
|
|
28
|
+
$this->imported++;
|
|
23
29
|
}
|
|
24
30
|
}
|
|
25
31
|
}
|
|
@@ -9,6 +9,11 @@ use Maatwebsite\Excel\Concerns\WithHeadingRow;
|
|
|
9
9
|
|
|
10
10
|
class VehicleImport implements ToCollection, WithHeadingRow
|
|
11
11
|
{
|
|
12
|
+
/**
|
|
13
|
+
* Counter for successfully imported rows.
|
|
14
|
+
*/
|
|
15
|
+
public int $imported = 0;
|
|
16
|
+
|
|
12
17
|
/**
|
|
13
18
|
* @return Collection
|
|
14
19
|
*/
|
|
@@ -20,6 +25,7 @@ class VehicleImport implements ToCollection, WithHeadingRow
|
|
|
20
25
|
}
|
|
21
26
|
|
|
22
27
|
Vehicle::createFromImport($row, true);
|
|
28
|
+
$this->imported++;
|
|
23
29
|
}
|
|
24
30
|
}
|
|
25
31
|
}
|
|
@@ -9,6 +9,11 @@ use Maatwebsite\Excel\Concerns\WithHeadingRow;
|
|
|
9
9
|
|
|
10
10
|
class VendorImport implements ToCollection, WithHeadingRow
|
|
11
11
|
{
|
|
12
|
+
/**
|
|
13
|
+
* Counter for successfully imported rows.
|
|
14
|
+
*/
|
|
15
|
+
public int $imported = 0;
|
|
16
|
+
|
|
12
17
|
/**
|
|
13
18
|
* @return Collection
|
|
14
19
|
*/
|
|
@@ -20,6 +25,7 @@ class VendorImport implements ToCollection, WithHeadingRow
|
|
|
20
25
|
}
|
|
21
26
|
|
|
22
27
|
Vendor::createFromImport($row, true);
|
|
28
|
+
$this->imported++;
|
|
23
29
|
}
|
|
24
30
|
}
|
|
25
31
|
}
|
|
@@ -507,7 +507,7 @@ class Vehicle extends Model
|
|
|
507
507
|
*
|
|
508
508
|
* @return \Illuminate\Support\Collection
|
|
509
509
|
*/
|
|
510
|
-
public static function getAvatarOptions()
|
|
510
|
+
public static function getAvatarOptions(?callable $customQueryCallback = null)
|
|
511
511
|
{
|
|
512
512
|
$options = [
|
|
513
513
|
'2_door_truck.svg',
|
|
@@ -540,8 +540,15 @@ class Vehicle extends Model
|
|
|
540
540
|
'taxi.svg',
|
|
541
541
|
];
|
|
542
542
|
|
|
543
|
+
// Query for custom avatars
|
|
544
|
+
$customAvatarsQuery = File::where('type', 'vehicle-avatar');
|
|
545
|
+
if (is_callable($customQueryCallback)) {
|
|
546
|
+
$customQueryCallback($customAvatarsQuery);
|
|
547
|
+
}
|
|
548
|
+
$customAvatars = $customAvatarsQuery->get();
|
|
549
|
+
|
|
543
550
|
// Get custom avatars
|
|
544
|
-
$customAvatars = collect(
|
|
551
|
+
$customAvatars = collect($customAvatars->mapWithKeys(
|
|
545
552
|
function ($file) {
|
|
546
553
|
$key = str_replace(['.svg', '.png'], '', 'Custom: ' . $file->original_filename);
|
|
547
554
|
|
|
@@ -47,7 +47,7 @@ class FleetOpsReportSchema implements ReportSchema
|
|
|
47
47
|
->description('Delivery and service orders')
|
|
48
48
|
->category('Operations')
|
|
49
49
|
->extension('fleet-ops')
|
|
50
|
-
->excludeColumns(['uuid', 'deleted_at'
|
|
50
|
+
->excludeColumns(['uuid', 'deleted_at']) // Hide foreign keys and system columns
|
|
51
51
|
->maxRows(50000)
|
|
52
52
|
->cacheTtl(3600)
|
|
53
53
|
->columns([
|
|
@@ -157,6 +157,12 @@ class FleetOpsReportSchema implements ReportSchema
|
|
|
157
157
|
->description('When the order was last updated')
|
|
158
158
|
->filterable()
|
|
159
159
|
->sortable(),
|
|
160
|
+
|
|
161
|
+
Column::make('meta', 'json')
|
|
162
|
+
->label('Metadata')
|
|
163
|
+
->description('Order metadata and custom fields')
|
|
164
|
+
->searchable()
|
|
165
|
+
->filterable(),
|
|
160
166
|
])
|
|
161
167
|
->computedColumns([
|
|
162
168
|
Column::count('total_orders', 'id')
|
|
@@ -178,6 +184,18 @@ class FleetOpsReportSchema implements ReportSchema
|
|
|
178
184
|
Column::avg('average_time', 'time')
|
|
179
185
|
->label('Average Time')
|
|
180
186
|
->description('Average duration per order'),
|
|
187
|
+
|
|
188
|
+
Column::sum('total_transaction_amount', 'amount')
|
|
189
|
+
->label('Total Transaction Amount')
|
|
190
|
+
->description('Sum of all transaction amounts'),
|
|
191
|
+
|
|
192
|
+
Column::avg('average_transaction_amount', 'amount')
|
|
193
|
+
->label('Average Transaction Amount')
|
|
194
|
+
->description('Average transaction amount per order'),
|
|
195
|
+
|
|
196
|
+
Column::count('orders_with_transactions', 'transaction_uuid')
|
|
197
|
+
->label('Orders with Transactions')
|
|
198
|
+
->description('Count of orders that have transactions'),
|
|
181
199
|
])
|
|
182
200
|
->relationships([
|
|
183
201
|
// Auto-join relationships for seamless access
|
|
@@ -272,6 +290,116 @@ class FleetOpsReportSchema implements ReportSchema
|
|
|
272
290
|
Column::make('phone', 'string')->label('Phone'),
|
|
273
291
|
Column::make('type', 'string')->label('Type'),
|
|
274
292
|
]),
|
|
293
|
+
|
|
294
|
+
Relationship::hasAutoJoin('transaction', 'transactions')
|
|
295
|
+
->label('Transaction')
|
|
296
|
+
->localKey('transaction_uuid')
|
|
297
|
+
->foreignKey('uuid')
|
|
298
|
+
->columns([
|
|
299
|
+
Column::make('public_id', 'string')
|
|
300
|
+
->label('Transaction ID')
|
|
301
|
+
->description('Public transaction identifier')
|
|
302
|
+
->searchable()
|
|
303
|
+
->filterable()
|
|
304
|
+
->sortable(),
|
|
305
|
+
|
|
306
|
+
Column::make('gateway_transaction_id', 'string')
|
|
307
|
+
->label('Gateway Transaction ID')
|
|
308
|
+
->description('Transaction ID from payment gateway')
|
|
309
|
+
->searchable()
|
|
310
|
+
->filterable()
|
|
311
|
+
->sortable(),
|
|
312
|
+
|
|
313
|
+
Column::make('gateway', 'string')
|
|
314
|
+
->label('Payment Gateway')
|
|
315
|
+
->description('Payment gateway used for transaction')
|
|
316
|
+
->filterable()
|
|
317
|
+
->aggregatable(),
|
|
318
|
+
|
|
319
|
+
Column::make('amount', 'integer')
|
|
320
|
+
->label('Amount')
|
|
321
|
+
->description('Transaction amount (in cents)')
|
|
322
|
+
->aggregatable()
|
|
323
|
+
->sortable()
|
|
324
|
+
->transformer(function ($value) {
|
|
325
|
+
// Convert cents to dollars with 2 decimal places
|
|
326
|
+
return number_format($value / 100, 2);
|
|
327
|
+
}),
|
|
328
|
+
|
|
329
|
+
Column::make('currency', 'string')
|
|
330
|
+
->label('Currency')
|
|
331
|
+
->description('Transaction currency code')
|
|
332
|
+
->filterable()
|
|
333
|
+
->aggregatable(),
|
|
334
|
+
|
|
335
|
+
Column::make('description', 'string')
|
|
336
|
+
->label('Description')
|
|
337
|
+
->description('Transaction description')
|
|
338
|
+
->searchable()
|
|
339
|
+
->filterable(),
|
|
340
|
+
|
|
341
|
+
Column::make('type', 'string')
|
|
342
|
+
->label('Transaction Type')
|
|
343
|
+
->description('Type of transaction')
|
|
344
|
+
->filterable()
|
|
345
|
+
->aggregatable(),
|
|
346
|
+
|
|
347
|
+
Column::make('status', 'string')
|
|
348
|
+
->label('Transaction Status')
|
|
349
|
+
->description('Current transaction status')
|
|
350
|
+
->filterable()
|
|
351
|
+
->aggregatable()
|
|
352
|
+
->transformer(function ($value) {
|
|
353
|
+
$labels = [
|
|
354
|
+
'pending' => 'Pending',
|
|
355
|
+
'completed' => 'Completed',
|
|
356
|
+
'failed' => 'Failed',
|
|
357
|
+
'refunded' => 'Refunded',
|
|
358
|
+
'canceled' => 'Canceled',
|
|
359
|
+
];
|
|
360
|
+
|
|
361
|
+
return $labels[$value] ?? ucfirst($value);
|
|
362
|
+
}),
|
|
363
|
+
|
|
364
|
+
Column::make('created_at', 'datetime')
|
|
365
|
+
->label('Transaction Date')
|
|
366
|
+
->description('When the transaction was created')
|
|
367
|
+
->filterable()
|
|
368
|
+
->sortable()
|
|
369
|
+
->aggregatable(),
|
|
370
|
+
])
|
|
371
|
+
->with([
|
|
372
|
+
// Nested relationship for transaction items
|
|
373
|
+
Relationship::hasAutoJoin('items', 'transaction_items')
|
|
374
|
+
->label('Transaction Items')
|
|
375
|
+
->localKey('uuid')
|
|
376
|
+
->foreignKey('transaction_uuid')
|
|
377
|
+
->columns([
|
|
378
|
+
Column::make('amount', 'string')
|
|
379
|
+
->label('Item Amount')
|
|
380
|
+
->description('Line item amount')
|
|
381
|
+
->aggregatable()
|
|
382
|
+
->sortable(),
|
|
383
|
+
|
|
384
|
+
Column::make('currency', 'string')
|
|
385
|
+
->label('Item Currency')
|
|
386
|
+
->description('Line item currency code')
|
|
387
|
+
->filterable(),
|
|
388
|
+
|
|
389
|
+
Column::make('details', 'string')
|
|
390
|
+
->label('Item Details')
|
|
391
|
+
->description('Detailed description of the line item')
|
|
392
|
+
->searchable()
|
|
393
|
+
->filterable(),
|
|
394
|
+
|
|
395
|
+
Column::make('code', 'string')
|
|
396
|
+
->label('Item Code')
|
|
397
|
+
->description('Item or SKU code')
|
|
398
|
+
->searchable()
|
|
399
|
+
->filterable()
|
|
400
|
+
->sortable(),
|
|
401
|
+
]),
|
|
402
|
+
]),
|
|
275
403
|
]);
|
|
276
404
|
}
|
|
277
405
|
|
package/translations/en-us.yaml
CHANGED
|
@@ -77,6 +77,7 @@ menu:
|
|
|
77
77
|
routing: Routing
|
|
78
78
|
custom-fields: Custom Fields
|
|
79
79
|
order-board: Order Board
|
|
80
|
+
avatars: Avatars
|
|
80
81
|
|
|
81
82
|
resource:
|
|
82
83
|
asset: Asset
|
|
@@ -1680,6 +1681,7 @@ route-list:
|
|
|
1680
1681
|
more-waypoints: more waypoints
|
|
1681
1682
|
|
|
1682
1683
|
settings:
|
|
1684
|
+
avatar-management: Avatar Management
|
|
1683
1685
|
custom-fields: Custom Fields
|
|
1684
1686
|
notifications:
|
|
1685
1687
|
fleet-ops-notification-settings: Fleet-Ops Notification Settings
|
package/DRIVER_SCHEDULING.md
DELETED
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
# FleetOps Driver Scheduling Module
|
|
2
|
-
|
|
3
|
-
This module implements driver scheduling with Hours of Service (HOS) compliance for FleetOps.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- **Fleet-Wide Scheduler**: Manage all drivers' schedules in a single calendar view
|
|
8
|
-
- **Driver Schedule Management**: Create, edit, and manage driver shifts
|
|
9
|
-
- **HOS Compliance**: Real-time validation against FMCSA regulations
|
|
10
|
-
- **Calendar View**: Visual schedule management with drag-and-drop
|
|
11
|
-
- **Resource Timeline**: View multiple drivers' schedules simultaneously
|
|
12
|
-
- **Individual Driver Schedules**: Dedicated schedule view on driver detail pages
|
|
13
|
-
- **Availability Management**: Track driver availability and time-off requests
|
|
14
|
-
- **Conflict Detection**: Automatic detection of scheduling conflicts
|
|
15
|
-
- **Dual View Modes**: Toggle between order scheduling and driver scheduling
|
|
16
|
-
|
|
17
|
-
## Components
|
|
18
|
-
|
|
19
|
-
### Operations/Scheduler (Fleet-Wide View)
|
|
20
|
-
|
|
21
|
-
The main scheduler view at `operations/scheduler` now supports both order scheduling and driver scheduling.
|
|
22
|
-
|
|
23
|
-
**Location**: `addon/controllers/operations/scheduler/index.js`
|
|
24
|
-
|
|
25
|
-
**Features**:
|
|
26
|
-
- **View Mode Toggle**: Switch between "Orders" and "Driver Schedules" modes
|
|
27
|
-
- **Resource Timeline**: In driver mode, shows all drivers as resources with their shifts
|
|
28
|
-
- **Drag-and-Drop**: Drag shifts between drivers or reschedule by dragging
|
|
29
|
-
- **Add Shift**: Quick action button to create new driver shifts
|
|
30
|
-
- **Real-Time Updates**: Calendar updates automatically when shifts are modified
|
|
31
|
-
- **Status Colors**: Visual indicators for shift status (pending, confirmed, etc.)
|
|
32
|
-
|
|
33
|
-
**View Modes**:
|
|
34
|
-
1. **Orders Mode** (default):
|
|
35
|
-
- Month calendar view
|
|
36
|
-
- Drag unscheduled orders to calendar
|
|
37
|
-
- Manage order scheduling
|
|
38
|
-
|
|
39
|
-
2. **Driver Schedules Mode**:
|
|
40
|
-
- Resource timeline view (week view with drivers as resources)
|
|
41
|
-
- View all drivers' shifts simultaneously
|
|
42
|
-
- Drag shifts between drivers
|
|
43
|
-
- Reschedule shifts by dragging
|
|
44
|
-
- Click shifts to view/edit details
|
|
45
|
-
|
|
46
|
-
**Usage**:
|
|
47
|
-
Navigate to Operations → Scheduler, then toggle between "Orders" and "Driver Schedules" using the header buttons.
|
|
48
|
-
|
|
49
|
-
### Driver::Schedule
|
|
50
|
-
|
|
51
|
-
Displays and manages a driver's schedule from their detail page.
|
|
52
|
-
|
|
53
|
-
**Location**: `addon/components/driver/schedule.js`
|
|
54
|
-
|
|
55
|
-
**Features**:
|
|
56
|
-
- HOS compliance dashboard with visual indicators
|
|
57
|
-
- Weekly calendar view of driver shifts
|
|
58
|
-
- Upcoming shifts list (next 5 shifts)
|
|
59
|
-
- Availability and time-off management
|
|
60
|
-
- Quick actions for adding shifts and requesting time off
|
|
61
|
-
|
|
62
|
-
**Usage**:
|
|
63
|
-
```handlebars
|
|
64
|
-
<Driver::Schedule @driver={{@model}} />
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
**Integration**: Add a "Schedule" tab to the driver detail page.
|
|
68
|
-
|
|
69
|
-
## Backend Components
|
|
70
|
-
|
|
71
|
-
### HOSConstraint
|
|
72
|
-
|
|
73
|
-
Validates schedule items against FMCSA Hours of Service regulations.
|
|
74
|
-
|
|
75
|
-
**Location**: `server/src/Constraints/HOSConstraint.php`
|
|
76
|
-
|
|
77
|
-
**Regulations Enforced**:
|
|
78
|
-
1. **11-Hour Driving Limit**: Maximum 11 hours driving after 10 consecutive hours off duty
|
|
79
|
-
2. **14-Hour Duty Window**: Cannot drive beyond 14th hour after coming on duty
|
|
80
|
-
3. **60/70-Hour Weekly Limit**: Cannot drive after 60/70 hours in 7/8 consecutive days
|
|
81
|
-
4. **30-Minute Break**: Required after 8 cumulative hours of driving
|
|
82
|
-
|
|
83
|
-
**Violation Severity**:
|
|
84
|
-
- `critical`: Immediate compliance issue, shift cannot be scheduled
|
|
85
|
-
- `warning`: Approaching limit, requires attention
|
|
86
|
-
|
|
87
|
-
**Registration**:
|
|
88
|
-
```php
|
|
89
|
-
// In FleetOps ServiceProvider boot() method
|
|
90
|
-
$constraintService = app(\Fleetbase\Services\Scheduling\ConstraintService::class);
|
|
91
|
-
$constraintService->register('driver', \Fleetbase\FleetOps\Constraints\HOSConstraint::class);
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
## HOS Compliance Dashboard
|
|
95
|
-
|
|
96
|
-
The HOS dashboard displays:
|
|
97
|
-
- **Daily Driving Hours**: X/11 hours with circular progress indicator
|
|
98
|
-
- **Weekly Hours**: X/70 hours with circular progress indicator
|
|
99
|
-
- **Compliance Status**: Badge indicating compliance level
|
|
100
|
-
- Green: Compliant
|
|
101
|
-
- Yellow: Approaching Limit
|
|
102
|
-
- Red: At Limit
|
|
103
|
-
|
|
104
|
-
## API Endpoints
|
|
105
|
-
|
|
106
|
-
FleetOps extends the core scheduling endpoints with driver-specific functionality:
|
|
107
|
-
|
|
108
|
-
- `GET /drivers/{id}/hos-status` - Get HOS compliance status for a driver
|
|
109
|
-
- `GET /drivers/{id}/schedule` - Get schedule items for a driver
|
|
110
|
-
- `POST /drivers/{id}/schedule` - Create a new shift for a driver
|
|
111
|
-
- `PUT /schedule-items/{id}` - Update a shift (with HOS validation)
|
|
112
|
-
- `DELETE /schedule-items/{id}` - Delete a shift
|
|
113
|
-
|
|
114
|
-
## Workflow
|
|
115
|
-
|
|
116
|
-
### Creating a Driver Shift
|
|
117
|
-
|
|
118
|
-
1. User clicks "Add Shift" button
|
|
119
|
-
2. Modal opens with shift form
|
|
120
|
-
3. User selects date, time, vehicle, and other details
|
|
121
|
-
4. System validates against HOS constraints
|
|
122
|
-
5. If violations found, display warnings/errors
|
|
123
|
-
6. If valid, create schedule item
|
|
124
|
-
7. Update driver schedule view and HOS dashboard
|
|
125
|
-
|
|
126
|
-
### HOS Validation
|
|
127
|
-
|
|
128
|
-
1. When a schedule item is created/updated
|
|
129
|
-
2. `HOSConstraint::validate()` is called
|
|
130
|
-
3. Checks all four HOS regulations
|
|
131
|
-
4. Returns violations array if any
|
|
132
|
-
5. Frontend displays violations to user
|
|
133
|
-
6. User can adjust shift or override (with proper permissions)
|
|
134
|
-
|
|
135
|
-
## Integration with Core Scheduling
|
|
136
|
-
|
|
137
|
-
FleetOps uses the core scheduling module with driver-specific customizations:
|
|
138
|
-
|
|
139
|
-
**Core Components Used**:
|
|
140
|
-
- `Schedule` model (subject_type: 'fleet', subject_uuid: fleet.id)
|
|
141
|
-
- `ScheduleItem` model (assignee_type: 'driver', assignee_uuid: driver.id)
|
|
142
|
-
- `ScheduleAvailability` model (subject_type: 'driver')
|
|
143
|
-
- `ScheduleConstraint` model (subject_type: 'driver')
|
|
144
|
-
|
|
145
|
-
**FleetOps Extensions**:
|
|
146
|
-
- `HOSConstraint` for compliance validation
|
|
147
|
-
- `Driver::Schedule` component for driver-specific UI
|
|
148
|
-
- HOS status API endpoint
|
|
149
|
-
- Driver-specific scheduling logic
|
|
150
|
-
|
|
151
|
-
## Future Enhancements
|
|
152
|
-
|
|
153
|
-
- **Automatic Schedule Generation**: AI-powered schedule optimization
|
|
154
|
-
- **ELD Integration**: Sync with Electronic Logging Devices
|
|
155
|
-
- **Predictive HOS**: Forecast HOS availability for future dates
|
|
156
|
-
- **Mobile App**: Driver-facing mobile app for schedule viewing
|
|
157
|
-
- **Notifications**: Real-time alerts for schedule changes and HOS warnings
|
|
158
|
-
- **Reporting**: HOS compliance reports and analytics
|
|
159
|
-
|
|
160
|
-
## Testing
|
|
161
|
-
|
|
162
|
-
### HOS Constraint Tests
|
|
163
|
-
|
|
164
|
-
Test cases should cover:
|
|
165
|
-
- 11-hour driving limit enforcement
|
|
166
|
-
- 14-hour duty window enforcement
|
|
167
|
-
- 60/70-hour weekly limit enforcement
|
|
168
|
-
- 30-minute break requirement
|
|
169
|
-
- Edge cases (consecutive shifts, split shifts, etc.)
|
|
170
|
-
|
|
171
|
-
### Integration Tests
|
|
172
|
-
|
|
173
|
-
- Create driver shift via API
|
|
174
|
-
- Validate HOS constraints are enforced
|
|
175
|
-
- Update shift and verify re-validation
|
|
176
|
-
- Delete shift and verify HOS recalculation
|
|
177
|
-
- Test driver schedule view rendering
|
|
178
|
-
|
|
179
|
-
## Compliance Notes
|
|
180
|
-
|
|
181
|
-
This implementation follows FMCSA Hours of Service regulations as of 2025. Regulations may vary by:
|
|
182
|
-
- Jurisdiction (US Federal, state-specific, Canada, etc.)
|
|
183
|
-
- Vehicle type (property-carrying vs. passenger-carrying)
|
|
184
|
-
- Industry (short-haul vs. long-haul)
|
|
185
|
-
|
|
186
|
-
**Important**: This is a software implementation and should not be the sole method of HOS compliance. Proper driver training, ELD integration, and regular audits are essential for full compliance.
|