-
Notifications
You must be signed in to change notification settings - Fork 0
/
tax.go
93 lines (73 loc) · 1.99 KB
/
tax.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
package mongo
import (
"encoding/json"
"fmt"
"strings"
"golang.org/x/exp/slices"
)
type detail map[string]Money
// Adds a new tax to the detail collection.
// If the tax description exists the money value will be added to it.
// This method returns a new map to make sure this operation is immutable
// across price types.
func (d detail) add(desc string, m Money) detail {
result := make(map[string]Money, 0)
for k, v := range d {
result[k] = v
}
if _, ok := result[desc]; ok {
result[desc] = result[desc].Add(m)
} else {
result[desc] = m
}
return result
}
// Mul multiplies all the values in the tax details collection by the passed
// amount.
func (d detail) mul(n int64) detail {
result := make(map[string]Money, 0)
for k, v := range d {
result[k] = v.Mul(n)
}
return result
}
// MarshalJSON is an implementation of json.Marshaller.
func (d detail) MarshalJSON() ([]byte, error) {
json := make([]string, 0)
for k, v := range d {
json = append(json, fmt.Sprintf(`{"amount": "%s", "description": "%s"}`, v.String(), k))
}
// Because the json map's order is non-deterministic, sort for deterministic output.
slices.Sort(json)
return []byte("[" + strings.Join(json, ",") + "]"), nil
}
// Taxes is a structure that holds the taxes information of a price.
type taxes struct {
total Money // The total tax.
detail detail // The breakdown of individual taxes.
}
// Add adds a new tax to the taxes collection.
func (t taxes) add(desc string, m Money) taxes {
t.detail = t.detail.add(desc, m)
t.total = t.total.Add(m)
return t
}
// Mul multiplies taxes in the taxes collection.
func (t taxes) mul(n int64) taxes {
t.detail = t.detail.mul(n)
t.total = t.total.Mul(n)
return t
}
// MarshalJSON is an implementation of json.Marshaller.
func (t taxes) MarshalJSON() ([]byte, error) {
detail, err := json.Marshal(t.detail)
if err != nil {
return []byte{}, err
}
json := fmt.Sprintf(
`{"total": "%s", "detail": %s}`,
t.total.String(),
detail,
)
return []byte(json), nil
}