Skip to content

Commit 7564af8

Browse files
authored
Merge pull request #28 from Molaryy/feat(billing)/add-billing-route
feat(invoices): add billing invoices in client handler
2 parents e7b8c86 + 0c4abca commit 7564af8

File tree

5 files changed

+157
-1
lines changed

5 files changed

+157
-1
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"id": "9qzw9Hj4",
3+
"number": 843071,
4+
"parent_id": null,
5+
"status": "paid",
6+
"date": "2024-06-23",
7+
"type": "invoice",
8+
"total_due": 11.90,
9+
"currency": "EUR",
10+
"csv_url": "url",
11+
"pdf_url": "url"
12+
}

pkg/invoices.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package serverscom
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
)
7+
8+
const (
9+
invoicesListPath = "/billing/invoices"
10+
11+
InvoicePath = "/billing/invoices/%s"
12+
)
13+
14+
// BilligService is an interface for interfacing with Billing Invoices endpoints
15+
// API documentation:
16+
// https://developers.servers.com/api-documentation/v1/#tag/Invoice
17+
type InvoiceService interface {
18+
// Primary collection
19+
Collection() Collection[InvoiceList]
20+
21+
// Generic operations
22+
GetBillingInvoice(ctx context.Context, id string) (*Invoice, error)
23+
}
24+
25+
// InvoiceHandler handles operations around hosts
26+
type InvoiceHandler struct {
27+
client *Client
28+
}
29+
30+
// Collection builds a new Collection[InvoiceList] interface
31+
func (h *InvoiceHandler) Collection() Collection[InvoiceList] {
32+
return NewCollection[InvoiceList](h.client, invoicesListPath)
33+
}
34+
35+
// GetBillingInvoice returns an invoice
36+
// Endpoint: https://developers.servers.com/api-documentation/v1/#tag/Invoice/operation/GetAnInvoice
37+
func (h *InvoiceHandler) GetBillingInvoice(ctx context.Context, id string) (*Invoice, error) {
38+
url := h.client.buildURL(InvoicePath, []interface{}{id}...)
39+
40+
body, err := h.client.buildAndExecRequest(ctx, "GET", url, nil)
41+
42+
if err != nil {
43+
return nil, err
44+
}
45+
46+
invoice := new(Invoice)
47+
48+
if err := json.Unmarshal(body, &invoice); err != nil {
49+
return nil, err
50+
}
51+
52+
return invoice, nil
53+
}

pkg/invoices_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package serverscom
2+
3+
import (
4+
"context"
5+
. "github.com/onsi/gomega"
6+
"testing"
7+
)
8+
9+
func TestInvoicesCollection(t *testing.T) {
10+
g := NewGomegaWithT(t)
11+
12+
ts, client := newFakeServer().
13+
WithRequestPath("/billing/invoices").
14+
WithRequestMethod("GET").
15+
WithResponseBodyStubInline(`[]`).
16+
WithResponseCode(200).
17+
Build()
18+
19+
defer ts.Close()
20+
21+
collection := client.Invoices.Collection()
22+
23+
ctx := context.TODO()
24+
25+
list, err := collection.List(ctx)
26+
27+
g.Expect(err).To(BeNil())
28+
g.Expect(list).To(BeEmpty())
29+
g.Expect(collection.HasNextPage()).To(Equal(false))
30+
g.Expect(collection.HasPreviousPage()).To(Equal(false))
31+
g.Expect(collection.HasFirstPage()).To(Equal(false))
32+
g.Expect(collection.HasLastPage()).To(Equal(false))
33+
}
34+
35+
func TestGetInvoice(t *testing.T) {
36+
g := NewGomegaWithT(t)
37+
38+
ts, client := newFakeServer().
39+
WithRequestPath("/billing/invoices/9qzw9Hj4").
40+
WithRequestMethod("GET").
41+
WithResponseBodyStubFile("fixtures/invoices/get_response.json").
42+
WithResponseCode(200).
43+
Build()
44+
45+
defer ts.Close()
46+
47+
ctx := context.TODO()
48+
49+
invoice, err := client.Invoices.GetBillingInvoice(ctx, "9qzw9Hj4")
50+
51+
g.Expect(err).To(BeNil())
52+
g.Expect(invoice).ToNot(BeNil())
53+
g.Expect(invoice.ID).To(Equal("9qzw9Hj4"))
54+
g.Expect(invoice.Number).To(Equal(int64(843071)))
55+
g.Expect(invoice.ParentID).To(BeNil())
56+
g.Expect(invoice.Status).To(Equal("paid"))
57+
g.Expect(invoice.Date).To(Equal("2024-06-23"))
58+
g.Expect(invoice.Type).To(Equal("invoice"))
59+
g.Expect(invoice.TotalDue).To(Equal(11.90))
60+
g.Expect(invoice.Currency).To(Equal("EUR"))
61+
g.Expect(invoice.CsvUrl).To(Equal("url"))
62+
g.Expect(invoice.PdfUrl).To(Equal("url"))
63+
}

pkg/serverscom.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ type Client struct {
4040

4141
KubernetesClusters KubernetesClustersService
4242

43+
Invoices InvoiceService
44+
4345
client *resty.Client
4446
}
4547

@@ -98,6 +100,7 @@ func (cli *Client) configureResources() {
98100
cli.CloudBlockStorageBackups = &CloudBlockStorageBackupsHandler{cli}
99101
cli.CloudBlockStorageVolumes = &CloudBlockStorageVolumesHandler{cli}
100102
cli.KubernetesClusters = &KubernetesClustersHandler{cli}
103+
cli.Invoices = &InvoiceHandler{cli}
101104
}
102105

103106
func (cli *Client) buildURL(path string, values ...interface{}) string {

pkg/types.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -976,7 +976,6 @@ type KubernetesCluster struct {
976976
}
977977

978978
// KubernetesClusterNode represents Kubernetes cluster node
979-
980979
type KubernetesClusterNode struct {
981980
ID string `json:"id"`
982981
Number int64 `json:"number"`
@@ -998,3 +997,29 @@ type KubernetesClusterNode struct {
998997
type KubernetesClusterUpdateInput struct {
999998
Labels map[string]string `json:"labels,omitempty"`
1000999
}
1000+
1001+
// InvoiceList represents invoices list
1002+
type InvoiceList struct {
1003+
ID string `json:"id"`
1004+
Number int64 `json:"number"`
1005+
ParentID *string `json:"parent_id"`
1006+
Status string `json:"status"`
1007+
Date string `json:"date"`
1008+
Type string `json:"type"`
1009+
TotalDue float64 `json:"total_due"`
1010+
Currency string `json:"currency"`
1011+
}
1012+
1013+
// Invoice represents an invoice
1014+
type Invoice struct {
1015+
ID string `json:"id"`
1016+
Number int64 `json:"number"`
1017+
ParentID *string `json:"parent_id"`
1018+
Status string `json:"status"`
1019+
Date string `json:"date"`
1020+
Type string `json:"type"`
1021+
TotalDue float64 `json:"total_due"`
1022+
Currency string `json:"currency"`
1023+
CsvUrl string `json:"csv_url"`
1024+
PdfUrl string `json:"pdf_url"`
1025+
}

0 commit comments

Comments
 (0)