Skip to content

Maintenance Forecasting

Accessible via: Pipelines → Maintenance tab (inside the Scenario Planner screen)

Maintenance forecasting predicts future demand driven by planned and unplanned maintenance events — overhauls, inspections, repairs, and replacements. It is primarily used in MRO (Maintenance, Repair & Operations) and aerospace/defense, where spare parts consumption is determined by scheduled service intervals rather than market demand.

Unlike statistical forecasting (which extrapolates from past demand), maintenance forecasting reasons forward from the maintenance schedule: which events will occur, which parts each event consumes, and how many times each event happens.

Figure: how maintenance-driven demand flows from the schedule through the BOM into the forecast.

flowchart TD
  A["Maintenance scenario schedule (event, date, site, qty)"] --> B["For each event occurrence"]
  B --> C["Read event BOM (item, qty, likelihood_of_removal)"]
  C --> D["per-event demand = bom_qty × likelihood × occurrence_qty"]
  D --> E["Distribute by coverage % or assign to site"]
  E --> F["Aggregate by (item, site, week)"]
  F --> G["PIPE_maintenance_forecast"]
  G --> H["Netting step (add or net against statistical)"]

Maintenance Events


Core Concepts

Maintenance Events

A maintenance event is a scheduled maintenance activity (e.g. "C-Check", "Engine Overhaul", "Landing Gear Inspection"). Each event has:

  • Name — a short label (e.g. "2000-Hour Inspection")
  • Description / Note — free-text notes
  • BOM — the list of parts consumed when this event is performed

Maintenance BOM

The Bill of Materials attached to each event defines which items (parts) are consumed and in what quantity. Each BOM line has:

Field Description
item_id The part number consumed
qty Quantity consumed per event occurrence
likelihood_of_removal Probability (0–1) that the part is actually replaced. A value of 0.8 means 80% of event occurrences consume this part

The demand contribution per occurrence is:

demand = bom_qty × likelihood_of_removal × occurrence_qty

where occurrence_qty is the number of asset/equipment units being maintained at once.

Figure: the lifecycle of a rotable/maintenance event occurrence driving part removal and replenishment.

stateDiagram-v2
  [*] --> Scheduled: event scheduled in scenario
  Scheduled --> Due: occurrence date reaches
  Due --> Removed: part likelihood_of_removal triggers
  Removed --> Consumed: bom_qty × likelihood × qty
  Consumed --> Demanded: aggregated into PIPE_maintenance_forecast
  Demanded --> Netted: combined with statistical/causal in netting
  Netted --> Replenished: supply order raised
  Replenished --> [*]: rotable back in pool
  Scheduled --> Deferred: scenario pushes date later
  Deferred --> Scheduled

Event Occurrences

Events recur on a schedule. An occurrence is a single instance of an event on a specific date, optionally at a specific site. Occurrences are stored per scenario and can be:

  • Explicitly dated — individual dates with optional site and quantity
  • Recurrence-based — e.g. every 500 flight hours, every 12 months (defined via the schedule UI or imported from the Excel MaintenanceEvents sheet)

Maintenance Scenarios

A maintenance scenario is a forecast scenario of type "Planned maintenance" that groups a set of events with their scheduled dates. Scenarios enable what-if planning:

  • Baseline scenario — the current maintenance schedule
  • Accelerated scenario — move events earlier (e.g. to reduce downtime risk)
  • Deferred scenario — push events later (e.g. to reduce near-term spend)

Each scenario can override event dates independently. The same event can occur on different dates across scenarios.

Fleet Plans

A fleet plan maps which assets are scheduled for which events and when. In the maintenance model this is captured by the scenario schedule — the set of (event, date, site, qty) tuples that define the maintenance calendar for that scenario.


Setting Up Maintenance Events

1. Create a Maintenance Event

Events are defined in the Maintenance tab of the Scenario Planner. They are also loaded automatically from the Excel MaintenanceEvents sheet during the ETL step (configured in Settingsdata_source.excel_source.maintenance_events_sheet).

To create a new event via the API:

POST /api/forecast/scenarios
Content-Type: application/json

{
  "name": "C-Check 2026",
  "description": "Heavy maintenance check",
  "scenario_type": "Planned maintenance"
}

2. Add Items to the Event BOM

Select an event and add the parts it consumes. Each line specifies the part, quantity per event, and likelihood of removal.

Maintenance BOM

Via the API, replace the entire BOM for an event:

PUT /api/maintenance/events/{event_id}/bom
Content-Type: application/json

[
  {"item_id": 101, "qty": 2, "likelihood_of_removal": 0.9},
  {"item_id": 205, "qty": 1, "likelihood_of_removal": 0.75}
]

3. Schedule Event Occurrences

For each event in a scenario, set the dates on which it occurs. You can also specify the site and the number of units being maintained on each date.

Via the API, replace all dates for one event in one scenario:

PUT /api/maintenance/events/{event_id}/scenario/{scenario_id}/dates
Content-Type: application/json

[
  {"date": "2026-07-01", "site_id": 3, "qty": 2},
  {"date": "2026-10-15", "site_id": 3, "qty": 1}
]

Both structured objects and bare date strings are accepted for backwards compatibility:

["2026-07-01", "2026-10-15"]

4. View All Events

Retrieve all maintenance events with their BOM items:

GET /api/maintenance/events

Response includes bom_items — an array of {item_id, item_name, qty, likelihood_of_removal} for each event.


Maintenance Scenarios

Creating a Scenario

From the Scenario Planner → Maintenance tab, click + New Scenario. Enter a name and description. The scenario is created with scenario_type = "Planned maintenance", which marks it as a maintenance scenario in the pipeline selector.

Maintenance Scenarios

Per-Scenario Date Overrides

The same maintenance event can have different schedules across scenarios. In the UI, select an event and toggle dates on/off or add new dates. Use the date grid to accelerate events (move dates earlier) or defer them (push dates later).

The full scenario schedule can be replaced atomically:

PUT /api/maintenance/scenario/{scenario_id}/schedule
Content-Type: application/json

{
  "schedule": {
    "1": [{"date": "2026-07-01", "qty": 2}, {"date": "2026-10-15", "qty": 1}],
    "3": [{"date": "2026-08-01", "qty": 4}]
  }
}

This replaces all event dates for the scenario in a single transaction.

Item Breakdown per Scenario

To see which maintenance events drive demand for a specific item in a specific forecast period:

GET /api/maintenance/scenario/{scenario_id}/item-breakdown?unique_id={item_id}_{site_id}&period=2026-07-06

The response lists each event that includes this item in its BOM, with:

  • Scheduled dates (all dates and dates within the requested period)
  • BOM quantity and likelihood of removal
  • Demand contribution for the period: bom_qty × likelihood × occurrence_qty
  • Full BOM of each event (all parts, not just the queried item)

Listing Scenarios

Retrieve all maintenance scenarios:

GET /api/maintenance/scenarios

Returns forecast scenarios that have at least one maintenance event linked.


Running Maintenance Forecasting

As a Pipeline Step

The maintenance forecast runs as the maintenance step in the pipeline. It is automatically chained after the forecast step when a pipeline is executed via the Process Runner.

The pipeline must have a maintenance_scenario_id configured. This is set in the Pipeline tab of the Scenario Planner when creating or editing a pipeline:

Pipeline field Description
maintenance_scenario_id Links the pipeline to a maintenance scenario
maintenance_pct Weight percentage for the maintenance signal in blended forecasts
maintenance_netting_mode How maintenance demand nets against statistical forecast (add or net)

Via Process Runner

From the Process Runner, select the maintenance step and run it independently. This computes the maintenance-driven demand for the active pipeline's maintenance scenario.

How the Engine Computes Demand

The maintenance engine follows this logic:

  1. For each event in the scenario, retrieve the BOM and the scheduled occurrence dates
  2. For each occurrence: per-event demand = bom_qty × likelihood_of_removal × occurrence_qty
  3. If coverage is configured, distribute demand across sites by coverage percentage
  4. If no coverage, assign demand to the occurrence's site (or leave unassigned if site is null)
  5. Aggregate demand by (item, site, week)
  6. Results are written to the PIPE_maintenance_forecast table

Results Feed into Forecast Netting

After the maintenance step, the netting step combines maintenance demand with:

  • Statistical forecast
  • Causal forecast (if configured)
  • Firm orders
  • Returns

The maintenance_netting_mode setting controls how maintenance demand is treated:

Mode Behaviour
add Maintenance demand is added on top of the statistical forecast (treated as firm demand)
net Maintenance demand consumes from the statistical forecast first; firm orders consume the remainder

See Supply Planning for details on netting logic.


Maintenance Demand Summary

Weekly Event Counts

View the number of maintenance event occurrences per calendar week:

GET /api/maintenance/events-weekly?scenario_id=5&segment_id=2

Response: array of {week, week_start, count} — one entry per week with at least one occurrence.

Maintenance Weekly Events

Items for a Specific Week

Find which items have maintenance events in a given week:

GET /api/maintenance/items-for-week?week_start=2026-07-06&scenario_id=5

Returns an array of item_id values for items consumed by events occurring that week.

Total Demand Summary

Aggregate maintenance demand per (item, site) pair across one or more scenarios:

GET /api/maintenance/demand/summary?scenario_ids=5&segment_id=2

Supports hierarchy filtering via hierarchy_id and hierarchy_selections parameters.

Maintenance Demand Summary

Response per row:

Field Description
item_id Part identifier
item_name Part name
site_id Site identifier (null if unlocated)
site_name Site name
unique_id Composite key "{item_id}_{site_id}"
total_demand Sum of all demand contributions across the specified scenarios

Per-Series Demand (Weekly)

For a specific (item, site) pair, retrieve the weekly demand time series:

GET /api/maintenance/demand/series?scenario_id=5&unique_id=101_3

Returns an array of {period, demand} — one entry per week with non-zero demand.

Events Summary

List all maintenance events with their occurrence counts and BOM items, sorted by frequency:

GET /api/maintenance/events-summary?scenario_id=5&segment_id=2

Response per event:

Field Description
event_id Event identifier
event_name Event name
event_note Event description
occurrence_count Number of scheduled dates (scoped by scenario_id)
bom_items Array of {item_id, item_name, qty, likelihood_of_removal}

Calendar & Coverage

Event Occurrences Across Scenarios

For a single event, view its scheduled occurrences across all scenarios:

GET /api/maintenance/events/{event_id}/occurrences

Returns per-scenario groups with dates, sites, and quantities.

Coverage — Site Distribution

When a maintenance event affects multiple sites but you don't know exact site assignments, you can define coverage — a percentage distribution of demand across sites.

Maintenance Coverage

Get coverage for an event in a scenario:

GET /api/maintenance/scenario/{scenario_id}/coverage/{event_id}

Response: array of {site_id, site_name, pct}.

Replace coverage:

PUT /api/maintenance/scenario/{scenario_id}/coverage/{event_id}
Content-Type: application/json

[
  {"site_id": 1, "pct": 60},
  {"site_id": 2, "pct": 40}
]

When coverage is defined, the demand engine splits each event's demand across sites by the configured percentages instead of using the occurrence's site_id.

Schedule Management

Retrieve the full maintenance schedule for a scenario (all events and their dates):

GET /api/maintenance/scenario/{scenario_id}/schedule

Response: a dictionary keyed by event_id, each value is an array of {date, qty}.

Replace the entire schedule (see Per-Scenario Date Overrides above).


Integration with Causal Forecasting

Maintenance events are one source of causal demand alongside fleet deployments and failure rates. The two models serve different use cases:

Model Use when
Causal Forecasting Demand is driven by asset fleet size, deployment, and failure rates
Maintenance Forecasting Demand is driven by explicitly scheduled maintenance events with known BOMs

Combining Both Signals

When both causal and maintenance forecasting are configured in a pipeline, their demands are combined during the netting step:

  • causal_pct — weight of the causal signal in the blended forecast
  • maintenance_pct — weight of the maintenance signal in the blended forecast
  • series_pct — weight of the statistical signal

The blended baseline shown in the Time Series Viewer is:

baseline = series_pct × statistical + causal_pct × causal + maintenance_pct × maintenance

The supply.netting_forecast_type setting (in Settings) controls which signal firm orders consume against: statistical, causal, maintenance, or blended.


API Reference

Method Endpoint Description
GET /api/maintenance/events List all maintenance events with BOM items
GET /api/maintenance/events-summary Events with occurrence counts and BOM, sorted by frequency
GET /api/maintenance/events-weekly Event occurrence counts per calendar week
GET /api/maintenance/items-for-week Item IDs with events in a given week
GET /api/maintenance/events/{event_id}/occurrences Occurrences for one event across all scenarios
PUT /api/maintenance/events/{event_id}/bom Replace BOM for an event
PUT /api/maintenance/events/{event_id}/scenario/{scenario_id}/dates Replace scheduled dates for one event in one scenario
GET /api/maintenance/scenarios List all maintenance scenarios
GET /api/maintenance/scenario/{scenario_id}/item-breakdown Events driving demand for an item in a period
GET /api/maintenance/scenario/{scenario_id}/schedule Full schedule for a scenario
PUT /api/maintenance/scenario/{scenario_id}/schedule Replace full schedule for a scenario
GET /api/maintenance/scenario/{scenario_id}/coverage/{event_id} Site coverage % for an event in a scenario
PUT /api/maintenance/scenario/{scenario_id}/coverage/{event_id} Replace site coverage % for an event
GET /api/maintenance/demand/summary Aggregate demand per (item, site) across scenarios
GET /api/maintenance/demand/series Weekly demand time series for one (item, site) pair

Common Query Parameters

Parameter Used by Description
scenario_id Most endpoints Pipeline's maintenance_scenario_id — scopes results to that scenario
scenario_ids /demand/summary Comma-separated scenario IDs for cross-scenario aggregation
segment_id Summary endpoints Filter to items belonging to a specific segment
hierarchy_id /demand/summary Hierarchy ID for DB-side filtering
hierarchy_selections /demand/summary JSON array of hierarchy node selections
unique_id /demand/series, /item-breakdown Composite key "{item_id}_{site_id}"
week_start /items-for-week ISO date of the Monday of the target week
period /item-breakdown ISO date of the forecast period start