A Riyadh-based food distributor running Dynamics 365 integrates a B2B buyer portal and, three weeks after go-live, discovers that orders placed through the portal are updating inventory positions in the ERP before the warehouse has picked them. The inventory numbers are wrong. The ERP has lost its status as the source of truth. The integration is rolled back. The portal is shut down. This failure is not unusual — and it originates before a single line of integration code is written.

The question every integration starts with

Most mid-to-large distributors in Egypt and Saudi Arabia operate an ERP — SAP, Oracle, or Dynamics 365. These systems were designed to be the source of truth for customers, inventory, pricing, and orders. They are good at that function. What they were not designed for is buyer-facing ordering: the interface a purchasing manager at a supermarket chain in Jeddah uses to place a weekly restocking order at 11pm, or the portal a restaurant group in Cairo uses to reorder ambient products across twelve locations.

When a distributor adds a self-service ordering layer, two systems now coexist around the same data objects. For every object — customers, SKUs, pricing, inventory positions, orders — one system must be authoritative. The integration question is not how to connect the two systems. It is: for each data object, which system owns it, and in which direction does data flow?

Getting this wrong does not produce a bad integration. It produces a data ownership conflict — a state where neither system is reliably accurate, both require manual reconciliation, and operations staff maintain a third truth in a spreadsheet. This is the condition that forces rollbacks. The technical failure comes later. The architectural failure happens in the design session.


What locks: the ERP holds it, permanently

Certain data must remain exclusively ERP-authoritative. The ordering layer reads this data. It does not write to it, does not maintain its own copy, and does not allow buyer-side actions to overwrite it. Three objects belong in this category without exception.

Customer master data is the first hard lock. The ERP holds the canonical record of each buyer: their legal entity, credit terms, payment conditions, assigned customer segment, and contract status. The ordering layer reads this record to personalize the buyer's catalog and apply their contracted pricing. If a buyer updates their delivery address in the portal, that update is staged for ERP review — it does not overwrite the ERP customer record. The ERP holds the lock. The portal reflects it. Any architecture where the portal can write back to customer master data will produce divergence within weeks, as portal-side updates and ERP-side updates accumulate without reconciliation.

Pricing configuration is the second lock. In a correctly integrated architecture, the ordering layer reads its pricing data from the ERP: segment base prices, contract overrides per SKU, volume discount tier structures. The ERP is the origin of every price the buyer sees at cart. The ordering layer applies its pricing engine logic on top of ERP-sourced data — calculating net prices through base price, segment discount, contract override, volume tier, and time-bound promotion — but it does not author the pricing data itself. The contract override lives in the ERP. The ordering layer derives the net price from it. Pricing configuration that exists in the ordering layer independently of the ERP is pricing configuration that will diverge from the ERP, invisibly, over time.

Inventory ATP — available-to-promise — is the third lock. The ordering layer queries the ERP's inventory position at the point of cart confirmation. It does not maintain a separate inventory ledger. A cart that shows a product in stock, then fails at submission because the ERP shows zero inventory, is a product failure. It is still preferable to an ordering layer that shows false availability because it maintains a stale local inventory mirror that has drifted from the ERP's live position. Stale availability data produces confirmed orders that cannot be fulfilled. Stale inventory mirrors produce that problem at scale.

The locked objects share a property: they are all supplier-controlled configurations. Customers, prices, and inventory positions are defined on the supplier side and must be authoritative in the supplier's system of record. The ordering layer presents them. It does not own them.


What syncs: the ordering layer writes one thing back

Data flows from the ERP to the ordering layer for customers, pricing, and inventory — the locked objects described above. One data object flows in the opposite direction: confirmed orders.

When a buyer submits an order through the portal and it passes cart validation — MOQ, pack type, ATP, and pricing all confirmed — the order record is written to the ERP's order management module. This is the integration's core function: converting a buyer-originated order into an ERP-native order that the warehouse team, the finance team, and the logistics operation can act on. Everything that happens after order submission — picking, dispatch, delivery, invoicing — runs in the ERP. The portal's role ends at the moment the order is confirmed.

The confirmed order must be written to the ERP as an immutable record. The warehouse does not edit it back through the portal. Adjustments that occur during fulfillment — a short-pick due to a warehouse discrepancy, a damaged case at loading, a temperature rejection at the receiving dock — are recorded as ERP adjustments against the original order, not as changes to the portal order record. The portal reflects the confirmed order. The ERP records what was actually fulfilled. The invoice is generated from the ERP's fulfillment record. This separation is not a workaround. It is the correct architecture for each system doing what it was designed to do.

The adjustment cycle is where integration architectures most often fail in practice. A distributor whose warehouse supervisors are trained to update order quantities in the portal after fulfillment changes — because the portal is the interface they are most familiar with — will produce an ordering layer that contains fulfillment corrections rather than confirmed orders. The data is now mixed, authoritative for neither function, and cannot be reliably used for buyer order history, reorder generation, or ERP reconciliation. The fix is not a user training programme. It is a clear interface policy: the portal is for placing and tracking orders, not for recording what was delivered. Delivery records belong in the ERP.

The portal is for placing and tracking orders. Delivery records belong in the ERP. Mixing these two functions in a single interface produces data that is authoritative for neither.


Integration in practice: a Jeddah frozen foods distributor

A Jeddah-based frozen foods distributor running SAP and serving eighty-plus modern trade accounts across Riyadh and Jeddah completed an ERP integration before launching a buyer portal. The implementation team made a deliberate decision early: no code would be written before the data ownership map was complete. Three decisions had to be resolved in writing — what data SAP owns exclusively, what data the portal queries at runtime, and what data the portal writes back to SAP.

During the data mapping exercise, the team discovered that SAP's pricing configuration contained two active conflicts. A regional partner segment discount was being partially overridden by a time-bound promotional rate that had officially expired but was extended informally — updated in the sales team's shared price list document but never corrected in SAP. Buyers in the regional partner segment had been receiving manually adjusted invoices for several months to account for the gap between what SAP calculated and what the sales team had promised. The conflict was invisible in daily operations. It became impossible to ignore when clean SAP pricing data had to serve as the sole authoritative input to a deterministic pricing engine.

The conflicts were resolved in SAP before the portal went live. On launch day, buyers saw their actual contracted net prices for the first time — derived directly from clean SAP data through the pricing engine, with no manual adjustment at invoice time. Invoice corrections in the first thirty days fell to near zero. Not because the portal displayed prices more clearly, but because the source data was now accurate and the pricing calculation was deterministic. The ERP became the single source of truth that it was always supposed to be — because the integration forced the question of ownership that daily manual operations had allowed the team to avoid.


What the ordering layer controls — and the ERP should not

The ordering layer is not passive in this architecture. It controls the buyer experience, the ordering rules, and the order-side exception workflow — capabilities the ERP was not built for and should not be expected to provide.

Catalog visibility and assortment rules are managed in the ordering layer's Admin Console, not in the ERP. Which SKUs a given customer segment can see, which products are restricted for regulatory reasons in Saudi Arabia, which are excluded from specific buyers for commercial terms — these rules are configured centrally and applied at the catalog display level. The ERP holds the product master. The ordering layer controls who sees what, and when. This separation is important because assortment rules change frequently — new regulatory exclusions, segment-level commercial decisions, seasonal SKU availability — and those changes must be manageable without ERP development work.

MOQ and pack type enforcement is an ordering layer function. The ERP holds MOQ configuration as reference data. The ordering layer reads that configuration and applies it at cart — blocking an invalid quantity before the buyer submits, with a clear correction prompt showing the nearest valid quantity. This enforcement happens in the portal because the ERP does not have a buyer cart. The enforcement point is where the buyer is interacting with the system. The ERP data makes the enforcement possible. The ordering layer makes it happen.

Order lifecycle visibility — the buyer's view of their order from submission through to delivered and invoiced — is also an ordering layer function. The ERP generates the warehouse pick, the shipment record, and the invoice. The ordering layer queries these status events and presents them to the buyer as a readable order timeline: Order Received, Processing, Preparing Shipment, Out for Delivery, Delivered, Invoiced. The ERP does not build that view. It does not need to. The ordering layer translates ERP status codes into buyer-facing language, which means the ERP's internal terminology and process codes never need to be exposed to the buyer directly.

Emdaad's integration architecture reflects this separation throughout. The ERP is the source of truth for customers, inventory, and pricing. The ordering layer queries those sources at the moments they are needed — catalog display, cart validation, order confirmation — and writes a single record back: the confirmed order. Each system does what it was designed for. The integration defines the boundary between them — and holds it.

For distributors evaluating a move from manual or ERP-only ordering to a self-service buyer portal, the integration design conversation should happen before the vendor selection conversation. The question of what locks and what syncs is not a technical implementation detail. It is the decision that determines whether the integration holds up at month three — or gets rolled back at week three.