@fleetbase/fleetops-engine 0.6.68 → 0.6.70
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 +44 -9
- package/addon/components/admin/telematics-settings.hbs +143 -0
- package/addon/components/admin/telematics-settings.js +145 -0
- package/addon/components/contact/form.hbs +13 -2
- package/addon/components/customer/details.hbs +17 -17
- package/addon/components/customer/form.hbs +13 -2
- package/addon/components/customer/form.js +0 -56
- package/addon/components/driver/details.hbs +13 -19
- package/addon/components/driver/form.hbs +20 -35
- package/addon/components/driver/form.js +0 -58
- 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/modals/driver-form.hbs +2 -2
- package/addon/components/modals/reset-profile-credentials.hbs +23 -0
- package/addon/components/modals/reset-profile-credentials.js +70 -0
- package/addon/components/profile-identity-hint.hbs +13 -0
- package/addon/components/profile-identity-hint.js +49 -0
- package/addon/components/telematic/hub.hbs +1 -1
- package/addon/components/widget/live-fleet.hbs +8 -40
- package/addon/controllers/analytics/reports/index.js +5 -0
- package/addon/controllers/connectivity/devices/index.js +4 -0
- package/addon/controllers/connectivity/fuel-providers/index.js +6 -4
- package/addon/controllers/connectivity/sensors/index.js +4 -0
- package/addon/controllers/connectivity/telematics/index.js +4 -0
- package/addon/controllers/maintenance/equipment/index.js +11 -4
- package/addon/controllers/maintenance/inspection-forms/index.js +2 -2
- package/addon/controllers/maintenance/inspection-submissions/index.js +8 -2
- package/addon/controllers/maintenance/maintenances/index.js +4 -0
- package/addon/controllers/maintenance/parts/index.js +11 -4
- package/addon/controllers/maintenance/schedules/index.js +17 -4
- package/addon/controllers/maintenance/work-orders/index.js +11 -4
- package/addon/controllers/management/contacts/index.js +4 -0
- package/addon/controllers/management/drivers/index.js +8 -0
- package/addon/controllers/management/fleets/index.js +4 -0
- package/addon/controllers/management/fuel-reports/index.js +4 -0
- package/addon/controllers/management/fuel-transactions/index.js +9 -7
- package/addon/controllers/management/issues/index.js +4 -0
- package/addon/controllers/management/places/index.js +4 -0
- package/addon/controllers/management/vehicles/index.js +4 -0
- package/addon/controllers/management/vendors/index.js +4 -0
- package/addon/controllers/operations/orders/index/details.js +30 -1
- package/addon/controllers/operations/orders/index.js +7 -0
- package/addon/controllers/operations/service-rates/index.js +3 -0
- package/addon/controllers/settings/index.js +13 -0
- package/addon/controllers/settings/telematics.js +113 -0
- package/addon/extension.js +42 -8
- 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.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 +50 -89
- package/addon/services/driver-actions.js +98 -0
- package/addon/templates/settings/telematics.hbs +70 -0
- package/addon/utils/profile-login-actions.js +172 -0
- package/app/components/admin/telematics-settings.js +1 -0
- package/app/components/{modals/reset-customer-credentials.js → map/marker-card/driver.js} +1 -1
- package/app/components/map/marker-card/vehicle.js +1 -0
- package/app/components/modals/reset-profile-credentials.js +1 -0
- package/app/components/profile-identity-hint.js +1 -0
- package/app/controllers/settings/telematics.js +1 -0
- package/app/routes/settings/telematics.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/scripts/pest-bootstrap.php +12 -0
- package/server/config/telemetry.php +12 -0
- package/server/migrations/2026_09_21_000001_convert_profile_only_users_to_managed_accounts.php +132 -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/resources/views/mail/driver-credentials.blade.php +21 -0
- package/server/src/Auth/Schemas/FleetOps.php +104 -5
- package/server/src/Console/Commands/DrainTelematicInbox.php +3 -13
- package/server/src/Console/Commands/FixCustomerCompanies.php +1 -1
- package/server/src/Console/Commands/FixDriverCompanies.php +1 -1
- package/server/src/Console/Commands/ProcessOperationalAlerts.php +3 -3
- package/server/src/Console/Commands/PruneTelematicsData.php +318 -0
- package/server/src/Exceptions/ProfileIdentityConflictException.php +34 -0
- package/server/src/Http/Controllers/Api/v1/CustomerController.php +14 -0
- package/server/src/Http/Controllers/Api/v1/DriverController.php +56 -39
- 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 +16 -17
- package/server/src/Http/Controllers/Internal/v1/CustomerController.php +54 -4
- 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 +204 -162
- package/server/src/Http/Controllers/Internal/v1/FleetOpsLookupController.php +47 -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 +178 -27
- 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/Http/Requests/CreateDriverRequest.php +6 -2
- package/server/src/Http/Requests/Internal/CreateDriverRequest.php +9 -18
- package/server/src/Http/Resources/v1/Contact.php +3 -0
- package/server/src/Http/Resources/v1/Driver.php +3 -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/Mail/DriverCredentialsMail.php +55 -0
- package/server/src/Models/Contact.php +55 -90
- package/server/src/Models/Sensor.php +3 -5
- package/server/src/Observers/ContactObserver.php +2 -22
- package/server/src/Observers/DriverObserver.php +5 -6
- package/server/src/Orchestration/Engines/VroomOrchestrationEngine.php +9 -1
- package/server/src/Providers/FleetOpsServiceProvider.php +18 -0
- package/server/src/Support/Ai/Capabilities/AbstractFleetOpsAICapability.php +62 -5
- package/server/src/Support/Ai/Capabilities/AssetStatusCapability.php +24 -5
- package/server/src/Support/Ai/Capabilities/CreateOrderPreviewCapability.php +6 -2
- package/server/src/Support/Ai/Capabilities/OrderInsightsCapability.php +40 -7
- package/server/src/Support/Ai/Capabilities/SearchResourcesCapability.php +86 -24
- package/server/src/Support/Ai/FleetOpsAiConsoleCommands.php +122 -0
- package/server/src/Support/Ai/Tools/CreateOrderTool.php +86 -0
- package/server/src/Support/Ai/Tools/ImportOrdersTool.php +53 -0
- package/server/src/Support/Ai/Tools/OptimizeOrderRouteTool.php +70 -0
- package/server/src/Support/Ai/Tools/SearchResourcesTool.php +73 -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/ProfileAccountManager.php +405 -0
- 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 +14 -1
- package/server/tests/AiOperationalQueryCapabilityTest.php +1 -0
- package/server/tests/AnalyticsRoutesTest.php +29 -2
- package/server/tests/ApiCustomerControllerContractsTest.php +21 -0
- package/server/tests/ApiDriverControllerContractsTest.php +102 -20
- package/server/tests/CommandContractsTest.php +4 -4
- package/server/tests/ControllerHelperContractsTest.php +3 -11
- package/server/tests/Feature/Http/AfaqyRealtimeIngestionTest.php +21 -1
- package/server/tests/Feature/Http/Api/DriverControllerAuthFlowsTest.php +36 -0
- package/server/tests/Feature/Http/Api/DriverControllerSessionHelpersTest.php +19 -6
- package/server/tests/Feature/Http/Api/ProfileOnlyUserConversionMigrationTest.php +201 -0
- package/server/tests/Feature/Http/Api/TelematicsRetentionIndexMigrationTest.php +115 -0
- package/server/tests/Feature/Http/Internal/ContactControllerEndpointsTest.php +6 -4
- package/server/tests/Feature/Http/Internal/CustomerControllerCredentialsTest.php +6 -2
- package/server/tests/Feature/Http/Internal/DriverControllerContractsTest.php +23 -0
- package/server/tests/Feature/Http/Internal/DriverControllerCreateRecordTest.php +42 -17
- package/server/tests/Feature/Http/Internal/DriverControllerExistingUserAdoptionTest.php +168 -277
- package/server/tests/Feature/Http/Internal/DriverControllerLoginManagementTest.php +716 -0
- package/server/tests/Feature/Http/Internal/OrderControllerContractsTest.php +10 -3
- package/server/tests/Feature/Http/Internal/OrderControllerImportFromFilesTest.php +18 -0
- package/server/tests/Feature/Http/Internal/OrderControllerTenantScopingTest.php +411 -0
- package/server/tests/Feature/Http/Internal/OrderControllerUpstreamNotFoundTest.php +8 -20
- package/server/tests/Feature/Http/Internal/SettingControllerHelpersTest.php +71 -0
- package/server/tests/Feature/Http/Internal/TelematicsStorageDeadlinesTest.php +119 -0
- package/server/tests/InternalCustomerControllerContractsTest.php +32 -1
- package/server/tests/InternalImportExportControllerContractsTest.php +5 -8
- package/server/tests/ModelAccessorContractsTest.php +82 -20
- package/server/tests/NavigatorControllerContractsTest.php +36 -4
- package/server/tests/NotificationAndMailContractsTest.php +31 -0
- package/server/tests/ObserverContractsTest.php +28 -3
- package/server/tests/OrchestratorConsumableApiTest.php +42 -0
- package/server/tests/ProviderContractsTest.php +10 -0
- package/server/tests/ReportSchemaContractsTest.php +120 -6
- package/server/tests/RequestContractsTest.php +19 -11
- 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/SupportJobAndAiCoverageTest.php +3 -3
- package/server/tests/TelematicControllerContractsTest.php +22 -4
- package/server/tests/Unit/Console/Commands/ProcessOperationalAlertsCommandTest.php +2 -2
- package/server/tests/Unit/Console/PruneTelematicsDataCommandTest.php +353 -0
- package/server/tests/Unit/Jobs/DispatchTelematicsRetentionJobsTest.php +114 -0
- package/server/tests/Unit/Jobs/PruneTelematicsDataJobTest.php +60 -0
- package/server/tests/Unit/Models/ContactCustomerUserTest.php +90 -14
- package/server/tests/Unit/Models/ContactTest.php +48 -5
- package/server/tests/Unit/Models/SensorTest.php +2 -2
- package/server/tests/Unit/Models/SmallModelSurfacesTest.php +31 -32
- package/server/tests/Unit/Observers/ObserverListenerSeamsTest.php +7 -2
- package/server/tests/Unit/Orchestration/VroomEngineTransportAndSettingsTest.php +20 -0
- package/server/tests/Unit/Providers/FleetOpsAiRegistrationTest.php +15 -2
- package/server/tests/Unit/Support/Ai/AssetStatusCapabilityQueriesTest.php +42 -0
- package/server/tests/Unit/Support/Ai/Capabilities/OrderInsightsCapabilityTest.php +19 -1
- package/server/tests/Unit/Support/Ai/Capabilities/SearchResourcesCapabilityTest.php +85 -1
- package/server/tests/Unit/Support/Ai/FleetOpsAiConsoleCommandsTest.php +31 -0
- package/server/tests/Unit/Support/Ai/Tools/FleetOpsAiToolsTest.php +246 -0
- package/server/tests/Unit/Support/AiCapabilityPermissionsTest.php +3 -3
- 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/ProfileAccountManagerTest.php +643 -0
- 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 +85 -2
- package/translations/uk-ua.yaml +3475 -0
- package/addon/components/modals/reset-customer-credentials.hbs +0 -18
- package/addon/components/modals/reset-customer-credentials.js +0 -55
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
use Fleetbase\FleetOps\Support\Telematics\Retention\RetentionPolicy;
|
|
4
|
+
use Illuminate\Support\Carbon;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* RetentionPolicy combines administrator policy with allowed company history
|
|
8
|
+
* preferences, enforces maximums, and caches policies for long-lived workers.
|
|
9
|
+
*/
|
|
10
|
+
function fleetopsRetentionResolver(array $system, array $company, ?array &$calls = null): void
|
|
11
|
+
{
|
|
12
|
+
$calls = [];
|
|
13
|
+
RetentionPolicy::$settingsResolver = function (string $scope, string $key, mixed $default, ?string $companyUuid) use ($system, $company, &$calls) {
|
|
14
|
+
$calls[] = [$scope, $key, $companyUuid];
|
|
15
|
+
expect($key)->toBe(RetentionPolicy::SETTING_KEY);
|
|
16
|
+
|
|
17
|
+
return $scope === 'system' ? $system : ($company[$companyUuid] ?? $default);
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
beforeEach(function () {
|
|
22
|
+
RetentionPolicy::flush();
|
|
23
|
+
RetentionPolicy::$settingsResolver = null;
|
|
24
|
+
config(['telematics.telemetry' => ['event_retention_days' => 45, 'processed_retention_hours' => 48, 'log_telemetry_activity' => true, 'poll_queue' => 'default']]);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
afterEach(function () {
|
|
28
|
+
RetentionPolicy::flush();
|
|
29
|
+
RetentionPolicy::$settingsResolver = null;
|
|
30
|
+
Carbon::setTestNow();
|
|
31
|
+
config(['telematics.telemetry' => []]);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('defaults come from package config, overridden by the admin setting, with everything clamped', function () {
|
|
35
|
+
fleetopsRetentionResolver([], []);
|
|
36
|
+
expect(RetentionPolicy::defaults())->toBe([
|
|
37
|
+
'event_retention_days' => 45,
|
|
38
|
+
'event_compact_after_days' => 7,
|
|
39
|
+
'position_retention_days' => 90,
|
|
40
|
+
'processed_retention_hours' => 48,
|
|
41
|
+
'quarantine_retention_days' => 7,
|
|
42
|
+
'sync_run_retention_days' => 7,
|
|
43
|
+
'max_event_retention_days' => 0,
|
|
44
|
+
'max_position_retention_days' => 0,
|
|
45
|
+
'log_telemetry_activity' => true,
|
|
46
|
+
]);
|
|
47
|
+
|
|
48
|
+
RetentionPolicy::flush();
|
|
49
|
+
fleetopsRetentionResolver([
|
|
50
|
+
'event_retention_days' => 99999,
|
|
51
|
+
'event_compact_after_days' => '',
|
|
52
|
+
'position_retention_days' => 0,
|
|
53
|
+
'quarantine_retention_days' => -5,
|
|
54
|
+
'processed_retention_hours' => null,
|
|
55
|
+
'log_telemetry_activity' => 'no',
|
|
56
|
+
'ignored' => 'value',
|
|
57
|
+
], []);
|
|
58
|
+
$defaults = RetentionPolicy::defaults();
|
|
59
|
+
expect($defaults['event_retention_days'])->toBe(3650)
|
|
60
|
+
->and($defaults['event_compact_after_days'])->toBe(7)
|
|
61
|
+
->and($defaults['position_retention_days'])->toBe(0)
|
|
62
|
+
->and($defaults['quarantine_retention_days'])->toBe(1)
|
|
63
|
+
->and($defaults['processed_retention_hours'])->toBe(48)
|
|
64
|
+
->and($defaults['log_telemetry_activity'])->toBeFalse()
|
|
65
|
+
->and($defaults)->not->toHaveKey('ignored')
|
|
66
|
+
->and(RetentionPolicy::keys())->toBe(array_keys(RetentionPolicy::FALLBACKS));
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test('company policies layer over the defaults and are cached until flushed', function () {
|
|
70
|
+
fleetopsRetentionResolver(['position_retention_days' => 30], ['company-1' => ['event_retention_days' => 10, 'log_telemetry_activity' => false]], $calls);
|
|
71
|
+
|
|
72
|
+
$policy = RetentionPolicy::forCompany('company-1');
|
|
73
|
+
expect($policy->get('event_retention_days'))->toBe(10)
|
|
74
|
+
->and($policy->get('position_retention_days'))->toBe(30)
|
|
75
|
+
->and($policy->get('processed_retention_hours'))->toBe(48)
|
|
76
|
+
->and($policy->logsTelemetryActivity())->toBeTrue()
|
|
77
|
+
->and($policy->toArray())->toHaveKeys(RetentionPolicy::keys())
|
|
78
|
+
->and(RetentionPolicy::forCompany('company-1'))->toBe($policy)
|
|
79
|
+
->and(RetentionPolicy::forCompany(null)->toArray())->toBe(RetentionPolicy::defaults())
|
|
80
|
+
->and(RetentionPolicy::forCompany('company-2')->get('event_retention_days'))->toBe(45)
|
|
81
|
+
->and(array_column($calls, 0))->toBe(['system', 'company', 'company']);
|
|
82
|
+
|
|
83
|
+
RetentionPolicy::flush('company-1');
|
|
84
|
+
RetentionPolicy::forCompany('company-1');
|
|
85
|
+
RetentionPolicy::forCompany('company-2');
|
|
86
|
+
expect(count($calls))->toBe(4);
|
|
87
|
+
|
|
88
|
+
RetentionPolicy::flush();
|
|
89
|
+
RetentionPolicy::forCompany('company-2');
|
|
90
|
+
expect(array_column($calls, 0))->toBe(['system', 'company', 'company', 'company', 'system', 'company']);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test('company history respects admin maximums and cannot override infrastructure or logging', function () {
|
|
94
|
+
fleetopsRetentionResolver([
|
|
95
|
+
'event_retention_days' => 0,
|
|
96
|
+
'position_retention_days' => 90,
|
|
97
|
+
'max_event_retention_days' => 30,
|
|
98
|
+
'max_position_retention_days' => 45,
|
|
99
|
+
'log_telemetry_activity' => false,
|
|
100
|
+
], [
|
|
101
|
+
'company-1' => [
|
|
102
|
+
'event_retention_days' => 0,
|
|
103
|
+
'position_retention_days' => 120,
|
|
104
|
+
'max_event_retention_days' => 0,
|
|
105
|
+
'max_position_retention_days' => 0,
|
|
106
|
+
'event_compact_after_days' => 0,
|
|
107
|
+
'processed_retention_hours' => 0,
|
|
108
|
+
'quarantine_retention_days' => 0,
|
|
109
|
+
'sync_run_retention_days' => 0,
|
|
110
|
+
'log_telemetry_activity' => true,
|
|
111
|
+
],
|
|
112
|
+
'company-2' => ['event_retention_days' => 5, 'position_retention_days' => 15],
|
|
113
|
+
]);
|
|
114
|
+
|
|
115
|
+
$policy = RetentionPolicy::forCompany('company-1');
|
|
116
|
+
expect($policy->get('event_retention_days'))->toBe(30)
|
|
117
|
+
->and($policy->get('position_retention_days'))->toBe(45)
|
|
118
|
+
->and($policy->get('event_compact_after_days'))->toBe(7)
|
|
119
|
+
->and($policy->get('processed_retention_hours'))->toBe(48)
|
|
120
|
+
->and($policy->get('quarantine_retention_days'))->toBe(7)
|
|
121
|
+
->and($policy->get('sync_run_retention_days'))->toBe(7)
|
|
122
|
+
->and($policy->logsTelemetryActivity())->toBeFalse()
|
|
123
|
+
->and(RetentionPolicy::forCompany('company-2')->get('event_retention_days'))->toBe(5)
|
|
124
|
+
->and(RetentionPolicy::forCompany('company-2')->get('position_retention_days'))->toBe(15)
|
|
125
|
+
->and(RetentionPolicy::forCompany('inherited')->get('event_retention_days'))->toBe(30)
|
|
126
|
+
->and(RetentionPolicy::forCompany('inherited')->get('position_retention_days'))->toBe(45)
|
|
127
|
+
->and(RetentionPolicy::forCompany(null)->get('event_retention_days'))->toBe(30);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test('unconfigured maximums preserve unlimited history and null preferences inherit defaults', function () {
|
|
131
|
+
fleetopsRetentionResolver([], ['company-1' => ['event_retention_days' => 0, 'position_retention_days' => null]]);
|
|
132
|
+
|
|
133
|
+
expect(RetentionPolicy::forCompany('company-1')->get('event_retention_days'))->toBe(0)
|
|
134
|
+
->and(RetentionPolicy::forCompany('company-1')->get('position_retention_days'))->toBe(90)
|
|
135
|
+
->and(RetentionPolicy::companyPreferences(['event_retention_days' => 'invalid', 'position_retention_days' => false]))->toBe([])
|
|
136
|
+
->and(RetentionPolicy::companyPreferences(['event_retention_days' => null, 'position_retention_days' => '', 'log_telemetry_activity' => true]))->toBe([]);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test('constrained preferences keep zero explicit when allowed and replace it when an administrator imposes a maximum', function () {
|
|
140
|
+
$preferences = ['event_retention_days' => 0, 'position_retention_days' => null];
|
|
141
|
+
expect(RetentionPolicy::constrainCompanyPreferences($preferences, RetentionPolicy::FALLBACKS))->toBe(['event_retention_days' => 0]);
|
|
142
|
+
|
|
143
|
+
$defaults = array_replace(RetentionPolicy::FALLBACKS, ['max_event_retention_days' => 90, 'max_position_retention_days' => 360]);
|
|
144
|
+
$bounded = RetentionPolicy::constrainCompanyPreferences($preferences, $defaults);
|
|
145
|
+
expect($bounded)->toBe(['event_retention_days' => 90])
|
|
146
|
+
->and(RetentionPolicy::constrainCompanyPreferences(['event_retention_days' => 30, 'position_retention_days' => 720], $defaults))->toBe(['event_retention_days' => 30, 'position_retention_days' => 360])
|
|
147
|
+
->and(RetentionPolicy::constrainCompanyPreferences([], $defaults))->toBe([])
|
|
148
|
+
->and(RetentionPolicy::constrainCompanyPreferences($bounded, RetentionPolicy::FALLBACKS))->toBe(['event_retention_days' => 90]);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
test('cutoffs, compaction and deletion rules follow the clamped values', function () {
|
|
152
|
+
Carbon::setTestNow('2026-09-23 12:00:00 UTC');
|
|
153
|
+
|
|
154
|
+
$policy = RetentionPolicy::fromArray(['event_retention_days' => 10, 'event_compact_after_days' => 10, 'processed_retention_hours' => 6, 'position_retention_days' => 0]);
|
|
155
|
+
expect($policy->deletesEvents())->toBeTrue()
|
|
156
|
+
->and($policy->compactsEvents())->toBeFalse()
|
|
157
|
+
->and($policy->cutoff('processed_retention_hours')?->toDateTimeString())->toBe('2026-09-23 06:00:00')
|
|
158
|
+
->and($policy->cutoff('event_retention_days')?->toDateTimeString())->toBe('2026-09-13 12:00:00')
|
|
159
|
+
->and($policy->cutoff('position_retention_days'))->toBeNull()
|
|
160
|
+
->and($policy->cutoff('unknown'))->toBeNull()
|
|
161
|
+
->and($policy->get('unknown'))->toBeNull();
|
|
162
|
+
|
|
163
|
+
expect(RetentionPolicy::fromArray(['event_retention_days' => 10, 'event_compact_after_days' => 3])->compactsEvents())->toBeTrue()
|
|
164
|
+
->and(RetentionPolicy::fromArray(['event_retention_days' => 0, 'event_compact_after_days' => 5])->compactsEvents())->toBeTrue()
|
|
165
|
+
->and(RetentionPolicy::fromArray(['event_retention_days' => 0, 'event_compact_after_days' => 5])->deletesEvents())->toBeFalse()
|
|
166
|
+
->and(RetentionPolicy::fromArray(['event_compact_after_days' => 0])->compactsEvents())->toBeFalse()
|
|
167
|
+
->and(RetentionPolicy::fromArray([], ['event_retention_days' => 12])->get('event_retention_days'))->toBe(12)
|
|
168
|
+
->and(RetentionPolicy::normalize(['log_telemetry_activity' => '1'], [])['log_telemetry_activity'])->toBeTrue();
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
test('a failing or malformed settings store falls back to the layer below', function () {
|
|
172
|
+
RetentionPolicy::$settingsResolver = fn () => throw new RuntimeException('settings unavailable');
|
|
173
|
+
expect(RetentionPolicy::forCompany('company-1')->get('event_retention_days'))->toBe(45);
|
|
174
|
+
|
|
175
|
+
RetentionPolicy::flush();
|
|
176
|
+
RetentionPolicy::$settingsResolver = fn () => 'not-an-array';
|
|
177
|
+
expect(RetentionPolicy::defaults()['processed_retention_hours'])->toBe(48);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
test('company lookups scope the session for the setting store and restore it afterwards', function () {
|
|
181
|
+
// Without a resolver the policy reaches Setting, which has no database here and throws.
|
|
182
|
+
app('session')->put('company', 'previous-company');
|
|
183
|
+
expect(RetentionPolicy::forCompany('company-9')->get('event_retention_days'))->toBe(45)
|
|
184
|
+
->and(app('session')->get('company'))->toBe('previous-company');
|
|
185
|
+
|
|
186
|
+
app('session')->forget('company');
|
|
187
|
+
RetentionPolicy::flush();
|
|
188
|
+
expect(RetentionPolicy::forCompany('company-9')->get('processed_retention_hours'))->toBe(48)
|
|
189
|
+
->and(app('session')->has('company'))->toBeFalse();
|
|
190
|
+
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
use Fleetbase\FleetOps\Support\Telematics\Retention\RetentionPolicy;
|
|
4
|
+
use Fleetbase\FleetOps\Support\Telematics\Retention\TelemetryActivity;
|
|
5
|
+
use Spatie\Activitylog\ActivityLogger;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Telemetry writes bypass the activity log unless an administrator enabled it, and
|
|
9
|
+
* still run when no activity logger is available.
|
|
10
|
+
*/
|
|
11
|
+
function fleetopsTelemetryActivityLogger(): ActivityLogger
|
|
12
|
+
{
|
|
13
|
+
$logger = new class extends ActivityLogger {
|
|
14
|
+
public int $suppressed = 0;
|
|
15
|
+
|
|
16
|
+
public function __construct()
|
|
17
|
+
{
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public function withoutLogs(Closure $callback): mixed
|
|
21
|
+
{
|
|
22
|
+
$this->suppressed++;
|
|
23
|
+
|
|
24
|
+
return $callback();
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
app()->instance(ActivityLogger::class, $logger);
|
|
28
|
+
|
|
29
|
+
return $logger;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
beforeEach(function () {
|
|
33
|
+
RetentionPolicy::flush();
|
|
34
|
+
config(['telematics.telemetry' => []]);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
afterEach(function () {
|
|
38
|
+
RetentionPolicy::flush();
|
|
39
|
+
RetentionPolicy::$settingsResolver = null;
|
|
40
|
+
app()->forgetInstance(ActivityLogger::class);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('telemetry activity follows the system policy and ignores legacy company overrides', function () {
|
|
44
|
+
RetentionPolicy::$settingsResolver = fn (string $scope, string $key, mixed $default, ?string $company) => $company === 'verbose' ? ['log_telemetry_activity' => true] : [];
|
|
45
|
+
$logger = fleetopsTelemetryActivityLogger();
|
|
46
|
+
|
|
47
|
+
expect(TelemetryActivity::run('quiet', fn () => 'saved'))->toBe('saved')
|
|
48
|
+
->and($logger->suppressed)->toBe(1)
|
|
49
|
+
->and(TelemetryActivity::run('verbose', fn () => 'saved'))->toBe('saved')
|
|
50
|
+
->and($logger->suppressed)->toBe(2)
|
|
51
|
+
->and(TelemetryActivity::run(null, fn () => 'system'))->toBe('system')
|
|
52
|
+
->and($logger->suppressed)->toBe(3);
|
|
53
|
+
|
|
54
|
+
RetentionPolicy::flush();
|
|
55
|
+
RetentionPolicy::$settingsResolver = fn (string $scope) => ['log_telemetry_activity' => $scope === 'system'];
|
|
56
|
+
|
|
57
|
+
expect(TelemetryActivity::run('quiet', fn () => 'logged'))->toBe('logged')
|
|
58
|
+
->and(TelemetryActivity::run('verbose', fn () => 'logged'))->toBe('logged')
|
|
59
|
+
->and(TelemetryActivity::run(null, fn () => 'system'))->toBe('system')
|
|
60
|
+
->and($logger->suppressed)->toBe(3);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test('telemetry writes still run when the activity logger cannot be resolved', function () {
|
|
64
|
+
RetentionPolicy::$settingsResolver = fn () => [];
|
|
65
|
+
app()->forgetInstance(ActivityLogger::class);
|
|
66
|
+
|
|
67
|
+
expect(TelemetryActivity::run('company-1', fn () => 'unlogged'))->toBe('unlogged');
|
|
68
|
+
});
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
if (!function_exists('Fleetbase\Models\session')) {
|
|
4
|
+
eval('namespace Fleetbase\Models; function session($key = null, $default = null) { if ($key === null) { return new class { public function has($k) { return \session($k) !== null; } public function get($k, $d = null) { return \session($k, $d); } public function missing($k) { return \session($k) === null; } }; } return \session($key, $default); }');
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
use Fleetbase\FleetOps\Models\Order;
|
|
8
|
+
use Fleetbase\FleetOps\Support\OrderTracker;
|
|
9
|
+
use Fleetbase\FleetOps\Tracking\TrackingIntelligenceService;
|
|
10
|
+
use Fleetbase\FleetOps\Tracking\TrackingOptions;
|
|
11
|
+
use Illuminate\Database\ConnectionResolver;
|
|
12
|
+
use Illuminate\Database\Eloquent\Model as EloquentModel;
|
|
13
|
+
use Illuminate\Database\SQLiteConnection;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Covers company tracking settings resolution for TrackingOptions: the
|
|
17
|
+
* order's company is used when there is no company session (queued jobs,
|
|
18
|
+
* console commands), and the session company remains the fallback.
|
|
19
|
+
*/
|
|
20
|
+
function fleetopsTrackingOptionsBoot(): SQLiteConnection
|
|
21
|
+
{
|
|
22
|
+
$connection = new SQLiteConnection(new PDO('sqlite::memory:'));
|
|
23
|
+
$resolver = new ConnectionResolver(['default' => $connection, 'mysql' => $connection]);
|
|
24
|
+
$resolver->setDefaultConnection('mysql');
|
|
25
|
+
EloquentModel::setConnectionResolver($resolver);
|
|
26
|
+
|
|
27
|
+
$connection->getSchemaBuilder()->create('settings', function ($blueprint) {
|
|
28
|
+
$blueprint->increments('id');
|
|
29
|
+
$blueprint->string('key')->nullable();
|
|
30
|
+
$blueprint->text('value')->nullable();
|
|
31
|
+
$blueprint->timestamps();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
$connection->table('settings')->insert([
|
|
35
|
+
['key' => 'company.company-a.tracking', 'value' => json_encode(['provider' => 'osrm', 'cache_ttl_seconds' => 15])],
|
|
36
|
+
['key' => 'company.company-b.tracking', 'value' => json_encode(['provider' => 'calculated', 'cache_ttl_seconds' => 45])],
|
|
37
|
+
]);
|
|
38
|
+
|
|
39
|
+
session(['company' => null]);
|
|
40
|
+
|
|
41
|
+
return $connection;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
test('tracking options read the given company settings regardless of session', function (?string $sessionCompany) {
|
|
45
|
+
fleetopsTrackingOptionsBoot();
|
|
46
|
+
session(['company' => $sessionCompany]);
|
|
47
|
+
|
|
48
|
+
$options = TrackingOptions::fromArray([], 'company-a');
|
|
49
|
+
|
|
50
|
+
expect($options->provider)->toBe('osrm')
|
|
51
|
+
->and($options->cacheTtlSeconds)->toBe(15);
|
|
52
|
+
|
|
53
|
+
// Explicit options still win over company settings
|
|
54
|
+
expect(TrackingOptions::fromArray(['provider' => 'google'], 'company-a')->provider)->toBe('google');
|
|
55
|
+
})->with([null, 'company-b']);
|
|
56
|
+
|
|
57
|
+
test('tracking options fall back to the session company when no company is given', function () {
|
|
58
|
+
fleetopsTrackingOptionsBoot();
|
|
59
|
+
session(['company' => 'company-b']);
|
|
60
|
+
|
|
61
|
+
$options = TrackingOptions::fromArray([]);
|
|
62
|
+
session(['company' => null]);
|
|
63
|
+
|
|
64
|
+
expect($options->provider)->toBe('calculated')
|
|
65
|
+
->and($options->cacheTtlSeconds)->toBe(45);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test('order tracker builds options from the order company', function () {
|
|
69
|
+
fleetopsTrackingOptionsBoot();
|
|
70
|
+
|
|
71
|
+
$service = new class extends TrackingIntelligenceService {
|
|
72
|
+
public ?TrackingOptions $received = null;
|
|
73
|
+
|
|
74
|
+
public function __construct()
|
|
75
|
+
{
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
public function track(Order $order, array|TrackingOptions $options = []): array
|
|
79
|
+
{
|
|
80
|
+
$this->received = $options;
|
|
81
|
+
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
app()->instance(TrackingIntelligenceService::class, $service);
|
|
86
|
+
|
|
87
|
+
$order = new Order();
|
|
88
|
+
$order->setRawAttributes(['uuid' => 'order-tracking-options', 'company_uuid' => 'company-a'], true);
|
|
89
|
+
|
|
90
|
+
(new OrderTracker($order))->toArray();
|
|
91
|
+
app()->forgetInstance(TrackingIntelligenceService::class);
|
|
92
|
+
|
|
93
|
+
expect($service->received)->toBeInstanceOf(TrackingOptions::class)
|
|
94
|
+
->and($service->received->provider)->toBe('osrm');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test('tracking remains available with configured defaults when the settings database is unavailable', function () {
|
|
98
|
+
$connection = fleetopsTrackingOptionsBoot();
|
|
99
|
+
$connection->getSchemaBuilder()->drop('settings');
|
|
100
|
+
$original = config('fleetops.tracking', []);
|
|
101
|
+
try {
|
|
102
|
+
config(['fleetops.tracking' => ['provider' => 'calculated', 'cache_ttl_seconds' => 17]]);
|
|
103
|
+
$options = TrackingOptions::fromArray([], 'uncached-unavailable-company');
|
|
104
|
+
expect($options->provider)->toBe('calculated')->and($options->cacheTtlSeconds)->toBe(17);
|
|
105
|
+
expect(TrackingOptions::fromArray(['provider' => 'osrm'], 'uncached-unavailable-company')->provider)->toBe('osrm');
|
|
106
|
+
} finally {
|
|
107
|
+
config(['fleetops.tracking' => $original]);
|
|
108
|
+
}
|
|
109
|
+
});
|
package/translations/en-us.yaml
CHANGED
|
@@ -114,6 +114,7 @@ menu:
|
|
|
114
114
|
maintenances: Maintenances
|
|
115
115
|
orchestrator: Orchestrator
|
|
116
116
|
orchestrator-settings: Orchestrator Settings
|
|
117
|
+
telematics-settings: Telematics
|
|
117
118
|
|
|
118
119
|
trailer:
|
|
119
120
|
navigation-description: Manage towed assets, towing connections, equipment, and telematics.
|
|
@@ -770,6 +771,9 @@ contact:
|
|
|
770
771
|
|
|
771
772
|
customer:
|
|
772
773
|
fields:
|
|
774
|
+
addresses: Addresses
|
|
775
|
+
no-addresses: This customer has no saved addresses.
|
|
776
|
+
primary-address: Primary
|
|
773
777
|
customer-details: Customer Details
|
|
774
778
|
select-address: Select Address
|
|
775
779
|
new-address: New Adddress
|
|
@@ -801,11 +805,9 @@ driver:
|
|
|
801
805
|
fields:
|
|
802
806
|
avatar: Avatar
|
|
803
807
|
driver-details: Driver Details
|
|
804
|
-
select-user: Select User
|
|
805
808
|
select-vehicle: Select Vehicle
|
|
806
809
|
upload-new-photo: Upload new photo
|
|
807
810
|
user-account: User Account
|
|
808
|
-
user-account-help-text: Each driver profile needs to be connected to a specific user account. This association is essential for handling the authentication process, ensuring that each driver can securely access and manage their profile.
|
|
809
811
|
vendor: Vendor
|
|
810
812
|
select-vendor: Select Vendor
|
|
811
813
|
driver-license: Drivers License
|
|
@@ -837,6 +839,40 @@ driver:
|
|
|
837
839
|
unassign-vehicle-body: This removes {driverName} from {vehicleName}. Order assignments are not changed.
|
|
838
840
|
unassign-vehicle-success: Unassigned {vehicleName} from {driverName}.
|
|
839
841
|
issue-title: Issue reported for {driverName}
|
|
842
|
+
|
|
843
|
+
profile-account:
|
|
844
|
+
staff-linked-helper: Linked to a team member account — manage email and phone from IAM.
|
|
845
|
+
will-link-to-staff: Will be linked to existing team member {name}.
|
|
846
|
+
actions:
|
|
847
|
+
reset-password: Reset Password
|
|
848
|
+
send-credentials: Send Credentials
|
|
849
|
+
deactivate-login: Deactivate Login
|
|
850
|
+
reactivate-login: Reactivate Login
|
|
851
|
+
convert-to-vendor: Convert to Vendor
|
|
852
|
+
prompts:
|
|
853
|
+
send-credentials-title: Send Login Credentials
|
|
854
|
+
send-credentials-body: Generate a new temporary password and send {name} their login credentials.
|
|
855
|
+
send-credentials-success: Login credentials sent to {name}.
|
|
856
|
+
deactivate-login-body: Deactivate the login for {name}. Their profile and history will be preserved.
|
|
857
|
+
deactivate-login-success: Login deactivated for {name}.
|
|
858
|
+
reactivate-login-body: Reactivate the login for {name}.
|
|
859
|
+
reactivate-login-success: Login reactivated for {name}.
|
|
860
|
+
send-portal-credentials-title: Send Portal Credentials
|
|
861
|
+
send-portal-credentials-body: Generate a new temporary password and email this contact their portal credentials.
|
|
862
|
+
send-portal-credentials-success: Portal credentials sent.
|
|
863
|
+
deactivate-portal-login-body: Deactivate portal access for this contact. Their profile and history will be preserved.
|
|
864
|
+
deactivate-portal-login-success: Portal login deactivated.
|
|
865
|
+
reactivate-portal-login-body: Reactivate portal access for this contact.
|
|
866
|
+
reactivate-portal-login-success: Portal login reactivated.
|
|
867
|
+
reset-password-title: Reset Login Credentials
|
|
868
|
+
reset-password-heading: You are about to reset the password for {name}
|
|
869
|
+
reset-password-body: Please enter the new password and confirm it below. You can optionally send the new credentials by selecting the checkbox.
|
|
870
|
+
reset-password-accept: Reset Credentials
|
|
871
|
+
reset-password-success: Password reset.
|
|
872
|
+
new-password: New Password
|
|
873
|
+
confirm-new-password: Confirm New Password
|
|
874
|
+
send-new-credentials: Send the new credentials to this account
|
|
875
|
+
|
|
840
876
|
device:
|
|
841
877
|
attachment:
|
|
842
878
|
title: Attached asset
|
|
@@ -2688,6 +2724,53 @@ route-list:
|
|
|
2688
2724
|
more-waypoints: more waypoints
|
|
2689
2725
|
|
|
2690
2726
|
settings:
|
|
2727
|
+
telematics:
|
|
2728
|
+
telematics-settings: Telematics Settings
|
|
2729
|
+
intro: Choose how long your organization keeps device events and position history within the limits set by your system administrator.
|
|
2730
|
+
use-system-default: Use system default
|
|
2731
|
+
history-policy-maximum: "Your administrator allows up to {days} days of history. Unlimited retention is not available."
|
|
2732
|
+
history-policy-unlimited: Your administrator allows unlimited history. Set the retention period to 0 to keep history forever.
|
|
2733
|
+
device-events: Device Events Retention
|
|
2734
|
+
event-retention-days: Keep device events for (days)
|
|
2735
|
+
event-retention-days-help: Events older than this are permanently deleted. Applies to telemetry updates and provider alerts alike.
|
|
2736
|
+
event-compact-after-days: Strip raw payloads after (days)
|
|
2737
|
+
event-compact-after-days-help: Events older than this keep their type, severity, location and normalized data, but the raw provider payload is removed. Raw payloads are the bulk of each event's size.
|
|
2738
|
+
compaction-warning: Raw payloads are only stripped from events that are kept. Set this lower than the event retention or set it to 0 to disable compaction.
|
|
2739
|
+
positions: Position History Retention
|
|
2740
|
+
position-retention-days: Keep positions for (days)
|
|
2741
|
+
position-retention-days-help: Vehicle and trailer position history older than this is permanently deleted. Route replay and history views only reach back this far.
|
|
2742
|
+
inbox: Delivery Inbox & Sync Run Retention
|
|
2743
|
+
processed-retention-hours: Keep processed deliveries for (hours)
|
|
2744
|
+
processed-retention-hours-help: Raw provider batches are stored encrypted until processed and kept briefly for replay and diagnostics. Each batch can be close to a megabyte.
|
|
2745
|
+
quarantine-retention-days: Keep quarantined deliveries for (days)
|
|
2746
|
+
quarantine-retention-days-help: Batches that could not be processed stay available for inspection and replay for this long.
|
|
2747
|
+
sync-run-retention-days: Keep sync run diagnostics for (days)
|
|
2748
|
+
sync-run-retention-days-help: One sync run row is recorded per connection per poll. In-flight runs are never removed.
|
|
2749
|
+
activity-logging: Telemetry Activity Logging
|
|
2750
|
+
log-telemetry-activity: Log telemetry activity
|
|
2751
|
+
log-telemetry-activity-help: Write telemetry-driven device, event and vehicle saves to the activity log. Off by default; every poll otherwise adds several activity rows per device.
|
|
2752
|
+
storage-usage: System Telematics Storage Usage
|
|
2753
|
+
table: Table
|
|
2754
|
+
rows: Rows
|
|
2755
|
+
estimated-rows: "{count} (estimated)"
|
|
2756
|
+
estimated-size: Estimated size
|
|
2757
|
+
oldest: Oldest row
|
|
2758
|
+
not-available: n/a
|
|
2759
|
+
raw-payload-rows: "{count} rows still carry raw payloads, {compactable} eligible for compaction now"
|
|
2760
|
+
refresh: Refresh
|
|
2761
|
+
run-cleanup: Run system cleanup
|
|
2762
|
+
run-cleanup-confirm: This queues telematics cleanup across all organizations, using the saved system policy and each organization's effective history preferences. Expired records are permanently deleted and cannot be recovered. Continue?
|
|
2763
|
+
cleanup-queued: Telematics cleanup has been queued across all organizations. Usage refreshes shortly; cleanup may still be running.
|
|
2764
|
+
cleanup-unavailable: System-wide telematics cleanup could not be confirmed. Please try again.
|
|
2765
|
+
usage-unavailable: Storage usage could not be loaded. Select Refresh to try again.
|
|
2766
|
+
space-reclaim-note: Usage includes all telematics data across the system. Row counts marked as estimated use database statistics. Sizes include table data and indexes. Deleting records frees space for reuse within the database; physical disk usage may not decrease immediately.
|
|
2767
|
+
settings-saved: Telematics settings saved.
|
|
2768
|
+
settings-unavailable: Telematics settings could not be loaded. Please try again.
|
|
2769
|
+
tables:
|
|
2770
|
+
device_events: Device events
|
|
2771
|
+
positions: Positions
|
|
2772
|
+
telematic_deliveries: Delivery inbox
|
|
2773
|
+
telematic_sync_runs: Sync runs
|
|
2691
2774
|
avatar-management: Avatar Management
|
|
2692
2775
|
custom-fields: Custom Fields
|
|
2693
2776
|
notifications:
|