feat: Driver Scheduling Integration — connect Driver model to core-api scheduling system#216
Open
feat: Driver Scheduling Integration — connect Driver model to core-api scheduling system#216
Conversation
added 2 commits
March 30, 2026 04:58
Connects the FleetOps Driver Eloquent model to the core-api scheduling system by adding polymorphic relationships: - schedules(): MorphMany<Schedule> — driver as subject - scheduleItems(): MorphMany<ScheduleItem> — driver as assignee - activeShiftFor(date): ?ScheduleItem — convenience method for the AllocationPayloadBuilder to retrieve the driver's active shift for a given date and inject start_at/end_at as VROOM time_window constraints - availabilities(): MorphMany<ScheduleAvailability> — time-off and preferred working hour records Also adds required use statements for Schedule, ScheduleItem, MorphMany, and ScheduleAvailability from the core-api namespace. Refs: #214
…i scheduling system
## Backend
### server/src/Models/Driver.php
- Add schedules() MorphMany — driver as polymorphic subject on Schedule
- Add scheduleItems() MorphMany — driver as polymorphic assignee on ScheduleItem
- Add activeShiftFor(date) — convenience method for AllocationPayloadBuilder
to retrieve the driver's active shift and inject time_window constraints
- Add availabilities() MorphMany — time-off and preferred working hours
- Add use statements for Schedule, ScheduleItem, ScheduleAvailability, MorphMany
### server/src/Http/Controllers/Internal/v1/Traits/DriverSchedulingTrait.php (new)
- scheduleItems(id, request) — GET /{id}/schedule-items with date range filter
- availabilities(id, request) — GET /{id}/availabilities with date range filter
- hosStatus(id) — GET /{id}/hos-status, computes daily/weekly hours from shifts
- activeShift(id) — GET /{id}/active-shift, used by AllocationPayloadBuilder
### server/src/Http/Controllers/Internal/v1/DriverController.php
- Use DriverSchedulingTrait to expose the four scheduling endpoints
### server/src/routes.php
- Register four scheduling sub-routes under the internal drivers fleetbaseRoutes group
## Frontend
### addon/components/driver/schedule.js (rewritten)
- Inject fetch, intl, store, driverScheduling, modalsManager, notifications
- loadDriverSchedule task: queries schedule-items via driverScheduling service
- loadAvailability task: queries schedule-availability via store
- loadHOSStatus task: calls /drivers/{id}/hos-status, suppresses 404 gracefully
- addShift, editShift, deleteShift actions using modals/add-driver-shift and
modals/driver-shift
- setAvailability, requestTimeOff, deleteAvailability actions using
modals/set-driver-availability
### addon/components/driver/schedule.hbs (rewritten)
- HOS Status panel (hidden when hosStatus is null)
- Upcoming Shifts panel with edit/delete per-shift buttons
- Availability & Time Off panel with add/delete availability buttons
- Fleetbase UI styling (minimal padding, Tailwind, ContentPanel, Badge, Button)
### addon/components/modals/add-driver-shift.{js,hbs} (new)
- Creates a ScheduleItem with assignee_type=driver
- Supports both single-driver (from driver panel) and multi-driver (from global
scheduler) modes via the hasManyDrivers computed property
### addon/components/modals/driver-shift.{js,hbs} (new)
- Edits an existing ScheduleItem, pre-populates fields from the passed item
### addon/components/modals/set-driver-availability.{js,hbs} (new)
- Shared modal for both Set Availability (is_available=true) and
Request Time Off (is_available=false) flows
### addon/services/driver-actions.js
- Add Schedule tab (component: 'driver/schedule') to the driver view panel tabs
### addon/controllers/operations/scheduler/index.js
- Add driverAvailabilities tracked property
- Enhance events computed to render unavailable availability records as
FullCalendar background events (red-300) so dispatchers see time-off blocks
- Add loadDriverAvailabilities task
- Call loadDriverAvailabilities when switching to 'drivers' view mode
- Use intl.t() for addDriverShift modal title and button text
Refs: #214
roncodes
pushed a commit
that referenced
this pull request
Mar 30, 2026
…etOps integration ## Backend ### Allocation Engine Architecture (server/src/Allocation/) - AllocationEngineInterface: defines the allocate()/getName()/getIdentifier() contract - AllocationEngineRegistry: singleton service-locator; engines register via resolving() hook - AllocationPayloadBuilder: engine-agnostic normalizer — builds jobs/vehicles arrays from Order/Vehicle models, reads custom fields for skill codes, injects driver shift time_windows from Driver::activeShiftFor() (prerequisite: PR #216 driver scheduling integration) - VroomAllocationEngine: default VROOM implementation; maps normalized payload to VROOM VRP wire format, handles integer ID mapping, parses routes/unassigned back to public_ids ### AllocationController (server/src/Http/Controllers/Internal/v1/) - POST fleet-ops/allocation/run — run engine against unassigned orders + online vehicles - POST fleet-ops/allocation/commit — commit assignments via Order::firstDispatchWithActivity() - GET fleet-ops/allocation/preview — preview without side effects - GET fleet-ops/allocation/engines — list registered engines (for settings dropdown) - GET fleet-ops/allocation/settings — get allocation settings - PATCH fleet-ops/allocation/settings — save allocation settings ### ProcessAllocationJob (server/src/Jobs/) - Queueable, idempotent background job for auto-allocation on order creation or re-allocation - Reads active engine from Setting::lookup('fleetops.allocation_engine', 'vroom') ### HandleDeliveryCompletion (server/src/Listeners/) - Listens on OrderCompleted; dispatches ProcessAllocationJob when auto_reallocate_on_complete is enabled — closes the re-allocation loop ### Provider/Route wiring - FleetOpsServiceProvider: registers AllocationEngineRegistry singleton + VroomAllocationEngine - EventServiceProvider: adds HandleDeliveryCompletion to OrderCompleted listeners - routes.php: adds /allocation group with 6 endpoints under internal v1 fleet-ops prefix ## Frontend ### Engine Registry Pattern (addon/services/) - allocation-engine-interface.js: abstract base class with allocate() contract - allocation-engine.js: registry service — register()/resolve()/has()/availableEngines - vroom-allocation-engine.js: VROOM adapter — delegates to backend AllocationController - order-allocation.js: orchestration service — run/commit/loadSettings/saveSettings tasks ### Instance Initializer (addon/instance-initializers/) - register-vroom-allocation.js: registers VroomAllocationEngine into the allocation-engine registry at app boot — identical pattern to register-osrm.js for route optimization ### Dispatcher Workbench (addon/components/) - order-allocation-workbench.js: three-panel workbench with Order Bucket, Proposed Plan view, Vehicle Bucket; runAllocation/commitPlan/discardPlan tasks; handleDrop for drag-and-drop override; planByVehicle computed groups assignments by vehicle for the plan view - order-allocation-workbench.hbs: full Handlebars template with toolbar, three panels, per-vehicle route cards, unassigned warning banner, override badges, empty states ### Settings UI (addon/controllers/settings/ + addon/templates/settings/) - order-allocation.js controller: loadSettings/saveSettings tasks, engineOptions from registry - order-allocation.hbs template: engine selector (PowerSelect from registry), auto-allocate toggles, max travel time input, balance workload toggle ### Route/Navigation wiring - routes.js: adds operations.allocation and settings.order-allocation routes - routes/operations/allocation.js: ability-guarded route - routes/settings/order-allocation.js: ability-guarded route with setupController hook - templates/operations/allocation.hbs: renders OrderAllocationWorkbench - extension.js: adds Allocation shortcut tile + fleet-ops:template:settings:order-allocation registry - layout/fleet-ops-sidebar.js: adds Allocation to operations nav, Order Allocation to settings nav Closes #214
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
This PR connects the FleetOps
Drivermodel to the existing scheduling system infleetbase/core-api, completing the scheduling integration described in issue #214. It is a prerequisite for the Intelligent Order Allocation Engine (PR to follow), which uses driver shifttime_windowdata as hard constraints in the optimization solver.Backend Changes
server/src/Models/Driver.phpschedules()— MorphMany relationship (driver as polymorphicsubjectonSchedule)scheduleItems()— MorphMany relationship (driver as polymorphicassigneeonScheduleItem)activeShiftFor($date)— convenience method used by theAllocationPayloadBuilderto retrieve the driver's active shift and injecttime_windowconstraints into the VROOM payloadavailabilities()— MorphMany relationship for time-off and preferred working hoursusestatements forSchedule,ScheduleItem,ScheduleAvailability,MorphManyserver/src/Http/Controllers/Internal/v1/Traits/DriverSchedulingTrait.php(new)Provides four scheduling endpoints as a trait applied to
DriverController:scheduleItems(id, request)—GET /{id}/schedule-itemswith optional date range filteravailabilities(id, request)—GET /{id}/availabilitieswith optional date range filterhosStatus(id)—GET /{id}/hos-status— computes daily and weekly hours from completed/in-progress shiftsactiveShift(id)—GET /{id}/active-shift— returns the driver's currently active shiftserver/src/Http/Controllers/Internal/v1/DriverController.phpuse DriverSchedulingTraitserver/src/routes.phpdriversfleetbaseRoutesgroupFrontend Changes
addon/components/driver/schedule.js(rewritten)fetch,intl,store,driverScheduling,modalsManager,notificationsloadDriverScheduletask: queries schedule-items via thedriverSchedulingserviceloadAvailabilitytask: queriesschedule-availabilityrecords via storeloadHOSStatustask: calls/drivers/{id}/hos-status, suppresses 404 gracefully for drivers without HOS dataaddShift,editShift,deleteShiftactions usingmodals/add-driver-shiftandmodals/driver-shiftsetAvailability,requestTimeOff,deleteAvailabilityactions usingmodals/set-driver-availabilityaddon/components/driver/schedule.hbs(rewritten)hosStatusis nulladdon/components/modals/add-driver-shift.{js,hbs}(new)ScheduleItemwithassignee_type=driverhasManyDriverscomputed propertyaddon/components/modals/driver-shift.{js,hbs}(new)ScheduleItem, pre-populates all fields from the passeditemaddon/components/modals/set-driver-availability.{js,hbs}(new)is_available=true) and Request Time Off (is_available=false) flowsaddon/services/driver-actions.jscomponent: 'driver/schedule') to the driver view panel tabs arrayaddon/controllers/operations/scheduler/index.jsdriverAvailabilitiestracked propertyeventscomputed to render unavailable availability records as FullCalendar background events (red-300) so dispatchers can see time-off blocks at a glanceloadDriverAvailabilitiestaskswitchViewMode('drivers')now also callsloadDriverAvailabilitiesaddDriverShiftmodal title and button text now useintl.t()Relationship to Allocation Engine
The
activeShiftFor()method on theDrivermodel is the key integration point for the upcoming Allocation Engine PR. TheAllocationPayloadBuilderwill call this method for each candidate driver and inject the shiftstart_at/end_atas a VROOMtime_windowconstraint, ensuring the solver cannot assign a route that would cause a driver to exceed their scheduled hours.Refs: #214