4 Migrating Number and Currency Formatting Customizations

Learn how to migrate your custom Oracle Communications Billing Care number and currency formatting implementations to use Oracle JET number converters and the Billing Care NumberUtil utility.

Starting in release 16.26.0, Billing Care uses Oracle JET number conversion for locale-aware formatting and parsing. If your existing Billing Care customizations use legacy util.js number or amount formatting methods, you must update them to use NumberUtil, Oracle JET converters, and oj-c-input-number.

Topics in this document:

About Number and Currency Formatting Updates

Billing Care 16.26.0 includes changes to how numbers, currency amounts, percentages, and localized numeric values are formatted and parsed.

Earlier Billing Care implementations could use custom formatting and parsing methods in util.js. These methods formatted numeric values into localized strings, removed formatting before calculations, manipulated signs while formatting values, and performed locale-specific parsing.

Starting in release 16.26.0, Billing Care uses NumberUtil.js as the common entry point for number converters. The Oracle JET converters handle locale-specific formatting and parsing, while ViewModels and REST requests keep numeric values independent of the display locale.

When you migrate your customizations to use NumberUtil, Oracle JET converters, and oj-c-input-number:

  • Use NumberUtil.getCurrencyConverter() for BRM currency amounts.

  • Use NumberUtil.getDecimalConverter() for noncurrency decimal values.

  • Use NumberUtil.getPercentConverter() for percentage values.

  • Use the oj-c-input-number component for editable and read-only numeric fields.

  • Keep values used in calculations, comparisons, and REST requests as numbers.

  • Use a converter's format() method only when you need to display a formatted number as plain text.

  • Use a converter's parse() method only when you need to convert a localized string to a number.

  • Compare numeric values directly or use NumberUtil.amountComparator() when a component or API requires a comparator.

Migrate customizations that use any of the following legacy methods:

  • formatNumber

  • convertAmountPositiveToNegative

  • convertAmountNegativeToPositive

  • formatAmount

  • unformatAmount

  • formatAmountWithAbbr

  • formatAmountWithoutSymbol

  • performAmountFormatting

  • reverseSignAndFormatAmount

  • unformatPaymentAmount

  • reformatAmountAndReveseSign

  • parseAmountBasedOnLocale

  • unformatLocaleAmountToFloat

  • amountComparator

Some legacy methods combine formatting, parsing, or sign manipulation in a single operation. NumberUtil does not provide a one-to-one replacement for every method. Instead, keep the underlying value numeric, perform business operations on that numeric value, and let the appropriate Oracle JET converter format or parse the value at the UI boundary.

Tasks for Migrating Number and Currency Formatting Customizations

Complete the following steps to migrate your number and currency formatting customizations:

  1. Identify legacy formatting and parsing calls. Search your customized JavaScript and ViewModel files for calls to the affected util.js methods.

  2. Identify the numeric value type. Determine whether each value represents a currency amount, a noncurrency decimal value, or a percentage.

  3. Update ViewModel dependencies. Add Registry.utilities.numberUtils to the Asynchronous Module Definition (AMD) dependency list and add NumberUtil as a parameter to the ViewModel function. See "Adding NumberUtil to a ViewModel".

  4. Create a currency, decimal, or percentage converter for each type of numeric value.

  5. Remove formatting from observables and computed values that participate in calculations, comparisons, validation, or REST request creation. See "Keeping Values Numeric".

  6. Update numeric UI fields to use oj-c-input-number with the appropriate converter for editable and read-only numeric fields. See "Updating Numeric UI Fields".

  7. Replace any manual formatting to use the converter's format() method when you need to display a formatted value in plain text. See the following topics:

  8. Replace any manual parsing to use the converter's parse() method when a customization receives a localized string. Do not parse a value that oj-c-input-number already provides as a number. See "Migrating Localized Amount Parsing".

  9. Update the sign of numeric values before formatting them. Do not use formatting methods to change the sign. See "Migrating Sign Conversion".

  10. Update any amount comparisons to compare numeric values directly. Use NumberUtil.amountComparator() when a component or API requires a comparator function. See "Migrating Amount Comparisons".

  11. Ensure that REST request payloads contain numeric values instead of locale-formatted strings. See "Keeping REST Payloads Numeric".

  12. Verify number formatting and parsing for each locale that your implementation supports. See "Testing the Migration".

Adding NumberUtil to a ViewModel

In your existing customizations, add NumberUtil and the Oracle JET input number component to the ViewModel dependencies.

For example:

define([ 
   "jquery", 
   "knockout", 
   Registry.utilities.numberUtils, 
   "oj-c/input-number"
], function ($, ko, NumberUtil) {
   // ViewModel implementation 
});

Obtain the applicable BRM currency balance element ID before you create a currency converter.

For example:
self.resourceId = globalAppContext.currentAccountViewModel() 
   .account() 
   .currentBillUnit() 
   .currency();

Creating Currency Converters

Use the NumberUtil.getCurrencyConverter() method for currency amounts.

To display an amount without a currency symbol:

self.numberConverterWithoutSymbol = 
   NumberUtil.getCurrencyConverter({ 
      resourceId: self.resourceId, 
      showCurrencySymbol: false 
   });

To display an amount with a currency symbol:

self.numberConverterWithSymbol =
    NumberUtil.getCurrencyConverter({
        resourceId: self.resourceId
    });

Use the converter without a currency symbol when the surrounding UI already identifies the currency.

Use the converter with a currency symbol when the displayed text must identify the currency explicitly, such as in messages, notes, subtitles, or tooltips.

Creating Decimal and Percentage Converters

Use a decimal converter for noncurrency numeric values:

self.decimalConverter = 
   NumberUtil.getDecimalConverter({ 
      resourceId: self.resourceId 
   });

Use a percentage converter for percentage values:

self.percentConverter = 
   NumberUtil.getPercentConverter({ 
      resourceId: self.resourceId 
   });

Keeping Values Numeric

Do not store formatted numbers in observables that participate in business logic.

For example, do not initialize an amount as a formatted string and then parse it before every calculation:

self.amount = 
   ko.observable(util.formatAmountWithoutSymbol(0)); 

self.total = ko.computed(function () { 
   return util.unformatAmount(self.amount()) + 
      util.unformatAmount(self.taxAmount()); 
});

Keep the values numeric instead:

self.amount = ko.observable(0); 
self.taxAmount = ko.observable(0); 

self.total = ko.computed(function () { 
   return self.amount() + self.taxAmount(); 
});

Keeping the values numeric avoids repeated formatting and parsing and prevents locale-specific strings from entering business logic.

Updating Numeric UI Fields

Use oj-c-input-number to display or edit numeric values.

For an editable currency amount:

<oj-c-input-number 
   id="amount" value="{{amount}}" 
   required="true" label-hint="[[makepayment.AMOUNT]]" 
   aria-label="[[makepayment.AMOUNT]]" 
   converter="[[numberConverterWithoutSymbol]]" 
   text-align="end"> 
</oj-c-input-number>

For a read-only amount:

<oj-c-input-number value="[[amount]]" 
   readonly="true" 
   converter="[[numberConverterWithoutSymbol]]" 
   text-align="right"> 
</oj-c-input-number>

Do not create a separate formatted-string observable when the component can format the numeric value directly.

Migrating Formatted Amounts

If an existing customization formats an amount by calling a utility method, keep the amount numeric and use the currency converter instead.

For example, replace:

self.displayAmount = 
   util.formatAmount(self.amount());

with:

self.displayAmount = 
   self.numberConverterWithSymbol.format(self.amount());

Use the format() method only when the application needs a string, such as for the following types of UI content:

  • Messages

  • Notes

  • Subtitles

  • Tooltips

  • Other plain-text UI content

When an oj-c-input-number component displays the value, assign the converter to the component instead of calling the format() method.

Migrating Amounts Without a Currency Symbol

If an existing customization uses the formatAmountWithoutSymbol method, create a currency converter with the showCurrencySymbol property set to false.

For example:

self.numberConverterWithoutSymbol = 
   NumberUtil.getCurrencyConverter({ 
      resourceId: self.resourceId, 
      showCurrencySymbol: false 
   });

Then, assign the converter to the applicable Oracle JET component.

Migrating Localized Amount Parsing

If your existing customizations contain values that already exist as numbers, do not parse the values.

For example, if self.amount() comes from oj-c-input-number, replace:

var amount = 
   util.unformatAmount(self.amount());

with:

var amount = self.amount();

When another source provides a localized string, use the converter's parse() method:

var amount = 
   self.numberConverterWithoutSymbol.parse(localizedAmount);

Apply this approach when you migrate logic that uses any of these methods:

  • unformatAmount

  • unformatPaymentAmount

  • parseAmountBasedOnLocale

  • unformatLocaleAmountToFloat

Do not manually remove currency symbols, grouping separators, decimal separators, or other locale-specific characters.

Migrating Sign Conversion

In your existing customizations, keep sign conversion separate from display formatting.

Apply this approach when you migrate logic that uses any of these methods:

  • convertAmountPositiveToNegative

  • convertAmountNegativeToPositive

  • reverseSignAndFormatAmount

  • reformatAmountAndReveseSign

For example, replace code that changes the sign and formats the value in the same operation:

self.formattedAmount = 
   util.reverseSignAndFormatAmount(self.amount());

with numeric logic:

self.reversedAmount = ko.computed(function () { 
   return -1 * self.amount(); });

Then, let the Oracle JET component format the numeric result:

<oj-c-input-number 
   value="[[reversedAmount]]" 
   readonly="true" 
   converter="[[numberConverterWithoutSymbol]]" 
   text-align="right"> 
</oj-c-input-number>

Do not convert a number to a formatted string simply to change its sign.

Migrating Amount Comparisons

In your existing customizations, compare numeric amounts directly whenever possible.

For example:

if (amount1 < amount2) { 
   // Processing 
}

When a component or API requires a comparator function, use the following method:

NumberUtil.amountComparator(amount1, amount2);

Do not format or parse values solely to compare them.

Keeping REST Payloads Numeric

In your existing customizations, send all numeric values in REST requests.

For example:

self.toJSON = function () { 
   return { 
      amount: self.amount(), 
      percent: self.percentage() * 100 
   }; 
};

Do not send a value produced by the converter.format() method or another locale-specific formatting operation.

Locale formatting belongs in the UI. It does not belong in values that Billing Care sends to REST services.

Testing the Migration

After you migrate your customizations, verify the following behavior:

  • Editable fields accept valid localized numeric input.

  • Read-only fields display numbers correctly.

  • Currency symbols appear in the expected position.

  • Decimal and grouping separators match the active locale.

  • Currency values use the expected decimal scale.

  • Positive, negative, and zero values display correctly.

  • Accounting-style negative values work correctly when you enable that option.

  • Calculations use numeric values.

  • Amount comparisons and sorting work correctly.

  • REST request payloads contain numeric values.

  • Messages, notes, subtitles, and tooltips display formatted values correctly.

  • Parsing correctly converts localized strings to numbers.

The key migration principle is to keep numeric business values separate from their localized display. Keep numbers numeric throughout your ViewModels, calculations, comparisons, and REST processing. Apply Oracle JET formatting when Billing Care displays a value, and parse a value only when your customization receives a localized string.

Example: Migrating an Amount Customization

The following example shows a customization that stores a formatted amount, parses it before use, and formats a sign-reversed amount.

Before

self.amountRawValue = ko.observable("0"); 

self.formattedAdjustAmount = ko.computed(function () { 
   if ($.isNumeric( 
         util.unformatAmount(self.amountRawValue()))) { 
      return util.formatAmountWithoutSymbol( 
         -1 * util.unformatAmount( 
             self.amountRawValue() 
         ) 
      ); 
   } 

   return util.formatAmountWithoutSymbol(0); 
}); 

accountAdjustmentObj.amount = 
   util.unformatAmount(self.amountRawValue());

After

Keep the amount and calculated values numeric:

self.amount = ko.observable(0); 

self.numberConverterWithoutSymbol = 
   NumberUtil.getCurrencyConverter({ 
      resourceId: self.resourceId, 
      showCurrencySymbol: false 
   }); 

self.adjustAmount = ko.computed(function () { 
   if ($.isNumeric(self.amount())) { 
      return -1 * self.amount(); 
   } 

   return 0; 
});

accountAdjustmentObj.amount = self.amount();

Let Oracle JET format the values in the UI:

<oj-c-input-number 
   id="adjustmentAmount" 
   value="{{amount}}" 
   required="true" 
   label-hint="[[makepayment.AMOUNT]]" 
   converter="[[numberConverterWithoutSymbol]]" 
   text-align="end"> 
</oj-c-input-number> 

<oj-c-input-number 
   id="adjustmentAmountDisplay" 
   value="[[adjustAmount]]" 
   readonly="true" 
   converter="[[numberConverterWithoutSymbol]]" 
   text-align="right"> 
</oj-c-input-number>

The migrated implementation keeps both values numeric and applies locale-specific formatting only when Billing Care displays them.

Configuring Accounting-Style Negative Values

Billing Care can display negative numbers with parentheses by using the force-accounting-parens configuration property.

For example:

billingcare:
   configuration:
      features:
         force-accounting-parens: false

When you set the property to true, the shared Billing Care number converter displays negative values with parentheses.

For example, the value -1234.50 displays as (1,234.50).

A currency amount can display as ($1,234.50).

The converter also accepts a parenthesized value as input and converts it to the corresponding negative number.

When you leave the property set to false, Oracle JET uses the active locale to determine the standard negative-number representation.

After you change the setting, reload Billing Care or start a new UI session so newly created converters use the updated configuration.