Extend Order Lines

You can use an order management extension to create a new order line that is or isn't already related to an existing one.

Examine the Line's Status

Examine the order line's status before you update the line because you might not be able to update an attribute on an order line that's in the Shipped, Invoiced, Closed, or Cancelled status.

Assume your extension updates the Shipping Method attribute, then add a condition at the beginning of your extension that determines whether the line is already fulfilled and closed. If that condition is true, then it doesn't make sense to update the Shipping Method attribute, and you can exit the extension.

Create a New Order Line

Here's an example code snippet that uses the createNewLine method to create a new order line:

header.createNewLine

Note

  • You can use the CreateLineParams() parameter with the createNewLine method.
  • As an option, you can specify a condition according to the values of an existing line to determine whether to add a new line.
  • Use the createNewLine method on the order header.
  • Use the setAttribute method on the order line to set the values for order line attributes when you create the line. If you don't do this, then the order management extension will cascade values from the order header to the order line.
  • If you use an order management extension to add a line, then the extension sets the AddedByExtensionFlag attribute to Y, and you can use it to determine whether an extension added the line.

Use the createNewLine method only:

  • With lines that you price in Oracle Pricing. If you use createNewLine with a line that you price in a source system, you will encounter an error.
  • With the On Save event. If you use createNewLine with any other event, you will encounter an error.
  • To create a line that contains a standard item. If you use createNewLine to create a line that contains a subscription or coverage, you will encounter an error.

Here's an example that creates a new line for an order where the CustomerPONumber attribute contains the value CreateStandaloneLine and the line contains the AS54888 item.

//---
import oracle.apps.scm.doo.common.extensions.CreateLineParams;
  def poNumber = header.getAttribute("CustomerPONumber");
  if(poNumber != "CreateStandaloneLine") return;
    def createLineParams = new CreateLineParams(); // Initialize the new variable so we can send the required attributes.
    createLineParams.setProductNumber("AS54888"); // Add the AS54888 item to the new line.
    createLineParams.setOrderedUOM("Each"); // Set the unit of measure to Each.
    createLineParams.setOrderedQuantity(10); // Set the ordered quantity to 10.
    header.createNewLine(createLineParams); // Use the attribute values from the above lines to create the line. The extension will cascade the other ship to and bill to attribute values from the order header.
--//

Assume the product identifier is 2157 for the AS54888, and you want to use the identifier instead of the number. To specify the identifier instead of the number, replace this line:

createLineParams.setProductNumber("AS54888");

with this line:

createLineParams.setProductIdentifier(2157);

Create an Order Line That Isn't Related to Another Order Line

You can create, read, update, or cancel an order line that has a standard item or service item and you don't have to reference an existing line, but you must price the sales order in Order Management.

The extension automatically updates the AddedByExtensionFlag attribute to indicate that it added the line.

This example adds a freight line according to a condition:

  • If the order line contains the AS54888 item, and if the quantity on the line is less than 5, then add a freight line.

It also adds the freight line's number to the original line.You can use that data to prevent adding another freight line during a subsequent save or revision.

If you copy the line that has the AS54888 after you add the freight line, then Order Management will also copy the extensible flexfield. Your code won't add a freight line for the copied line.

// Import the objects that you need to add an order line.
import oracle.apps.scm.doo.common.extensions.CreateLineParams;
// This code is for testing purposes. It makes sure the extension doesn't affect other users.
// It looks at the customer's purchase order number:
if (!"SNADDFREIGHT".equals(header.getAttribute("CustomerPONumber"))) return;

def lines = header.getAttribute("Lines");
while(lines.hasNext()){
    def line = lines.next();
    def float orderQuantity = line.getAttribute("OrderedQuantity")
    def product = line.getAttribute("ProductNumber");
    def linenumber = line.getAttribute("LineNumber");
    // Use this code to debug the extension:
    debug(" Orig Line " + linenumber + " " + orderQuantity.toString() + product + line.getAttribute("AddedByExtensionFlag"));

    def MinimumOrdQty = 5
    if (product == "AS54888") {
        //If the ordered quantity is more than 5, then continue to next code line.
        if (orderQuantity > MinimumOrdQty) continue;
        else {
          /* Get the extensible flexfield's context for the line. If the context isn't available, then it means the extension didn't add the new line, so you use getContext instead of getOrCreate.
            */
          def effContext = line.getContextRow("FulfillLineContext3");
          //If the extensible flexfield's context is available, and if the segment contains data, then go to next code line.
          if (effContext != null && effContext.getAttribute("_FL3AttributeChar1") != null) continue;
          //If your code reaches this point, then the extension didn't add the freight line.
          def createLineParams = new CreateLineParams();
          createLineParams.setProductNumber("Freight_GST_QPMapper");
          createLineParams.setOrderedUOM("Each");
          createLineParams.setOrderedQuantity(1);
          /* The extension will automatically use header.createNewLine to create the new line.
             This line will include the price just as it would if you added it in the Order Management                                     work area. The extension sets the AddedByExtensionFlag attribute to Y on the new line. 
             If you want to add a free item, then use line.createNewLine instead of header.createNewLine. You can't edit the free line, the free line won't contain a price, and the extension won't set the AddedByExtensionFlag attribute on the free line to Y.*/
          fline = header.createNewLine(createLineParams);
          // Use code line to debug this extension:
          debug("Freight " + fline.getAttribute("LineNumber"));
          // Now that you added the freight line, you can add those details to the extensible flexfield on the original line:
          def effContext1 = line.getOrCreateContextRow("FulfillLineContext3");
          effContext1.setAttribute("_FL3AttributeChar1",fline.getAttribute("LineNumber"));
        }
    }
}

void debug(String msg) {
    header.setAttribute("ShippingInstructions", header.getAttribute("ShippingInstructions") + msg + "\n");
}

Manage an Internal Material Transfer

You can't use the createNewLine method with a sales order that includes an internal material transfer because the pricing for an internal material transfer is frozen.

Use this condition in your extension to skip adding a line when the order includes an internal material transfer:

If (header.getAttribute("TransactionDocumentTypeCode") == "TO") return;

Indicate Whether an Extension Automatically Added an Item

You can customize the Order Management work area to indicate whether an Order Management Extension automatically added an item. Assume you want to display the text Automatically added by system in the description of the item on the order line.

Assume you want to display the text Automatically added by system in the description of the item on the order line

Here's the general flow that you will use to set it up.

Here's the general flow that you will use to set it up.

Try it.

  1. Open Page Composer.
    • Create a sandbox, and enable Page Composer. For details, see Change How Order Management Displays Attributes.
    • Go to the Order Management work area, then click Tasks > Manage Orders.
    • On the Manage Orders page, search for, then open any sales order.
    • On the Order page, in the upper-right corner, click your login name.
    • In the Settings and Actions menu, click Edit Pages.

      Page Composer opens in a separate user interface that sits like a frame around the outside of the Order Management work area. You can now use Page Composer to modify the user interface for the Order Management work area in real time.

  2. Access the sales order's structure.
    • Click Page Composer's Structure tab.
    • Toggle the Hide Structure, Show Structure button so you can see where the Structure window is. Its usually at the bottom of the page.
    • In the Structure window, click Dock > Right.
    • Expand the Structure window until you can examine it's contents.
    • On the sales order, on the order line, click the Item column header.
    • Notice that the Structure window automatically scrolls to the column: Item component.
  3. Add a text component to the sales order.
    • You're going to add text inside the panelGroupLayout: vertical component, so click panelGroupLayout: vertical.
    • At the top of the structure window, click the plus icon ( + ).
    • In the Add Content Dialog, click Components.
    • Click Add in the Text row.
    • Notice that Page Composer added a new showDetailFrame: Text component immediately below the panelGroupLayout: vertical component in the structure window.
    • In the Add Content Dialog, click Close.
  4. Add an order management extension.
    • Right-click the new showDetailFrame: Text component, then click Edit.
    • In the Component Properties dialog, on the Display Options tab, in the Basic section, click the down arrow next to the Text attribute, then click Expression Builder.
    • In the Expression Editor dialog, select the Type a Value or Expression option, then enter the value.
      #{row.bindings.AddedByExtensionFlag.attributeValue=='Y'}
    • Click OK.
    • In the Component Properties dialog, click Apply > OK.
  5. Add the text that you want to display.• Notice that the Item column in the sales order now includes an area where you can enter text.
    • Notice that the Item column in the sales order now includes an area where you can enter text.
    • Click Edit Text, then add the text that you want to display, such as Automatically added by system.

Display an Icon

Assume you have an icon name coverageinclude_ena.png, and you want to display it as part of the item. You can use an order management extension in Page Composer to add it:

Assume you have an icon name coverageinclude_ena.png, and you want to display it as part of the item. You can use an order management extension in Page Composer to add it

Add a Free Item

You can add a free item to an existing item according to a condition. The line will have a price of 0.00 and you can't update it. The extension automatically updates the tranformedFrom attribute to indicate that it added this line to an existing item. For example:

  • If the order line contains the AS54888 item, and if the quantity on the line is more than 10, then add a free item with a quantity 1.

You use the On Save event:

// import the objects that you need to add an order line
import oracle.apps.scm.doo.common.extensions.CreateLineParams;
// This code is for testing purposes. It makes sure the extension doesn't affect other users.
// It looks at the customer's purchase order number:
if (!"SNADDFREE".equals(header.getAttribute("CustomerPONumber"))) return;

def lines = header.getAttribute("Lines");
while(lines.hasNext()){
    def line = lines.next();
    def float orderQuantity = line.getAttribute("OrderedQuantity")
    def product = line.getAttribute("ProductNumber");
    def linenumber = line.getAttribute("LineNumber");
    // Use this code to debug the extension:
    debug(" Orig Line " + linenumber + " " + orderQuantity.toString() + product + line.getAttribute("AddedByExtensionFlag"));

    if (product == "AS54888") {
        //If the ordered quantity is less than or equal to 10, then continue to the next code line.
        if (orderQuantity <= 10) continue;
        else {
          def isClosed = line.isClosed()
          def isCanceled = line.isCanceled()
          def isTransformed = line.isTransformed();
          debug("closed " + isClosed + " canceled " + isCanceled + " transformed " + isTransformed);
          //Make sure the current order line isn't closed, cancelled, or transformed.
          if (isClosed || isCanceled || isTransformed) continue;
          //Make sure you haven't already added a free item to the order line.
          def freeLines = line.getTransformedLines();
          // The above code line gives you a list of lines that you have added for the order line.
          debug(" associated lines " + freeLines);
          //If the above code returns an empty list, then the freeLines variable will be false
          // If you need to check the count of items in the list, then use the size()method.
          if (freeLines && freeLines.size() > 0) continue;
          //If your code reaches this point, then the extension didn't add the free order line.
          def createLineParams = new CreateLineParams();
          createLineParams.setProductNumber("AS54888"); //Freight_GST_QPMapper");
          createLineParams.setOrderedUOM("Each");
          createLineParams.setOrderedQuantity(orderQuantity);
          /* The extension will automatically use line.createNewLine to add the order line that has the free item.
             This order line will have a price of 0 and you can't update it.
             If you want to add an independent line that's priced and that you can update, then use header.createNewLine instead of line.createNewLine.
             */
          fline = line.createNewLine(createLineParams);
          // Use this code line to debug this extension:
          debug("Free " + fline.getAttribute("LineNumber"));
        }
    }
}

Get Manual Price Adjustments from Order Lines

Iimport oracle.apps.scm.doo.common.extensions.ValidationException;
import oracle.apps.scm.doo.common.extensions.Message;

if (!"PMC TEST".equals(header.getAttribute("CustomerPONumber"))) return;

List < Message > messages = new ArrayList < Message > ();

def lines = header.getAttribute("Lines");
while (lines.hasNext()) {
    def line = lines.next();
    def MPAS = line.getAttribute("ManualPriceAdjustments");

    while (MPAS.hasNext()) {
        def mpa = MPAS.next();
        messages.add(new Message(Message.MessageType.ERROR, "AdjustmentElementBasis is " + mpa.getAttribute("AdjustmentElementBasis")));
        messages.add(new Message(Message.MessageType.ERROR, "AdjustmentTypeCode is " + mpa.getAttribute("AdjustmentTypeCode")));
        messages.add(new Message(Message.MessageType.ERROR, "ChargeDefinitionCode is " + mpa.getAttribute("ChargeDefinitionCode")));
        messages.add(new Message(Message.MessageType.ERROR, "ChargeRollupFlag is " + mpa.getAttribute("ChargeRollupFlag")));


        messages.add(new Message(Message.MessageType.ERROR, "Comments is " + mpa.getAttribute("Comments")));
        messages.add(new Message(Message.MessageType.ERROR, "ManualPriceAdjustmentId is " + mpa.getAttribute("ManualPriceAdjustmentId")));

        messages.add(new Message(Message.MessageType.ERROR, "ParentEntityCode is " + mpa.getAttribute("ParentEntityCode")));

        messages.add(new Message(Message.MessageType.ERROR, "ParentEntityId is " + mpa.getAttribute("ParentEntityId")));


        messages.add(new Message(Message.MessageType.ERROR, "PricePeriodicityCode is " + mpa.getAttribute("PricePeriodicityCode")));
        messages.add(new Message(Message.MessageType.ERROR, "ReasonCode is " + mpa.getAttribute("ReasonCode")));
        messages.add(new Message(Message.MessageType.ERROR, "SequenceNumber is " + mpa.getAttribute("SequenceNumber")));

        messages.add(new Message(Message.MessageType.ERROR, "SourceManualPriceAdjustmentIdentifier is " + mpa.getAttribute("SourceManualPriceAdjustmentIdentifier")));
        messages.add(new Message(Message.MessageType.ERROR, "ValidationStatusCode is " + mpa.getAttribute("ValidationStatusCode")));

        messages.add(new Message(Message.MessageType.ERROR, "ChargeDefinition is " + mpa.getAttribute("ChargeDefinition")));
        messages.add(new Message(Message.MessageType.ERROR, "AdjustmentType is " + mpa.getAttribute("AdjustmentType")));
        messages.add(new Message(Message.MessageType.ERROR, "AdjustmentElementBasisCode is " + mpa.getAttribute("AdjustmentElementBasisCode")));

    }
}

ValidationException ex = new ValidationException(messages);
throw ex;

Get Fulfillment Line Attributes

import oracle.apps.scm.doo.common.extensions.ValidationException;
import oracle.apps.scm.doo.common.extensions.Message;

if (!"PMC TEST".equals(header.getAttribute("CustomerPONumber"))) return;

List < Message > messages = new ArrayList < Message > ();

def lines = header.getAttribute("Lines");
while (lines.hasNext()) {
    def line = lines.next();
    def flinedetails = line.getAttribute("FulfillLineDetails");
    while (flinedetails.hasNext()) {
        def flinedetail = flinedetails.next();
        messages.add(new Message(Message.MessageType.ERROR, "ActualDeliveryDate is " + flinedetail.getAttribute("ActualDeliveryDate")));


        messages.add(new Message(Message.MessageType.ERROR, "AvailabilityShipDate is " + flinedetail.getAttribute("AvailabilityShipDate")));
        messages.add(new Message(Message.MessageType.ERROR, "BillOfLadingNumber is " + flinedetail.getAttribute("BillOfLadingNumber")));
        messages.add(new Message(Message.MessageType.ERROR, "BillingTransactionNumber is " + flinedetail.getAttribute("BillingTransactionNumber")));
        messages.add(new Message(Message.MessageType.ERROR, "DeliveryName is " + flinedetail.getAttribute("DeliveryName")));
        messages.add(new Message(Message.MessageType.ERROR, "ExceptionFlag is " + flinedetail.getAttribute("ExceptionFlag")));

        messages.add(new Message(Message.MessageType.ERROR, "Category is " + flinedetail.getAttribute("Category")));
        messages.add(new Message(Message.MessageType.ERROR, "CreatedBy is " + flinedetail.getAttribute("CreatedBy")));
        messages.add(new Message(Message.MessageType.ERROR, "CreationDate is " + flinedetail.getAttribute("CreationDate")));
        messages.add(new Message(Message.MessageType.ERROR, "CustomerTrxLineId is " + flinedetail.getAttribute("CustomerTrxLineId")));



        messages.add(new Message(Message.MessageType.ERROR, "FulfillLineDetailId is " + flinedetail.getAttribute("FulfillLineDetailId")));
        messages.add(new Message(Message.MessageType.ERROR, "FulfillLineId is " + flinedetail.getAttribute("FulfillLineId")));
        messages.add(new Message(Message.MessageType.ERROR, "LastUpdateDate is " + flinedetail.getAttribute("LastUpdateDate")));
        messages.add(new Message(Message.MessageType.ERROR, "LastUpdateLogin is " + flinedetail.getAttribute("LastUpdateLogin")));
        messages.add(new Message(Message.MessageType.ERROR, "LastUpdatedBy is " + flinedetail.getAttribute("LastUpdatedBy")));


        messages.add(new Message(Message.MessageType.ERROR, "ObjectVersionNumber is " + flinedetail.getAttribute("ObjectVersionNumber")));
        messages.add(new Message(Message.MessageType.ERROR, "Quantity is " + flinedetail.getAttribute("Quantity")));
        messages.add(new Message(Message.MessageType.ERROR, "RmaReceiptDate is " + flinedetail.getAttribute("RmaReceiptDate")));
        messages.add(new Message(Message.MessageType.ERROR, "RmaReceiptLineNumber is " + flinedetail.getAttribute("RmaReceiptLineNumber")));
        messages.add(new Message(Message.MessageType.ERROR, "RmaReceiptNumber is " + flinedetail.getAttribute("RmaReceiptNumber")));
        messages.add(new Message(Message.MessageType.ERROR, "RmaReceiptTransactionId is " + flinedetail.getAttribute("RmaReceiptTransactionId")));
        messages.add(new Message(Message.MessageType.ERROR, "Status is " + flinedetail.getAttribute("Status")));
        messages.add(new Message(Message.MessageType.ERROR, "StatusAsofDate is " + flinedetail.getAttribute("StatusAsofDate")));


        messages.add(new Message(Message.MessageType.ERROR, "TaskType is " + flinedetail.getAttribute("TaskType")));
        messages.add(new Message(Message.MessageType.ERROR, "TrackingNumber is " + flinedetail.getAttribute("TrackingNumber")));
        messages.add(new Message(Message.MessageType.ERROR, "TradeComplianceCode is " + flinedetail.getAttribute("TradeComplianceCode")));
        messages.add(new Message(Message.MessageType.ERROR, "TradeComplianceExplanation is " + flinedetail.getAttribute("TradeComplianceExplanation")));
        messages.add(new Message(Message.MessageType.ERROR, "TradeComplianceResultCode is " + flinedetail.getAttribute("TradeComplianceResultCode")));
        messages.add(new Message(Message.MessageType.ERROR, "TradeComplianceTypeCode is " + flinedetail.getAttribute("TradeComplianceTypeCode")));

        messages.add(new Message(Message.MessageType.ERROR, "WaybillNumber is " + flinedetail.getAttribute("WaybillNumber")));
        messages.add(new Message(Message.MessageType.ERROR, "TradeComplianceName is " + flinedetail.getAttribute("TradeComplianceName")));
        messages.add(new Message(Message.MessageType.ERROR, "TradeComplianceCode is " + flinedetail.getAttribute("TradeComplianceCode")));
        messages.add(new Message(Message.MessageType.ERROR, "TradeComplianceResultName is " + flinedetail.getAttribute("TradeComplianceResultName")));
        messages.add(new Message(Message.MessageType.ERROR, "TradeComplianceTypeName is " + flinedetail.getAttribute("TradeComplianceTypeName")));


    }

}

ValidationException ex = new ValidationException(messages);
throw ex;

Prevent Updates on Order Lines

Prevent Order Management from updating order lines that it has fulfilled, canceled, closed, backordered, or split. This extension doesn't prevent updates to lines that Order Management has canceled.

import oracle.apps.scm.doo.common.extensions.ValidationException;  
import oracle.apps.scm.doo.common.extensions.Message;
 
/*
def poNumber = header.getAttribute("OrderNumber");
if (poNumber == null || !poNumber.equals("520956"))
return;
*/
def reference = header.getAttribute("ReferenceHeaderId");
 
if(reference != null){
  def lines = header.getAttribute("Lines");
 
  if (!lines.hasNext()){
      throw new ValidationException("We need more time to process the order.");
  }
 
  Set<Long> splitFlinesSet = null;
  def vo = context.getViewObject("oracle.apps.scm.doo.processOrder.publicModel.partyMerge.view.FulfillLinePVO");
  def vc1 = vo.createViewCriteria();
  def vcrow1 = vc1.createViewCriteriaRow();
  vcrow1.setAttribute("HeaderId", header.getAttribute("HeaderId"));
  vcrow1.setAttribute("FulfillLineNumber", " > 1 ");
  vcrow1.setAttribute("FulfillmentSplitRefId", " is not null ");
  vcrow1.setAttribute("FulfilledQty", " is null ");
  rowset1 = vo.findByViewCriteria(vc1, -1);
 
  rowset1.reset();
  while (rowset1.hasNext()) {
    if (splitFlinesSet == null) {
      splitFlinesSet = new TreeSet<Long>();
    }
    def line1 = rowset1.next();
    splitFlinesSet.add(line1.getAttribute("FulfillLineId"));
  }
 
  if (splitFlinesSet == null) {
    return;
  }
 
  while (lines.hasNext()) {
    def line = lines.next();
    Long fLineId = line.getAttribute("FulfillmentLineIdentifier");
    if (!(splitFlinesSet.contains(fLineId))) {
      continue;
    }
    if('Y'.equals(line.getAttribute("ModifiedFlag")) && line.getAttribute("ReferenceFulfillmentLineIdentifier") != null && !(0 == line.getAttribute("OrderedQuantity")) ){
      throw new ValidationException("Backordered Split line can't be updated. DisplayLineNumber: " + line.getAttribute("DisplayLineNumber"));
    }
  }
}

Prevent Updates on Order Lines That Are on Backorder

import oracle.apps.scm.doo.common.extensions.ValidationException;
import oracle.apps.scm.doo.common.extensions.Message;
 
String orderType = header.getAttribute("TransactionTypeCode");
def excludeStatuses = ["CANCELED", "CLOSED", "PARTIAL_CLOSE"] as Set;
def forOrderTypes = ["DOMESTIC", "EXPORT", "DOMESTICPPD", "CONSIGN", "EXPORTC", "EXPORTD", "EXPORTF", "HWIPARTNER", "HWIPARTNERC", "HWIPARTNERD", "HWIPARTNERF", "RETURN", "VAS"] as Set;
 
if (orderType == null) return;
if (!forOrderTypes.contains(orderType)) return;
 
def lines = header.getAttribute("Lines");
while (lines.hasNext()) {
 def line = lines.next();
  
 Long lineId = line.getAttribute("LineId");
 boolean backUpdateFlag = readFlineStatus(lineId);
 
 if (backUpdateFlag) //if not back order line
 {
  if (!excludeStatuses.contains(line.getAttribute("StatusCode"))) {
 
   def BillingTransactionTypeId_Current = line.getAttribute("BillingTransactionTypeIdentifier");
   def BillingTransactionTypeId_New = line.getAttribute("BillingTransactionTypeIdentifier");
 
   if (orderType.equals("DOMESTIC")) {
    BillingTransactionTypeId_New = 300000034980382;
   }
   if (orderType.equals("EXPORT")) {
    BillingTransactionTypeId_New = 300000034980386;
   }
   if (orderType.equals("DOMESTICPPD")) {
    BillingTransactionTypeId_New = 300000039619347;
   }
   if (orderType.equals("CONSIGN")) {
    BillingTransactionTypeId_New = 300000034980380;
   }
   if (orderType.equals("EXPORTC")) {
    BillingTransactionTypeId_New = 300000034988180;
   }
   if (orderType.equals("EXPORTD")) {
    BillingTransactionTypeId_New = 300000034988182;
   }
   if (orderType.equals("EXPORTF")) {
    BillingTransactionTypeId_New = 300000034989759;
   }
   if (orderType.equals("HWIPARTNER")) {
    BillingTransactionTypeId_New = 300000084209774;
   }
   if (orderType.equals("HWIPARTNERC")) {
    BillingTransactionTypeId_New = 300000036925861;
   }
   if (orderType.equals("HWIPARTNERD")) {
    BillingTransactionTypeId_New = 300000036925863;
   }
   if (orderType.equals("HWIPARTNERF")) {
    BillingTransactionTypeId_New = 300000036925870;
   }
   if (orderType.equals("RETURN")) {
    BillingTransactionTypeId_New = 300000034980378;
   }
   if (orderType.equals("VAS")) {
    BillingTransactionTypeId_New = 300000034980370;
   }
 
   if (BillingTransactionTypeId_Current != BillingTransactionTypeId_New) {
    line.setAttribute("BillingTransactionTypeIdentifier", BillingTransactionTypeId_New);
   }
  }//Condition skipping lines of particular status codes
 }//Back order line check condition
}
 
/*Method that determines whether the line is shipped or backordered. If the line shipped, the method returns true. If the line is backordered, the method returns false.

*/
def readFlineStatus(Long lineId) {
 
 def lines = header.getAttribute("Lines");
 
 if (!lines.hasNext()) {
  throw new ValidationException("In readFlineStatus failing to read lines");
 }
 
 while (lines.hasNext()) {
 
  def line = lines.next();
  def eachLineId = line.getAttribute("LineId");
  def quantity = line.getAttribute("OrderedQuantity");
 
  if (lineId.equals(eachLineId)) {
 
   def flineDetails = line.getAttribute("FulfillLineDetails");
   if (!flineDetails.hasNext()) {
    continue;
   }
 
   while (flineDetails.hasNext()) {
    def eachFlineDetails = flineDetails.next();
    def status = eachFlineDetails.getAttribute("Status");
    if ("BACKORDERED".equals(status) || "SHIPPED".equals(status)) {
     return false;
    }
 
   }
  }
 }
 return true;
}

Skip Order Lines According to Status and Set the Requested Ship Date

Skip order lines that are in Fulfilled, Closed, or Canceled status, and set the Requested Ship Date on the order line to the same value that the RequestShipDate attribute contains on the order header.

import oracle.apps.scm.doo.common.extensions.ValidationException;
import oracle.apps.scm.doo.common.extensions.Message;
/* Exclude orchestration processes that you have set up where the statuses are equivalent to SHIPPED or FULFILLED.*/
Set excludeStatusesSet = ["CANCELED", "CLOSED", "SHIPPED", "BACKORDERED", "AWAIT_BILLING", "BILLED" ];
/*
def poNumber = header.getAttribute("CustomerPONumber");
if (poNumber == null || !poNumber.equals("CSR_2720"))
return;
*/
def requestedDate = header.getAttribute("RequestShipDate");
def lines = header.getAttribute("Lines");
while (lines.hasNext()) {
def line = lines.next();
def statusCode = line.getAttribute("StatusCode");
if (statusCode != null && excludeStatusesSet.contains(statusCode)) {
continue;
}
/*
def comments = line.getAttribute("Comments");
if (comments == null)
comments = "TEST:";
line.setAttribute("Comments", comments + header.getAttribute("ChangeVersionNumber"));
*/
/*set the RequestedShipDate attribute on the order line to the value of the requestedDate variable. requestedDate contains the value of the RequestShipDate order header attribute.
line.setAttribute("RequestedShipDate",requestedDate);
line.setAttribute("ScheduleShipDate",requestedDate);
}

Update the ModifiedFlag Attribute for Closed Order Lines

if(!header.getAttribute("OrderNumber").equals("100002054")) {
  return;
}
 
def lines = header.getAttribute("Lines");
while(lines.hasNext()) {
  def line = lines.next();
 
  if(line.getAttribute("ModifiedFlag").equals("Y") && line.getAttribute("StatusCode").equals("CLOSED")) {
    line.setAttribute("ModifiedFlag", "N");
  }
}

Manipulate Dates on Order Lines

Here's an example that illustrates how to include dates in your extension. This extension uses the On Save extension point.

import oracle.apps.scm.doo.common.extensions.ValidationException;
import oracle.apps.scm.doo.common.extensions.Message;
import java.sql.Date;
import java.sql.Timestamp;

if( !"SNDATE".equals( header.getAttribute("CustomerPONumber" ) ) ) return;
 
def pattern = "MM/dd/YYYY hh:mm:ss a";
def date = header.getAttribute("TransactionOn");
/* You can use these formats:
Letter  Date or Time          Type                   Example
G       Era designator        Text                   AD
y       Year                  Year                   1996; 96
Y       year                  Year                   2009; 09
M       Month in year         Month                  Jul
MMMM    Month in year         Month                  July
w       Week in year          Number                 27
W       Week in month         Number                 2
D       Day in year           Number                 189
d       Day in month          Number                 10
E       Day name in week      Text                   Tue
EEEE    Day name in week      Text                   Tuesday
u       Day number of week    Number                !1 (1 = Monday, ..., 7 = Sunday)    
a       Am/pm marker          Text                   PM
H       Hour in day (0-23)    Number                 0
k       Hour in day (1-24)    Number                 24
K       Hour in am/pm (0-11)  Number                 0
h       Hour in am/pm (1-12)  Number                 12
m       Minute in hour        Number                 30
s       Second in minute      Number                 55
S       Millisecond           Number                 978
z       Time zone             Text                   PST
zzzz    Time zone             Text                   Pacific Standard Time;
Z       Time zone             RFC 822 time zone      -0800
X       Time zone             ISO 8601 time zone     -08; -0800; -08:00
*/
 
debug( "Order Date "+ date.format(pattern));

def headerRSD = header.getAttribute("RequestShipDate");
 
def headerRSD_Time = headerRSD.getTime();
def vPSD = new java.sql.Date(headerRSD_Time - getTimeInMillis(2));
def vPAD = new java.sql.Date(headerRSD_Time + getTimeInMillis(7));

def lines = header.getAttribute("Lines");
while( lines.hasNext() ) {
  def line = lines.next();
  line.setAttribute("PromiseShipDate", vPSD);
  line.setAttribute("PromiseArrivalDate", vPAD);
}
  
public static long getTimeInMillis(long days) {
  return days * 24 * 60 * 60 * 1000;
}

 
void debug(String msg) {
    String text = header.getAttribute("ShippingInstructions");
    header.setAttribute("ShippingInstructions", text + ". " + msg);
}

Remove the System Date from the Contract Start Date on the Order Line

Order Management sets the Contract Start Date attribute to the system date when you copy a sales order. Use this extension to remove the system date from the Contract Start Date.

def lines = header.getAttribute("Lines");
 
while( lines.hasNext() ) {
   def line = lines.next();
   def VARTotalContractAmount = line.getAttribute("TotalContractAmount");
   def refFlineId=line.getAttribute("ReferenceFulfillmentLineIdentifier");
   if( VARTotalContractAmount == null && refFlineId==null) {
      line.setAttribute("ContractStartDate1",null);
   }
 
}

Set the Default Value for the Unit of Measure on the Order Line

import oracle.apps.scm.doo.common.extensions.ValidationException;
 
def poNumber = header.getAttribute("CustomerPONumber");;
def reference = header.getAttribute("ReferenceHeaderId");
def headerId = header.getAttribute("HeaderId");
def sourceOrderId = header.getAttribute("SourceTransactionIdentifier");
 
//If you use the Order Management work area to create the sales order, then don't run this extension.
if (headerId == sourceOrderId)
    return;
//If its an order revision, then don't run this extension. Remove this condition to run the extension for revisions.
if (reference != null)
    return;
 
def lines = header.getAttribute("Lines");
while (lines.hasNext()) {
    def line = lines.next();
    def inventoryItemId = line.getAttribute("ProductIdentifier");
    def orgId = line.getAttribute("InventoryOrganizationIdentifier");
    def parentFLineId = line.getAttribute("RootParentLineReference");
    if (parentFLineId != null) {
        def item = getItem(inventoryItemId, orgId);
        def uomCode = item.getAttribute("PrimaryUomCode");
        if (uomCode != null) {
            line.setAttribute("OrderedUOMCode", uomCode);
        }
    }
 
}
 
Object getItem(Long itemId, Long orgId) {
    def itemPVO = context.getViewObject("oracle.apps.scm.productModel.items.publicView.ItemPVO");
    def vc = itemPVO.createViewCriteria();
    def vcrow = vc.createViewCriteriaRow();
    vcrow.setAttribute("InventoryItemId", itemId);
    vcrow.setAttribute("OrganizationId", orgId);
    def rowset = itemPVO.findByViewCriteria(vc, -1);
    def item = rowset.first();
    return item;
}

Get the Rate for a Unit of Measure

import oracle.apps.scm.doo.common.extensions.ValidationException;
 
def serviceInvoker = context.getServiceInvoker();                                                      
 
String payLoad =  "<ns1:invUomConvert xmlns:ns1=\"http://xmlns.oracle.com/apps/scm/inventory/uom/uomPublicService/types/\">"+
            "<ns1:pInventoryItemId>141</ns1:pInventoryItemId>"+
            "<ns1:pFromQuantity>1</ns1:pFromQuantity>"+
            "<ns1:pFromUomCode>Ea</ns1:pFromUomCode>"+
            "<ns1:pToUomCode>Ea</ns1:pToUomCode>"+
            "<ns1:pFromUnitOfMeasure/>"+
            "<ns1:pToUnitOfMeasure/>"+
        "</ns1:invUomConvert>";
         
def responseBody = serviceInvoker.invokeSoapService("UOM_RATE", payLoad).getSoapBody().getTextContent();
//throw new ValidationException("response final_Uom_Rate : "+responseBody);

Identify Order Lines That You Partially Shipped

import oracle.apps.scm.doo.common.extensions.ValidationException;
import oracle.apps.scm.doo.common.extensions.Message;

String customerPONumber = header.getAttribute("CustomerPONumber");
if (customerPONumber != "SNPART") return;
List<Message> messages = new ArrayList<Message>();
// Get all of the sales order's order lines.
def Lines = header.getAttribute("Lines");
while (Lines.hasNext()) {
    def line = Lines.next();
    def flineID = line.getAttribute("FulfillmentLineIdentifier");
    debug("Fulfill Line Id " + flineID.toString());
    // Find out whether the FulfillmentSplitReferenceId attribute contains a value.
    def splitFrom = line.getAttribute("FulfillmentSplitReferenceId")
    if (splitFrom != null) {
       // Find out whether the order line is split because of a partial shipment.
       if (line.getAttribute("ShippedQuantity")== null) {
       //This is the open order line.
       debug("Line " + flineID + " is split from " + splitFrom);
      //Add your logic here.
       }
    }
}

void debug(String msg) {
    //messages.add(new Message(Message.MessageType.WARNING,msg));
    header.setAttribute("PackingInstructions", header.getAttribute("PackingInstructions") + "" + msg);
}

Cascade Values Between Order Lines in Configuration Models

This example cascades an attribute value from the top parent of a configuration model to all of that parent's child lines.

import oracle.apps.scm.doo.common.extensions.ValidationException;
 
def poNumber = header.getAttribute("CustomerPONumber");;
 
//Condition that specifies to call the extension.
if(poNumber != null && poNumber.equals("CASCADE_CONTRACT_SDATE")){
    def lines=header.getAttribute("Lines");
    long currentTime = new Date().getTime();
    def date = new java.sql.Date(currentTime);
 
    //Iteration all lines of the order
    while( lines.hasNext() ) {
        def line=lines.next();
 
        def inventoryItemId = line.getAttribute("ProductIdentifier");
        def orgId = line.getAttribute("InventoryOrganizationIdentifier");
        def parentLineReference=line.getAttribute("ParentLineReference");
        def rootParentLineReference=line.getAttribute("RootParentLineReference");
        def item = getItem(inventoryItemId, orgId); // Getting item details for the line
        def itemTypeCode=item.getAttribute("BomItemType");
        def pickComponentsFlag=item.getAttribute("PickComponentsFlag");
        def parentstartdate=line.getAttribute("ContractStartDate1");
        def flineId=line.getAttribute("FulfillmentLineIdentifier");
        //Passing root line for PTO ,Hybrid and ATO Items
        if(1==itemTypeCode  && flineId==rootParentLineReference && rootParentLineReference== parentLineReference && parentstartdate!=null){
            updateChildLines(line);
        }
        //Passing root line For KIT Items
        else if(4==itemTypeCode  && "Y".equals(pickComponentsFlag) && parentstartdate!=null){
            updateChildLines(line);
        }
    }
}
 
Object getItem(Long itemId, Long orgId) {
    def itemPVO = context.getViewObject("oracle.apps.scm.productModel.items.publicView.ItemPVO");
    def vc = itemPVO.createViewCriteria();
    def vcrow = vc.createViewCriteriaRow();
    vcrow.setAttribute("InventoryItemId", itemId); 
    vcrow.setAttribute("OrganizationId", orgId);
    def rowset = itemPVO.findByViewCriteria(vc, -1);
    def item = rowset.first();
    return item;
}
 
//Iterate through all lines. Set the child lines's contract start date and end date to the parent's contract start date and end date.
void updateChildLines(def rootfline){
    def lines=header.getAttribute("Lines");
    def flineId=rootfline.getAttribute("FulfillmentLineIdentifier");
    def parentstartdate=rootfline.getAttribute("ContractStartDate1");
    def parentenddate=rootfline.getAttribute("ContractEndDate1");
    while( lines.hasNext() ) {
        def line=lines.next();
        def rootFlineId=line.getAttribute("RootParentLineReference");
        if(flineId==rootFlineId){
            line.setAttribute("ContractStartDate1",parentstartdate);
            line.setAttribute("ContractEndDate1",parentenddate);
        }
    } 
}

Set the Fulfillment Organization and Shipping Instructions

If the item is shippable, then set the fulfillment organization for the order line and shipping instructions on the line to the default shipping organization that the item references.

import oracle.apps.scm.doo.common.extensions.ValidationException;
import oracle.apps.scm.doo.common.extensions.Message;

def poNumber = header.getAttribute("CustomerPONumber");

if (poNumber == null) return;

if (!poNumber.startsWith("DefaultShippingOrg")) return;

def lines = header.getAttribute("Lines");
while (lines.hasNext()) {
    def line = lines.next();
    def inventoryItemId = line.getAttribute("ProductIdentifier");
    def orgId = line.getAttribute("InventoryOrganizationIdentifier");
    def item = getItem(inventoryItemId, orgId);

    String shippable = item.getAttribute("ShippableItemFlag");

    if ("Y".equals(shippable)) {
        Long defaultOrgId = item.getAttribute("DefaultShippingOrg");

        //msg =   new Message(Message.MessageType.WARNING, "default: " + inventoryItemId + " - " + orgId + " - " + shippable+ " - " +  defaultOrgId);
        //throw new ValidationException(msg);

        line.setAttribute("FulfillmentOrganizationIdentifier", defaultOrgId);
        line.setAttribute("FulfillmentOrganizationIdentifier", 1234);
        line.setAttribute("ShippingInstructions", "Ship From Org :" + 999);
    }
}

Object getItem(Long itemId, Long orgId) {
    def itemPVO = context.getViewObject("oracle.apps.scm.productModel.items.publicView.ItemPVO");
    def vc = itemPVO.createViewCriteria();
    def vcrow = vc.createViewCriteriaRow();
    vcrow.setAttribute("InventoryItemId", itemId);
    vcrow.setAttribute("OrganizationId", orgId);
    vc.add(vcrow);

    def rowset = itemPVO.findByViewCriteriaWithBindVars(vc, -1, new String[0], new String[0]);
    def item = rowset.first();

    return item;

}

Add Packing Instruction for Hazardous Items

If the item is hazardous, then set the packing instructions on the order line.

def poNumber = header.getAttribute("CustomerPONumber");

if (poNumber == null) return;

if (!poNumber.startsWith("HazardousMaterial")) return;

def lines = header.getAttribute("Lines");
while (lines.hasNext()) {
    def line = lines.next();
    def inventoryItemId = line.getAttribute("ProductIdentifier");
    def orgId = line.getAttribute("InventoryOrganizationIdentifier");
    def item = getItem(inventoryItemId, orgId);

    String hazardous = item.getAttribute("HazardousMaterialFlag");

    if ("Y".equals(hazardous)) {
        //get row for fulfill line context PackShipInstruction
        line.setAttribute("PackingInstructions", "Hazardous Handling Required.");
    }
}

Object getItem(Long itemId, Long orgId) {
    def itemPVO = context.getViewObject("oracle.apps.scm.productModel.items.publicView.ItemPVO");
    def vc = itemPVO.createViewCriteria();
    def vcrow = vc.createViewCriteriaRow();
    vcrow.setAttribute("InventoryItemId", itemId);
    vcrow.setAttribute("OrganizationId", orgId);
    vc.add(vcrow);

    def rowset = itemPVO.findByViewCriteriaWithBindVars(vc, -1, new String[0], new String[0]);
    def item = rowset.first();

    return item;

}