sr_scheduling — Programmer's Notes¶
Module version: 17.0.1.0.0 Last updated: 2026-04-05 Primary owner: Dan Dependencies: sr_management, sr_management_fixes, base_geolocalize, crm, hr, hr_holidays
What This Module Does¶
Truck route scheduling and dispatch management. CSRs schedule pickups via the Add Note wizard — system finds the best date/route based on truck capacity, available hours, driving direction, and customer service windows. Includes driver messaging, LTL (less-than-truckload) pickups, and ORS (OpenRouteService) truck routing.
Downstream Dependents¶
| Module | What it uses |
|---|---|
| sr_truck_schedule | truck.schedule model, calendar/task fields |
| sr_reports | customer.pickups queries |
| sr_seo_locations | sr_management + sr_scheduling fields |
Key Models¶
| Model | Purpose |
|---|---|
| truck.schedule | Route management (draft→in_progress→completed→cancel) |
| customer.pickups (inherited) | Extends with truck assignment, service window enforcement |
| truck.route.log | Warehouse departure/arrival tracking |
| ltl.pickup | LTL freight pickup management |
| driver.message | Driver-dispatcher two-way messaging |
| trucking.company | LTL carrier info |
| ors.routing | OpenRouteService truck routing (driving-hgv profile) |
Critical Methods¶
customer_pickups.py¶
create()override calls_manage_truck_schedule()which uses ORS truck routing API- Set
is_old_pickup=Trueto bypass route management in scripts/tests _check_service_window_fits()— enforces customer HOO windows. Windows < 6 hours = "tight" constraint. Returns False if pickup doesn't fit.
ors_routing.py¶
- All distances use
driving-hgv(truck) profile, NOT car - API key in
ir.config_parameterasors_api_key - Falls back to haversine (35 mph, 1.3x winding factor) when ORS unavailable
- Frontend maps proxy through
/ors/routecontroller endpoint
Key Gotchas¶
- Samsara route pushing is DISABLED — drivers use Odoo driver portal on tablets, not Samsara navigation
- Samsara kept for: ELD, telemetry, mechanical notifications only
- Timezone cron calls Google Maps API at 200/hour — first run on full DB takes ~24 hours
- Service windows are separate from HOO (Apr 2026) —
has_service_window/service_window_start/service_window_endon both res.partner and customer.pickups. HOO is just the customer's business hours (informational). - 0/0 HOO is allowed — means "not set yet" and won't raise ValidationError
- Direction checking disabled (Apr 2026) —
routing_utils.directions_are_compatible()always returns True. Route optimizer handles stop ordering; weight/time/box constraints prevent overloaded routes. - Stage writes trigger route recalculation hooks — be careful writing to pickup stage fields
- morning_prep_minutes / evening_unload_minutes are region-specific — Sunbright 30min, others 60min
- The Add Note wizard is the primary entry point for CSRs. It lives in
wizard/add_note.py. - Wizard searches all trucks in region (Apr 2026) — not just the customer's default truck. Auto-updates
truck_assigned_idwhen matching schedule found on different truck.
Route Time Estimation (Apr 2026)¶
The old truck.schedule.total_trip_time stored field summed per-pickup warehouse travel time (broken — treated each pickup as independent round-trip).
New method: truck.schedule.estimate_optimized_route_hours(extra_customer=None, extra_additional_time=0.0)
- Nearest-neighbor TSP from warehouse → stops → warehouse
- Haversine distance × 1.3 circuity factor (straight-line → road distance)
- 50 mph average (East TN mix of mountain roads and interstate)
- Plus stop times per pickup (time_at_pickup_location + additional_time)
Used in: customer.pickups._check_schedule_has_capacity, add.note._return_valid_schedules, res.partner.action_refresh_pick_up_date, add.note._build_schedule_explanation.
Stop Sequence Optimization (Apr 2026)¶
customer.pickups._optimize_schedule_sequence(schedule) runs on every pickup create/assign. Nearest-neighbor from warehouse writes sequence field on each pickup so the route displays in driving order.
System Parameters¶
| Key | Default | Purpose |
|---|---|---|
google_maps_api_key |
(required) | Timezone lookup |
ors_api_key |
(required) | Truck routing |
time_at_pickup_location |
0.5 |
Hours per pickup stop |
no_hours_per_day |
10 |
Max route hours |
trip_start_time |
8.0 |
Default departure time |
minimum_route_weight |
1500 |
lbs — routes below this defer 7 days for consolidation |
max_weight |
8000 |
lbs — absolute max per route |
max_number_of_boxes |
50 |
max boxes per route |
direction_scheduling.strictness |
relaxed |
legacy — no longer enforced (always compatible) |
direction_scheduling.proximity_miles |
100 |
legacy — no longer used |
Testing¶
Scenario test harness: sr_scheduling/tests/run_scenarios.py (also on Dan's Desktop at ~/Desktop/scheduling_tests/)
Runs end-to-end scheduling scenarios from a CSV file, generates HTML report with color-coded pass/fail and optimized route summaries. Run with:
Functional tests: ~/Desktop/scheduling_tests/run_functional_tests.py — verifies module health (fields exist, methods callable, system params set).
Functional test spec: SR-Odoo/FUNCTIONAL_TESTS_SCHEDULING.md — full suite documentation.