1package faker
  2
  3import (
  4	"fmt"
  5	"math"
  6	"reflect"
  7
  8	"github.com/go-faker/faker/v4/pkg/options"
  9)
 10
 11// Currency Codes | Source: https://en.wikipedia.org/wiki/ISO_4217
 12var currencies = []string{
 13	"AED", "AFN", "ALL", "AMD", "ANG", "AOA", "ARS", "AUD", "AWG",
 14	"AZN", "BAM", "BBD", "BDT", "BGN", "BHD", "BIF", "BMD", "BND",
 15	"BOB", "BOV", "BRL", "BSD", "BTN", "BWP", "BYN", "BZD", "CAD",
 16	"CDF", "CHE", "CHF", "CHW", "CLF", "CLP", "CNY", "COP", "COU",
 17	"CRC", "CUC", "CUP", "CVE", "CZK", "DJF", "DKK", "DOP", "DZD",
 18	"EGP", "ERN", "ETB", "EUR", "FJD", "FKP", "GBP", "GEL", "GHS",
 19	"GIP", "GMD", "GNF", "GTQ", "GYD", "HKD", "HNL", "HRK", "HTG",
 20	"HUF", "IDR", "ILS", "INR", "IQD", "IRR", "ISK", "JMD", "JOD",
 21	"JPY", "KES", "KGS", "KHR", "KMF", "KPW", "KRW", "KWD", "KYD",
 22	"KZT", "LAK", "LBP", "LKR", "LRD", "LSL", "LYD", "MAD", "MDL",
 23	"MGA", "MKD", "MMK", "MNT", "MOP", "MRU", "MUR", "MVR", "MWK",
 24	"MXN", "MXV", "MYR", "MZN", "NAD", "NGN", "NIO", "NOK", "NPR",
 25	"NZD", "OMR", "PAB", "PEN", "PGK", "PHP", "PKR", "PLN", "PYG",
 26	"QAR", "RON", "RSD", "RUB", "RWF", "SAR", "SBD", "SCR", "SDG",
 27	"SEK", "SGD", "SHP", "SLL", "SOS", "SRD", "SSP", "STN", "SVC",
 28	"SYP", "SZL", "THB", "TJS", "TMT", "TND", "TOP", "TRY", "TTD",
 29	"TWD", "TZS", "UAH", "UGX", "USD", "USN", "UYI", "UYU", "UYW",
 30	"UZS", "VES", "VND", "VUV", "WST", "XAF", "XAG", "XAU", "XBA",
 31	"XBB", "XBC", "XBD", "XCD", "XDR", "XOF", "XPD", "XPF", "XPT",
 32	"XSU", "XTS", "XUA", "XXX", "YER", "ZAR", "ZMW", "ZWL",
 33}
 34
 35// Money provides an interface to generate a custom price with or without a random currency code
 36type Money interface {
 37	Currency(v reflect.Value) (interface{}, error)
 38	Amount(v reflect.Value) (interface{}, error)
 39	AmountWithCurrency(v reflect.Value) (interface{}, error)
 40}
 41
 42// Price struct
 43type Price struct {
 44}
 45
 46// GetPrice returns a new Money interface of Price struct
 47func GetPrice() Money {
 48	return &Price{}
 49}
 50
 51func (p Price) currency() string {
 52	return randomElementFromSliceString(currencies)
 53}
 54
 55// Currency returns a random currency from currencies
 56func (p Price) Currency(v reflect.Value) (interface{}, error) {
 57	return p.currency(), nil
 58}
 59
 60// Currency get fake Currency (IDR, USD)
 61func Currency(opts ...options.OptionFunc) string {
 62	return singleFakeData(CurrencyTag, func() interface{} {
 63		p := Price{}
 64		return p.currency()
 65	}, opts...).(string)
 66}
 67
 68func (p Price) amount() float64 {
 69	return precision(rand.Float64()*math.Pow10(rand.Intn(8)), rand.Intn(2)+1)
 70}
 71
 72// Amount returns a random floating price amount
 73// with a random precision of [1,2] up to (10**8 - 1)
 74func (p Price) Amount(v reflect.Value) (interface{}, error) {
 75	kind := v.Kind()
 76	val := p.amount()
 77	if kind == reflect.Float32 {
 78		v.Set(reflect.ValueOf(float32(val)))
 79		return float32(val), nil
 80	}
 81	v.Set(reflect.ValueOf(val))
 82	return val, nil
 83}
 84
 85func (p Price) amountwithcurrency() string {
 86	val := p.amount()
 87	return fmt.Sprintf("%s %f", p.currency(), val)
 88}
 89
 90// AmountWithCurrency combines both price and currency together
 91func (p Price) AmountWithCurrency(v reflect.Value) (interface{}, error) {
 92	return p.amountwithcurrency(), nil
 93}
 94
 95// AmountWithCurrency get fake AmountWithCurrency  USD 49257.100
 96func AmountWithCurrency(opts ...options.OptionFunc) string {
 97	return singleFakeData(AmountWithCurrencyTag, func() interface{} {
 98		p := Price{}
 99		return p.amountwithcurrency()
100	}, opts...).(string)
101}
102
103// precision | a helper function to set precision of price
104func precision(val float64, pre int) float64 {
105	div := math.Pow10(pre)
106	return float64(int64(val*div)) / div
107}