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