Repository: VictorAvelar/mollie-api-go (go)

Issue:
Implement Organizations API resource
**Description**
Implement the API endpoints related to the organization resource and provide test coverage, as an example you might take a look at #6 

**Additional context**
The API reference for refunds can be found here: https://docs.mollie.com/reference/v2/organizations-api/get-organization


Pull request description:
Implement organizations api
<!--- Provide a general summary of your changes in the Title above -->

## Description

Implement organizations api

## Motivation and context

closes #24 

## How has this been tested?

I added unit test

## Screenshots (if appropriate)

## Types of changes

What types of changes does your code introduce? Put an `x` in all the boxes that apply:
- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)

## Checklist:

Go over all the following points, and put an `x` in all the boxes that apply.

Please, please, please, don't send your pull request until all of the boxes are ticked. Once your pull request is created, it will trigger a build on our continuous integration server to make sure your [tests and code style pass](https://help.github.com/articles/about-required-status-checks/).

- [x] I have read the **[CONTRIBUTING](CONTRIBUTING.md)** document.
- [x] My pull request addresses exactly one patch/feature.
- [x] I have created a branch for this patch/feature.
- [x] Each individual commit in the pull request is meaningful.
- [x] I have added tests to cover my changes.
- [x] If my change requires a change to the documentation, I have updated it accordingly.

If you're unsure about any of these, don't hesitate to ask. We're here to help!


Patch:
diff --git a/mollie/mollie.go b/mollie/mollie.go
index 2c307a4..20ddc31 100644
--- a/mollie/mollie.go
+++ b/mollie/mollie.go
@@ -36,10 +36,11 @@ type Client struct {
 	common         service // Reuse a single struct instead of allocating one for each service on the heap.
 	config         *Config
 	// Services
-	Payments    *PaymentsService
-	Chargebacks *ChargebacksService
-	Methods     *MethodsService
-	Invoices    *InvoicesService
+	Payments      *PaymentsService
+	Chargebacks   *ChargebacksService
+	Methods       *MethodsService
+	Invoices      *InvoicesService
+	Organizations *OrganizationsService
 }
 
 type service struct {
@@ -152,6 +153,7 @@ func NewClient(baseClient *http.Client, c *Config) (mollie *Client, err error) {
 	mollie.Chargebacks = (*ChargebacksService)(&mollie.common)
 	mollie.Methods = (*MethodsService)(&mollie.common)
 	mollie.Invoices = (*InvoicesService)(&mollie.common)
+	mollie.Organizations = (*OrganizationsService)(&mollie.common)
 
 	// Parse authorization from environment
 	if tkn, ok := os.LookupEnv(APITokenEnv); ok {
diff --git a/mollie/organizations.go b/mollie/organizations.go
new file mode 100644
index 0000000..e5ae8dc
--- /dev/null
+++ b/mollie/organizations.go
@@ -0,0 +1,74 @@
+package mollie
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+)
+
+// Organization describes an organization detail
+type Organization struct {
+	Resource           string             `json:"resource,omitempty"`
+	ID                 string             `json:"id,omitempty"`
+	Name               string             `json:"name,omitempty"`
+	Email              string             `json:"email,omitempty"`
+	Locale             string             `json:"locale,omitempty"`
+	Address            *Address           `json:"address,omitempty"`
+	RegistrationNumber string             `json:"registrationNumber,omitempty"`
+	VatNumber          string             `json:"vatNumber,omitempty"`
+	VatRegulation      string             `json:"vatRegulation,omitempty"`
+	Links              *OrganizationLinks `json:"_links,omitempty"`
+}
+
+// OrganizationLinks describes all the possible links to be returned with
+// a organization object.
+type OrganizationLinks struct {
+	Self          URL `json:"self,omitempty"`
+	Chargebacks   URL `json:"chargebacks,omitempty"`
+	Customers     URL `json:"customers,omitempty"`
+	Invoices      URL `json:"invoices,omitempty"`
+	Payments      URL `json:"payments,omitempty"`
+	Profiles      URL `json:"profiles,omitempty"`
+	Refunds       URL `json:"refunds,omitempty"`
+	Settlements   URL `json:"settlements,omitempty"`
+	Documentation URL `json:"documentation,omitempty"`
+}
+
+// OrganizationsService instance operates over organization resources
+type OrganizationsService service
+
+// Get retrieve an organization by its id.
+func (os *OrganizationsService) Get(id string) (o *Organization, err error) {
+	getURL := fmt.Sprintf("v2/organizations/%s", id)
+
+	req, err := os.client.NewAPIRequest(http.MethodGet, getURL, nil)
+	if err != nil {
+		return
+	}
+	res, err := os.client.Do(req)
+	if err != nil {
+		return
+	}
+	if err = json.Unmarshal(res.content, &o); err != nil {
+		return
+	}
+	return
+}
+
+// GetCurrent retrieve the currently authenticated organization
+func (os *OrganizationsService) GetCurrent() (o *Organization, err error) {
+	getURL := "v2/organizations/me"
+
+	req, err := os.client.NewAPIRequest(http.MethodGet, getURL, nil)
+	if err != nil {
+		return
+	}
+	res, err := os.client.Do(req)
+	if err != nil {
+		return
+	}
+	if err = json.Unmarshal(res.content, &o); err != nil {
+		return
+	}
+	return
+}


Test patch:
diff --git a/mollie/organizations_test.go b/mollie/organizations_test.go
new file mode 100644
index 0000000..21d82e0
--- /dev/null
+++ b/mollie/organizations_test.go
@@ -0,0 +1,116 @@
+package mollie
+
+import (
+	"github.com/VictorAvelar/mollie-api-go/testdata"
+	"net/http"
+	"net/url"
+	"strings"
+	"testing"
+)
+
+func TestOrganizationsService_Get(t *testing.T) {
+	setup()
+	defer teardown()
+	id := "org_12345678"
+	_ = tClient.WithAuthenticationValue("test_token")
+	tMux.HandleFunc("/v2/organizations/"+id, func(w http.ResponseWriter, r *http.Request) {
+		testHeader(t, r, AuthHeader, "Bearer test_token")
+		testMethod(t, r, "GET")
+		if _, ok := r.Header[AuthHeader]; !ok {
+			w.WriteHeader(http.StatusUnauthorized)
+		}
+
+		w.WriteHeader(http.StatusOK)
+		_, _ = w.Write([]byte(testdata.GetOrganizationResponse))
+	})
+
+	res, err := tClient.Organizations.Get(id)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if res.ID != id {
+		t.Errorf("mismatching info. want %v, got %v", id, res.ID)
+	}
+}
+
+func TestOrganizationsService_GetCurrent(t *testing.T) {
+	setup()
+	defer teardown()
+	id := "org_12345678"
+	_ = tClient.WithAuthenticationValue("test_token")
+	tMux.HandleFunc("/v2/organizations/me", func(w http.ResponseWriter, r *http.Request) {
+		testHeader(t, r, AuthHeader, "Bearer test_token")
+		testMethod(t, r, "GET")
+		if _, ok := r.Header[AuthHeader]; !ok {
+			w.WriteHeader(http.StatusUnauthorized)
+		}
+
+		w.WriteHeader(http.StatusOK)
+		_, _ = w.Write([]byte(testdata.GetCurrentOrganizationResponse))
+	})
+
+	res, err := tClient.Organizations.GetCurrent()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if res.ID != id {
+		t.Errorf("mismatching info. want %v, got %v", id, res.ID)
+	}
+}
+
+func TestOrganizationsService_HttpRequestErrors(t *testing.T) {
+	setup()
+	defer teardown()
+	tMux.HandleFunc("/v2/organizations/", errorHandler)
+
+	_, gerr := tClient.Organizations.Get("org_12345678")
+	_, gcerr := tClient.Organizations.GetCurrent()
+
+	tests := []error{gerr, gcerr}
+
+	for _, tt := range tests {
+		if tt == nil {
+			t.Fail()
+		}
+	}
+}
+
+func TestOrganizationsService_NewAPIRequestErrors(t *testing.T) {
+	setup()
+	defer teardown()
+	u, _ := url.Parse(tServer.URL)
+	tClient.BaseURL = u
+	tMux.HandleFunc("/v2/organizations/", errorHandler)
+
+	_, gerr := tClient.Organizations.Get("org_12345678")
+	_, gcerr := tClient.Organizations.GetCurrent()
+
+	tests := []error{gerr, gcerr}
+
+	for _, tt := range tests {
+		if tt != errBadBaseURL {
+			t.Fail()
+		}
+	}
+}
+
+func TestOrganizationsService_EncodingResponseErrors(t *testing.T) {
+	setup()
+	defer teardown()
+	tMux.HandleFunc("/v2/organizations/", encodingHandler)
+
+	_, gerr := tClient.Organizations.Get("org_12345678")
+	_, gcerr := tClient.Organizations.GetCurrent()
+
+	tests := []error{gerr, gcerr}
+
+	for _, tt := range tests {
+		if tt == nil {
+			t.Fail()
+		} else if !strings.Contains(tt.Error(), "invalid character") {
+			t.Errorf("unexpected error %v", tt)
+		}
+	}
+}
diff --git a/testdata/organizations.go b/testdata/organizations.go
new file mode 100644
index 0000000..e8a9746
--- /dev/null
+++ b/testdata/organizations.go
@@ -0,0 +1,81 @@
+package testdata
+
+// GetOrganizationResponse example
+const GetOrganizationResponse = `{
+    "resource": "organization",
+    "id": "org_12345678",
+    "name": "Mollie B.V.",
+    "email": "info@mollie.com",
+    "address": {
+        "streetAndNumber": "Keizersgracht 313",
+        "postalCode": "1016 EE",
+        "city": "Amsterdam",
+        "country": "NL"
+    },
+    "registrationNumber": "30204462",
+    "vatNumber": "NL815839091B01",
+    "_links": {
+        "self": {
+            "href": "https://api.mollie.com/v2/organizations/org_12345678",
+            "type": "application/hal+json"
+        },
+        "documentation": {
+            "href": "https://docs.mollie.com/reference/v2/organizations-api/get-organization",
+            "type": "text/html"
+        }
+    }
+}`
+
+// GetCurrentOrganizationResponse example
+const GetCurrentOrganizationResponse = `{
+     "resource": "organization",
+     "id": "org_12345678",
+     "name": "Mollie B.V.",
+     "email": "info@mollie.com",
+     "address": {
+        "streetAndNumber" : "Keizersgracht 313",
+        "postalCode": "1016 EE",
+         "city": "Amsterdam",
+         "country": "NL"
+     },
+     "registrationNumber": "30204462",
+     "vatNumber": "NL815839091B01",
+     "_links": {
+         "self": {
+             "href": "https://api.mollie.com/v2/organizations/me",
+             "type": "application/hal+json"
+         },
+         "chargebacks": {
+             "href": "https://api.mollie.com/v2/chargebacks",
+             "type": "application/hal+json"
+         },
+         "customers": {
+             "href": "https://api.mollie.com/v2/customers",
+             "type": "application/hal+json"
+         },
+         "invoices": {
+             "href": "https://api.mollie.com/v2/invoices",
+             "type": "application/hal+json"
+         },
+         "payments": {
+             "href": "https://api.mollie.com/v2/payments",
+             "type": "application/hal+json"
+         },
+         "profiles": {
+             "href": "https://api.mollie.com/v2/profiles",
+             "type": "application/hal+json"
+         },
+         "refunds": {
+             "href": "https://api.mollie.com/v2/refunds",
+             "type": "application/hal+json"
+         },
+         "settlements": {
+             "href": "https://api.mollie.com/v2/settlements",
+             "type": "application/hal+json"
+         },
+         "documentation": {
+             "href": "https://docs.mollie.com/reference/v2/organizations-api/current-organization",
+             "type": "text/html"
+         }
+     }
+ }`