Skip to content

feat: Driver Scheduling Integration — connect Driver model to core-api scheduling system#216

Open
roncodes wants to merge 2 commits intomainfrom
feat/driver-scheduling-integration
Open

feat: Driver Scheduling Integration — connect Driver model to core-api scheduling system#216
roncodes wants to merge 2 commits intomainfrom
feat/driver-scheduling-integration

Conversation

@roncodes
Copy link
Copy Markdown
Member

Overview

This PR connects the FleetOps Driver model to the existing scheduling system in fleetbase/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 shift time_window data as hard constraints in the optimization solver.


Backend Changes

server/src/Models/Driver.php

  • Added schedules() — MorphMany relationship (driver as polymorphic subject on Schedule)
  • Added scheduleItems() — MorphMany relationship (driver as polymorphic assignee on ScheduleItem)
  • Added activeShiftFor($date) — convenience method used by the AllocationPayloadBuilder to retrieve the driver's active shift and inject time_window constraints into the VROOM payload
  • Added availabilities() — MorphMany relationship for time-off and preferred working hours
  • Added required use statements for Schedule, ScheduleItem, ScheduleAvailability, MorphMany

server/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-items with optional date range filter
  • availabilities(id, request)GET /{id}/availabilities with optional date range filter
  • hosStatus(id)GET /{id}/hos-status — computes daily and weekly hours from completed/in-progress shifts
  • activeShift(id)GET /{id}/active-shift — returns the driver's currently active shift

server/src/Http/Controllers/Internal/v1/DriverController.php

  • Added use DriverSchedulingTrait

server/src/routes.php

  • Registered four scheduling sub-routes under the internal drivers fleetbaseRoutes group

Frontend Changes

addon/components/driver/schedule.js (rewritten)

  • Injects fetch, intl, store, driverScheduling, modalsManager, notifications
  • loadDriverSchedule task: queries schedule-items via the driverScheduling service
  • loadAvailability task: queries schedule-availability records via store
  • loadHOSStatus task: calls /drivers/{id}/hos-status, suppresses 404 gracefully for drivers without HOS data
  • 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 — shows daily/weekly hours with compliance badge; hidden when hosStatus is null
  • Upcoming Shifts panel — lists shifts with inline edit/delete buttons
  • Availability & Time Off panel — lists availability restrictions with add/delete actions
  • Styled with Fleetbase UI conventions (ContentPanel, Badge, Button, Tailwind)

addon/components/modals/add-driver-shift.{js,hbs} (new)

  • Creates a ScheduleItem with assignee_type=driver
  • Supports both single-driver mode (opened from driver panel) and multi-driver mode (opened from global scheduler) via hasManyDrivers computed property

addon/components/modals/driver-shift.{js,hbs} (new)

  • Edits an existing ScheduleItem, pre-populates all 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

  • Added Schedule tab (component: 'driver/schedule') to the driver view panel tabs array

addon/controllers/operations/scheduler/index.js

  • Added driverAvailabilities tracked property
  • Enhanced events computed to render unavailable availability records as FullCalendar background events (red-300) so dispatchers can see time-off blocks at a glance
  • Added loadDriverAvailabilities task
  • switchViewMode('drivers') now also calls loadDriverAvailabilities
  • addDriverShift modal title and button text now use intl.t()

Relationship to Allocation Engine

The activeShiftFor() method on the Driver model is the key integration point for the upcoming Allocation Engine PR. The AllocationPayloadBuilder will call this method for each candidate driver and inject the shift start_at/end_at as a VROOM time_window constraint, ensuring the solver cannot assign a route that would cause a driver to exceed their scheduled hours.

Refs: #214

Ronald A Richardson 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant