ERP-MES vertical slice

How an ERP order moves through the line without losing data ownership

This educational case shows a vertical slice between ERP, MES and SCADA. Odoo remains the owner of the manufacturing order and final confirmation. MES adds admission, execution identity and outbox. Ignition runs the SFC and remains the source of line facts.

I followed one order through the full loop: the operator starts it from Odoo, Node-RED picks up the release, MES admits one execution, and Ignition receives the command over OPC UA. The completion then returns to ERP as a verified result.

The real task was not only to send a command. The important part was keeping ownership clear: ERP does not write line tags, Node-RED does not invent production facts, and Odoo cannot close the order before MES returns a result.

ERP -> MES -> SFC

one order, execution and result
Ignition
Node-RED
PostgreSQL
JavaScript
Manufacturing Order Handoff Summary
The problem

Split responsibility first

ERP, MES and SCADA solve different tasks. Odoo knows the order, product, BoM and final confirmation. MES knows which execution was accepted and which result still needs to return. Ignition knows line state, SFC and runtime tags. Node-RED connects the systems, but does not become the owner of production facts.

Manufacturing Order Handoff Overview
Odoo — business order

Odoo stores the Manufacturing Order, BoM, quantity, components and final ERP confirmation. It does not write line tags or decide what happened inside the SFC.

MES PostgreSQL — admission and outbox

MES DB creates a durable execution, protects the line from a second active order and stores completion until it is delivered to ERP.

Ignition — line facts

Ignition SFC runs the Line01 runtime and writes state, good/reject counters and material consumption. These facts are not calculated in Node-RED.

Manufacturing Order Handoff Step
Order flow

One order receives one execution

After Start in Odoo, the order becomes queued for MES. Node-RED picks up the next release and builds a stable request identity. MES DB admits only one active execution for the line, so a repeated poll does not turn into a second production order.

Manufacturing Order Handoff Overview
Operator clicks Start

WH/MO/00032 moves to In Progress. The MES block shows that the order is queued for release.

Node-RED polls Odoo

Flow 10 picks up the next queued order from Odoo and builds a canonical MES request with stable identity.

MES admits one execution

MES accepts the execution, checks whether the line is busy and publishes a Start command only for the accepted order.

Manufacturing Order Handoff Step
OPC UA and SFC

The command is accepted only as a complete payload

Node-RED writes command fields to Ignition only after MES admission. RequestSequence is written last, so the Gateway script sees a complete payload. Ignition checks the order, execution, product, quantity and current line state. Only then does the SFC start runtime.

Manufacturing Order Handoff Overview
Write command payload

Node-RED writes CommandId, WorkOrderId, MesExecutionId, ProductCode and TargetGoodQty into Ignition command tags.

Commit with RequestSequence

RequestSequence is written last. It is the boundary that tells Ignition the command is ready for validation.

SFC owns runtime

Ignition SFC writes STARTING, RUNNING, COMPLETED, good count, reject count and consumption facts. Node-RED only observes.

Manufacturing Order Handoff Step
Completion

The result returns through an outbox

Ignition publishes completion after CompletionSequence changes. MES stores the production facts and creates a row for ERP outbox. A separate Node-RED flow delivers the pending result to Odoo and marks it as delivered only after a successful ERP response.

Manufacturing Order Handoff Overview
Observe completion sequence

Flow 30 sees a new CompletionSequence over OPC UA and publishes a production-completed event.

Record MES completion

MES DB stores completion and creates an erp_outbox row. A repeated resultId does not create a second ERP posting.

Deliver ERP result

Flow 40 sends the pending outbox back to Odoo and marks the row as delivered only after a successful ERP response.

Manufacturing Order Handoff Step
ERP confirmation

ERP closes the order only after MES

Early confirmation in Odoo is hidden until MES returns a result. After receipt, the operator gets the final Produce All action. Odoo remains the owner of ERP posting, but it can no longer close the order before the line has completed.

Manufacturing Order Handoff Overview
MO 32 released to MES

WH/MO/00032 is in progress: product PKG-A, target quantity 10.00 and MES release queued.

Facts returned

Odoo receives good quantity 10.00 and consumption for MAT-BASE-A, MAT-LABEL-A and MAT-PACK-A.

ERP remains final owner

After the MES result, WH/MO/00032 is closed in Odoo. MES release is confirmed in ERP and the execution ID is retained on the order.

What the case shows:

  1. ERP can drive the start without bypassing MES and SCADA
  2. MES admission and outbox keep the flow idempotent and traceable
  3. Node-RED stays an adapter, not the owner of production facts
  4. Ignition SFC remains the source of runtime state and material consumption
  5. Final ERP posting happens only after a confirmed MES result
Manufacturing Order Handoff Step

Other projects

Part Production Cell — MES & OEE Project

Part Production Cell — MES & OEE

OpenPLC, Ignition Perspective and SQLite: order in events, KPIs and downtime causes.

View case study Arrow
Pump Station Simulator Project

Pump Station Simulator

OPC UA, SQLite, and Ignition: from live pump state to persisted history and a verified operating scenario.

View case study Arrow
Tank Level Control Project

Tank Level Control

OpenPLC, Modbus TCP, and Ignition: from ladder logic to a verifiable operator scenario.

View case study Arrow