-
Notifications
You must be signed in to change notification settings - Fork 4
/
outlay.go
78 lines (72 loc) · 2.43 KB
/
outlay.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
package bill
import (
"encoding/json"
"github.com/invopop/gobl/cal"
"github.com/invopop/gobl/num"
"github.com/invopop/gobl/org"
"github.com/invopop/gobl/uuid"
"github.com/invopop/validation"
)
// Outlay represents a reimbursable expense that was paid for by the supplier and invoiced separately
// by the third party directly to the customer.
// Most suppliers will want to include the expenses of their providers as part of their
// own operational costs. However, outlays are common in countries like Spain where it is typical
// for an accountant or lawyer to pay for notary fees, but forward the invoice to the
// customer.
type Outlay struct {
uuid.Identify
// Outlay number index inside the invoice for ordering (calculated).
Index int `json:"i" jsonschema:"title=Index" jsonschema_extras:"calculated=true"`
// When was the outlay made.
Date *cal.Date `json:"date,omitempty" jsonschema:"title=Date"`
// Invoice number or other reference detail used to identify the outlay.
Code string `json:"code,omitempty" jsonschema:"title=Code"`
// Series of the outlay invoice.
Series string `json:"series,omitempty" jsonschema:"title=Series"`
// Details on what the outlay was.
Description string `json:"description" jsonschema:"title=Description"`
// Who was the supplier of the outlay
Supplier *org.Party `json:"supplier,omitempty" jsonschema:"title=Supplier"`
// Amount paid by the supplier.
Amount num.Amount `json:"amount" jsonschema:"title=Amount"`
}
// Validate ensures the outlay contains everything required.
func (o *Outlay) Validate() error {
return validation.ValidateStruct(o,
validation.Field(&o.UUID),
validation.Field(&o.Index, validation.Required),
validation.Field(&o.Date),
validation.Field(&o.Description, validation.Required),
validation.Field(&o.Supplier),
validation.Field(&o.Amount, validation.Required),
)
}
// UnmarshalJSON helps migrate the desc field to description.
func (o *Outlay) UnmarshalJSON(data []byte) error {
type Alias Outlay
aux := struct {
Desc string `json:"desc"`
*Alias
}{
Alias: (*Alias)(o),
}
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
if aux.Desc != "" {
o.Description = aux.Desc
}
return nil
}
func calculateOutlays(zero num.Amount, outlays []*Outlay) *num.Amount {
if len(outlays) == 0 {
return nil
}
total := zero
for i, o := range outlays {
o.Amount = o.Amount.MatchPrecision(zero)
o.Index = i + 1
total = total.Add(o.Amount)
}
return &total
}