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

View File

@ -3,7 +3,6 @@ package connectwise
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/url" "net/url"
@ -87,69 +86,3 @@ func getHTTPResponseBody(resp *http.Response) ([]byte, error) {
return body, nil 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 //GetTicketByID expects a ticket ID and returns a pointer to a Ticket struct
func (cw *Site) GetTicketByID(ticketID int) (*Ticket, error) { func (cw *Site) GetTicketByID(ticketID int) (*Ticket, error) {
restAction := fmt.Sprintf("/service/tickets/%d", ticketID) req := NewRequest(cw, fmt.Sprintf("/service/tickets/%d", ticketID), "GET", nil)
cwurl, err := cw.BuildURL(restAction) err := req.Do()
if err != nil { 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) ticket := &Ticket{}
if err != nil { err = json.Unmarshal(req.Body, ticket)
return nil, fmt.Errorf("could not get request %s: %s", cwurl, err)
}
ticket := Ticket{}
err = json.Unmarshal(body, &ticket)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to unmarshal body into struct: %s", err) 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 //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) { 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 { 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) timeEntryReference := &[]TimeEntryReference{}
if err != nil { err = json.Unmarshal(req.Body, timeEntryReference)
return nil, fmt.Errorf("could not get request %s: %s", cwurl, err)
}
timeEntryReference := []TimeEntryReference{}
err = json.Unmarshal(body, &timeEntryReference)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to unmarshal body into struct: %s", err) 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 //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) { func (cw *Site) GetTicketConfigurationsByID(ticketID int) (*[]ConfigurationReference, error) {
restAction := fmt.Sprintf("/service/tickets/%d/configurations", ticketID) req := NewRequest(cw, fmt.Sprintf("/service/tickets/%d/configurations", ticketID), "GET", nil)
cwurl, err := cw.BuildURL(restAction) err := req.Do()
if err != nil { 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) configurationReference := &[]ConfigurationReference{}
if err != nil { err = json.Unmarshal(req.Body, configurationReference)
return nil, fmt.Errorf("could not get request %s: %s", cwurl, err)
}
configurationReference := []ConfigurationReference{}
err = json.Unmarshal(body, &configurationReference)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to unmarshal body into struct: %s", err) 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 package connectwise
import ( import (
"bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
) )
//Callback is a struct to hold the unmarshaled JSON data when making a call to the System API //Callback is a struct to hold the unmarshaled JSON data when making a call to the System API
//TBD: struct tags
type Callback struct { type Callback struct {
ID int ID int `json:"id"`
Description string Description string `json:"description"`
URL string URL string `json:"url"`
ObjectID int ObjectID int `json:"objectId"`
Type string Type string `json:"type"`
Level string Level string `json:"level"`
MemberID int MemberID int `json:"memberId"`
InactiveFlag bool 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 //GetCallbacks returns a slice of Callback structs containing all the callbacks currently registered with ConnectWise
func (cw *Site) GetCallbacks() (*[]Callback, error) { func (cw *Site) GetCallbacks() (*[]Callback, error) {
restAction := "/system/callbacks" req := NewRequest(cw, "/system/callbacks", "GET", nil)
cwurl, err := cw.BuildURL(restAction) err := req.Do()
if err != nil { 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) callbacks := &[]Callback{}
if err != nil { err = json.Unmarshal(req.Body, callbacks)
return nil, fmt.Errorf("could not get request %s: %s", cwurl, err)
}
callbacks := []Callback{}
err = json.Unmarshal(body, &callbacks)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to unmarshal body into struct: %s", err) 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 //NewCallback expects a Callback struct and will register a new callback with Connectwise
//TBD: This should return something useful, response body?? //TBD: This should return something useful, response body??
func (cw *Site) NewCallback(callback Callback) error { func (cw *Site) NewCallback(callback *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)
}
jsonCallback, err := json.Marshal(callback) jsonCallback, err := json.Marshal(callback)
if err != nil { 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) req := NewRequest(cw, "/system/callbacks", "POST", jsonCallback)
err = req.Do()
_, err = cw.PostRequest(cwurl, jsonBuffer)
if err != nil { 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 //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 { func (cw *Site) DeleteCallback(callback int) error {
restAction := fmt.Sprintf("/system/callbacks/%d", callback) req := NewRequest(cw, fmt.Sprintf("/system/callbacks/%d", callback), "DELETE", nil)
cwurl, err := cw.BuildURL(restAction) err := req.Do()
if err != nil { if err != nil {
return fmt.Errorf("could not build url %s: %s", restAction, err) return fmt.Errorf("request failed for %s: %s", req.RestAction, err)
}
_, err = cw.DeleteRequest(cwurl)
if err != nil {
return fmt.Errorf("could not delete request %s: %s", cwurl, err)
} }
return nil 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 //GetTimeEntryByID expects a time entry ID and will return a pointer to a TimeEntry struct
func (cw *Site) GetTimeEntryByID(timeEntryID int) (*TimeEntry, error) { func (cw *Site) GetTimeEntryByID(timeEntryID int) (*TimeEntry, error) {
restAction := fmt.Sprintf("/time/entries/%d", timeEntryID) req := NewRequest(cw, fmt.Sprintf("/time/entries/%d", timeEntryID), "GET", nil)
cwurl, err := cw.BuildURL(restAction) err := req.Do()
if err != nil { 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) timeEntry := &TimeEntry{}
if err != nil { err = json.Unmarshal(req.Body, timeEntry)
return nil, fmt.Errorf("could not get request %s: %s", cwurl, err)
}
timeEntry := TimeEntry{}
err = json.Unmarshal(body, &timeEntry)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to unmarshal body into struct: %s", err) return nil, fmt.Errorf("failed to unmarshal body into struct: %s", err)
} }
return &timeEntry, nil return timeEntry, nil
} }