@fleetbase/fleetops-engine 0.6.71 → 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 +15 -18
- 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/form/route.hbs +1 -1
- package/addon/components/order/form/route.js +13 -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/operations/orders/index/details.js +19 -3
- package/addon/controllers/operations/scheduler/index.js +45 -14
- 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 +65 -1
- package/addon/helpers/parcel-box-image.js +16 -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/location.js +69 -21
- package/addon/services/map-settings.js +28 -0
- package/addon/services/order-allocation.js +1 -1
- package/addon/styles/fleetops-engine.css +1391 -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/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/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 +84 -24
- 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 +200 -9
- 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 +101 -2
- 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/OrderControllerContractsTest.php +110 -14
- 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/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/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 +287 -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
|
@@ -8,8 +8,11 @@ use Fleetbase\FleetOps\Events\OrderCanceled;
|
|
|
8
8
|
use Fleetbase\FleetOps\Events\OrderCompleted;
|
|
9
9
|
use Fleetbase\FleetOps\Events\OrderDispatched;
|
|
10
10
|
use Fleetbase\FleetOps\Events\OrderDriverAssigned;
|
|
11
|
+
use Fleetbase\FleetOps\Events\OrderDriverUnassigned;
|
|
11
12
|
use Fleetbase\FleetOps\Flow\Activity;
|
|
13
|
+
use Fleetbase\FleetOps\Notifications\OrderUnassigned;
|
|
12
14
|
use Fleetbase\FleetOps\Support\LabelPdf;
|
|
15
|
+
use Fleetbase\FleetOps\Support\OrderEditPolicy;
|
|
13
16
|
use Fleetbase\FleetOps\Support\OrderTracker;
|
|
14
17
|
use Fleetbase\FleetOps\Support\Utils;
|
|
15
18
|
use Fleetbase\FleetOps\Traits\HasTrackingNumber;
|
|
@@ -35,6 +38,7 @@ use Illuminate\Database\Eloquent\Relations\MorphTo;
|
|
|
35
38
|
use Illuminate\Database\Eloquent\Relations\Relation;
|
|
36
39
|
use Illuminate\Support\Carbon;
|
|
37
40
|
use Illuminate\Support\Collection;
|
|
41
|
+
use Illuminate\Support\Facades\Log;
|
|
38
42
|
use Illuminate\Support\Str;
|
|
39
43
|
use Spatie\Activitylog\LogOptions;
|
|
40
44
|
use Spatie\Activitylog\Traits\LogsActivity;
|
|
@@ -196,6 +200,38 @@ class Order extends Model
|
|
|
196
200
|
*/
|
|
197
201
|
protected $with = [];
|
|
198
202
|
|
|
203
|
+
/**
|
|
204
|
+
* Relation paths and tables the cached order lists embed, so a write to any
|
|
205
|
+
* of them invalidates those lists (fleetbase/core-api#301).
|
|
206
|
+
*
|
|
207
|
+
* They mirror OrderFilter::queryForInternal()'s eager loads and whereHas
|
|
208
|
+
* membership, the payload relation's own `with`, Payload's `$with` and the
|
|
209
|
+
* public query's loads. customer and facilitator are morphTo relations, so
|
|
210
|
+
* their tables (contacts, vendors, integrated_vendors) are named instead;
|
|
211
|
+
* a vendor loads its place, which payload.pickup already covers. files
|
|
212
|
+
* (customer photo, vendor logo) is left out: every upload writes it, and a
|
|
213
|
+
* new photo is set by writing the contact's or vendor's own row.
|
|
214
|
+
*
|
|
215
|
+
* @var string[]
|
|
216
|
+
*/
|
|
217
|
+
protected $apiCacheDependencies = [
|
|
218
|
+
'payload',
|
|
219
|
+
'payload.pickup',
|
|
220
|
+
'payload.dropoff',
|
|
221
|
+
'payload.return',
|
|
222
|
+
'payload.entities',
|
|
223
|
+
'payload.waypoints',
|
|
224
|
+
'payload.firstWaypointMarker.place',
|
|
225
|
+
'payload.lastWaypointMarker.place',
|
|
226
|
+
'trackingNumber',
|
|
227
|
+
'trackingStatuses',
|
|
228
|
+
'driverAssigned',
|
|
229
|
+
'vehicleAssigned',
|
|
230
|
+
'contacts',
|
|
231
|
+
'vendors',
|
|
232
|
+
'integrated_vendors',
|
|
233
|
+
];
|
|
234
|
+
|
|
199
235
|
/**
|
|
200
236
|
* The attributes that should be cast to native types.
|
|
201
237
|
*
|
|
@@ -244,6 +280,16 @@ class Order extends Model
|
|
|
244
280
|
'_key',
|
|
245
281
|
];
|
|
246
282
|
|
|
283
|
+
/**
|
|
284
|
+
* Set for one save: the driver assignment being saved sends no assignment notification.
|
|
285
|
+
*/
|
|
286
|
+
public bool $silentDriverAssignment = false;
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Set for one save: the driver taken off the order is not sent an unassigned push (they declined it themselves).
|
|
290
|
+
*/
|
|
291
|
+
public bool $quietDriverUnassignment = false;
|
|
292
|
+
|
|
247
293
|
/**
|
|
248
294
|
* Enforce a morph map.
|
|
249
295
|
*/
|
|
@@ -263,6 +309,31 @@ class Order extends Model
|
|
|
263
309
|
);
|
|
264
310
|
}
|
|
265
311
|
|
|
312
|
+
/**
|
|
313
|
+
* Bulk removal deletes the matched orders one at a time instead of with a single
|
|
314
|
+
* query, so the "deleted" event fires for each and OrderObserver cascades the soft
|
|
315
|
+
* delete to the order's payload, entities and tracking data. Matching, the tenant
|
|
316
|
+
* constraint (GHSA-3wj9-hh56-7fw7) and the returned count follow core-api's version.
|
|
317
|
+
*/
|
|
318
|
+
public function bulkRemove($ids = [])
|
|
319
|
+
{
|
|
320
|
+
$orders = static::where(function ($query) use ($ids) {
|
|
321
|
+
$query->whereIn($this->getQualifiedKeyName(), $ids)->orWhereIn($this->getQualifiedPublicId(), $ids);
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
// Tenant constraint: never delete another company's orders.
|
|
325
|
+
$companyUuid = session('company');
|
|
326
|
+
if ($companyUuid) {
|
|
327
|
+
$orders->where($this->qualifyColumn('company_uuid'), $companyUuid);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
$orders = $orders->get();
|
|
331
|
+
$orders->each->delete();
|
|
332
|
+
$this->invalidateApiCacheOnChange();
|
|
333
|
+
|
|
334
|
+
return $orders->count();
|
|
335
|
+
}
|
|
336
|
+
|
|
266
337
|
/**
|
|
267
338
|
* Get the activity log options for the model.
|
|
268
339
|
*/
|
|
@@ -1034,6 +1105,7 @@ class Order extends Model
|
|
|
1034
1105
|
$route->save();
|
|
1035
1106
|
|
|
1036
1107
|
$this->updateQuietly(['route_uuid' => $route->uuid]);
|
|
1108
|
+
$this->invalidateApiCache();
|
|
1037
1109
|
|
|
1038
1110
|
return $this;
|
|
1039
1111
|
}
|
|
@@ -1169,6 +1241,7 @@ class Order extends Model
|
|
|
1169
1241
|
]);
|
|
1170
1242
|
|
|
1171
1243
|
if ($attached) {
|
|
1244
|
+
$this->invalidateApiCache();
|
|
1172
1245
|
$this->setRelation('purchaseRate', $purchaseRate);
|
|
1173
1246
|
|
|
1174
1247
|
if ($purchaseRate->transaction_uuid) {
|
|
@@ -1231,6 +1304,7 @@ class Order extends Model
|
|
|
1231
1304
|
]);
|
|
1232
1305
|
|
|
1233
1306
|
$this->updateQuietly(['transaction_uuid' => $transaction->uuid]);
|
|
1307
|
+
$this->invalidateApiCache();
|
|
1234
1308
|
} catch (\Throwable $e) {
|
|
1235
1309
|
}
|
|
1236
1310
|
|
|
@@ -1270,6 +1344,7 @@ class Order extends Model
|
|
|
1270
1344
|
if ($save) {
|
|
1271
1345
|
$this->saveQuietly();
|
|
1272
1346
|
$this->flushAttributesCache();
|
|
1347
|
+
$this->invalidateApiCache();
|
|
1273
1348
|
}
|
|
1274
1349
|
|
|
1275
1350
|
dispatch(fn () => event(new OrderDispatched($this)))->afterCommit();
|
|
@@ -1308,6 +1383,29 @@ class Order extends Model
|
|
|
1308
1383
|
return $this;
|
|
1309
1384
|
}
|
|
1310
1385
|
|
|
1386
|
+
/**
|
|
1387
|
+
* Determine whether the order is still waiting to be dispatched.
|
|
1388
|
+
*
|
|
1389
|
+
* A deferred dispatch, such as the queued finalize job for orders created with
|
|
1390
|
+
* `dispatch: true`, can run after the order was already dispatched or started
|
|
1391
|
+
* through another path. Dispatching it then would move the status back to
|
|
1392
|
+
* "dispatched", so only an order that still sits at its initial status with no
|
|
1393
|
+
* dispatch or start recorded qualifies.
|
|
1394
|
+
*/
|
|
1395
|
+
public function isAwaitingDispatch(): bool
|
|
1396
|
+
{
|
|
1397
|
+
if ($this->dispatched || $this->dispatched_at || $this->started || $this->started_at) {
|
|
1398
|
+
return false;
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
$status = $this->status ?? 'created';
|
|
1402
|
+
if ($status !== 'created' && $status !== $this->config()?->getInitialStatusCode()) {
|
|
1403
|
+
return false;
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
return !$this->hasDispatchedStatus();
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1311
1409
|
/**
|
|
1312
1410
|
* Dispatches the order only if it hasn't been dispatched yet.
|
|
1313
1411
|
* A check is performed before dispatching the order.
|
|
@@ -1345,11 +1443,33 @@ class Order extends Model
|
|
|
1345
1443
|
* @return mixed the result of the OrderCanceled event
|
|
1346
1444
|
*/
|
|
1347
1445
|
public function cancel()
|
|
1446
|
+
{
|
|
1447
|
+
return $this->cancelWithReason(null);
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
/**
|
|
1451
|
+
* Cancels the order, recording why.
|
|
1452
|
+
*
|
|
1453
|
+
* The reason becomes the details of the canceled tracking status and is carried on
|
|
1454
|
+
* the OrderCanceled event's activity, which the canceled notifications read.
|
|
1455
|
+
*
|
|
1456
|
+
* @return mixed the result of the OrderCanceled event
|
|
1457
|
+
*/
|
|
1458
|
+
public function cancelWithReason(?string $reason = null)
|
|
1348
1459
|
{
|
|
1349
1460
|
// The canceled activity comes from the order config, which may define its own code.
|
|
1350
1461
|
$this->loadMissing('orderConfig');
|
|
1351
1462
|
$orderConfig = $this->orderConfig ?? $this->config();
|
|
1352
1463
|
$canceledActivity = $orderConfig->getCanceledActivity();
|
|
1464
|
+
|
|
1465
|
+
// A reason given for the cancellation becomes the canceled status details, which
|
|
1466
|
+
// the canceled notifications read. The config's activity itself is left untouched.
|
|
1467
|
+
$reason = is_string($reason) ? trim($reason) : null;
|
|
1468
|
+
$reasonActivity = null;
|
|
1469
|
+
if ($reason !== null && $reason !== '' && $canceledActivity instanceof Activity) {
|
|
1470
|
+
$canceledActivity = $reasonActivity = (clone $canceledActivity)->set('details', $reason);
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1353
1473
|
$this->status = $canceledActivity->code ?? 'canceled';
|
|
1354
1474
|
$this->updateActivity($canceledActivity);
|
|
1355
1475
|
|
|
@@ -1361,7 +1481,13 @@ class Order extends Model
|
|
|
1361
1481
|
}
|
|
1362
1482
|
}
|
|
1363
1483
|
|
|
1364
|
-
|
|
1484
|
+
// The event carries the activity when a reason was given, so the canceled
|
|
1485
|
+
// notifications (which read the activity details) include it.
|
|
1486
|
+
return dispatch(function () use ($reasonActivity) {
|
|
1487
|
+
$event = new OrderCanceled($this);
|
|
1488
|
+
$event->activity = $reasonActivity;
|
|
1489
|
+
event($event);
|
|
1490
|
+
})->afterCommit();
|
|
1365
1491
|
}
|
|
1366
1492
|
|
|
1367
1493
|
/**
|
|
@@ -1377,6 +1503,52 @@ class Order extends Model
|
|
|
1377
1503
|
}
|
|
1378
1504
|
}
|
|
1379
1505
|
|
|
1506
|
+
/**
|
|
1507
|
+
* Tell a driver the order was taken off them: broadcasts `order.driver_unassigned`
|
|
1508
|
+
* on their channels and pushes `{ type: "order_unassigned", id }` to their devices.
|
|
1509
|
+
* The order is cleared as the driver's current job.
|
|
1510
|
+
*
|
|
1511
|
+
* @param Driver|string|null $driver the driver (or driver uuid) removed from the order
|
|
1512
|
+
*/
|
|
1513
|
+
public function notifyDriverUnassigned($driver): bool
|
|
1514
|
+
{
|
|
1515
|
+
if (is_string($driver)) {
|
|
1516
|
+
$driver = Driver::where('uuid', $driver)->withoutGlobalScopes()->first();
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
if (!$driver instanceof Driver) {
|
|
1520
|
+
return false;
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
if ($driver->current_job_uuid && $driver->current_job_uuid === $this->uuid) {
|
|
1524
|
+
$driver->forceFill(['current_job_uuid' => null])->saveQuietly();
|
|
1525
|
+
}
|
|
1526
|
+
|
|
1527
|
+
try {
|
|
1528
|
+
event(new OrderDriverUnassigned($this, $driver));
|
|
1529
|
+
} catch (\Throwable $exception) {
|
|
1530
|
+
Log::warning('Unable to broadcast order.driver_unassigned', ['order' => $this->public_id, 'error' => $exception->getMessage()]);
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
if (!$this->quietDriverUnassignment) {
|
|
1534
|
+
try {
|
|
1535
|
+
$driver->notify(new OrderUnassigned($this));
|
|
1536
|
+
} catch (\Throwable $exception) {
|
|
1537
|
+
Log::warning('Unable to notify driver of unassignment', ['order' => $this->public_id, 'error' => $exception->getMessage()]);
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
return true;
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
/**
|
|
1545
|
+
* The edit policy for the order at its current status.
|
|
1546
|
+
*/
|
|
1547
|
+
public function editPolicy(): OrderEditPolicy
|
|
1548
|
+
{
|
|
1549
|
+
return OrderEditPolicy::for($this);
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1380
1552
|
/**
|
|
1381
1553
|
* Updates the activity of the order.
|
|
1382
1554
|
* Updates the order status and inserts a new activity based on the provided activity details.
|
|
@@ -1634,7 +1806,7 @@ class Order extends Model
|
|
|
1634
1806
|
return $this;
|
|
1635
1807
|
}
|
|
1636
1808
|
|
|
1637
|
-
return $this->assignDriver($driver);
|
|
1809
|
+
return $this->assignDriver($driver, $silent);
|
|
1638
1810
|
}
|
|
1639
1811
|
|
|
1640
1812
|
throw new \Exception('Invalid driver provided for assignment!');
|
|
@@ -1647,12 +1819,16 @@ class Order extends Model
|
|
|
1647
1819
|
$this->setRelation('driverAssigned', $driver);
|
|
1648
1820
|
}
|
|
1649
1821
|
|
|
1650
|
-
|
|
1651
|
-
|
|
1822
|
+
// The order observer sends OrderDriverAssigned once the assignment is saved
|
|
1823
|
+
// (and tells a replaced driver they were unassigned), so it is not fired here
|
|
1824
|
+
// as well. A silent assignment is flagged for that one save.
|
|
1825
|
+
$this->silentDriverAssignment = (bool) $silent;
|
|
1826
|
+
try {
|
|
1827
|
+
$this->save();
|
|
1828
|
+
} finally {
|
|
1829
|
+
$this->silentDriverAssignment = false;
|
|
1652
1830
|
}
|
|
1653
1831
|
|
|
1654
|
-
$this->save();
|
|
1655
|
-
|
|
1656
1832
|
return $this;
|
|
1657
1833
|
}
|
|
1658
1834
|
|
|
@@ -1672,7 +1848,10 @@ class Order extends Model
|
|
|
1672
1848
|
$driverAssigned = Driver::where('uuid', $this->driver_assigned_uuid)->first();
|
|
1673
1849
|
}
|
|
1674
1850
|
|
|
1675
|
-
|
|
1851
|
+
// A driver that has never reported a position still carries the
|
|
1852
|
+
// POINT(0 0) placeholder it was created with. Measuring from there
|
|
1853
|
+
// puts the origin at null island, so fall back to the pickup.
|
|
1854
|
+
if ($driverAssigned instanceof Driver && static::isKnownPosition($driverAssigned->location)) {
|
|
1676
1855
|
return $driverAssigned->location;
|
|
1677
1856
|
}
|
|
1678
1857
|
}
|
|
@@ -1703,6 +1882,16 @@ class Order extends Model
|
|
|
1703
1882
|
return $destination ? $destination->location : null;
|
|
1704
1883
|
}
|
|
1705
1884
|
|
|
1885
|
+
/**
|
|
1886
|
+
* Determines whether a position is a real, resolved location rather than
|
|
1887
|
+
* missing or the POINT(0 0) placeholder stored for drivers that have not
|
|
1888
|
+
* reported a position yet and for places that failed to geocode.
|
|
1889
|
+
*/
|
|
1890
|
+
public static function isKnownPosition($position): bool
|
|
1891
|
+
{
|
|
1892
|
+
return $position instanceof Point && ($position->getLat() != 0.0 || $position->getLng() != 0.0);
|
|
1893
|
+
}
|
|
1894
|
+
|
|
1706
1895
|
/**
|
|
1707
1896
|
* Sets the preliminary distance and time for the order.
|
|
1708
1897
|
* Uses a utility method to calculate the distance and time between the current origin and destination positions.
|
|
@@ -1714,13 +1903,14 @@ class Order extends Model
|
|
|
1714
1903
|
$origin = $this->getCurrentOriginPosition();
|
|
1715
1904
|
$destination = $this->getDestinationPosition();
|
|
1716
1905
|
|
|
1717
|
-
if ($origin
|
|
1906
|
+
if (!static::isKnownPosition($origin) || !static::isKnownPosition($destination)) {
|
|
1718
1907
|
return $this;
|
|
1719
1908
|
}
|
|
1720
1909
|
|
|
1721
1910
|
$matrix = Utils::getPreliminaryDistanceMatrix($origin, $destination);
|
|
1722
1911
|
|
|
1723
1912
|
$this->updateQuietly(['distance' => $matrix->distance, 'time' => $matrix->time]);
|
|
1913
|
+
$this->invalidateApiCache();
|
|
1724
1914
|
|
|
1725
1915
|
return $this;
|
|
1726
1916
|
}
|
|
@@ -1736,7 +1926,7 @@ class Order extends Model
|
|
|
1736
1926
|
$origin = $this->getCurrentOriginPosition();
|
|
1737
1927
|
$destination = $this->getDestinationPosition();
|
|
1738
1928
|
|
|
1739
|
-
if (
|
|
1929
|
+
if (!static::isKnownPosition($origin) || !static::isKnownPosition($destination)) {
|
|
1740
1930
|
return $this;
|
|
1741
1931
|
}
|
|
1742
1932
|
|
|
@@ -1758,6 +1948,7 @@ class Order extends Model
|
|
|
1758
1948
|
'distance' => $matrix->distance,
|
|
1759
1949
|
'time' => $matrix->time,
|
|
1760
1950
|
]);
|
|
1951
|
+
$this->invalidateApiCache();
|
|
1761
1952
|
}
|
|
1762
1953
|
|
|
1763
1954
|
return $this;
|