@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,22 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\FleetOps\Models;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\Models\Model;
|
|
6
|
+
use Fleetbase\Traits\HasUuid;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* What a verified device may see: one customer within one order, until `expires_at`.
|
|
10
|
+
*/
|
|
11
|
+
class TrackingSessionGrant extends Model
|
|
12
|
+
{
|
|
13
|
+
use HasUuid;
|
|
14
|
+
|
|
15
|
+
protected $table = 'tracking_session_grants';
|
|
16
|
+
|
|
17
|
+
protected $fillable = ['tracking_session_uuid', 'company_uuid', 'order_uuid', 'customer_type', 'customer_uuid', 'channel', 'expires_at'];
|
|
18
|
+
|
|
19
|
+
protected $casts = [
|
|
20
|
+
'expires_at' => 'datetime',
|
|
21
|
+
];
|
|
22
|
+
}
|
|
@@ -7,6 +7,7 @@ use Fleetbase\FleetOps\Casts\Point;
|
|
|
7
7
|
use Fleetbase\FleetOps\Support\Utils;
|
|
8
8
|
use Fleetbase\LaravelMysqlSpatial\Eloquent\SpatialTrait;
|
|
9
9
|
use Fleetbase\Models\Model;
|
|
10
|
+
use Fleetbase\Support\ApiModelCache;
|
|
10
11
|
use Fleetbase\Traits\HasApiModelBehavior;
|
|
11
12
|
use Fleetbase\Traits\HasMetaAttributes;
|
|
12
13
|
use Fleetbase\Traits\HasPublicId;
|
|
@@ -177,6 +178,11 @@ class TrackingStatus extends Model
|
|
|
177
178
|
|
|
178
179
|
$result = static::insertTrackingStatus($values);
|
|
179
180
|
|
|
181
|
+
// Inserted without model events
|
|
182
|
+
if ($result) {
|
|
183
|
+
ApiModelCache::invalidateModelCache($instance, $values['company_uuid']);
|
|
184
|
+
}
|
|
185
|
+
|
|
180
186
|
return $result ? $uuid : false;
|
|
181
187
|
}
|
|
182
188
|
|
|
@@ -81,6 +81,23 @@ class Vehicle extends Model
|
|
|
81
81
|
*/
|
|
82
82
|
protected $with = [];
|
|
83
83
|
|
|
84
|
+
/**
|
|
85
|
+
* Relation paths the cached vehicle lists embed or filter on (fleetbase/core-api#301).
|
|
86
|
+
*
|
|
87
|
+
* The public list loads vendor (with its place), category, warranty and
|
|
88
|
+
* driver; driver, current trailers (through asset_connections) and fleets
|
|
89
|
+
* (through fleet_vehicles) decide which vehicles the filters return.
|
|
90
|
+
* photo is left out: files is written by every upload, and a new photo is
|
|
91
|
+
* set by writing the vehicle's own photo_uuid. devices is left out too: the
|
|
92
|
+
* device filters only read which devices are attached, but telemetry saves
|
|
93
|
+
* the device row on every ping, which would keep vehicle lists from ever
|
|
94
|
+
* being served from cache. Device::attachTo() and detach() invalidate the
|
|
95
|
+
* vehicle lists instead.
|
|
96
|
+
*
|
|
97
|
+
* @var string[]
|
|
98
|
+
*/
|
|
99
|
+
protected $apiCacheDependencies = ['vendor', 'vendor.place', 'category', 'warranty', 'driver', 'currentTrailers', 'fleets'];
|
|
100
|
+
|
|
84
101
|
/**
|
|
85
102
|
* Get the activity log options for the model.
|
|
86
103
|
*/
|
|
@@ -525,7 +542,8 @@ class Vehicle extends Model
|
|
|
525
542
|
return static::getAvatar($value);
|
|
526
543
|
}
|
|
527
544
|
|
|
528
|
-
|
|
545
|
+
// legacy rows hold an absolute URL; re-sign it if it points into the private media bucket
|
|
546
|
+
return Utils::signStoredFileUrl($value);
|
|
529
547
|
}
|
|
530
548
|
|
|
531
549
|
/**
|
|
@@ -628,6 +646,7 @@ class Vehicle extends Model
|
|
|
628
646
|
public function unassignDriver(): self
|
|
629
647
|
{
|
|
630
648
|
Driver::where('vehicle_uuid', $this->uuid)->update(['vehicle_uuid' => null]);
|
|
649
|
+
Driver::invalidateApiCacheManually($this->company_uuid);
|
|
631
650
|
$this->unsetRelation('driver');
|
|
632
651
|
|
|
633
652
|
return $this;
|
|
@@ -794,7 +813,7 @@ class Vehicle extends Model
|
|
|
794
813
|
return null;
|
|
795
814
|
}
|
|
796
815
|
|
|
797
|
-
return static::where(function ($query) use ($vehicleName) {
|
|
816
|
+
return static::where('company_uuid', session('company'))->where(function ($query) use ($vehicleName) {
|
|
798
817
|
$query->where('public_id', $vehicleName)
|
|
799
818
|
->orWhere('internal_id', $vehicleName)
|
|
800
819
|
->orWhere('plate_number', $vehicleName)
|
|
@@ -117,6 +117,13 @@ class Vendor extends Model
|
|
|
117
117
|
*/
|
|
118
118
|
protected $with = ['place'];
|
|
119
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Relation paths the cached vendor lists embed through `$with` (fleetbase/core-api#301).
|
|
122
|
+
*
|
|
123
|
+
* @var string[]
|
|
124
|
+
*/
|
|
125
|
+
protected $apiCacheDependencies = ['place'];
|
|
126
|
+
|
|
120
127
|
/**
|
|
121
128
|
* Get the activity log options for the model.
|
|
122
129
|
*/
|
|
@@ -8,6 +8,7 @@ use Fleetbase\FleetOps\Support\Utils;
|
|
|
8
8
|
use Fleetbase\FleetOps\Traits\HasTrackingNumber;
|
|
9
9
|
use Fleetbase\FleetOps\Traits\PayloadAccessors;
|
|
10
10
|
use Fleetbase\Models\Model;
|
|
11
|
+
use Fleetbase\Traits\HasApiModelCache;
|
|
11
12
|
use Fleetbase\Traits\HasPublicId;
|
|
12
13
|
use Fleetbase\Traits\HasUuid;
|
|
13
14
|
use Fleetbase\Traits\TracksApiCredential;
|
|
@@ -20,6 +21,8 @@ use Illuminate\Support\Str;
|
|
|
20
21
|
class Waypoint extends Model
|
|
21
22
|
{
|
|
22
23
|
use HasUuid;
|
|
24
|
+
// Writes bump the waypoints API cache version, which cached order lists embed.
|
|
25
|
+
use HasApiModelCache;
|
|
23
26
|
use HasPublicId;
|
|
24
27
|
use TracksApiCredential;
|
|
25
28
|
use HasTrackingNumber;
|
|
@@ -221,16 +224,22 @@ class Waypoint extends Model
|
|
|
221
224
|
if ($result && $payload) {
|
|
222
225
|
// create tracking number for entity
|
|
223
226
|
$trackingNumberId = static::createTrackingNumber([
|
|
224
|
-
'owner_uuid'
|
|
225
|
-
'owner_type'
|
|
226
|
-
'
|
|
227
|
-
'
|
|
227
|
+
'owner_uuid' => $uuid,
|
|
228
|
+
'owner_type' => Utils::getModelClassName('waypoint'),
|
|
229
|
+
'owner_public_id' => $values['public_id'],
|
|
230
|
+
'region' => $payload->getPickupRegion(),
|
|
231
|
+
'location' => static::pickupLocationWkt($payload),
|
|
228
232
|
]);
|
|
229
233
|
|
|
230
234
|
// set tracking number
|
|
231
235
|
static::updateTrackingNumberUuid($uuid, $trackingNumberId);
|
|
232
236
|
}
|
|
233
237
|
|
|
238
|
+
// Inserted and updated without model events
|
|
239
|
+
if ($result) {
|
|
240
|
+
static::invalidateApiCacheManually($values['company_uuid']);
|
|
241
|
+
}
|
|
242
|
+
|
|
234
243
|
return $result ? $uuid : false;
|
|
235
244
|
}
|
|
236
245
|
|
|
@@ -4,6 +4,7 @@ namespace Fleetbase\FleetOps\Notifications;
|
|
|
4
4
|
|
|
5
5
|
use Fleetbase\FleetOps\Http\Resources\v1\Order as OrderResource;
|
|
6
6
|
use Fleetbase\FleetOps\Models\Order;
|
|
7
|
+
use Fleetbase\FleetOps\Support\TrackingCode;
|
|
7
8
|
use Fleetbase\FleetOps\Support\Utils;
|
|
8
9
|
use Fleetbase\Support\PushNotification;
|
|
9
10
|
use Illuminate\Broadcasting\Channel;
|
|
@@ -128,7 +129,7 @@ class OrderAssigned extends Notification implements ShouldQueue
|
|
|
128
129
|
$message->line('Dispatch is scheduled for ' . $this->order->scheduled_at);
|
|
129
130
|
}
|
|
130
131
|
|
|
131
|
-
$message->action('Track Order',
|
|
132
|
+
$message->action('Track Order', TrackingCode::pageUrl($this->order->trackingNumber->tracking_number, data_get($this, 'order.company_uuid')));
|
|
132
133
|
|
|
133
134
|
return $message;
|
|
134
135
|
}
|
|
@@ -5,6 +5,7 @@ namespace Fleetbase\FleetOps\Notifications;
|
|
|
5
5
|
use Fleetbase\FleetOps\Http\Resources\v1\Order as OrderResource;
|
|
6
6
|
use Fleetbase\FleetOps\Models\Order;
|
|
7
7
|
use Fleetbase\FleetOps\Models\Waypoint;
|
|
8
|
+
use Fleetbase\FleetOps\Support\TrackingCode;
|
|
8
9
|
use Fleetbase\FleetOps\Support\Utils;
|
|
9
10
|
use Fleetbase\Support\PushNotification;
|
|
10
11
|
use Illuminate\Broadcasting\Channel;
|
|
@@ -81,6 +82,11 @@ class OrderCanceled extends Notification implements ShouldQueue
|
|
|
81
82
|
$this->title = 'Order ' . $this->getTrackingNumber() . ' was canceled';
|
|
82
83
|
$this->message = 'Order ' . $this->getTrackingNumber() . ' has been canceled.';
|
|
83
84
|
$this->data = ['id' => $this->order->public_id, 'type' => 'order_canceled'];
|
|
85
|
+
|
|
86
|
+
// apps show why the order was canceled when a reason was given
|
|
87
|
+
if ($reason !== '') {
|
|
88
|
+
$this->data['reason'] = $reason;
|
|
89
|
+
}
|
|
84
90
|
}
|
|
85
91
|
|
|
86
92
|
/**
|
|
@@ -138,7 +144,7 @@ class OrderCanceled extends Notification implements ShouldQueue
|
|
|
138
144
|
->line($this->message)
|
|
139
145
|
->line($this->reason)
|
|
140
146
|
->line('No further action is necessary.')
|
|
141
|
-
->action('Track Order',
|
|
147
|
+
->action('Track Order', TrackingCode::pageUrl($this->getTrackingNumber(), data_get($this, 'order.company_uuid')));
|
|
142
148
|
}
|
|
143
149
|
|
|
144
150
|
/**
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\FleetOps\Notifications;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\FleetOps\Models\Order;
|
|
6
|
+
use Fleetbase\Support\PushNotification;
|
|
7
|
+
use Illuminate\Broadcasting\Channel;
|
|
8
|
+
use Illuminate\Bus\Queueable;
|
|
9
|
+
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
10
|
+
use Illuminate\Notifications\Notification;
|
|
11
|
+
use NotificationChannels\Apn\ApnChannel;
|
|
12
|
+
use NotificationChannels\Fcm\FcmChannel;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Tells the assigned driver that an order they have changed.
|
|
16
|
+
*
|
|
17
|
+
* Push data: { type: "order_changed", id: order public id, changes: [...] }.
|
|
18
|
+
*/
|
|
19
|
+
class OrderChanged extends Notification implements ShouldQueue
|
|
20
|
+
{
|
|
21
|
+
use Queueable;
|
|
22
|
+
|
|
23
|
+
public static string $name = 'Order Changed';
|
|
24
|
+
public static string $description = 'Notify the assigned driver when an order they have is changed.';
|
|
25
|
+
public static string $package = 'fleet-ops';
|
|
26
|
+
|
|
27
|
+
public Order $order;
|
|
28
|
+
|
|
29
|
+
public array $changes = [];
|
|
30
|
+
|
|
31
|
+
public string $title;
|
|
32
|
+
|
|
33
|
+
public string $message;
|
|
34
|
+
|
|
35
|
+
public array $data = [];
|
|
36
|
+
|
|
37
|
+
public function __construct(Order $order, array $changes = [], string $summary = '')
|
|
38
|
+
{
|
|
39
|
+
$this->order = $order;
|
|
40
|
+
$this->changes = array_values($changes);
|
|
41
|
+
$this->title = 'Order ' . (data_get($order, 'trackingNumber.tracking_number') ?? $order->public_id) . ' changed';
|
|
42
|
+
$this->message = $summary !== '' ? $summary : 'This order was changed, tap for details.';
|
|
43
|
+
$this->data = ['type' => 'order_changed', 'id' => $order->public_id, 'changes' => $this->changes];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public function via($notifiable): array
|
|
47
|
+
{
|
|
48
|
+
return ['broadcast', FcmChannel::class, ApnChannel::class];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public function broadcastOn(): array
|
|
52
|
+
{
|
|
53
|
+
return [
|
|
54
|
+
new Channel('driver.' . data_get($this->order, 'driver_assigned_uuid')),
|
|
55
|
+
new Channel('driver.' . data_get($this->order, 'driverAssigned.public_id')),
|
|
56
|
+
];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public function toArray($notifiable = null): array
|
|
60
|
+
{
|
|
61
|
+
return [
|
|
62
|
+
'event' => 'order.changed_notification',
|
|
63
|
+
'title' => $this->title,
|
|
64
|
+
'body' => $this->message,
|
|
65
|
+
'data' => $this->data,
|
|
66
|
+
];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
public function toFcm($notifiable)
|
|
70
|
+
{
|
|
71
|
+
return PushNotification::createFcmMessage($this->title, $this->message, $this->fcmData());
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
public function toApn($notifiable)
|
|
75
|
+
{
|
|
76
|
+
return PushNotification::createApnMessage($this->title, $this->message, $this->data, 'view_order');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* FCM data values must be strings, so on FCM the change list travels comma
|
|
81
|
+
* separated ("dropoff,items"); APNs and the broadcast carry it as a list.
|
|
82
|
+
*/
|
|
83
|
+
public function fcmData(): array
|
|
84
|
+
{
|
|
85
|
+
return array_merge($this->data, ['changes' => implode(',', $this->changes)]);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -5,6 +5,7 @@ namespace Fleetbase\FleetOps\Notifications;
|
|
|
5
5
|
use Fleetbase\FleetOps\Http\Resources\v1\Order as OrderResource;
|
|
6
6
|
use Fleetbase\FleetOps\Models\Order;
|
|
7
7
|
use Fleetbase\FleetOps\Models\Waypoint;
|
|
8
|
+
use Fleetbase\FleetOps\Support\TrackingCode;
|
|
8
9
|
use Fleetbase\FleetOps\Support\Utils;
|
|
9
10
|
use Fleetbase\Support\PushNotification;
|
|
10
11
|
use Illuminate\Broadcasting\Channel;
|
|
@@ -131,7 +132,7 @@ class OrderCompleted extends Notification implements ShouldQueue
|
|
|
131
132
|
->subject($this->title)
|
|
132
133
|
->line($this->message)
|
|
133
134
|
->line('No further action is necessary.')
|
|
134
|
-
->action('Track Order',
|
|
135
|
+
->action('Track Order', TrackingCode::pageUrl($this->getTrackingNumber(), data_get($this, 'order.company_uuid')));
|
|
135
136
|
}
|
|
136
137
|
|
|
137
138
|
/**
|
|
@@ -5,6 +5,7 @@ namespace Fleetbase\FleetOps\Notifications;
|
|
|
5
5
|
use Fleetbase\FleetOps\Events\OrderDispatchFailed as OrderDispatchFailedEvent;
|
|
6
6
|
use Fleetbase\FleetOps\Http\Resources\v1\Order as OrderResource;
|
|
7
7
|
use Fleetbase\FleetOps\Models\Order;
|
|
8
|
+
use Fleetbase\FleetOps\Support\TrackingCode;
|
|
8
9
|
use Fleetbase\FleetOps\Support\Utils;
|
|
9
10
|
use Illuminate\Broadcasting\Channel;
|
|
10
11
|
use Illuminate\Bus\Queueable;
|
|
@@ -127,6 +128,6 @@ class OrderDispatchFailed extends Notification implements ShouldQueue
|
|
|
127
128
|
return (new MailMessage())
|
|
128
129
|
->subject($this->title)
|
|
129
130
|
->line($this->message)
|
|
130
|
-
->action('Track Order',
|
|
131
|
+
->action('Track Order', TrackingCode::pageUrl($this->order->trackingNumber->tracking_number, data_get($this, 'order.company_uuid')));
|
|
131
132
|
}
|
|
132
133
|
}
|
|
@@ -6,6 +6,7 @@ use Fleetbase\Events\ResourceLifecycleEvent;
|
|
|
6
6
|
use Fleetbase\FleetOps\Http\Resources\v1\Order as OrderResource;
|
|
7
7
|
use Fleetbase\FleetOps\Models\Order;
|
|
8
8
|
use Fleetbase\FleetOps\Models\Waypoint;
|
|
9
|
+
use Fleetbase\FleetOps\Support\TrackingCode;
|
|
9
10
|
use Fleetbase\FleetOps\Support\Utils;
|
|
10
11
|
use Fleetbase\Support\PushNotification;
|
|
11
12
|
use Illuminate\Broadcasting\Channel;
|
|
@@ -170,7 +171,7 @@ class OrderDispatched extends Notification implements ShouldQueue
|
|
|
170
171
|
return (new MailMessage())
|
|
171
172
|
->subject($this->title)
|
|
172
173
|
->line($this->message)
|
|
173
|
-
->action('Track Order',
|
|
174
|
+
->action('Track Order', TrackingCode::pageUrl($this->getTrackingNumber(), data_get($this, 'order.company_uuid')));
|
|
174
175
|
}
|
|
175
176
|
|
|
176
177
|
/**
|
|
@@ -5,6 +5,7 @@ namespace Fleetbase\FleetOps\Notifications;
|
|
|
5
5
|
use Fleetbase\FleetOps\Http\Resources\v1\Order as OrderResource;
|
|
6
6
|
use Fleetbase\FleetOps\Models\Order;
|
|
7
7
|
use Fleetbase\FleetOps\Models\Waypoint;
|
|
8
|
+
use Fleetbase\FleetOps\Support\TrackingCode;
|
|
8
9
|
use Fleetbase\FleetOps\Support\Utils;
|
|
9
10
|
use Fleetbase\Support\PushNotification;
|
|
10
11
|
use Illuminate\Broadcasting\Channel;
|
|
@@ -138,7 +139,7 @@ class OrderFailed extends Notification implements ShouldQueue
|
|
|
138
139
|
->line($this->message)
|
|
139
140
|
->line($this->reason)
|
|
140
141
|
->line('No further action is necessary.')
|
|
141
|
-
->action('Track Order',
|
|
142
|
+
->action('Track Order', TrackingCode::pageUrl($this->getTrackingNumber(), data_get($this, 'order.company_uuid')));
|
|
142
143
|
}
|
|
143
144
|
|
|
144
145
|
/**
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\FleetOps\Notifications;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\FleetOps\Models\Order;
|
|
6
|
+
use Fleetbase\Support\PushNotification;
|
|
7
|
+
use Illuminate\Bus\Queueable;
|
|
8
|
+
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
9
|
+
use Illuminate\Notifications\Notification;
|
|
10
|
+
use NotificationChannels\Apn\ApnChannel;
|
|
11
|
+
use NotificationChannels\Fcm\FcmChannel;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Tells a driver that an order was taken off them (unassigned or reassigned).
|
|
15
|
+
*
|
|
16
|
+
* Push data: { type: "order_unassigned", id: order public id }.
|
|
17
|
+
*/
|
|
18
|
+
class OrderUnassigned extends Notification implements ShouldQueue
|
|
19
|
+
{
|
|
20
|
+
use Queueable;
|
|
21
|
+
|
|
22
|
+
public static string $name = 'Order Unassigned';
|
|
23
|
+
public static string $description = 'Notify a driver when an order is unassigned from them or reassigned to another driver.';
|
|
24
|
+
public static string $package = 'fleet-ops';
|
|
25
|
+
|
|
26
|
+
public Order $order;
|
|
27
|
+
|
|
28
|
+
public string $title;
|
|
29
|
+
|
|
30
|
+
public string $message;
|
|
31
|
+
|
|
32
|
+
public array $data = [];
|
|
33
|
+
|
|
34
|
+
public function __construct(Order $order)
|
|
35
|
+
{
|
|
36
|
+
$this->order = $order;
|
|
37
|
+
$this->title = 'Order ' . (data_get($order, 'trackingNumber.tracking_number') ?? $order->public_id) . ' unassigned';
|
|
38
|
+
$this->message = 'This order is no longer assigned to you.';
|
|
39
|
+
$this->data = ['type' => 'order_unassigned', 'id' => $order->public_id];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public function via($notifiable): array
|
|
43
|
+
{
|
|
44
|
+
return [FcmChannel::class, ApnChannel::class];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public function toArray($notifiable = null): array
|
|
48
|
+
{
|
|
49
|
+
return [
|
|
50
|
+
'event' => 'order.unassigned_notification',
|
|
51
|
+
'title' => $this->title,
|
|
52
|
+
'body' => $this->message,
|
|
53
|
+
'data' => $this->data,
|
|
54
|
+
];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public function toFcm($notifiable)
|
|
58
|
+
{
|
|
59
|
+
return PushNotification::createFcmMessage($this->title, $this->message, $this->data);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public function toApn($notifiable)
|
|
63
|
+
{
|
|
64
|
+
return PushNotification::createApnMessage($this->title, $this->message, $this->data, 'view_order');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -5,6 +5,7 @@ namespace Fleetbase\FleetOps\Notifications;
|
|
|
5
5
|
use Fleetbase\FleetOps\Flow\Activity;
|
|
6
6
|
use Fleetbase\FleetOps\Models\Order;
|
|
7
7
|
use Fleetbase\FleetOps\Models\Waypoint;
|
|
8
|
+
use Fleetbase\FleetOps\Support\TrackingCode;
|
|
8
9
|
use Fleetbase\FleetOps\Support\Utils;
|
|
9
10
|
use Fleetbase\Support\PushNotification;
|
|
10
11
|
use Illuminate\Broadcasting\Channel;
|
|
@@ -132,7 +133,7 @@ class WaypointCompleted extends Notification implements ShouldQueue
|
|
|
132
133
|
->subject($this->title)
|
|
133
134
|
->line($this->message)
|
|
134
135
|
->line('No further action is necessary.')
|
|
135
|
-
->action('Track Order',
|
|
136
|
+
->action('Track Order', TrackingCode::pageUrl($this->waypoint->trackingNumber->tracking_number, data_get($this, 'waypoint.company_uuid')));
|
|
136
137
|
}
|
|
137
138
|
|
|
138
139
|
/**
|
|
@@ -14,8 +14,8 @@ class CompanyUserObserver
|
|
|
14
14
|
*/
|
|
15
15
|
public function deleted(CompanyUser $companyUser)
|
|
16
16
|
{
|
|
17
|
-
// if the company user deleted is a driver, delete their driver record
|
|
18
|
-
$this->deleteDrivers($companyUser->user_uuid);
|
|
17
|
+
// if the company user deleted is a driver, delete their driver record in that company
|
|
18
|
+
$this->deleteDrivers($companyUser->user_uuid, $companyUser->company_uuid);
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
/**
|
|
@@ -26,19 +26,20 @@ class CompanyUserObserver
|
|
|
26
26
|
public function updated(CompanyUser $companyUser)
|
|
27
27
|
{
|
|
28
28
|
// If the company user has any driver assosciated update status to same as company_users
|
|
29
|
-
$driver = $this->findDriver($companyUser->user_uuid);
|
|
29
|
+
$driver = $this->findDriver($companyUser->user_uuid, $companyUser->company_uuid);
|
|
30
30
|
if ($driver && $companyUser->wasChanged('status')) {
|
|
31
31
|
$driver->update(['status' => $companyUser->status]);
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
protected function deleteDrivers(string $userUuid): void
|
|
35
|
+
protected function deleteDrivers(string $userUuid, ?string $companyUuid): void
|
|
36
36
|
{
|
|
37
|
-
|
|
37
|
+
// Delete each driver through the model so DriverObserver cleans up after it
|
|
38
|
+
Driver::where(['user_uuid' => $userUuid, 'company_uuid' => $companyUuid])->get()->each->delete();
|
|
38
39
|
}
|
|
39
40
|
|
|
40
|
-
protected function findDriver(string $userUuid): ?Driver
|
|
41
|
+
protected function findDriver(string $userUuid, ?string $companyUuid): ?Driver
|
|
41
42
|
{
|
|
42
|
-
return Driver::where('user_uuid', $
|
|
43
|
+
return Driver::where(['user_uuid' => $userUuid, 'company_uuid' => $companyUuid])->first();
|
|
43
44
|
}
|
|
44
45
|
}
|
|
@@ -79,7 +79,12 @@ class DriverObserver
|
|
|
79
79
|
|
|
80
80
|
protected function unassignOrders(Driver $driver): int
|
|
81
81
|
{
|
|
82
|
-
|
|
82
|
+
$unassigned = Order::where(['driver_assigned_uuid' => $driver->uuid])->update(['driver_assigned_uuid' => null]);
|
|
83
|
+
if ($unassigned > 0) {
|
|
84
|
+
Order::invalidateApiCacheManually($driver->company_uuid);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return $unassigned;
|
|
83
88
|
}
|
|
84
89
|
|
|
85
90
|
protected function findDriverUser(Driver $driver): ?User
|
|
@@ -2,12 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
namespace Fleetbase\FleetOps\Observers;
|
|
4
4
|
|
|
5
|
+
use Fleetbase\FleetOps\Models\Entity;
|
|
5
6
|
use Fleetbase\FleetOps\Models\Order;
|
|
7
|
+
use Fleetbase\FleetOps\Models\Payload;
|
|
8
|
+
use Fleetbase\FleetOps\Models\TrackingNumber;
|
|
9
|
+
use Fleetbase\FleetOps\Models\TrackingStatus;
|
|
10
|
+
use Fleetbase\FleetOps\Models\Waypoint;
|
|
6
11
|
use Fleetbase\FleetOps\Support\LiveCacheService;
|
|
12
|
+
use Fleetbase\FleetOps\Support\TrackingPublisher;
|
|
13
|
+
use Fleetbase\Support\ApiModelCache;
|
|
7
14
|
use Illuminate\Support\Facades\Cache;
|
|
8
15
|
|
|
9
16
|
class OrderObserver
|
|
10
17
|
{
|
|
18
|
+
/**
|
|
19
|
+
* Deletion timestamps captured while an order is being restored, keyed by order uuid.
|
|
20
|
+
* Restoring clears the order's deleted_at before "restored" fires, so the timestamp the
|
|
21
|
+
* children were deleted with is read in "restoring" and used once the restore succeeds.
|
|
22
|
+
*
|
|
23
|
+
* @var array<string, string>
|
|
24
|
+
*/
|
|
25
|
+
protected static array $restoringFrom = [];
|
|
26
|
+
|
|
11
27
|
/**
|
|
12
28
|
* Handle the Order "created" event.
|
|
13
29
|
*
|
|
@@ -42,10 +58,21 @@ class OrderObserver
|
|
|
42
58
|
$order->setDriverLocationAsPickup();
|
|
43
59
|
|
|
44
60
|
if ($order->wasChanged('driver_assigned_uuid')) {
|
|
45
|
-
|
|
61
|
+
// The driver taken off the order hears about it, whether it was unassigned or reassigned.
|
|
62
|
+
$previousDriverUuid = $order->getOriginal('driver_assigned_uuid');
|
|
63
|
+
if ($previousDriverUuid) {
|
|
64
|
+
$order->notifyDriverUnassigned($previousDriverUuid);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (!$order->silentDriverAssignment) {
|
|
68
|
+
$order->notifyDriverAssigned();
|
|
69
|
+
}
|
|
46
70
|
}
|
|
47
71
|
|
|
48
72
|
$this->invalidateCache($order);
|
|
73
|
+
|
|
74
|
+
// Public tracking channels follow status, assignment and ETA changes.
|
|
75
|
+
app(TrackingPublisher::class)->orderChanged($order);
|
|
49
76
|
}
|
|
50
77
|
|
|
51
78
|
/**
|
|
@@ -59,9 +86,122 @@ class OrderObserver
|
|
|
59
86
|
$order->facilitator->provider()->callback('onDeleted', $order);
|
|
60
87
|
}
|
|
61
88
|
|
|
89
|
+
$this->cascadeDelete($order);
|
|
90
|
+
$this->invalidateCache($order);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Handle the Order "restoring" event: remember when the order was deleted.
|
|
95
|
+
*/
|
|
96
|
+
public function restoring(Order $order): void
|
|
97
|
+
{
|
|
98
|
+
if ($order->uuid && $order->deleted_at) {
|
|
99
|
+
static::$restoringFrom[$order->uuid] = $order->fromDateTime($order->deleted_at);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Handle the Order "restored" event: bring back the children deleted with the order.
|
|
105
|
+
*/
|
|
106
|
+
public function restored(Order $order): void
|
|
107
|
+
{
|
|
108
|
+
$deletedAt = static::$restoringFrom[$order->uuid] ?? null;
|
|
109
|
+
unset(static::$restoringFrom[$order->uuid]);
|
|
110
|
+
|
|
111
|
+
if ($deletedAt) {
|
|
112
|
+
$this->cascadeRestore($order, $deletedAt);
|
|
113
|
+
}
|
|
114
|
+
|
|
62
115
|
$this->invalidateCache($order);
|
|
63
116
|
}
|
|
64
117
|
|
|
118
|
+
/**
|
|
119
|
+
* Soft-deletes what belongs to the order: its tracking number and, unless another live
|
|
120
|
+
* order shares it, its payload with the payload's entities and waypoints and their
|
|
121
|
+
* tracking numbers, plus every one of those tracking numbers' statuses. Children are
|
|
122
|
+
* stamped with the order's own deleted_at so a restore can find exactly those rows.
|
|
123
|
+
*/
|
|
124
|
+
protected function cascadeDelete(Order $order): void
|
|
125
|
+
{
|
|
126
|
+
$deletedAt = $order->fromDateTime($order->deleted_at ?? $order->freshTimestamp());
|
|
127
|
+
$tree = $this->childTree($order, Payload::query(), Entity::query(), Waypoint::query());
|
|
128
|
+
|
|
129
|
+
if ($tree['payload']) {
|
|
130
|
+
Payload::where('uuid', $tree['payload'])->update(['deleted_at' => $deletedAt]);
|
|
131
|
+
Entity::whereIn('uuid', $tree['entities'])->update(['deleted_at' => $deletedAt]);
|
|
132
|
+
Waypoint::whereIn('uuid', $tree['waypoints'])->update(['deleted_at' => $deletedAt]);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
$trackingNumbers = TrackingNumber::where(fn ($query) => $query->whereIn('uuid', $tree['tracking_numbers'])->orWhereIn('owner_uuid', $tree['owners']))->pluck('uuid')->all();
|
|
136
|
+
TrackingStatus::whereIn('tracking_number_uuid', $trackingNumbers)->update(['deleted_at' => $deletedAt]);
|
|
137
|
+
TrackingNumber::whereIn('uuid', $trackingNumbers)->update(['deleted_at' => $deletedAt]);
|
|
138
|
+
|
|
139
|
+
$this->invalidateChildApiCaches($order);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Restores the children cascadeDelete() removed: the rows of the same tree whose
|
|
144
|
+
* deleted_at matches the order's. Children deleted on their own beforehand carry
|
|
145
|
+
* a different timestamp and stay deleted.
|
|
146
|
+
*/
|
|
147
|
+
protected function cascadeRestore(Order $order, string $deletedAt): void
|
|
148
|
+
{
|
|
149
|
+
$trashed = fn (string $model) => $model::onlyTrashed()->where('deleted_at', $deletedAt);
|
|
150
|
+
$tree = $this->childTree($order, $trashed(Payload::class), $trashed(Entity::class), $trashed(Waypoint::class));
|
|
151
|
+
|
|
152
|
+
$trackingNumbers = $trashed(TrackingNumber::class)->where(fn ($query) => $query->whereIn('uuid', $tree['tracking_numbers'])->orWhereIn('owner_uuid', $tree['owners']))->pluck('uuid')->all();
|
|
153
|
+
$trashed(TrackingNumber::class)->whereIn('uuid', $trackingNumbers)->update(['deleted_at' => null]);
|
|
154
|
+
$trashed(TrackingStatus::class)->whereIn('tracking_number_uuid', $trackingNumbers)->update(['deleted_at' => null]);
|
|
155
|
+
|
|
156
|
+
if ($tree['payload']) {
|
|
157
|
+
$trashed(Payload::class)->where('uuid', $tree['payload'])->update(['deleted_at' => null]);
|
|
158
|
+
$trashed(Entity::class)->whereIn('uuid', $tree['entities'])->update(['deleted_at' => null]);
|
|
159
|
+
$trashed(Waypoint::class)->whereIn('uuid', $tree['waypoints'])->update(['deleted_at' => null]);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
$this->invalidateChildApiCaches($order);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* The cascades write their tables without model events, so invalidate the API
|
|
167
|
+
* caches of every table they touch.
|
|
168
|
+
*/
|
|
169
|
+
protected function invalidateChildApiCaches(Order $order): void
|
|
170
|
+
{
|
|
171
|
+
foreach ([Payload::class, Entity::class, Waypoint::class, TrackingNumber::class, TrackingStatus::class] as $modelClass) {
|
|
172
|
+
ApiModelCache::invalidateModelCache(new $modelClass(), $order->company_uuid);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Collects the uuids under an order from the given payload, entity and waypoint
|
|
178
|
+
* queries. The payload is left out when another live order still references it.
|
|
179
|
+
*
|
|
180
|
+
* @return array{payload: ?string, entities: array, waypoints: array, tracking_numbers: array, owners: array}
|
|
181
|
+
*/
|
|
182
|
+
protected function childTree(Order $order, $payloads, $entities, $waypoints): array
|
|
183
|
+
{
|
|
184
|
+
$tree = ['payload' => null, 'entities' => [], 'waypoints' => [], 'tracking_numbers' => [$order->tracking_number_uuid], 'owners' => [$order->uuid]];
|
|
185
|
+
|
|
186
|
+
$shared = $order->payload_uuid && Order::where('payload_uuid', $order->payload_uuid)->where('uuid', '!=', $order->uuid)->exists();
|
|
187
|
+
$payload = $order->payload_uuid && !$shared ? $payloads->where('uuid', $order->payload_uuid)->first() : null;
|
|
188
|
+
|
|
189
|
+
if ($payload) {
|
|
190
|
+
$children = $entities->where('payload_uuid', $payload->uuid)->get(['uuid', 'tracking_number_uuid'])
|
|
191
|
+
->concat($waypoints->where('payload_uuid', $payload->uuid)->get(['uuid', 'tracking_number_uuid']));
|
|
192
|
+
|
|
193
|
+
$tree['payload'] = $payload->uuid;
|
|
194
|
+
$tree['entities'] = $children->whereInstanceOf(Entity::class)->pluck('uuid')->all();
|
|
195
|
+
$tree['waypoints'] = $children->whereInstanceOf(Waypoint::class)->pluck('uuid')->all();
|
|
196
|
+
$tree['tracking_numbers'] = array_merge($tree['tracking_numbers'], [$payload->pickup_tracking_number_uuid, $payload->dropoff_tracking_number_uuid, $payload->return_tracking_number_uuid], $children->pluck('tracking_number_uuid')->all());
|
|
197
|
+
$tree['owners'] = array_merge($tree['owners'], $children->pluck('uuid')->all());
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
$tree['tracking_numbers'] = array_values(array_filter($tree['tracking_numbers']));
|
|
201
|
+
|
|
202
|
+
return $tree;
|
|
203
|
+
}
|
|
204
|
+
|
|
65
205
|
/**
|
|
66
206
|
* Invalidate relevant cache tags for live endpoints.
|
|
67
207
|
*
|