All files / modules/75-ce/utils formatCost.ts

100% Statements 24/24
100% Branches 10/10
100% Functions 3/3
100% Lines 24/24

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102                                24x             24x 24x 24x 24x                   24x             329x             24x 355x 355x 26x     329x 9x 9x                                   329x 11x 11x 3x     8x 3x     5x 3x       320x                 24x  
/*
 * Copyright 2022 Harness Inc. All rights reserved.
 * Use of this source code is governed by the PolyForm Shield 1.0.0 license
 * that can be found in the licenses directory at the root of this repository, also available at
 * https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt.
 */
 
interface FormatCostOptions {
  currency?: string
  locale?: string
  decimalPoints?: number
  shortFormat?: boolean
}
 
type FormatCost = (value: number, options?: FormatCostOptions) => string
 
const defaultOptions = {
  shortFormat: false,
  currency: 'USD',
  locale: 'en-us',
  decimalPoints: 2
}
 
const TOTAL_DIGITS_TO_SHOW = 3
const POWER_OF_TEN_IN_BILLION = 9
const POWER_OF_TEN_IN_MILLION = 6
const POWER_OF_TEN_IN_THOUSANDS = 3
 
type convertNumberToLocaleStringType = (
  value: number,
  locale: string,
  currency: string,
  maximumFractionDigits: number,
  minimumFractionDigits: number
) => string
 
const convertNumberToLocaleString: convertNumberToLocaleStringType = (
  value,
  locale,
  currency,
  maximumFractionDigits,
  minimumFractionDigits
) =>
  value.toLocaleString(locale, {
    style: 'currency',
    currency,
    maximumFractionDigits,
    minimumFractionDigits
  })
 
const formatCost: FormatCost = (value: number, options?: FormatCostOptions) => {
  const costOptions = { ...defaultOptions, ...options }
  if (isNaN(value)) {
    return ''
  }
 
  const getCostInShortFormat = (power: number, cost: number, suffix: string, numberOfDigits: number) => {
    const decimalPlacesToHave = Math.max(power + TOTAL_DIGITS_TO_SHOW - numberOfDigits, 0)
    return (
      convertNumberToLocaleString(
        cost / Math.pow(10, power),
        costOptions.locale,
        costOptions.currency,
        decimalPlacesToHave,
        decimalPlacesToHave
      ) + suffix
    )
  }
 
  /**
    Option shortFormat will convert the cost as mentioned below -
    2,345,456 as $2.34M
    12,345,456 as $12.3M
    123,456,789 as $123M
    and so on for thousands and billions
  */
  if (costOptions.shortFormat) {
    const numberOfDigits = value.toFixed(0).length
    if (numberOfDigits > POWER_OF_TEN_IN_BILLION) {
      return getCostInShortFormat(POWER_OF_TEN_IN_BILLION, value, 'B', numberOfDigits)
    }
 
    if (numberOfDigits > 6) {
      return getCostInShortFormat(POWER_OF_TEN_IN_MILLION, value, 'M', numberOfDigits)
    }
 
    if (numberOfDigits > 3) {
      return getCostInShortFormat(POWER_OF_TEN_IN_THOUSANDS, value, 'K', numberOfDigits)
    }
  }
 
  return convertNumberToLocaleString(
    value,
    costOptions.locale,
    costOptions.currency,
    costOptions.decimalPoints,
    costOptions.decimalPoints
  )
}
 
export default formatCost