Complete refactor of request system... much more flexible requests.

This commit is contained in:
Steven Polley 2018-07-07 17:18:59 -06:00
parent 9eabee18ff
commit 0c7791e267
5 changed files with 72 additions and 176 deletions

View File

@ -3,7 +3,6 @@ package connectwise
import (
"encoding/json"
"fmt"
"net/url"
)
//Agreement is a struct to hold the unmarshaled JSON data when making a call to the Finance API
@ -118,50 +117,38 @@ type Agreement struct {
//GetAgreements returns a list of agreements, not paginated and currently not that useful
//TBD: Pagination and filtering options still need to be considered
func (cw *Site) GetAgreements() (*[]Agreement, error) {
restAction := "/finance/agreements"
cwurl, err := cw.BuildURL(restAction)
req := NewRequest(cw, "/finance/agreements", "GET", nil)
err := req.Do()
if err != nil {
return nil, fmt.Errorf("could not build url %s: %s", restAction, err)
return nil, fmt.Errorf("request failed for %s: %s", req.RestAction, err)
}
body, err := cw.GetRequest(cwurl)
if err != nil {
return nil, fmt.Errorf("could not get request %s: %s", cwurl, err)
}
agreements := []Agreement{}
err = json.Unmarshal(body, &agreements)
agreements := &[]Agreement{}
err = json.Unmarshal(req.Body, agreements)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal body into struct: %s", err)
}
return &agreements, nil
return agreements, nil
}
//GetAgreementsByCompanyName returns a list of agreements that belong to an exact matching company name
//TBD: Pagination and filtering options still need to be considered
func (cw *Site) GetAgreementsByCompanyName(companyName string) (*[]Agreement, error) {
restAction := "/finance/agreements"
cwurl, err := cw.BuildURL(restAction)
req := NewRequest(cw, "/finance/agreements", "GET", nil)
req.Parameters["conditions"] = "company/name=\"" + companyName + "\""
err := req.Do()
if err != nil {
return nil, fmt.Errorf("could not build url %s: %s", restAction, err)
return nil, fmt.Errorf("request failed for %s: %s", req.RestAction, err)
}
parameters := url.Values{}
parameters.Add("conditions", "company/name=\""+companyName+"\"")
cwurl.RawQuery = parameters.Encode()
body, err := cw.GetRequest(cwurl)
if err != nil {
return nil, fmt.Errorf("could not get request %s: %s", cwurl, err)
}
agreements := []Agreement{}
err = json.Unmarshal(body, &agreements)
agreements := &[]Agreement{}
err = json.Unmarshal(req.Body, agreements)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal body into struct: %s", err)
}
return &agreements, nil
return agreements, nil
}
//GetBillingCycles is not complete

View File

@ -3,7 +3,6 @@ package connectwise
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
@ -87,69 +86,3 @@ func getHTTPResponseBody(resp *http.Response) ([]byte, error) {
return body, nil
}
//GetRequest takes a Site and request URL, and returns the body of the response
func (cw *Site) GetRequest(cwurl *url.URL) ([]byte, error) {
client := &http.Client{}
req, err := http.NewRequest("GET", cwurl.String(), nil)
if err != nil {
return nil, fmt.Errorf("could not construct http request: %s", err)
}
req.Header.Set("Authorization", cw.Auth)
req.Header.Set("Content-Type", "application/json")
response, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("could not perform http get request: %s", err)
}
body, err := getHTTPResponseBody(response)
if err != nil {
return nil, fmt.Errorf("could not get http response body: %s", err)
}
return body, nil
}
//PostRequest takes a Site and request URL, and returns the body of the response
func (cw *Site) PostRequest(cwurl *url.URL, reqBody io.Reader) ([]byte, error) {
client := &http.Client{}
req, err := http.NewRequest("POST", cwurl.String(), reqBody)
if err != nil {
return nil, fmt.Errorf("could not construct http request: %s", err)
}
req.Header.Set("Authorization", cw.Auth)
req.Header.Set("Content-Type", "application/json")
response, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("could not perform http post request: %s", err)
}
body, err := getHTTPResponseBody(response)
if err != nil {
return nil, fmt.Errorf("could not get http response body: %s", err)
}
return body, nil
}
//DeleteRequest takes a Site and request URL, and returns the body of the response
func (cw *Site) DeleteRequest(cwurl *url.URL) ([]byte, error) {
client := &http.Client{}
req, err := http.NewRequest("DELETE", cwurl.String(), nil)
if err != nil {
return nil, fmt.Errorf("could not construct http request: %s", err)
}
req.Header.Set("Authorization", cw.Auth)
req.Header.Set("Content-Type", "application/json")
response, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("could not perform http delete request: %s", err)
}
body, err := getHTTPResponseBody(response)
if err != nil {
return nil, fmt.Errorf("could not get http response body: %s", err)
}
return body, nil
}

View File

@ -195,63 +195,52 @@ type ConfigurationReference struct {
//GetTicketByID expects a ticket ID and returns a pointer to a Ticket struct
func (cw *Site) GetTicketByID(ticketID int) (*Ticket, error) {
restAction := fmt.Sprintf("/service/tickets/%d", ticketID)
cwurl, err := cw.BuildURL(restAction)
req := NewRequest(cw, fmt.Sprintf("/service/tickets/%d", ticketID), "GET", nil)
err := req.Do()
if err != nil {
return nil, fmt.Errorf("could not build url %s: %s", restAction, err)
return nil, fmt.Errorf("request failed for %s: %s", req.RestAction, err)
}
body, err := cw.GetRequest(cwurl)
if err != nil {
return nil, fmt.Errorf("could not get request %s: %s", cwurl, err)
}
ticket := Ticket{}
err = json.Unmarshal(body, &ticket)
ticket := &Ticket{}
err = json.Unmarshal(req.Body, ticket)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal body into struct: %s", err)
}
return &ticket, nil
return ticket, nil
}
//GetTicketTimeEntriesByID expects a ticket ID and returns a pointer a to a slice of TimeEntryReference's, all the time entries attached to that ticket
func (cw *Site) GetTicketTimeEntriesByID(ticketID int) (*[]TimeEntryReference, error) {
restAction := fmt.Sprintf("/service/tickets/%d/timeentries", ticketID)
cwurl, err := cw.BuildURL(restAction)
req := NewRequest(cw, fmt.Sprintf("/service/tickets/%d/timeentries", ticketID), "GET", nil)
err := req.Do()
if err != nil {
return nil, fmt.Errorf("could not build url %s: %s", restAction, err)
return nil, fmt.Errorf("request failed for %s: %s", req.RestAction, err)
}
body, err := cw.GetRequest(cwurl)
if err != nil {
return nil, fmt.Errorf("could not get request %s: %s", cwurl, err)
}
timeEntryReference := []TimeEntryReference{}
err = json.Unmarshal(body, &timeEntryReference)
timeEntryReference := &[]TimeEntryReference{}
err = json.Unmarshal(req.Body, timeEntryReference)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal body into struct: %s", err)
}
return &timeEntryReference, nil
return timeEntryReference, nil
}
//GetTicketConfigurationsByID expects a ticket ID and returns a pointer to a slice of the configurations attached to the ticket
func (cw *Site) GetTicketConfigurationsByID(ticketID int) (*[]ConfigurationReference, error) {
restAction := fmt.Sprintf("/service/tickets/%d/configurations", ticketID)
cwurl, err := cw.BuildURL(restAction)
req := NewRequest(cw, fmt.Sprintf("/service/tickets/%d/configurations", ticketID), "GET", nil)
err := req.Do()
if err != nil {
return nil, fmt.Errorf("could not build url %s: %s", restAction, err)
return nil, fmt.Errorf("request failed for %s: %s", req.RestAction, err)
}
body, err := cw.GetRequest(cwurl)
if err != nil {
return nil, fmt.Errorf("could not get request %s: %s", cwurl, err)
}
configurationReference := []ConfigurationReference{}
err = json.Unmarshal(body, &configurationReference)
configurationReference := &[]ConfigurationReference{}
err = json.Unmarshal(req.Body, configurationReference)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal body into struct: %s", err)
}
return &configurationReference, nil
return configurationReference, nil
}

View File

@ -1,81 +1,73 @@
package connectwise
import (
"bytes"
"encoding/json"
"fmt"
)
//Callback is a struct to hold the unmarshaled JSON data when making a call to the System API
//TBD: struct tags
type Callback struct {
ID int
Description string
URL string
ObjectID int
Type string
Level string
MemberID int
InactiveFlag bool
ID int `json:"id"`
Description string `json:"description"`
URL string `json:"url"`
ObjectID int `json:"objectId"`
Type string `json:"type"`
Level string `json:"level"`
MemberID int `json:"memberId"`
InactiveFlag bool `json:"inactiveFlag"`
Info struct {
LastUpdated string `json:"lastUpdated"`
UpdatedBy string `json:"updatedBy"`
} `json:"_info"`
}
//GetCallbacks returns a slice of Callback structs containing all the callbacks currently registered with ConnectWise
func (cw *Site) GetCallbacks() (*[]Callback, error) {
restAction := "/system/callbacks"
cwurl, err := cw.BuildURL(restAction)
req := NewRequest(cw, "/system/callbacks", "GET", nil)
err := req.Do()
if err != nil {
return nil, fmt.Errorf("could not build url %s: %s", restAction, err)
return nil, fmt.Errorf("request failed for %s: %s", req.RestAction, err)
}
body, err := cw.GetRequest(cwurl)
if err != nil {
return nil, fmt.Errorf("could not get request %s: %s", cwurl, err)
}
callbacks := []Callback{}
err = json.Unmarshal(body, &callbacks)
callbacks := &[]Callback{}
err = json.Unmarshal(req.Body, callbacks)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal body into struct: %s", err)
}
return &callbacks, nil
return callbacks, nil
}
//NewCallback expects a Callback struct and will register a new callback with Connectwise
//TBD: This should return something useful, response body??
func (cw *Site) NewCallback(callback Callback) error {
restAction := "/system/callbacks"
cwurl, err := cw.BuildURL(restAction)
if err != nil {
return fmt.Errorf("could not build url %s: %s", restAction, err)
}
func (cw *Site) NewCallback(callback *Callback) (*Callback, error) {
jsonCallback, err := json.Marshal(callback)
if err != nil {
return fmt.Errorf("could not marshal json data: %s", err)
return nil, fmt.Errorf("could not marshal json data: %s", err)
}
jsonBuffer := bytes.NewReader(jsonCallback)
_, err = cw.PostRequest(cwurl, jsonBuffer)
req := NewRequest(cw, "/system/callbacks", "POST", jsonCallback)
err = req.Do()
if err != nil {
return fmt.Errorf("could not post request %s: %s", cwurl, err)
return nil, fmt.Errorf("request failed for %s: %s", req.RestAction, err)
}
return nil
callback = &Callback{}
err = json.Unmarshal(req.Body, callback)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal body into struct: %s", err)
}
return callback, nil
}
//DeleteCallback expects the ID of an existing callback and will unregister it with ConnectWise
//TBD: This should return something useful, response body??
//Does not return anything - CW gives an empty response body
func (cw *Site) DeleteCallback(callback int) error {
restAction := fmt.Sprintf("/system/callbacks/%d", callback)
cwurl, err := cw.BuildURL(restAction)
req := NewRequest(cw, fmt.Sprintf("/system/callbacks/%d", callback), "DELETE", nil)
err := req.Do()
if err != nil {
return fmt.Errorf("could not build url %s: %s", restAction, err)
}
_, err = cw.DeleteRequest(cwurl)
if err != nil {
return fmt.Errorf("could not delete request %s: %s", cwurl, err)
return fmt.Errorf("request failed for %s: %s", req.RestAction, err)
}
return nil

View File

@ -86,22 +86,17 @@ type TimeEntry struct {
//GetTimeEntryByID expects a time entry ID and will return a pointer to a TimeEntry struct
func (cw *Site) GetTimeEntryByID(timeEntryID int) (*TimeEntry, error) {
restAction := fmt.Sprintf("/time/entries/%d", timeEntryID)
cwurl, err := cw.BuildURL(restAction)
req := NewRequest(cw, fmt.Sprintf("/time/entries/%d", timeEntryID), "GET", nil)
err := req.Do()
if err != nil {
return nil, fmt.Errorf("could not build url %s: %s", restAction, err)
return nil, fmt.Errorf("request failed for %s: %s", req.RestAction, err)
}
body, err := cw.GetRequest(cwurl)
if err != nil {
return nil, fmt.Errorf("could not get request %s: %s", cwurl, err)
}
timeEntry := TimeEntry{}
err = json.Unmarshal(body, &timeEntry)
timeEntry := &TimeEntry{}
err = json.Unmarshal(req.Body, timeEntry)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal body into struct: %s", err)
}
return &timeEntry, nil
return timeEntry, nil
}