@fleetbase/fleetops-engine 0.6.69 → 0.6.71
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/RELEASE.md +21 -14
- package/addon/components/admin/telematics-settings.hbs +143 -0
- package/addon/components/admin/telematics-settings.js +145 -0
- package/addon/components/fuel-integration/hub.hbs +1 -1
- package/addon/components/layout/fleet-ops-sidebar.js +37 -17
- package/addon/components/map/leaflet-live-map.hbs +4 -242
- package/addon/components/map/leaflet-live-map.js +2 -1
- package/addon/components/map/marker-card/driver.hbs +57 -0
- package/addon/components/map/marker-card/driver.js +3 -0
- package/addon/components/map/marker-card/vehicle.hbs +78 -0
- package/addon/components/map/marker-card/vehicle.js +3 -0
- package/addon/components/order/details/activity.hbs +8 -6
- package/addon/components/order/details/activity.js +9 -0
- package/addon/components/order/details.hbs +29 -0
- package/addon/components/order/details.js +26 -0
- package/addon/components/order/form/details.hbs +30 -4
- package/addon/components/order/form/details.js +46 -0
- package/addon/components/order/form/route.hbs +4 -2
- package/addon/components/order/form/route.js +11 -0
- package/addon/components/order/form.hbs +12 -0
- package/addon/components/order/form.js +21 -1
- package/addon/components/order/kanban.js +72 -0
- package/addon/components/order-config-manager/activity-flow.js +45 -10
- package/addon/components/order-config-manager/lifecycle.hbs +250 -0
- package/addon/components/order-config-manager/lifecycle.js +358 -0
- package/addon/components/order-config-manager.js +5 -1
- package/addon/components/telematic/hub.hbs +1 -1
- package/addon/components/widget/live-fleet.hbs +8 -40
- package/addon/controllers/analytics/reports/index.js +15 -1
- package/addon/controllers/connectivity/devices/index/details.js +1 -0
- package/addon/controllers/connectivity/devices/index.js +12 -2
- package/addon/controllers/connectivity/events/index.js +31 -1
- package/addon/controllers/connectivity/fuel-providers/index.js +6 -4
- package/addon/controllers/connectivity/sensors/index/details.js +1 -1
- package/addon/controllers/connectivity/sensors/index.js +41 -1
- package/addon/controllers/connectivity/telematics/index.js +4 -0
- package/addon/controllers/maintenance/equipment/index/details.js +2 -2
- package/addon/controllers/maintenance/equipment/index.js +36 -10
- package/addon/controllers/maintenance/inspection-forms/index.js +32 -12
- package/addon/controllers/maintenance/inspection-submissions/index/details.js +2 -1
- package/addon/controllers/maintenance/inspection-submissions/index.js +56 -10
- package/addon/controllers/maintenance/maintenances/index/details.js +2 -0
- package/addon/controllers/maintenance/maintenances/index.js +24 -1
- package/addon/controllers/maintenance/parts/index/details.js +2 -2
- package/addon/controllers/maintenance/parts/index.js +36 -9
- package/addon/controllers/maintenance/schedules/index.js +48 -6
- package/addon/controllers/maintenance/work-orders/index/details.js +3 -3
- package/addon/controllers/maintenance/work-orders/index.js +47 -9
- package/addon/controllers/management/contacts/customers.js +13 -0
- package/addon/controllers/management/contacts/index.js +47 -1
- package/addon/controllers/management/drivers/index/details.js +1 -0
- package/addon/controllers/management/drivers/index.js +36 -2
- package/addon/controllers/management/fleets/index/details.js +1 -0
- package/addon/controllers/management/fleets/index.js +43 -1
- package/addon/controllers/management/fuel-reports/index.js +26 -2
- package/addon/controllers/management/fuel-transactions/index.js +45 -7
- package/addon/controllers/management/issues/index/details.js +1 -0
- package/addon/controllers/management/issues/index.js +26 -2
- package/addon/controllers/management/places/index.js +40 -1
- package/addon/controllers/management/trailers/index/details.js +1 -0
- package/addon/controllers/management/trailers/index.js +50 -2
- package/addon/controllers/management/vehicles/index/details.js +1 -0
- package/addon/controllers/management/vehicles/index.js +37 -2
- package/addon/controllers/management/vendors/index.js +30 -2
- package/addon/controllers/operations/orders/index/details.js +61 -5
- package/addon/controllers/operations/orders/index.js +66 -4
- package/addon/controllers/operations/service-rates/index.js +18 -1
- package/addon/controllers/settings/index.js +13 -0
- package/addon/controllers/settings/telematics.js +113 -0
- package/addon/extension.js +70 -6
- package/addon/routes/analytics/index.js +14 -1
- package/addon/routes/analytics/reports/index/details.js +1 -1
- package/addon/routes/analytics/reports/index/edit.js +1 -1
- package/addon/routes/analytics/reports/index/new.js +14 -1
- package/addon/routes/analytics/reports.js +14 -1
- package/addon/routes/connectivity/devices/index/new.js +14 -1
- package/addon/routes/connectivity/devices.js +14 -1
- package/addon/routes/connectivity/events.js +14 -1
- package/addon/routes/connectivity/fuel-providers/details/transactions.js +12 -0
- package/addon/routes/connectivity/fuel-providers/details.js +9 -0
- package/addon/routes/connectivity/fuel-providers/edit.js +9 -0
- package/addon/routes/connectivity/fuel-providers/new.js +14 -1
- package/addon/routes/connectivity/fuel-providers.js +14 -1
- package/addon/routes/connectivity/sensors/index/new.js +14 -1
- package/addon/routes/connectivity/sensors.js +14 -1
- package/addon/routes/connectivity/telematics/new.js +14 -1
- package/addon/routes/connectivity/telematics.js +14 -1
- package/addon/routes/connectivity/tracking.js +14 -1
- package/addon/routes/maintenance/equipment/index/details.js +2 -2
- package/addon/routes/maintenance/equipment/index/edit.js +2 -2
- package/addon/routes/maintenance/equipment/index/new.js +14 -1
- package/addon/routes/maintenance/equipment.js +14 -1
- package/addon/routes/maintenance/index.js +14 -1
- package/addon/routes/maintenance/inspection-forms/index/details.js +10 -1
- package/addon/routes/maintenance/inspection-forms/index/edit.js +10 -1
- package/addon/routes/maintenance/inspection-forms/index/new.js +14 -1
- package/addon/routes/maintenance/inspection-forms.js +14 -1
- package/addon/routes/maintenance/inspection-submissions/index/details.js +10 -1
- package/addon/routes/maintenance/inspection-submissions/index/edit.js +10 -1
- package/addon/routes/maintenance/inspection-submissions/index/new.js +14 -1
- package/addon/routes/maintenance/inspection-submissions.js +14 -1
- package/addon/routes/maintenance/maintenances/index/details.js +2 -2
- package/addon/routes/maintenance/maintenances/index/edit.js +2 -2
- package/addon/routes/maintenance/maintenances/index/new.js +14 -1
- package/addon/routes/maintenance/maintenances.js +14 -1
- package/addon/routes/maintenance/parts/index/details.js +2 -2
- package/addon/routes/maintenance/parts/index/edit.js +2 -2
- package/addon/routes/maintenance/parts/index/new.js +14 -1
- package/addon/routes/maintenance/parts.js +14 -1
- package/addon/routes/maintenance/schedules/index/details.js +2 -2
- package/addon/routes/maintenance/schedules/index/edit.js +2 -2
- package/addon/routes/maintenance/schedules/index/new.js +15 -1
- package/addon/routes/maintenance/schedules.js +15 -1
- package/addon/routes/maintenance/work-orders/index/details.js +2 -2
- package/addon/routes/maintenance/work-orders/index/edit.js +2 -2
- package/addon/routes/maintenance/work-orders/index/new.js +14 -1
- package/addon/routes/maintenance/work-orders.js +14 -1
- package/addon/routes/management/fuel-transactions/index/details.js +9 -0
- package/addon/routes/management/fuel-transactions.js +14 -1
- package/addon/routes/management/index.js +13 -0
- package/addon/routes/management/trailers.js +16 -0
- package/addon/routes/management/vendors/integrated/details.js +14 -1
- package/addon/routes/management/vendors/integrated/edit.js +14 -1
- package/addon/routes/management/vendors/integrated/new.js +14 -1
- package/addon/routes/management/vendors/integrated.js +14 -1
- package/addon/routes/operations/orders/index/details.js +1 -0
- package/addon/routes/operations/orders.js +40 -1
- package/addon/routes/operations/routes/index/details.js +14 -1
- package/addon/routes/operations/routes/index/new.js +13 -0
- package/addon/routes/operations/routes.js +14 -1
- package/addon/routes/operations/service-rates/index/new.js +11 -0
- package/addon/routes/operations/service-rates.js +14 -1
- package/addon/routes/settings/avatars.js +14 -1
- package/addon/routes/settings/custom-fields.js +14 -1
- package/addon/routes/settings/map.js +14 -1
- package/addon/routes/settings/notifications.js +11 -0
- package/addon/routes/settings/orchestrator.js +1 -1
- package/addon/routes/settings/payments/index.js +1 -1
- package/addon/routes/settings/routing.js +14 -1
- package/addon/routes/settings/scheduling.js +14 -1
- package/addon/routes/settings/telematics.js +21 -0
- package/addon/routes/virtual.js +11 -0
- package/addon/routes.js +1 -0
- package/addon/services/contact-actions.js +1 -0
- package/addon/services/customer-actions.js +2 -1
- package/addon/services/device-actions.js +1 -0
- package/addon/services/device-event-actions.js +1 -0
- package/addon/services/driver-actions.js +4 -13
- package/addon/services/equipment-actions.js +1 -0
- package/addon/services/fleet-actions.js +1 -0
- package/addon/services/fuel-report-actions.js +1 -0
- package/addon/services/inspection-form-actions.js +1 -0
- package/addon/services/inspection-submission-actions.js +1 -0
- package/addon/services/integrated-vendor-actions.js +1 -0
- package/addon/services/issue-actions.js +1 -0
- package/addon/services/maintenance-actions.js +1 -0
- package/addon/services/maintenance-schedule-actions.js +2 -1
- package/addon/services/order-actions.js +7 -0
- package/addon/services/order-presentation.js +129 -0
- package/addon/services/part-actions.js +1 -0
- package/addon/services/place-actions.js +1 -0
- package/addon/services/sensor-actions.js +1 -0
- package/addon/services/service-area-actions.js +1 -0
- package/addon/services/service-rate-actions.js +1 -0
- package/addon/services/telematic-actions.js +1 -0
- package/addon/services/trailer-actions.js +4 -14
- package/addon/services/vehicle-actions.js +4 -13
- package/addon/services/vendor-actions.js +1 -0
- package/addon/services/work-order-actions.js +1 -0
- package/addon/services/zone-actions.js +1 -0
- package/addon/templates/analytics/reports/index/details.hbs +1 -0
- package/addon/templates/analytics/reports/index.hbs +1 -0
- package/addon/templates/connectivity/devices/index/details.hbs +1 -0
- package/addon/templates/connectivity/devices/index.hbs +1 -0
- package/addon/templates/connectivity/events/index.hbs +1 -0
- package/addon/templates/connectivity/sensors/index/details.hbs +1 -0
- package/addon/templates/connectivity/sensors/index.hbs +1 -0
- package/addon/templates/maintenance/equipment/index/details.hbs +1 -0
- package/addon/templates/maintenance/equipment/index.hbs +2 -0
- package/addon/templates/maintenance/inspection-forms/index/details.hbs +1 -0
- package/addon/templates/maintenance/inspection-forms/index.hbs +1 -0
- package/addon/templates/maintenance/inspection-submissions/index/details.hbs +1 -0
- package/addon/templates/maintenance/inspection-submissions/index.hbs +1 -0
- package/addon/templates/maintenance/maintenances/index/details.hbs +1 -0
- package/addon/templates/maintenance/maintenances/index.hbs +1 -0
- package/addon/templates/maintenance/parts/index/details.hbs +1 -0
- package/addon/templates/maintenance/parts/index.hbs +2 -0
- package/addon/templates/maintenance/schedules/index/details.hbs +1 -0
- package/addon/templates/maintenance/schedules/index.hbs +2 -0
- package/addon/templates/maintenance/work-orders/index/details.hbs +1 -0
- package/addon/templates/maintenance/work-orders/index.hbs +1 -0
- package/addon/templates/management/contacts/customers/details.hbs +1 -0
- package/addon/templates/management/contacts/customers.hbs +1 -0
- package/addon/templates/management/contacts/index/details.hbs +1 -0
- package/addon/templates/management/contacts/index.hbs +1 -0
- package/addon/templates/management/contacts.hbs +1 -0
- package/addon/templates/management/drivers/index/details.hbs +1 -0
- package/addon/templates/management/drivers/index.hbs +2 -0
- package/addon/templates/management/fleets/index/details.hbs +1 -0
- package/addon/templates/management/fleets/index.hbs +1 -0
- package/addon/templates/management/fuel-reports/index/details.hbs +1 -0
- package/addon/templates/management/fuel-reports/index.hbs +1 -0
- package/addon/templates/management/fuel-transactions/index.hbs +1 -0
- package/addon/templates/management/issues/index/details.hbs +1 -0
- package/addon/templates/management/issues/index.hbs +1 -0
- package/addon/templates/management/places/index/details.hbs +1 -0
- package/addon/templates/management/places/index.hbs +1 -0
- package/addon/templates/management/trailers/index/details.hbs +1 -0
- package/addon/templates/management/trailers/index.hbs +2 -0
- package/addon/templates/management/vehicles/index/details.hbs +1 -0
- package/addon/templates/management/vehicles/index.hbs +2 -0
- package/addon/templates/management/vendors/index/details.hbs +1 -0
- package/addon/templates/management/vendors/index.hbs +2 -0
- package/addon/templates/management/vendors/integrated.hbs +1 -0
- package/addon/templates/operations/orders/index/details.hbs +1 -0
- package/addon/templates/operations/orders/index.hbs +1 -0
- package/addon/templates/operations/service-rates/index/details.hbs +1 -0
- package/addon/templates/operations/service-rates/index.hbs +1 -0
- package/addon/templates/settings/telematics.hbs +70 -0
- package/addon/utils/normalize-order-config-flow.js +6 -1
- package/app/components/admin/telematics-settings.js +1 -0
- package/app/components/map/marker-card/driver.js +1 -0
- package/app/components/map/marker-card/vehicle.js +1 -0
- package/app/controllers/settings/telematics.js +1 -0
- package/app/routes/settings/telematics.js +1 -0
- package/app/services/order-presentation.js +1 -0
- package/app/templates/settings/telematics.js +1 -0
- package/composer.json +2 -2
- package/docs/AFAQY.md +1 -1
- package/docs/TELEMATICS_QUEUES.md +1 -1
- package/docs/TELEMETRY_ARCHITECTURE.md +72 -1
- package/extension.json +1 -1
- package/package.json +3 -3
- package/server/config/telemetry.php +12 -0
- package/server/migrations/2026_09_23_000001_add_retention_index_to_device_events.php +40 -0
- package/server/migrations/2026_09_23_000002_add_retention_index_to_positions.php +40 -0
- package/server/migrations/2026_09_23_000003_add_retention_index_to_telematic_sync_runs.php +40 -0
- package/server/src/Auth/Schemas/FleetOps.php +104 -5
- package/server/src/Console/Commands/DrainTelematicInbox.php +3 -13
- package/server/src/Console/Commands/ProcessOperationalAlerts.php +3 -3
- package/server/src/Console/Commands/PruneTelematicsData.php +318 -0
- package/server/src/Http/Controllers/Api/v1/OrchestrationController.php +9 -0
- package/server/src/Http/Controllers/FleetOpsController.php +21 -0
- package/server/src/Http/Controllers/Internal/v1/AnalyticsController.php +11 -0
- package/server/src/Http/Controllers/Internal/v1/ContactController.php +11 -0
- package/server/src/Http/Controllers/Internal/v1/CustomerController.php +14 -0
- package/server/src/Http/Controllers/Internal/v1/DeviceController.php +13 -0
- package/server/src/Http/Controllers/Internal/v1/DeviceEventController.php +11 -0
- package/server/src/Http/Controllers/Internal/v1/DriverController.php +22 -0
- package/server/src/Http/Controllers/Internal/v1/FuelProviderConnectionController.php +13 -0
- package/server/src/Http/Controllers/Internal/v1/FuelProviderTransactionController.php +15 -0
- package/server/src/Http/Controllers/Internal/v1/FuelReportController.php +9 -3
- package/server/src/Http/Controllers/Internal/v1/InspectionFormController.php +15 -0
- package/server/src/Http/Controllers/Internal/v1/LiveController.php +16 -0
- package/server/src/Http/Controllers/Internal/v1/MaintenanceController.php +15 -0
- package/server/src/Http/Controllers/Internal/v1/MaintenanceScheduleController.php +15 -0
- package/server/src/Http/Controllers/Internal/v1/ManifestController.php +15 -0
- package/server/src/Http/Controllers/Internal/v1/MetricsController.php +11 -0
- package/server/src/Http/Controllers/Internal/v1/NavigatorController.php +42 -1
- package/server/src/Http/Controllers/Internal/v1/OrchestrationController.php +12 -0
- package/server/src/Http/Controllers/Internal/v1/OrderController.php +56 -4
- package/server/src/Http/Controllers/Internal/v1/PaymentController.php +13 -0
- package/server/src/Http/Controllers/Internal/v1/RadarController.php +19 -0
- package/server/src/Http/Controllers/Internal/v1/ServiceAreaController.php +9 -3
- package/server/src/Http/Controllers/Internal/v1/SettingController.php +465 -14
- package/server/src/Http/Controllers/Internal/v1/TelematicController.php +21 -0
- package/server/src/Http/Controllers/Internal/v1/TrailerController.php +21 -0
- package/server/src/Http/Controllers/Internal/v1/VehicleController.php +21 -0
- package/server/src/Http/Controllers/Internal/v1/VendorController.php +17 -0
- package/server/src/Http/Controllers/Internal/v1/WorkOrderController.php +11 -0
- package/server/src/Jobs/DispatchTelematicsRetentionJobs.php +70 -0
- package/server/src/Jobs/PruneTelematicsDataJob.php +74 -0
- package/server/src/Listeners/NotifyDriverOnShiftChange.php +3 -3
- package/server/src/Mail/CustomerCredentialsMail.php +1 -1
- package/server/src/Models/Order.php +35 -3
- package/server/src/Models/OrderConfig.php +129 -0
- package/server/src/Models/TrackingNumber.php +8 -4
- package/server/src/Orchestration/Engines/VroomOrchestrationEngine.php +9 -1
- package/server/src/Providers/FleetOpsServiceProvider.php +3 -0
- package/server/src/Support/Analytics/LiveFleet.php +18 -2
- package/server/src/Support/Authorization.php +103 -0
- package/server/src/Support/Database/TableIndexes.php +66 -0
- package/server/src/Support/OrderTracker.php +2 -2
- package/server/src/Support/Reporting/FleetOpsReportSchema.php +476 -116
- package/server/src/Support/Telematics/Retention/RetentionPolicy.php +300 -0
- package/server/src/Support/Telematics/Retention/TelemetryActivity.php +40 -0
- package/server/src/Support/Telematics/TelematicService.php +12 -2
- package/server/src/Support/Telematics/Telemetry/Ingestor.php +4 -2
- package/server/src/Tracking/TrackingIntelligenceService.php +1 -1
- package/server/src/Tracking/TrackingOptions.php +2 -2
- package/server/src/Traits/AuthorizesMethods.php +37 -0
- package/server/src/routes.php +9 -1
- package/server/tests/AnalyticsRoutesTest.php +29 -2
- package/server/tests/Feature/Http/AfaqyRealtimeIngestionTest.php +16 -1
- package/server/tests/Feature/Http/Api/TelematicsRetentionIndexMigrationTest.php +115 -0
- package/server/tests/Feature/Http/Internal/OrderControllerActivityFlowsTest.php +72 -0
- package/server/tests/Feature/Http/Internal/OrderControllerCreateRecordTest.php +26 -0
- package/server/tests/Feature/Http/Internal/SettingControllerHelpersTest.php +71 -0
- package/server/tests/Feature/Http/Internal/TelematicsStorageDeadlinesTest.php +119 -0
- package/server/tests/InternalImportExportControllerContractsTest.php +5 -8
- package/server/tests/NavigatorControllerContractsTest.php +36 -4
- package/server/tests/NotificationAndMailContractsTest.php +31 -0
- package/server/tests/ObserverContractsTest.php +1 -1
- package/server/tests/OrchestratorConsumableApiTest.php +42 -0
- package/server/tests/OrderConfigLifecycleTest.php +120 -0
- package/server/tests/ProviderContractsTest.php +10 -0
- package/server/tests/ReportSchemaContractsTest.php +120 -6
- package/server/tests/SettingControllerContractsTest.php +429 -18
- package/server/tests/SmallControllerContractsTest.php +8 -5
- package/server/tests/Support/PruneTelematicsDataProbe.php +55 -0
- package/server/tests/Unit/Console/Commands/ProcessOperationalAlertsCommandTest.php +2 -2
- package/server/tests/Unit/Console/PruneTelematicsDataCommandTest.php +353 -0
- package/server/tests/Unit/Events/OrderDispatchFailedTest.php +2 -1
- package/server/tests/Unit/Jobs/DispatchTelematicsRetentionJobsTest.php +114 -0
- package/server/tests/Unit/Jobs/PruneTelematicsDataJobTest.php +60 -0
- package/server/tests/Unit/Orchestration/VroomEngineTransportAndSettingsTest.php +20 -0
- package/server/tests/Unit/Support/Analytics/LiveFleetTest.php +6 -0
- package/server/tests/Unit/Support/AuthorizationTest.php +142 -0
- package/server/tests/Unit/Support/MaintainableAndOperationalAlertsTest.php +12 -1
- package/server/tests/Unit/Support/MoreQuerySeamsTest.php +11 -2
- package/server/tests/Unit/Support/Telematics/Retention/RetentionPolicyTest.php +190 -0
- package/server/tests/Unit/Support/Telematics/Retention/TelemetryActivityTest.php +68 -0
- package/server/tests/Unit/Tracking/TrackingOptionsCompanySettingsTest.php +109 -0
- package/translations/en-us.yaml +108 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{{#if (eq this.layout "table")}}
|
|
2
2
|
<Layout::Resource::Tabular
|
|
3
|
+
@registry="fleet-ops:vendor:table"
|
|
3
4
|
@resource="vendor"
|
|
4
5
|
@title={{t "resource.vendors"}}
|
|
5
6
|
@searchQuery={{this.query}}
|
|
@@ -34,6 +35,7 @@
|
|
|
34
35
|
{{else}}
|
|
35
36
|
<Layout::Section::Header @title={{t "resource.vendors"}} @actionsWrapperClass="space-x-1">
|
|
36
37
|
<Layout::Resource::TabularActions
|
|
38
|
+
@registry="fleet-ops:vendor:table"
|
|
37
39
|
@searchQuery={{this.query}}
|
|
38
40
|
@onSearch={{perform this.vendorActions.controllerSearchTask this}}
|
|
39
41
|
@columns={{this.columns}}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<Layout::Section::Header @title={{t "settings.telematics.telematics-settings"}}>
|
|
2
|
+
<Button
|
|
3
|
+
@type="primary"
|
|
4
|
+
@size="sm"
|
|
5
|
+
@icon="save"
|
|
6
|
+
@text={{t "common.save-changes"}}
|
|
7
|
+
@onClick={{perform this.saveSettings}}
|
|
8
|
+
@disabled={{or this.saveSettings.isRunning this.getSettings.isRunning (not this.settingsLoaded)}}
|
|
9
|
+
@isLoading={{or this.saveSettings.isRunning this.getSettings.isRunning}}
|
|
10
|
+
@permission="fleet-ops update telematics-settings"
|
|
11
|
+
/>
|
|
12
|
+
</Layout::Section::Header>
|
|
13
|
+
<Layout::Section::Body class="overflow-y-scroll-i h-full">
|
|
14
|
+
<div class="container mx-auto">
|
|
15
|
+
<div class="max-w-3xl my-10 mx-auto space-y-6">
|
|
16
|
+
<InfoBlock @type="info" @icon="circle-info">
|
|
17
|
+
{{t "settings.telematics.intro"}}
|
|
18
|
+
</InfoBlock>
|
|
19
|
+
|
|
20
|
+
<ContentPanel @title={{t "settings.telematics.device-events"}} @open={{true}} @wrapperClass="bordered-classic">
|
|
21
|
+
<InputGroup>
|
|
22
|
+
<Toggle
|
|
23
|
+
@label={{t "settings.telematics.use-system-default"}}
|
|
24
|
+
@isToggled={{this.useDefaultEventRetention}}
|
|
25
|
+
@onToggle={{this.setUseDefaultEventRetention}}
|
|
26
|
+
@disabled={{not this.settingsLoaded}}
|
|
27
|
+
/>
|
|
28
|
+
</InputGroup>
|
|
29
|
+
<InputGroup @name={{t "settings.telematics.event-retention-days"}} @helpText={{t "settings.telematics.event-retention-days-help"}}>
|
|
30
|
+
<Input
|
|
31
|
+
@type="number"
|
|
32
|
+
@value={{this.eventRetentionDays}}
|
|
33
|
+
min={{this.eventRetentionMinimum}}
|
|
34
|
+
max={{this.eventRetentionMaximum}}
|
|
35
|
+
disabled={{or this.useDefaultEventRetention (not this.settingsLoaded)}}
|
|
36
|
+
class="w-full form-input"
|
|
37
|
+
/>
|
|
38
|
+
</InputGroup>
|
|
39
|
+
{{#if this.settingsLoaded}}
|
|
40
|
+
<p class="text-xs text-gray-500 dark:text-gray-400">{{this.eventRetentionPolicyHelp}}</p>
|
|
41
|
+
{{/if}}
|
|
42
|
+
</ContentPanel>
|
|
43
|
+
|
|
44
|
+
<ContentPanel @title={{t "settings.telematics.positions"}} @open={{true}} @wrapperClass="bordered-classic">
|
|
45
|
+
<InputGroup>
|
|
46
|
+
<Toggle
|
|
47
|
+
@label={{t "settings.telematics.use-system-default"}}
|
|
48
|
+
@isToggled={{this.useDefaultPositionRetention}}
|
|
49
|
+
@onToggle={{this.setUseDefaultPositionRetention}}
|
|
50
|
+
@disabled={{not this.settingsLoaded}}
|
|
51
|
+
/>
|
|
52
|
+
</InputGroup>
|
|
53
|
+
<InputGroup @name={{t "settings.telematics.position-retention-days"}} @helpText={{t "settings.telematics.position-retention-days-help"}}>
|
|
54
|
+
<Input
|
|
55
|
+
@type="number"
|
|
56
|
+
@value={{this.positionRetentionDays}}
|
|
57
|
+
min={{this.positionRetentionMinimum}}
|
|
58
|
+
max={{this.positionRetentionMaximum}}
|
|
59
|
+
disabled={{or this.useDefaultPositionRetention (not this.settingsLoaded)}}
|
|
60
|
+
class="w-full form-input"
|
|
61
|
+
/>
|
|
62
|
+
</InputGroup>
|
|
63
|
+
{{#if this.settingsLoaded}}
|
|
64
|
+
<p class="text-xs text-gray-500 dark:text-gray-400">{{this.positionRetentionPolicyHelp}}</p>
|
|
65
|
+
{{/if}}
|
|
66
|
+
</ContentPanel>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
<Spacer @height="200px" />
|
|
70
|
+
</Layout::Section::Body>
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { isArray } from '@ember/array';
|
|
2
2
|
|
|
3
|
-
export function getOrderConfigFlowRootCode(flow = {}) {
|
|
3
|
+
export function getOrderConfigFlowRootCode(flow = {}, initialCode = null) {
|
|
4
|
+
// A configured lifecycle (`meta.lifecycle.initial`) names its own root activity.
|
|
5
|
+
if (initialCode && flow[initialCode]) {
|
|
6
|
+
return initialCode;
|
|
7
|
+
}
|
|
8
|
+
|
|
4
9
|
if (flow.created) {
|
|
5
10
|
return 'created';
|
|
6
11
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/components/admin/telematics-settings';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/components/map/marker-card/driver';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/components/map/marker-card/vehicle';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/controllers/settings/telematics';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/routes/settings/telematics';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/services/order-presentation';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/templates/settings/telematics';
|
package/composer.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fleetbase/fleetops-api",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.71",
|
|
4
4
|
"description": "Fleet & Transport Management Extension for Fleetbase",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fleetbase-extension",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"barryvdh/laravel-dompdf": "^3.1",
|
|
26
26
|
"brick/geo": "0.7.2",
|
|
27
27
|
"cknow/laravel-money": "^7.1",
|
|
28
|
-
"fleetbase/core-api": "
|
|
28
|
+
"fleetbase/core-api": ">=1.6.65",
|
|
29
29
|
"geocoder-php/google-maps-places-provider": "^1.4",
|
|
30
30
|
"giggsey/libphonenumber-for-php": "^8.13",
|
|
31
31
|
"league/geotools": "^1.1.0",
|
package/docs/AFAQY.md
CHANGED
|
@@ -57,7 +57,7 @@ Existing provider interfaces and vehicle/trailer event names remain compatible.
|
|
|
57
57
|
|
|
58
58
|
The public receiver remains `POST webhooks/telematics/afaqy?telematic=...&key=...` under the application's API prefix. A new `device.telemetry_updated` broadcast identifies the device; an open device panel reloads its authorized resource and refetches after socket reconnection. Company broadcast identity comes from the persisted asset, not a worker session. Map movement uses the existing vehicle/trailer events, rejects older source timestamps, and reloads visible telemetry assets after socket reconnection with at most five concurrent requests.
|
|
59
59
|
|
|
60
|
-
Configure shared queues, retention, limits, and freshness under `telematics.telemetry` using `server/config/telemetry.php`. `TELEMATICS_BATCH_SIZE` controls units per ingestion delivery (default 100); `TELEMATICS_REQUEST_TIMEOUT_SECONDS` controls the bounded polling request timeout (default 45 seconds). AFAQY's adapter switches and optional queue overrides remain under `telematics.afaqy` in `server/config/afaqy.php`. Defaults: two MiB per webhook, 10,000 pending deliveries per connection, processed
|
|
60
|
+
Configure shared queues, retention, limits, and freshness under `telematics.telemetry` using `server/config/telemetry.php`. `TELEMATICS_BATCH_SIZE` controls units per ingestion delivery (default 100); `TELEMATICS_REQUEST_TIMEOUT_SECONDS` controls the bounded polling request timeout (default 45 seconds). AFAQY's adapter switches and optional queue overrides remain under `telematics.afaqy` in `server/config/afaqy.php`. Defaults: two MiB per webhook, 10,000 pending deliveries per connection, stale-position thresholds 120 seconds with ignition on and 600 seconds with ignition off/unknown. Retention (processed payloads 24 hours, quarantined deliveries seven days, device events 30 days, positions 90 days) is applied by `fleetops:prune-telematics-data`. Administrators configure retention policy, logging, system storage diagnostics and system cleanup in Admin → Fleet-Ops Config → Telematics. Organizations choose only event and position history preferences within those limits in Fleet-Ops → Settings → Telematics; config values are the fallback. See `docs/TELEMETRY_ARCHITECTURE.md` § Retention. Each device's metadata records the effective threshold. Connection status categories remain unchanged.
|
|
61
61
|
|
|
62
62
|
## Incident verification
|
|
63
63
|
|
|
@@ -14,7 +14,7 @@ nothing changes: every job and broadcast stays on the same queue as before.
|
|
|
14
14
|
| Setting | Default | Work routed |
|
|
15
15
|
| --- | --- | --- |
|
|
16
16
|
| `TELEMATICS_POLL_QUEUE` | `default` | Scheduled and manual polls (`PollTelematicTelemetry`), legacy device discovery (`SyncTelematicDevicesJob`), and queued connection tests (`TestTelematicConnectionJob`). |
|
|
17
|
-
| `TELEMATICS_INGESTION_QUEUE` | `default` | Applying polled or pushed positions (`ProcessTelematicDelivery`), including jobs re-queued by `fleetops:drain-telematic-inbox` and manual replays. |
|
|
17
|
+
| `TELEMATICS_INGESTION_QUEUE` | `default` | Applying polled or pushed positions (`ProcessTelematicDelivery`), including jobs re-queued by `fleetops:drain-telematic-inbox` and manual replays, and on-demand retention runs (`PruneTelematicsDataJob`, queued by "Run system cleanup" in Admin → Fleet-Ops Config → Telematics). |
|
|
18
18
|
| `TELEMATICS_BROADCAST_QUEUE` | unset | Live-map broadcasts created by telematics ingestion: `DeviceTelemetryUpdated`, and `VehicleLocationChanged` / `TrailerLocationChanged` when a device is attached. When unset, broadcasts use the queue connection's default queue. |
|
|
19
19
|
|
|
20
20
|
`TELEMATICS_BROADCAST_QUEUE` affects only broadcasts that telematics ingestion
|
|
@@ -48,11 +48,82 @@ persistence. The performance requirement did not justify those dependencies.
|
|
|
48
48
|
## Tradeoffs
|
|
49
49
|
|
|
50
50
|
Three shared tables separate run-level diagnostics, high-volume delivery retention,
|
|
51
|
-
and connection-level secrets with different lifetimes. Provider-specific protocol
|
|
51
|
+
and connection-level secrets with different lifetimes (see Retention below). Provider-specific protocol
|
|
52
52
|
classes remain appropriate. Capability opt-in avoids silently changing every
|
|
53
53
|
existing integration's ingestion or webhook behavior. Production throughput and
|
|
54
54
|
real AFAQY payload verification remain separate deployment gates.
|
|
55
55
|
|
|
56
|
+
## Retention
|
|
57
|
+
|
|
58
|
+
Every poll writes one `device_events` row, one `positions` row and a delivery
|
|
59
|
+
envelope per batch for each reporting device. Without a ceiling those tables grow
|
|
60
|
+
until the disk fills, so retention is enforced by `fleetops:prune-telematics-data`
|
|
61
|
+
(scheduled every fifteen minutes, `withoutOverlapping(14)`) using a per-company
|
|
62
|
+
policy resolved by `Support\Telematics\Retention\RetentionPolicy`:
|
|
63
|
+
|
|
64
|
+
| Layer | Source | Where it is edited |
|
|
65
|
+
|---|---|---|
|
|
66
|
+
| Package config | `server/config/telemetry.php` | deployment |
|
|
67
|
+
| System policy | setting `fleet-ops.telematics-settings` | Admin console → Fleet-Ops Config → Telematics |
|
|
68
|
+
| Company history preferences | `company.<uuid>.fleet-ops.telematics-settings` | Fleet-Ops → Settings → Telematics |
|
|
69
|
+
|
|
70
|
+
Defaults: device events 30 days, raw payload/meta stripped ("compacted") after
|
|
71
|
+
7 days, positions 90 days, processed deliveries 24 hours, quarantined deliveries
|
|
72
|
+
7 days, sync runs 7 days. Organizations can choose only device event and position
|
|
73
|
+
history retention, or inherit the system defaults. Administrators own raw payload,
|
|
74
|
+
delivery, sync-run retention and telemetry activity logging.
|
|
75
|
+
|
|
76
|
+
`max_event_retention_days` and `max_position_retention_days` constrain every
|
|
77
|
+
organization's history, including inherited defaults. A maximum of `0` allows
|
|
78
|
+
unlimited history; a history preference of `0` keeps records forever only while
|
|
79
|
+
that maximum is unset. Setting a finite maximum replaces saved unlimited or longer
|
|
80
|
+
preferences with that maximum. Missing preferences continue to inherit. Values
|
|
81
|
+
are also clamped to `RetentionPolicy::LIMITS`.
|
|
82
|
+
|
|
83
|
+
Admin storage diagnostics cover the entire system, including organizations the
|
|
84
|
+
administrator does not belong to. System cleanup queues work for every
|
|
85
|
+
organization plus orphaned records, with each organization's effective policy
|
|
86
|
+
applied independently. Storage sizes include table data and indexes; database row
|
|
87
|
+
estimates are labeled. Cleanup is asynchronous, so refreshing usage does not mean
|
|
88
|
+
all queued work has finished.
|
|
89
|
+
|
|
90
|
+
Manual system cleanup requires an asynchronous queue connection and a worker for
|
|
91
|
+
`telematics.telemetry.ingestion_queue`. A synchronous or disabled queue is rejected
|
|
92
|
+
instead of running every organization's cleanup inside the HTTP request.
|
|
93
|
+
|
|
94
|
+
Deploy the frontend and backend together and reload Octane and queue workers after
|
|
95
|
+
updating the backend. In linked development checkouts, Octane's watch paths must
|
|
96
|
+
include `packages/fleetops/server`; watching only the host API directory leaves
|
|
97
|
+
previously loaded controllers and policies running.
|
|
98
|
+
|
|
99
|
+
Rules the sweep follows:
|
|
100
|
+
|
|
101
|
+
- Hard deletes only. The models soft-delete, so `delete()` would grow the table;
|
|
102
|
+
rows already soft-deleted are purged regardless of age.
|
|
103
|
+
- Bounded work: at most `--max-batches` (default 50) statements of `--batch-size`
|
|
104
|
+
(default 1000) rows per table per company per run. A capped run is normal; the
|
|
105
|
+
next tick continues. Operators can catch up faster off-peak with
|
|
106
|
+
`php artisan fleetops:prune-telematics-data --max-batches=500 --no-lock`.
|
|
107
|
+
- Compaction keeps the event (type, severity, location, normalized `data`) and
|
|
108
|
+
nulls `payload` and `meta`, which hold the bulk of each row.
|
|
109
|
+
- `telematic_deliveries` and `telematic_sync_runs` carry no company; they are
|
|
110
|
+
resolved through the company's connections (including trashed ones). In-flight
|
|
111
|
+
sync runs (`fetching`, `ingesting`) are recovered by the drain, never expired.
|
|
112
|
+
- Rows whose company or connection no longer exists are swept with the system
|
|
113
|
+
defaults.
|
|
114
|
+
- Migrations add `(company_uuid, created_at)` on `device_events` and `positions`
|
|
115
|
+
and `(telematic_uuid, updated_at)` on `telematic_sync_runs`; on multi-GB tables
|
|
116
|
+
run them in a maintenance window.
|
|
117
|
+
- Deleting rows frees space inside InnoDB files, not on disk. Run
|
|
118
|
+
`OPTIMIZE TABLE device_events` (requires `innodb_file_per_table`) off-peak to
|
|
119
|
+
return it to the operating system.
|
|
120
|
+
|
|
121
|
+
Two write-amplification fixes accompany the sweep: `device_events.meta` stores only
|
|
122
|
+
the normalized block (the raw unit lives once, in `payload`), and telemetry-driven
|
|
123
|
+
saves run inside `activity()->withoutLogs()` unless the system administrator enables
|
|
124
|
+
"Log telemetry activity". `DrainTelematicInbox` now only recovers deliveries and
|
|
125
|
+
finishes interrupted runs.
|
|
126
|
+
|
|
56
127
|
## Adding an adapter
|
|
57
128
|
|
|
58
129
|
Implement `TelemetryProviderInterface` alongside the existing provider contract.
|
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.71",
|
|
4
4
|
"description": "Fleet & Transport Management Extension for Fleetbase",
|
|
5
5
|
"fleetbase": {
|
|
6
6
|
"route": "fleet-ops"
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@babel/core": "^7.23.2",
|
|
47
|
-
"@fleetbase/ember-core": "^0.3.
|
|
48
|
-
"@fleetbase/ember-ui": "^0.4.
|
|
47
|
+
"@fleetbase/ember-core": "^0.3.25",
|
|
48
|
+
"@fleetbase/ember-ui": "^0.4.5",
|
|
49
49
|
"@fleetbase/fleetops-data": "^0.2.2",
|
|
50
50
|
"@fleetbase/leaflet-routing-machine": "^3.2.17",
|
|
51
51
|
"@fortawesome/ember-fontawesome": "^2.0.0",
|
|
@@ -13,8 +13,20 @@ return [
|
|
|
13
13
|
'batch_size' => env('TELEMATICS_BATCH_SIZE', 100),
|
|
14
14
|
'max_payload_bytes' => 2097152,
|
|
15
15
|
'max_pending_deliveries' => 10000,
|
|
16
|
+
// Administrators control infrastructure retention and activity logging.
|
|
17
|
+
// Companies may choose event/position history retention within the maximums.
|
|
18
|
+
// A maximum of 0 imposes no cap and permits unlimited history (retention 0).
|
|
16
19
|
'processed_retention_hours' => 24,
|
|
17
20
|
'quarantine_retention_days' => 7,
|
|
21
|
+
'sync_run_retention_days' => 7,
|
|
22
|
+
'event_retention_days' => 30,
|
|
23
|
+
'event_compact_after_days' => 7,
|
|
24
|
+
'position_retention_days' => 90,
|
|
25
|
+
'max_event_retention_days' => 0,
|
|
26
|
+
'max_position_retention_days' => 0,
|
|
27
|
+
'log_telemetry_activity' => false,
|
|
28
|
+
'prune_batch_size' => 1000,
|
|
29
|
+
'prune_max_batches' => 50,
|
|
18
30
|
'stale_engine_on_seconds' => 120,
|
|
19
31
|
'stale_engine_off_seconds' => 600,
|
|
20
32
|
];
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
use Fleetbase\FleetOps\Support\Database\TableIndexes;
|
|
4
|
+
use Illuminate\Database\Migrations\Migration;
|
|
5
|
+
use Illuminate\Database\Schema\Blueprint;
|
|
6
|
+
use Illuminate\Support\Facades\Schema;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Supports the bounded retention sweep in fleetops:prune-telematics-data,
|
|
10
|
+
* which ranges over these columns for every company on every run.
|
|
11
|
+
*/
|
|
12
|
+
return new class extends Migration {
|
|
13
|
+
private const TABLE = 'device_events';
|
|
14
|
+
private const INDEX = 'device_events_company_created_at_index';
|
|
15
|
+
private const COLUMNS = ['company_uuid', 'created_at'];
|
|
16
|
+
|
|
17
|
+
public function up(): void
|
|
18
|
+
{
|
|
19
|
+
if (!Schema::hasTable(self::TABLE) || !Schema::hasColumns(self::TABLE, self::COLUMNS)) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (TableIndexes::covers(self::TABLE, self::COLUMNS)) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
Schema::table(self::TABLE, fn (Blueprint $table) => $table->index(self::COLUMNS, self::INDEX));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public function down(): void
|
|
31
|
+
{
|
|
32
|
+
if (!Schema::hasTable(self::TABLE)) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if ((TableIndexes::for(self::TABLE)[self::INDEX] ?? null) === self::COLUMNS) {
|
|
37
|
+
Schema::table(self::TABLE, fn (Blueprint $table) => $table->dropIndex(self::INDEX));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
use Fleetbase\FleetOps\Support\Database\TableIndexes;
|
|
4
|
+
use Illuminate\Database\Migrations\Migration;
|
|
5
|
+
use Illuminate\Database\Schema\Blueprint;
|
|
6
|
+
use Illuminate\Support\Facades\Schema;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Supports the bounded retention sweep in fleetops:prune-telematics-data,
|
|
10
|
+
* which ranges over these columns for every company on every run.
|
|
11
|
+
*/
|
|
12
|
+
return new class extends Migration {
|
|
13
|
+
private const TABLE = 'positions';
|
|
14
|
+
private const INDEX = 'positions_company_created_at_index';
|
|
15
|
+
private const COLUMNS = ['company_uuid', 'created_at'];
|
|
16
|
+
|
|
17
|
+
public function up(): void
|
|
18
|
+
{
|
|
19
|
+
if (!Schema::hasTable(self::TABLE) || !Schema::hasColumns(self::TABLE, self::COLUMNS)) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (TableIndexes::covers(self::TABLE, self::COLUMNS)) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
Schema::table(self::TABLE, fn (Blueprint $table) => $table->index(self::COLUMNS, self::INDEX));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public function down(): void
|
|
31
|
+
{
|
|
32
|
+
if (!Schema::hasTable(self::TABLE)) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if ((TableIndexes::for(self::TABLE)[self::INDEX] ?? null) === self::COLUMNS) {
|
|
37
|
+
Schema::table(self::TABLE, fn (Blueprint $table) => $table->dropIndex(self::INDEX));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
use Fleetbase\FleetOps\Support\Database\TableIndexes;
|
|
4
|
+
use Illuminate\Database\Migrations\Migration;
|
|
5
|
+
use Illuminate\Database\Schema\Blueprint;
|
|
6
|
+
use Illuminate\Support\Facades\Schema;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Supports the bounded retention sweep in fleetops:prune-telematics-data,
|
|
10
|
+
* which ranges over these columns for every company on every run.
|
|
11
|
+
*/
|
|
12
|
+
return new class extends Migration {
|
|
13
|
+
private const TABLE = 'telematic_sync_runs';
|
|
14
|
+
private const INDEX = 'telematic_sync_runs_telematic_updated_at_index';
|
|
15
|
+
private const COLUMNS = ['telematic_uuid', 'updated_at'];
|
|
16
|
+
|
|
17
|
+
public function up(): void
|
|
18
|
+
{
|
|
19
|
+
if (!Schema::hasTable(self::TABLE) || !Schema::hasColumns(self::TABLE, self::COLUMNS)) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (TableIndexes::covers(self::TABLE, self::COLUMNS)) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
Schema::table(self::TABLE, fn (Blueprint $table) => $table->index(self::COLUMNS, self::INDEX));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public function down(): void
|
|
31
|
+
{
|
|
32
|
+
if (!Schema::hasTable(self::TABLE)) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if ((TableIndexes::for(self::TABLE)[self::INDEX] ?? null) === self::COLUMNS) {
|
|
37
|
+
Schema::table(self::TABLE, fn (Blueprint $table) => $table->dropIndex(self::INDEX));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
};
|