@fleetbase/fleetops-engine 0.6.43 → 0.6.45
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/entity/form.hbs +24 -0
- package/addon/components/entity/form.js +30 -0
- package/addon/components/leaflet-draw-control.js +1 -1
- package/addon/components/map/drawer/geofence-event-listing.hbs +123 -0
- package/addon/components/map/drawer/geofence-event-listing.js +103 -0
- package/addon/components/map/drawer.js +1 -0
- package/addon/components/map/leaflet-live-map.js +83 -0
- package/addon/components/modals/orchestrator-import.js +2 -78
- package/addon/components/order/form/service-rate.hbs +1 -1
- package/addon/components/service-area/form.hbs +59 -0
- package/addon/components/service-rate/details.hbs +6 -6
- package/addon/components/service-rate/form.hbs +28 -15
- package/addon/components/zone/form.hbs +60 -1
- package/addon/controllers/operations/orders/index/details/virtual.js +5 -0
- package/addon/controllers/operations/orders/index/details.js +27 -2
- package/addon/controllers/operations/service-rates/index/edit.js +1 -0
- package/addon/controllers/operations/service-rates/index/new.js +1 -0
- package/addon/helpers/f-to-int.js +6 -0
- package/addon/routes/application.js +3 -3
- package/addon/routes/operations/orders/index/details/virtual.js +1 -0
- package/addon/routes/operations/orders/index/details.js +19 -3
- package/addon/services/equipment-actions.js +4 -6
- package/addon/services/geofence-event-bus.js +223 -0
- package/addon/services/leaflet-map-manager.js +4 -0
- package/addon/services/maintenance-actions.js +4 -6
- package/addon/services/part-actions.js +4 -6
- package/addon/services/service-rate-actions.js +8 -3
- package/addon/templates/operations/orders/index/details/virtual.hbs +7 -1
- package/addon/utils/fleet-ops-options.js +33 -0
- package/addon/utils/serialize-payload.js +1 -1
- package/app/components/map/drawer/geofence-event-listing.js +1 -0
- package/app/controllers/operations/orders/index/details/virtual.js +1 -0
- package/app/helpers/f-to-int.js +1 -0
- package/app/services/geofence-event-bus.js +1 -0
- package/composer.json +1 -1
- package/extension.json +1 -1
- package/package.json +2 -2
- package/server/migrations/2026_04_05_000001_add_geofence_config_to_zones_table.php +48 -0
- package/server/migrations/2026_04_05_000002_add_geofence_config_to_service_areas_table.php +38 -0
- package/server/migrations/2026_04_05_000003_create_driver_geofence_states_table.php +62 -0
- package/server/migrations/2026_04_05_000004_create_geofence_events_log_table.php +66 -0
- package/server/migrations/2026_04_22_000001_add_vehicle_support_to_geofence_events_log.php +31 -0
- package/server/migrations/2026_04_22_000002_create_vehicle_geofence_states_table.php +39 -0
- package/server/src/Console/Commands/SimulateGeofenceEvents.php +278 -0
- package/server/src/Events/GeofenceDwelled.php +208 -0
- package/server/src/Events/GeofenceEntered.php +207 -0
- package/server/src/Events/GeofenceExited.php +213 -0
- package/server/src/Http/Controllers/Api/v1/DriverController.php +100 -0
- package/server/src/Http/Controllers/Api/v1/GeofenceController.php +263 -0
- package/server/src/Http/Controllers/Api/v1/OrderController.php +13 -8
- package/server/src/Http/Controllers/Api/v1/PurchaseRateController.php +11 -3
- package/server/src/Http/Controllers/Api/v1/ServiceAreaController.php +2 -2
- package/server/src/Http/Controllers/Api/v1/ServiceQuoteController.php +4 -0
- package/server/src/Http/Controllers/Api/v1/ServiceRateController.php +6 -1
- package/server/src/Http/Controllers/Api/v1/VehicleController.php +88 -0
- package/server/src/Http/Controllers/Api/v1/ZoneController.php +2 -2
- package/server/src/Http/Controllers/Internal/v1/GeofenceController.php +7 -0
- package/server/src/Http/Requests/CreateServiceAreaRequest.php +8 -4
- package/server/src/Http/Requests/CreateServiceRateRequest.php +2 -2
- package/server/src/Http/Requests/CreateZoneRequest.php +8 -4
- package/server/src/Http/Resources/v1/Order.php +0 -1
- package/server/src/Http/Resources/v1/ServiceQuote.php +2 -2
- package/server/src/Jobs/CheckGeofenceDwell.php +139 -0
- package/server/src/Listeners/HandleGeofenceDwelled.php +56 -0
- package/server/src/Listeners/HandleGeofenceEntered.php +187 -0
- package/server/src/Listeners/HandleGeofenceExited.php +56 -0
- package/server/src/Models/Entity.php +7 -0
- package/server/src/Models/GeofenceEventLog.php +155 -0
- package/server/src/Models/Order.php +39 -7
- package/server/src/Models/ServiceArea.php +21 -2
- package/server/src/Models/ServiceQuote.php +3 -1
- package/server/src/Models/ServiceRate.php +122 -30
- package/server/src/Models/Zone.php +20 -2
- package/server/src/Notifications/DriverArrivedAtGeofence.php +86 -0
- package/server/src/Observers/PurchaseRateObserver.php +3 -5
- package/server/src/Providers/EventServiceProvider.php +19 -0
- package/server/src/Providers/FleetOpsServiceProvider.php +10 -0
- package/server/src/Rules/ComputableAlgo.php +1 -3
- package/server/src/Support/Algo.php +87 -1
- package/server/src/Support/GeofenceIntersectionService.php +206 -0
- package/server/src/Support/Utils.php +35 -0
- package/server/src/routes.php +16 -0
|
@@ -123,6 +123,38 @@ export const contactTypes = [
|
|
|
123
123
|
{ label: 'Dispatcher', value: 'dispatcher', description: 'Scheduling and operations contact' },
|
|
124
124
|
];
|
|
125
125
|
|
|
126
|
+
export const entityTypes = [
|
|
127
|
+
{ label: 'Parcel', value: 'parcel', description: 'Standard parcel or package used by parcel-based pricing.' },
|
|
128
|
+
{ label: 'Package', value: 'package', description: 'Generic package or boxed item.' },
|
|
129
|
+
{ label: 'Product', value: 'product', description: 'Sellable product or catalog item.' },
|
|
130
|
+
{ label: 'Item', value: 'item', description: 'Generic inventory item when no stronger type applies.' },
|
|
131
|
+
{ label: 'SKU / Inventory Unit', value: 'sku', description: 'Stock keeping unit or tracked inventory piece.' },
|
|
132
|
+
{ label: 'Document', value: 'document', description: 'Envelopes, paperwork, and lightweight documents.' },
|
|
133
|
+
{ label: 'Envelope', value: 'envelope', description: 'Flat document mailer or envelope.' },
|
|
134
|
+
{ label: 'Box', value: 'box', description: 'Single boxed shipment unit.' },
|
|
135
|
+
{ label: 'Carton', value: 'carton', description: 'Single carton, box, or case.' },
|
|
136
|
+
{ label: 'Case', value: 'case', description: 'Case-packed goods or packaged case.' },
|
|
137
|
+
{ label: 'Bundle', value: 'bundle', description: 'Bundled or strapped items shipped together.' },
|
|
138
|
+
{ label: 'Bag', value: 'bag', description: 'Bagged goods, sacks, or pouches.' },
|
|
139
|
+
{ label: 'Tote', value: 'tote', description: 'Reusable tote, bin, or container.' },
|
|
140
|
+
{ label: 'Crate', value: 'crate', description: 'Rigid crate or caged shipment unit.' },
|
|
141
|
+
{ label: 'Pallet', value: 'pallet', description: 'Palletized freight or grouped cargo.' },
|
|
142
|
+
{ label: 'Container', value: 'container', description: 'Containerized shipment or storage container.' },
|
|
143
|
+
{ label: 'Freight', value: 'freight', description: 'Loose freight or larger shipment unit.' },
|
|
144
|
+
{ label: 'Cargo', value: 'cargo', description: 'General cargo not classified more specifically.' },
|
|
145
|
+
{ label: 'Equipment', value: 'equipment', description: 'Tools, machines, or operational equipment.' },
|
|
146
|
+
{ label: 'Machinery', value: 'machinery', description: 'Industrial machinery or large mechanical unit.' },
|
|
147
|
+
{ label: 'Asset', value: 'asset', description: 'Tracked business asset or returnable item.' },
|
|
148
|
+
{ label: 'Return', value: 'return', description: 'Returned goods or reverse-logistics item.' },
|
|
149
|
+
{ label: 'Sample', value: 'sample', description: 'Sample item for trial, demo, or inspection.' },
|
|
150
|
+
{ label: 'Spare Part', value: 'spare_part', description: 'Replacement component or service part.' },
|
|
151
|
+
{ label: 'Medical Supply', value: 'medical_supply', description: 'Healthcare, lab, or medical delivery item.' },
|
|
152
|
+
{ label: 'Food', value: 'food', description: 'Prepared food, meal, or grocery item.' },
|
|
153
|
+
{ label: 'Beverage', value: 'beverage', description: 'Drink, liquid refreshment, or bottled shipment.' },
|
|
154
|
+
{ label: 'Retail Goods', value: 'retail_goods', description: 'General consumer or retail merchandise.' },
|
|
155
|
+
{ label: 'Passenger', value: 'passenger', description: 'Person transported as part of the order payload.' },
|
|
156
|
+
];
|
|
157
|
+
|
|
126
158
|
export const contactStatuses = [
|
|
127
159
|
{ label: 'Active', value: 'active', description: 'Contact is valid and in use' },
|
|
128
160
|
{ label: 'Inactive', value: 'inactive', description: 'Contact is no longer valid' },
|
|
@@ -821,6 +853,7 @@ export default function fleetOpsOptions(key) {
|
|
|
821
853
|
fleetTypes,
|
|
822
854
|
fleetStatuses,
|
|
823
855
|
contactTypes,
|
|
856
|
+
entityTypes,
|
|
824
857
|
contactStatuses,
|
|
825
858
|
fuelReportTypes,
|
|
826
859
|
fuelReportStatuses,
|
|
@@ -5,7 +5,7 @@ export default function serializePayload(payload) {
|
|
|
5
5
|
const serialized = {
|
|
6
6
|
pickup: serializeModel(payload.pickup),
|
|
7
7
|
dropoff: serializeModel(payload.dropoff),
|
|
8
|
-
|
|
8
|
+
entities: serializeArray(payload.entities),
|
|
9
9
|
waypoints: serializeArray(payload.waypoints),
|
|
10
10
|
};
|
|
11
11
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/components/map/drawer/geofence-event-listing';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/controllers/operations/orders/index/details/virtual';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/helpers/f-to-int';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/services/geofence-event-bus';
|
package/composer.json
CHANGED
package/extension.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fleetbase/fleetops-engine",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.45",
|
|
4
4
|
"description": "Fleet & Transport Management Extension for Fleetbase",
|
|
5
5
|
"fleetbase": {
|
|
6
6
|
"route": "fleet-ops"
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@babel/core": "^7.23.2",
|
|
45
45
|
"@fleetbase/ember-core": "^0.3.18",
|
|
46
46
|
"@fleetbase/ember-ui": "^0.3.26",
|
|
47
|
-
"@fleetbase/fleetops-data": "^0.1.
|
|
47
|
+
"@fleetbase/fleetops-data": "^0.1.30",
|
|
48
48
|
"@fleetbase/leaflet-routing-machine": "^3.2.17",
|
|
49
49
|
"@fortawesome/ember-fontawesome": "^2.0.0",
|
|
50
50
|
"@fortawesome/fontawesome-svg-core": "6.4.0",
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
use Illuminate\Database\Migrations\Migration;
|
|
4
|
+
use Illuminate\Database\Schema\Blueprint;
|
|
5
|
+
use Illuminate\Support\Facades\Schema;
|
|
6
|
+
|
|
7
|
+
return new class extends Migration {
|
|
8
|
+
/**
|
|
9
|
+
* Run the migrations.
|
|
10
|
+
*
|
|
11
|
+
* Adds geofence trigger configuration columns to the zones table,
|
|
12
|
+
* enabling each zone to be configured as an active geofence with
|
|
13
|
+
* entry/exit/dwell event triggers.
|
|
14
|
+
*/
|
|
15
|
+
public function up(): void
|
|
16
|
+
{
|
|
17
|
+
Schema::table('zones', function (Blueprint $table) {
|
|
18
|
+
// Whether to fire a GeofenceEntered event when a driver enters this zone
|
|
19
|
+
$table->boolean('trigger_on_entry')->default(true)->after('stroke_color');
|
|
20
|
+
|
|
21
|
+
// Whether to fire a GeofenceExited event when a driver exits this zone
|
|
22
|
+
$table->boolean('trigger_on_exit')->default(true)->after('trigger_on_entry');
|
|
23
|
+
|
|
24
|
+
// Minutes a driver must remain inside before a GeofenceDwelled event fires.
|
|
25
|
+
// NULL disables dwell tracking for this zone.
|
|
26
|
+
$table->unsignedSmallInteger('dwell_threshold_minutes')->nullable()->after('trigger_on_exit');
|
|
27
|
+
|
|
28
|
+
// Optional speed limit (km/h) enforced within this zone.
|
|
29
|
+
// NULL means no speed limit is configured.
|
|
30
|
+
$table->unsignedSmallInteger('speed_limit_kmh')->nullable()->after('dwell_threshold_minutes');
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Reverse the migrations.
|
|
36
|
+
*/
|
|
37
|
+
public function down(): void
|
|
38
|
+
{
|
|
39
|
+
Schema::table('zones', function (Blueprint $table) {
|
|
40
|
+
$table->dropColumn([
|
|
41
|
+
'trigger_on_entry',
|
|
42
|
+
'trigger_on_exit',
|
|
43
|
+
'dwell_threshold_minutes',
|
|
44
|
+
'speed_limit_kmh',
|
|
45
|
+
]);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
use Illuminate\Database\Migrations\Migration;
|
|
4
|
+
use Illuminate\Database\Schema\Blueprint;
|
|
5
|
+
use Illuminate\Support\Facades\Schema;
|
|
6
|
+
|
|
7
|
+
return new class extends Migration {
|
|
8
|
+
/**
|
|
9
|
+
* Run the migrations.
|
|
10
|
+
*
|
|
11
|
+
* Adds geofence trigger configuration columns to the service_areas table,
|
|
12
|
+
* enabling each service area to act as an active geofence boundary.
|
|
13
|
+
*/
|
|
14
|
+
public function up(): void
|
|
15
|
+
{
|
|
16
|
+
Schema::table('service_areas', function (Blueprint $table) {
|
|
17
|
+
$table->boolean('trigger_on_entry')->default(true)->after('stroke_color');
|
|
18
|
+
$table->boolean('trigger_on_exit')->default(true)->after('trigger_on_entry');
|
|
19
|
+
$table->unsignedSmallInteger('dwell_threshold_minutes')->nullable()->after('trigger_on_exit');
|
|
20
|
+
$table->unsignedSmallInteger('speed_limit_kmh')->nullable()->after('dwell_threshold_minutes');
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Reverse the migrations.
|
|
26
|
+
*/
|
|
27
|
+
public function down(): void
|
|
28
|
+
{
|
|
29
|
+
Schema::table('service_areas', function (Blueprint $table) {
|
|
30
|
+
$table->dropColumn([
|
|
31
|
+
'trigger_on_entry',
|
|
32
|
+
'trigger_on_exit',
|
|
33
|
+
'dwell_threshold_minutes',
|
|
34
|
+
'speed_limit_kmh',
|
|
35
|
+
]);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
use Illuminate\Database\Migrations\Migration;
|
|
4
|
+
use Illuminate\Database\Schema\Blueprint;
|
|
5
|
+
use Illuminate\Support\Facades\Schema;
|
|
6
|
+
|
|
7
|
+
return new class extends Migration {
|
|
8
|
+
/**
|
|
9
|
+
* Run the migrations.
|
|
10
|
+
*
|
|
11
|
+
* Creates the driver_geofence_states table which acts as the state machine
|
|
12
|
+
* store for the geofencing engine. It tracks whether each driver is currently
|
|
13
|
+
* inside each geofence, enabling the system to detect transitions (entry/exit)
|
|
14
|
+
* rather than just evaluating current position in isolation.
|
|
15
|
+
*
|
|
16
|
+
* One record exists per driver-geofence pair. Records are upserted on each
|
|
17
|
+
* location update where a crossing is detected.
|
|
18
|
+
*/
|
|
19
|
+
public function up(): void
|
|
20
|
+
{
|
|
21
|
+
Schema::create('driver_geofence_states', function (Blueprint $table) {
|
|
22
|
+
$table->id();
|
|
23
|
+
$table->uuid('driver_uuid')->index();
|
|
24
|
+
$table->uuid('geofence_uuid')->index();
|
|
25
|
+
|
|
26
|
+
// Discriminator: 'zone' or 'service_area'
|
|
27
|
+
$table->string('geofence_type', 50)->default('zone');
|
|
28
|
+
|
|
29
|
+
// Whether the driver is currently inside this geofence
|
|
30
|
+
$table->boolean('is_inside')->default(false)->index();
|
|
31
|
+
|
|
32
|
+
// Timestamp of when the driver most recently entered this geofence
|
|
33
|
+
$table->timestamp('entered_at')->nullable();
|
|
34
|
+
|
|
35
|
+
// Timestamp of when the driver most recently exited this geofence
|
|
36
|
+
$table->timestamp('exited_at')->nullable();
|
|
37
|
+
|
|
38
|
+
// Queue job ID of the pending CheckGeofenceDwell job.
|
|
39
|
+
// Stored so it can be cancelled if the driver exits before the dwell threshold.
|
|
40
|
+
$table->string('dwell_job_id')->nullable();
|
|
41
|
+
|
|
42
|
+
$table->timestamps();
|
|
43
|
+
|
|
44
|
+
// Composite unique key: one state record per driver-geofence pair
|
|
45
|
+
$table->unique(['driver_uuid', 'geofence_uuid'], 'driver_geofence_unique');
|
|
46
|
+
|
|
47
|
+
// Cascade delete when the driver is deleted
|
|
48
|
+
$table->foreign('driver_uuid')
|
|
49
|
+
->references('uuid')
|
|
50
|
+
->on('drivers')
|
|
51
|
+
->onDelete('cascade');
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Reverse the migrations.
|
|
57
|
+
*/
|
|
58
|
+
public function down(): void
|
|
59
|
+
{
|
|
60
|
+
Schema::dropIfExists('driver_geofence_states');
|
|
61
|
+
}
|
|
62
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
use Illuminate\Database\Migrations\Migration;
|
|
4
|
+
use Illuminate\Database\Schema\Blueprint;
|
|
5
|
+
use Illuminate\Support\Facades\Schema;
|
|
6
|
+
|
|
7
|
+
return new class extends Migration {
|
|
8
|
+
/**
|
|
9
|
+
* Run the migrations.
|
|
10
|
+
*
|
|
11
|
+
* Creates the geofence_events_log table which provides a persistent,
|
|
12
|
+
* queryable audit trail of all geofence events (entered, exited, dwelled).
|
|
13
|
+
* This table powers the reporting dashboard, dwell time analytics, and
|
|
14
|
+
* geofence activity history views.
|
|
15
|
+
*/
|
|
16
|
+
public function up(): void
|
|
17
|
+
{
|
|
18
|
+
Schema::create('geofence_events_log', function (Blueprint $table) {
|
|
19
|
+
$table->id();
|
|
20
|
+
$table->uuid('uuid')->unique()->index();
|
|
21
|
+
$table->uuid('company_uuid')->index();
|
|
22
|
+
$table->uuid('driver_uuid')->index();
|
|
23
|
+
$table->uuid('vehicle_uuid')->nullable()->index();
|
|
24
|
+
$table->uuid('order_uuid')->nullable()->index();
|
|
25
|
+
$table->uuid('geofence_uuid')->index();
|
|
26
|
+
|
|
27
|
+
// Discriminator: 'zone' or 'service_area'
|
|
28
|
+
$table->string('geofence_type', 50)->default('zone');
|
|
29
|
+
|
|
30
|
+
// Snapshot of the geofence name at the time of the event
|
|
31
|
+
$table->string('geofence_name')->nullable();
|
|
32
|
+
|
|
33
|
+
// The type of geofence event
|
|
34
|
+
$table->enum('event_type', ['entered', 'exited', 'dwelled'])->index();
|
|
35
|
+
|
|
36
|
+
// Driver location at the time of the event
|
|
37
|
+
$table->decimal('latitude', 10, 7)->nullable();
|
|
38
|
+
$table->decimal('longitude', 10, 7)->nullable();
|
|
39
|
+
|
|
40
|
+
// Driver speed at the time of the event (km/h)
|
|
41
|
+
$table->decimal('speed_kmh', 8, 2)->nullable();
|
|
42
|
+
|
|
43
|
+
// Populated for 'exited' and 'dwelled' events
|
|
44
|
+
$table->unsignedInteger('dwell_duration_minutes')->nullable();
|
|
45
|
+
|
|
46
|
+
// The precise time the event occurred (not the DB insert time)
|
|
47
|
+
$table->timestamp('occurred_at')->index();
|
|
48
|
+
|
|
49
|
+
$table->timestamps();
|
|
50
|
+
|
|
51
|
+
// Composite indexes for common query patterns
|
|
52
|
+
$table->index(['company_uuid', 'occurred_at'], 'gel_company_occurred_idx');
|
|
53
|
+
$table->index(['geofence_uuid', 'occurred_at'], 'gel_geofence_occurred_idx');
|
|
54
|
+
$table->index(['driver_uuid', 'occurred_at'], 'gel_driver_occurred_idx');
|
|
55
|
+
$table->index(['order_uuid', 'event_type'], 'gel_order_event_idx');
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Reverse the migrations.
|
|
61
|
+
*/
|
|
62
|
+
public function down(): void
|
|
63
|
+
{
|
|
64
|
+
Schema::dropIfExists('geofence_events_log');
|
|
65
|
+
}
|
|
66
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
use Illuminate\Database\Migrations\Migration;
|
|
4
|
+
use Illuminate\Database\Schema\Blueprint;
|
|
5
|
+
use Illuminate\Support\Facades\Schema;
|
|
6
|
+
|
|
7
|
+
return new class extends Migration {
|
|
8
|
+
/**
|
|
9
|
+
* Run the migrations.
|
|
10
|
+
*/
|
|
11
|
+
public function up(): void
|
|
12
|
+
{
|
|
13
|
+
Schema::table('geofence_events_log', function (Blueprint $table) {
|
|
14
|
+
$table->uuid('subject_uuid')->nullable()->after('order_uuid')->index();
|
|
15
|
+
$table->string('subject_type', 50)->default('driver')->after('subject_uuid')->index();
|
|
16
|
+
$table->string('subject_name')->nullable()->after('subject_type');
|
|
17
|
+
$table->uuid('driver_uuid')->nullable()->change();
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Reverse the migrations.
|
|
23
|
+
*/
|
|
24
|
+
public function down(): void
|
|
25
|
+
{
|
|
26
|
+
Schema::table('geofence_events_log', function (Blueprint $table) {
|
|
27
|
+
$table->dropColumn(['subject_uuid', 'subject_type', 'subject_name']);
|
|
28
|
+
$table->uuid('driver_uuid')->nullable(false)->change();
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
use Illuminate\Database\Migrations\Migration;
|
|
4
|
+
use Illuminate\Database\Schema\Blueprint;
|
|
5
|
+
use Illuminate\Support\Facades\Schema;
|
|
6
|
+
|
|
7
|
+
return new class extends Migration {
|
|
8
|
+
/**
|
|
9
|
+
* Run the migrations.
|
|
10
|
+
*/
|
|
11
|
+
public function up(): void
|
|
12
|
+
{
|
|
13
|
+
Schema::create('vehicle_geofence_states', function (Blueprint $table) {
|
|
14
|
+
$table->id();
|
|
15
|
+
$table->uuid('vehicle_uuid')->index();
|
|
16
|
+
$table->uuid('geofence_uuid')->index();
|
|
17
|
+
$table->string('geofence_type', 50)->default('zone');
|
|
18
|
+
$table->boolean('is_inside')->default(false)->index();
|
|
19
|
+
$table->timestamp('entered_at')->nullable();
|
|
20
|
+
$table->timestamp('exited_at')->nullable();
|
|
21
|
+
$table->string('dwell_job_id')->nullable();
|
|
22
|
+
$table->timestamps();
|
|
23
|
+
|
|
24
|
+
$table->unique(['vehicle_uuid', 'geofence_uuid'], 'vehicle_geofence_unique');
|
|
25
|
+
$table->foreign('vehicle_uuid')
|
|
26
|
+
->references('uuid')
|
|
27
|
+
->on('vehicles')
|
|
28
|
+
->onDelete('cascade');
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Reverse the migrations.
|
|
34
|
+
*/
|
|
35
|
+
public function down(): void
|
|
36
|
+
{
|
|
37
|
+
Schema::dropIfExists('vehicle_geofence_states');
|
|
38
|
+
}
|
|
39
|
+
};
|