billing.go raw
1 package govultr
2
3 import (
4 "context"
5 "fmt"
6 "net/http"
7
8 "github.com/google/go-querystring/query"
9 )
10
11 // BillingService is the interface to interact with the billing endpoint on the Vultr API
12 // Link : https://www.vultr.com/api/#tag/billing
13 type BillingService interface {
14 ListHistory(ctx context.Context, options *ListOptions) ([]History, *Meta, *http.Response, error)
15 ListInvoices(ctx context.Context, options *ListOptions) ([]Invoice, *Meta, *http.Response, error)
16 GetInvoice(ctx context.Context, invoiceID string) (*Invoice, *http.Response, error)
17 ListInvoiceItems(ctx context.Context, invoiceID int, options *ListOptions) ([]InvoiceItem, *Meta, *http.Response, error)
18 ListPendingCharges(ctx context.Context, options *ListOptions) ([]InvoiceItem, *http.Response, error)
19 }
20
21 // BillingServiceHandler handles interaction with the billing methods for the Vultr API
22 type BillingServiceHandler struct {
23 client *Client
24 }
25
26 // History represents a billing history item on an account
27 type History struct {
28 ID int `json:"id"`
29 Date string `json:"date"`
30 Type string `json:"type"`
31 Description string `json:"description"`
32 Amount float32 `json:"amount"`
33 Balance float32 `json:"balance"`
34 }
35
36 // Invoice represents an invoice on an account
37 type Invoice struct {
38 ID int `json:"id"`
39 Date string `json:"date"`
40 Description string `json:"description"`
41 Amount float32 `json:"amount"`
42 Balance float32 `json:"balance"`
43 }
44
45 // InvoiceItem represents an item on an accounts invoice
46 type InvoiceItem struct {
47 Description string `json:"description"`
48 Product string `json:"product"`
49 StartDate string `json:"start_date"`
50 EndDate string `json:"end_date"`
51 Units int `json:"units"`
52 UnitType string `json:"unit_type"`
53 UnitPrice float32 `json:"unit_price"`
54 Total float32 `json:"total"`
55 }
56
57 type billingHistoryBase struct {
58 History []History `json:"billing_history"`
59 Meta *Meta `json:"meta"`
60 }
61
62 type invoicesBase struct {
63 Invoice []Invoice `json:"billing_invoices"`
64 Meta *Meta `json:"meta"`
65 }
66
67 type invoiceBase struct {
68 Invoice *Invoice `json:"billing_invoice"`
69 }
70
71 type invoiceItemsBase struct {
72 InvoiceItems []InvoiceItem `json:"invoice_items"`
73 Meta *Meta `json:"meta"`
74 }
75
76 type pendingChargesBase struct {
77 PendingCharges []InvoiceItem `json:"pending_charges"`
78 }
79
80 // ListHistory retrieves a list of all billing history on the current account
81 func (b *BillingServiceHandler) ListHistory(ctx context.Context, options *ListOptions) ([]History, *Meta, *http.Response, error) { //nolint:dupl,lll
82 uri := "/v2/billing/history"
83 req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
84 if err != nil {
85 return nil, nil, nil, err
86 }
87
88 newValues, err := query.Values(options)
89 if err != nil {
90 return nil, nil, nil, err
91 }
92
93 req.URL.RawQuery = newValues.Encode()
94
95 invoices := new(billingHistoryBase)
96 resp, err := b.client.DoWithContext(ctx, req, invoices)
97 if err != nil {
98 return nil, nil, resp, err
99 }
100
101 return invoices.History, invoices.Meta, resp, nil
102 }
103
104 // ListInvoices retrieves a list of all billing invoices on the current account
105 func (b *BillingServiceHandler) ListInvoices(ctx context.Context, options *ListOptions) ([]Invoice, *Meta, *http.Response, error) { //nolint:dupl,lll
106 uri := "/v2/billing/invoices"
107 req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
108 if err != nil {
109 return nil, nil, nil, err
110 }
111
112 newValues, err := query.Values(options)
113 if err != nil {
114 return nil, nil, nil, err
115 }
116
117 req.URL.RawQuery = newValues.Encode()
118
119 invoices := new(invoicesBase)
120 resp, err := b.client.DoWithContext(ctx, req, invoices)
121 if err != nil {
122 return nil, nil, resp, err
123 }
124
125 return invoices.Invoice, invoices.Meta, resp, nil
126 }
127
128 // GetInvoice retrieves an invoice that matches the given invoiceID
129 func (b *BillingServiceHandler) GetInvoice(ctx context.Context, invoiceID string) (*Invoice, *http.Response, error) {
130 uri := fmt.Sprintf("/v2/billing/invoices/%s", invoiceID)
131 req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
132
133 if err != nil {
134 return nil, nil, err
135 }
136
137 invoice := new(invoiceBase)
138 resp, err := b.client.DoWithContext(ctx, req, invoice)
139 if err != nil {
140 return nil, resp, err
141 }
142
143 return invoice.Invoice, resp, nil
144 }
145
146 // ListInvoiceItems retrieves items in an invoice that matches the given invoiceID
147 func (b *BillingServiceHandler) ListInvoiceItems(ctx context.Context, invoiceID int, options *ListOptions) ([]InvoiceItem, *Meta, *http.Response, error) { //nolint:dupl,lll
148 uri := fmt.Sprintf("/v2/billing/invoices/%d/items", invoiceID)
149 req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
150 if err != nil {
151 return nil, nil, nil, err
152 }
153
154 newValues, err := query.Values(options)
155 if err != nil {
156 return nil, nil, nil, err
157 }
158
159 req.URL.RawQuery = newValues.Encode()
160
161 invoice := new(invoiceItemsBase)
162 resp, err := b.client.DoWithContext(ctx, req, invoice)
163 if err != nil {
164 return nil, nil, resp, err
165 }
166
167 return invoice.InvoiceItems, invoice.Meta, resp, nil
168 }
169
170 // ListPendingCharges retrieves a list of all pending charges on the current account
171 func (b *BillingServiceHandler) ListPendingCharges(ctx context.Context, options *ListOptions) ([]InvoiceItem, *http.Response, error) {
172 uri := "/v2/billing/pending-charges"
173 req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
174 if err != nil {
175 return nil, nil, err
176 }
177
178 newValues, err := query.Values(options)
179 if err != nil {
180 return nil, nil, err
181 }
182
183 req.URL.RawQuery = newValues.Encode()
184
185 invoice := new(pendingChargesBase)
186 resp, err := b.client.DoWithContext(ctx, req, invoice)
187 if err != nil {
188 return nil, resp, err
189 }
190
191 return invoice.PendingCharges, resp, nil
192 }
193