Use Order Management Extensions to Import Large Volumes of Sales Orders

Use an order management extension when you have a large volume of them to import.

Assume you need to process 100,000 order lines each hour and over 1,000,000 order lines each day. We recommend that you use an order management extension instead of a transformation rule. An extension provides superior performance when processing a high volume of lines.

For details about using extensions, see Overview of Creating Order Management Extensions.

For details and examples, go to REST API for Oracle Supply Chain Management Cloud, expand Order Management, then click Sales Orders for Order Hub.

Guidelines

Make sure your extension:

  • Creates the customer before you import the order.
  • Identifies the item.
    • Sets the value for the ProductIdentifier attribute or the ProductNumber attribute on the order line. Make sure the value uniquely identifies the item.
    • Make sure the Product Information Management work area contains the item that these attributes reference.
  • Sets the Ordered Quantity attribute on the order line to a positive, numeric value.
  • Adds the new order line on the On Save or the On Start of Submission Request event. Don't add the line on the End of Submission event.
  • Adds the new line to a sales order that isn't closed or canceled. If the sales order is closed or canceled, then you can't add a new line to that order.
  • Adds a new line that references an existing order line only when a transformation rule hasn't already transformed the existing line.
  • Doesn't add a configured item to a sales order. You can't use an extension to add a configured item to a sales order.
  • Doesn't add a new order line to a sales order during the End of Submission event.

A transformation rule automatically does a number of actions. However, if you use an extension, then you must code your extension to do these actions:

  • Set the default quantity of the order line that you're adding according to the quantity on the source line.
  • You must cascade or manipulate the quantity according to the source line, or specify a quantity according to some other attribute.
  • If you modify or remove the source line, then your extension must modify or remove the new line that it created for the source line.

Note

  • You must enable the Import and Fulfill Large Volumes of Sales Orders opt-in feature. For details, see Use REST API with FBDI to Import Large Volumes of Sales Orders.
  • As an option, you can enable the Respond Immediately on Start of Submission Request order profile. If you do, the Sales Orders For Order Hub REST service will respond when it starts to submit the sales order. If you don't enable it, then REST responds after it finishes submitting the sales order.
  • REST API can't call an oracle business rule, but you can use it with all three extension points.
  • You can't use extensions and transformation rules to add new lines at the same time. You must use extensions or transformation rules.
  • Transformation rules and extensions set the price of the new line to 0.
  • You can't edit the new line in the Order Management work area.

Examples

Assume the examples in this subtopic use these values.

ProductIdentifier ProductNumber
149 AS54888
2157 AS92888

Add More Than Order One Line for a Source Line

Assume you need to import item AS54888 and transform it into two separate order lines. One line will have the AS92888 item with a quantity of 15, and the other line will have the AS54888 item with a quantity of 20.

import oracle.apps.scm.doo.common.extensions.CreateLineParams;
  
if( !"CREATE_MUL_LINES".equals( header.getAttribute("CustomerPONumber" ) ) ) return;
  
def lines = header.getAttribute("Lines");
   
while( lines.hasNext() ) {
  def line = lines.next();
  
//If the source line is closed, cancelled, or already transformed, then you can't add it to the sales order.  
// See if the source line is closed.
  def isClosed = line.isClosed()

    // See if the source line is canceled.
  def isCanceled = line.isCanceled()

    // See if the source line is already transformed.
  def isTransformed = line.isTransformed();
    
  if (isClosed || isCanceled || isTransformed) { // Skip if the line is closed, canceled, or already transformed.
    continue;
  }//Get the name of the item that’s on the order line.
  def productName = line.getAttribute("ProductName");
    
  if (isClosed || isCanceled || isTransformed || productName != 'AS54888') { // Skip this section if the line is closed, canceled, already transformed, or the item on the line isn't AS54888.

    continue;
  }
  
  def orderedQuantity = line.getAttribute("OrderedQuantity");
  
  //// Add the first transformed line AS92888
  def createLineParams = new CreateLineParams();
  createLineParams.setProductNumber("AS92888");
  //createLineParams.setProductIdentifier(2157);
  createLineParams.setOrderedUOM("Each")
  createLineParams.setOrderedQuantity(15);
  
  def transformedLines = line.getTransformedLines("AS92888");
  //def transformedLines = line.getTransformedLines(2157);
  if (transformedLines.size() == 0) { // If you haven't already added the line, then add it now.
     line.createNewLine(createLineParams);

  }
  
  //// Add the second transformed line AS54888
  createLineParams.setProductNumber("AS54888");
  //createLineParams.setProductIdentifier(149);
  createLineParams.setOrderedUOM("Each")
  createLineParams.setOrderedQuantity(20);
  
  transformedLines = line.getTransformedLines("AS54888");
  //transformedLines = line.getTransformedLines(149);
  if (transformedLines.size() == 0) { // add new line if it is not created before
     line.createNewLine(createLineParams);
  }
}

Add a Line According to Conditions

You can specify to add a new order line only if the source line meets a condition. Assume you want to add a line only if the import payload contains the AS54888 item and its quantity is 100.

import oracle.apps.scm.doo.common.extensions.CreateLineParams;
 
if( !"CREATE_LINE_IF_AS54888&QTY100".equals( header.getAttribute("CustomerPONumber" ) ) ) return;
 
def lines = header.getAttribute("Lines");
  
while( lines.hasNext() ) {
  def line = lines.next();
 
  def isClosed = line.isClosed()
  def isCanceled = line.isCanceled()
  def isTransformed = line.isTransformed();
   
  if (isClosed || isCanceled || isTransformed) { // Skip if the line is closed or canceled, or if the line is already transformed.
    continue;
  }
 
  def orderedQuantity = line.getAttribute("OrderedQuantity");  // get the original line's quantity
  def productNumber = line.getAttribute("ProductNumber");      // get the original line's product number
 
  if (productNumber == "AS54888" && orderedQuantity == 100) {
 
      //def transformedLines = line.getTransformedLines("AS92888");
      def transformedLines = line.getTransformedLines(2157);
      if (transformedLines.size() == 0) {  // If you haven't already created the transformed line, then create it now.
         def createLineParams = new CreateLineParams();
         //createLineParams.setProductNumber("AS92888");
         createLineParams.setProductIdentifier(2157);
         createLineParams.setOrderedUOM("Each")
         createLineParams.setOrderedQuantity(orderedQuantity);
 
         line.createNewLine(createLineParams);
     }
  }
}

Cancel Order Lines That You Transformed

If you modify or remove the source line, then your extension must modify or remove the new line that it created for the source line. Canceling the source line won't automatically cancel the transformed lines.

This example removes the transformed lines any time you remove the source lines or canceled lines.

import oracle.apps.scm.doo.common.extensions.CreateLineParams;
import oracle.apps.scm.doo.common.extensions.Line;
 
if( !"CANCEL_TRANSFORMED_LINES".equals( header.getAttribute("CustomerPONumber" ) ) ) return;
 
def lines = header.getAttribute("Lines");
                                 
while( lines.hasNext() ) {
   
  def line = lines.next();
 
  def isClosed = line.isClosed();
  def isCanceled = line.isCanceled();
  def isTransformed = line.isTransformed();
  def orderedQuantity = line.getAttribute("OrderedQuantity");
   
  if (orderedQuantity == 0 && !isTransformed) { //Source line is canceled
    List<Line> transfomrLines = line.getTransformedLines(); //Get all the transformed lines for the current line.
    for (Line transformedLine : transfomrLines) {
      def orderedQuantityTL = transformedLine.getAttribute("OrderedQuantity");
      if (orderedQuantityTL != 0 && transformedLine.isOpen()) {
        transformedLine.setAttribute("OrderedQuantity", 0);
      }
    }
  }
}

Example That Fails

Assume you create an extension and receive an error.

Request failed because order management extension CREATE_LINE_CLOSED_CANCELED  attempted to add new line that references a closed or canceled line. Happens during event On Save. You can use an order management extension to add a new order line that references an existing order line only if the existing line isnt closed or canceled.

Here's an example of an extension that fails because it attempts to add a new line to a sales order that's closed, canceled, or already transformed.

"import oracle.apps.scm.doo.common.extensions.CreateLineParams;
if( !"CREATE_LINE_CLOSED_CANCELED".equals( header.getAttribute("CustomerPONumber" ) ) ) return;
def createLineParams = new CreateLineParams();
createLineParams.setProductNumber("AS54888");
createLineParams.setOrderedUOM("Each")
createLineParams.setOrderedQuantity(50);
def lines = header.getAttribute("Lines");
while( lines.hasNext() ) {
  def line = lines.next();
  def isTransformed = line.isTransformed();
  def transformedLines = line.getTransformedLines(); 
  if (isTransformed || transformedLines.size() > 0) {
    continue;
  }
  line.createNewLine(createLineParams);
}"

To avoid this problem, add this snippet near the beginning of your code.

// See if the source line is closed.
  def isClosed = line.isClosed()

    // See if the source line is canceled.
  def isCanceled = line.isCanceled()

    // See if the source line is already transformed.
  def isTransformed = line.isTransformed();
    
  if (isClosed || isCanceled || isTransformed) { // Skip if the line is closed, canceled, or already transformed.
    continue;
  }