From 5cc00344e2ed7736887a718bf5ddb2b25d1dc357 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 27 Nov 2023 13:06:58 -0300 Subject: DD51 look for currency symbol and split between small and normal --- packages/taler-util/src/amounts.ts | 65 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-) (limited to 'packages') diff --git a/packages/taler-util/src/amounts.ts b/packages/taler-util/src/amounts.ts index 5c6444b00..76ba3a0c5 100644 --- a/packages/taler-util/src/amounts.ts +++ b/packages/taler-util/src/amounts.ts @@ -30,6 +30,7 @@ import { DecodingError, renderContext, } from "./codec.js"; +import { CurrencySpecification } from "./index.js"; import { AmountString } from "./taler-types.js"; /** @@ -49,6 +50,11 @@ export const amountFractionalLength = 8; */ export const amountMaxValue = 2 ** 52; +/** + * Separator character between interger and fractional + */ +export const FRAC_SEPARATOR = "." + /** * Non-negative financial amount. Fractional values are expressed as multiples * of 1e-8. @@ -373,7 +379,7 @@ export class Amounts { if (!res) { return undefined; } - const tail = res[3] || ".0"; + const tail = res[3] || (FRAC_SEPARATOR + "0"); if (tail.length > amountFractionalLength + 1) { return undefined; } @@ -508,7 +514,7 @@ export class Amounts { let s = av.toString(); if (af || minFractional) { - s = s + "."; + s = s + FRAC_SEPARATOR; let n = af; for (let i = 0; i < amountFractionalLength; i++) { if (!n && i >= minFractional) { @@ -543,4 +549,59 @@ export class Amounts { } return amountFractionalLength - i + 1; } + + + static stringifyValueWithSpec(value: AmountJson, spec: CurrencySpecification): { currency: string, normal: string, small?: string } { + const strValue = Amounts.stringifyValue(value) + const pos = strValue.indexOf(FRAC_SEPARATOR) + const originalPosition = pos < 0 ? strValue.length : pos; + + let currency = value.currency + const names = Object.keys(spec.alt_unit_names) + let FRAC_POS_NEW_POSITION = originalPosition + //find symbol + //FIXME: this should be based on a cache to speed up + if (names.length > 0) { + let unitIndex: string = "0" //default entry by DD51 + names.forEach(index => { + const i = Number.parseInt(index, 10) + if (Number.isNaN(i)) return; //skip + if (originalPosition - i <= 0) return; //too big + if (originalPosition - i < FRAC_POS_NEW_POSITION) { + FRAC_POS_NEW_POSITION = originalPosition - i; + unitIndex = index + } + }) + currency = spec.alt_unit_names[unitIndex] + } + + if (originalPosition === FRAC_POS_NEW_POSITION) { + const { normal, small } = splitNormalAndSmall(strValue, originalPosition, spec) + return { currency, normal, small } + } + + const intPart = strValue.substring(0, originalPosition) + const fracPArt = strValue.substring(originalPosition + 1) + //indexSize is always smaller than originalPosition + const newValue = intPart.substring(0, FRAC_POS_NEW_POSITION) + FRAC_SEPARATOR + intPart.substring(FRAC_POS_NEW_POSITION) + fracPArt + const { normal, small } = splitNormalAndSmall(newValue, FRAC_POS_NEW_POSITION, spec) + return { currency, normal, small } + } + + +} + +function splitNormalAndSmall(decimal: string, fracSeparatorIndex: number, spec: CurrencySpecification): { normal: string, small?: string } { + let normal: string; + let small: string | undefined; + if (decimal.length - fracSeparatorIndex - 1 > spec.num_fractional_normal_digits) { + const limit = fracSeparatorIndex + spec.num_fractional_normal_digits + 1 + normal = decimal.substring(0, limit) + small = decimal.substring(limit) + } else { + normal = decimal + small = undefined + } + return { normal, small } } + -- cgit v1.2.3