@fleetbase/fleetops-engine 0.6.70 → 0.6.72
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 +18 -47
- package/addon/components/admin/tracking-page-settings.hbs +56 -0
- package/addon/components/admin/tracking-page-settings.js +67 -0
- package/addon/components/device/form.hbs +2 -2
- package/addon/components/driver/details.hbs +1 -1
- package/addon/components/driver/form.hbs +1 -1
- package/addon/components/equipment/form.hbs +1 -1
- package/addon/components/layout/fleet-ops-sidebar.js +11 -3
- package/addon/components/maintenance/form.hbs +3 -3
- package/addon/components/map/google-live-map.js +2 -2
- package/addon/components/map/leaflet-live-map.js +45 -32
- package/addon/components/orchestrator/phase-builder.js +2 -1
- package/addon/components/orchestrator-workbench.hbs +7 -1
- package/addon/components/orchestrator-workbench.js +16 -2
- 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 +5 -3
- package/addon/components/order/form/route.js +24 -1
- 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/service-rate/details.hbs +1 -1
- package/addon/components/service-rate/form.hbs +1 -1
- package/addon/components/tracking-page/full-view.hbs +276 -0
- package/addon/components/tracking-page/full-view.js +474 -0
- package/addon/components/tracking-page/locale-selector.js +30 -0
- package/addon/components/tracking-page/map.hbs +44 -0
- package/addon/components/tracking-page/map.js +328 -0
- package/addon/components/tracking-page/order-list.hbs +35 -0
- package/addon/components/tracking-page/public-view.hbs +60 -0
- package/addon/components/tracking-page/settings-preview.hbs +21 -0
- package/addon/components/tracking-page/settings-preview.js +23 -0
- package/addon/components/tracking-page/verify-panel.hbs +109 -0
- package/addon/components/tracking-page.hbs +142 -0
- package/addon/components/tracking-page.js +564 -0
- package/addon/components/trailer/form.hbs +2 -2
- package/addon/components/vehicle/form.hbs +3 -3
- package/addon/components/warranty/form.hbs +2 -2
- package/addon/components/widget/live-fleet.js +54 -6
- package/addon/components/widget/proof-of-delivery.hbs +49 -0
- package/addon/components/widget/proof-of-delivery.js +62 -0
- package/addon/components/work-order/form.hbs +3 -3
- package/addon/controllers/analytics/reports/index.js +10 -1
- package/addon/controllers/connectivity/devices/index/details.js +1 -0
- package/addon/controllers/connectivity/devices/index.js +8 -2
- package/addon/controllers/connectivity/events/index.js +31 -1
- package/addon/controllers/connectivity/sensors/index/details.js +1 -1
- package/addon/controllers/connectivity/sensors/index.js +37 -1
- package/addon/controllers/maintenance/equipment/index/details.js +2 -2
- package/addon/controllers/maintenance/equipment/index.js +28 -9
- 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 +49 -9
- package/addon/controllers/maintenance/maintenances/index/details.js +2 -0
- package/addon/controllers/maintenance/maintenances/index.js +20 -1
- package/addon/controllers/maintenance/parts/index/details.js +2 -2
- package/addon/controllers/maintenance/parts/index.js +28 -8
- package/addon/controllers/maintenance/schedules/index.js +33 -4
- package/addon/controllers/maintenance/work-orders/index/details.js +3 -3
- package/addon/controllers/maintenance/work-orders/index.js +39 -8
- package/addon/controllers/management/contacts/customers.js +13 -0
- package/addon/controllers/management/contacts/index.js +43 -1
- package/addon/controllers/management/drivers/index/details.js +1 -0
- package/addon/controllers/management/drivers/index.js +32 -2
- package/addon/controllers/management/fleets/index/details.js +1 -0
- package/addon/controllers/management/fleets/index.js +39 -1
- package/addon/controllers/management/fuel-reports/index.js +22 -2
- package/addon/controllers/management/fuel-transactions/index.js +43 -7
- package/addon/controllers/management/issues/index/details.js +1 -0
- package/addon/controllers/management/issues/index.js +22 -2
- package/addon/controllers/management/places/index.js +36 -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 +33 -2
- package/addon/controllers/management/vendors/index.js +26 -2
- package/addon/controllers/operations/orders/index/details.js +50 -7
- package/addon/controllers/operations/orders/index.js +59 -4
- package/addon/controllers/operations/scheduler/index.js +45 -14
- package/addon/controllers/operations/service-rates/index.js +15 -1
- package/addon/controllers/settings/index.js +6 -0
- package/addon/controllers/settings/map.js +75 -0
- package/addon/controllers/settings/orchestrator.js +8 -6
- package/addon/controllers/settings/tracking-page.js +212 -0
- package/addon/extension.js +97 -1
- package/addon/helpers/parcel-box-image.js +16 -0
- package/addon/routes/operations/orders/index/details.js +1 -0
- package/addon/routes/operations/orders/index/new.js +5 -4
- package/addon/routes/operations/scheduler/index.js +1 -1
- package/addon/routes/settings/tracking-page.js +31 -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/location.js +69 -21
- package/addon/services/maintenance-actions.js +1 -0
- package/addon/services/maintenance-schedule-actions.js +2 -1
- package/addon/services/map-settings.js +28 -0
- package/addon/services/order-actions.js +7 -0
- package/addon/services/order-allocation.js +1 -1
- 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/styles/fleetops-engine.css +1391 -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/map.hbs +46 -0
- package/addon/templates/settings/tracking-page.hbs +318 -0
- package/addon/utils/identity-cell-resource.js +2 -56
- package/addon/utils/map-default-view.js +132 -0
- package/addon/utils/normalize-order-config-flow.js +6 -1
- package/addon/utils/placeholder-images.js +4 -69
- package/addon/utils/resource-descriptors/assets.js +2 -57
- package/addon/utils/resource-descriptors/helpers.js +23 -122
- package/addon/utils/resource-descriptors/operations.js +2 -61
- package/addon/utils/resource-descriptors/people.js +3 -142
- package/addon/utils/resource-descriptors/shared.js +18 -0
- package/addon/utils/tracking-live-source.js +123 -0
- package/addon/utils/tracking-page-theme.js +123 -0
- package/app/components/admin/tracking-page-settings.js +1 -0
- package/app/components/tracking-page/full-view.js +1 -0
- package/app/components/tracking-page/locale-selector.js +1 -0
- package/app/components/tracking-page/map.js +1 -0
- package/app/components/tracking-page/order-list.js +1 -0
- package/app/components/tracking-page/public-view.js +1 -0
- package/app/components/tracking-page/settings-preview.js +1 -0
- package/app/components/tracking-page/verify-panel.js +1 -0
- package/app/components/tracking-page.js +1 -0
- package/app/components/widget/proof-of-delivery.js +1 -0
- package/app/controllers/settings/tracking-page.js +1 -0
- package/app/helpers/parcel-box-image.js +1 -0
- package/app/routes/settings/tracking-page.js +1 -0
- package/app/services/order-presentation.js +1 -0
- package/app/templates/settings/tracking-page.js +1 -0
- package/app/utils/map-default-view.js +1 -0
- package/app/utils/tracking-live-source.js +1 -0
- package/app/utils/tracking-page-theme.js +1 -0
- package/composer.json +2 -2
- package/extension.json +1 -1
- package/package.json +4 -4
- package/scripts/pest-bootstrap.php +4 -0
- package/server/config/fleetops.php +4 -0
- package/server/migrations/2026_10_08_000001_create_tracking_sessions_tables.php +51 -0
- package/server/migrations/2026_10_10_000001_add_trashed_index_to_device_events.php +40 -0
- package/server/migrations/2026_10_10_000002_add_trashed_index_to_positions.php +40 -0
- package/server/migrations/2026_10_12_000001_add_deleted_at_to_tracking_sessions_tables.php +32 -0
- package/server/resources/views/labels/default.php +2 -2
- package/server/resources/views/labels/entity-label.php +2 -2
- package/server/resources/views/labels/waypoint-label.php +2 -2
- package/server/src/Auth/Schemas/FleetOps.php +5 -0
- package/server/src/Console/Commands/ProcessOperationalAlerts.php +1 -0
- package/server/src/Console/Commands/PruneTelematicsData.php +101 -26
- package/server/src/Events/OrderChanged.php +257 -0
- package/server/src/Events/OrderDriverUnassigned.php +68 -0
- package/server/src/Exceptions/OrderEditLockedException.php +32 -0
- package/server/src/Expansions/CompanyExpansion.php +3 -2
- package/server/src/Expansions/UserExpansion.php +12 -10
- package/server/src/Http/Controllers/Api/v1/CustomerController.php +108 -18
- package/server/src/Http/Controllers/Api/v1/DriverController.php +95 -10
- package/server/src/Http/Controllers/Api/v1/EntityController.php +66 -0
- package/server/src/Http/Controllers/Api/v1/FleetController.php +10 -4
- package/server/src/Http/Controllers/Api/v1/OrderController.php +139 -36
- package/server/src/Http/Controllers/Api/v1/PayloadController.php +76 -8
- package/server/src/Http/Controllers/Api/v1/PlaceController.php +3 -3
- package/server/src/Http/Controllers/Api/v1/TrackingNumberController.php +6 -32
- package/server/src/Http/Controllers/Api/v1/VehicleController.php +5 -0
- package/server/src/Http/Controllers/Internal/v1/ContactController.php +3 -0
- package/server/src/Http/Controllers/Internal/v1/DriverController.php +10 -0
- package/server/src/Http/Controllers/Internal/v1/FleetController.php +16 -2
- package/server/src/Http/Controllers/Internal/v1/InspectionSubmissionController.php +13 -8
- package/server/src/Http/Controllers/Internal/v1/IssueController.php +2 -0
- package/server/src/Http/Controllers/Internal/v1/MaintenanceController.php +4 -2
- package/server/src/Http/Controllers/Internal/v1/OrchestrationController.php +93 -11
- package/server/src/Http/Controllers/Internal/v1/OrderController.php +118 -28
- package/server/src/Http/Controllers/Internal/v1/PositionController.php +22 -0
- package/server/src/Http/Controllers/Internal/v1/ProofController.php +55 -4
- package/server/src/Http/Controllers/Internal/v1/SettingController.php +303 -10
- package/server/src/Http/Controllers/Internal/v1/TrailerController.php +1 -0
- package/server/src/Http/Controllers/Internal/v1/VehicleController.php +1 -0
- package/server/src/Http/Controllers/Public/TrackingController.php +518 -0
- package/server/src/Http/Filter/ContactFilter.php +1 -1
- package/server/src/Http/Filter/InspectionFormFilter.php +23 -0
- package/server/src/Http/Filter/InspectionSubmissionFilter.php +23 -0
- package/server/src/Http/Filter/MaintenanceFilter.php +23 -0
- package/server/src/Http/Filter/OrderFilter.php +39 -4
- package/server/src/Http/Filter/ProofFilter.php +18 -0
- package/server/src/Http/Filter/RouteFilter.php +18 -0
- package/server/src/Http/Filter/TelematicFilter.php +23 -0
- package/server/src/Http/Filter/WarrantyFilter.php +23 -0
- package/server/src/Http/Requests/CancelOrderRequest.php +2 -1
- package/server/src/Http/Resources/v1/Concerns/ResolvesPublicRelationFields.php +14 -1
- package/server/src/Http/Resources/v1/Index/Customer.php +18 -0
- package/server/src/Http/Resources/v1/Index/Order.php +11 -2
- package/server/src/Http/Resources/v1/PublicOrderTracking.php +153 -0
- package/server/src/Http/Resources/v1/TrackingNumber.php +8 -34
- package/server/src/Http/Resources/v1/Zone.php +31 -23
- package/server/src/Jobs/FinalizeApiOrderCreation.php +3 -1
- package/server/src/Jobs/ProcessAllocationJob.php +16 -6
- package/server/src/Jobs/PublishTrackingUpdate.php +50 -0
- package/server/src/Listeners/HandleGeofenceEntered.php +31 -15
- package/server/src/Listeners/HandleOrderCanceled.php +9 -1
- package/server/src/Listeners/HandleUserRemovedFromCompany.php +2 -1
- package/server/src/Listeners/PublishTrackingUpdates.php +27 -0
- package/server/src/Mail/CustomerCredentialsMail.php +4 -2
- package/server/src/Models/AssetConnection.php +3 -0
- package/server/src/Models/Contact.php +3 -0
- package/server/src/Models/Device.php +28 -0
- package/server/src/Models/DeviceEvent.php +7 -0
- package/server/src/Models/Driver.php +20 -7
- package/server/src/Models/Entity.php +12 -4
- package/server/src/Models/Fleet.php +11 -32
- package/server/src/Models/FleetDriver.php +3 -0
- package/server/src/Models/FleetVehicle.php +3 -0
- package/server/src/Models/FuelReport.php +5 -13
- package/server/src/Models/Issue.php +4 -16
- package/server/src/Models/Order.php +234 -11
- package/server/src/Models/OrderConfig.php +129 -0
- package/server/src/Models/Payload.php +227 -35
- package/server/src/Models/Place.php +7 -1
- package/server/src/Models/ServiceArea.php +7 -0
- package/server/src/Models/ServiceRate.php +7 -17
- package/server/src/Models/TrackingNumber.php +109 -6
- package/server/src/Models/TrackingSession.php +33 -0
- package/server/src/Models/TrackingSessionGrant.php +22 -0
- package/server/src/Models/TrackingStatus.php +6 -0
- package/server/src/Models/Vehicle.php +21 -2
- package/server/src/Models/Vendor.php +7 -0
- package/server/src/Models/Waypoint.php +13 -4
- package/server/src/Notifications/OrderAssigned.php +2 -1
- package/server/src/Notifications/OrderCanceled.php +7 -1
- package/server/src/Notifications/OrderChanged.php +87 -0
- package/server/src/Notifications/OrderCompleted.php +2 -1
- package/server/src/Notifications/OrderDispatchFailed.php +2 -1
- package/server/src/Notifications/OrderDispatched.php +2 -1
- package/server/src/Notifications/OrderFailed.php +2 -1
- package/server/src/Notifications/OrderUnassigned.php +66 -0
- package/server/src/Notifications/WaypointCompleted.php +2 -1
- package/server/src/Observers/CompanyUserObserver.php +8 -7
- package/server/src/Observers/DriverObserver.php +6 -1
- package/server/src/Observers/OrderObserver.php +141 -1
- package/server/src/Observers/TrackingNumberObserver.php +18 -6
- package/server/src/Observers/UserObserver.php +2 -1
- package/server/src/Observers/VehicleObserver.php +8 -3
- package/server/src/Orchestration/Engines/RouteSequencingEngine.php +21 -3
- package/server/src/Orchestration/Engines/VroomOrchestrationEngine.php +38 -8
- package/server/src/Orchestration/OrchestrationEngineRegistry.php +61 -1
- package/server/src/Orchestration/Support/OrchestratorSettings.php +61 -0
- package/server/src/Orchestration/Support/RouteMetrics.php +165 -0
- package/server/src/Providers/EventServiceProvider.php +11 -0
- package/server/src/Providers/FleetOpsServiceProvider.php +13 -0
- package/server/src/Support/ApiCacheThrottle.php +76 -0
- package/server/src/Support/LiveOrderQuery.php +3 -1
- package/server/src/Support/OrderEdit.php +365 -0
- package/server/src/Support/OrderEditPolicy.php +292 -0
- package/server/src/Support/ProfileAccountManager.php +54 -1
- package/server/src/Support/ResolvesOrderServiceStops.php +5 -0
- package/server/src/Support/SocketChannels.php +346 -0
- package/server/src/Support/Telematics/TelematicService.php +7 -2
- package/server/src/Support/Telematics/Telemetry/Inbox.php +8 -1
- package/server/src/Support/TrackingChannel.php +55 -0
- package/server/src/Support/TrackingCode.php +242 -0
- package/server/src/Support/TrackingPage/TrackingAccess.php +356 -0
- package/server/src/Support/TrackingPage/TrackingPageConfig.php +264 -0
- package/server/src/Support/TrackingPage/TrackingRecipient.php +111 -0
- package/server/src/Support/TrackingPage/TrackingResolver.php +201 -0
- package/server/src/Support/TrackingPage/TrackingTarget.php +40 -0
- package/server/src/Support/TrackingPage/TrackingView.php +543 -0
- package/server/src/Support/TrackingPublisher.php +261 -0
- package/server/src/Support/TrackingScope.php +182 -0
- package/server/src/Support/TrackingUpdate.php +402 -0
- package/server/src/Support/Utils.php +15 -3
- package/server/src/Traits/HasTrackingNumber.php +2 -0
- package/server/src/routes.php +39 -7
- package/server/tests/ApiCustomerControllerContractsTest.php +54 -7
- package/server/tests/ApiDriverPasswordContractsTest.php +25 -21
- package/server/tests/ApiEntityControllerContractsTest.php +84 -0
- package/server/tests/ApiOrderControllerContractsTest.php +245 -0
- package/server/tests/ApiPayloadControllerContractsTest.php +121 -0
- package/server/tests/ApiPlaceControllerContractsTest.php +1 -1
- package/server/tests/ApiTrackingNumberControllerContractsTest.php +6 -9
- package/server/tests/CompactResourceSerializationTest.php +23 -59
- package/server/tests/ControllerFilterContractsTest.php +1 -1
- package/server/tests/CustomerContactIdentitySafetyTest.php +1 -1
- package/server/tests/EventContractsTest.php +26 -60
- package/server/tests/ExpansionContractsTest.php +15 -2
- package/server/tests/Feature/Http/Api/CustomerControllerHelperSeamsTest.php +29 -3
- package/server/tests/Feature/Http/Api/DriverControllerAuthFlowsTest.php +23 -0
- package/server/tests/Feature/Http/Api/OrderControllerNearbyFiltersTest.php +16 -16
- package/server/tests/Feature/Http/Api/OrderControllerQueryFiltersTest.php +41 -14
- package/server/tests/Feature/Http/Api/TrackingNumberControllerHelpersTest.php +57 -22
- package/server/tests/Feature/Http/Internal/DriverControllerCreateRecordTest.php +23 -9
- package/server/tests/Feature/Http/Internal/OrchestrationControllerContractsTest.php +171 -1
- package/server/tests/Feature/Http/Internal/OrderControllerActivityFlowsTest.php +72 -0
- package/server/tests/Feature/Http/Internal/OrderControllerContractsTest.php +110 -14
- package/server/tests/Feature/Http/Internal/OrderControllerCreateRecordTest.php +26 -0
- package/server/tests/Feature/Http/Internal/OrderControllerHelpersTest.php +7 -5
- package/server/tests/Feature/Http/Internal/PositionControllerReplayChannelTest.php +135 -0
- package/server/tests/Feature/Http/Internal/ProofControllerContractsTest.php +3 -3
- package/server/tests/Feature/Http/Internal/ProofControllerRecentTest.php +170 -0
- package/server/tests/Feature/Http/Public/TrackingControllerTest.php +495 -0
- package/server/tests/IndexCustomerPhotoTest.php +151 -0
- package/server/tests/ModelAccessorContractsTest.php +4 -3
- package/server/tests/NotificationAndMailContractsTest.php +5 -8
- package/server/tests/ObserverContractsTest.php +72 -10
- package/server/tests/OrderActivityFlowRegressionTest.php +3 -2
- package/server/tests/OrderConfigLifecycleTest.php +120 -0
- package/server/tests/OrderFilterExecutionTest.php +167 -2
- package/server/tests/ProcessAllocationJobContractsTest.php +20 -0
- package/server/tests/PublicOrderTrackingResourceTest.php +221 -0
- package/server/tests/QueueJobContractsTest.php +2 -1
- package/server/tests/RequestContractsTest.php +1 -1
- package/server/tests/RouteRegistrationExecutionTest.php +26 -0
- package/server/tests/RouteSequencingEngineTest.php +17 -0
- package/server/tests/SettingControllerContractsTest.php +110 -0
- package/server/tests/Support/TrackingPageDatabase.php +200 -0
- package/server/tests/TenantScopingTest.php +206 -0
- package/server/tests/TrackingPageSettingsTest.php +343 -0
- package/server/tests/Unit/Console/PruneTelematicsDataCommandTest.php +51 -0
- package/server/tests/Unit/Events/OrderDispatchFailedTest.php +2 -1
- package/server/tests/Unit/Http/Filter/ContactFilterAddressTest.php +61 -0
- package/server/tests/Unit/Http/Resources/IndexOrderResourceTest.php +30 -0
- package/server/tests/Unit/Jobs/FinalizeApiOrderCreationDispatchGuardTest.php +266 -0
- package/server/tests/Unit/Listeners/HandleGeofenceEnteredTest.php +182 -22
- package/server/tests/Unit/Listeners/HandleUserRemovedFromCompanyTest.php +5 -0
- package/server/tests/Unit/Models/DriverAssignVehicleTest.php +81 -0
- package/server/tests/Unit/Models/FleetTest.php +4 -3
- package/server/tests/Unit/Models/OrderCancelReasonTest.php +143 -0
- package/server/tests/Unit/Models/OrderPayloadConfigAndDistanceTest.php +60 -0
- package/server/tests/Unit/Models/OrderPayloadRouteTest.php +4 -2
- package/server/tests/Unit/Models/PayloadTest.php +18 -4
- package/server/tests/Unit/Models/ServiceRatePersistenceAndServicabilityTest.php +2 -2
- package/server/tests/Unit/Models/TrackingNumberTest.php +67 -6
- package/server/tests/Unit/Models/VehicleTest.php +16 -2
- package/server/tests/Unit/Models/WaypointTest.php +4 -3
- package/server/tests/Unit/Notifications/OrderChangeNotificationsTest.php +59 -0
- package/server/tests/Unit/Notifications/TerminalOrderNotificationsTest.php +3 -3
- package/server/tests/Unit/Observers/DriverDeletionCleanupTest.php +158 -0
- package/server/tests/Unit/Observers/FleetOpsCompanyUserAndServiceAreaObserversTest.php +20 -0
- package/server/tests/Unit/Observers/ObserverListenerSeamsTest.php +3 -3
- package/server/tests/Unit/Observers/OrderAssignmentObserverTest.php +100 -0
- package/server/tests/Unit/Observers/OrderDeleteCascadeTest.php +213 -0
- package/server/tests/Unit/Observers/VehicleObserverDeleteTest.php +67 -0
- package/server/tests/Unit/Orchestration/EngineSelectionAndRouteMetricsTest.php +336 -0
- package/server/tests/Unit/Orchestration/Engines/VroomOrchestrationEngineLifecycleTest.php +8 -1
- package/server/tests/Unit/Support/ApiCacheDependenciesTest.php +347 -0
- package/server/tests/Unit/Support/OrderEditPolicyTest.php +156 -0
- package/server/tests/Unit/Support/OrderOperationsTest.php +514 -0
- package/server/tests/Unit/Support/OsrmProofAndIssueFilterTest.php +4 -3
- package/server/tests/Unit/Support/ProfileAccountManagerTest.php +141 -0
- package/server/tests/Unit/Support/QuerySeamsTest.php +5 -1
- package/server/tests/Unit/Support/SocketChannelsTest.php +396 -0
- package/server/tests/Unit/Support/TrackingChannelTest.php +232 -0
- package/server/tests/Unit/Support/TrackingCodeTest.php +186 -0
- package/server/tests/Unit/Support/TrackingPage/TrackingAccessTest.php +200 -0
- package/server/tests/Unit/Support/TrackingPage/TrackingRecipientTest.php +51 -0
- package/server/tests/Unit/Support/TrackingPage/TrackingResolverTest.php +181 -0
- package/server/tests/Unit/Support/TrackingPage/TrackingViewTest.php +479 -0
- package/server/tests/Unit/Support/TrackingPublisherTest.php +425 -0
- package/server/tests/Unit/Support/TrackingUpdateTest.php +363 -0
- package/server/tests/Unit/Support/UtilsAdditionalTest.php +9 -0
- package/server/tests/Unit/Support/UtilsGeoMatrixAndVendorTest.php +25 -0
- package/server/tests/VehicleResourceContractsTest.php +46 -0
- package/server/tests/VroomOrchestrationEngineTest.php +34 -1
- package/server/tests/ZoneGeofenceSettingsResourceTest.php +121 -0
- package/translations/ar-ae.yml +274 -0
- package/translations/bg-bg.yaml +274 -0
- package/translations/en-us.yaml +347 -0
- package/translations/es-pa.yaml +274 -0
- package/translations/fr-fr.yaml +274 -0
- package/translations/mn-mn.yaml +274 -0
- package/translations/pt-br.yaml +274 -0
- package/translations/ru-ru.yaml +276 -2
- package/translations/uk-ua.yaml +275 -1
- package/translations/vi-vn.yaml +274 -0
- package/addon/components/cell/contact-identity.hbs +0 -1
- package/addon/components/cell/customer-identity.hbs +0 -1
- package/addon/components/cell/driver-identity.hbs +0 -1
- package/addon/components/cell/fleet-identity.hbs +0 -1
- package/addon/components/cell/order-identity.hbs +0 -1
- package/addon/components/cell/place-identity.hbs +0 -1
- package/addon/components/cell/vehicle-identity.hbs +0 -1
- package/addon/components/cell/vendor-identity.hbs +0 -1
- package/addon/components/contact/pill.hbs +0 -24
- package/addon/components/contact/summary.hbs +0 -1
- package/addon/components/customer/pill.hbs +0 -24
- package/addon/components/customer/summary.hbs +0 -1
- package/addon/components/driver/pill.hbs +0 -24
- package/addon/components/driver/summary.hbs +0 -1
- package/addon/components/fleet/pill.hbs +0 -24
- package/addon/components/fleet/summary.hbs +0 -1
- package/addon/components/order/pill.hbs +0 -24
- package/addon/components/order/summary.hbs +0 -1
- package/addon/components/place/pill.hbs +0 -24
- package/addon/components/place/summary.hbs +0 -1
- package/addon/components/select-option/contact.hbs +0 -12
- package/addon/components/select-option/customer.hbs +0 -12
- package/addon/components/select-option/driver.hbs +0 -12
- package/addon/components/select-option/fleet.hbs +0 -12
- package/addon/components/select-option/order.hbs +0 -12
- package/addon/components/select-option/place.hbs +0 -12
- package/addon/components/select-option/vehicle.hbs +0 -12
- package/addon/components/select-option/vendor.hbs +0 -12
- package/addon/components/vehicle/pill.hbs +0 -24
- package/addon/components/vehicle/summary.hbs +0 -1
- package/addon/components/vendor/pill.hbs +0 -24
- package/addon/components/vendor/summary.hbs +0 -1
- package/app/components/cell/contact-identity.js +0 -1
- package/app/components/cell/customer-identity.js +0 -1
- package/app/components/cell/driver-identity.js +0 -1
- package/app/components/cell/fleet-identity.js +0 -1
- package/app/components/cell/order-identity.js +0 -1
- package/app/components/cell/place-identity.js +0 -1
- package/app/components/cell/vehicle-identity.js +0 -1
- package/app/components/cell/vendor-identity.js +0 -1
- package/app/components/contact/pill.js +0 -1
- package/app/components/contact/summary.js +0 -1
- package/app/components/customer/pill.js +0 -1
- package/app/components/customer/summary.js +0 -1
- package/app/components/driver/pill.js +0 -1
- package/app/components/driver/summary.js +0 -1
- package/app/components/fleet/pill.js +0 -1
- package/app/components/fleet/summary.js +0 -1
- package/app/components/order/pill.js +0 -1
- package/app/components/order/summary.js +0 -1
- package/app/components/place/pill.js +0 -1
- package/app/components/place/summary.js +0 -1
- package/app/components/select-option/contact.js +0 -1
- package/app/components/select-option/customer.js +0 -1
- package/app/components/select-option/driver.js +0 -1
- package/app/components/select-option/fleet.js +0 -1
- package/app/components/select-option/order.js +0 -1
- package/app/components/select-option/place.js +0 -1
- package/app/components/select-option/vehicle.js +0 -1
- package/app/components/select-option/vendor.js +0 -1
- package/app/components/vehicle/pill.js +0 -1
- package/app/components/vehicle/summary.js +0 -1
- package/app/components/vendor/pill.js +0 -1
- package/app/components/vendor/summary.js +0 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\FleetOps\Http\Filter;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\Http\Filter\Filter;
|
|
6
|
+
|
|
7
|
+
class ProofFilter extends Filter
|
|
8
|
+
{
|
|
9
|
+
public function queryForInternal()
|
|
10
|
+
{
|
|
11
|
+
$this->builder->where('company_uuid', $this->session->get('company'));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
public function queryForPublic()
|
|
15
|
+
{
|
|
16
|
+
$this->queryForInternal();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\FleetOps\Http\Filter;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\Http\Filter\Filter;
|
|
6
|
+
|
|
7
|
+
class RouteFilter extends Filter
|
|
8
|
+
{
|
|
9
|
+
public function queryForInternal()
|
|
10
|
+
{
|
|
11
|
+
$this->builder->where('company_uuid', $this->session->get('company'));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
public function queryForPublic()
|
|
15
|
+
{
|
|
16
|
+
$this->queryForInternal();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\FleetOps\Http\Filter;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\Http\Filter\Filter;
|
|
6
|
+
|
|
7
|
+
class TelematicFilter extends Filter
|
|
8
|
+
{
|
|
9
|
+
public function queryForInternal()
|
|
10
|
+
{
|
|
11
|
+
$this->builder->where('company_uuid', $this->session->get('company'));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
public function queryForPublic()
|
|
15
|
+
{
|
|
16
|
+
$this->queryForInternal();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public function query(?string $searchQuery)
|
|
20
|
+
{
|
|
21
|
+
$this->builder->search($searchQuery);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\FleetOps\Http\Filter;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\Http\Filter\Filter;
|
|
6
|
+
|
|
7
|
+
class WarrantyFilter extends Filter
|
|
8
|
+
{
|
|
9
|
+
public function queryForInternal()
|
|
10
|
+
{
|
|
11
|
+
$this->builder->where('company_uuid', $this->session->get('company'));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
public function queryForPublic()
|
|
15
|
+
{
|
|
16
|
+
$this->queryForInternal();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public function query(?string $searchQuery)
|
|
20
|
+
{
|
|
21
|
+
$this->builder->search($searchQuery);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
namespace Fleetbase\FleetOps\Http\Resources\v1\Concerns;
|
|
4
4
|
|
|
5
5
|
use Fleetbase\Support\Http;
|
|
6
|
+
use Fleetbase\Support\RequestRelations;
|
|
7
|
+
use Illuminate\Database\Eloquent\Model;
|
|
6
8
|
use Illuminate\Http\Resources\MissingValue;
|
|
7
9
|
|
|
8
10
|
/**
|
|
@@ -30,6 +32,13 @@ trait ResolvesPublicRelationFields
|
|
|
30
32
|
* model actually defines are kept — a parent's expansion must never reach
|
|
31
33
|
* this model's loader, where it raises RelationNotFoundException.
|
|
32
34
|
*
|
|
35
|
+
* The result is handed to `loadMissing()`, and Eloquent loads a name by
|
|
36
|
+
* calling it as a method on a blank model, so a name that is merely a
|
|
37
|
+
* method (`with=saveInstance`) would run it. When core's RequestRelations
|
|
38
|
+
* is available an Eloquent model keeps only declared relations, each
|
|
39
|
+
* segment named as the model's method (`service_area` → `serviceArea`).
|
|
40
|
+
* Older core releases without it keep the root-method check below.
|
|
41
|
+
*
|
|
33
42
|
* @return array<int, string>
|
|
34
43
|
*/
|
|
35
44
|
protected function requestedRelations($request): array
|
|
@@ -46,6 +55,10 @@ trait ResolvesPublicRelationFields
|
|
|
46
55
|
|
|
47
56
|
$with = array_values(array_filter(array_map('strval', $with), 'strlen'));
|
|
48
57
|
|
|
58
|
+
if ($this->resource instanceof Model && class_exists(RequestRelations::class)) {
|
|
59
|
+
return RequestRelations::eagerLoads($this->resource, $with);
|
|
60
|
+
}
|
|
61
|
+
|
|
49
62
|
return array_values(array_filter($with, fn (string $relation): bool => $this->definesRelation($relation)));
|
|
50
63
|
}
|
|
51
64
|
|
|
@@ -77,7 +90,7 @@ trait ResolvesPublicRelationFields
|
|
|
77
90
|
* loaded on the public endpoints, so the key was absent unless `with` named
|
|
78
91
|
* it. Absent stays absent; it never becomes a string.
|
|
79
92
|
*
|
|
80
|
-
* @param array<int, string> $with
|
|
93
|
+
* @param array<int, string> $with the relation paths requestedRelations() kept, named as the model's methods
|
|
81
94
|
*/
|
|
82
95
|
protected function publicRelationObject(string $relation, array $with, \Closure $resource): mixed
|
|
83
96
|
{
|
|
@@ -2,8 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
namespace Fleetbase\FleetOps\Http\Resources\v1\Index;
|
|
4
4
|
|
|
5
|
+
use Fleetbase\FleetOps\Models\Contact;
|
|
6
|
+
use Fleetbase\FleetOps\Models\Customer as CustomerModel;
|
|
7
|
+
use Fleetbase\FleetOps\Models\Vendor;
|
|
5
8
|
use Fleetbase\Http\Resources\FleetbaseResource;
|
|
6
9
|
use Fleetbase\Support\Http;
|
|
10
|
+
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
|
7
11
|
|
|
8
12
|
/**
|
|
9
13
|
* Lightweight Customer resource for index views.
|
|
@@ -28,6 +32,20 @@ class Customer extends FleetbaseResource
|
|
|
28
32
|
'name' => $this->name,
|
|
29
33
|
'phone' => $this->phone ?? null,
|
|
30
34
|
'email' => $this->email ?? null,
|
|
35
|
+
'photo_url' => $this->resource instanceof Vendor ? $this->logo_url : ($this->photo_url ?? null),
|
|
31
36
|
];
|
|
32
37
|
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Eager loads the file each customer type's `photo_url` reads (a contact's
|
|
41
|
+
* photo, a vendor's logo), so listing orders does not query once per row.
|
|
42
|
+
*/
|
|
43
|
+
public static function withPhoto(MorphTo $relation): MorphTo
|
|
44
|
+
{
|
|
45
|
+
return $relation->morphWith([
|
|
46
|
+
Contact::class => ['photo'],
|
|
47
|
+
CustomerModel::class => ['photo'],
|
|
48
|
+
Vendor::class => ['logo'],
|
|
49
|
+
]);
|
|
50
|
+
}
|
|
33
51
|
}
|
|
@@ -94,12 +94,12 @@ class Order extends FleetbaseResource
|
|
|
94
94
|
|
|
95
95
|
// Latest status only, not full array
|
|
96
96
|
'latest_status' => $this->whenLoaded('trackingStatuses', function () {
|
|
97
|
-
$latest = $this->
|
|
97
|
+
$latest = $this->latestTrackingStatus();
|
|
98
98
|
|
|
99
99
|
return $latest ? $latest->status : 'created';
|
|
100
100
|
}),
|
|
101
101
|
'latest_status_code' => $this->whenLoaded('trackingStatuses', function () {
|
|
102
|
-
$latest = $this->
|
|
102
|
+
$latest = $this->latestTrackingStatus();
|
|
103
103
|
|
|
104
104
|
return $latest ? $latest->code : null;
|
|
105
105
|
}),
|
|
@@ -127,4 +127,13 @@ class Order extends FleetbaseResource
|
|
|
127
127
|
],
|
|
128
128
|
];
|
|
129
129
|
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* The newest loaded tracking status. The relation has no order, so the
|
|
133
|
+
* statuses are sorted here, newest insert first within the same second.
|
|
134
|
+
*/
|
|
135
|
+
protected function latestTrackingStatus(): mixed
|
|
136
|
+
{
|
|
137
|
+
return $this->trackingStatuses->sortBy([['created_at', 'desc'], ['id', 'desc']])->first();
|
|
138
|
+
}
|
|
130
139
|
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\FleetOps\Http\Resources\v1;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\FleetOps\Models\Order;
|
|
6
|
+
use Fleetbase\FleetOps\Support\Utils;
|
|
7
|
+
use Illuminate\Http\Resources\Json\JsonResource;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* What the public Track Order page gets for a tracking number.
|
|
11
|
+
*
|
|
12
|
+
* The lookup has no session, so whoever holds the tracking number sees this.
|
|
13
|
+
* It carries only what `order-tracking-lookup` renders: status, the tracking
|
|
14
|
+
* timeline, ETA and progress, the stop coordinates the map routes between,
|
|
15
|
+
* and the item list. Notes, meta, internal ids, files, rates, and customer
|
|
16
|
+
* and facilitator details stay out. The driver's position is included only
|
|
17
|
+
* while the order is under way.
|
|
18
|
+
*
|
|
19
|
+
* It extends `JsonResource`, not `FleetbaseResource`, so transformers that
|
|
20
|
+
* other extensions register for resources cannot add fields to it. Records are
|
|
21
|
+
* keyed by public id, which Ember Data needs to build them, so the page never
|
|
22
|
+
* learns an internal uuid.
|
|
23
|
+
*/
|
|
24
|
+
class PublicOrderTracking extends JsonResource
|
|
25
|
+
{
|
|
26
|
+
/**
|
|
27
|
+
* Never wrapped, whatever another resource set the shared wrapper to.
|
|
28
|
+
*
|
|
29
|
+
* @var string|null
|
|
30
|
+
*/
|
|
31
|
+
public static $wrap;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Statuses after which the order is no longer under way.
|
|
35
|
+
*/
|
|
36
|
+
public const FINISHED_STATUSES = ['completed', 'canceled', 'cancelled'];
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Transform the resource into an array.
|
|
40
|
+
*
|
|
41
|
+
* @param \Illuminate\Http\Request $request
|
|
42
|
+
*/
|
|
43
|
+
public function toArray($request): array
|
|
44
|
+
{
|
|
45
|
+
/** @var Order $order */
|
|
46
|
+
$order = $this->resource;
|
|
47
|
+
$trackingNumber = $order->trackingNumber;
|
|
48
|
+
$tracker = is_array($order->tracker_data) ? $order->tracker_data : [];
|
|
49
|
+
|
|
50
|
+
return [
|
|
51
|
+
'uuid' => $order->public_id,
|
|
52
|
+
'tracking' => data_get($trackingNumber, 'tracking_number'),
|
|
53
|
+
'status' => $order->status,
|
|
54
|
+
'has_driver_assigned' => (bool) $order->has_driver_assigned,
|
|
55
|
+
'tracking_number' => $trackingNumber ? [
|
|
56
|
+
'uuid' => $trackingNumber->public_id,
|
|
57
|
+
'tracking_number' => $trackingNumber->tracking_number,
|
|
58
|
+
] : null,
|
|
59
|
+
'tracking_statuses' => collect($order->trackingStatuses)->map(fn ($status) => [
|
|
60
|
+
'uuid' => $status->public_id,
|
|
61
|
+
'status' => $status->status,
|
|
62
|
+
'details' => $status->details,
|
|
63
|
+
'created_at' => $status->created_at,
|
|
64
|
+
])->values()->all(),
|
|
65
|
+
'payload' => $this->payload($order->payload),
|
|
66
|
+
'tracker_data' => $this->trackerData($tracker, static::isInProgress($order)),
|
|
67
|
+
'created_at' => $order->created_at,
|
|
68
|
+
];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Whether the order is under way: started, and not yet completed or canceled.
|
|
73
|
+
*/
|
|
74
|
+
public static function isInProgress(Order $order): bool
|
|
75
|
+
{
|
|
76
|
+
return (bool) $order->started && !in_array(strtolower((string) $order->status), static::FINISHED_STATUSES, true);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* The stops the map routes between and the items the page lists.
|
|
81
|
+
*/
|
|
82
|
+
protected function payload($payload): ?array
|
|
83
|
+
{
|
|
84
|
+
if (!$payload) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return [
|
|
89
|
+
'uuid' => $payload->public_id,
|
|
90
|
+
'pickup' => $this->place($payload->pickup),
|
|
91
|
+
'dropoff' => $this->place($payload->dropoff),
|
|
92
|
+
'waypoints' => collect($payload->waypoints)->map(fn ($place) => $this->place($place))->values()->all(),
|
|
93
|
+
'entities' => collect($payload->entities)->map(fn ($entity) => [
|
|
94
|
+
'uuid' => $entity->public_id,
|
|
95
|
+
'name' => $entity->name,
|
|
96
|
+
'description' => $entity->description,
|
|
97
|
+
'tracking' => data_get($entity, 'tracking'),
|
|
98
|
+
'price' => $entity->price,
|
|
99
|
+
'currency' => $entity->currency,
|
|
100
|
+
'photo_url' => data_get($entity, 'photo_url'),
|
|
101
|
+
])->values()->all(),
|
|
102
|
+
];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* A stop as the map needs it: its coordinates, with no address or contact.
|
|
107
|
+
*/
|
|
108
|
+
protected function place($place): ?array
|
|
109
|
+
{
|
|
110
|
+
if (!$place) {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return [
|
|
115
|
+
'uuid' => $place->public_id,
|
|
116
|
+
'location' => Utils::castPoint($place->location),
|
|
117
|
+
];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* The tracker fields the page reads; the driver's position only while under way.
|
|
122
|
+
*/
|
|
123
|
+
protected function trackerData(array $tracker, bool $inProgress): array
|
|
124
|
+
{
|
|
125
|
+
return [
|
|
126
|
+
'driver' => [
|
|
127
|
+
'location' => $inProgress ? data_get($tracker, 'driver.location') : null,
|
|
128
|
+
],
|
|
129
|
+
'progress' => [
|
|
130
|
+
'percentage' => data_get($tracker, 'progress.percentage'),
|
|
131
|
+
'completed_stops' => data_get($tracker, 'progress.completed_stops'),
|
|
132
|
+
],
|
|
133
|
+
'eta' => [
|
|
134
|
+
'active_stop_seconds' => data_get($tracker, 'eta.active_stop_seconds'),
|
|
135
|
+
'completion_at' => data_get($tracker, 'eta.completion_at'),
|
|
136
|
+
],
|
|
137
|
+
'active_stop' => $this->stop(data_get($tracker, 'active_stop')),
|
|
138
|
+
'next_stop' => $this->stop(data_get($tracker, 'next_stop')),
|
|
139
|
+
];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* A stop the page names under "Current/Next Destination".
|
|
144
|
+
*/
|
|
145
|
+
protected function stop($stop): ?array
|
|
146
|
+
{
|
|
147
|
+
if (!is_array($stop)) {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return ['address' => data_get($stop, 'address')];
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
namespace Fleetbase\FleetOps\Http\Resources\v1;
|
|
4
4
|
|
|
5
|
+
use Fleetbase\FleetOps\Support\TrackingCode;
|
|
5
6
|
use Fleetbase\FleetOps\Support\Utils;
|
|
6
7
|
use Fleetbase\Http\Resources\FleetbaseResource;
|
|
7
8
|
use Fleetbase\Support\Http;
|
|
@@ -30,47 +31,20 @@ class TrackingNumber extends FleetbaseResource
|
|
|
30
31
|
'status' => $this->last_status,
|
|
31
32
|
'status_code' => $this->last_status_code,
|
|
32
33
|
'qr_code' => $this->qr_code,
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
// decode endpoint or handing out uuids generally.
|
|
40
|
-
//
|
|
41
|
-
// `when()` omits the key entirely when false — it is absent, not null — so a
|
|
42
|
-
// production response is byte-identical to before.
|
|
43
|
-
'qr_code_content' => $this->when(static::exposesQrCodeContent(), fn () => $this->owner_uuid),
|
|
34
|
+
// A value that scans as this tracking number: the QR content current labels
|
|
35
|
+
// print (see TrackingCode). It names the tracking number and the subject's
|
|
36
|
+
// public id, both already in this resource, so it is safe to publish, and lets
|
|
37
|
+
// clients that print their own labels, or cannot decode a PNG, use the code.
|
|
38
|
+
// Labels printed before it encode the owner uuid; resolvers accept both.
|
|
39
|
+
'qr_code_content' => $this->when($this->tracking_number, fn () => TrackingCode::qrContent($this->tracking_number, Utils::get($this->owner, 'public_id'))),
|
|
44
40
|
'barcode' => $this->barcode,
|
|
45
|
-
'url' =>
|
|
41
|
+
'url' => $this->when($this->tracking_number, fn () => TrackingCode::pageUrl($this->tracking_number, $this->company_uuid)),
|
|
46
42
|
'type' => Utils::getTypeFromClassName($this->owner_type),
|
|
47
43
|
'updated_at' => $this->updated_at,
|
|
48
44
|
'created_at' => $this->created_at,
|
|
49
45
|
];
|
|
50
46
|
}
|
|
51
47
|
|
|
52
|
-
/**
|
|
53
|
-
* Whether the QR code's decoded content may be published.
|
|
54
|
-
*
|
|
55
|
-
* Debug mode only, and fails closed: any failure to determine the debug state — no
|
|
56
|
-
* container, an application without the accessor — answers false rather than
|
|
57
|
-
* defaulting to exposure.
|
|
58
|
-
*/
|
|
59
|
-
protected static function exposesQrCodeContent(): bool
|
|
60
|
-
{
|
|
61
|
-
try {
|
|
62
|
-
$app = app();
|
|
63
|
-
|
|
64
|
-
if (!is_object($app) || !method_exists($app, 'hasDebugModeEnabled')) {
|
|
65
|
-
return false;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return (bool) $app->hasDebugModeEnabled();
|
|
69
|
-
} catch (\Throwable $e) {
|
|
70
|
-
return false;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
48
|
/**
|
|
75
49
|
* Transform the resource into an webhook payload.
|
|
76
50
|
*
|
|
@@ -17,19 +17,23 @@ class Zone extends FleetbaseResource
|
|
|
17
17
|
public function toArray($request)
|
|
18
18
|
{
|
|
19
19
|
return $this->withCustomFields([
|
|
20
|
-
'id'
|
|
21
|
-
'public_id'
|
|
22
|
-
'uuid'
|
|
23
|
-
'service_area_uuid'
|
|
24
|
-
'name'
|
|
25
|
-
'description'
|
|
26
|
-
'center'
|
|
27
|
-
'border'
|
|
28
|
-
'color'
|
|
29
|
-
'stroke_color'
|
|
30
|
-
'
|
|
31
|
-
'
|
|
32
|
-
'
|
|
20
|
+
'id' => $this->when(Http::isInternalRequest(), $this->id, $this->public_id),
|
|
21
|
+
'public_id' => $this->when(Http::isInternalRequest(), $this->public_id),
|
|
22
|
+
'uuid' => $this->when(Http::isInternalRequest(), $this->uuid),
|
|
23
|
+
'service_area_uuid' => $this->when(Http::isInternalRequest(), $this->service_area_uuid),
|
|
24
|
+
'name' => $this->name,
|
|
25
|
+
'description' => $this->description,
|
|
26
|
+
'center' => $this->location,
|
|
27
|
+
'border' => $this->border,
|
|
28
|
+
'color' => $this->color,
|
|
29
|
+
'stroke_color' => $this->stroke_color,
|
|
30
|
+
'trigger_on_entry' => $this->trigger_on_entry,
|
|
31
|
+
'trigger_on_exit' => $this->trigger_on_exit,
|
|
32
|
+
'dwell_threshold_minutes' => $this->dwell_threshold_minutes,
|
|
33
|
+
'speed_limit_kmh' => $this->speed_limit_kmh,
|
|
34
|
+
'status' => $this->status,
|
|
35
|
+
'updated_at' => $this->updated_at,
|
|
36
|
+
'created_at' => $this->created_at,
|
|
33
37
|
]);
|
|
34
38
|
}
|
|
35
39
|
|
|
@@ -41,16 +45,20 @@ class Zone extends FleetbaseResource
|
|
|
41
45
|
public function toWebhookPayload()
|
|
42
46
|
{
|
|
43
47
|
return [
|
|
44
|
-
'id'
|
|
45
|
-
'name'
|
|
46
|
-
'description'
|
|
47
|
-
'center'
|
|
48
|
-
'border'
|
|
49
|
-
'color'
|
|
50
|
-
'stroke_color'
|
|
51
|
-
'
|
|
52
|
-
'
|
|
53
|
-
'
|
|
48
|
+
'id' => $this->public_id,
|
|
49
|
+
'name' => $this->name,
|
|
50
|
+
'description' => $this->description,
|
|
51
|
+
'center' => $this->location,
|
|
52
|
+
'border' => $this->border,
|
|
53
|
+
'color' => $this->color,
|
|
54
|
+
'stroke_color' => $this->stroke_color,
|
|
55
|
+
'trigger_on_entry' => $this->trigger_on_entry,
|
|
56
|
+
'trigger_on_exit' => $this->trigger_on_exit,
|
|
57
|
+
'dwell_threshold_minutes' => $this->dwell_threshold_minutes,
|
|
58
|
+
'speed_limit_kmh' => $this->speed_limit_kmh,
|
|
59
|
+
'status' => $this->status,
|
|
60
|
+
'updated_at' => $this->updated_at,
|
|
61
|
+
'created_at' => $this->created_at,
|
|
54
62
|
];
|
|
55
63
|
}
|
|
56
64
|
}
|
|
@@ -38,7 +38,9 @@ class FinalizeApiOrderCreation implements ShouldQueue
|
|
|
38
38
|
$order->setPreliminaryDistanceAndTime();
|
|
39
39
|
$order->purchaseServiceQuote($serviceQuote);
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
// The order may have been dispatched or started while this job waited in the
|
|
42
|
+
// queue; dispatching it again would move its status backwards.
|
|
43
|
+
if ($this->shouldDispatch && $order->isAwaitingDispatch()) {
|
|
42
44
|
$order->dispatchWithActivity();
|
|
43
45
|
}
|
|
44
46
|
|
|
@@ -6,7 +6,7 @@ use Fleetbase\FleetOps\Models\Driver;
|
|
|
6
6
|
use Fleetbase\FleetOps\Models\Order;
|
|
7
7
|
use Fleetbase\FleetOps\Models\Vehicle;
|
|
8
8
|
use Fleetbase\FleetOps\Orchestration\OrchestrationEngineRegistry;
|
|
9
|
-
use Fleetbase\
|
|
9
|
+
use Fleetbase\FleetOps\Orchestration\Support\OrchestratorSettings;
|
|
10
10
|
use Illuminate\Bus\Queueable;
|
|
11
11
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
12
12
|
use Illuminate\Foundation\Bus\Dispatchable;
|
|
@@ -69,9 +69,17 @@ class ProcessAllocationJob implements ShouldQueue
|
|
|
69
69
|
return;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
$
|
|
72
|
+
$result = $registry->allocateWithFallback($this->engineId(), $orders, $vehicles, $this->allocationOptions());
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
if (!empty($result['summary']['fallback_reason'])) {
|
|
75
|
+
$this->logInfo(sprintf(
|
|
76
|
+
'[ProcessAllocationJob] Used the %s engine instead of %s for company %s: %s',
|
|
77
|
+
$result['summary']['engine'],
|
|
78
|
+
$result['summary']['requested_engine'],
|
|
79
|
+
$this->companyUuid,
|
|
80
|
+
$result['summary']['fallback_reason']
|
|
81
|
+
));
|
|
82
|
+
}
|
|
75
83
|
|
|
76
84
|
foreach ($result['assignments'] as $assignment) {
|
|
77
85
|
$order = $this->findOrderByPublicId($assignment['order_id']);
|
|
@@ -125,14 +133,16 @@ class ProcessAllocationJob implements ShouldQueue
|
|
|
125
133
|
|
|
126
134
|
protected function engineId(): string
|
|
127
135
|
{
|
|
128
|
-
return
|
|
136
|
+
return OrchestratorSettings::engineForCompany($this->companyUuid);
|
|
129
137
|
}
|
|
130
138
|
|
|
131
139
|
protected function allocationOptions(): array
|
|
132
140
|
{
|
|
141
|
+
$settings = OrchestratorSettings::forCompany($this->companyUuid);
|
|
142
|
+
|
|
133
143
|
return [
|
|
134
|
-
'max_travel_time' =>
|
|
135
|
-
'balance_workload' =>
|
|
144
|
+
'max_travel_time' => (int) $settings['max_travel_time_seconds'],
|
|
145
|
+
'balance_workload' => (bool) $settings['balance_workload'],
|
|
136
146
|
];
|
|
137
147
|
}
|
|
138
148
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\FleetOps\Jobs;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\FleetOps\Models\Order;
|
|
6
|
+
use Fleetbase\FleetOps\Support\TrackingPublisher;
|
|
7
|
+
use Fleetbase\FleetOps\Support\TrackingUpdate;
|
|
8
|
+
use Illuminate\Bus\Queueable;
|
|
9
|
+
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
10
|
+
use Illuminate\Foundation\Bus\Dispatchable;
|
|
11
|
+
use Illuminate\Queue\InteractsWithQueue;
|
|
12
|
+
use Illuminate\Support\Facades\Cache;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Builds and publishes an order's public tracking updates off the request path.
|
|
16
|
+
*
|
|
17
|
+
* Location jobs publish the position only, except that at most once per ETA interval they
|
|
18
|
+
* publish the full update instead so that customers' ETAs follow the vehicle.
|
|
19
|
+
*/
|
|
20
|
+
class PublishTrackingUpdate implements ShouldQueue
|
|
21
|
+
{
|
|
22
|
+
use Dispatchable;
|
|
23
|
+
use InteractsWithQueue;
|
|
24
|
+
use Queueable;
|
|
25
|
+
|
|
26
|
+
public $tries = 1;
|
|
27
|
+
public $timeout = 60;
|
|
28
|
+
|
|
29
|
+
public function __construct(public string $orderUuid, public string $reason = TrackingUpdate::REASON_STATUS, public ?string $dbConnection = null)
|
|
30
|
+
{
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public function handle(TrackingPublisher $publisher): int
|
|
34
|
+
{
|
|
35
|
+
$order = Order::on($this->dbConnection)->where('uuid', $this->orderUuid)->first();
|
|
36
|
+
if (!$order) {
|
|
37
|
+
return 0;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if ($this->reason !== TrackingUpdate::REASON_LOCATION) {
|
|
41
|
+
return $publisher->publishOrder($order, $this->reason);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (Cache::add('fleetops:tracking:eta:' . $order->uuid, 1, TrackingPublisher::ETA_INTERVAL)) {
|
|
45
|
+
return $publisher->publishOrder($order, TrackingUpdate::REASON_ETA);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return $publisher->publishLocation($order);
|
|
49
|
+
}
|
|
50
|
+
}
|