December 2017 Defining Extensions That Modify Order Management Cloud Copyright © 2005, 2017 Oracle and/or its affiliates. All rights reserved. This software and related documentation are provided under a license agreement containing restrictions on use and disclosure and are protected by intellectual property laws. Except as expressly permitted in your license agreement or allowed by law, you may not use, copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform, publish, or display any part, in any form, or by any means. Reverse engineering, disassembly, or decompilation of this software, unless required by law for interoperability, is prohibited. The information contained herein is subject to change without notice and is not warranted to be error-free. If you find any errors, please report them to us in writing. If this is software or related documentation that is delivered to the U.S. Government or anyone licensing it on behalf of the U.S. Government, the following notice is applicable: U.S. GOVERNMENT END USERS: Oracle programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, delivered to U.S. Government end users are “commercial computer software” pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such, use, duplication, disclosure, modification, and adaptation of the programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, shall be subject to license terms and license restrictions applicable to the programs. No other rights are granted to the U.S. Government. This software or hardware is developed for general use in a variety of information management applications. It is not developed or intended for use in any inherently dangerous applications, including applications that may create a risk of personal injury. If you use this software or hardware in dangerous applications, then you shall be responsible to take all appropriate fail-safe, backup, redundancy, and other measures to ensure its safe use. Oracle Corporation and its affiliates disclaim any liability for any damages caused by use of this software or hardware in dangerous applications. Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners. Intel and Intel Xeon are trademarks or registered trademarks of Intel Corporation. All SPARC trademarks are used under license and are trademarks or registered trademarks of SPARC International, Inc. AMD, Opteron, the AMD logo, and the AMD Opteron logo are trademarks or registered trademarks of Advanced Micro Devices. UNIX is a registered trademark of The Open Group. This software or hardware and documentation may provide access to or information on content, products, and services from third parties. Oracle Corporation and its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect to third-party content, products, and services. Oracle Corporation and its affiliates will not be responsible for any loss, costs, or damages incurred due to your access to or use of third-party content, products, or services. Documentation Accessibility For information about Oracle's commitment to accessibility, visit the Oracle Accessibility Program website at http://www.oracle.com/pls/topic/lookup?ctx=acc&id=docacc. Access to Oracle Support Oracle customers have access to electronic support through My Oracle Support. For details, visit http://www.oracle.com/pls/topic/lookup? ctx=acc&id=info or visit http://www.oracle.com/pls/topic/lookup?ctx=acc&id=trs if you are hearing impaired. Contents 1 Managing Order Management Extensions................................................................................5 Overview.............................................................................................................................................5 Example Actions That Order Management Extensions Can Perform........................................6 Parts of an Order Management Extension..........................................................................................6 2 Points Where You Can Run Order Management Extensions....................................................8 Extension Point Behavior...................................................................................................................9 On Save........................................................................................................................................9 On Start of Submission Request................................................................................................10 On End of Submission Request.................................................................................................10 3 Guidelines for Coding Order Management Extensions..........................................................10 Use Implicit Variables......................................................................................................................11 Reference Sales Order Entities.........................................................................................................11 Navigate Row Sets............................................................................................................................12 Navigate Row Sets of Grandchild Entities................................................................................13 Validate Your Code..........................................................................................................................14 4 Calling Web Services from Order Management Extensions...................................................14 1. Set Up the Call.......................................................................................................................15 2. Call the Web Service.............................................................................................................16 3. Determine Item of Interest.....................................................................................................17 5 Using Order Management Extensions to Access Data Outside of Order Management Cloud............................................................................................................................................18 Using View Criteria Objects to Filter Results..................................................................................19 Example of Filtering Results.....................................................................................................19 6 Managing Messages and Errors When Using Order Management Extensions.......................22 Example of Creating Validation Exceptions....................................................................................22 Hard-coding the Message..........................................................................................................24 Referencing Request Functions.................................................................................................24 Raising Multiple Validation Messages............................................................................................24 Writing Messages to Order Management Logs...............................................................................26 Example of Writing Messages to Order Management Logs.....................................................26 7 Applied Examples..................................................................................................................29 Using Order Management Extensions to Update the Order Submit Date: Worked Example.........29 Defining Extensions That Modify Order Management Cloud 3 Test Your Work.........................................................................................................................30 Using Order Management Extensions to Validate Relationships Between Attributes: Worked Example............................................................................................................................................31 Test Your Work.........................................................................................................................33 Using Order Management Extensions to Verify Data That Users Enter: Worked Example..........34 8 Methods You Can Use with Order Management Extensions: Reference................................35 Execution Context Method...............................................................................................................35 Logger Method.................................................................................................................................36 Message Method...............................................................................................................................36 Specifying Message Name and Tokens....................................................................................36 Creating Messages for Sales Orders and Sales Order Lines.....................................................37 Row Set Iterator Method..................................................................................................................37 Service Invoker Method...................................................................................................................38 Validation Exception Method...........................................................................................................38 Displaying Messages from the Message Repository................................................................38 Displaying Message Objects from the Message Repository.....................................................39 Referencing Lookup Codes.......................................................................................................39 View Object Method........................................................................................................................41 Creating View Criterion............................................................................................................41 Finding Rows According to View Criterion.............................................................................41 9 Attributes You Can Use With Order Management Extensions: Reference.............................42 Sales Order Entities That Extensions Can Access...........................................................................42 List of Attributes...............................................................................................................................43 Defining Extensions That Modify Order Management Cloud 4 1 Managing Order Management Extensions Overview Starting in Release 11.13.17.05.0 (Release 13, Update 17B) of Order Management Cloud, you can use the Manage Extensions page in the Setup and Maintenance work area to write your own Groovy script that modifies your Order Management deployment, and to specify the extension point that determines when to run this script. An order management extension is a Groovy script you write that meets your specific business requirements. An extension point is an event that you specify to determine when to run this script. You can use a flexfield to modify the data model, or Page Composer to modify the user interface, but you cannot use them to programmatically modify logic or modify your order management deployment. Instead, you can use an order management extension. The following Groovy script is an example of an order management extension named Update Order Submit Date. It uses the _H1AttributeDateTime attribute so it can set the value of an extensible flexfield to the date and time when Order Management submitted the sales order. Business Requirements That an Order Management Extension Can Meet You can create an order management extension that meets the following business requirements. Defining Extensions That Modify Order Management Cloud 5 Table 1. Business Requirements That Order Management Extensions Can Meet Example Business Requirement Description Use an order management extension to get data from the following sources: Use the getAttr method to get data from Order Management. Get data Use a public view object (PVO) to access data from some other Oracle Fusion product. A public view object is a data object that Order Management gets from some other Fusion solution. For example, you can use a public view object to look up an item category in Oracle Fusion Product Information Management or a purchase order in Oracle Fusion Purchasing. Use a web service to get data from a source that resides outside of Order Management Cloud. Implement your own logic Use the Groovy programming language to write your own logic when you code your extension. Your code can validate a sales order. If validation fails, then your code can also stop the flow and create a message. For details about Groovy, see The Groovy Programming Language website at www.groovy-lang.org. Raise error messages and warnings Use an extension to raise an error message or warning. Set the default value for sales order attributes or extensible flexifields Use Groovy to write your own logic that sets default values. Example Actions That an Order Management Extension Can Perform The following are some examples of actions that an order management extension can perform. Table 2. Example Actions That Order Management Extensions Can Perform Action Description Submit a sales order The following are examples of order management extensions: Reassign the warehouse for pick-to-order. You define an item that determines whether the sales order references a pick-to-order or a hardware model. Stop support lines that reference an incorrect accounting rule. You can define item entities and accounting rule entities. Make sure only one contract is Active or Signed for a booking. You can define entities for the installed base, contracts, or order Defining Extensions That Modify Order Management Cloud 6 ▪ Using Order Management Extensions to Access Data Outside of Order Management Using View Criteria Objects to Filter Results Action Description management. Assign a sales representative. You can define sales compensation rules. Update the accounting rule for a model for included items. Update the quote status for each sales order from a storefront that a third-party partner maintains. Write a validation on an imported source order that rejects the import or prevents the Order Entry Specialist from saving the order without fixing the problem. Save or validate a sales order Parts of an Order Management Extension Each order management extension can contain the following parts. Table 3. Parts of an Order Management Extension Part Description Function A Groovy function, similar to a Java function, such as getAttr. You can use a function only in the extension where you define it. You cannot define a function in one extension, and then use it in another extension. Attribute The attribute of a sales order, such as ShippingInstructions. The name of a web service. Note the following points: Web Service Message Your extension code can only call a web service that you define on the Manage Web Service Definitions page. You must manually create the Request payload in your code. Your code must parse and interpret the Response payload. You must write your code so that it works only for a synchronous interaction. You cannot write code for an asynchronous interaction. A message that you send to Order Management and that can display in the Order Management work area. Note the following points: An extension can log an error or warning message in the messaging framework. Order Management logs each message in a log file as part of order import or when a web service rejects a sales order. An error message stops the flow and rejects the save or submit action. A warning allows the flow to continue. If you use a warning at the beginning of a submission request, then Order Management displays the Defining Extensions That Modify Order Management Cloud 7 Using Order Management Extensions to Access Data Outside of Order Management ▪ Using View Criteria Objects to Filter Results Part Description warning message to the Order Entry Specialist, and then continues to process the sales order in order fulfillment. 2 You can use the Manage Messages page to define messages and tokens. You can use tokens to insert dynamic content into each message. You can modify the DOO_MSG_REQUEST_FUNCTION lookup to categorize the errors that Order Management displays to the Order Entry Specialist and to improve searching for these errors. Points Where You Can Run Order Management Extensions The following diagram illustrates the extension points where you can run an order management extension. Perform Action on Sales Order Implicit Save 1 2 Click Submit Start On Save Save Sales Order On Start of Submission Request Lock Sales Order Import Source Order 6 5 Fulfill Sales Order 4 On End of Submission Request 3 Process Submission Request Legend Stop Extension Point Explanation of Callouts You can run an extension at an extension point when creating a sales order: 1. Something occurs that triggers the On Save event: 8 An Order Entry Specialist performs an action in Order Management that causes one of the following implicit saves to occur: Defining Extensions That Modify Order Management Cloud ▪ Using Order Management Extensions to Access Data Outside of Order Management Using View Criteria Objects to Filter Results Validate Save Save and Close Validate Reprice Submit Copy Order Create Revision Create Return Order Management Cloud imports a source order from a source system, and then processes it, such as creating cross-references, defaulting values, and so on. 2. You can create an extension that runs on the On Save event. 3. You can create an extension that runs on the On Start of Submission Request extension point. If the extension results in failure, then Order Management sets the sales order status to Draft, with errors. 4. Order Management processes the submission request, including running validations, performing a credit check, communicating with Global Trade Management, and so on. 5. You can create an extension that runs on the On End of Submission Request extension point. If the extension results in: Failure. Order Management sets the sales order status to Draft, with errors. Warning. Order Management displays a warning message, successfully submits the sales order, and continues to process it through order fulfillment. The Order Entry Specialist can examine the warning messages on the submitted order. 6. The fulfillment system fulfills the sales order, including shipping, invoicing, and so on. You cannot run an extension during order fulfillment. Extension Point Behavior This section describes the behavior of each extension point. On Save If an order management extension that runs during On Save raises a validation failure, then Order Management stops running the extension and moves control to the next extension that you specify to run during On Save. If the validation failure includes at least one error message, and if Order Management has already run each of the On Save extensions, then it aborts the save for the sales order. Order Management handles each message that the extension raises differently depending on how it is saving the sales order: An Order Entry Specialist is saving a sales order in the Order Management work area. Order Management displays the message in a dialog. This user must correct the validation error and attempt to save the sales order again. A service is saving a source order during order import. Order Management returns the message in a response. The channel that is importing the source order must fix it, and then import it again. Defining Extensions That Modify Order Management Cloud 9 Using Order Management Extensions to Access Data Outside of Order Management ▪ Using View Criteria Objects to Filter Results Order Management does not save the message in the messaging framework because it might not have saved the sales order and the change that caused the validation to fail. On Start of Submission Request Note the following points for an extension that you define to run on the On Start of Submission Request extension point: Order Management calls the extension when the extension point occurs. It is the first operation that Order Management performs when it validates the submit. An extension can modify values on each writable order attribute, including header attributes and order line attributes, flexfield attributes, and attachment attributes. For details, see Attributes You Can Use With Order Management Extensions. Order Management runs the extension before it validates the submit or applies constraints. If an extension raises a validation failure, then Order Management stops running the extension and moves control to the next extension that you specify to run during On Start of Submission Request. If the validation failure includes at least one error message, then Order Management aborts the submit for the sales order, returns the order status to Draft, and then logs the error and warning messages. If the Order Entry Specialist is saving a sales order in the Order Management work area, and if the validation failure includes at least one error message, then Order Management displays a dialog that includes the message. If all messages are warnings, then Order Management submits the sales order to order fulfillment and does not display a dialog in the Order Management work area. The user can view the warning message after Order Management submits the sales order to order fulfillment. On End of Submission Request Note the following points for an extension that you define to run on the On End of Submission Request extension point: Order Management calls the extension when the extension point occurs. It makes this call as the last step before it sends the sales order to order fulfillment. The extension can modify values only on header flexfields and fulfillment line flexfields. If the extension attempts to modify any other attribute, then Order Management logs a runtime error and aborts all extensions that it is running for this extension point. 3 Guidelines for Coding Order Management Extensions This topic describes guidelines that can help you code an order management extension. Use Implicit Variables You can use the following implicit variables with each extension. You do not need to define them. Table 4. Implicit Variables Implicit Variable 10 Description Defining Extensions That Modify Order Management Cloud ▪ Using Order Management Extensions to Access Data Outside of Order Management Using View Criteria Objects to Filter Results Implicit Variable Description Context object that allows each extension to access context information, such as the name of the extension that is running, the event code, and so on. The context object also provides access to utility and helper methods, such as logging. Context You use the format: context extension name For example: context Update Order Submit Date Reference Sales Order Entities You can use the implicit header variable to access each order entity. Order Management exposes each entity as a generic row object. Each extension can reference only get methods or set methods. Table 5. Referencing Sales Order Entities Action Format Read an attribute value. getAttribute("attributeName") Write to an attribute. setAttribute("attributeName", attributeValue) Consider the following examples. Table 6. Referencing Sales Order Entities, Examples Code Description def soldToPartyName = header.getAttribute("BuyingPartyName"); Get the value of the BuyingPartyName attribute. header.setAttribute("ShippingInstructions", "Please use only next-day air."); Set the value of the ShippingInstructions attribute to Please use only next-day air. def lines = header.getAttribute("Lines"); Return a set of lines. You can iterate over the iterator to access individual lines. Defining Extensions That Modify Order Management Cloud 11 Using Order Management Extensions to Access Data Outside of Order Management ▪ Using View Criteria Objects to Filter Results Defining Variable Type in Groovy Groovy is a dynamic language and does not require that you define the type for each variable. For example, you can define soldToPartyName and Lines each as a variable without a type. As an option, you can specify a type, if necessary. For example, you can define soldToPartyName as type String. You can access each child entity as an attribute. For example: header.getAttribute("Lines"), header.getAttribute("SalesCredits") Navigate Row Sets Order Management returns each child entity as a set of rows. The following example illustrates how you can use while next to access each row from the set. Table 7. Navigating Row Sets Code Description def lines = header.getAttribute("Lines"); Call a method on the header to access the row set iterator for the order lines. while( lines.hasNext() ) { Determine whether the lines row set includes a next row, and loop until the row set does not contain any more rows. def line = lines.next(); Get the next line row. def itemNumber = line.getAttribute("ProductNumber"); Get the value of the ProductNumber attribute on the current line and assign the value to the itemNumber variable. def quantity = line.getAttribute("OrderedQuantity"); } Get the value of the ordered quantity. def salesCredits = header.getAttribute("SalesCredits"); Access the SalesCredits child entities of the sales order header. Here is the same code without comments. 1. 2. 3. 4. 5. 6. 7. def lines = header.getAttribute("Lines"); while( lines.hasNext() ) { def line = lines.next(); def itemNumber = line.getAttribute("ProductNumber"); def quantity = line.getAttribute("OrderedQuantity"); } def salesCredits = header.getAttribute("SalesCredits"); Navigate Row Sets of Grandchild Entities You can access a grandchild entity. The following example extension does the following work: 12 Defining Extensions That Modify Order Management Cloud ▪ Using Order Management Extensions to Access Data Outside of Order Management Using View Criteria Objects to Filter Results Accesses the Charge Component row of an order line Gets the order line Accesses the order charge rows below the order line Accesses the charge component rows from the order charge Table 8. Navigating Row Sets of Grandchild Entities Code Description def lines = header.getAttribute("Lines"); Call a method on the header to access the row set iterator for the order lines. while( lines.hasNext() ) { Determine whether the lines row set includes a next row, and loop until the row set does not contain any more rows. def line = lines.next(); Get the next line row. def charges = line.getAttribute("OrderCharges"); Get the row set for the order charges of the child entity. while( charges.hasNext() ) { Loop through the order charge rows. def charge = charges.next(); Get the next order charge from the row set. def chargeComps = charge.getAttribute("ChargeComponents"); Get the row set for the charge components of the child entity. while( chargeCompo.hasNext() ) { Loop through the charge components for the current charge. def chargeComp = chargeCompo.next(); Get the next charge component. def currency = chargeComp.getAttribute("ChargeCurrencyCode "); Get the value of the ChargeCurrencyCode attribute from the current charge component row. Here is the same code without comments. 1. def lines = header.getAttribute("Lines"); 8. while( lines.hasNext() ) { 9. def line = lines.next(); 10. def charges = line.getAttribute("OrderCharges"); 11. while( charges.hasNext() ) { 12. def charge = charges.next(); 13. def chargeComps = charge.getAttribute("ChargeComponents"); 14. while( chargeCompo.hasNext() ) { 15. def chargeComp = chargeCompo.next(); 16. def currency = chargeComp.getAttribute("ChargeCurrencyCode"); Defining Extensions That Modify Order Management Cloud 13 Using Order Management Extensions to Access Data Outside of Order Management ▪ Using View Criteria Objects to Filter Results 17. } 18. } 19. } Validate Your Code You can enter your code into the Definition area of the Edit Extensions page, and then click Validate to validate your design-time code. Order Management will make sure you correctly format your code, such as correct usage of parentheses, semicolons, and so on. If an error occurs at runtime, then Order Management handles the error in the same way that it handles any other error. It displays the cause of failure, extension name, and event name. It displays these details in the Order Management work area and in the log files. It can handle the following runtime errors: Reference to an attribute or method that is not valid Incorrect reference between the message name and a token Incorrect reference to a web service name 4 Calling Web Services from Order Management Extensions An Order Management Cloud implementation can get data from a source that resides outside of Order Management before it performs default logic or validation logic. You can reference the ServiceInvoker in your extension code to invoke a web service. ServiceInvoker is available from the context object. For details, see ExecutionContext Method and ExecutionContext Method. You must use the page named Manage External Interface Web Service Details to register any web service that your extension calls. You specify the connector name, a URL, and login credentials. For details, see the Integrating Order Management Cloud chapter of the Oracle SCM Cloud, Implementing Order Management guide on Oracle Help Center at http://docs-uat.us.oracle.com/cloud/latest. The example extension in this topic does the following work: Allocates sales credits to a salesperson for order lines that include an item that satisfies a condition. References the purchase order number and item number when it calls a web service so that it can get the name of the salesperson and the percent sales credit to allocate. Extracts the salesperson name and percent allocation from the web service response, and then creates a new row in the sales credit row set that it gets from the order line. Summary of the Work Call a web service from an order management extension: 1. Set up the call. 2. Call the web service. 3. Determine item of Interest. This topic includes example values. You might use different values, depending on your business requirements. 14 Defining Extensions That Modify Order Management Cloud ▪ Using Order Management Extensions to Access Data Outside of Order Management Using View Criteria Objects to Filter Results 1. Set Up the Call Use the following code to set up the call. Table 9. Example of Calling a Web Service, Set Up the Call Code Description def lines = header.getAttribute("Lines"); Get the row set for the order lines. while( lines.hasNext() ) Determine whether more lines exist that we must process. def line = lines.next(); def itemNumber = line.getAttribute("ProductNumber"); Get the item number that the line specifies. if( itemOfInterest(itemNumber) ) Determine whether the item number satisfies a condition. allocateSalesCredits(line); Call the method that allocates sales credits for this line. 2. Call the Web Service The following code calls the web service to get the sales credit allocation. It uses the following parameters: param line. Line where we will allocate the sales credit. param itemNumber. Number of the item that you specify on the line. Table 10. Example of Calling a Web Service, Call the Web Service Code Description void allocateSalesCredits(def line, String itemNumber) { def serviceInvoker = context.getServiceInvoker(); Get the handle that you use to call the web service. def poNumber = header.getAttribute("CustomerPONumber"); Get the value of the Purchase Order Number attribute for the customer from the order header. String payLoad = "<ns1:GetSalesCreditAllocation xmlns:ns1=\"http://www.your_company.com/Sal esCreditWS/\">" + "<ns1:poNumber>" + poNumber + "</ns1:poNumber>" + "<ns1:itemNumber>" + itemNumber + "</ns1:itemNumber>" + Concatenate the strings so you can prepare the payload. As an option, you can also use an XML API to concatenate the string. Defining Extensions That Modify Order Management Cloud 15 Using Order Management Extensions to Access Data Outside of Order Management ▪ Using View Criteria Objects to Filter Results Code Description "</ns1:GetSalesCreditAllocation>"; Use the interface name of the web service and the request payload to call the web service. def responseBody = serviceInvoker.invokeSoapService("SalesCredit AllocationService", payLoad).getSoapBody(); Note that you must specify the interface name in the Connector Name attribute on the Manage External Interface Web Service Details. For this example, you specify SalesCreditAllocationService as the Connector Name. def salesPerson = //; Extract the salesperson name from the response payload. def percent = // Extract the percent allocation from the response payload. def salesCredits = line.getAttribute("SalesCredits"); Get the row set for the sales credit from the current line. def salesCredit = salesCredits.createRow(); Create a sales credit row. sc.setAttribute("Salesperson", salesPerson); Set the value for the salesperson attribute. sc.setAttribute("Percent", new BigDecimal(percent)); Set the value for the percent allocation attribute. sc.setAttribute("SalesCreditTypeCode", 1L); Set the sales credit type. In this example, assume that 1 equals Revenue credits. salesCredits.insertRow(salesCredit); } Insert the new row in the row set. 3. Determine Item of Interest The following code returns a boolean value that indicates whether we are interested in the item that the web service sent. Table 11. Example of Calling a Web Service, Determine Item of Interest Code Description boolean itemOfInterest(String itemNumber) { For brevity, this example does not include details about how to implement this method. The logic you use is specific to your business requirements. if condition return true; 16 condition is code that you write. It that decides whether the item number is of interest. Defining Extensions That Modify Order Management Cloud ▪ Using Order Management Extensions to Access Data Outside of Order Management Using View Criteria Objects to Filter Results Code Description else return false } Code Without Comments Here is the entire code with no comments: 1. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 5 def lines = header.getAttribute("Lines"); while( lines.hasNext() ) { def line = lines.next(); def itemNumber = line.getAttribute("ProductNumber"); if( itemOfInterest(itemNumber) ) { allocateSalesCredits(line); } } void allocateSalesCredits(def line, String itemNumber) { def serviceInvoker = context.getServiceInvoker(); def poNumber = header.getAttribute("CustomerPONumber"); String payLoad = "<ns1:GetSalesCreditAllocation xmlns:ns1=\"http://www.acme.com/SalesCreditWS/\">" + "<ns1:poNumber>" + poNumber + "</ns1:poNumber>" + "<ns1:itemNumber>" + itemNumber + "</ns1:itemNumber>" + "</ns1:GetSalesCreditAllocation>"; def responseBody = serviceInvoker.invokeSoapService("SalesCreditAllocationService", payLoad).getSoapBody(); def salesPerson = //; def percent = // def salesCredits = line.getAttribute("SalesCredits"); def salesCredit = salesCredits.createRow(); sc.setAttribute("Salesperson", salesPerson); sc.setAttribute("Percent", new BigDecimal(percent)); sc.setAttribute("SalesCreditTypeCode", 1L); salesCredits.insertRow(salesCredit); } boolean itemOfInterest(String itemNumber) { if condition //pseudcode return true; else return false } Using Order Management Extensions to Access Data Outside of Order Management If you deploy into Oracle Fusion Cloud, then you cannot programmatically access the Oracle database. You cannot use PL, SQL, or JDBC to access data in other application tables. However, you can write an Defining Extensions That Modify Order Management Cloud 17 Using Order Management Extensions to Access Data Outside of Order Management ▪ Using View Criteria Objects to Filter Results order management extension that calls an API on the context object so that it queries the table and accesses the public view objects that the table contains. You must specify the complete definition name of the view object. The following example extension accesses a view object. Table 12. Example of Accessing Data from Other Oracle Fusion Entities Code Description Create an instance of the public view object for the item. def itemPVO = context.getViewObject("oracle.apps.scm.product Model.items.publicView.ItemPVO"); Note that this code uses each view object as a row iterator, so the methods on the RowIterator interface are also available on each view object. You can use the RowSetIterator Method to access a method that gets the rows that the view object query returns, and to navigate the row set for the view object. For details, see ViewObject Method. def item = itemPVO.first(); Access the first item. Using View Criteria Objects to Filter Results The example in Table 12 is only for demonstration purposes. It is too simplistic for practical use because it gets arbitrary items from the items table. It is more likely that you must query for an item or a set of items that match a criterion. To support SQL, your extension must provide a WHERE clause that only selects rows that match a criterion. You can use the ViewCriteria object for this purpose. An order management extension can create a view criteria object that adds filtering logic to the view object before it gets data from these objects. A view criteria object is a filter that you create and apply programmatically to a view object. Order Management converts each of these filters into a WHERE clause when your extension runs the query that you define in the view object. You use the view criteria row object to create a view criteria object. The view criteria object contains the attribute names and attribute values that become part of the WHERE clause. The following example does the following work: Creates a view criteria and uses it to query a view object. Queries the item master for an item according to the item Id and inventory organization Id. Examines the HazardousMaterialFlag attribute on the item. If the HazardousMaterialFlag attribute flags the item as hazardous, then the extension sets the flexfield context segment named Shipping Instruction to indicate that the item requires hazardous handling. This topic includes example values. You might use different values, depending on your business requirements. Use view criteria objects to filter results: 18 Defining Extensions That Modify Order Management Cloud ▪ Using Order Management Extensions to Access Data Outside of Order Management Using View Criteria Objects to Filter Results 1. Get the item. Use the following code to get the item. Table 13. Example of Filtering Results, Get the Item Code Description def lines = header.getAttribute("Lines"); Get the row set for the order lines. while( lines.hasNext() ) { Determine whether we must process more order lines. def line = lines.next(); Get the next line and assign it to the variable line. def inventoryItemId = line.getAttribute("ProductIdentifier"); Get the inventory item Id for the item from the order line that the Order Entry Specialist selected. def orgId = line.getAttribute("InventoryOrganizationIdentifi er"); Get the organization for the item from the order line that the Order Entry Specialist selected. def item = getItem(inventoryItemId, orgId); Get the item. Use the item Id and the organization Id to call the getItem method. String hazardous = item.getAttribute("HazardousMaterialFlag"); Get the HazardousMaterialFlag attribute from the item. if( "Y".equals(hazardous) ) { Determine whether HazardousMaterialFlag flags the item as hazardous. def packShipInstruction = line. getOrCreateContextRow("PackShipInstruction") ; Get the row for the extensible flexfield context named PackShipInstruction. packShipInstruction.setAttribute("_ShippingInst ruction", "Hazardous Handling Required."); Set the Shipping Instruction context segment. 2. Define the public view object. Use the following code to define the public view object. It uses the following parameters: param itemId. Inventory item Id that identifies the item. param orgId. Inventory organization Id that identifies the organization that owns of the item. Table 14. Example of Filtering Results, Defining the Public View Object Code Description Object getItem(Long itemId, Long orgId) { def itemPVO = context.getViewObject("oracle.apps.scm.product Create an instance of the public view object for the item. Defining Extensions That Modify Order Management Cloud 19 Using Order Management Extensions to Access Data Outside of Order Management ▪ Using View Criteria Objects to Filter Results Code Description Model.items.publicView.ItemPVO"); def vc = itemPVO.createViewCriteria(); Create the view criteria object. def vcrow = vc.createViewCriteriaRow(); Create the view criteria row. vcrow.setAttribute("InventoryItemId", itemId); Set the inventory item attribute so you can include it in the filter condition, and set the value that you will use to compare to this attribute. vcrow.setAttribute("OrganizationId", orgId); Set the organization attribute so you can include it in the filter condition, and set the value that you will use to compare to this attribute. def rowset = itemPVO.findByViewCriteria(vc, -1); Define the view criteria that filters the rows when you query the view object. def item = rowset.first(); Get the first item row that meets the condition. Code Without Comments Here is the entire code with no comments: 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) ) { def packShipInstruction = line. getOrCreateContextRow("PackShipInstruction"); packShipInstruction.setAttribute("_ShippingInstruction", "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); 20 Defining Extensions That Modify Order Management Cloud ▪ Using Order Management Extensions to Access Data Outside of Order Management Using View Criteria Objects to Filter Results vcrow.setAttribute("OrganizationId", orgId); def rowset = itemPVO.findByViewCriteria(vc, -1); def item = rowset.first(); return item; } 6 Managing Error Messages When Using Order Management Extensions An order management extension can raise a validation error to indicate that a sales order requires correction before Order Management can submit it to order fulfillment. To raise a validation error, Order Management creates a validation exception, stops running the extension that failed, and then runs any subsequent extensions for this extension point that you define. Order Management accumulates each message that it creates from validation exceptions for all the extensions that it runs during the extension point, and then displays them together to the Order Entry Specialist or, if it is a source order from a source system, then it returns them through a service call in the response to the caller. If Order Management creates a validation exception, then your extension code must send a message that describes the cause of the failure. You must do one of the following: Code the message text in your order management extension. You must specify Distributed Order Orchestration as the application for this message. Order Management will display this text in the Order Management work area without modification. Code your order management extension so that it sends the name of an Oracle Fusion message and the message parameters. Order Management will get the message from the Oracle Fusion message repository, populate any message tokens that the message references, display the message in the Order Management work area, and then add it to the message log. You can use the Manage Messages page to define a message. This topic frequently mentions ValidationException. For details, see ValidationException Method. Example of Creating Validation Exceptions The following example creates a validation exception. Table 15. Example of Creating an Instance of a Validation Exception Code Description import oracle.apps.scm.doo.common.extensions.Validat ionException; Import the ValidationException class. def salesCredits = header.getAttribute("SalesCredits"); Get the row set for the sales credits that the order header specifies. Defining Extensions That Modify Order Management Cloud 21 Using Order Management Extensions to Access Data Outside of Order Management ▪ Using View Criteria Objects to Filter Results Code Description while( salesCredits.hasNext() ) Determine whether more sales credit rows exist. def salesCredit = salesCredits.next(); Get the next sales credit row. if( "1".equals(salesCredit.getAttribute("SalesCre ditTypeCode")) ) Determine whether the sales credit is a revenue percent. def percent = salesCredit.getAttribute("Percent"); Get the percent allocation of the sales credit. if( percent < 30 ) { If percent is less than 30, then create a validation error. def tokens = [SALESPERSON: salesCredit.getAttribute("Salesperson"), PERCENT: percent]; Specify the token values to send to ValidationException. throw new ValidationException("SALES_CREDIT_TOO_ LOW_MSG", tokens); Create the exception, and then stop the execution. Here’s the same code without comments: 1. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. import oracle.apps.scm.doo.common.extensions.ValidationException; def salesCredits = header.getAttribute("SalesCredits"); while( salesCredits.hasNext() ) { def salesCredit = salesCredits.next(); if( "1".equals(salesCredit.getAttribute("SalesCreditTypeCode")) ) { def percent = salesCredit.getAttribute("Percent"); if( percent < 30 ) { def tokens = [SALESPERSON: salesCredit.getAttribute("Salesperson"), PERCENT: percent]; throw new ValidationException("SALES_CREDIT_TOO_LOW_MSG", tokens); } } } Hard-coding the Message The following variation creates a validation exception that uses hard-coded message text. You replace def tokens and throw new with the following code: String messageText = "Sales credit allocation of " + percent + "% for salesperson " + salesperson + " is less than the allowed minimum of 30"; throw new ValidationException(messageText); 22 Defining Extensions That Modify Order Management Cloud ▪ Using Order Management Extensions to Access Data Outside of Order Management Using View Criteria Objects to Filter Results Referencing Request Functions The following variation creates a validation exception that references a request function that you define instead of the default function that comes predefined with Order Management. You replace def tokens and throw new with the following code: def tokens = [SALESPERSON: salesCredit.getAttribute("Salesperson"), PERCENT: percent]; throw new ValidationException("ORA_CUSTOM_REQ_FUNCTION", "SALES_CREDIT_TOO_LOW_MSG", tokens); Raising Multiple Validation Messages You can define an order management extension that raises multiple error messages. In the example in Table 15, the extension stops running as soon as it finds one sales credit record that does not meet the requirement, and then reports the error. This extension code does not create or use a Message object but instead works directly against the ValidationException class. An extension can create one or more instances of a Message object before calling ValidationException. This capability allows you to report all sales credit rows that fail the requirement, and it provides more control in how you code your extension. The following example uses the Message object and provides detailed error reporting. It reports all sales credit rows that fail validation. Table 16. Example of Raising Multiple Validation Messages Code Description import oracle.apps.scm.doo.common.extensions.Validat ionException; Import the ValidationException class so you can construct a ValidationMessage object. import oracle.apps.scm.doo.common.extensions.Messag e; Import the Message class so you can construct a Message object. def salesCredits = header.getAttribute("SalesCredits"); Get the row set for the sales credits that the order header references. List<Message> msgs = new ArrayList<Message>(); Determine whether more sales credit rows exist that we must process. while( salesCredits.hasNext() ) def salesCredit = salesCredits.next(); Get the next sales credit row. if( "1".equals(salesCredit.getAttribute("SalesCre ditTypeCode")) ) { Determine whether the sales credit is a revenue percent. def percent = salesCredit.getAttribute("Percent"); Get the percent allocation of the sales credit. Defining Extensions That Modify Order Management Cloud 23 Using Order Management Extensions to Access Data Outside of Order Management ▪ Using View Criteria Objects to Filter Results Code Description if( percent < 30 ) { If percent is less than 30, then create a validation error. def tokens = [SALESPERSON: salesCredit.getAttribute("Salesperson"), PERCENT: percent]; Specify the token values to send to ValidationException. Message msg = new Message(Message.MessageType.ERROR, "SALES_CREDIT_TOO_LOW_MSG", tokens); Create a new message. msgs.add(msg); Accumulate each message in a list. if( !msgs.isEmpty() ) { If the msgs list is not empty, then at least one sales credit row is in error. throw new ValidationException(msgs); Create and throw ValidationException. Here’s the same code without comments: 1. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. import oracle.apps.scm.doo.common.extensions.ValidationException; import oracle.apps.scm.doo.common.extensions.Message; def salesCredits = header.getAttribute("SalesCredits"); List<Message> msgs = new ArrayList<Message>(); while( salesCredits.hasNext() ) { def salesCredit = salesCredits.next(); if( "1".equals(salesCredit.getAttribute("SalesCreditTypeCode")) ) { def percent = salesCredit.getAttribute("Percent"); if( percent < 30 ) { def tokens = [SALESPERSON: salesCredit.getAttribute("Salesperson"), PERCENT: percent]; Message msg = new Message(Message.MessageType.ERROR, "SALES_CREDIT_TOO_LOW_MSG", tokens); msgs.add(msg); } } } if( !msgs.isEmpty() ) { throw new ValidationException(msgs); } Writing Messages to Order Management Logs Your order management extension can write log messages to the same applications log file and use the same application settings that an Oracle Fusion application uses. To avoid degrading performance when logging, it is recommended that you apply the following rules when you write your extension: 24 Defining Extensions That Modify Order Management Cloud ▪ Using Order Management Extensions to Access Data Outside of Order Management Using View Criteria Objects to Filter Results Use the SEVERE logging level only for extremely important conditions, such as a read error condition. Logging all events as SEVERE will produce a large number of log messages and degrade performance. Use the FINEST logging level to get detailed reporting. It is recommended that you use FINEST for entry and exit logging. The Logger Method can write logs at different levels. Avoid concatenating strings. If your log statement must concatenate strings, then write your code so that it makes sure logging for the targeted logging level is enabled before you perform the concatenation. Use the Logger Method to avoid code readability problems that sometimes occur when you write code that makes sure the logging level is enabled, and when you include this code for every log statement. The Logger Method provides an alternative way to log for each level. It can use a format string and parameters as input. It can substitute the parameters in the format string only if the logging is enabled at the targeted level before writing to the log. This approach postpones string manipulation until your code confirms that logging is enabled. For details about how to set log levels, see java.util.logging.Level on the Java™ Platform, Standard Edition 7 API Specification website at https://docs.oracle.com/javase/7/docs/api/java/util/logging/Level.html. Example of Writing Messages to Order Management Logs The following example demonstrates the use of logs. 1. Write to the Log The following code writes to the log. Table 17. Example of Writing Messages to Logs, Write to the Log Code Description def logger = context.getLogger(); Get the logger object from the context. The first few lines have been left out of the example. def item = getItem(inventoryItemId, orgId); Get the item. Use item Id and organization Id when calling the getItem method. String hazardous = item.getAttribute("HazardousMaterialFlag"); Get the HazardousMaterialFlag attribute from the item. if( "Y".equals(hazardous) ) { Determine whether the item is hazardous. logger.logFinest("Found line with hazardous item %s, %s", inventoryItemId, orgId); Log at the finest level. Note that the string format provides the first argument and the subsequent arguments provide the parameters. def packShipInstruction = line. getOrCreateContextRow("PackShipInstruction") ; Get the row for the extensible flexfield context named PackShipInstruction. packShipInstruction.setAttribute("_ShippingInst ruction", "Hazardous Handling Required."); Set the context segment for Shipping Instruction. Defining Extensions That Modify Order Management Cloud 25 Using Order Management Extensions to Access Data Outside of Order Management ▪ Using View Criteria Objects to Filter Results 2. Define the Public View Object The following code defines the public view object. It uses the following parameters: param itemId. Inventory item Id that identifies the item. param orgId. Inventory organization Id that identifies the organization that owns the item. Table 18. Example of Writing Messages to Logs, Define the Public View Object Code Description Object getItem(Long itemId, Long orgId, def logger) { logger.logFiner("Entering method getItem"); def itemPVO = context.getViewObject("oracle.apps.scm.product Model.items.publicView.ItemPVO"); Create an instance of a public view object named Item. Specify to log at the FINER level. def vc = itemPVO.createViewCriteria(); Create the view criteria object. def vcrow = vc.createViewCriteriaRow(); Create the view criteria row. vcrow.setAttribute("InventoryItemId", itemId); Set the inventory item attribute to include in the filter condition and the value to use when comparing against this attribute. vcrow.setAttribute("OrganizationId", orgId); Set the organization attribute to include in the filter condition and the value to use when comparing against this attribute. def rowset = itemPVO.findByViewCriteria(vc, -1); Specify the view criteria to filter rows and query the view object. def item = rowset.first(); Get the first item row that matches the condition. logger.logFiner("Exiting method getItem: itemNumber %s", item.getAttribute("ItemNumber")); Specify to log at the FINER level. Exit the log. Code Without Comments Here is the entire code with no comments: 1. 80. 81. 82. 83. def logger = context.getLogger(); def item = getItem(inventoryItemId, orgId); String hazardous = item.getAttribute("HazardousMaterialFlag"); if( "Y".equals(hazardous) ) { logger.logFinest("Found line with hazardous item %s, %s", inventoryItemId, orgId); 84. def packShipInstruction = line. getOrCreateContextRow("PackShipInstruction"); 85. packShipInstruction.setAttribute("_ShippingInstruction", "Hazardous Handling Required."); 26 Defining Extensions That Modify Order Management Cloud ▪ Using Order Management Extensions to Access Data Outside of Order Management Using View Criteria Objects to Filter Results 86. } 87. Object getItem(Long itemId, Long orgId, def logger) { 88. logger.logFiner("Entering method getItem"); 89. def itemPVO = context.getViewObject("oracle.apps.scm.productModel.items.publicView. ItemPVO"); 90. def vc = itemPVO.createViewCriteria(); 91. def vcrow = vc.createViewCriteriaRow(); 92. vcrow.setAttribute("InventoryItemId", itemId); 93. vcrow.setAttribute("OrganizationId", orgId); 94. def rowset = itemPVO.findByViewCriteria(vc, -1); 95. def item = rowset.first(); 96. logger.logFiner("Exiting method getItem: itemNumber %s", item.getAttribute("ItemNumber")); 97. return item; 98. } 7 Applied Examples This chapter includes applied examples that describe how to you can use order management extensions to meet your specific business requirements. Some of these examples import classes from Oracle Trading Community Architecture only for demonstration purposes. The import structure you use depends on the architecture that you reference in your environment. Using Order Management Extensions to Update the Order Submit Date: Worked Example In this example, you create an order management extension that uses an extensible flexfield to update the order submit date. Use an order management extension to update the order submit date: 1. Create an extensible flexfield using the following values. Attribute Value Name H1AttributeDateTime1 Category Additional Header Information Context HeaderContext1 For details about how to create an extensible flexfield, see Configuring Extensible Flexfields in Order Management: Explained. 2. In the Navigator, click Setup and Maintenance. 3. On the Setup and Maintenance page, click Order Management, and then click Setup. 4. On the Setup page, search for, and then open Manage Order Management Extensions. Defining Extensions That Modify Order Management Cloud 27 Using Order Management Extensions to Access Data Outside of Order Management ▪ Using View Criteria Objects to Filter Results 5. Notice that the Manage Order Management Extensions page includes the following elements: Three tabs, one for each extension point. A Sequence column. Order Management runs the extensions for each extension point sequentially according to the values in the Sequence column. For example, if the first row contains a value of 10, the second row a value of 30, and the third row a value of 20, then Order Management will run row one, row three, and then row two. 6. On the Manage Order Management Extensions page, Click Actions, and then click Create New. 7. In the Create Extension dialog, accept the default values, and then click OK. The Use Existing option creates a reference to an extension that already exists. It does not create a copy. For example, assume an extension named My_Extension already exists on the On Save extension point. Assume you set Use Existing to My_Extension when you create an extension on the On Start of Submission Request extension point. If you modify My_Extension from On Start of Submission Request at any point in the future, then Order Management will automatically update My_Extension for On Save with your modification. If you modify My_Extension for On Save, then Order Management will update My_Extension for On Start of Submission Request. 8. On the Create Extension page, enter the following values. Attribute Value Name Update Order Submit Date Description This extension sets the value of an extensible flexfield to the date and time when Order Management submitted the sales order. 9. In the Definition area, add the following Groovy code: 1. // Make sure the extension runs only for your test sales order. If multiple developers use your test environment, then this condition makes sure the code updates only your sales order. You must remove this condition in a production environment. 99. def poNumber = header.getAttribute("CustomerPONumber"); 100. if( !"UpdateOrderSubmissionDate".equals(poNumber) ) return; 101. 102. // Get the current time, and then create an instance of java.sql.Date, and set it to the current time. 103. long currentTime = new Date().getTime(); 104. def date = new java.sql.Date(currentTime); 105. 106. // Get the row for the flexfield context named HeaderContext1. 107. def flexfieldContext = header.getOrCreateContextRow("HeaderContext1"); 108. 109. // Set the date on the attribute named _H1AttributeDateTime1 to the current date. Use flexfieldContext to identify the flexfield context where _H1AttributeDateTime1 resides, which is HeaderContext1. 110. flexfieldContext.setAttribute("_H1AttributeDateTime1", date); 28 Defining Extensions That Modify Order Management Cloud ▪ Using Order Management Extensions to Access Data Outside of Order Management Using View Criteria Objects to Filter Results 10. Click Validate, and then click Save and Close. Test Your Work Test your work: 1. Navigate to the Order Management work area, create a new sales order with the following value, and then click Submit. Attribute Value Purchase Order UpdateOrderSubmitDate_run_extension 2. Click Actions, and then click View Additional Information. 3. In the Additional Information dialog, click HeaderEFFDetails, and then verify that the dialog displays the following value. Attribute H1AttributeDateTime1 Value The current date and time. For example: 04/01/17 6:25 PM Using Order Management Extensions to Validate Relationships Between Attributes: Worked Example In this example, you create an order management extension that makes sure the sales order includes a relationship between the sold-to customer and the ship-to customer, and between the sold-to customer and bill-to customer. If one of these relationships does not exist when the user attempt to submit the sales order, then the extension stops the sales order from proceeding and displays an error message. Use an order management extension to validate relationships between attributes: 1. On the Manage Order Management Extensions page, on the On Start of Submission Request tab, create a new extension with the following values. Attribute Value Name Validate Relationships Between Attributes Description Make sure a relationship exists between the sold-to customer and the ship-to customer, and between the sold-to customer and the bill-to customer. If one of these relationships does not exist, then create an error and stop the sales order from proceeding. 2. In the Definition area, add the following Groovy code: 1. //import classes for validation exceptions and messages from Oracle Trading Community Architecture. 111. import oracle.apps.scm.doo.common.extensions.ValidationException; 112. import oracle.apps.scom.doo.comm.extensions.Message; 113. Defining Extensions That Modify Order Management Cloud 29 Using Order Management Extensions to Access Data Outside of Order Management ▪ Using View Criteria Objects to Filter Results 114. // Make sure the extension runs only for your test sales order. If multiple developers use your test environment, then this condition makes sure the code updates only your sales order. You must remove this condition in a production environment. 115. def poNumber = header.getAttribute("CustomerPONumber" ); 116. if(poNumber == null) return; 117. if( !poNumber.startsWith("MatchRelationship") ) return; 118. boolean relationExists=false; 119. 120. //define the variables you will use to store the identifiers. 121. def soldTo = header.getAttribute("BuyingPartyIdentifier") 122. def billTo = header.getAttribute("BillToCustomerIdentifier") 123. 124. //if the relationship exists, then further validation is not necessary, so save the sales order, and then exit. 125. if (header.getAttribute("BuyingPartyName")==header.getAttribute("BillTo CustomerName")) 126. relationExists=true; 127. 128. //determine what relationship currently exists between the bill-to customer and the sold-to customer. 129. //reference the view object that stores the relationship. In this example, the CustomerAccountRelationship view object stores this relationship. 130. def CustPVO = context.getViewObject("oracle.apps.cdm.foundation.parties.publicView .customerAccounts.CustomerAccountRelationshipPVO"); 131. 132. //create the view criteria. 133. def vc = CustPVO.createViewCriteria(); 134. def vcrow = vc.createViewCriteriaRow(); 135. //RelatedCustAccountId is an attribute that stores the sold-to relationship, so you set vcrow to reference RelatedCustAccountId. You will examine it to determine whether the sold-to customer is related to the bill-to customer. 136. vcrow.setAttribute("RelatedCustAccountId", soldTo); 137. //Query the view object according to the criteria that you set in the previous line of code. 138. def rowSet = CustPVO.findByViewCriteria(vc, -1); 139. 140. //Read through the row set. If a row exists that contains a relationship, then you have determined that a relationship exists between sold-to and bill-to, so save the sales order, and then exit. 141. while (rowSet.hasNext()) { 142. def row = rowSet.next(); 143. def billtorelation=row.getAttribute("CustAccountId") 144. if (billtorelation == billTo) 145. { 146. relationExists=true; 147. } 148. } 149. //Create an exception when a relationship does not exist and display an error message. 30 Defining Extensions That Modify Order Management Cloud ▪ Using Order Management Extensions to Access Data Outside of Order Management Using View Criteria Objects to Filter Results 150. //header.setAttribute("ShippingInstructions", header.getAttribute("ShippingInstructions") + ", " relationExists) 151. 152. if( !relationExists) { 153. throw new ValidationException("The order submit failed because the bill-to customer is not related to the sold-to customer."); 154. } Note that this example is only for demonstration purposes in a development environment. It hard codes the message to display in the Order Management work area in the English language as The order submit failed because the bill-to customer is not related to the sold-to customer. In general, to avoid problems with translation to other languages, it is recommended that you not hard code the message in a production environment, but instead use the following format to reference a message from the messaging framework: throw new ValidationException("lookup_code", "message name", token_values); where: lookup_code determines where and how to display the message in the Order Management work area. For example, you can reference multiple lookup codes to display messages in different pie slices on the infolets in the Order Management work area, according to lookup code. message name identifies the name of the message that exists in the messaging framework. token_values specifies a list of the values to use in the tokens that the message contains. If the message does not contain any tokens, then use null. For example, use the following code to display the contents of the FOM_CMN_INV_BILL_TO message: throw new ValidationException("ORA_MANAGE_EXTENSIONS", "FOM_CMN_INV_BILL_TO", null); For details about using lookup_code, see ValidationException Method. Test Your Work Test your work: 1. Navigate to the Order Management work area, create a new sales order with the following value, and then click Submit. Attribute Value Customer Computer Service and Rentals Bill-to Customer Business World Inc. Purchase Order ValidateRelationshipsBetweenAttributes _run_extension 2. Verify that the error dialog displays the message you hard-coded. Note that Computer Service and Rentals is the sold-to customer, Business World Inc is the bill-to customer, they do not match, so Order Management displays an error. 3. Set the following value, and then click Submit. Defining Extensions That Modify Order Management Cloud 31 Using Order Management Extensions to Access Data Outside of Order Management ▪ Using View Criteria Objects to Filter Results Attribute Value Bill-to Customer Computer Service and Rentals 4. Verify that Order Management submits the sales order and sets the status to Processing. Note that Computer Service and Rentals is the sold-to customer and the bill-to customer, they match, so Order Management processes the sales order. Using Order Management Extensions to Verify Data That Users Enter: Worked Example In this example, you create an order management extension that determines whether a purchase order exists for the purchase order number that the Order Entry Specialist enters in the Purchase Order attribute. This applied example calls a public virtual object to get data from Oracle Fusion Procurement. For demonstration purposes, this applied example hard codes some values, such as HW INTERNAL. Your environment will likely require different, variable values. Use an order management extension to verify data that users enter: 1. On the Manage Order Management Extensions page, on the On Start of Submission Request tab, create a new extension with the following values. Attribute Value Name Verify That the Purchase Order Exists Description Determine whether a purchase order exists for the purchase order number that the Order Entry Specialist enters in the Purchase Order attribute. 2. In the Definition area, add the following Groovy code: 1. //Import classes for validation exceptions and messages from Oracle Trading Community Architecture. 155. import oracle.apps.scm.doo.common.extensions.ValidationException; 156. 157. def orderType = header.getAttribute("TransactionTypeCode"); 158. 159. //Determine whether the sales order is internal. 160. if(orderType != null && orderType.contains("HW INTERNAL")) { 161. 162. //Determine whether the purchase order exists. 163. String poNumber = header.getAttribute("CustomerPONumber"); 164. 165. boolean poExists = false; 166. if( poNumber != null ) { 167. 168. //Get the PVO you need to access purchase orders. 169. def poPVO = context.getViewObject("oracle.apps.prc.po.publicView.PurchasingD ocumentHeaderPVO"); 170. 32 Defining Extensions That Modify Order Management Cloud ▪ Using Order Management Extensions to Access Data Outside of Order Management Using View Criteria Objects to Filter Results 171. 172. 173. 174. 175. 176. 177. //Create the view criteria. Use where clause predicates. def vc = poPVO.createViewCriteria(); def vcrow = vc.createViewCriteriaRow(); vcrow.setAttribute("Segment1", poNumber); //Query the view object to find a matching row. def rowset = poPVO.findByViewCriteriaWithBindVars(vc, 1, new String [0], new String [0]); 178. 179. 180. 181. 182. 183. //Determine whether a matching row exists. poExists = rowset.hasNext(); } 184. 185. 186. 187. } 8 //If a matching row does not exist, then the purchase order that the user entered does not exist. Create a validation error and stop the sales order submit. if( !poExists ) { throw new ValidationException("ORA_MANAGE_EXTENSIONS", "DOO_EXT_HW_INTERNAL_PO_REQD", null); } Methods You Can Use with Order Management Extensions: Reference This topic describes the methods you can use with order management extensions.#2001 Execution Context Method The ExecutionContext method calls a SOAP web service. It uses the following format: SoapServiceResponse invokeSoapService(String integrationName, String xmlStr) where: integrationName. Identifies the name of the integration. xmlStr. XML representation of the SOAP body in String format. ExecutionContext returns the following details. Table 19. ExecutionContext Returns Parameter Description getExtensionName() String. Name of the order management extension that is currently running. getEventCode() String. Abbreviation that identifies the event that triggered the extension. Defining Extensions That Modify Order Management Cloud 33 Using Order Management Extensions to Access Data Outside of Order Management ▪ Using View Criteria Objects to Filter Results Parameter Description getLogger() Logger. Logger where the extension can write logs. Logger Method The Logger method returns the message log. It uses the following format: logFine(String msg) where: logFine. Identifies the name of the log file. Message Method The Message method uses a message type and message text to create a message for the sales order. It uses the ORA_MANAGE_EXTENSIONS request function to log messages, by default. It uses the following format: Message(MessageType messageType, String messageText) where: messageType. Type of message. You can use one of the following values: Message.MessageType.ERROR or Message.MessageType.WARNING. messageText. Text of the message to display. Specifying Message Name and Tokens You can specify the message name and message token parameters to create a message for the sales order. You use the following format: Message(MessageType messageType, String messageName, Map<String, Object> messageParams) where: messageType. Type of message. You can use one of the following values: Message.MessageType.ERROR or Message.MessageType.WARNING. messageName. Name of the message that you specify on the Manage Messages page. You must specify Distributed Order Orchestration as the application for this message when you use the Manage Messages page. messageParams. A map that contains message tokens and token values. The Message method uses this map to populate the tokens with values. These tokens are part of the message. Creating Messages for Sales Orders and Sales Order Lines You can use the Request function, message name, and message token parameters to create a message for the sales order or the order line. The Message method will log the message with the request function that you specify. You use the following format for the sales order: Message(MessageType messageType, String requestFunction, String messageName, Map string, object msgParams) 34 Defining Extensions That Modify Order Management Cloud ▪ Using Order Management Extensions to Access Data Outside of Order Management Using View Criteria Objects to Filter Results You use the following format for the order line: Message(MessageType messageType, String requestFunction, Object line, String messageName, Map string, object msgParams) where: Object line. Identifies the order line against which to log the message. For details about the other parameters, see Mapping Tokens for the Message Repository. Row Set Iterator Method The RowSetIterator method manages rows in the iterator. It uses the following format: Row first() RowSetIterator returns the following details. Table 20. RowSetIterator Returns Parameter Description Row first() Returns the first row in the iterator. hasNext() Returns a Boolean value that indicates whether another row exists after the current row. Returns the next row in the iterator. Row next() If no more rows exist after the current row, then this parameter returns a null value. Row last() Returns the last row in the iterator. hasPrevious() Returns a Boolean value that indicates whether another row exists before the current row. Returns the previous row in the iterator. Row previous() createRow() insertRow(Row row) If no more rows exist before the current row, then this parameter returns a null value. Creates a new row. If the entity does not support creating a new row, then this parameter returns an error message when your extension calls this method. Inserts the row into the current iterator, where row specifies the row number to insert. Use this method to add a new row to the iterator after you create the iterator. Defining Extensions That Modify Order Management Cloud 35 Using Order Management Extensions to Access Data Outside of Order Management ▪ Using View Criteria Objects to Filter Results Service Invoker Method Calls a service. Validation Exception Method The ValidationException method uses the error text that you specify to create a validation exception. It displays the message text that you specify. It uses the following format: ValidationException(String messageText) where: messageText. Message text that Order Management will display in the Order Management work area. Displaying Messages from the Message Repository ValidationException can get the error message text from the Oracle Fusion message repository, populate token values, and then display the message in the Order Management work area. You use the following format: ValidationException(String messageName, Map string, object messageParams) where: messageName. Name of the message that you specify on the Manage Messages page. You must specify Distributed Order Orchestration as the application for this message when you use the Manage Messages page. For details, see Creating and Editing a Message: Procedure on Oracle Help Portal at https://fusionhelp.oracle.com/helpPortal. messageParams. A map that contains message tokens and token values. ValidationException uses this map to populate tokens with values in the message. Mapping Tokens for the Message Repository ValidationException uses the following format to create the map that messageParams specifies: ValidationException(java.lang.String requestFunction, java.lang.String messageName, java.util.Map<java.lang.String,java.lang.Object> messageParams) where: requestFunction. Lookup code of the request function to log the message against. You use the Order Management lookup named Request Function to define a request function. If this parameter passes a null value, then ValidationException defaults the request function to ORA_MANAGE_EXTENSIONS. messageName. Name of the message that you specify on the Manage Messages page. You must specify Distributed Order Orchestration as the application for this message when you use the Manage Messages page. messageParams. A map that contains message tokens and token values. ValidationException uses this map to populate tokens with values in the message. 36 Defining Extensions That Modify Order Management Cloud ▪ Using Order Management Extensions to Access Data Outside of Order Management Using View Criteria Objects to Filter Results Displaying Message Objects from the Message Repository ValidationException can use a list of message objects to create a validation exception. It can accommodate a validation error that includes multiple messages. You use the following format: ValidationException(List message messages) Where: messages. A list of message objects. For details about how to create a message object, see Message Method. Referencing Lookup Codes You can use the following format to reference a lookup code: throw new ValidationException("lookup_code") The lookup type named DOO_MSG_REQUEST_FUNCTION contains the following lookup codes. You can specify one of these lookup codes or add new ones to the lookup. Table 21. Lookup Codes Lookup Code Description ASSIGN_PROC Process assignment. MANAGE_TASK Fulfillment task. MANAGE_HOLD Hold. MANAGE_PROC Fulfillment process. PLAN_PROC Fulfillment planning. PROC_CHANGE Change order. XFORM_ORDER Order transformation. Location that Order Management uses to store an incoming source order before it transforms it to a sales order. VALD_CONSTRAINT Processing constraint. VALD_PROC_DEFN Process definition. VALD_ACTION_ELGB Action eligibility. ORA_VALD_ORDER_DATA Order validation. ORA_VALD_CONFIG Configuration. ORA_VALD_PRICING Pricing. ORA_NOTIFY_EVENT Event notification. Defining Extensions That Modify Order Management Cloud 37 Using Order Management Extensions to Access Data Outside of Order Management ▪ Using View Criteria Objects to Filter Results Lookup Code Description ORA_VALD_PAYMENT Payment. ORA_VERIFY_TRADE_COMPLIANCE Verify that fulfillment lines meet trade compliance policies. ORA_CREDIT_CHECK Verify credit check failure. ORA_ORDER_APPROVALS Message function classification for Order Approval messages. ORA_MANAGE_EXTENSIONS Default type for messages that the extensions framework logs. View Object Method The ViewObject method finds and returns a view criterion. It uses the following format: ViewCriteria getViewCriteria(name) where: name. Name of the view criterion. A view criterion is a list of row criterion for the WHERE clause in a view object. Each row criterion is an array that contains criterion for each attribute. Creating View Criterion To create a view criterion, you use the following format: ViewCriteria createViewCriteria() ViewObject returns the new view criterion object. Finding Rows According to View Criterion Use the following format to find rows according to the view criterion that you provide and return them in the form of an iterator: RowIterator findByViewCriteria(ViewCriteria viewCriteria, int maxNumOfRows) where: viewCriteria. Name of the view criteria to use to find rows. maxNumOfRows. Maximum number of rows to return. Use the following format to include an array of variable names and values: 38 Defining Extensions That Modify Order Management Cloud ▪ Using Order Management Extensions to Access Data Outside of Order Management Using View Criteria Objects to Filter Results RowIterator findByViewCriteriaWithBindVars(ViewCriteria viewCriteria, int maxNumOfRows, String[] variableNames, Object[] variableValues) where: variableNames. Array of variable names to use with the view criteria. variableValues. Array of variable values to use with the view criteria. Use the following format to finds rows according to the name of the view criteria: RowIterator findByViewCriteriaWithBindVars(String viewCriteriaName, int maxNumOfRows, String[] variableNames, Object[] variableValues) where: viewCriteriaName. Name of the view criteria to use to find the rows. 9 Attributes You Can Use With Order Management Extensions: Reference This topic describes the attributes that each extension can access. Note the following points: An extension can read from or write to the identifier attributes of a sales order, such as BillToCustomerIdentifier. Your extension code can use the attribute name of the virtual object. Order Management converts values to identifiers when it saves your code. Identifier values use the Oracle Mobile Supply Chain identifier. You can use public virtual objects, but it might be necessary for you to use the identifier attributes. Sales Order Entities That Extensions Can Access Each extension can read data from or write data to the following sales order entities. Table 22. Sales Order Entities That Extensions Can Access Entity Read During All Events Write During Save or Start of Submission Request Write During End of Submission Request Order header Yes Yes No Order line Yes Yes No Extensible flexfield on the order header Yes Yes Extensible flexfield Yes Yes Yes Yes Defining Extensions That Modify Order Management Cloud 39 Using Order Management Extensions to Access Data Outside of Order Management ▪ Using View Criteria Objects to Filter Results Read During All Events Write During Save or Start of Submission Request Write During End of Submission Request Header attachment Yes Yes Yes Fulfillment line attachment Yes Yes No Fulfillment line detail Yes No No Sales credit Yes Yes No Public view object Yes No No Pricing entity, such as order charge, charge component, manual price adjustment, total, or price validation Yes No No Lot serial Yes No No Serial number Yes No No Item attribute Yes Yes No Payment Yes No No Billing plan Yes No No Tax detail Yes No No Item master No No No Customer master No No No Document reference No No No Entity on each fulfillment line List of Attributes Use the following file to get a list of the attributes that each extension can access. 40 Defining Extensions That Modify Order Management Cloud ▪ Using Order Management Extensions to Access Data Outside of Order Management Using View Criteria Objects to Filter Results Order Entities available in Extensions.xlsx Defining Extensions That Modify Order Management Cloud 41