Pricing Algorithms

Use a pricing algorithm to manage pricing logic and price calculations.

Use a pricing algorithm to manage price logic and price calculations.

A pricing algorithm is a set of rules that uses conditional logic, variables, functions, and Groovy script to manipulate data that affects pricing. Use it to modify the logic that Oracle Pricing uses when it prices an item.

  • Create procedural logic. Pricing uses different pricing algorithms to calculate different prices. For example, the predefined Price Sales Transaction algorithm uses logical steps to price each sales transaction.

    • Determine Pricing Segment and Strategy

    • Get List Price

    • Apply Adjustments and Discounts

    • Calculate Shipping and Tax

  • Modify, reuse, resequence, add, or remove steps.

  • Add functions and variables.

  • Create your own algorithm.

  • Use Groovy script and Expression Builder to code and extend your algorithm.

  • Add your own dynamic pricing calculation. For example, calculate a commodity price that changes daily. For another example, set up pricing for your sales orders that's different from pricing for your service contracts, and set up pricing for your service contracts that's different from pricing for your subscriptions.

  • Create and publish different versions of your algorithm and test them to try out different scenarios.

  • Reference another pricing algorithm from your own pricing algorithm.

For use cases that use pricing algorithms, see the Use Cases chapter, starting at Overview of Pricing Use Cases. For even more use cases, see Technical Reference for Oracle Pricing (Document ID 2248583.1) on My Oracle Support, then examine the various attachments.

Parts of a Pricing Algorithm

A pricing algorithm manipulates data in the output service data object (SDO) that Pricing uses to calculate price, such as adding a value to each attribute in the SDO.

Here are the parts of a typical pricing algorithm.

parts of a typical pricing algorithm

Note

  1. Name. Each pricing algorithm achieves a finite goal, such as determining the shipping charge list to use when calculating the shipping charge, and creating the shipping charges for each order line that requires a shipping charge calculation.

  2. Version. Pricing increments the version of the pricing algorithm each time you publish it.

  3. Sequence. A series of steps that the pricing algorithm processes in a sequence. You can move each step up or down to modify the sequence.

    Assume a tax authority requires that you calculate tax only on the item that you are selling, and not on the shipping charge. You can move Step 10, Compute Tax, to immediately above Step 4, Create Shipping Charges.

  4. Step Type. Click the step, then use the Step Details area to modify the step.

    The Type specifies the type of logic that the step uses, such as Conditional Action, Nested Action, Group, or Subalgorithm.

    Step 4, Create Shipping Charges, is a conditional step that writes shipping charges to the output SDO only if the order line is a candidate for a shipping charge. Here's the condition it uses.

    Condition

    Description

    'SUCCESS' == ServiceParam.OutputStatus && 'LINE' == Candidate.ParentEntityCode

    Run this step only if the order line is a candidate for a shipping charge.

    Here's the format that the condition uses.

    • SUCCESS

    • ServiceParam. Identifies a data set in this pricing algorithm step.

    • OutputStatus.

    • &&.

    • LINE.

    • Candidate. Identifies a data set in the pricing algorithm step.

    • ParentEntityCode.

    For details, see Pricing Algorithm Steps.

  5. Data Sets. Each row in the Data Sets area defines a data set, and each data set filters the set of records that the step processes.

  6. Variables. Set up variables that the pricing algorithm uses. For example, if you set the NeedsCurrencyConversion variable to Yes in the Calculate Shipping Charges algorithm, then each algorithm step that involves currency will do a conversion.

  7. Functions. Set up functions that receive data from the algorithm, process it, then return one or more values to the algorithm.

  8. Subalgorithm. Another pricing algorithm that this pricing algorithm references.

    Step 10 of the Calculate Shipping Charges algorithm references the Create Net Price Charge Component subalgorithm. At runtime, Pricing runs the subalgorithm, then returns to the subsequent step. It returns to step 11.

Variables

A variable in a pricing algorithm stores a value that can change depending on conditions or details that pass through each algorithm step. Use it to receive data from the object that calls the pricing algorithm, or to send data to the object.

A variable in a pricing algorithm stores a value that can change depending on conditions or details that pass through each algorithm step.

Here are the attributes you can use with a variable.

Attributes

Description

Name

Alphanumeric text that describes the variable. Use a name that's unique in the algorithm.

Don't include spaces.

Data Type

Data type, such as String.

If you set Data Type to Data Object, then you must set a value in the Internal Service Schema attribute.

Required

Add a check mark to make this variable required in an algorithm step.

Input/Output

Specify usage.

  • Input. The object that calls this pricing algorithm can send the value of this variable to the pricing algorithm.

  • Output. The algorithm can send the value of this variable to the object that calls this pricing algorithm.

Internal Service Schema

If you set the Data Type variable to Data Object, then set Internal Service Schema to the service that provides details to this variable, or that can use the output that this variable provides.

For example, the CalculateSalesOrderTotals service calculates the total price of a sales order. If you must use this variable to calculate total price, then set Internal Service Schema to CalculateSalesOrderTotals.

Most algorithms include at least one Data Object variable.

Default Expression

Groovy expression that specifies the default value for the variable. If the input payload results in setting the value of the variable to a value that isn't empty, then Pricing ignores the expression.

You can use an expression for each data type except Data Object.

Most algorithms include the PriceRequest variable. It stores details for the PriceRequest service data object according to the transaction you must price, such as a sales order.

Most algorithms include the PriceRequest variable. It stores details for the PriceRequest service data object according to the transaction you must price, such as a sales order.

Note

  • PriceRequest uses the PricingInternal.PriceRequestInternal internal service schema.

  • PriceRequest stores details for the Header, Line, and ChargeCandidate entities.

  • Pricing creates the ChargeCandidate from the segment price list on the pricing strategy.

Types of Pricing Algorithms

Type

Description

New

A pricing algorithm that Pricing provides for the first time.

  • A new pricing algorithm includes functionality that doesn't exist in prior releases. It might also include corrections for features from prior releases.

  • New pricing algorithms come predefined in the current release.

  • The Manage Algorithms page uses version 0 to indicate a new pricing algorithm.

  • You must manually promote new algorithms when you install a new release or upgrade from a prior release.

Current

A pricing algorithm that you promoted from a prior release to the current release.

  • A current pricing algorithm is up-to-date with the current release.

  • The Manage Algorithms page uses version 1 to indicate a current pricing algorithm.

  • You can modify a current pricing algorithm.

Extended

A pricing algorithm that you create so it meets your specific business needs.

You click Actions > Create on the Manage Algorithms page to create an extended pricing algorithm.

Modified

A predefined pricing algorithm that you modified.

Functions

A function in a pricing algorithm is a routine that receives data from the pricing algorithm, processes it, then returns one or more values to the pricing algorithm. You can use a view object lookup function or a script function.

Here's an example of how the predefined Get Currency Conversion Rates algorithm uses two view object lookups, one script, and three arguments.

example of how the predefined Get Currency Conversion Rates algorithm uses two view object queries functions, one script function, and three arguments

Note

Attribute

Description

Name

Enter alphanumeric text. Use camel case and make the first letter lower case. Don't include spaces. For example, enter myPricingFunction.

Query Type

Choose a value.

  • View Object Lookup. Search for data in the Oracle database and return a result.

  • Script. Call a script that determines the value.

Argument

Click the Arguments link, then add arguments.

  • Use arguments to communicate data from the algorithm step to the function, and from the function to the step.

  • Enter the name.

    • Make sure its unique in the pricing algorithm across all functions.

    • Use camel case and make the first letter upper case.

    • Don't includes spaces.

    • For example, MyPricingFunctionArgument.

  • Sequence your arguments.

    Pricing uses the arguments you add in the same sequence you add them. For example, if you add argument x, and then y, and then z, then Pricing uses argument x first, and then y, and then z.

    Click Move Up or Move Down to modify the sequence.

  • You don't assign a data type to an argument. The argument takes the data type according to the value that the function sends through the argument. For example, if the function sends numeric data through argument x, then argument x is Numeric.

  • Use the Arguments tab to add arguments for a view object lookup or script.

Example of Script

A script runs procedural logic then returns values.

Here's an example of a step that uses script to call a function.

example of a step that uses script to call a function.

Note

  • Step 2, GetPricingCurrencyConversionRates, needs to get the currency conversion rate for the transaction.

  • Script in the First Row Actions section of GetPricingCurrencyConversionRates calls the getAdjustedRate function.

  • The function uses arguments, such as AdjustmentTypeCode and AdjustmentValue, to calculate the conversion rate.

  • The function returns the conversion rate in the ConversionRate argument.

Here's the complete script of the first row action. Notice how the script uses arguments frequently, such as ConversionRate, but makes only one call to the getAdjustedRate function. To improve performance, make only one call to the function in your script.

ConvRate.ConversionTypeCode = Match.ConversionTypeCode
ConvRate.ConversionRate = Match.ConversionRate
finest {'test GetCurrencyConversionRate - on First row'}
if (Match.ConversionTypeCode == 'GL_SOURCED') {
finest {'get GL Rate for -- FromCurr: '+FromCurrencyCode+' ToCurr: '+ToCurrencyCode+' PriceAsOf: '+PriceAsOf+' GlConvType: '+GlConversionTypeCode}
  rate = pricingUtil.getGlRate(FromCurrencyCode, ToCurrencyCode, PriceAsOf, GlConversionTypeCode)
finest {'GL Rate returned -- ConversionRate: '+rate}
ConvRate.ConversionRate = rate
}
finest {'ConversionRate: '+ConvRate.ConversionRate}
if (Match.AdjustmentTypeCode != null && ConvRate.ConversionRate != null && ((ConvRate.ConversionTypeCode.contains('GL') && ConvRate.ConversionRate != -1 && ConvRate.ConversionRate != -2) || !ConvRate.ConversionTypeCode.contains('GL'))) {
finest {'Rate Adjustment -- AdjType: '+Match.AdjustmentTypeCode+' AdjValue: '+Match.AdjustmentValue}
  ConvRate.ConversionRate = getAdjustedRate(ConvRate.ConversionRate, Match.AdjustmentTypeCode, Match.AdjustmentValue)
}
finest {'Conversion Error Check - ConvType: '+ConvRate?.ConversionTypeCode}
if (ConvRate?.ConversionTypeCode?.contains('GL') && (ConvRate.ConversionRate == null || ConvRate.ConversionRate == -1 || ConvRate.ConversionRate == -2)) {
finest {'GL Conversion Error'}
  ConvRate.ConversionRate = null;
  ConvRate.MessageTypeCode = 'ERROR';
  ConvRate.PrcMessageName = 'QP_PDP_PRICE_GL_CURR_ERROR';
  ConvRate.GlMessageName = (ConvPurpose == 'VALIDATE_PRICE')?'QP_PDP_POLICY_GL_CURR_ERROR':null;
  ConvRate.PrcErrorMessage = getFndMessage('QP','QP_PDP_PRICE_GL_CURR_ERROR', null);
  ConvRate.GlErrorMessage =  ((ConvPurpose == 'VALIDATE_PRICE')?getFndMessage('QP','QP_PDP_POLICY_GL_CURR_ERROR', null):null);
}
else if (!ConvRate?.ConversionTypeCode?.contains('GL') && (ConvRate.ConversionRate == null)) {
finest {'QP Conversion Error'}
  ConvRate.ConversionRate = null;
  ConvRate.MessageTypeCode = 'ERROR';
  ConvRate.PrcMessageName = 'QP_PDP_PRICE_CURR_LIST_ERROR';
  ConvRate.GlMessageName = (ConvPurpose == 'VALIDATE_PRICE')?'QP_PDP_POLICY_CURR_LIST_ERROR':null;
  ConvRate.PrcErrorMessage = getFndMessage('QP','QP_PDP_PRICE_CURR_LIST_ERROR', null);
  ConvRate.GlErrorMessage =  (ConvPurpose == 'VALIDATE_PRICE')?getFndMessage('QP','QP_PDP_POLICY_CURR_LIST_ERROR', null):null;
}

Here's the complete script of the getAdjustedRate function. Use finest to declare your arguments, then add logic, such as If statements.

finest {'getAdjustedRate Arguments-- AdjType: '+adjustmentTypeCode+' AdjValue: '+adjustmentValue+' convRate: '+conversionRate}
if (conversionRate != null && adjustmentValue != null) {
if (adjustmentTypeCode == 'MARKUP_AMOUNT') { conversionRate += adjustmentValue}
if (adjustmentTypeCode == 'MARKDOWN_AMOUNT') { conversionRate -= adjustmentValue}
if (adjustmentTypeCode == 'MARKUP_PERCENT') { conversionRate += conversionRate * adjustmentValue / 100}
if (adjustmentTypeCode == 'MARKDOWN_PERCENT') { conversionRate -= conversionRate * adjustmentValue / 100}
}
if (adjustmentTypeCode == 'OVERRIDE') { conversionRate = adjustmentValue}
return conversionRate  

Example of View Object Lookup

Here's an example of a step that uses a view object lookup to call a function. To start, add your arguments.

example of a step that uses a view object lookup to call a function.

Then click View Object Query, and set up the query. Here's a typical view object query. Note that view object query and view object lookup mean the same thing.

a typical view object query

Here's the code that this example uses.

  1. Application Module.

    Example

    Description

    oracle.apps.scm.pricing.priceExecution.pricingProcesses.publicModel.applicationModule.PricingProcessAM

    Identify the application module.

    A pricing algorithm is part of the pricing process so use PricingProcess.

    • oracle.apps.scm.pricing.priceExecution. The path to PricingProcess.

    • applicationModule.PricingProcessAM. Specifies to use PricingProcessAM, where AM means application module.

    Learn about Application Module and Application Configuration. For details, see Choices That You Can Select in Pricing Matrixes.

  2. Application Configuration.

    Example

    Description

    ${(PriceRequest.PricingServiceParameter[0]?.CacheEnabledFlag==null || PriceRequest.PricingServiceParameter[0].CacheEnabledFlag) ? 'PricingProcessAMShared' : 'PricingProcessAMLocal'}

    You must use this configuration for most algorithms.

  3. View Object.

    Example

    Description

    CurrencyConvRate1

    Enter the name of the view object.

    Pricing comes predefined to use CurrencyConvRate1 for the GetCurrencyConversionRate function.

    You can also use the fully qualified name. Here's an example that identifies the name of the view object when you use a descriptive flexfield.

    oracle.apps.flex.scm.pricing.priceExecution.pricingProcesses.priceListCharges.view.PriceListChargeDFFVO

    where

    • oracle.apps.flex.scm.pricing.priceExecution.pricingProcesses.priceListCharges. The path to the priceListCharges entity of the pricingProcesses application module for flexfields.

    • PriceListChargeDFFVO. Name of the view object, where DFFVO means descriptive flexfield view object.

  4. View Criteria.

    Example

    Description

    No value for this example.

    Criteria that determines whether you can query the view object according to the bind variables.

  5. In Memory Search Specification.

    Example

    Description

    isInDateRange(StrategyDetailStartDate, StrategyDetailEndDate, priceAsOf) && isInDateRange(ConvListStartDate, ConvListEndDate, priceAsOf)&& isInDateRange(ConvDetailStartDate, ConvDetailEndDate, pricingDate)

    Add search specifications that filter results of the view object that's currently in memory.

    This example includes three isInDateRange functions that specify how to search.

    The first isInDateRange filters according to pricing strategies.

    • isInDateRange. Name of the search specification.

    • StrategyDetailStartDate. Filter results so they only include pricing strategies that start on or after this date.

    • StrategyDetailEndDate. Filter results so they only include pricing strategies that start on or before this date.

    • priceAsOf. Filter results so they only include records where Pricing used the strategy to price an item on a specific date.

    The second isInDateRange filters according to currency conversion lists.

    • isInDateRange. Name of the search specification.

    • ConvListStartDate. Filter results so they only include currency conversion lists that start on or after this date.

    • ConvListEndDate. Filter results so they only include currency conversion lists that end on or before this date.

    • priceAsOf. Filter results so they only include records where Pricing used the conversion list to price an item on a specific date.

    The third isInDateRange filters according to currency conversion details.

    • isInDateRange. Name of the search specification.

    • ConvDetailStartDate. Filter results so they only include currency conversion details that start on or after this date.

    • ConvDetailEndDate. Filter results so they only include currency conversion details that end on or before this date.

    • pricingDate. Filter results so they only include records where Pricing used the conversion details to price an item on a specific date.

    The specifications are cumulative. For example, this specification filters according to pricing strategy, and currency conversion list, and conversion detail.

    Assume the search specifications filter to return only pricing strategies a and b, currency conversion lists c and d, and conversion detail e. If records 1, 2, and 3 include pricing strategies a and b, and if records 7 and 8 include currency conversion lists c and d, and if record 9 includes conversion details e, then the search results will include records 1, 2, 3, 7, 8, and 9.

  6. Order By.

    Example

    Description

    No value for this example.

    Sort the records of the data set in ascending order or descending order, according to one or more columns.

    For example, to use precedence when sequencing the query results according to prices on the pricing strategy, set Order By to Precedence.

    Order By affects performance. Don't use it unless you really need it.

    For details, see the Data Sets section of this topic.

  7. Single Row.

    Example

    Description

    Disabled for this example.

    Check whether the view object can return only one row. For example, a price list includes only one Price List Id. If you query according to Price List Id, then enable Single Row.

    Enabling this option decreases processing time because the algorithm proceeds immediately after it receives the one record instead of searching through all possible records.

  8. Bind Variables.

    Example

    Description

    Bind Variable Name. For example, fromCurrencyCode.

    Name of the bind variable that you add to the view object.

    Bind Variable Value. For example, fromCurrency.

    Use a fixed value, Groovy expression, or argument name. In this example, fromCurrency is the name of argument for this function.

If you add a lookup for a hierarchical view object, then you can click the Hierarchical Query tab, then set properties.

Properties

Description

Connect By

Specify how to connect.

Query Result Alias

Specify the alias.