Integrating the Optimization service with Sterling Order Management System by using APIs

As a system integrator, you can integrate the Optimization service with Sterling Order Management System by using the Idle, Rank, and Optimizer APIs.

Before you begin

To access the IBM® Sterling Intelligent Promising APIs, you must generate an authorization bearer token. For more information about generating an API token, see Getting started with APIs.

Familiarize yourself with the user exit that is the integration point between the Optimization service and Sterling Order Management System. For more information, see System administration components: defining user exit implementations.

Procedure

Using the Idle API

  1. Open the Idle API. For more information, see the Idle API.
  2. To invoke the API by using a REST client, use the access token that you obtained already and make an API call along with the header and input body. For example:
    https://api.watsoncommerce.ibm.com/optimizer/{tenantId}/v1/order/idle
    By Header:
    "Authorization" : "Bearer [access_token]"
  3. To Invoke the API by using the OMPGetExternalCostForOptionsUE user exit, see the following sample user exit:
    package sfo.sample;
    
    import javax.xml.parsers.DocumentBuilderFactory;
    
    import org.json.JSONObject;
    import org.w3c.dom.Document;
    
    import com.mashape.unirest.http.HttpResponse;
    import com.mashape.unirest.http.Unirest;
    import com.yantra.yfs.japi.YFSEnvironment;
    import com.yantra.yfs.japi.YFSUserExitException;
    import com.yantra.yfs.japi.ue.OMPGetExternalCostForOptionsUE;
    
    public class CallSFOIdleAPI implements OMPGetExternalCostForOptionsUE 
    {
    		//replace with the OAuth URL provided for your provisioned account
    		private static final String SFO_OAUTH_URL = "https://otmz-preview.orderoptimizer.ibm.com/oauth2/endpoint/xxxxOTMZOAuthProvider/token";
    
    		//replace with the client id for your provisioned account
    		private static final String SFO_CLIENT_ID = "xxxxOTMZClient";
    		
    		//replace with the client secret for your provisioned account
    		private static final String SFO_CLIENT_SECRET = "xxxx";
    		
    		//replace with the URL for your provisioned account
    		private static final String SFO_ASYNCH_OPTIMIZATION_URL = "https://otmz-preview.orderoptimizer.ibm.com/xxxx/otmz/services/idle/V1/promiseOrder";
    		
    
    		//call out to SFO
    		/**
    		 * @param oEnv - The OMS Environment context
    		 * @param inXML - The XML representing the Promise 
    		 * @return 
    		 * @throws YFSUserExitException
    		 */
    		public Document getExternalCostForOptions(final YFSEnvironment oEnv, final Document inXML)
    				throws YFSUserExitException {
    			
    			Document outXML;
    					
    			try {
    
    				//fetch the Bearer Token
    				HttpResponse<String> authTokenResponse = Unirest.post(SFO_OAUTH_URL)
    				  .header("Content-Type", "application/x-www-form-urlencoded")
    				  .body("grant_type=client_credentials&client_id=" + SFO_CLIENT_ID + "&client_secret=" + SFO_CLIENT_SECRET)
    				  .asString();
    				String accessToken = extractToken(authTokenResponse);
    				
    				//convert XML to JSON
    				String jsonInput = convertXMLToJson(inXML);
    				
    				//populate orderDate attribute in input
    
    				//call the Optimization API
    				HttpResponse<String> optimizerApiResponse = Unirest
    						.post(SFO_ASYNCH_OPTIMIZATION_URL)
    						.header("Content-Type", "application/json").header("authorization", "Bearer " + accessToken).body(jsonInput)
    						.asString();
    				
    				outXML = convertJsonToXML(optimizerApiResponse.getBody());
    				
    				//populate attribute Overridden=N output XML
    				
    				return outXML;			
    				
    			} catch (Exception ex) {
    				ex.printStackTrace();
    				throw new YFSUserExitException("Error in calling SFO.");
    			}
    
    		}
    
    		/**
    		 * @param inXML - The XML to be converted to JSON
    		 * @return The JSON string
    		 */
    		private String convertXMLToJson(Document inXML) {
    		     String toReturn = "";
    			//convert XML to JSON String
    			return toReturn;
    
    		}
    		
    
    		/**
    		 * @param inXML - The JSON String to be converted to XML
    		 * @return The XML Document
    		 */
    
    		private Document convertJsonToXML(String string)
    				throws Exception {
    			Document outXML = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
    			//convert JSON string to XML
    			return outXML;
    		}
    
    		/**
    		 * @param authTokenResponse - The HTTP Response containing the access token
    		 * @return The access token
    		 */
    		private String extractToken(HttpResponse<String> authTokenResponse) {
    			return new JSONObject(authTokenResponse.getBody()).getString("access_token");
    		}
    }
    
  4. Provide the request and response for the Idle API.

    The Idle API accept requests for a promise order from Sterling Order Management System.

Using the Rank API

  1. Open the Rank API. For more information, see the Rank API.
  2. To invoke the API by using the REST client, use the access token that you obtained already and make an API call along with the header and input body. For example:
    https://<Base URL>/optimizer/{tenantId}/v1/order/nodes/rank
  3. Next, call the Rank API from the OMPGetSourcingCorrectionsUE in IBM® Sterling Order Management System Software by using the following user exit template:
    <Promise OrderHeaderKey="" OrderNo="" CarrierServiceCode="" CustomerID="" DemandType="" DistanceToConsider="" DistanceUOMToConsider="" EnterpriseCode="" IgnorePromised="" LevelOfService="" OrderReference="" OrganizationCode="" Purpose="" ReceivingNode="" SCAC="" ScacAndServiceKey="" Segment="" SegmentType="" TransactionId="" Mode="">
    	<ShipToAddress AddressLine1="" AddressLine2="" AddressLine3="" AddressLine4="" AddressLine5="" AddressLine6="" AlternateEmailID="" Beeper="" City="" Company="" Country="" DayFaxNo="" DayPhone="" Department="" EMailID="" EveningFaxNo="" EveningPhone="" FirstName="" IsCommercialAddress="" JobTitle="" LastName="" MiddleName="" MobilePhone="" OtherPhone="" PersonID="" State="" Suffix="" TaxGeoCode="" Title="" ZipCode=""/>
    	<PromiseLines TotalNumberOfRecords="">
    		<PromiseLine OrderHeaderKey="" OrderNo="" OrderLineKey="" LineId="" BundleParentLineId="" CarrierServiceCode="" DepartmentCode="" FreightTerms="" GiftWrap="" GroupID="" ItemID="" KitCode="" KitQty="" LevelOfService="" OrderLineReference="" ProductClass="" ReceivingNode="" RequiredQty="" SCAC="" ScacAndServiceKey="" Segment="" SegmentType="" UnitOfMeasure="">
    			<SourcingRuleHeader FulfillmentType="" ItemClassification="" ItemClassification2="" ItemClassification3="" ItemGroupCode="" ItemID="" NodeTypeID="" OrderSourcingClassification="" Purpose="" RegionKey="" SellerOrganizationCode="" ToNodeKey="">
    				<SourcingRuleDetails>
    					<SourcingRuleDetail DistributionRuleId="" FromNodeKey="" FutureInventoryWindow="" ProcureToShipAllowed="" SeqNo="" SubstitutionAllowed="" WorkOrderCreationAllowed="">
    						<SourcingTemplate>
    							<AdditionalData AvailableCapacityPercentage="" DaysToConsiderAvailableCapacityPercentage="" ExpandToMinimizeNumOfShipments="" ExternallyDefinedReasonCode="" IdleAsset="" Radius="" RadiusUOM=""/>
    						</SourcingTemplate>
    						<ShipNodes>
    							<ShipNode ShipNode=""/>
    						</ShipNodes>
    					</SourcingRuleDetail>
    				</SourcingRuleDetails>
    			</SourcingRuleHeader>
    			<ShipToAddress AddressLine1="" AddressLine2="" AddressLine3="" AddressLine4="" AddressLine5="" AddressLine6="" AlternateEmailID="" Beeper="" City="" Company="" Country="" DayFaxNo="" DayPhone="" Department="" EMailID="" EveningFaxNo="" EveningPhone="" FirstName="" IsCommercialAddress="" JobTitle="" LastName="" MiddleName="" MobilePhone="" OtherPhone="" PersonID="" State="" Suffix="" TaxGeoCode="" Title="" ZipCode=""/>
    			<Tag BatchNo="" LotAttribute1="" LotAttribute2="" LotAttribute3="" LotKeyReference="" LotNumber="" ManufacturingDate="" RevisionNo=""/>
    		</PromiseLine>
    	</PromiseLines>
    </Promise>

Using the Optimizer API

  1. Open the Optimizer API. For more information, see the Optimizer API.
    Note: This Optimizer V2 API is deprecated. New customers should use the Optimizer V3 API.
  2. To invoke the API by using the REST client, use the access token that you obtained already and make an API call along with the header and input body. For example:

https://<BaseURL>/optimizer/{tenantId}/v3/order/optimization

  1. Next, call the Optimizer API from the OMPGetExternalCostForOptionsUE in IBM Sterling Order Management System Software by using the following user exit template:
    <?xml version="1.0" encoding="UTF-8"?>
    <!--
    Licensed Materials - Property of IBM
    IBM Sterling Selling and Fulfillment Suite, Sterling Order Management
    System (5737-D18)
    (C) Copyright IBM Corp. 2010, 2020 All Rights Reserved.
    US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
     -->
    <Promise>
        <PromiseLines>
            <PromiseLine CarrierServiceCode="" DeliveryMethod=""
                DistributionRuleId="" FillQuantity="" FulfillmentType=""
                ItemID="" LineId="" OrderLineReference="" ProductClass=""
                ReceivingNode="" RequiredQty="" SCAC="" ScacAndServiceKey=""
                ShipNode="" UnitOfMeasure="">
                <ShipToAddress  Country="" State="" ZipCode="" PersonInfoKey="" />
                <PossibleAssignments>
                    <Assignment AssignmentKey="" Capacity=""
                        CapacityConsumed="" CapacityUnitOfMeasure=""
                        CapacityUtilization="" CarrierServiceCode=""
                        DeliveryDate="" Distance="" NodeProcessingDate=""
                        ProcuredQty="" ProductAvailDate="" Quantity=""
                        SCAC="" ShipDate="" ShipNode="">
                        <PossibleCarriers>
                            <Carrier CarrierServiceCode=""
                                ExpectedDeliveryDate="" ExpectedShipmentDate=""/>
                        </PossibleCarriers>
                        <Supplies>
                            <Supply AvailableQuantity="" FirstShipDate=""
                                LastShipDate="" SafetyQuantity="" Track=""/>
                        </Supplies>
                        <Costs Currency="" HoursOfSupplyCostPerUnit=""
                            ItemInventoryCostPerUnit=""
                            NodePriorityCostPerUnit=""
                            NodeShippingCapacityCostPerUnit=""
                            OutboundShipmentHandlingCostPerUnit="" ShipmentDelayCostPerUnit=""/>
                        <SubstituteItems>
                            <SubstituteItem AssignmentKey="" Capacity=""
                                CapacityConsumed="" CapacityUnitOfMeasure=""
                                CapacityUtilization="" ItemID=""
                                ProcuredQty="" ProductClass="" Quantity=""
                                ShipDate="" UOM="">
                                <Costs Currency="" ItemInventoryCostPerUnit=""/>
                                <Supplies>
                                    <Supply AvailableQuantity=""
                                        FirstShipDate="" LastShipDate=""
                                        SafetyQuantity="" Track=""/>
                                </Supplies>
                                <Procurements>
                                    <Procurement AssignmentKey=""
                                        Capacity="" CapacityConsumed=""
                                        CapacityUnitOfMeasure=""
                                        CapacityUtilization=""
                                        ProcureFromNode="" Quantity="" ShipDate="">
                                        <Costs Currency=""
                                        ItemInventoryCostPerUnit=""
                                        NodePriorityCostPerUnit=""
                                        NodeShippingCapacityCostPerUnit="" OutboundShipmentHandlingCostPerUnit=""/>
                                        <Supplies>
                                        <Supply AvailableQuantity=""
                                        FirstShipDate=""
                                        LastShipDate=""
                                        SafetyQuantity="" Track=""/>
                                        </Supplies>
                                    </Procurement>
                                </Procurements>
                            </SubstituteItem>
                        </SubstituteItems>
                        <Procurements>
                            <Procurement AssignmentKey="" Capacity=""
                                CapacityConsumed="" CapacityUnitOfMeasure=""
                                CapacityUtilization="" ProcureFromNode=""
                                Quantity="" ShipDate="">
                                <Costs Currency=""
                                    ItemInventoryCostPerUnit=""
                                    NodePriorityCostPerUnit=""
                                    NodeShippingCapacityCostPerUnit="" OutboundShipmentHandlingCostPerUnit=""/>
                                <Supplies>
                                    <Supply AvailableQuantity=""
                                        FirstShipDate="" LastShipDate=""
                                        SafetyQuantity="" Track=""/>
                                </Supplies>
                            </Procurement>
                        </Procurements>
                    </Assignment>
                </PossibleAssignments>
            </PromiseLine>
        </PromiseLines>
        <SuggestedOption>
            <Option AvailableFromUnplannedInventory="" FirstDate=""
                HasAnyUnavailableQty="" LastDate="" LeastPriority=""
                MaxPriority="" NodeQty="" TotalShipments="">
                <PromiseLines TotalNumberOfRecords="">
                    <PromiseLine CarrierServiceCode="" DeliveryMethod=""
                        ItemID="" LineId="" ProductClass="" RequiredQty="" UnitOfMeasure="">
                        <Assignments TotalNumberOfRecords="">
                            <Assignment DeliveryDate="" Distance=""
                                EmptyAssignmentReason="" InteractionNo=""
                                InvQty="Required" IsReservationOnly=""
                                MergeNode="" NodePriority=""
                                NodeProcessingDate="" ProcuredQty=""
                                ProductAvailDate="" Quantity=""
                                QuantityFromUnplannedInventory=""
                                ReservedQty="" SCAC="" SegmentChangeQty=""
                                ShipDate="" ShipNode="" SubstitutedQty="" TransferNo="">
                                <SubstituteItems>
                                    <SubstituteItem ItemID="" ProcuredQty=""
                                        ProductClass="" Quantity=""
                                        ReservedQty="" UOM="">
                                        <Procurements>
                                        <Procurement ProcureFromNode=""
                                        Quantity="" ShipDate="" TransferNo=""/>
                                        </Procurements>
                                    </SubstituteItem>
                                </SubstituteItems>
                                <Procurements>
                                    <Procurement ProcureFromNode=""
                                        ProductAvailDate="" Quantity=""
                                        ShipDate="" TransferNo=""/>
                                </Procurements>
                            </Assignment>
                        </Assignments>
                    </PromiseLine>
                </PromiseLines>
                <Interactions TotalNumberOfRecords="">
                    <Interaction ApptEndTimestamp="" ApptStartTimestamp=""
                        Carrier="" CarrierServiceCode="" DeliveryDate=""
                        DeliveryMethod="" InteractionNo="" IsDelivery=""
                        ItemGroupCode="" LevelOfService="" Node=""
                        OrganizationCode="" ShipDate="">
                        <PersonInfoShipTo AddressLine1="" AddressLine2=""
                            AddressLine3="" AddressLine4="" AddressLine5=""
                            AddressLine6="" AlternateEmailID="" Beeper=""
                            City="" Company="" Country="" DayFaxNo=""
                            DayPhone="" Department="" EMailID="" ErrorTxt=""
                            EveningFaxNo="" EveningPhone="" FirstName=""
                            HttpUrl="" IsAddressVerified=""
                            IsCommercialAddress="" JobTitle="" LastName=""
                            Latitude="" Longitude="" MiddleName=""
                            MobilePhone="" OtherPhone="" PersonID=""
                            PreferredShipAddress="" State="" Suffix=""
                            TaxGeoCode="" Title="" UseCount=""
                            VerificationStatus="" ZipCode="" isHistory=""/>
                    </Interaction>
                </Interactions>
                <Costs Currency="" HandlingCost="" HoursOfSupplyCost=""
                    ItemInventoryCost="" NodePriorityCost=""
                    NodeShippingCapacityCost="" ShipmentDelayCost=""
                    TotalCost="" TransportationCost=""/>
            </Option>
        </SuggestedOption>
    </Promise>
  2. Provide the request and response for the Optimizer V2 API. For example:
    <Promise OrderDate="" OrderNo="">
      <PromiseLines>
    
        <PromiseLine CarrierServiceCode="" ItemID="" LineId="" ProductClass="" RequiredQty="" UnitOfMeasure=""  DeliveryMethod="" IsPreDefinedNode="">
           <ShipToAddress Country="" State="" ZipCode="" />
          <PossibleAssignments>
             <Assignment AssignmentKey="" CapacityConsumed="" CapacityUtilization="" Distance="" Quantity=""  ShipNode="" IsExternalNode="" DeliveryDate="" ShipDate="">
                <Supplies>
                 <Supply AvailableQuantity="" FirstShipDate="" LastShipDate="" SafetyQuantity="" Track="" /> 
    </Supplies>
             </Assignment>
          </PossibleAssignments>
        </PromiseLine>
      </PromiseLines>
      <SuggestedOption>
        <Option FirstDate="" HasAnyUnavailableQty="" LastDate="" TotalShipments="">
          <PromiseLines>
             <PromiseLine LineId="">
                <Assignments>
                 <Assignment DeliveryDate="" Distance="" EmptyAssignmentReason="" InteractionNo="" Quantity=""  ShipDate="" ShipNode="" /> </Assignments>
             </PromiseLine>
          </PromiseLines>
          <Interactions>
             <Interaction Carrier="" CarrierServiceCode="" DeliveryDate="" DeliveryMethod="" InteractionNo="" Node="" ShipDate="">
               <PersonInfoShipTo Country="" State="" ZipCode="" /> </Interaction>
          </Interactions>
        </Option>
      </SuggestedOption>
    </Promise>
    The Optimizer API response is returned in XML format.
    
    <Promise OrderNo="" OrderDate="">
      <PromiseLines>
       <PromiseLine LineId="" ItemID="">
         <PossibleAssignments>
          <Assignment AssignmentKey="" Quantity="" IsExternalNode="" RejectChoice="" RejectionReason=""  FirstShipDate="">
            <PossibleCarriers>
              <Carrier CarrierServiceCode="" Scac="" ExpectedShipDate=""></Carrier>
            </PossibleCarriers>
            <Costs AssignmentPriority=""></Costs>
          </Assignment>
        </PossibleAssignments>
       </PromiseLine>
      </PromiseLines>
    </Promise>
    

    The CapacityConsumed attribute is required when the fulfillment network load balancing cost configuration is set to greater than 0. Otherwise, it is optional. The Idle API accept requests for a promise order from Sterling Order Management System.