This blog article is about the use of decimal places also known as Arithmetic Precision, in Oracle Application Composer.
Arithmetic precision in Oracle Fusion Applications relates to the number of decimal places displayed and stored in numeric fields. For example, distance measured in kilometers can be displayed and stored with three decimal places to show distance to the nearest metre: 300.124km is 300,124 metres.
When a new record is created, values with a greater number of decimal places that are entered are rounded off to the allowed number of decimal places predefined in the field at the time the record is saved.
For example if a new distance of 478,525.124245 is input into the distance field described above, the value stored would be 478,525.124 as the input value would be rounded down.
Here is a screen shot of the Edit screen of a field called Distance highlighting where the number of decimal places is configured.
If a third of the distance needed to be automatically calculated and displayed, the value 478,525.124 would have to be divided by 3 and then could be displayed in a Text Field using Groovy script. The result below shows both the un-rounded and rounded result of dividing the above by 3.
1/3 of the distance = 159508.3746666667 1/3 of the distance (rounded) = 159508.375
Here is the code that displays the above:
// Retrieve the maximum number of decimal places for the Distance_c field def curObj = newView('myObject_c'); def attr = curObj.findAttributeDef("Distance_c"); def maxDecimalPlaces = attr.getScale(); // Divide the Distance value by three java.math.BigDecimal oldNum = Distance_c; def newDistance = Distance_c / 3; // Create a MathContext Object for rounding off values java.math.MathContext mc = new java.math.MathContext( newDistance.precision() - newDistance.scale() + maxDecimalPlaces, java.math.RoundingMode.HALF_DOWN); // Round off the new distance value def output = newDistance.round(mc); // Display new values rounded and not rounded def displayOutput = "1/3 of the distance = "+newDistance+ "\n" + "1/3 of the distance (rounded) = " + output; return displayOutput;
To retrieve the number of decimal places from the Distance field we have to retrieve the AttributeDef object by creating a handle to the ViewObject using the newView
Groovy function. The AttributeDef.getScale() method retrieves the value.
The Distance_c
value is divided by three and assigned to a variable using the def
keyword. Groovy automatically creates a BigDecimal
value which is why we didn't have to explicitly specify that. All numerical fields are BigDecimal values.
The MathContext class is the engine that performs the rounding in this example. The constructor that we used above to instantiate the MathContext is MathContext(int setPrecision, RoundingMode setRoundingMode)
. The two parameters here define how rounding will be executed.
The first parameter setPrecision
is the number of digits to round to. The second parameter setRoundingMode
determines what rules to follow when rounding. RoundingMode.HALF_DOWN
rounds towards the "nearest neighbor" unless both neighbors are equidistant, in which case the value is round down. The RoundingMode javadoc contains more information on the different rounding modes.
The way that setPrecision
parameter newDistance.precision() - newDistance.scale() + maxDecimalPlaces
is understood by looking at all three parameters and their place.
The value newDistance.precision()
is the BigDecimal.precision()
function which returns the number of digits in the un-scaled value which is the total number of digits in the newDistance
value. In the example above this is 16.
The value newDistance.scale()
is the BigDecimal.scale()
function which returns the number of digits to the right of the decimal point, which in the example above is 10.
By subtracting the scale()
value from the precision()
value we are able to retrieve the number of digits to the left of the decimal point which in this example is 6. Adding the maxDecimalPlaces
value of 3 makes a total of 9 which is the total number of digits that the newDistance needs to be rounded to - 159508.375
.
Once the MathContext object is instantiated then the rounding operation is performed by executing the - newDistance.round()
function.
The code in the example after this point is for displaying the output. Incidentally when using the "\n" within the middle of a String in groovy will display in following line if the String is displayed in a multiline text box.
Another point to note is that all the methods in the java.math.BigDecimal and java.math.MathContext classes are available for use in Oracle Sales Cloud.
A note about the behavior of rounding and decimal places in currency fields is that it is different to normal numerical fields because it is dependent on the currency type not simply on the fact that it's a currency field. For example the number of maximum decimal places used in USD is 2 as opposed to the number of decimal places used in JPY is 0. This is because there is no smaller unit of currency than ¥1 unlike in USD. When entering a currency value into a currency field this will always result in the rounded value being stored based on the currency. However to retrieve the precision values in Groovy is not possible at present.