diff --git a/billing_history.go b/billing_history.go new file mode 100644 index 0000000..3999600 --- /dev/null +++ b/billing_history.go @@ -0,0 +1,73 @@ +package godo + +import ( + "context" + "net/http" + "time" +) + +const billingHistoryBasePath = "v2/customers/my/billing_history" + +// BillingHistoryService is an interface for interfacing with the BillingHistory +// endpoints of the DigitalOcean API +// See: https://developers.digitalocean.com/documentation/v2/#billing_history +type BillingHistoryService interface { + List(context.Context, *ListOptions) (*BillingHistory, *Response, error) +} + +// BillingHistoryServiceOp handles communication with the BillingHistory related methods of +// the DigitalOcean API. +type BillingHistoryServiceOp struct { + client *Client +} + +var _ BillingHistoryService = &BillingHistoryServiceOp{} + +// BillingHistory represents a DigitalOcean Billing History +type BillingHistory struct { + BillingHistory []BillingHistoryEntry `json:"billing_history"` + Links *Links `json:"links"` + Meta *Meta `json:"meta"` +} + +// BillingHistoryEntry represents an entry in a customer's Billing History +type BillingHistoryEntry struct { + Description string `json:"description"` + Amount string `json:"amount"` + InvoiceID *string `json:"invoice_id"` + InvoiceUUID *string `json:"invoice_uuid"` + Date time.Time `json:"date"` + Type string `json:"type"` +} + +func (b BillingHistory) String() string { + return Stringify(b) +} + +// List the Billing History for a customer +func (s *BillingHistoryServiceOp) List(ctx context.Context, opt *ListOptions) (*BillingHistory, *Response, error) { + path := billingHistoryBasePath + path, err := addOptions(path, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + root := new(BillingHistory) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + if l := root.Links; l != nil { + resp.Links = l + } + if m := root.Meta; m != nil { + resp.Meta = m + } + + return root, resp, err +} diff --git a/billing_history_test.go b/billing_history_test.go new file mode 100644 index 0000000..c1026cd --- /dev/null +++ b/billing_history_test.go @@ -0,0 +1,71 @@ +package godo + +import ( + "fmt" + "net/http" + "reflect" + "testing" + "time" +) + +func TestBillingHistory_List(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/v2/customers/my/billing_history", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodGet) + fmt.Fprint(w, `{ + "billing_history": [ + { + "description": "Invoice for May 2018", + "amount": "12.34", + "invoice_id": "123", + "invoice_uuid": "example-uuid", + "date": "2018-06-01T08:44:38Z", + "type": "Invoice" + }, + { + "description": "Payment (MC 2018)", + "amount": "-12.34", + "date": "2018-06-02T08:44:38Z", + "type": "Payment" + } + ], + "meta": { + "total": 2 + } + }`) + }) + + history, resp, err := client.BillingHistory.List(ctx, nil) + if err != nil { + t.Errorf("BillingHistory.List returned error: %v", err) + } + + expectedBillingHistory := []BillingHistoryEntry{ + { + Description: "Invoice for May 2018", + Amount: "12.34", + InvoiceID: String("123"), + InvoiceUUID: String("example-uuid"), + Date: time.Date(2018, 6, 1, 8, 44, 38, 0, time.UTC), + Type: "Invoice", + }, + { + Description: "Payment (MC 2018)", + Amount: "-12.34", + InvoiceID: nil, + InvoiceUUID: nil, + Date: time.Date(2018, 6, 2, 8, 44, 38, 0, time.UTC), + Type: "Payment", + }, + } + entries := history.BillingHistory + if !reflect.DeepEqual(entries, expectedBillingHistory) { + t.Errorf("BillingHistory.List\nBillingHistory: got=%#v\nwant=%#v", entries, expectedBillingHistory) + } + expectedMeta := &Meta{Total: 2} + if !reflect.DeepEqual(resp.Meta, expectedMeta) { + t.Errorf("BillingHistory.List\nMeta: got=%#v\nwant=%#v", resp.Meta, expectedMeta) + } +} diff --git a/godo.go b/godo.go index ff439f3..e11a45d 100644 --- a/godo.go +++ b/godo.go @@ -46,6 +46,7 @@ type Client struct { Account AccountService Actions ActionsService Balance BalanceService + BillingHistory BillingHistoryService CDNs CDNService Domains DomainsService Droplets DropletsService @@ -168,6 +169,7 @@ func NewClient(httpClient *http.Client) *Client { c.Account = &AccountServiceOp{client: c} c.Actions = &ActionsServiceOp{client: c} c.Balance = &BalanceServiceOp{client: c} + c.BillingHistory = &BillingHistoryServiceOp{client: c} c.CDNs = &CDNServiceOp{client: c} c.Certificates = &CertificatesServiceOp{client: c} c.Domains = &DomainsServiceOp{client: c} diff --git a/godo_test.go b/godo_test.go index 1803fec..658c727 100644 --- a/godo_test.go +++ b/godo_test.go @@ -75,6 +75,7 @@ func testClientServices(t *testing.T, c *Client) { "Account", "Actions", "Balance", + "BillingHistory", "CDNs", "Domains", "Droplets",