How to Handle Amount, Scale, and Unscaled Values
Author:
Fluent Commerce
Changed on:
9 Dec 2024
Overview
This guide teaches you how to manage large monetary values accurately in Fluent OMS using
`scale`
`unscaledValue`
`amount`
Key points
- Avoid floating-point inaccuracies by using and
`scale`
for large amounts.`unscaledValue`
- Treat and
`unscaledValue`
as the source of truth for exact monetary values.`scale`
- Adjust to handle very large amounts while maintaining precision.
`scale`
- For display and reporting, always reconstruct amounts from and
`unscaledValue`
.`scale`
In Fluent OMS, monetary values are represented using three related fields:
- amount (Float): A floating-point representation of the monetary value.
- scale (Int): The number of decimal places that the unscaled value represents.
- unscaledValue (Int): The integer representation of the amount before decimal placement.
These three fields together are conceptually similar to a
`BigDecimal`
`amount`
- unscaledValue: This is the raw integer form of the monetary amount before considering the decimal point. For example, if you have 123.45:
- might be
`unscaledValue`
.`12345`
- scale: This indicates how many decimal places are present. Using the above example:
- would be
`scale`
because we have two decimal places.`2`
- amount: This is a floating-point number derived by applying the scale to the :
`unscaledValue`
`amount = unscaledValue * 10^(-scale)`
- Continuing the example, .
`12345 * 10^(-2) = 123.45`
Floating-point numbers (like
`Float`
`Double`
Our OMS fields (
`amount`
`scale`
`unscaledValue`
`scale`
`unscaledValue`
For Data Input (Mutations)
- Option A (High Accuracy Preferred):
Always provideand`scale`
fields when creating or updating monetary values. This ensures the OMS stores an exact decimal value.`unscaledValue`
1 mutation {
2
3 updateInvoice(input: {ref: "invoiceRef123",
4 totalAmount: {unscaledValue: 1234567878, scale: 2, amount: 12345678.78}}) {
5 ref
6 totalAmount {
7 amount
8 scale
9 unscaledValue
10 }
11
12 }
13
14}
Language: json
Name: Example mutation
Description:
Example mutation
In this example:
- = 1234567878
`unscaledValue`
- = 2
`scale`
- Thus, the exact monetary value is 12345678.78. Including the amount is optional if you are primarily relying on unscaled value and scale for precision, but it can be helpful for readability. The system will use the and
`unscaledValue`
as the source of truth.`scale`
- Option B (Display Only):
If you must use thealone, understand that it may not represent large values accurately. For very large values (generally 7+ digits before the decimal), floating-point inaccuracies are likely. Consider limiting the usage of`amount`
alone to scenarios where perfect accuracy is not critical.`amount`
For Data Retrieval
- When reading values from the OMS, do not rely solely on the if you need precision.
`amount`
- Use and
`scale`
to reconstruct the exact amount:`unscaledValue`
`precise_value = unscaledValue * 10^(-scale)`
- For example, if and
`unscaledValue = 100000087`
, then:`scale = 2`
`precise_value = 100000087 * 10^(-2) = 1000000.87`
- Display this calculated value in your UI or use it in downstream calculations for guaranteed accuracy.
Choosing the Right Scale
Select a
`scale`
UI Display Considerations:
- If the UI is currently displaying the directly, you may see rounding issues on large amounts.
`amount`
- To ensure the UI displays exact values, transform and
`unscaledValue`
into a formatted string. This ensures that what the user sees matches the exact intended monetary value, regardless of the internal floating-point representation.`scale`
Example template code :`{{currency (divide unscaledValue ( pow 10 scale) _decimalPlaces=scale) currency}}`
Summary
- DO provide and
`scale`
when accuracy matters—these are your source of truth.`unscaledValue`
- DO use and
`scale`
to reconstruct the precise monetary value for display and further calculations.`unscaledValue`
- DON’T rely solely on the for large or critical monetary values, as floating-point inaccuracies can cause rounding issues.
`amount`
- CHECK that your chosen and
`scale`
fit within the integer range, and consider using different scales to handle very large values.`unscaledValue`