Scheduling

How the scheduler chooses placements, and every option that controls it.

Run a schedule

Click Schedule in the top bar to open the Run Scheduler modal. Pick a direction, sort order and constraints, then Preview → Apply. APS runs the engine client-side — nothing is committed to Odoo until you publish.

Direction

Forward

Every operation starts as early as possible, respecting dependencies and resource capacity. Use when you want to know the earliest you could complete each order.

Backward (just-in-time)

Every operation ends as late as possible before its due date. Good for minimising work-in-progress and storage. Late orders surface immediately. Orders are taken in the run's sort order, so when two compete for the slot nearest the due date the higher priority gets it. A rush order is planned forward from now in this direction too, ahead of everything that has not started.

A bill of material is exploded level by level. The finished order is placed against its own deadline; each sub-assembly is then backed up from the moment its parent needs it, not from a deadline of its own. An order whose deadline has already passed cannot be backed up from it at all — it is planned forward from now, in sequence, and reported once as PAST_DEADLINE.

A sub-assembly order is known by the link Odoo keeps when the parent's component created it. Where Odoo keeps no such link, for instance when an automation creates the sub-assembly orders make-to-stock, the order named in its Source(origin) field is taken as the parent, provided that order consumes what the sub-assembly makes. Either way the parent waits for its sub-assemblies in every direction, whether material is respected or not, and the sub-assembly carries the SUB tag.

Bidirectional

Schedules around locked & anchor operations. Predecessors push backward from each anchor, successors push forward. Use after locking key milestones.

What the run was told

Direction, sort order and capacity mode must all be chosen before Preview is offered; a chosen entry cannot be cleared by clicking it again. The preview repeats the settings in one line, the same line the Gantt shows for the plan on screen, and they are recorded on the plan when it is applied.

A preview is good for the data it saw. If a priority, a rush or a lock is set after that, in this tab or in another, Apply is refused with the time of the change, the page fetches the change, and the dialog asks for a new Preview, so a plan is never written from data that has moved on. A tab's own drags and locks are known to it, so they never have its own preview refused.

Sort order (which job goes first)

When two operations compete for the same time slot, the sort order decides who wins.

  • Priority — lower priority value wins. Ties broken by due date (earlier first), then hierarchy (children before parents).
  • Due date — earliest due date wins. Ties broken by priority, then hierarchy.
  • Earliest start — operations already scheduled earliest win. Useful for tweaks that should preserve existing order.
Priority is inherited. A parent MO's priority is propagated to all its children so a tree is scheduled as one cohort. You can't accidentally schedule a sub-assembly later than its parent.

Rush orders

A priority of 100 still queues behind work that is late, because a late order has the earlier due date. For a genuine emergency, open the priority dialog on a sales order or an MO and switch on Rush order. It is then planned before everything that has not started, whichever sort order the run uses, and it claims scarce material first.

Two things still hold: work that is already running is never moved aside, and the freeze window is not broken into. So a rush order starts at the first slot beyond the freeze wall, not before it. Marking a sales order marks every MO under it; marking an MO marks its sub-assemblies too. The marker lives in APS, is copied into any scenario you create, and a sync from Odoo never clears it.

It takes the parts as well as the slot. Material is handed out in the order jobs are planned, so a rush order can leave a component short for an order that would otherwise have had it, including parts Odoo has already reserved for an order that has not started, is not locked and is outside the freeze window. That order is reported as a shortage, and with leave it out of the plan it is withheld rather than given a date it cannot meet.

Freeze window

The freeze window protects the imminent future from being rescheduled. Any step whose current start falls inside the window is held in place during this run, and nothing new is placed to start inside it.

A day is 24 hours on the clock from the moment of the run, not a working day and not a calendar date. Run on Tuesday at 1 PM with a window of 1 and everything dated before Wednesday 1 PM is held; Wednesday afternoon is replanned. Nights and weekends count: run on Friday at 1 PM and a window of 3 reaches Monday 1 PM only, so to hold all of Monday use 4. The dialog shows the exact moment under the field, "Holds steps starting before …", on the organisation's clock.

Two rules sit above the setting: work that is running or finished is never moved, whatever the window says, and work that should have started earlier and never did is not treated as in flight — it is rescheduled rather than left sitting in the past.

A step the plan has running at the moment of the run counts as inside the window, so running the plan again a few minutes later keeps the first job on each work centre where it was. A parent MO's step inside the window stays unless one of its sub-assemblies is planned again in this run.

  • 0 — hold nothing ahead of now; only locked, running and finished work stays.
  • 1 — hold what starts in the next 24 hours.
  • 7 — hold what starts in the next 7 × 24 hours.
  • No freeze window — switch on to ignore the window entirely.

A step the window held is marked held on the Work Orders page, and like every dated step the run looked at it reads as planned afterwards. A run that finds nothing to move can still be applied: it records what it kept, what it held and what it left out.

A rush order does not break into the window either. If an earlier run already put two jobs on a work centre for tomorrow morning and the window is 1, a rush order set today lands behind those two, not behind the job that is running now. To put it directly behind the running job, run with No freeze window.

Use higher values to keep the shop floor stable: workers don't want a new plan dropped on them mid-shift. Use No freeze window when rebaselining everything (e.g. after a major disruption).

Frozen work keeps whatever dates it already had. If Odoo planned a step at 17:00 on a work centre whose day ends at 16:30, and that step starts inside the freeze window, the schedule shows it at 17:00, in the hatched non-working time, because that is what the shop floor is currently expected to do. It is not APS placing work outside the calendar: the run did not touch it. Switch on No freeze window, or shorten the horizon, and the step is replanned into the next open shift.

When a frozen step has work still ahead of it. A step that cannot move pins its own slot but not the steps it depends on. If Odoo says Prep is due today while the Weld before it has not happened, the Weld is replanned to the first free slot beyond the freeze wall — which is after the Prep. The run reports each of these as a conflict naming the order and the steps involved, so you can either shorten the freeze window or check in Odoo whether the earlier step was in fact already done.

Include past work orders

Even with no freeze, an op whose start is in the past is left where it is by default. Switch this on to pull all past-scheduled ops forward into the future and reschedule them as if unscheduled. Useful when old data has accumulated.

Use alternative resources

When the assigned work center is congested, APS can move an operation to an equivalent one configured in Odoo. The candidate that frees the operation earliest is chosen, and only work centers listed as alternatives in Odoo are ever considered. Duration is recalculated for the work center that gets the job, so a slower or higher-capacity alternative changes the time the operation takes. Disable if you want strict per-resource assignment.

This works alongside the material settings: an operation moved to an alternative still cannot start before its components arrive, and an order left out for lack of material is not resurrected by having a second work center free.

Capacity mode

  • Finite (default) — respects work-center capacity. Two ops can't overlap on the same unit.
  • Infinite — overlaps allowed. Useful for “ideal world” lead-time analysis.

Material-aware scheduling

Switch on Respect material availability to delay work until its components are in stock or arriving on a confirmed PO. APS uses FIFO supply allocation: higher-priority orders claim supply first.

A component waits for the step that uses it, not for the whole order. Odoo says which work order consumes each component; one it does not assign belongs to the order's first step. The steps before the consuming one are free to run, and once the consuming step has started or finished the component holds nothing back and is no longer counted as a shortage: an order whose cutting step is done does not wait for next month's sheet delivery to be packed.

Per direction:

  • Forward — enforces material availability by delaying placement until parts are on hand.
  • Backward — plans to the deadline and reports what the material cannot support, as MATERIAL_LATE / MATERIAL_SHORTAGE conflicts, so you can see what needs expediting rather than having the date quietly moved.
  • Bidirectional and RCCP — enforce the same material floor as Forward.

All five presets ask for material awareness. One further choice sits on the Custom tab:

  • When material is missing — an order whose components no stock or purchase order covers is either scheduled and flagged (the default: production gets a date, purchasing sees the order on the Gantt) or left out of the plan. Leaving it out also holds back the orders above it, because a top-level order cannot be finished while a sub-assembly it consumes has nothing to make it from, and the parts it was holding go back into the pool for the next order that can finish with them.

You do not need a separate setting to keep blocked work out of the early slots. The material floor already holds an order back to the date its parts arrive, so the time in front of that date stays available to work that can actually run.

See Materials for details.

What happens during a run

  1. Operations are sorted (sort order setting)
  2. The freeze window holds what starts in the next N × 24 hours
  3. Engine walks the sorted list, placing each op in its earliest legal slot
  4. Capacity, calendar, dependencies, alternatives and (optionally) materials are checked
  5. If no slot fits, the op is flagged with a conflict (you'll see it on the Gantt)

Nothing is committed to Odoo. The plan lives in the active dataset until you Publish to Odoo.

APS 4 Manufacturing

Built by Avalah

Odoo Gold Partner

APS 4 Manufacturing

Built by Avalah

Odoo Gold Partner