Professional Documents
Culture Documents
ADv Pricing - Lev - Configurator & Attribute Mapping
ADv Pricing - Lev - Configurator & Attribute Mapping
EXECUTIVE OVERVIEW
Oracle Advanced Pricing 11.5.8 adds functionality that greatly simplifies the
process of defining additional pricing attributes. Setup screens have been
consolidated, and it is no longer necessary to define flex fields and defaulting rules.
This paper is offered as an update and supplement to the Oracle Advanced Pricing
Implementation manual Release 11i and the White Paper QP: Dont Customize,
Extend.
In this paper, you will learn how to define a new pricing context, define new pricing
attributes that source data from Oracle Configurator tables, and use those attribute
values in Price List Lines and Formulas. The pricing structure will work exactly the
same in Order Management, Quoting, and iStore demonstrating a single point of
setup for multiple selling channels.
INTRODUCTION
This white paper provides a solution for how to price items based on attributes
chosen at runtime in Oracle Configurator. In this example, the item is a service
where pricing logic is to be applied based on non-BOM options selected for a given
product. While the attributes herein were mapped from the Oracle Configurator
tables, they could have come from any source, and the process would remain
essentially the same.
SUPPORTING DATA
Server B
Platinum
3324
5916
6060
3264
Gold
2220
3372
4056
1980
- 24/7 onsite
Gold+20%
Gold+20%
Gold+20%
Gold+20%
Gold+30%
Gold+30%
Gold+30%
Gold+30%
1080
1836
1968
1212
Silver+20%
Silver+20%
Silver+20%
Silver+20%
- 24/7 onsite
Silver+30%
Silver+30%
Silver+30%
Silver+30%
Silver+50%
Silver+50%
Silver+50%
Silver+50%
800
1200
1300
900
Brnz+20%
Brnz+20%
Silver
Bronze
- 24/7 online& phone
Storage 1
Brnz+20%
Storage 2
Brnz+20%
The above rates are for a 1 year service agreement. In addition, there is a
DURATION factor to apply a 1.90 multiplier for 2 years, and a 2.72 multiplier for
3 years.
To summarize, prices are defined for each combination of Product and Metal
Level, then an adjustment is applied based on the Options selected, Duration,
Geography, and Customer.
ORACLES APPOACH
With this scenario, it is possible to set up 16 part numbers, 1 for each combination of product and metal level.
However, in this example we chose to do everything with ONE part number instead. While there are certain
advantages using 16 part number method (easier visibility in Price List Maintenance Form), we wanted to prove the
point that we dont have to have a proliferation of part numbers in order to have dynamic pricing.
In this example, servers and storage units are highly configurable, so Oracle Configurator is part of the solution
footprint. The attributes by which prices are determined are easy to collect within a Configurator user interface. The
only thing left was to tell Advanced Pricing how to find them. The latest Attribute Mapping capabilities make this
easy.
Given the above, our solution breaks down into the following steps:
Add the appropriate questions to the Configurator UI (Simple Oracle Configurator Development)
Format the answers to these questions in the CZ CONFIG ATTRIBUTES table for ease of extraction (a
single Oracle Configurator Functional Companion Rule)
Create a single PL/SQL Attribute Mapping function which handles variable inputs
Use the attributes in price list lines, formulae, and modifiers as needed
We start with a single part number called SUPREME. This service could be applied to one or many servers and or
storage units that are sold as a part of a system configuration. As such, the part number was added to the BOM of
each server and each storage unit. The result is that, for a given system configuration, the SUPREME would appear
multiple times, at various levels in the structure.
The level at which SUPREME appears gives us the PRODUCT attribute. The answers to various questions in the
configuration UI give us METAL LEVEL and OPTIONS, and potentially GEOGRAPHY (not modeled in this
scenario). The CUSTOMER is a normal, readily available attribute of the ordering process.
Configurator Functional Companion to build CZ CONFIG ATTRIBUTES
While it is possible for the pricing engine to source the attributes directly from the normal CZ schema, there are
advantages in efficiency and ease of extraction to putting the attributes into a formatted table within the CZ schema.
The concept of Configurator Output Attributes can extend far beyond pricing attributes to include descriptive or
instructive data for down stream processing, workflow triggers, etc.
A straightforward Functional Companion (FC) rule (a java extension) was written and attached to the model structure.
(Java code is attached in Appendix A) The effect of this FC is to write a row into the standard Oracle table
CZ_CONFIG_ATTRIBUTES for each occurrence of the part number SUPREME in the final, CONFIGURED Bill
of Material. In the columns of each row are the values for the attributes PRODUCT, METAL LEVEL, OPTION,
DURATION.
Functional Companions are a non-invasive, upgrade resistant method of adding to the functionality of the out of the
box Oracle Configurator. THIS IS AN EXTENSION, NOT A CUSTOMIZATION
Create a single PL/SQL Attribute Mapping function
A new function was written and installed in the instance that will retrieve the values from the
CZ_CONFIG_ATTRIBUTES table. A single function was written, that handles variable inputs, and can thus be reused to retrieve various values. (PL/SQL body of the function is attached as Appendix B).
It is likely that it could be achieved in a more generic fashion to maximize re-use, given a broader perspective in an
overall implementation. The key point is that this function can be defined such that it never needs to be maintained
again. All pricing behaviors based on the results of this function are defined in Oracle forms. There has been no
change made to standard code, so future upgrades should have no impact. THIS IS AN EXTENSION, NOT A
CUSTOMIZATION.
Choose your new context, and click the LINK ATTRIBUTES BUTTON
For each of our new attributes, we have chosen ATTRIBUTE MAPPING as the Mapping method. Other options
here include CUSTOM SOURCED which is a call to an external program, or USER ENTERED, which can be used
to generate flex fields that can be populated on an Order Management line, for example.
Now we will drill into the mapping for the METAL LEVEL:
What we see above is that there is a separate map for ASO, OKC, and ONT. We have selected a User Source Type
of PL/SQL API. Other alternatives include CONSTANT, SYSTEM VARIABLE, PROFILE OPTION, and
PL/SQL API Multi-Record.
The key to the map is the User Value String. This could simply be an attribute that exists in the associated Global
Object, in this case ASO_PRICING_INT.G_LINE_REC, or, it could be a call to a package that you create, using one
of the values in the Global Object as a hook to get somewhere else.
In the above user value string, we have said: Run the function Get_SM_Price_Attr from within package
SM_PRICING, the inputs included the strings ASO METAL-LEVEL and SMQPValue, as well as the config
header, revision, and quote line code which are natural elements of the Global Object
ASO_PRICING_INT.G_LINE_REC.
Below is an example of how this string looks when we are calling from ORDER MANAGEMENT, looking for the
DURATION attribute.
As you can see from the string above, we have substituted ASO for ONT, and DURATION for METAL-LEVEL.
Also, since Order Management uses a different Global Object (OE_ORDER_PUB.G_LINE), and the Config header
and revision and line have different names in that object, the variables are changed accordingly.
THE PL/SQL PACKAGE AND FUNCTION ARE THE SAME!
Now we can use these attribute values wherever we like!
Use the attributes in price list lines, formulae, and modifiers as need
Since the prices were defined for each combination of PRODUCT and METAL LEVEL, we set up a price list line for
each:
The pricing engine, based on the combination PRODUCT and METAL LEVEL, selects the price list line. The price
list line stores the base price, and a link to the appropriate formula.
Since the OPTION uplifts differ between GOLD, SILVER and BRONZE, we created a formula for each case, and
applied the appropriate formula to the line. Below you can see that the formula SUPREME GOLD uses the values of
the other 2 attributes, DURATION and OPTION to finish the pricing calculation.
The result is, when you order a SERVER A, and select GOLD for your metal level, 24 hour onsite service option, and
a duration of 2 years, the following occurs:
1.
The price list line with $2220 is selected because of PRODUCT and METAL LEVEL
2.
CONCLUSION
The enhancements to the Attribute Mapping methodology in 11.5.8 have streamlined the pricing business process.
Using a structured methodology like the one described here opens up tremendous flexibility in pricing techniques, and
can have a massive favorable impact on maintenance costs and ROI.
oracle.apps.fnd.common.Context;
oracle.apps.cz.cio.*;
com.sun.java.util.collections.*;
java.sql.*;
oracle.apps.cz.utilities.*;
java.io.*;
java.text.*;
java.util.StringTokenizer;
}
int noNodes = mselServiceNodes.size();
// get the sevice level attributes
mMetalLevel = getQpValue((IRuntimeNode)root, mMetalLevelFeat);
mDuration = getQpValue((IRuntimeNode)root, mDurationFeat);
mOptions = getQpValue((IRuntimeNode)root, mOptionsFeat);
// write the config data
writeAttributes();
}
private String getQpValue (IRuntimeNode currRoot, String featName) {
String ret = "";
IRuntimeNode mlIrtn = getFeaturebyName(currRoot, featName);
if (mlIrtn != null) {
try {
IOption optSel = ((IOptionFeature)mlIrtn).getSelectedOption();
if (optSel == null) {
ret = "none";
} else {
Property qpProp =
((RuntimeNode)optSel).getPropertyByName(mQpPropName);
if (qpProp != null && qpProp.hasStringValue()) {
ret = qpProp.getStringValue();
}
}
} catch (SelectionNotMutexedException snme) {
ret = "none";
}
}
return ret;
}
/**
* Clears all attribute data for this configuration from
* the CZ_CONFIG_ATTRIBUTES table.
*/
public void clearConfigAttributes(Configuration config) throws SQLException {
long configHdrId = config.getConfigHeaderIdLong();
long configHdrRev = config.getConfigHeaderRevisionLong();
Connection conn = config.getContext().getJDBCConnection();
PreparedStatement pStmt = null;
int ret;
try {
String sql = "DELETE FROM CZ_CONFIG_ATTRIBUTES WHERE CONFIG_HDR_ID=? AND
CONFIG_REV_NBR=?";
pStmt = conn.prepareStatement(sql);
pStmt.setLong(1, configHdrId);
pStmt.setLong(2, configHdrRev);
ret = pStmt.executeUpdate();
} finally {
if (pStmt != null) pStmt.close();
}
}
private void traverseBomTree(RuntimeNode node) {
}
return ret;
}
/**
* Return the column name in CZ_CONFIG_ATTRIBUTES to write this attribute value
to,
* given an attribute context name, attribute name, and database context.
* This only applies to flexfield attributes
*/
public String getAttributeFieldName (String attrContext, String attribute,
Context ctx) {
Connection conn = ctx.getJDBCConnection(ctx);
ResultSet rs = null;
PreparedStatement pStmt = null;
String sql, columnName = null;
try {
try {
sql = "SELECT dfu.application_column_name " +
"FROM FND_DESCR_FLEX_COLUMN_USAGES DFU, " +
"FND_DESCRIPTIVE_FLEXS FDL , FND_APPLICATION FAN " +
"WHERE fan.application_short_name = 'CZ' " +
"AND dfu.application_id = fan.application_id " +
"AND fdl.application_id = fan.application_id " +
"AND fdl.APPLICATION_TABLE_NAME = 'CZ_CONFIG_ATTRIBUTES' " +
"AND dfu.descriptive_flexfield_name =
fdl.descriptive_flexfield_name " +
"AND dfu.descriptive_flex_context_code = ? " +
"AND end_user_column_name = ? ";
pStmt = conn.prepareStatement(sql);
pStmt.setString(1,attrContext );
pStmt.setString(2,attribute );
rs = pStmt.executeQuery();
if (rs.next()) {
columnName = rs.getString(1);
} else {
throw new RuntimeException("No column name found for context = " +
attrContext +
" and attribute = " + attribute);
}
} finally {
// close all
if (rs != null) rs.close();
if (pStmt != null) pStmt.close();
}
} catch (SQLException e) {
throw new RuntimeException("Error querying attribute names");
}
return columnName;
}
}
NUMBER := null;
VARCHAR2(10);
BEGIN
IF p_calling_app = 'ASO' THEN
SELECT
INTO
FROM
WHERE
AND
AND
config_item_id
v_config_item_id
aso_quote_line_details
quote_line_id = p_id
config_header_id = p_config_hdr_id
config_revision_num = p_config_rev_nbr;
ATTRIBUTE4
v_return
cz_config_attributes
WHERE
AND
AND
AND
config_hdr_id = p_config_hdr_id
config_rev_nbr = p_config_rev_nbr
config_item_id = v_config_item_id
attribute_category = p_context;
ATTRIBUTE1
v_return
cz_config_attributes
config_hdr_id = p_config_hdr_id
config_rev_nbr = p_config_rev_nbr
config_item_id = v_config_item_id
attribute_category = p_context;
ATTRIBUTE2
v_return
cz_config_attributes
config_hdr_id = p_config_hdr_id
config_rev_nbr = p_config_rev_nbr
config_item_id = v_config_item_id
attribute_category = p_context;
ATTRIBUTE3
v_return
cz_config_attributes
config_hdr_id = p_config_hdr_id
config_rev_nbr = p_config_rev_nbr
config_item_id = v_config_item_id
attribute_category = p_context;
ELSE
v_return := null;
END IF;
ELSE
v_return := null;
END IF;
RETURN v_return;
END Get_SM_Price_Attr;
END sm_pricing;
/
.]