-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathcharges.go
More file actions
134 lines (122 loc) · 3.69 KB
/
Copy pathcharges.go
File metadata and controls
134 lines (122 loc) · 3.69 KB
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package ubl
import (
"github.com/invopop/gobl/bill"
"github.com/invopop/gobl/catalogues/cef"
"github.com/invopop/gobl/catalogues/untdid"
"github.com/invopop/gobl/num"
"github.com/invopop/gobl/tax"
)
// AllowanceCharge represents an allowance or charge
type AllowanceCharge struct {
ChargeIndicator bool `xml:"cbc:ChargeIndicator"`
AllowanceChargeReasonCode *string `xml:"cbc:AllowanceChargeReasonCode"`
AllowanceChargeReason *string `xml:"cbc:AllowanceChargeReason"`
MultiplierFactorNumeric *string `xml:"cbc:MultiplierFactorNumeric"`
Amount Amount `xml:"cbc:Amount"`
BaseAmount *Amount `xml:"cbc:BaseAmount"`
TaxCategory []*TaxCategory `xml:"cac:TaxCategory"`
}
func (ui *Invoice) addCharges(inv *bill.Invoice) {
if inv.Charges == nil && inv.Discounts == nil {
return
}
var notes []*tax.Note
if inv.Tax != nil {
notes = inv.Tax.Notes
}
ui.AllowanceCharge = make([]AllowanceCharge, len(inv.Charges)+len(inv.Discounts))
// Use invoice sum (before discounts) as base amount for percentage calculations
baseAmount := inv.Totals.Sum
for i, ch := range inv.Charges {
ui.AllowanceCharge[i] = makeCharge(ch, string(inv.Currency), baseAmount, notes)
}
for i, d := range inv.Discounts {
ui.AllowanceCharge[i+len(inv.Charges)] = makeDiscount(d, string(inv.Currency), baseAmount, notes)
}
}
func makeCharge(ch *bill.Charge, ccy string, baseAmount num.Amount, notes []*tax.Note) AllowanceCharge {
c := AllowanceCharge{
ChargeIndicator: true,
Amount: Amount{
Value: ch.Amount.String(),
CurrencyID: &ccy,
},
}
if ch.Reason != "" {
c.AllowanceChargeReason = &ch.Reason
}
e := ch.Ext.Get(untdid.ExtKeyCharge).String()
if e != "" {
c.AllowanceChargeReasonCode = &e
}
if ch.Percent != nil {
p := ch.Percent.StringWithoutSymbol()
c.MultiplierFactorNumeric = &p
// Add BaseAmount when percentage is provided
c.BaseAmount = &Amount{
Value: baseAmount.String(),
CurrencyID: &ccy,
}
}
if ch.Taxes != nil {
c.TaxCategory = makeTaxCategory(ch.Taxes, notes)
}
return c
}
func makeDiscount(d *bill.Discount, ccy string, baseAmount num.Amount, notes []*tax.Note) AllowanceCharge {
c := AllowanceCharge{
ChargeIndicator: false,
Amount: Amount{
Value: d.Amount.String(),
CurrencyID: &ccy,
},
}
if d.Reason != "" {
c.AllowanceChargeReason = &d.Reason
}
e := d.Ext.Get(untdid.ExtKeyAllowance).String()
if e != "" {
c.AllowanceChargeReasonCode = &e
}
if d.Percent != nil {
p := d.Percent.StringWithoutSymbol()
c.MultiplierFactorNumeric = &p
// Add BaseAmount when percentage is provided
c.BaseAmount = &Amount{
Value: baseAmount.String(),
CurrencyID: &ccy,
}
}
if d.Taxes != nil {
c.TaxCategory = makeTaxCategory(d.Taxes, notes)
}
return c
}
func makeTaxCategory(taxes tax.Set, notes []*tax.Note) []*TaxCategory {
set := []*TaxCategory{}
for _, t := range taxes {
category := TaxCategory{}
category.TaxScheme = &TaxScheme{ID: IDType{Value: t.Category.String()}}
e := t.Ext.Get(untdid.ExtKeyTaxCategory).String()
if e != "" {
category.ID = &IDType{Value: e}
}
if v := t.Ext.Get(cef.ExtKeyVATEX).String(); v != "" {
category.TaxExemptionReasonCode = &v
}
if note := findTaxNote(notes, t.Category, t.Ext); note != nil {
category.TaxExemptionReason = ¬e.Text
}
// Set percent: required unless category is "O" (outside scope)
if t.Percent != nil {
p := t.Percent.StringWithoutSymbol()
category.Percent = &p
} else if category.ID == nil || category.ID.Value != "O" {
// Default to 0% when not outside scope
zero := "0"
category.Percent = &zero
}
set = append(set, &category)
}
return set
}