Currency Input Field Rounding Issues with Decimal Values Above 10,000 (Ex.: 200,300.57) - Need Plugin Recommendation

I'm working on a custom currency input field component and facing a challenging issue with decimal value conversion and rounding when values exceed 10,000 (5+ digits).

Here's my current implementation:

a!localVariables(
  a!textField(
    label: ri!label,
    labelPosition: a!defaultValue(ri!labelPosition, "ABOVE"),
    value: a!currency(
      isoCode: a!defaultValue(ri!isoCode, "BRL"),
      value: rule!process_BRLInputSanitizer(
        value: ri!value,
        toDecimal: true,
        showSeparators: false
      ),
      decimalPlaces: 2,
      showSeparators: true
    ),
    placeholder: ri!placeholder,
    saveInto: a!localVariables(
      {
        a!save(
          ri!value,
          a!currency(
            isoCode: a!defaultValue(ri!isoCode, "BRL"),
            value: rule!process_BRLInputSanitizer(
              value: save!value,
              toDecimal: true,
              showSeparators: false
            ),
            decimalPlaces: 2,
            showSeparators: true
          ),
          
        ),
        ri!saveInto
      }
    ),
    disabled: a!defaultValue(ri!disabled, false),
    readOnly: a!defaultValue(ri!readOnly, false),
    refreshAfter: "KEYPRESS",
    validations: { ri!validations },
    showWhen: a!defaultValue(ri!showWhen, true),
    instructions: ri!instructions,
    helpTooltip: ri!helpTooltip
  )
)

Supporting Rule (process_BRLInputSanitizer):

a!localVariables(
  local!toDecimal: a!defaultValue(ri!toDecimal, false),
  local!value: tostring(ri!value),
  local!left: substitute(local!value, ",", "."),
  local!right: substitute(local!value, ".", ","),
  local!result: if(
    local!toDecimal,
    concat(
      left(local!right, len(local!right) - 3),
      right(local!left, 3)
    ),
    concat(
      left(local!left, len(local!left) - 3),
      right(local!right, 3)
    )
  ),
  if(
    a!defaultValue(ri!showSeparators, true),
    local!result,
    if(
      local!toDecimal,
      substitute(local!result, ",", ""),
      substitute(local!result, ".", "")
    )
  )
)
The Problem: When the system casts the value back to a Decimal type, it rounds the value incorrectly when it exceeds 10,000 (5+ digits). I need the value to remain as a precise Decimal because my Record Type field that integrates with the backend requires decimal format.

Questions:

  1. Why does this rounding occur specifically when values exceed 5 digits?
  2. Is there an existing plugin or component that handles dynamic currency formatting (showing decimal separators while the user types) that maintains decimal precision?
  3. If such a plugin exists, it would save me from building this from scratch.

I'm essentially trying to create a currency input that displays proper formatting (R$323,845.27) while maintaining the underlying decimal value for record Type integration.

Any recommendations for existing solutions or insights into the rounding behavior would be greatly appreciated!

Thank you all for your time and assistance.

  Discussion posts and replies are publicly visible

Parents
  • 0
    Certified Lead Developer

    Appian's default way of displaying decimal numbers takes some sometimes unintuitive liberties with the number of significant figures shown - in ways that are a little unintuitive and opaque to not only the end user but also the designer (frustratingly).  I'm not exactly sure I'm comprehending the manual conversions you're with your utuility rule, but I was under the impression that a!currency() was supposed to handle things like "dots instead of commas and commas instead of dots" automatically for currencies that use opposing systems (though i haven't tested this).  BTW, are users not using locales that support the proper number entry system inherently?  I thought it worked without manual conversion when the locale was set right (also haven't personally tested though).

    My general advice at this point would be to go back to basics and make sure you're doing any manual conversion on a displayed number (versus the underlying decimal value) only at the very end, to avoid it becoming confused.

  • Yes, the currency formatter is meant to handle it, but it's automatically rounding the value when I convert it back to decimal, even though I don't want it to.

  • 0
    Certified Lead Developer
    in reply to Silas. B. Ferreira

    Could you provide a screenshot of an example of the output you're seeing and the actual underlying value that you'd expect to be seeing?

    Have you tried formatting the output through functions like 'text(value, "0.00")' to signify that you want the displayed output to show the entire number including 2 decimal places at all times?  Because as I said, when just displaying decimal data, Appian (badly) guesses at what level of significant digits should be displayed to the user.

  • I was just about to provide it

    I will try what you suggested in just a sec

Reply Children
  • 0
    Certified Lead Developer
    in reply to Silas. B. Ferreira

    So basically my prior answer is correct:

  • a!localVariables(
      local!amount,
      local!amountDecimal,
      a!textField(
        label: "Amount in Text",
        /* Instructions  show the saved datatype*/
        instructions: "Type of local!amount: " & typename(typeof(local!amount)),
        value: a!currency(
          isoCode: "BRL",
          value: local!amount,
          format: "SYMBOL"
        ),
        /* Instead of saving the value as text, a!save() is used to store to the desired datatype*/
        saveInto: {
          a!save(
            local!amountDecimal,
            text(todecimal(save!value), "#.##")
          ),
          a!save(local!amount, save!value)
        }
      )
    )

    Right, this method text() casts the value to text.

    However, I am wondering as well if, whenever it casts, Appian is gonna pass the real value when it's expected to be a decimal, or, it is simply going to round, and miss the decimals digits.

    For example: a recordType's field is a Decimal, so, when appian automatically converts the value to the decimal field in my grid `fv!item.field` (which expects a decimal but receives a casted value), is it gonna simply round or is it going to preserve the original value as sholud be (ex.: 400300.37 instead of 400300.4)?

     

  • 0
    Certified Lead Developer
    in reply to Silas. B. Ferreira
    However, I am wondering as well if Appian is gonna pass the real value when it's expected to be a decimal

    The "real value" is what's being stored in Appian, which is what I'm trying to show you.  The rounded value you're seeing in the local variables panel is merely a "user facing" output, not the internal value.