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 ¶
- Variables
- type Amount
- type Code
- type Currency
- type CurrencyConverter
- type Money
- func (m *Money) Abs() *Money
- func (m *Money) Add(other *Money) (*Money, error)
- func (m *Money) Amount() Amount
- func (m *Money) AmountFloat() float64
- func (m *Money) Currency() Currency
- func (m *Money) CurrencyCode() Code
- func (m *Money) Divide(divisor float64) (*Money, error)
- func (m *Money) Equals(other *Money) bool
- func (m *Money) GreaterThan(other *Money) (bool, error)
- func (m *Money) IsCurrency(currency Currency) bool
- func (m *Money) IsNegative() bool
- func (m *Money) IsPositive() bool
- func (m *Money) IsSameCurrency(other *Money) bool
- func (m *Money) IsZero() bool
- func (m *Money) LessThan(other *Money) (bool, error)
- func (m Money) MarshalJSON() ([]byte, error)
- func (m *Money) Multiply(factor float64) (*Money, error)
- func (m *Money) Negate() *Money
- func (m *Money) String() string
- func (m *Money) Subtract(other *Money) (*Money, error)
- func (m *Money) UnmarshalJSON(data []byte) error
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrMismatchedCurrencies is returned when performing operations on money with // different currencies ErrMismatchedCurrencies = errors.New("mismatched currencies") // ErrNegativeAmount is returned when an operation would result in a negative amount ErrNegativeAmount = errors.New("resulting amount cannot be negative") )
Common money package errors
var ( // ErrInvalidAmount is returned when an invalid amount is provided. ErrInvalidAmount = fmt.Errorf("invalid amount float") // ErrAmountExceedsMaxSafeInt is returned when an amount exceeds the maximum safe integer value. ErrAmountExceedsMaxSafeInt = fmt.Errorf("amount exceeds maximum safe integer value") // ErrMismatchedCurrencies is returned when performing operations // on money with different currencies. ErrInvalidCurrency = fmt.Errorf("invalid currency code") )
var ( USDCurrency = Currency{Code: USD, Decimals: 2} EURCurrency = Currency{Code: EUR, Decimals: 2} GBPCurrency = Currency{Code: GBP, Decimals: 2} JPYCurrency = Currency{Code: JPY, Decimals: 0} // Japanese Yen has no decimal places )
Common currency instances
var DefaultCode = USD
DefaultCode is the default currency code (USD)
var DefaultCurrency = USDCurrency
DefaultCurrency is the default currency (USD)
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 Code ¶ added in v1.3.0
type Code string
Code represents a currency code (e.g., "USD", "EUR").
const ( USD Code = "USD" // US Dollar EUR Code = "EUR" // Euro JPY Code = "JPY" // Japanese Yen KWD Code = "KWD" // Kuwaiti Dinar GBP Code = "GBP" // British Pound )
Common currency codes
func (Code) ToCurrency ¶ added in v1.3.0
ToCurrency converts a Code to a Currency with default decimals
type Currency ¶ added in v1.3.0
type Currency struct {
Code Code // 3-letter ISO 4217 code (e.g., "USD")
Decimals int // Number of decimal places (0-8)
}
Currency represents a monetary unit with its standard decimal places
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 must be valid (valid ISO 4217 code and valid decimal places).
- All arithmetic operations require matching currencies.
Example (Comparison) ¶
ExampleMoney_Comparison demonstrates comparing money values
package main
import (
"fmt"
"github.com/amirasaad/fintech/pkg/money"
)
func main() {
// Create two USD amounts
money1, _ := money.New(100.50, money.USD)
money2, _ := money.New(75.25, money.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 Must ¶
Must creates a Money object from the given amount and currency. Invariants enforced:
- Currency must be valid (valid ISO 4217 code and valid decimal places).
- 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 ¶
New creates a new Money value object with the given amount and currency. The currency parameter can be either a Code, Currency, or string (e.g., "USD"). Invariants enforced:
- Currency must be valid (valid ISO 4217 code and valid decimal places).
- 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
package main
import (
"fmt"
"log"
"github.com/amirasaad/fintech/pkg/money"
)
func main() {
// Create money with USD
usdMoney, err := money.New(100.50, money.USD)
if err != nil {
log.Fatal(err)
}
fmt.Printf("USD Money: %s\n", usdMoney.String())
// Create money with EUR
eurMoney, err := money.New(75.25, money.EUR)
if err != nil {
log.Fatal(err)
}
fmt.Printf("EUR Money: %s\n", eurMoney.String())
// Create money with JPY (0 decimals)
jpyMoney, err := money.New(1000, money.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 ¶
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 ¶
NewFromSmallestUnit creates a new Money object from the smallest currency unit. The currency parameter can be either a Code or a Currency. Invariants enforced:
- Currency must be valid (valid ISO 4217 code and valid decimal places).
Returns Money or an error if any invariant is violated.
Example ¶
ExampleNewFromSmallestUnit demonstrates creating money from smallest unit
package main
import (
"fmt"
"log"
"github.com/amirasaad/fintech/pkg/money"
)
func main() {
// Create USD money from cents (smallest unit)
usdMoney, err := money.NewFromSmallestUnit(10050, money.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 := money.NewFromSmallestUnit(1000, money.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(currency interface{}) *Money
Zero creates a Money object with zero amount in the specified currency. The currency parameter can be either a Code or a Currency.
func (*Money) Add ¶
Add returns a new Money object with the sum of amounts. Invariants enforced:
- Currencies must match.
Example ¶
ExampleMoney_Add demonstrates adding money values
package main
import (
"fmt"
"log"
"github.com/amirasaad/fintech/pkg/money"
)
func main() {
// Create two USD amounts
money1, _ := money.New(100.50, money.USD)
money2, _ := money.New(25.75, money.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 ¶
Amount returns the amount of the Money object in the smallest currency unit.
Example ¶
ExampleMoney_Amount demonstrates getting the amount
package main
import (
"fmt"
"github.com/amirasaad/fintech/pkg/money"
)
func main() {
// Create money with different amounts
money1, _ := money.New(100.50, money.USD)
money2, _ := money.New(1000, money.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 ¶
AmountFloat returns the amount as a float64 in the main currency unit (e.g., dollars for USD).
Example ¶
ExampleMoney_AmountFloat demonstrates getting the amount as float64
package main
import (
"fmt"
"github.com/amirasaad/fintech/pkg/money"
)
func main() {
// Create money with different amounts
money1, _ := money.New(100.50, money.USD)
money2, _ := money.New(1000, money.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 ¶
Currency returns the currency of the Money object.
Example ¶
ExampleMoney_Currency demonstrates getting the currency
package main
import (
"fmt"
"github.com/amirasaad/fintech/pkg/money"
)
func main() {
// Create money with different currencies
usdMoney, _ := money.New(100.50, money.USD)
eurMoney, _ := money.New(75.25, money.EUR)
jpyMoney, _ := money.New(1000, money.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) CurrencyCode ¶ added in v1.3.0
CurrencyCode returns the currency code of the Money object.
func (*Money) Divide ¶
Divide divides the Money amount by a scalar divisor. The result is rounded to the nearest integer. Invariants enforced:
- Divisor must be positive.
Returns a new Money object or an error if the divisor is invalid.
Example ¶
ExampleMoney_Divide demonstrates dividing money by a factor
package main
import (
"fmt"
"log"
"github.com/amirasaad/fintech/pkg/money"
)
func main() {
// Create USD amount
money, _ := money.New(100.50, money.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 ¶
Equals checks if the current Money object is equal to another Money object. Invariants enforced:
- Currencies must match.
func (*Money) GreaterThan ¶
GreaterThan checks if the current Money object is greater than another Money object. Invariants enforced:
- Currencies must match.
func (*Money) IsCurrency ¶
IsCurrency checks if the money object has the specified currency
func (*Money) IsNegative ¶
IsNegative returns true if the Money is not nil and its amount is less than zero.
func (*Money) IsPositive ¶
IsPositive returns true if the Money is not nil and its amount is greater than zero.
Example ¶
ExampleMoney_IsPositive demonstrates checking if money is positive
package main
import (
"fmt"
"github.com/amirasaad/fintech/pkg/money"
)
func main() {
// Create positive and negative amounts
positive, _ := money.New(100.50, money.USD)
negative, _ := money.New(-25.75, money.USD)
zero, _ := money.New(0, money.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 ¶
IsSameCurrency checks if the current Money object has the same currency as another Money object.
func (*Money) IsZero ¶
IsZero returns true if the Money is nil or its amount is zero.
Example ¶
ExampleMoney_IsZero demonstrates checking if money is zero
package main
import (
"fmt"
"github.com/amirasaad/fintech/pkg/money"
)
func main() {
// Create positive and zero amounts
positive, _ := money.New(100.50, money.USD)
zero, _ := money.New(0, money.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 ¶
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 ¶
MarshalJSON implements json.Marshaler interface.
func (*Money) Multiply ¶
Multiply multiplies the Money amount by a scalar factor. The result is rounded to the nearest integer. Invariants enforced:
- Factor must not be negative.
- Result must not overflow int64.
Returns a new Money object or an error if the factor is invalid or would cause overflow.
Example ¶
ExampleMoney_Multiply demonstrates multiplying money by a factor
package main
import (
"fmt"
"log"
"github.com/amirasaad/fintech/pkg/money"
)
func main() {
// Create USD amount
money, _ := money.New(100.50, money.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) String ¶
String returns a string representation of the Money object.
Example ¶
ExampleMoney_String demonstrates string representation
package main
import (
"fmt"
"github.com/amirasaad/fintech/pkg/money"
)
func main() {
// Create money with different currencies
usdMoney, _ := money.New(100.50, money.USD)
eurMoney, _ := money.New(75.25, money.EUR)
jpyMoney, _ := money.New(1000, money.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 ¶
Subtract returns a new Money object with the difference of amounts. The result can be negative if the subtrahend is larger than the minuend. Invariants enforced:
- Currencies must match.
Example ¶
ExampleMoney_Subtract demonstrates subtracting money values
package main
import (
"fmt"
"log"
"github.com/amirasaad/fintech/pkg/money"
)
func main() {
// Create two USD amounts
money1, _ := money.New(100.50, money.USD)
money2, _ := money.New(25.75, money.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 ¶
UnmarshalJSON implements json.Unmarshaler interface.