Phase 4 · Purchasing · Oracle RMS Series

Oracle RMS Purchase Orders

Purchase Orders are the engine of retail buying in Oracle RMS. From a buyer manually placing a seasonal order to the replenishment engine raising hundreds of automated POs overnight — every order travels through the same three-table structure, the same status lifecycle, and the same approval and transmission pathway. This guide covers all of it.

15 min read📅April 25, 2026✍️Priyanshu Pandey📚Oracle RMS Series

What Is a Purchase Order in Oracle RMS?

A Purchase Order in Oracle RMS is the formal record of a buying commitment between a retailer and a supplier. It specifies what items are being ordered, in what quantities, at what cost, and for delivery to which locations. Every unit of stock that arrives at a store or warehouse enters the system through a purchase order receipt — there is no other way to introduce new inventory into the RMS stock ledger.

Purchase orders in RMS are created in two fundamentally different ways. Manual POs are created by buyers working in the RMS buying screen — selecting a supplier, adding items, specifying quantities, and setting delivery dates. Automated POs are generated by the replenishment engine, which calculates required quantities based on sales patterns, min/max thresholds, and lead times, then creates POs without buyer intervention subject to the AUTO_APPR_IND configuration on ITEM_LOC.

Both types produce identical records in the same three tables: ORDHEAD, ORDSKU, and ORDLOC. The distinction between manual and automated is carried in the ORDER_TYPE column on ORDHEAD and in workflow attributes — it does not change the fundamental data structure.

📋
Every stock receipt in RMS traces back to a PO

There is no mechanism in Oracle RMS to receive stock without a corresponding purchase order. Even inventory adjustments, transfers, and returns use different transaction types. The purchase order is the only pathway for new inventory to enter the system from an external supplier. This is a fundamental design constraint — it means every unit of supplier-sourced stock has a complete audit trail from order to receipt to stock ledger.

Three-Table Structure

The Three-Table PO Structure

Every purchase order in Oracle RMS is represented by three related records that form a parent-child-grandchild hierarchy:

Calendar Rollup Hierarchy
ORDHEAD — PO HeaderOne row per purchase order

The top-level record. Identifies the supplier, the overall PO status, the currency and exchange rate, payment terms, shipping method, and all header-level dates. Every ORDSKU and ORDLOC row for the order references this via ORDER_NO.

ORDSKU — Item LinesOne row per item on the PO

One row per distinct item ordered on the PO. Holds the agreed unit cost for that item on this specific order, the total ordered quantity rolled up from ORDLOC, and item-level attributes like origin country and supplier reference number. A PO with 50 different items has 50 ORDSKU rows.

ORDLOC — Location LinesOne row per item per delivery location

The most granular level. One row per item per delivery location on the PO. This is where the actual ordered quantity and received quantity live. A PO for 10 items each destined for 20 stores has 200 ORDLOC rows. All inventory movement calculations reference ORDLOC — it is the source of STOCK_ON_ORDER in ITEM_LOC_SOH.

PO Types

PO Types — Regular, Replenishment, Distribution

The ORDER_TYPE column on ORDHEAD classifies the purpose of the purchase order. This drives workflow routing, approval rules, and how the order is handled in downstream systems.

0RRegular / Manual PO
ORDER_TYPE = 'N' or 'R'

Created manually by a buyer for planned purchases — seasonal buys, promotional stock, new item introductions, or opportunistic buys outside the automated replenishment cycle. The buyer selects supplier, items, quantities, and delivery dates explicitly. These orders typically go through a full approval workflow before transmission.

0BReplenishment PO
ORDER_TYPE = 'B' (Buyer-generated by replenishment)

Generated by the Oracle RMS replenishment engine based on calculated demand, current stock levels, and supplier lead times. Replenishment POs are the most common PO type in a live RMS environment — they run overnight in batch and can create hundreds of orders per run. Whether they are auto-approved or require buyer review is controlled by AUTO_APPR_IND on ITEM_LOC.

0DDistribution Order
ORDER_TYPE = 'D'

A distribution order moves stock from a warehouse to one or more stores as a pre-distribution — allocating inventory before it arrives at the warehouse rather than through a separate transfer after receipt. The warehouse receives against the distribution order, and the system simultaneously allocates the received stock to the destination stores. Used heavily in fashion and seasonal retail where pre-season allocations need to be committed ahead of delivery.

0CConsignment and Concession Orders
PURCHASE_TYPE = 1 or 2 on ORDSKU

For consignment stock (where ownership transfers only on sale, not on receipt) and concession arrangements (where a third party sells on the retailer's premises), Oracle RMS uses a modified PO workflow indicated by PURCHASE_TYPE on ORDSKU: 1 = consignment, 2 = concession. The structural tables are the same; the cost accounting and settlement logic differs.

Status Lifecycle

The Status Lifecycle — Worksheet to Closed

Every Oracle RMS purchase order progresses through a defined status lifecycle. Status transitions are governed by business rules that the application enforces — an order cannot jump from Worksheet to Closed, for example, because receiving cannot occur against an unapproved order.

Calendar Rollup Hierarchy
Worksheet — 'W'Being built — not yet submitted

The starting state for all manually created POs. The buyer can add items, change quantities, and modify costs freely. Worksheet POs have no commitment to the supplier. Replenishment-generated POs skip this state if AUTO_APPR_IND = 'Y' — they are created directly in Approved status.

Submitted — 'S'Awaiting approval

The buyer has completed the PO and submitted it for approval. The order can no longer be freely edited — changes require it to be returned to Worksheet. For orders where AUTO_APPR_IND = 'Y', this state is bypassed automatically.

Approved — 'A'Ready for supplier transmission

The PO has been approved by an authorised buyer. From here it can be transmitted to the supplier via EDI, email, or print. Once Approved, ORDLOC quantities contribute to ITEM_LOC_SOH.STOCK_ON_ORDER — the stock is committed and affects replenishment calculations.

In Progress — 'I'Partially received

At least one ORDLOC line has received some quantity but not the full ordered quantity. The PO remains open for further receipts. STOCK_ON_ORDER in ITEM_LOC_SOH decreases by the received quantity as each receipt is processed.

Closed — 'C'Fully received or manually closed

All ORDLOC lines have been fully received, or the PO was manually closed by a buyer after all viable receipts were completed. Stock on order for all lines drops to zero. The PO is a read-only historical record.

Cancelled — 'X'Cancelled before full receipt

The PO was cancelled before all lines were received. Any quantities already received remain in stock. Outstanding undelivered quantities are removed from STOCK_ON_ORDER. A PO with any receipt quantity cannot be fully cancelled — partial cancellation applies to undelivered lines only.

⚠️
Approved POs contribute to STOCK_ON_ORDER — this affects replenishment

The moment a PO reaches STATUS = 'A', all ORDLOC.QTY_ORDERED values for that order are added to ITEM_LOC_SOH.STOCK_ON_ORDER at each delivery location. Replenishment calculations subtract STOCK_ON_ORDER from the calculated need before raising new orders. An Approved PO that is never transmitted or received ties up stock-on-order capacity and suppresses future replenishment orders — a common cause of understocking when old approved POs are left open.

ORDHEAD

ORDHEAD — PO Header Deep Dive

01ORDHEAD
One row per purchase order
ColumnTypeDescription
ORDER_NOPK
NUMBER(10)System-generated PO number. The primary key referenced by all ORDSKU and ORDLOC rows.
SUPPLIERFK
NUMBER(10)FK → SUPS.SUPPLIER. The supplier this order is placed with.
STATUS
VARCHAR2(1)W = Worksheet · S = Submitted · A = Approved · I = In Progress · C = Closed · X = Cancelled.
ORDER_TYPE
VARCHAR2(1)N/R = Regular · B = Replenishment · D = Distribution. Controls workflow and downstream processing.
WRITTEN_DATE
DATEDate the PO was created. Populated at INSERT time.
ORIG_APPROVAL_DATE
DATEDate the PO was first approved. Set when STATUS transitions to 'A'.
NOT_BEFORE_DATE
DATEEarliest date the supplier should ship. Also called the earliest ship date.
NOT_AFTER_DATE
DATELatest date the supplier should ship. Orders arriving after this date may be subject to penalties.
OTB_EDATE
DATEThe Open to Buy end date — identifies which OTB period this order's cost commits against.
CURRENCY_CODE
VARCHAR2(3)Trading currency of the order. Usually the supplier's default currency from SUPS.
EXCHANGE_RATE
NUMBER(20,10)Exchange rate applied to convert PO currency to primary currency at the time of order creation.
TERMS
VARCHAR2(30)Payment terms code for this order. Defaults from SUPS.PAYMENT_TERMS but can be overridden per PO.
SHIP_METHOD
VARCHAR2(30)Shipping method — AIR, SEA, ROAD, etc.
IMPORT_IND
VARCHAR2(1)Y = import order (cross-border). Triggers additional import management and duty calculation workflows.
DEPTFK
NUMBER(4)FK → DEPS.DEPT. Department-level association. Relevant for department-level OTB tracking.
QC_IND
VARCHAR2(1)Y = this order requires quality control inspection on receipt before stock is posted to sellable SOH.
COMMENT_DESC
VARCHAR2(4000)Free-text buyer notes and order comments. Not transmitted to suppliers unless explicitly included in EDI.
ORDSKU

ORDSKU — Item Line Details

02ORDSKU
ORDER_NO + ITEM composite PK
ColumnTypeDescription
ORDER_NOPKFK
NUMBER(10)FK → ORDHEAD.ORDER_NO.
ITEMPKFK
VARCHAR2(25)FK → ITEM_MASTER.ITEM. Always VARCHAR2 — never cast to NUMBER.
UNIT_COST
NUMBER(20,4)Agreed unit cost for this item on this order. Defaults from ITEM_SUPPLIER.UNIT_COST but can be overridden per PO line.
ORIGIN_COUNTRY_ID
VARCHAR2(3)Country of origin for this item on this order. Drives duty and landed cost calculations.
SUPP_PACK_SIZE
NUMBER(12,4)Outer case pack size as agreed for this order. Defaults from ITEM_SUPPLIER.SUPP_PACK_SIZE.
INNER_PACK_SIZE
NUMBER(12,4)Inner pack size for this order. Defaults from ITEM_SUPPLIER.INNER_PACK_SIZE.
PURCHASE_TYPE
NUMBER(1)0 = standard purchase · 1 = consignment · 2 = concession. Controls cost accounting on receipt.
SUPP_REF_NUM
VARCHAR2(30)Supplier's reference number for this item — the supplier's own SKU code. Used in EDI and supplier communications.
COMMENT_DESC
VARCHAR2(4000)Item-level order notes. Visible to the buyer; may be included in PO transmission depending on EDI configuration.
ORDLOC

ORDLOC — Location-Level Quantities

ORDLOC is the most operationally active of the three PO tables. It holds the quantity ordered and quantity received per item per delivery location, and is the table directly read by receiving processes, replenishment calculations, and stock-on-order reporting.

03ORDLOC
ORDER_NO + ITEM + LOC + LOC_TYPE composite PK
ColumnTypeDescription
ORDER_NOPKFK
NUMBER(10)FK → ORDHEAD.ORDER_NO.
ITEMPKFK
VARCHAR2(25)FK → ITEM_MASTER.ITEM. Part of composite PK with ORDER_NO and LOC.
LOCPK
NUMBER(10)Delivery location number — STORE.STORE or WH.WH. Combined with LOC_TYPE to identify the receiving location.
LOC_TYPEPK
VARCHAR2(1)'S' = store · 'W' = warehouse. Always filter on LOC and LOC_TYPE together.
QTY_ORDERED
NUMBER(12,4)Quantity ordered for this item at this location. The original committed quantity.
QTY_RECEIVED
NUMBER(12,4)Quantity received so far. Updated by each receipt transaction. When QTY_RECEIVED = QTY_ORDERED, this line is fulfilled.
QTY_CANCELLED
NUMBER(12,4)Quantity cancelled on this line. QTY_ORDERED - QTY_RECEIVED - QTY_CANCELLED = outstanding quantity.
UNIT_COST
NUMBER(20,4)Unit cost at delivery location level. Usually matches ORDSKU.UNIT_COST but can differ for location-specific pricing.
CANCEL_DATE
DATEDate this specific line was cancelled. NULL if not cancelled.
EARLIEST_SHIP_DATE
DATELocation-level earliest ship date override. NULL if inheriting from ORDHEAD.NOT_BEFORE_DATE.
LATEST_SHIP_DATE
DATELocation-level latest ship date override. NULL if inheriting from ORDHEAD.NOT_AFTER_DATE.
📊
ORDLOC is the source of STOCK_ON_ORDER in ITEM_LOC_SOH

When an ORDLOC row is created for an Approved PO (or when a PO transitions to Approved status), Oracle RMS adds QTY_ORDERED to ITEM_LOC_SOH.STOCK_ON_ORDER for the corresponding item-location combination. Each receipt against the PO reduces QTY_RECEIVED on ORDLOC and correspondingly reduces STOCK_ON_ORDER. This keeps the stock-on-order position in ITEM_LOC_SOH always in sync with the outstanding committed quantity across all open ORDLOC lines.

Approval Workflow

The Approval and Transmission Workflow

The path from a Worksheet PO to a transmitted order involves distinct steps that Oracle RMS either automates or routes to a buyer queue depending on configuration.

04Manual PO Approval Path
Buyer-created orders
  1. Buyer creates POSTATUS = 'W' (Worksheet). Items, quantities, and costs are entered.
  2. Buyer submits for approvalSTATUS = 'S'. PO is locked from editing and appears in the approver's queue.
  3. Approver reviews and approvesSTATUS = 'A'. ORIG_APPROVAL_DATE is set. STOCK_ON_ORDER is updated across all ORDLOC locations.
  4. PO is transmitted to supplier → via EDI, email, or printed document. The transmission event is recorded but does not change STATUS.
  5. Supplier acknowledges and ships → no direct RMS status change unless EDI acknowledgement processing is active.
  6. Stock arrives and is received → STATUS moves to 'I' (first receipt) and eventually 'C' (fully received).
05Replenishment PO Path
AUTO_APPR_IND = 'Y' — no buyer intervention
  1. Replenishment batch calculates need → based on SOH, STOCK_ON_ORDER, min/max thresholds, and lead times.
  2. PO created directly in Approved statusSTATUS = 'A' set at creation. Worksheet and Submitted states are skipped.
  3. STOCK_ON_ORDER updated immediately at the ORDLOC locations.
  4. PO transmitted via EDI → automated transmission batch sends the PO to the supplier without buyer intervention.
  5. Receipt processed on delivery → STATUS transitions through 'I' to 'C'.
⚠️
AUTO_APPR_IND = 'N' creates a Worksheet PO — not Submitted or Approved

When AUTO_APPR_IND = 'N' on ITEM_LOC, replenishment-generated POs are created with STATUS = 'W' (Worksheet), not 'S' or 'A'. They appear in the buyer's to-do queue for manual review and approval. If the buyer's queue is not monitored, these POs sit as Worksheets indefinitely — STOCK_ON_ORDER is not updated until they reach Approved status, so replenishment will keep trying to generate new POs for the same items.

Open to Buy

Open to Buy — OTB_EDATE and Cost Impact

Oracle RMS integrates with an Open to Buy (OTB) framework that tracks buying commitments against budget periods. The OTB_EDATE column on ORDHEAD identifies which OTB period a purchase order's cost commitment falls within.

When a PO is approved, its total cost (sum of ORDLOC.UNIT_COST × QTY_ORDERED across all lines) is committed against the OTB budget for the OTB_EDATE period in the item's department. This is how buyers track whether they have sufficient budget headroom before approving additional orders.

ColumnTypeDescription
OTB_EDATE on ORDHEAD
DATEThe end date of the OTB period this order falls within. Set by the buyer at order creation — usually the planned delivery period end date.
OTB commitment
On ApprovalWhen STATUS changes to 'A', the PO's total cost is committed against OTB for ORDHEAD.DEPT in the OTB_EDATE period.
OTB release
On Receipt or CancellationWhen lines are received or cancelled, the committed OTB is released proportionally, freeing budget for future orders in the same period.
Partial Receipts

Partial Receipts and the In Progress State

Real-world supplier deliveries are rarely exactly the ordered quantity. Suppliers often deliver in multiple shipments, deliver short due to production issues, or deliver in a different quantity than ordered. Oracle RMS handles this through the In Progress ('I') status and the QTY_RECEIVED column on ORDLOC.

06How Partial Receipts Work
ORDLOC.QTY_RECEIVED tracks each delivery

Each receipt transaction against a PO line:

  1. Increases ORDLOC.QTY_RECEIVED by the receipt quantity
  2. Increases ITEM_LOC_SOH.STOCK_ON_HAND at the receiving location by the receipt quantity
  3. Decreases ITEM_LOC_SOH.STOCK_ON_ORDER by the receipt quantity
  4. Updates ITEM_LOC_SOH.AV_COST using the weighted average cost formula
  5. Creates stock ledger entries in STKLEDGR for the inventory movement

The PO transitions to 'I' (In Progress) on the first partial receipt and remains there until all lines are fully received or the PO is manually closed.

Outstanding quantity per ORDLOC line: QTY_ORDERED - QTY_RECEIVED - QTY_CANCELLED

When this value reaches zero for all lines on the PO, the PO is eligible for closure. Oracle RMS can auto-close POs when the last receipt brings the outstanding to zero, or buyers can manually close POs with outstanding quantities that the supplier will not deliver.

RC:OMS · Multi-Channel Order Management
Managing purchase orders and stock receipts across Amazon, Flipkart and your own store?

RC:OMS brings the same double-entry inventory accuracy as Oracle RMS to multi-channel stock management. Every purchase receipt, every channel sale, every stock movement tracked with full audit trail. Built for Indian multi-channel sellers — no overselling, no reconciliation gaps.

Launch RC:OMS Demo
Quick Reference

Key Tables — Quick Reference

Purchase Order Tables — Oracle RMS
ORDHEAD
PO header — one per order
ORDSKU
Item lines — one per item
ORDLOC
Location lines — one per item per loc
ITEM_LOC_SOH
SOH updated on every receipt
STKLEDGR
Stock ledger — receipt audit trail
SUPS
Supplier master — FK on ORDHEAD
Practical SQL

Practical SQL Examples

1. Full PO summary — header, items, quantities and delivery locations

SQL

-- Complete PO view from header through to location quantities SELECT oh.order_no, oh.status, oh.order_type, s.supp_name, oh.currency_code, oh.written_date, oh.orig_approval_date, oh.not_before_date, oh.not_after_date, os.item, im.item_desc, os.unit_cost, ol.loc, ol.loc_type, CASE ol.loc_type WHEN 'S' THEN st.store_name WHEN 'W' THEN w.wh_name END loc_name, ol.qty_ordered, ol.qty_received, ol.qty_cancelled, ol.qty_ordered

  • ol.qty_received
  • NVL(ol.qty_cancelled, 0) qty_outstanding, ROUND(ol.qty_ordered * os.unit_cost, 2) line_cost FROM ordhead oh JOIN sups s ON s.supplier = oh.supplier JOIN ordsku os ON os.order_no = oh.order_no JOIN item_master im ON im.item = os.item JOIN ordloc ol ON ol.order_no = os.order_no AND ol.item = os.item LEFT JOIN store st ON st.store = ol.loc AND ol.loc_type = 'S' LEFT JOIN wh w ON w.wh = ol.loc AND ol.loc_type = 'W' WHERE oh.order_no = :v_order_no ORDER BY os.item, ol.loc;

2. Open POs by supplier — outstanding stock on order

SQL

-- All open Approved and In Progress POs for a supplier -- Shows total outstanding value and quantity per item SELECT oh.order_no, oh.status, oh.currency_code, oh.not_before_date, os.item, im.item_desc, SUM(ol.qty_ordered) total_ordered, SUM(ol.qty_received) total_received, SUM(ol.qty_ordered

  • ol.qty_received
  • NVL(ol.qty_cancelled, 0)) total_outstanding, SUM((ol.qty_ordered
  • ol.qty_received
  • NVL(ol.qty_cancelled, 0))
  • os.unit_cost) outstanding_cost FROM ordhead oh JOIN ordsku os ON os.order_no = oh.order_no JOIN item_master im ON im.item = os.item JOIN ordloc ol ON ol.order_no = os.order_no AND ol.item = os.item WHERE oh.supplier = :v_supplier AND oh.status IN ('A', 'I') GROUP BY oh.order_no, oh.status, oh.currency_code, oh.not_before_date, os.item, im.item_desc HAVING SUM(ol.qty_ordered
  • ol.qty_received
  • NVL(ol.qty_cancelled, 0)) > 0 ORDER BY oh.not_before_date, os.item;

3. Approved POs older than lead time — overdue delivery check

SQL

-- Approved POs where NOT_AFTER_DATE has passed and no receipt has occurred -- These represent overdue deliveries that are still holding STOCK_ON_ORDER SELECT oh.order_no, oh.written_date, oh.not_after_date, SYSDATE - oh.not_after_date days_overdue, s.supp_name, s.contact_name, s.contact_phone, COUNT(DISTINCT os.item) item_count, SUM(ol.qty_ordered - NVL(ol.qty_received, 0)

  • NVL(ol.qty_cancelled, 0)) total_outstanding_units, SUM((ol.qty_ordered - NVL(ol.qty_received, 0)
  • NVL(ol.qty_cancelled, 0))
  • os.unit_cost) outstanding_cost FROM ordhead oh JOIN sups s ON s.supplier = oh.supplier JOIN ordsku os ON os.order_no = oh.order_no JOIN ordloc ol ON ol.order_no = os.order_no AND ol.item = os.item WHERE oh.status IN ('A', 'I') AND oh.not_after_date < SYSDATE AND ol.qty_received = 0 GROUP BY oh.order_no, oh.written_date, oh.not_after_date, s.supp_name, s.contact_name, s.contact_phone ORDER BY days_overdue DESC;

4. Worksheet POs that AUTO_APPR_IND should have auto-approved — replenishment queue check

SQL
-- Replenishment POs sitting in Worksheet status when they should be auto-approved
-- Indicates AUTO_APPR_IND configuration issue or a batch failure
SELECT oh.order_no,
oh.written_date,
oh.supplier,
s.supp_name,
COUNT(DISTINCT os.item)                    item_count,
MIN(oh.written_date)                       oldest_po_date
FROM   ordhead   oh
JOIN   sups      s   ON s.supplier  = oh.supplier
JOIN   ordsku    os  ON os.order_no = oh.order_no
WHERE  oh.status     = 'W'
AND  oh.order_type = 'B'               -- replenishment-generated
AND  oh.written_date < SYSDATE - 1    -- older than 1 day
GROUP BY oh.order_no, oh.written_date, oh.supplier, s.supp_name
ORDER BY oh.written_date;

5. PL/SQL — check whether a PO can be cancelled

PL/SQL

-- Validate whether a PO is eligible for cancellation -- Returns 'OK' or a description of the blocking condition FUNCTION can_cancel_po ( p_order_no IN ordhead.order_no%TYPE ) RETURN VARCHAR2 IS l_status ordhead.status%TYPE; l_recv_count PLS_INTEGER; BEGIN SELECT status INTO l_status FROM ordhead WHERE order_no = p_order_no;

-- Cannot cancel a Closed PO IF l_status = 'C' THEN RETURN 'BLOCKED: PO is already Closed'; END IF;

-- Cannot cancel an already-Cancelled PO IF l_status = 'X' THEN RETURN 'BLOCKED: PO is already Cancelled'; END IF;

-- If In Progress, check for any received quantities IF l_status = 'I' THEN SELECT COUNT(1) INTO l_recv_count FROM ordloc WHERE order_no = p_order_no AND qty_received > 0;

IF l_recv_count > 0 THEN RETURN 'PARTIAL_CANCEL_ONLY: PO has ' || l_recv_count || ' line(s) with receipts — only outstanding lines can be cancelled'; END IF; END IF;

RETURN 'OK';

EXCEPTION WHEN NO_DATA_FOUND THEN RETURN 'NOT_FOUND: ORDER_NO ' || p_order_no || ' does not exist'; WHEN OTHERS THEN RETURN 'ERROR: ' || SQLERRM; END can_cancel_po;

Gotchas

Common Gotchas for Developers

  • !

    Querying ORDLOC without LOC_TYPE and getting duplicate location results. Store 200 and Warehouse 200 both appear as LOC = 200 in ORDLOC. The LOC_TYPE column is the only discriminator. Filtering by LOC alone in PO queries will return rows for both location types when the numbers collide — silently doubling quantities in aggregated reports.

  • !

    Leaving Approved POs open after the supplier confirms non-delivery.

    Approved POs with no receipts continue to hold STOCK_ON_ORDER in ITEM_LOC_SOH indefinitely. The replenishment engine subtracts this stock-on-order from calculated need, so it will not raise replacement orders for items it believes are already on the way. When a supplier confirms they cannot deliver, POs must be explicitly cancelled or closed to release the stock-on-order commitment.

  • !

    Treating ORDSKU.UNIT_COST as the definitive cost for all locations.

    ORDLOC also has a UNIT_COST column that can differ from ORDSKU.UNIT_COST when location-specific pricing is configured. The receiving process uses ORDLOC.UNIT_COST to calculate the WAC update for ITEM_LOC_SOH.AV_COST. Reporting queries that calculate total order value using only ORDSKU.UNIT_COST × ORDLOC.QTY_ORDERED may produce incorrect figures if the two cost columns differ.

  • !

    Creating POs for items not ranged at the delivery location.

    Oracle RMS validates on PO approval that the delivery location in ORDLOC has a corresponding ITEM_LOC record for the item. If the item is not ranged at that location, the approval will fail. Direct SQL inserts to ORDLOC that bypass this check will create PO lines that cannot be received — the receiving process will fail when it tries to update ITEM_LOC_SOH and finds no SOH record.

  • !

    Using ORDSKU for total order quantities without summing ORDLOC.

    The canonical source for ordered and received quantities is ORDLOC, not ORDSKU. Some implementations store a rolled-up total quantity on ORDSKU as a convenience column, but it may not be kept perfectly in sync with ORDLOC in all RMS versions. Always sum ORDLOC.QTY_ORDERED aggregated by ORDER_NO + ITEM when you need the accurate total ordered quantity per item per PO.

  • !

    Not accounting for QTY_CANCELLED when calculating outstanding quantity.

    The formula for outstanding quantity on an ORDLOC line is QTY_ORDERED - QTY_RECEIVED - QTY_CANCELLED. Queries that calculate outstanding as simply QTY_ORDERED - QTY_RECEIVED will overstate outstanding for partially cancelled lines, producing incorrect stock-on-order totals and misleading replenishment calculations.

  • !

    Raising a PO to a supplier with SUP_STATUS = 'I' (Inactive). Oracle RMS blocks PO creation against an inactive supplier through the UI. Integration scripts that create ORDHEAD records via direct SQL bypass this check. An inactive supplier's PO will pass insertion but fail when the EDI transmission batch tries to resolve the supplier's communication details — causing a silent transmission failure that leaves the supplier unaware of the order.

Key Takeaways

Key Takeaways
  • Every purchase order in Oracle RMS spans three tables: ORDHEAD (one per PO), ORDSKU (one per item on the PO), and ORDLOC (one per item per delivery location). The outstanding quantity per line is QTY_ORDERED - QTY_RECEIVED - QTY_CANCELLED.
  • The PO status lifecycle has six states: Worksheet (W) → Submitted (S) → Approved (A) → In Progress (I) → Closed (C) or Cancelled (X). STOCK_ON_ORDER in ITEM_LOC_SOH is only committed when the PO reaches Approved status.
  • Approved POs that are never received continue to hold STOCK_ON_ORDER indefinitely, suppressing future replenishment orders for the same items. Overdue POs must be explicitly cancelled or closed to release their commitment.
  • Always filter ORDLOC on both LOC and LOC_TYPE together — Store 200 and Warehouse 200 share the same LOC value; LOC_TYPE is the only discriminator.
  • ORDLOC.UNIT_COST drives WAC updates at receipt — not ORDSKU.UNIT_COST. The two can differ when location-specific pricing is configured. Always use ORDLOC.UNIT_COST in receiving cost calculations.
  • AUTO_APPR_IND = 'N' on ITEM_LOC creates replenishment POs in Worksheet status, not Approved — they require buyer action before STOCK_ON_ORDER is committed. Unmonitored approval queues are a common cause of stockouts.
  • OTB_EDATE on ORDHEAD identifies which Open to Buy period the order's cost commits against. Cost is committed on Approval and released on receipt or cancellation.
RetailCoder
All systems operational
v1.0 Live

RC:OMS

Multi-channel order management with double-entry inventory ledger. Amazon, Flipkart, Shopify, WooCommerce — one source of truth.

Launch demo →
v1.0 Live

RC:Storefront

Self-hosted headless e-commerce. Your server, your data, zero transaction fees. Native RC:OMS inventory sync.

Visit Storefront →
Pipeline

RC:Pulse

AI-powered retail analytics and demand forecasting — built natively on top of your RC:OMS and Storefront data.

Request early access →
Built in India 🇮🇳  ·  Architected by Priyanshu PandeyTalk to an engineer →