@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,81 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
use Fleetbase\FleetOps\Models\Driver;
|
|
4
|
+
use Fleetbase\FleetOps\Models\Vehicle;
|
|
5
|
+
use Fleetbase\Tests\Support\TrackingPageDatabase;
|
|
6
|
+
use Illuminate\Cache\ArrayStore;
|
|
7
|
+
use Illuminate\Cache\Repository;
|
|
8
|
+
use Illuminate\Database\Eloquent\Model as EloquentModel;
|
|
9
|
+
use Illuminate\Database\SQLiteConnection;
|
|
10
|
+
use Illuminate\Support\Facades\Cache;
|
|
11
|
+
|
|
12
|
+
beforeEach(function () {
|
|
13
|
+
Cache::swap(new Repository(new ArrayStore()));
|
|
14
|
+
session(['company' => 'co-1']);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
afterEach(function () {
|
|
18
|
+
EloquentModel::unsetConnectionResolver();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
function driverAssignVehicleDatabase(): SQLiteConnection
|
|
22
|
+
{
|
|
23
|
+
$db = TrackingPageDatabase::boot();
|
|
24
|
+
|
|
25
|
+
$db->getSchemaBuilder()->create('users', function ($table) {
|
|
26
|
+
$table->increments('id');
|
|
27
|
+
$table->string('uuid')->nullable();
|
|
28
|
+
$table->string('company_uuid')->nullable();
|
|
29
|
+
$table->timestamps();
|
|
30
|
+
$table->softDeletes();
|
|
31
|
+
});
|
|
32
|
+
$db->getSchemaBuilder()->create('drivers', function ($table) {
|
|
33
|
+
$table->increments('id');
|
|
34
|
+
$table->string('uuid')->nullable();
|
|
35
|
+
$table->string('public_id')->nullable();
|
|
36
|
+
$table->string('company_uuid')->nullable();
|
|
37
|
+
$table->string('user_uuid')->nullable();
|
|
38
|
+
$table->string('vehicle_uuid')->nullable();
|
|
39
|
+
$table->timestamps();
|
|
40
|
+
$table->softDeletes();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
foreach (['user-1', 'user-2'] as $user) {
|
|
44
|
+
TrackingPageDatabase::insert($db, 'users', ['uuid' => $user, 'company_uuid' => 'co-1']);
|
|
45
|
+
}
|
|
46
|
+
TrackingPageDatabase::insert($db, 'drivers', ['uuid' => 'driver-1', 'company_uuid' => 'co-1', 'user_uuid' => 'user-1', 'vehicle_uuid' => 'vehicle-1']);
|
|
47
|
+
TrackingPageDatabase::insert($db, 'drivers', ['uuid' => 'driver-2', 'company_uuid' => 'co-1', 'user_uuid' => 'user-2']);
|
|
48
|
+
|
|
49
|
+
return $db;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function driverAssignVehicleVehicle(): Vehicle
|
|
53
|
+
{
|
|
54
|
+
$vehicle = new Vehicle();
|
|
55
|
+
$vehicle->setRawAttributes(['uuid' => 'vehicle-1', 'company_uuid' => 'co-1'], true);
|
|
56
|
+
$vehicle->exists = true;
|
|
57
|
+
|
|
58
|
+
return $vehicle;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function driverAssignVehicleAssignments(SQLiteConnection $db): array
|
|
62
|
+
{
|
|
63
|
+
return $db->table('drivers')->orderBy('uuid')->pluck('vehicle_uuid', 'uuid')->all();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
test('assigning a driver the vehicle it already has keeps the assignment', function () {
|
|
67
|
+
$db = driverAssignVehicleDatabase();
|
|
68
|
+
|
|
69
|
+
Driver::where('uuid', 'driver-1')->first()->assignVehicle(driverAssignVehicleVehicle());
|
|
70
|
+
|
|
71
|
+
expect(driverAssignVehicleAssignments($db))->toBe(['driver-1' => 'vehicle-1', 'driver-2' => null]);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test('assigning a vehicle to another driver moves it from its current driver', function () {
|
|
75
|
+
$db = driverAssignVehicleDatabase();
|
|
76
|
+
|
|
77
|
+
$driver = Driver::where('uuid', 'driver-2')->first()->assignVehicle(driverAssignVehicleVehicle());
|
|
78
|
+
|
|
79
|
+
expect(driverAssignVehicleAssignments($db))->toBe(['driver-1' => null, 'driver-2' => 'vehicle-1'])
|
|
80
|
+
->and($driver->vehicle->uuid)->toBe('vehicle-1');
|
|
81
|
+
});
|
|
@@ -33,7 +33,8 @@ use Illuminate\Database\SQLiteConnection;
|
|
|
33
33
|
use Spatie\Activitylog\LogOptions;
|
|
34
34
|
use Spatie\Sluggable\SlugOptions;
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
// Extends the relation the model method now declares, so the override stays compatible; the parent constructor is skipped on purpose.
|
|
37
|
+
class FleetOpsFleetUnitCountingRelationFake extends HasManyThrough
|
|
37
38
|
{
|
|
38
39
|
public array $wheres = [];
|
|
39
40
|
|
|
@@ -59,7 +60,7 @@ class FleetOpsFleetUnitCountingFake extends Fleet
|
|
|
59
60
|
public array $driverRelations = [];
|
|
60
61
|
public array $vehicleRelations = [];
|
|
61
62
|
|
|
62
|
-
public function drivers()
|
|
63
|
+
public function drivers(): HasManyThrough
|
|
63
64
|
{
|
|
64
65
|
$relation = new FleetOpsFleetUnitCountingRelationFake(5);
|
|
65
66
|
$this->driverRelations[] = $relation;
|
|
@@ -67,7 +68,7 @@ class FleetOpsFleetUnitCountingFake extends Fleet
|
|
|
67
68
|
return $relation;
|
|
68
69
|
}
|
|
69
70
|
|
|
70
|
-
public function vehicles()
|
|
71
|
+
public function vehicles(): HasManyThrough
|
|
71
72
|
{
|
|
72
73
|
$relation = new FleetOpsFleetUnitCountingRelationFake(8);
|
|
73
74
|
$this->vehicleRelations[] = $relation;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
if (!class_exists('FleetOpsOrderCancelReasonRecorder', false)) {
|
|
4
|
+
class FleetOpsOrderCancelReasonRecorder
|
|
5
|
+
{
|
|
6
|
+
public static array $events = [];
|
|
7
|
+
|
|
8
|
+
public static function dispatch($job): object
|
|
9
|
+
{
|
|
10
|
+
if ($job instanceof Closure) {
|
|
11
|
+
$job();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return new class {
|
|
15
|
+
public function afterCommit(): self
|
|
16
|
+
{
|
|
17
|
+
return $this;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (!function_exists('Fleetbase\FleetOps\Models\dispatch')) {
|
|
25
|
+
eval('namespace Fleetbase\FleetOps\Models; function dispatch($job) { return \FleetOpsOrderCancelReasonRecorder::dispatch($job); }');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (!function_exists('Fleetbase\FleetOps\Models\event')) {
|
|
29
|
+
eval('namespace Fleetbase\FleetOps\Models; function event($event = null) { \FleetOpsOrderCancelReasonRecorder::$events[] = $event; return $event; }');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (!class_exists('Fleetbase\FleetOps\Events\OrderCanceled', false)) {
|
|
33
|
+
eval('namespace Fleetbase\FleetOps\Events; class OrderCanceled { public $activity = null; public $waypoint = null; public function __construct(public $order) {} public function getModelRecord() { return $this->order; } }');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
use Fleetbase\FleetOps\Events\OrderCanceled;
|
|
37
|
+
use Fleetbase\FleetOps\Flow\Activity;
|
|
38
|
+
use Fleetbase\FleetOps\Listeners\HandleOrderCanceled;
|
|
39
|
+
use Fleetbase\FleetOps\Models\Driver;
|
|
40
|
+
use Fleetbase\FleetOps\Models\Order;
|
|
41
|
+
use Fleetbase\FleetOps\Models\OrderConfig;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Covers canceling an order with a reason: the reason becomes the canceled
|
|
45
|
+
* status details and rides on the OrderCanceled event, while the config's
|
|
46
|
+
* activity is left untouched and a plain cancel carries no activity.
|
|
47
|
+
*/
|
|
48
|
+
class FleetOpsOrderCancelReasonOrder extends Order
|
|
49
|
+
{
|
|
50
|
+
public array $activities = [];
|
|
51
|
+
|
|
52
|
+
public function updateActivity(?Activity $activity = null, $proof = null): Order
|
|
53
|
+
{
|
|
54
|
+
$this->activities[] = $activity;
|
|
55
|
+
$this->status = $activity?->code;
|
|
56
|
+
|
|
57
|
+
return $this;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
class FleetOpsOrderCancelReasonConfig extends OrderConfig
|
|
62
|
+
{
|
|
63
|
+
public ?Activity $canceled = null;
|
|
64
|
+
|
|
65
|
+
public function getCanceledActivity()
|
|
66
|
+
{
|
|
67
|
+
return $this->canceled;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function fleetopsOrderCancelReasonOrder(): array
|
|
72
|
+
{
|
|
73
|
+
FleetOpsOrderCancelReasonRecorder::$events = [];
|
|
74
|
+
|
|
75
|
+
$config = new FleetOpsOrderCancelReasonConfig();
|
|
76
|
+
$config->canceled = new Activity(['code' => 'canceled', 'status' => 'Order canceled', 'details' => 'Order was canceled']);
|
|
77
|
+
|
|
78
|
+
$order = new FleetOpsOrderCancelReasonOrder();
|
|
79
|
+
$order->setRawAttributes(['uuid' => 'order-uuid', 'status' => 'dispatched'], true);
|
|
80
|
+
$order->setRelation('orderConfig', $config);
|
|
81
|
+
|
|
82
|
+
return [$order, $config];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
test('canceling with a reason records it as the canceled details and on the event', function () {
|
|
86
|
+
[$order, $config] = fleetopsOrderCancelReasonOrder();
|
|
87
|
+
|
|
88
|
+
$order->cancelWithReason(' Customer moved house ');
|
|
89
|
+
|
|
90
|
+
$event = collect(FleetOpsOrderCancelReasonRecorder::$events)->first(fn ($event) => $event instanceof OrderCanceled);
|
|
91
|
+
|
|
92
|
+
expect($order->status)->toBe('canceled')
|
|
93
|
+
->and($order->activities[0]->get('details'))->toBe('Customer moved house')
|
|
94
|
+
->and($config->canceled->get('details'))->toBe('Order was canceled')
|
|
95
|
+
->and($event)->not->toBeNull()
|
|
96
|
+
->and($event->activity->get('details'))->toBe('Customer moved house');
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test('a plain cancel keeps the config activity and sends no reason', function () {
|
|
100
|
+
[$order, $config] = fleetopsOrderCancelReasonOrder();
|
|
101
|
+
|
|
102
|
+
$order->cancel();
|
|
103
|
+
|
|
104
|
+
$event = collect(FleetOpsOrderCancelReasonRecorder::$events)->first(fn ($event) => $event instanceof OrderCanceled);
|
|
105
|
+
|
|
106
|
+
expect($order->activities[0])->toBe($config->canceled)
|
|
107
|
+
->and($event->activity)->toBeNull();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test('the canceled listener passes the reason on to the assigned driver', function () {
|
|
111
|
+
[$order] = fleetopsOrderCancelReasonOrder();
|
|
112
|
+
$order->setRawAttributes(array_merge($order->getAttributes(), ['driver_assigned_uuid' => 'driver-uuid']));
|
|
113
|
+
$order->setRelation('facilitator', null);
|
|
114
|
+
$order->setRelation('trackingNumber', null);
|
|
115
|
+
|
|
116
|
+
$driver = new class extends Driver {
|
|
117
|
+
public array $notified = [];
|
|
118
|
+
|
|
119
|
+
public function notify($instance)
|
|
120
|
+
{
|
|
121
|
+
$this->notified[] = $instance;
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
$listener = new class($driver) extends HandleOrderCanceled {
|
|
126
|
+
public function __construct(private Driver $driverForTest)
|
|
127
|
+
{
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
protected function findAssignedDriver($order): ?Driver
|
|
131
|
+
{
|
|
132
|
+
return $this->driverForTest;
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
$event = new OrderCanceled($order);
|
|
137
|
+
$event->activity = new Activity(['code' => 'canceled', 'details' => 'Customer moved house']);
|
|
138
|
+
$listener->handle($event);
|
|
139
|
+
|
|
140
|
+
expect($driver->notified)->toHaveCount(1)
|
|
141
|
+
->and($driver->notified[0]->reason)->toBe('Customer moved house')
|
|
142
|
+
->and($driver->notified[0]->data)->toBe(['id' => null, 'type' => 'order_canceled', 'reason' => 'Customer moved house']);
|
|
143
|
+
});
|
|
@@ -240,6 +240,66 @@ test('distance and time setters use origin and destination positions', function
|
|
|
240
240
|
expect($origin?->getLat())->toBe(1.20);
|
|
241
241
|
});
|
|
242
242
|
|
|
243
|
+
test('a driver without a reported location does not turn the order origin into null island', function () {
|
|
244
|
+
$connection = fleetopsOrderPayloadBoot();
|
|
245
|
+
// Sunshine -> Melton, Victoria: a ~25 km straight-line run
|
|
246
|
+
$connection->table('places')->insert([
|
|
247
|
+
['uuid' => '11111111-1111-4111-8111-111111111111', 'public_id' => 'place_vicpickup', 'company_uuid' => 'company-1', 'location' => fleetopsOrderPayloadWkb(-37.78, 144.83)],
|
|
248
|
+
['uuid' => '22222222-2222-4222-8222-222222222222', 'public_id' => 'place_vicdropoff', 'company_uuid' => 'company-1', 'location' => fleetopsOrderPayloadWkb(-37.68, 144.58)],
|
|
249
|
+
]);
|
|
250
|
+
$connection->table('payloads')->insert(['uuid' => 'payload-1', 'company_uuid' => 'company-1', 'pickup_uuid' => '11111111-1111-4111-8111-111111111111', 'dropoff_uuid' => '22222222-2222-4222-8222-222222222222']);
|
|
251
|
+
$connection->table('users')->insert(['uuid' => 'user-1', 'company_uuid' => 'company-1', 'type' => 'user']);
|
|
252
|
+
// Drivers are created with a POINT(0 0) placeholder until their first location report
|
|
253
|
+
$connection->table('drivers')->insert(['uuid' => '44444444-4444-4444-8444-444444444444', 'public_id' => 'driver_vicnoloc', 'company_uuid' => 'company-1', 'user_uuid' => 'user-1', 'location' => fleetopsOrderPayloadWkb(0, 0)]);
|
|
254
|
+
$connection->table('orders')->insert(['uuid' => 'order-1', 'company_uuid' => 'company-1', 'payload_uuid' => 'payload-1', 'driver_assigned_uuid' => '44444444-4444-4444-8444-444444444444']);
|
|
255
|
+
|
|
256
|
+
$order = Order::query()->where('uuid', 'order-1')->first();
|
|
257
|
+
$origin = $order->getCurrentOriginPosition();
|
|
258
|
+
expect($origin?->getLat())->toBe(-37.78)
|
|
259
|
+
->and($origin?->getLng())->toBe(144.83);
|
|
260
|
+
|
|
261
|
+
$order->setPreliminaryDistanceAndTime();
|
|
262
|
+
$distance = (float) $connection->table('orders')->value('distance');
|
|
263
|
+
$time = (float) $connection->table('orders')->value('time');
|
|
264
|
+
expect($distance)->toBeGreaterThan(20000)->toBeLessThan(30000)
|
|
265
|
+
->and($time)->toBe(round($distance / 100) * 7.2);
|
|
266
|
+
|
|
267
|
+
$connection->table('orders')->where('uuid', 'order-1')->update(['distance' => null, 'time' => null]);
|
|
268
|
+
$order = Order::query()->where('uuid', 'order-1')->first();
|
|
269
|
+
$order->setDistanceAndTime(['provider' => 'calculate']);
|
|
270
|
+
expect((float) $connection->table('orders')->value('distance'))->toBe($distance)
|
|
271
|
+
->and((float) $connection->table('orders')->value('time'))->toBe($time);
|
|
272
|
+
|
|
273
|
+
// Once the driver reports a real position it becomes the origin again
|
|
274
|
+
$connection->table('drivers')->update(['location' => fleetopsOrderPayloadWkb(-37.70, 144.70)]);
|
|
275
|
+
$order = Order::query()->where('uuid', 'order-1')->first();
|
|
276
|
+
expect($order->getCurrentOriginPosition()?->getLat())->toBe(-37.70);
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
test('distance setters leave the order untouched when an endpoint is an ungeocoded placeholder', function () {
|
|
280
|
+
$connection = fleetopsOrderPayloadBoot();
|
|
281
|
+
$connection->table('places')->insert([
|
|
282
|
+
['uuid' => '11111111-1111-4111-8111-111111111111', 'public_id' => 'place_vicpickup', 'company_uuid' => 'company-1', 'location' => fleetopsOrderPayloadWkb(-37.78, 144.83)],
|
|
283
|
+
['uuid' => '22222222-2222-4222-8222-222222222222', 'public_id' => 'place_ungeocoded', 'company_uuid' => 'company-1', 'location' => fleetopsOrderPayloadWkb(0, 0)],
|
|
284
|
+
]);
|
|
285
|
+
$connection->table('payloads')->insert([
|
|
286
|
+
['uuid' => 'payload-1', 'company_uuid' => 'company-1', 'pickup_uuid' => '11111111-1111-4111-8111-111111111111', 'dropoff_uuid' => '22222222-2222-4222-8222-222222222222'],
|
|
287
|
+
['uuid' => 'payload-2', 'company_uuid' => 'company-1', 'pickup_uuid' => '22222222-2222-4222-8222-222222222222', 'dropoff_uuid' => '11111111-1111-4111-8111-111111111111'],
|
|
288
|
+
]);
|
|
289
|
+
$connection->table('orders')->insert([
|
|
290
|
+
['uuid' => 'order-1', 'company_uuid' => 'company-1', 'payload_uuid' => 'payload-1'],
|
|
291
|
+
['uuid' => 'order-2', 'company_uuid' => 'company-1', 'payload_uuid' => 'payload-2'],
|
|
292
|
+
]);
|
|
293
|
+
|
|
294
|
+
foreach (['order-1', 'order-2'] as $uuid) {
|
|
295
|
+
$order = Order::query()->where('uuid', $uuid)->first();
|
|
296
|
+
expect($order->setPreliminaryDistanceAndTime())->toBe($order)
|
|
297
|
+
->and($order->setDistanceAndTime(['provider' => 'calculate']))->toBe($order)
|
|
298
|
+
->and($connection->table('orders')->where('uuid', $uuid)->value('distance'))->toBeNull()
|
|
299
|
+
->and($connection->table('orders')->where('uuid', $uuid)->value('time'))->toBeNull();
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
|
|
243
303
|
test('config resolution prefers uuid then company default', function () {
|
|
244
304
|
$connection = fleetopsOrderPayloadBoot();
|
|
245
305
|
$flow = json_encode([
|
|
@@ -205,10 +205,12 @@ test('assign driver covers instance string and invalid identifier branches', fun
|
|
|
205
205
|
expect($assigned->assignDriver($driver))->toBe($assigned)
|
|
206
206
|
->and($assigned->notified)->toBe([]);
|
|
207
207
|
|
|
208
|
-
// Driver instance assignment
|
|
208
|
+
// Driver instance assignment saves; the order observer sends the assignment
|
|
209
|
+
// notification after the save, so assignDriver does not send it as well
|
|
209
210
|
$order->assignDriver($driver);
|
|
210
211
|
expect($order->driver_assigned_uuid)->toBe('driver-1')
|
|
211
|
-
->and($order->notified)->toBe([
|
|
212
|
+
->and($order->notified)->toBe([])
|
|
213
|
+
->and($order->silentDriverAssignment)->toBeFalse()
|
|
212
214
|
->and($connection->table('orders')->value('driver_assigned_uuid'))->toBe('driver-1');
|
|
213
215
|
|
|
214
216
|
// Public id resolution recurses into instance assignment
|
|
@@ -32,7 +32,8 @@ use Illuminate\Database\Eloquent\Relations\HasManyThrough;
|
|
|
32
32
|
use Illuminate\Database\Eloquent\Relations\HasOne;
|
|
33
33
|
use Illuminate\Database\SQLiteConnection;
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
// Extends the relation the model method now declares, so the override stays compatible; the parent constructor is skipped on purpose.
|
|
36
|
+
class FleetOpsPayloadUnitRelationCountFake extends HasManyThrough
|
|
36
37
|
{
|
|
37
38
|
public function __construct(private readonly Payload $payload, private readonly string $relation)
|
|
38
39
|
{
|
|
@@ -44,6 +45,19 @@ class FleetOpsPayloadUnitRelationCountFake
|
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
|
|
48
|
+
// Extends the relation the model method now declares, so the override stays compatible; the parent constructor is skipped on purpose.
|
|
49
|
+
class FleetOpsPayloadUnitEntityCountFake extends HasMany
|
|
50
|
+
{
|
|
51
|
+
public function __construct(private readonly Payload $payload)
|
|
52
|
+
{
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public function count(): int
|
|
56
|
+
{
|
|
57
|
+
return $this->payload->getRelation('entities')?->count() ?? 0;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
47
61
|
class FleetOpsPayloadUnitDatabaseProbe
|
|
48
62
|
{
|
|
49
63
|
public function __construct(private SQLiteConnection $connection)
|
|
@@ -147,14 +161,14 @@ class FleetOpsPayloadUnitFake extends Payload
|
|
|
147
161
|
public array $activityUpdates = [];
|
|
148
162
|
public array $currentWaypointWrites = [];
|
|
149
163
|
|
|
150
|
-
public function waypoints()
|
|
164
|
+
public function waypoints(): HasManyThrough
|
|
151
165
|
{
|
|
152
166
|
return new FleetOpsPayloadUnitRelationCountFake($this, 'waypoints');
|
|
153
167
|
}
|
|
154
168
|
|
|
155
|
-
public function entities()
|
|
169
|
+
public function entities(): HasMany
|
|
156
170
|
{
|
|
157
|
-
return new
|
|
171
|
+
return new FleetOpsPayloadUnitEntityCountFake($this);
|
|
158
172
|
}
|
|
159
173
|
|
|
160
174
|
public function hasMeta($key): bool
|
|
@@ -92,12 +92,12 @@ class FleetOpsServicableRate extends ServiceRate
|
|
|
92
92
|
return parent::getAttribute($key);
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
public function rateFees()
|
|
95
|
+
public function rateFees(): Illuminate\Database\Eloquent\Relations\HasMany
|
|
96
96
|
{
|
|
97
97
|
return $this->hasMany(Fleetbase\FleetOps\Models\ServiceRateFee::class, 'service_rate_uuid', 'uuid');
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
public function parcelFees()
|
|
100
|
+
public function parcelFees(): Illuminate\Database\Eloquent\Relations\HasMany
|
|
101
101
|
{
|
|
102
102
|
return $this->hasMany(Fleetbase\FleetOps\Models\ServiceRateParcelFee::class, 'service_rate_uuid', 'uuid');
|
|
103
103
|
}
|
|
@@ -84,13 +84,21 @@ class FleetOpsTrackingNumberInsertFake extends TrackingNumber
|
|
|
84
84
|
|
|
85
85
|
beforeEach(function () {
|
|
86
86
|
FleetOpsTrackingNumberInsertFake::resetInsertFake();
|
|
87
|
+
|
|
88
|
+
$this->previousConsoleConfig = config('fleetbase.console');
|
|
89
|
+
config(['fleetbase.console' => ['host' => 'console.fleetbase.test', 'subdomain' => null, 'secure' => true]]);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
afterEach(function () {
|
|
93
|
+
config(['fleetbase.console' => $this->previousConsoleConfig]);
|
|
87
94
|
});
|
|
88
95
|
|
|
89
96
|
test('tracking number insert filters values and creates initial owner status', function () {
|
|
90
97
|
$owner = new Order();
|
|
91
98
|
$owner->setRawAttributes([
|
|
92
|
-
'uuid'
|
|
93
|
-
'
|
|
99
|
+
'uuid' => 'order-uuid',
|
|
100
|
+
'public_id' => 'order_public',
|
|
101
|
+
'status' => 'pending',
|
|
94
102
|
], true);
|
|
95
103
|
|
|
96
104
|
$uuid = FleetOpsTrackingNumberInsertFake::insertGetUuid([
|
|
@@ -114,8 +122,10 @@ test('tracking number insert filters values and creates initial owner status', f
|
|
|
114
122
|
'owner_uuid' => 'order-uuid',
|
|
115
123
|
'owner_type' => Utils::getMutationType($owner),
|
|
116
124
|
'tracking_number' => 'TRACK-AE',
|
|
117
|
-
|
|
118
|
-
|
|
125
|
+
// The QR carries the tracking url naming the owner by public id, never its uuid;
|
|
126
|
+
// the barcode carries the bare tracking number printed beneath it.
|
|
127
|
+
'qr_code' => 'QRCODE,M:https://console.fleetbase.test/~/track-order?order=TRACK-AE&r=order_public&v=1',
|
|
128
|
+
'barcode' => 'C128:TRACK-AE',
|
|
119
129
|
'meta' => '{"source":"api"}',
|
|
120
130
|
])->and($inserted)->not->toHaveKey('not_allowed');
|
|
121
131
|
|
|
@@ -147,8 +157,8 @@ test('tracking number insert defaults region location and skips side effects whe
|
|
|
147
157
|
->and(FleetOpsTrackingNumberInsertFake::$insertedValues[0])->toMatchArray([
|
|
148
158
|
'uuid' => 'tracking-uuid',
|
|
149
159
|
'tracking_number' => 'TRACK-SG',
|
|
150
|
-
'qr_code' => 'QRCODE:',
|
|
151
|
-
'barcode' => '
|
|
160
|
+
'qr_code' => 'QRCODE,M:https://console.fleetbase.test/~/track-order?order=TRACK-SG&v=1',
|
|
161
|
+
'barcode' => 'C128:TRACK-SG',
|
|
152
162
|
])
|
|
153
163
|
->and(FleetOpsTrackingNumberInsertFake::$createdStatuses)->toBe([])
|
|
154
164
|
->and(FleetOpsTrackingNumberInsertFake::$statusUpdates)->toBe([])
|
|
@@ -197,3 +207,54 @@ test('tracking numbers generate unique values and resolve or fail lookups', func
|
|
|
197
207
|
->and(TrackingNumber::findTrackingOrFail('track_findone1')->uuid)->toBe('tn-find-1')
|
|
198
208
|
->and(fn () => TrackingNumber::findTrackingOrFail('missing-number'))->toThrow(Illuminate\Database\Eloquent\ModelNotFoundException::class);
|
|
199
209
|
});
|
|
210
|
+
|
|
211
|
+
test('tracking number insert takes the owner public id from callers without an owner model', function () {
|
|
212
|
+
// Waypoints and entities insert their owner with a raw query and pass only ids.
|
|
213
|
+
FleetOpsTrackingNumberInsertFake::insertGetUuid([
|
|
214
|
+
'owner_uuid' => 'waypoint-uuid',
|
|
215
|
+
'owner_type' => 'Fleetbase\\FleetOps\\Models\\Waypoint',
|
|
216
|
+
'owner_public_id' => 'waypoint_public',
|
|
217
|
+
'region' => 'SG',
|
|
218
|
+
]);
|
|
219
|
+
|
|
220
|
+
$inserted = FleetOpsTrackingNumberInsertFake::$insertedValues[0];
|
|
221
|
+
|
|
222
|
+
expect($inserted['qr_code'])->toBe('QRCODE,M:https://console.fleetbase.test/~/track-order?order=TRACK-SG&r=waypoint_public&v=1')
|
|
223
|
+
// A helper key, not a column: the fillable filter keeps it out of the insert.
|
|
224
|
+
->and($inserted)->not->toHaveKey('owner_public_id')
|
|
225
|
+
->and($inserted['owner_uuid'])->toBe('waypoint-uuid');
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
test('tracking number code images render a medium-correction QR and a Code 128 barcode', function () {
|
|
229
|
+
$calls = new ArrayObject();
|
|
230
|
+
foreach (['DNS2D', 'DNS1D'] as $facade) {
|
|
231
|
+
app()->instance($facade, new class($facade, $calls) {
|
|
232
|
+
public function __construct(private string $facade, private ArrayObject $calls)
|
|
233
|
+
{
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
public function getBarcodePNG(...$arguments)
|
|
237
|
+
{
|
|
238
|
+
$this->calls[] = array_merge([$this->facade], $arguments);
|
|
239
|
+
|
|
240
|
+
return $this->facade . '-png';
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
Illuminate\Support\Facades\Facade::clearResolvedInstance($facade);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
try {
|
|
247
|
+
expect(TrackingNumber::codeImages('ACM1234567890SG', 'entity_public'))->toBe([
|
|
248
|
+
'qr_code' => 'DNS2D-png',
|
|
249
|
+
'barcode' => 'DNS1D-png',
|
|
250
|
+
])->and($calls->getArrayCopy())->toBe([
|
|
251
|
+
['DNS2D', 'https://console.fleetbase.test/~/track-order?order=ACM1234567890SG&r=entity_public&v=1', 'QRCODE,M'],
|
|
252
|
+
['DNS1D', 'ACM1234567890SG', 'C128', 2, 60],
|
|
253
|
+
]);
|
|
254
|
+
} finally {
|
|
255
|
+
foreach (['DNS2D', 'DNS1D'] as $facade) {
|
|
256
|
+
app()->forgetInstance($facade);
|
|
257
|
+
Illuminate\Support\Facades\Facade::clearResolvedInstance($facade);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
});
|
|
@@ -100,6 +100,17 @@ class FleetOpsVehicleModelFindResultFake
|
|
|
100
100
|
{
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
public function where($column, $operator = null): static
|
|
104
|
+
{
|
|
105
|
+
if (is_callable($column)) {
|
|
106
|
+
$column($this->query);
|
|
107
|
+
} else {
|
|
108
|
+
$this->query->calls[] = ['where', [$column, $operator]];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return $this;
|
|
112
|
+
}
|
|
113
|
+
|
|
103
114
|
public function first(): ?Vehicle
|
|
104
115
|
{
|
|
105
116
|
return $this->result;
|
|
@@ -117,6 +128,8 @@ class FleetOpsVehicleModelFindableFake extends Vehicle
|
|
|
117
128
|
|
|
118
129
|
if (is_callable($column)) {
|
|
119
130
|
$column($query);
|
|
131
|
+
} else {
|
|
132
|
+
$query->calls[] = ['where', [$column, $operator]];
|
|
120
133
|
}
|
|
121
134
|
|
|
122
135
|
self::$lastQuery = $query;
|
|
@@ -258,9 +271,10 @@ test('vehicle import parses single vehicle name and find by name builds identifi
|
|
|
258
271
|
FleetOpsVehicleModelFindableFake::$result = $found;
|
|
259
272
|
|
|
260
273
|
expect(FleetOpsVehicleModelFindableFake::findByName('ABC-123'))->toBe($found)
|
|
274
|
+
->and(FleetOpsVehicleModelFindableFake::$lastQuery->calls[0])->toBe(['where', ['company_uuid', 'company-vehicle']])
|
|
261
275
|
->and(FleetOpsVehicleModelFindableFake::$lastQuery->calls)->toContain(['where', ['public_id', 'ABC-123']])
|
|
262
276
|
->and(FleetOpsVehicleModelFindableFake::$lastQuery->calls)->toContain(['orWhere', ['plate_number', 'ABC-123']])
|
|
263
277
|
->and(FleetOpsVehicleModelFindableFake::$lastQuery->calls)->toContain(['orWhere', ['fuel_card_number', 'ABC-123']])
|
|
264
|
-
->and(FleetOpsVehicleModelFindableFake::$lastQuery->calls[
|
|
265
|
-
->and(FleetOpsVehicleModelFindableFake::$lastQuery->calls[
|
|
278
|
+
->and(FleetOpsVehicleModelFindableFake::$lastQuery->calls[8][0])->toBe('orWhereRaw')
|
|
279
|
+
->and(FleetOpsVehicleModelFindableFake::$lastQuery->calls[9][0])->toBe('orWhereRaw');
|
|
266
280
|
});
|
|
@@ -218,9 +218,10 @@ test('waypoint insert filters values and creates payload tracking number', funct
|
|
|
218
218
|
])->and($inserted)->not->toHaveKey('not_allowed')
|
|
219
219
|
->and(FleetOpsWaypointInsertFake::$createdTracking)->toHaveCount(1)
|
|
220
220
|
->and(FleetOpsWaypointInsertFake::$createdTracking[0])->toMatchArray([
|
|
221
|
-
'owner_uuid'
|
|
222
|
-
'owner_type'
|
|
223
|
-
'
|
|
221
|
+
'owner_uuid' => 'waypoint-uuid',
|
|
222
|
+
'owner_type' => Utils::getModelClassName('waypoint'),
|
|
223
|
+
'owner_public_id' => FleetOpsWaypointInsertFake::$insertedValues[0]['public_id'],
|
|
224
|
+
'region' => 'AE',
|
|
224
225
|
])
|
|
225
226
|
->and(FleetOpsWaypointInsertFake::$createdTracking[0]['location'])->toBe('POINT(55.2708 25.2048)')
|
|
226
227
|
->and(FleetOpsWaypointInsertFake::$trackingNumberWrites)->toBe([
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
use Fleetbase\FleetOps\Models\Order;
|
|
4
|
+
use Fleetbase\FleetOps\Models\TrackingNumber;
|
|
5
|
+
use Fleetbase\FleetOps\Notifications\OrderChanged;
|
|
6
|
+
use Fleetbase\FleetOps\Notifications\OrderUnassigned;
|
|
7
|
+
use NotificationChannels\Apn\ApnChannel;
|
|
8
|
+
use NotificationChannels\Fcm\FcmChannel;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Covers the driver pushes for order changes and unassignment: their titles,
|
|
12
|
+
* bodies and the data the apps read.
|
|
13
|
+
*/
|
|
14
|
+
function fleetopsOrderChangeNotificationOrder(): Order
|
|
15
|
+
{
|
|
16
|
+
$trackingNumber = new TrackingNumber();
|
|
17
|
+
$trackingNumber->setRawAttributes(['uuid' => 'tn-1', 'tracking_number' => 'FLB-CHANGE-1'], true);
|
|
18
|
+
|
|
19
|
+
$order = new Order();
|
|
20
|
+
$order->setRawAttributes([
|
|
21
|
+
'uuid' => 'order-uuid',
|
|
22
|
+
'public_id' => 'order_change',
|
|
23
|
+
'company_uuid' => 'company-1',
|
|
24
|
+
'driver_assigned_uuid' => 'driver-uuid',
|
|
25
|
+
], true);
|
|
26
|
+
$order->setRelation('trackingNumber', $trackingNumber);
|
|
27
|
+
$order->setRelation('driverAssigned', null);
|
|
28
|
+
|
|
29
|
+
return $order;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
test('order changed pushes the changes to the driver with fcm safe data', function () {
|
|
33
|
+
$notification = new OrderChanged(fleetopsOrderChangeNotificationOrder(), ['dropoff', 'items'], 'Drop-off changed to 8 Marina View · Items changed');
|
|
34
|
+
|
|
35
|
+
expect($notification->title)->toBe('Order FLB-CHANGE-1 changed')
|
|
36
|
+
->and($notification->message)->toBe('Drop-off changed to 8 Marina View · Items changed')
|
|
37
|
+
->and($notification->data)->toBe(['type' => 'order_changed', 'id' => 'order_change', 'changes' => ['dropoff', 'items']])
|
|
38
|
+
->and($notification->fcmData())->toBe(['type' => 'order_changed', 'id' => 'order_change', 'changes' => 'dropoff,items'])
|
|
39
|
+
->and($notification->via(null))->toBe(['broadcast', FcmChannel::class, ApnChannel::class])
|
|
40
|
+
->and($notification->toArray())->toMatchArray(['event' => 'order.changed_notification', 'data' => $notification->data])
|
|
41
|
+
->and(array_map(fn ($channel) => $channel->name, $notification->broadcastOn()))->toContain('driver.driver-uuid')
|
|
42
|
+
->and((new OrderChanged(fleetopsOrderChangeNotificationOrder()))->message)->toBe('This order was changed, tap for details.');
|
|
43
|
+
|
|
44
|
+
// The push builders reach for the FCM and APN clients, which the harness does not configure
|
|
45
|
+
expect(fn () => $notification->toFcm(null))->toThrow(Exception::class)
|
|
46
|
+
->and(fn () => $notification->toApn(null))->toThrow(Error::class);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('order unassigned tells the driver the order is no longer theirs', function () {
|
|
50
|
+
$notification = new OrderUnassigned(fleetopsOrderChangeNotificationOrder());
|
|
51
|
+
|
|
52
|
+
expect($notification->title)->toBe('Order FLB-CHANGE-1 unassigned')
|
|
53
|
+
->and($notification->data)->toBe(['type' => 'order_unassigned', 'id' => 'order_change'])
|
|
54
|
+
->and($notification->via(null))->toBe([FcmChannel::class, ApnChannel::class])
|
|
55
|
+
->and($notification->toArray()['event'])->toBe('order.unassigned_notification');
|
|
56
|
+
|
|
57
|
+
expect(fn () => $notification->toFcm(null))->toThrow(Exception::class)
|
|
58
|
+
->and(fn () => $notification->toApn(null))->toThrow(Error::class);
|
|
59
|
+
});
|
|
@@ -141,7 +141,7 @@ test('completed order notification formats mail and array payloads from order tr
|
|
|
141
141
|
'No further action is necessary.'
|
|
142
142
|
)
|
|
143
143
|
->and($mail->actionText)->toBe('Track Order')
|
|
144
|
-
->and($mail->actionUrl)->
|
|
144
|
+
->and($mail->actionUrl)->toBe('https://console.fleetbase.test/~/track/ORDER-TRACK');
|
|
145
145
|
});
|
|
146
146
|
|
|
147
147
|
test('failed order notification formats mail and array payloads from waypoint tracking', function () {
|
|
@@ -166,7 +166,7 @@ test('failed order notification formats mail and array payloads from waypoint tr
|
|
|
166
166
|
'No further action is necessary.'
|
|
167
167
|
)
|
|
168
168
|
->and($mail->actionText)->toBe('Track Order')
|
|
169
|
-
->and($mail->actionUrl)->
|
|
169
|
+
->and($mail->actionUrl)->toBe('https://console.fleetbase.test/~/track/WP-FAILED');
|
|
170
170
|
});
|
|
171
171
|
|
|
172
172
|
test('dispatched order notification formats mail from waypoint tracking fallback', function () {
|
|
@@ -181,5 +181,5 @@ test('dispatched order notification formats mail from waypoint tracking fallback
|
|
|
181
181
|
->and($mail->subject)->toBe('Order WP-DISPATCHED has been dispatched!')
|
|
182
182
|
->and($mail->introLines)->toBe(['An order has just been dispatched to you and is ready to be started.'])
|
|
183
183
|
->and($mail->actionText)->toBe('Track Order')
|
|
184
|
-
->and($mail->actionUrl)->
|
|
184
|
+
->and($mail->actionUrl)->toBe('https://console.fleetbase.test/~/track/WP-DISPATCHED');
|
|
185
185
|
});
|