@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
|
@@ -130,12 +130,13 @@ class FleetOpsPasswordDriverFake extends Driver
|
|
|
130
130
|
|
|
131
131
|
class FleetOpsPasswordControllerProbe extends DriverController
|
|
132
132
|
{
|
|
133
|
-
public static ?Driver $driver
|
|
134
|
-
public static bool $driverMissing
|
|
135
|
-
public static ?User $identityUser
|
|
136
|
-
public static mixed $resetCode
|
|
137
|
-
public static array $sentCodes
|
|
138
|
-
public static bool $sendThrows
|
|
133
|
+
public static ?Driver $driver = null;
|
|
134
|
+
public static bool $driverMissing = false;
|
|
135
|
+
public static ?User $identityUser = null;
|
|
136
|
+
public static mixed $resetCode = null;
|
|
137
|
+
public static array $sentCodes = [];
|
|
138
|
+
public static bool $sendThrows = false;
|
|
139
|
+
public static ?Throwable $sendRefusal = null;
|
|
139
140
|
|
|
140
141
|
public function findDriver(string $id, array $with = []): Driver
|
|
141
142
|
{
|
|
@@ -180,6 +181,9 @@ class FleetOpsPasswordControllerProbe extends DriverController
|
|
|
180
181
|
|
|
181
182
|
protected static function sendResetCode(User $user, string $identity): void
|
|
182
183
|
{
|
|
184
|
+
if (static::$sendRefusal) {
|
|
185
|
+
throw static::$sendRefusal;
|
|
186
|
+
}
|
|
183
187
|
if (static::$sendThrows) {
|
|
184
188
|
throw new RuntimeException('sms gateway down');
|
|
185
189
|
}
|
|
@@ -205,6 +209,7 @@ beforeEach(function () {
|
|
|
205
209
|
FleetOpsPasswordControllerProbe::$resetCode = null;
|
|
206
210
|
FleetOpsPasswordControllerProbe::$sentCodes = [];
|
|
207
211
|
FleetOpsPasswordControllerProbe::$sendThrows = false;
|
|
212
|
+
FleetOpsPasswordControllerProbe::$sendRefusal = null;
|
|
208
213
|
});
|
|
209
214
|
|
|
210
215
|
test('change password requires both the current and the new one', function () {
|
|
@@ -331,6 +336,16 @@ test('forgot password reports a delivery failure rather than pretending it sent'
|
|
|
331
336
|
expect($response->getStatusCode())->toBe(400);
|
|
332
337
|
});
|
|
333
338
|
|
|
339
|
+
test('forgot password passes an sms guard refusal through with its status', function () {
|
|
340
|
+
FleetOpsPasswordControllerProbe::$identityUser = fleetopsPasswordUser();
|
|
341
|
+
FleetOpsPasswordControllerProbe::$sendRefusal = Fleetbase\Exceptions\SmsBlockedException::limited('destination_cooldown', 30);
|
|
342
|
+
|
|
343
|
+
$response = (new FleetOpsPasswordControllerProbe())->forgotPassword(new Request(['identity' => '+6581000001']));
|
|
344
|
+
|
|
345
|
+
expect($response->getStatusCode())->toBe(429)
|
|
346
|
+
->and($response->getData())->toBe(['error' => 'Unable to send a verification code right now. Try again in a minute.']);
|
|
347
|
+
});
|
|
348
|
+
|
|
334
349
|
test('reset password requires identity, code and a new password', function () {
|
|
335
350
|
$response = (new FleetOpsPasswordControllerProbe())->resetPassword(new Request(['identity' => 'a@b.test']));
|
|
336
351
|
|
|
@@ -362,23 +377,13 @@ test('reset password gives one answer for an unknown identity and a bad code ali
|
|
|
362
377
|
->and($unknownIdentity->getData())->toBe($badCode->getData());
|
|
363
378
|
});
|
|
364
379
|
|
|
365
|
-
test('reset password sets the password
|
|
380
|
+
test('reset password sets the password and ends every session once the code verified', function () {
|
|
366
381
|
$user = fleetopsPasswordUser();
|
|
367
382
|
FleetOpsPasswordControllerProbe::$identityUser = $user;
|
|
368
383
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
{
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
public function delete(): bool
|
|
376
|
-
{
|
|
377
|
-
$this->deleted = true;
|
|
378
|
-
|
|
379
|
-
return true;
|
|
380
|
-
}
|
|
381
|
-
};
|
|
384
|
+
// findResetCode() hands back the code it verified and used up; nothing more is done
|
|
385
|
+
// to it here.
|
|
386
|
+
FleetOpsPasswordControllerProbe::$resetCode = (object) ['uuid' => 'reset-code'];
|
|
382
387
|
|
|
383
388
|
$response = (new FleetOpsPasswordControllerProbe())->resetPassword(
|
|
384
389
|
new Request(['identity' => 'driver@example.test', 'code' => '123456', 'password' => 'newpassword'])
|
|
@@ -386,7 +391,6 @@ test('reset password sets the password, spends the code, and ends every session'
|
|
|
386
391
|
|
|
387
392
|
expect($response->getStatusCode())->toBe(200)
|
|
388
393
|
->and($user->saved)->toHaveCount(1)
|
|
389
|
-
->and($deleted)->toBeTrue()
|
|
390
394
|
// A reset is a recovery from losing control; nothing keeps working.
|
|
391
395
|
->and($user->tokensDeleted)->toBeTrue();
|
|
392
396
|
});
|
|
@@ -4,8 +4,11 @@ use Fleetbase\FleetOps\Http\Controllers\Api\v1\EntityController;
|
|
|
4
4
|
use Fleetbase\FleetOps\Http\Requests\CreateEntityRequest;
|
|
5
5
|
use Fleetbase\FleetOps\Http\Requests\UpdateEntityRequest;
|
|
6
6
|
use Fleetbase\FleetOps\Models\Entity;
|
|
7
|
+
use Fleetbase\FleetOps\Models\Order;
|
|
7
8
|
use Fleetbase\FleetOps\Models\Payload;
|
|
8
9
|
use Fleetbase\FleetOps\Models\Place;
|
|
10
|
+
use Fleetbase\FleetOps\Support\OrderEdit;
|
|
11
|
+
use Fleetbase\FleetOps\Support\OrderEditPolicy;
|
|
9
12
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
|
10
13
|
use Illuminate\Http\Request;
|
|
11
14
|
|
|
@@ -327,3 +330,84 @@ test('api entity controller returns not found responses for missing entities', f
|
|
|
327
330
|
'status' => 404,
|
|
328
331
|
]);
|
|
329
332
|
})->with(['update', 'find', 'delete']);
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Entities that belong to an order: the order's edit uses the real lock policy and records its commit.
|
|
336
|
+
*/
|
|
337
|
+
class FleetOpsApiEntityOrderControllerProbe extends FleetOpsApiEntityControllerProbe
|
|
338
|
+
{
|
|
339
|
+
public ?Order $order = null;
|
|
340
|
+
|
|
341
|
+
public array $edits = [];
|
|
342
|
+
|
|
343
|
+
protected function orderEditForPayload(?string $payloadUuid): ?OrderEdit
|
|
344
|
+
{
|
|
345
|
+
if (!$this->order) {
|
|
346
|
+
return null;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return $this->edits[] = new FleetOpsApiEntityOrderEditFake($this->order);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
class FleetOpsApiEntityOrderEditFake extends OrderEdit
|
|
354
|
+
{
|
|
355
|
+
public int $commits = 0;
|
|
356
|
+
|
|
357
|
+
public function __construct(public Order $order)
|
|
358
|
+
{
|
|
359
|
+
$this->policy = OrderEditPolicy::for($order);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
public function commit(array $extra = [], bool $notifyDriver = true): array
|
|
363
|
+
{
|
|
364
|
+
$this->commits++;
|
|
365
|
+
|
|
366
|
+
return ['items'];
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
function fleetopsApiEntityOrderController(string $status): FleetOpsApiEntityOrderControllerProbe
|
|
371
|
+
{
|
|
372
|
+
$controller = new FleetOpsApiEntityOrderControllerProbe();
|
|
373
|
+
$controller->order = new Order();
|
|
374
|
+
$controller->order->setRawAttributes(['uuid' => 'order-uuid', 'public_id' => 'order_entity', 'status' => $status], true);
|
|
375
|
+
$controller->entity = new FleetOpsApiEntityFake();
|
|
376
|
+
$controller->entity->setRawAttributes(['uuid' => 'entity-uuid', 'payload_uuid' => 'payload-uuid'], true);
|
|
377
|
+
|
|
378
|
+
return $controller;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
test('api entity controller announces item edits on orders that allow them', function () {
|
|
382
|
+
$controller = fleetopsApiEntityOrderController('created');
|
|
383
|
+
|
|
384
|
+
$controller->create(new FleetOpsCreateEntityRequestFake(['name' => 'Latte', 'payload' => 'payload_public']));
|
|
385
|
+
$controller->update('entity_public', new FleetOpsUpdateEntityRequestFake(['name' => 'Iced Latte']));
|
|
386
|
+
$controller->delete('entity_public', new Request());
|
|
387
|
+
|
|
388
|
+
expect(array_map(fn ($edit) => $edit->commits, $controller->edits))->toBe([1, 1, 1])
|
|
389
|
+
->and($controller->createdEntities)->toHaveCount(1)
|
|
390
|
+
->and($controller->entity->deletedForTest)->toBeTrue();
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
test('api entity controller refuses item edits the order status locks', function () {
|
|
394
|
+
$dispatched = fleetopsApiEntityOrderController('dispatched');
|
|
395
|
+
$created = $dispatched->create(new FleetOpsCreateEntityRequestFake(['name' => 'Latte', 'payload' => 'payload_public']));
|
|
396
|
+
$deleted = $dispatched->delete('entity_public', new Request());
|
|
397
|
+
|
|
398
|
+
expect($created->getStatusCode())->toBe(422)
|
|
399
|
+
->and($created->getData(true)['locked'])->toBe(['items' => 'Items cannot be changed once a driver has the order.'])
|
|
400
|
+
->and($deleted->getStatusCode())->toBe(422)
|
|
401
|
+
->and($dispatched->createdEntities)->toBe([])
|
|
402
|
+
->and($dispatched->entity->deletedForTest)->toBeFalse();
|
|
403
|
+
|
|
404
|
+
// once ready, an item may be removed but not changed
|
|
405
|
+
$ready = fleetopsApiEntityOrderController('ready');
|
|
406
|
+
$updated = $ready->update('entity_public', new FleetOpsUpdateEntityRequestFake(['name' => 'Iced Latte']));
|
|
407
|
+
$ready->delete('entity_public', new Request());
|
|
408
|
+
|
|
409
|
+
expect($updated->getStatusCode())->toBe(422)
|
|
410
|
+
->and($updated->getData(true)['error'])->toBe('Once the order is ready, items can only be removed.')
|
|
411
|
+
->and($ready->entity->updatedPayloads)->toBe([])
|
|
412
|
+
->and($ready->entity->deletedForTest)->toBeTrue();
|
|
413
|
+
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<?php
|
|
2
2
|
|
|
3
|
+
use Fleetbase\FleetOps\Exceptions\OrderEditLockedException;
|
|
3
4
|
use Fleetbase\FleetOps\Http\Controllers\Api\v1\OrderController;
|
|
4
5
|
use Fleetbase\FleetOps\Http\Requests\CreateOrderRequest;
|
|
5
6
|
use Fleetbase\FleetOps\Http\Requests\ScheduleOrderRequest;
|
|
@@ -12,6 +13,8 @@ use Fleetbase\FleetOps\Models\Place;
|
|
|
12
13
|
use Fleetbase\FleetOps\Models\Proof;
|
|
13
14
|
use Fleetbase\FleetOps\Models\ServiceQuote;
|
|
14
15
|
use Fleetbase\FleetOps\Models\Waypoint;
|
|
16
|
+
use Fleetbase\FleetOps\Support\OrderEdit;
|
|
17
|
+
use Fleetbase\FleetOps\Support\OrderEditPolicy;
|
|
15
18
|
use Fleetbase\FleetOps\Support\OrderTracker;
|
|
16
19
|
use Fleetbase\Models\File;
|
|
17
20
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
|
@@ -41,6 +44,8 @@ class FleetOpsApiOrderCrudControllerProbe extends OrderController
|
|
|
41
44
|
public bool $missingOrderConfig = false;
|
|
42
45
|
public mixed $resolvedSubject = null;
|
|
43
46
|
public ?string $companyUuid = 'company-uuid';
|
|
47
|
+
public ?FleetOpsApiOrderEditFake $edit = null;
|
|
48
|
+
public array $editLockedWith = [];
|
|
44
49
|
|
|
45
50
|
protected function findOrder(string $id, array $with = [], array $withCount = []): Order
|
|
46
51
|
{
|
|
@@ -54,6 +59,26 @@ class FleetOpsApiOrderCrudControllerProbe extends OrderController
|
|
|
54
59
|
return $this->order;
|
|
55
60
|
}
|
|
56
61
|
|
|
62
|
+
public ?FleetOpsApiOrderPayloadFake $switchedPayload = null;
|
|
63
|
+
|
|
64
|
+
protected function findPayloadByUuid(?string $uuid): ?Payload
|
|
65
|
+
{
|
|
66
|
+
return $this->switchedPayload;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
protected function beginOrderEdit(Order $order): OrderEdit
|
|
70
|
+
{
|
|
71
|
+
$this->edit ??= new FleetOpsApiOrderEditFake($order);
|
|
72
|
+
$this->edit->lockWith = $this->editLockedWith;
|
|
73
|
+
|
|
74
|
+
return $this->edit;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
protected function lockedEditResponse(OrderEditLockedException $exception)
|
|
78
|
+
{
|
|
79
|
+
return ['apiError' => $exception->getMessage(), 'status' => 422, 'locked' => $exception->locked];
|
|
80
|
+
}
|
|
81
|
+
|
|
57
82
|
protected function drivingDistanceAndTime(mixed $origin, mixed $destination): mixed
|
|
58
83
|
{
|
|
59
84
|
return $this->matrix ?? (object) ['distance' => 1200, 'time' => 360];
|
|
@@ -244,6 +269,43 @@ class FleetOpsApiOrderCrudControllerProbe extends OrderController
|
|
|
244
269
|
}
|
|
245
270
|
}
|
|
246
271
|
|
|
272
|
+
/**
|
|
273
|
+
* Records the edit guard and commit instead of reading and announcing through the database.
|
|
274
|
+
*/
|
|
275
|
+
class FleetOpsApiOrderEditFake extends OrderEdit
|
|
276
|
+
{
|
|
277
|
+
public array $guarded = [];
|
|
278
|
+
public array $lockWith = [];
|
|
279
|
+
public int $commits = 0;
|
|
280
|
+
|
|
281
|
+
public function __construct(public Order $order)
|
|
282
|
+
{
|
|
283
|
+
$this->policy = OrderEditPolicy::for($order);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
public function requestedChanges(array $input, string $entitiesMode = self::ENTITIES_APPEND): array
|
|
287
|
+
{
|
|
288
|
+
return ['input' => $input, 'entities_mode' => $entitiesMode];
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
public function guard(array $changes): static
|
|
292
|
+
{
|
|
293
|
+
$this->guarded[] = $changes;
|
|
294
|
+
if ($this->lockWith) {
|
|
295
|
+
throw new OrderEditLockedException($this->lockWith);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return $this;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
public function commit(array $extra = [], bool $notifyDriver = true): array
|
|
302
|
+
{
|
|
303
|
+
$this->commits++;
|
|
304
|
+
|
|
305
|
+
return [];
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
247
309
|
class FleetOpsApiOrderCrudFake extends Order
|
|
248
310
|
{
|
|
249
311
|
public array $lookups = [];
|
|
@@ -383,6 +445,16 @@ class FleetOpsApiOrderCrudFake extends Order
|
|
|
383
445
|
return $this;
|
|
384
446
|
}
|
|
385
447
|
|
|
448
|
+
public ?string $cancelReasonForTest = null;
|
|
449
|
+
|
|
450
|
+
public function cancelWithReason(?string $reason = null)
|
|
451
|
+
{
|
|
452
|
+
$this->cancelledForTest = true;
|
|
453
|
+
$this->cancelReasonForTest = $reason;
|
|
454
|
+
|
|
455
|
+
return $this;
|
|
456
|
+
}
|
|
457
|
+
|
|
386
458
|
public function tracker(): OrderTracker
|
|
387
459
|
{
|
|
388
460
|
return $this->trackerFake;
|
|
@@ -447,6 +519,13 @@ class FleetOpsApiOrderPayloadFake extends Payload
|
|
|
447
519
|
return $this;
|
|
448
520
|
}
|
|
449
521
|
|
|
522
|
+
public function syncEntities($entities = []): array
|
|
523
|
+
{
|
|
524
|
+
$this->calls[] = ['sync-entities', $entities];
|
|
525
|
+
|
|
526
|
+
return ['created' => [], 'updated' => [], 'deleted' => []];
|
|
527
|
+
}
|
|
528
|
+
|
|
450
529
|
public function setCurrentWaypoint(Place|Waypoint $destination, bool $save = true): Payload
|
|
451
530
|
{
|
|
452
531
|
$this->calls[] = ['current', $destination instanceof Place, $save];
|
|
@@ -753,6 +832,25 @@ test('api order controller updates by payload id and clears route waypoints', fu
|
|
|
753
832
|
->and($payload->removedWaypoints)->toBeTrue();
|
|
754
833
|
});
|
|
755
834
|
|
|
835
|
+
test('api order controller moves the cash to collect onto the payload it switches to by id', function () {
|
|
836
|
+
$order = new FleetOpsApiOrderCrudFake();
|
|
837
|
+
$order->payload = new FleetOpsApiOrderPayloadFake();
|
|
838
|
+
$switched = new FleetOpsApiOrderPayloadFake();
|
|
839
|
+
|
|
840
|
+
$controller = new FleetOpsApiOrderCrudControllerProbe();
|
|
841
|
+
$controller->order = $order;
|
|
842
|
+
$controller->switchedPayload = $switched;
|
|
843
|
+
|
|
844
|
+
$controller->update('order-public', new FleetOpsApiOrderUpdateRequestFake([
|
|
845
|
+
'payload' => 'payload_public',
|
|
846
|
+
'cod_amount' => '1800',
|
|
847
|
+
]));
|
|
848
|
+
|
|
849
|
+
expect($order->updates[0])->toMatchArray(['payload_uuid' => 'payloads-uuid'])
|
|
850
|
+
->and($switched->getAttributes()['cod_amount'])->toBe(1800)
|
|
851
|
+
->and($switched->savedForTest)->toBeTrue();
|
|
852
|
+
});
|
|
853
|
+
|
|
756
854
|
test('api order controller finds deletes and updates distance matrices without database records', function () {
|
|
757
855
|
$order = new FleetOpsApiOrderCrudFake();
|
|
758
856
|
$controller = new FleetOpsApiOrderCrudControllerProbe();
|
|
@@ -1028,3 +1126,150 @@ test('api order controller captures QR proof payloads and validates error branch
|
|
|
1028
1126
|
'status' => 400,
|
|
1029
1127
|
]);
|
|
1030
1128
|
});
|
|
1129
|
+
|
|
1130
|
+
test('api order controller captures QR proof from tracking url codes and barcodes', function () {
|
|
1131
|
+
session(['company' => 'company-uuid']);
|
|
1132
|
+
|
|
1133
|
+
$subject = (object) [
|
|
1134
|
+
'uuid' => 'subject-uuid',
|
|
1135
|
+
'public_id' => 'waypoint_subject',
|
|
1136
|
+
'trackingNumber' => (object) ['tracking_number' => 'ACM1234567890SG'],
|
|
1137
|
+
];
|
|
1138
|
+
|
|
1139
|
+
// The url printed by current labels, from any host, and the Code 128 barcode.
|
|
1140
|
+
foreach ([
|
|
1141
|
+
'https://console.fleetbase.test/track-order?order=ACM1234567890SG&r=waypoint_subject&v=1',
|
|
1142
|
+
'https://old-host.example/track-order?order=ACM1234567890SG&r=waypoint_subject&v=1',
|
|
1143
|
+
'ACM1234567890SG',
|
|
1144
|
+
] as $code) {
|
|
1145
|
+
$controller = new FleetOpsApiOrderCrudControllerProbe();
|
|
1146
|
+
$controller->order = new FleetOpsApiOrderCrudFake();
|
|
1147
|
+
$controller->resolvedSubject = $subject;
|
|
1148
|
+
|
|
1149
|
+
expect($controller->captureQrScan(new Request(['code' => $code]), 'order-public', 'waypoint_subject')['resource'])->toBe('proof')
|
|
1150
|
+
->and($controller->createdProofs[0]['subject_uuid'])->toBe('subject-uuid');
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
// A scanner's whole result object, rather than its value, is refused as before
|
|
1154
|
+
// instead of failing the request.
|
|
1155
|
+
$controller = new FleetOpsApiOrderCrudControllerProbe();
|
|
1156
|
+
$controller->order = new FleetOpsApiOrderCrudFake();
|
|
1157
|
+
$controller->resolvedSubject = $subject;
|
|
1158
|
+
|
|
1159
|
+
expect($controller->captureQrScan(new Request(['code' => ['type' => 'qr', 'value' => 'ACM1234567890SG']]), 'order-public', 'waypoint_subject'))->toBe([
|
|
1160
|
+
'apiError' => 'Unable to validate QR code data.',
|
|
1161
|
+
'status' => 400,
|
|
1162
|
+
]);
|
|
1163
|
+
|
|
1164
|
+
// Another parcel's label is refused, whether it names another owner or, naming none,
|
|
1165
|
+
// another tracking number.
|
|
1166
|
+
foreach ([
|
|
1167
|
+
'https://console.fleetbase.test/track-order?order=ACM1234567890SG&r=waypoint_other&v=1',
|
|
1168
|
+
'https://console.fleetbase.test/track-order?order=ACM0000000000SG&v=1',
|
|
1169
|
+
] as $code) {
|
|
1170
|
+
$controller = new FleetOpsApiOrderCrudControllerProbe();
|
|
1171
|
+
$controller->order = new FleetOpsApiOrderCrudFake();
|
|
1172
|
+
$controller->resolvedSubject = $subject;
|
|
1173
|
+
|
|
1174
|
+
expect($controller->captureQrScan(new Request(['code' => $code]), 'order-public', 'waypoint_subject'))->toBe([
|
|
1175
|
+
'apiError' => 'Unable to validate QR code data.',
|
|
1176
|
+
'status' => 400,
|
|
1177
|
+
])->and($controller->createdProofs)->toBe([]);
|
|
1178
|
+
}
|
|
1179
|
+
});
|
|
1180
|
+
|
|
1181
|
+
test('api order controller refuses order edits the status locks with a 422 and writes nothing', function () {
|
|
1182
|
+
$order = new FleetOpsApiOrderCrudFake(['status' => 'completed']);
|
|
1183
|
+
$payload = new FleetOpsApiOrderPayloadFake();
|
|
1184
|
+
$order->payload = $payload;
|
|
1185
|
+
|
|
1186
|
+
$controller = new FleetOpsApiOrderCrudControllerProbe();
|
|
1187
|
+
$controller->order = $order;
|
|
1188
|
+
$controller->editLockedWith = ['dropoff' => 'The order is completed and can no longer be changed.'];
|
|
1189
|
+
|
|
1190
|
+
$response = $controller->update('order-public', new FleetOpsApiOrderUpdateRequestFake([
|
|
1191
|
+
'payload' => ['dropoff' => ['name' => 'Somewhere else']],
|
|
1192
|
+
]));
|
|
1193
|
+
|
|
1194
|
+
expect($response)->toBe([
|
|
1195
|
+
'apiError' => 'The order is completed and can no longer be changed.',
|
|
1196
|
+
'status' => 422,
|
|
1197
|
+
'locked' => ['dropoff' => 'The order is completed and can no longer be changed.'],
|
|
1198
|
+
])
|
|
1199
|
+
->and($payload->calls)->toBe([])
|
|
1200
|
+
->and($payload->savedForTest)->toBeFalse()
|
|
1201
|
+
->and($order->updates)->toBe([])
|
|
1202
|
+
->and($controller->edit->commits)->toBe(0);
|
|
1203
|
+
});
|
|
1204
|
+
|
|
1205
|
+
test('api order controller passes the edit to the guard, keeps cod 0, replaces entities and commits once', function () {
|
|
1206
|
+
$order = new FleetOpsApiOrderCrudFake(['status' => 'dispatched']);
|
|
1207
|
+
$payload = new FleetOpsApiOrderPayloadFake();
|
|
1208
|
+
$order->payload = $payload;
|
|
1209
|
+
|
|
1210
|
+
$controller = new FleetOpsApiOrderCrudControllerProbe();
|
|
1211
|
+
$controller->order = $order;
|
|
1212
|
+
|
|
1213
|
+
$controller->update('order-public', new FleetOpsApiOrderUpdateRequestFake([
|
|
1214
|
+
'payload' => [
|
|
1215
|
+
'dropoff' => ['name' => 'New drop'],
|
|
1216
|
+
'entities' => [['id' => 'entity_keep', 'name' => 'Latte']],
|
|
1217
|
+
'entities_mode' => 'replace',
|
|
1218
|
+
'cod_amount' => 0,
|
|
1219
|
+
],
|
|
1220
|
+
'notes' => 'Leave at the door',
|
|
1221
|
+
]));
|
|
1222
|
+
|
|
1223
|
+
expect($controller->edit->guarded)->toBe([[
|
|
1224
|
+
'input' => [
|
|
1225
|
+
'dropoff' => ['name' => 'New drop'],
|
|
1226
|
+
'entities' => [['id' => 'entity_keep', 'name' => 'Latte']],
|
|
1227
|
+
'notes' => 'Leave at the door',
|
|
1228
|
+
'cod_amount' => 0,
|
|
1229
|
+
],
|
|
1230
|
+
'entities_mode' => 'replace',
|
|
1231
|
+
]])
|
|
1232
|
+
->and($payload->calls)->toContain(['sync-entities', [['id' => 'entity_keep', 'name' => 'Latte']]])
|
|
1233
|
+
->and(collect($payload->calls)->where(0, 'entities')->all())->toBe([])
|
|
1234
|
+
->and($payload->getAttributes()['cod_amount'])->toBe(0)
|
|
1235
|
+
->and(collect($payload->calls)->where(0, 'current')->all())->toBe([])
|
|
1236
|
+
->and($controller->edit->commits)->toBe(1);
|
|
1237
|
+
});
|
|
1238
|
+
|
|
1239
|
+
test('api order controller reads a top-level cod amount and appends entities by default', function () {
|
|
1240
|
+
$order = new FleetOpsApiOrderCrudFake();
|
|
1241
|
+
$payload = new FleetOpsApiOrderPayloadFake();
|
|
1242
|
+
$order->payload = $payload;
|
|
1243
|
+
|
|
1244
|
+
$controller = new FleetOpsApiOrderCrudControllerProbe();
|
|
1245
|
+
$controller->order = $order;
|
|
1246
|
+
|
|
1247
|
+
$controller->update('order-public', new FleetOpsApiOrderUpdateRequestFake([
|
|
1248
|
+
'entities' => [['name' => 'Crate']],
|
|
1249
|
+
'cod_amount' => '2500',
|
|
1250
|
+
]));
|
|
1251
|
+
|
|
1252
|
+
expect($payload->calls)->toContain(['entities', [['name' => 'Crate']]])
|
|
1253
|
+
->and($payload->getAttributes()['cod_amount'])->toBe(2500)
|
|
1254
|
+
->and($controller->edit->guarded[0]['input'])->toMatchArray(['cod_amount' => '2500'])
|
|
1255
|
+
->and($controller->edit->guarded[0]['entities_mode'])->toBe('append');
|
|
1256
|
+
});
|
|
1257
|
+
|
|
1258
|
+
test('api order controller cancels with a reason when one is given', function () {
|
|
1259
|
+
$order = new FleetOpsApiOrderCrudFake();
|
|
1260
|
+
$controller = new FleetOpsApiOrderCrudControllerProbe();
|
|
1261
|
+
$controller->order = $order;
|
|
1262
|
+
|
|
1263
|
+
$controller->cancelOrder('order-public', new Request(['reason' => ' Customer moved away ']));
|
|
1264
|
+
|
|
1265
|
+
expect($order->cancelledForTest)->toBeTrue()
|
|
1266
|
+
->and($order->cancelReasonForTest)->toBe('Customer moved away');
|
|
1267
|
+
|
|
1268
|
+
$plain = new FleetOpsApiOrderCrudFake();
|
|
1269
|
+
$controller = new FleetOpsApiOrderCrudControllerProbe();
|
|
1270
|
+
$controller->order = $plain;
|
|
1271
|
+
$controller->cancelOrder('order-public', new Request());
|
|
1272
|
+
|
|
1273
|
+
expect($plain->cancelledForTest)->toBeTrue()
|
|
1274
|
+
->and($plain->cancelReasonForTest)->toBeNull();
|
|
1275
|
+
});
|
|
@@ -3,9 +3,12 @@
|
|
|
3
3
|
use Fleetbase\FleetOps\Http\Controllers\Api\v1\PayloadController;
|
|
4
4
|
use Fleetbase\FleetOps\Http\Requests\CreatePayloadRequest;
|
|
5
5
|
use Fleetbase\FleetOps\Http\Requests\UpdatePayloadRequest;
|
|
6
|
+
use Fleetbase\FleetOps\Models\Order;
|
|
6
7
|
use Fleetbase\FleetOps\Models\Payload;
|
|
7
8
|
use Fleetbase\FleetOps\Models\Place;
|
|
8
9
|
use Fleetbase\FleetOps\Models\Waypoint;
|
|
10
|
+
use Fleetbase\FleetOps\Support\OrderEdit;
|
|
11
|
+
use Fleetbase\FleetOps\Support\OrderEditPolicy;
|
|
9
12
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
|
10
13
|
use Illuminate\Http\Request;
|
|
11
14
|
|
|
@@ -124,6 +127,15 @@ class FleetOpsApiPayloadEndpointFake extends Payload
|
|
|
124
127
|
return $this;
|
|
125
128
|
}
|
|
126
129
|
|
|
130
|
+
public array $entitySyncs = [];
|
|
131
|
+
|
|
132
|
+
public function syncEntities($entities = []): array
|
|
133
|
+
{
|
|
134
|
+
$this->entitySyncs[] = $entities;
|
|
135
|
+
|
|
136
|
+
return ['created' => [], 'updated' => [], 'deleted' => []];
|
|
137
|
+
}
|
|
138
|
+
|
|
127
139
|
public function getPickupOrFirstWaypoint(): ?Place
|
|
128
140
|
{
|
|
129
141
|
return $this->firstWaypoint;
|
|
@@ -312,3 +324,112 @@ test('api payload controller returns not found responses for missing payloads',
|
|
|
312
324
|
'status' => 404,
|
|
313
325
|
]);
|
|
314
326
|
})->with(['update', 'find', 'delete']);
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* A payload that belongs to an order: the order's edit is recorded instead of read from the database.
|
|
330
|
+
*/
|
|
331
|
+
class FleetOpsApiPayloadOrderControllerProbe extends FleetOpsApiPayloadControllerProbe
|
|
332
|
+
{
|
|
333
|
+
public ?Order $order = null;
|
|
334
|
+
|
|
335
|
+
public ?FleetOpsApiPayloadOrderEditFake $edit = null;
|
|
336
|
+
|
|
337
|
+
protected function orderForPayload(Payload $payload): ?Order
|
|
338
|
+
{
|
|
339
|
+
return $this->order;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
protected function beginOrderEdit(Order $order): OrderEdit
|
|
343
|
+
{
|
|
344
|
+
return $this->edit ??= new FleetOpsApiPayloadOrderEditFake($order);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
class FleetOpsApiPayloadOrderEditFake extends OrderEdit
|
|
349
|
+
{
|
|
350
|
+
public array $requested = [];
|
|
351
|
+
public int $commits = 0;
|
|
352
|
+
|
|
353
|
+
public function __construct(public Order $order)
|
|
354
|
+
{
|
|
355
|
+
$this->policy = OrderEditPolicy::for($order);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
public function requestedChanges(array $input, string $entitiesMode = self::ENTITIES_APPEND): array
|
|
359
|
+
{
|
|
360
|
+
$this->requested[] = [$input, $entitiesMode];
|
|
361
|
+
|
|
362
|
+
return parent::requestedChanges(array_diff_key($input, ['entities' => true, 'cod_amount' => true]), $entitiesMode)
|
|
363
|
+
+ (isset($input['entities']) ? ['items' => ['adds' => $entitiesMode !== self::ENTITIES_REPLACE]] : []);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
public function commit(array $extra = [], bool $notifyDriver = true): array
|
|
367
|
+
{
|
|
368
|
+
$this->commits++;
|
|
369
|
+
|
|
370
|
+
return [];
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
function fleetopsApiPayloadOrderController(string $status): FleetOpsApiPayloadOrderControllerProbe
|
|
375
|
+
{
|
|
376
|
+
$controller = new FleetOpsApiPayloadOrderControllerProbe();
|
|
377
|
+
$controller->payload = new FleetOpsApiPayloadEndpointFake();
|
|
378
|
+
$controller->payload->firstWaypoint = fleetopsApiPayloadPlace();
|
|
379
|
+
$controller->order = new Order();
|
|
380
|
+
$controller->order->setRawAttributes(['uuid' => 'order-uuid', 'public_id' => 'order_payload', 'status' => $status], true);
|
|
381
|
+
|
|
382
|
+
return $controller;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
test('api payload controller keeps a cash to collect of zero and still skips empty values', function () {
|
|
386
|
+
$controller = fleetopsApiPayloadController();
|
|
387
|
+
|
|
388
|
+
$response = $controller->update('payload-public', fleetopsUpdatePayloadRequest([
|
|
389
|
+
'cod_amount' => 0,
|
|
390
|
+
'type' => '',
|
|
391
|
+
'provider' => null,
|
|
392
|
+
]));
|
|
393
|
+
|
|
394
|
+
// the first fill is the model constructor's
|
|
395
|
+
expect(end($response['payload']->filledPayloads))->toBe(['cod_amount' => 0])
|
|
396
|
+
->and($response['payload']->getAttributes()['cod_amount'])->toBe(0);
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
test('api payload controller edits an order payload through the order edit', function () {
|
|
400
|
+
$controller = fleetopsApiPayloadOrderController('dispatched');
|
|
401
|
+
|
|
402
|
+
$response = $controller->update('payload-public', fleetopsUpdatePayloadRequest([
|
|
403
|
+
'dropoff' => ['public_id' => 'dropoff-public'],
|
|
404
|
+
'cod_amount' => 1500,
|
|
405
|
+
]));
|
|
406
|
+
|
|
407
|
+
expect($response['payload']->dropoffAssignments)->toBe([['public_id' => 'dropoff-public']])
|
|
408
|
+
->and($response['payload']->currentWaypointAssignments)->toBe([])
|
|
409
|
+
->and($controller->edit->requested[0])->toBe([['dropoff' => ['public_id' => 'dropoff-public'], 'cod_amount' => 1500], 'append'])
|
|
410
|
+
->and($controller->edit->commits)->toBe(1);
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
test('api payload controller replaces entities on request and refuses locked item edits', function () {
|
|
414
|
+
$controller = fleetopsApiPayloadOrderController('created');
|
|
415
|
+
|
|
416
|
+
$response = $controller->update('payload-public', fleetopsUpdatePayloadRequest([
|
|
417
|
+
'entities' => [['id' => 'entity_keep']],
|
|
418
|
+
'entities_mode' => 'replace',
|
|
419
|
+
]));
|
|
420
|
+
|
|
421
|
+
expect($response['payload']->entitySyncs)->toBe([[['id' => 'entity_keep']]])
|
|
422
|
+
->and($response['payload']->entityAssignments)->toBe([]);
|
|
423
|
+
|
|
424
|
+
$locked = fleetopsApiPayloadOrderController('dispatched');
|
|
425
|
+
$response = $locked->update('payload-public', fleetopsUpdatePayloadRequest([
|
|
426
|
+
'entities' => [['name' => 'Extra']],
|
|
427
|
+
]));
|
|
428
|
+
|
|
429
|
+
expect($response->getStatusCode())->toBe(422)
|
|
430
|
+
->and($response->getData(true)['error'])->toBe('Items cannot be changed once a driver has the order.')
|
|
431
|
+
->and($response->getData(true)['locked'])->toBe(['items' => 'Items cannot be changed once a driver has the order.'])
|
|
432
|
+
->and($locked->payload->entityAssignments)->toBe([])
|
|
433
|
+
->and($locked->payload->savedForTest)->toBeFalse()
|
|
434
|
+
->and($locked->edit->commits)->toBe(0);
|
|
435
|
+
});
|
|
@@ -537,5 +537,5 @@ test('api place controller returns not found errors for missing places', functio
|
|
|
537
537
|
? $controller->update('missing-place', fleetopsUpdatePlaceRequest([]))
|
|
538
538
|
: $controller->{$method}('missing-place', new Request());
|
|
539
539
|
|
|
540
|
-
expect($response)->toBe(['apiError' => 'Place resource not found.', 'status' =>
|
|
540
|
+
expect($response)->toBe(['apiError' => 'Place resource not found.', 'status' => 404]);
|
|
541
541
|
})->with(['update', 'find', 'delete']);
|
|
@@ -68,9 +68,9 @@ class FleetOpsApiTrackingNumberControllerProbe extends TrackingNumberController
|
|
|
68
68
|
return ['resource' => 'deleted-tracking-number', 'trackingNumber' => $trackingNumber];
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
protected function findQrModel(
|
|
71
|
+
protected function findQrModel(string $code)
|
|
72
72
|
{
|
|
73
|
-
$this->qrLookups[] =
|
|
73
|
+
$this->qrLookups[] = $code;
|
|
74
74
|
|
|
75
75
|
return $this->qrModel;
|
|
76
76
|
}
|
|
@@ -206,15 +206,12 @@ test('api tracking number controller decodes qr models and reports missing value
|
|
|
206
206
|
$controller = new FleetOpsApiTrackingNumberControllerProbe();
|
|
207
207
|
$controller->qrModel = $model;
|
|
208
208
|
|
|
209
|
-
$
|
|
209
|
+
$code = 'https://console.fleetbase.test/track-order?order=ACM1234567890SG&r=order_public&v=1';
|
|
210
|
+
$response = $controller->fromQR(fleetopsDecodeTrackingNumberQrRequest(['code' => $code]));
|
|
210
211
|
|
|
212
|
+
// The raw scanned value goes to the resolver, which understands every format.
|
|
211
213
|
expect($response)->toBe(['resource' => 'qr-model', 'model' => $model])
|
|
212
|
-
->and($controller->qrLookups)->toBe([
|
|
213
|
-
[
|
|
214
|
-
['entities', 'orders'],
|
|
215
|
-
['uuid' => 'order-uuid'],
|
|
216
|
-
],
|
|
217
|
-
]);
|
|
214
|
+
->and($controller->qrLookups)->toBe([$code]);
|
|
218
215
|
|
|
219
216
|
$controller = new FleetOpsApiTrackingNumberControllerProbe();
|
|
220
217
|
|