-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprice.go
112 lines (93 loc) · 2.24 KB
/
price.go
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
103
104
105
106
107
108
109
110
111
112
package twigots
import (
"encoding/json"
"fmt"
"math"
"strconv"
"github.com/orsinium-labs/enum"
)
type Price struct {
Currency Currency `json:"currencyCode"`
// Amount is the cost in Cents, Pennies etc.
// Prefer using `Number`
Amount int `json:"amountInCents"`
}
// Number is the numerical value of the price.
// E.g. Dollars, Pounds, Euros etc.
// Use this over `Amount“.
func (p Price) Number() float64 {
return float64(p.Amount) / 100
}
// The price as a string.
// e.g. $30.62
func (p Price) String() string {
return priceString(p.Number(), p.Currency)
}
// Add prices together. Currency will be kept.
// Returns a new price.
func (p Price) Add(other Price) Price {
return Price{
Currency: p.Currency,
Amount: p.Amount + other.Amount,
}
}
// Subtract price from another. Currency will be kept.
// Returns a new price.
func (p Price) Subtract(other Price) Price {
return Price{
Currency: p.Currency,
Amount: p.Amount - other.Amount,
}
}
// Multiply prices together. Returns a new price.
func (p Price) Multiply(num int) Price {
return Price{
Currency: p.Currency,
Amount: p.Amount * num,
}
}
// Divide prices. Currency will be kept.
// Returns a new price.
func (p Price) Divide(num int) Price {
return Price{
Currency: p.Currency,
Amount: int(math.Round(float64(p.Amount) / float64(num))),
}
}
func priceString(cost float64, currency Currency) string {
costString := strconv.FormatFloat(cost, 'f', 2, 64)
currencyString := currency.Symbol()
if currencyString == "" {
return costString + currency.Value
}
return currencyString + costString
}
var (
currency = enum.NewBuilder[string, Currency]()
CurrencyGBP = currency.Add(Currency{"GBP"})
Currencies = currency.Enum()
)
type Currency enum.Member[string]
// Symbol is the character that represents the currency
// e.g. $, £, €.
func (c Currency) Symbol() string {
switch c {
case CurrencyGBP:
return "£"
default:
return ""
}
}
func (c *Currency) UnmarshalJSON(data []byte) error {
var currencyString string
err := json.Unmarshal(data, ¤cyString)
if err != nil {
return err
}
currency := Currencies.Parse(currencyString)
if currency == nil {
return fmt.Errorf("currency '%s' is not valid", currencyString)
}
*c = *currency
return nil
}