money

package
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 9, 2025 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package money provides functionality for handling monetary values.

It is a value object that represents a monetary value in a specific currency. Invariants:

  • Amount is always stored in the smallest currency unit (e.g., cents for USD).
  • Currency code must be valid ISO 4217 (3 uppercase letters).
  • All arithmetic operations require matching currencies.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrExchangeRateUnavailable indicates the exchange rate service is unreachable or down.
	ErrExchangeRateUnavailable = errors.New("exchange rate service unavailable")

	// ErrUnsupportedCurrencyPair indicates the currency pair is not supported.
	ErrUnsupportedCurrencyPair = errors.New("unsupported currency pair")

	// ErrExchangeRateExpired indicates the exchange rate data is stale or expired.
	ErrExchangeRateExpired = errors.New("exchange rate has expired")

	// ErrExchangeRateInvalid indicates the received exchange rate is invalid.
	ErrExchangeRateInvalid = errors.New("invalid exchange rate received")
)

Functions

This section is empty.

Types

type Amount

type Amount = int64

Amount represents a monetary amount as an integer in the smallest currency unit (e.g., cents for USD).

type CurrencyConverter

type CurrencyConverter interface {
	// Convert converts an amount from one currency to another.
	// Returns the converted amount and the rate used, or an error if conversion is not possible.
	Convert(amount float64, from, to string) (*common.ConversionInfo, error)

	// GetRate returns the current exchange rate between two currencies.
	// This is useful for displaying rates without performing a conversion.
	GetRate(from, to string) (float64, error)

	// IsSupported checks if a currency pair is supported by the converter.
	IsSupported(from, to string) bool
}

CurrencyConverter defines the interface for converting amounts between currencies.

type ExchangeRate

type ExchangeRate struct {
	FromCurrency string
	ToCurrency   string
	Rate         float64
	LastUpdated  time.Time
	Source       string
	ExpiresAt    time.Time
}

ExchangeRate represents a single exchange rate with metadata.

type Money

type Money struct {
	// contains filtered or unexported fields
}

Money represents a monetary value in a specific currency. Invariants:

  • Amount is always stored in the smallest currency unit (e.g., cents for USD).
  • Currency code must be valid ISO 4217 (3 uppercase letters).
  • All arithmetic operations require matching currencies.
Example (Comparison)

ExampleMoney_Comparison demonstrates comparing money values

// Create two USD amounts
money1, _ := New(100.50, currency.USD)
money2, _ := New(75.25, currency.USD)

// Compare them
greater, _ := money1.GreaterThan(money2)
equal := money1.Equals(money2)
less, _ := money1.LessThan(money2)

fmt.Printf("Greater than: %t\n", greater)
fmt.Printf("Equal: %t\n", equal)
fmt.Printf("Less than: %t\n", less)
Output:

Greater than: true
Equal: false
Less than: false

func ConvertMoney

func ConvertMoney(
	converter CurrencyConverter,
	m Money,
	to string,
) (Money, *common.ConversionInfo, error)

ConvertMoney converts a Money value object to the target currency using the converter. Returns a new Money object in the target currency and the conversion info.

func Must

func Must(amount float64, currencyCode currency.Code) Money

Must creates a Money object from the given amount and currency code. Invariants enforced:

  • Currency code must be valid ISO 4217 (3 uppercase letters).
  • Amount must not have more decimal places than allowed by the currency.
  • Amount is converted to the smallest currency unit.

Panics if any invariant is violated.

func New

func New(
	amount float64,
	currencyCode currency.Code,
) (
	money Money,
	err error,
)

New creates a new Money value object with the given amount and currency code. Invariants enforced:

  • Currency code must be valid ISO 4217 (3 uppercase letters).
  • Amount must not have more decimal places than allowed by the currency.
  • Amount is converted to the smallest currency unit.

Returns Money or an error if any invariant is violated.

Example

ExampleNew demonstrates how to create a new Money instance

// Create money with USD
usdMoney, err := New(100.50, currency.USD)
if err != nil {
	log.Fatal(err)
}
fmt.Printf("USD Money: %s\n", usdMoney.String())

// Create money with EUR
eurMoney, err := New(75.25, currency.EUR)
if err != nil {
	log.Fatal(err)
}
fmt.Printf("EUR Money: %s\n", eurMoney.String())

// Create money with JPY (0 decimals)
jpyMoney, err := New(1000, currency.Code("JPY"))
if err != nil {
	log.Fatal(err)
}
fmt.Printf("JPY Money: %s\n", jpyMoney.String())
Output:

USD Money: 100.50 USD
EUR Money: 75.25 EUR
JPY Money: 1000 JPY

func NewFromData

func NewFromData(amount int64, cc string) Money

NewFromData creates a Money object from raw data (used for DB hydration). This bypasses invariants and should only be used for repository hydration or tests. Deprecated: use NewFromSmallestUnit instead.

func NewFromSmallestUnit

func NewFromSmallestUnit(
	amount int64,
	currencyCode currency.Code,
) (
	money Money,
	err error,
)

NewFromSmallestUnit creates a new Money object from the smallest currency unit. Invariants enforced:

  • Currency code must be valid ISO 4217 (3 uppercase letters).

Returns Money or an error if any invariant is violated.

Example

ExampleNewFromSmallestUnit demonstrates creating money from smallest unit

// Create USD money from cents (smallest unit)
usdMoney, err := NewFromSmallestUnit(10050, currency.USD) // 100.50 USD
if err != nil {
	log.Fatal(err)
}
fmt.Printf("USD from cents: %s\n", usdMoney.String())

// Create JPY money from yen (smallest unit)
jpyMoney, err := NewFromSmallestUnit(1000, currency.Code("JPY")) // 1000 JPY
if err != nil {
	log.Fatal(err)
}
fmt.Printf("JPY from yen: %s\n", jpyMoney.String())
Output:

USD from cents: 100.50 USD
JPY from yen: 1000 JPY

func Zero

func Zero(cur currency.Code) Money

Zero creates a Money object with zero amount in the specified currency.

func (Money) Abs

func (m Money) Abs() Money

Abs returns the absolute value of the Money amount.

func (Money) Add

func (m Money) Add(other Money) (Money, error)

Add adds another Money object to the current Money object. Invariants enforced:

  • Currencies must match.

Returns Money or an error if currencies do not match.

Example

ExampleMoney_Add demonstrates adding money values

// Create two USD amounts
money1, _ := New(100.50, currency.USD)
money2, _ := New(25.75, currency.USD)

// Add them together
result, err := money1.Add(money2)
if err != nil {
	log.Fatal(err)
}
fmt.Printf("Result: %s\n", result.String())
Output:

Result: 126.25 USD

func (Money) Amount

func (m Money) Amount() Amount

Amount returns the amount of the Money object in the smallest currency unit.

Example

ExampleMoney_Amount demonstrates getting the amount

// Create money with different amounts
money1, _ := New(100.50, currency.USD)
money2, _ := New(1000, currency.Code("JPY"))

fmt.Printf("USD amount: %.2f\n", money1.AmountFloat())
fmt.Printf("JPY amount: %.0f\n", money2.AmountFloat())
Output:

USD amount: 100.50
JPY amount: 1000

func (Money) AmountFloat

func (m Money) AmountFloat() float64

AmountFloat returns the amount as a float64 in the main currency unit (e.g., dollars for USD). Invariants enforced:

  • Currency metadata must be valid.
Example

ExampleMoney_AmountFloat demonstrates getting the amount as float64

// Create money with different amounts
money1, _ := New(100.50, currency.USD)
money2, _ := New(1000, currency.Code("JPY"))

fmt.Printf("USD amount float: %.2f\n", money1.AmountFloat())
fmt.Printf("JPY amount float: %.0f\n", money2.AmountFloat())
Output:

USD amount float: 100.50
JPY amount float: 1000

func (Money) Currency

func (m Money) Currency() currency.Code

Currency returns the currency of the Money object.

Example

ExampleMoney_Currency demonstrates getting the currency

// Create money with different currencies
usdMoney, _ := New(100.50, currency.USD)
eurMoney, _ := New(75.25, currency.EUR)
jpyMoney, _ := New(1000, currency.Code("JPY"))

fmt.Printf("USD Money currency: %s\n", usdMoney.Currency())
fmt.Printf("EUR Money currency: %s\n", eurMoney.Currency())
fmt.Printf("JPY Money currency: %s\n", jpyMoney.Currency())
Output:

USD Money currency: USD
EUR Money currency: EUR
JPY Money currency: JPY

func (Money) Divide

func (m Money) Divide(divisor float64) (Money, error)

Divide divides the Money amount by a scalar divisor. Invariants enforced:

  • Divisor must not be zero.
  • Result must not overflow int64.
  • Division must not lose precision.

Returns Money or an error if any invariant is violated.

Example

ExampleMoney_Divide demonstrates dividing money by a factor

// Create USD amount
money, _ := New(100.50, currency.USD)

// Divide by 2
result, err := money.Divide(2)
if err != nil {
	log.Fatal(err)
}
fmt.Printf("Result: %s\n", result.String())
Output:

Result: 50.25 USD

func (Money) Equals

func (m Money) Equals(other Money) bool

Equals checks if the current Money object is equal to another Money object. Invariants enforced:

  • Currencies must match.

Returns false if currencies do not match.

func (Money) GreaterThan

func (m Money) GreaterThan(other Money) (bool, error)

GreaterThan checks if the current Money object is greater than another Money object. Invariants enforced:

  • Currencies must match.

Returns an error if currencies do not match.

func (Money) IsCurrency

func (m Money) IsCurrency(code string) bool

Is checks the currency code if the same as money object

func (Money) IsNegative

func (m Money) IsNegative() bool

IsNegative returns true if the amount is less than zero.

func (Money) IsPositive

func (m Money) IsPositive() bool

IsPositive returns true if the amount is greater than zero.

Example

ExampleMoney_IsPositive demonstrates checking if money is positive

// Create positive and negative amounts
positive, _ := New(100.50, currency.USD)
negative, _ := New(-25.75, currency.USD)
zero, _ := New(0, currency.USD)

fmt.Printf("Positive amount is positive: %t\n", positive.IsPositive())
fmt.Printf("Negative amount is positive: %t\n", negative.IsPositive())
fmt.Printf("Zero amount is positive: %t\n", zero.IsPositive())
Output:

Positive amount is positive: true
Negative amount is positive: false
Zero amount is positive: false

func (Money) IsSameCurrency

func (m Money) IsSameCurrency(other Money) bool

IsSameCurrency checks if the current Money object has the same currency as another Money object.

func (Money) IsZero

func (m Money) IsZero() bool

IsZero returns true if the amount is zero.

Example

ExampleMoney_IsZero demonstrates checking if money is zero

// Create positive and zero amounts
positive, _ := New(100.50, currency.USD)
zero, _ := New(0, currency.USD)

fmt.Printf("Positive amount is zero: %t\n", positive.IsZero())
fmt.Printf("Zero amount is zero: %t\n", zero.IsZero())
Output:

Positive amount is zero: false
Zero amount is zero: true

func (Money) LessThan

func (m Money) LessThan(other Money) (bool, error)

LessThan checks if the current Money object is less than another Money object. Invariants enforced:

  • Currencies must match.

Returns an error if currencies do not match.

func (Money) MarshalJSON

func (m Money) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler interface.

func (Money) Multiply

func (m Money) Multiply(factor float64) (Money, error)

Multiply multiplies the Money amount by a scalar factor. Invariants enforced:

  • Result must not overflow int64.

Returns Money or an error if overflow would occur.

Example

ExampleMoney_Multiply demonstrates multiplying money by a factor

// Create USD amount
money, _ := New(100.50, currency.USD)

// Multiply by 2.5
result, err := money.Multiply(2.5)
if err != nil {
	log.Fatal(err)
}
fmt.Printf("Result: %s\n", result.String())
Output:

Result: 251.25 USD

func (Money) Negate

func (m Money) Negate() Money

Negate negates the current Money object.

func (Money) String

func (m Money) String() string

String returns a string representation of the Money object.

Example

ExampleMoney_String demonstrates string representation

// Create money with different currencies
usdMoney, _ := New(100.50, currency.USD)
eurMoney, _ := New(75.25, currency.EUR)
jpyMoney, _ := New(1000, currency.Code("JPY"))

fmt.Printf("USD: %s\n", usdMoney.String())
fmt.Printf("EUR: %s\n", eurMoney.String())
fmt.Printf("JPY: %s\n", jpyMoney.String())
Output:

USD: 100.50 USD
EUR: 75.25 EUR
JPY: 1000 JPY

func (Money) Subtract

func (m Money) Subtract(other Money) (Money, error)

Subtract subtracts another Money object from the current Money object. Invariants enforced:

  • Currencies must match.

Returns Money or an error if currencies do not match.

Example

ExampleMoney_Subtract demonstrates subtracting money values

// Create two USD amounts
money1, _ := New(100.50, currency.USD)
money2, _ := New(25.75, currency.USD)

// Subtract the second from the first
result, err := money1.Subtract(money2)
if err != nil {
	log.Fatal(err)
}
fmt.Printf("Result: %s\n", result.String())
Output:

Result: 74.75 USD

func (*Money) UnmarshalJSON

func (m *Money) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler interface.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL