-
-
Notifications
You must be signed in to change notification settings - Fork 457
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add service desk customer and request endpoints
- Loading branch information
Showing
7 changed files
with
761 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package jira | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
) | ||
|
||
// CustomerService handles ServiceDesk customers for the Jira instance / API. | ||
type CustomerService struct { | ||
client *Client | ||
} | ||
|
||
// Customer represents a ServiceDesk customer. | ||
type Customer struct { | ||
AccountID string `json:"accountId,omitempty" structs:"accountId,omitempty"` | ||
Name string `json:"name,omitempty" structs:"name,omitempty"` | ||
Key string `json:"key,omitempty" structs:"key,omitempty"` | ||
EmailAddress string `json:"emailAddress,omitempty" structs:"emailAddress,omitempty"` | ||
DisplayName string `json:"displayName,omitempty" structs:"displayName,omitempty"` | ||
Active *bool `json:"active,omitempty" structs:"active,omitempty"` | ||
TimeZone string `json:"timeZone,omitempty" structs:"timeZone,omitempty"` | ||
Links *SelfLink `json:"_links,omitempty" structs:"_links,omitempty"` | ||
} | ||
|
||
// CustomerListOptions is the query options for listing customers. | ||
type CustomerListOptions struct { | ||
Query string `url:"query,omitempty"` | ||
Start int `url:"start,omitempty"` | ||
Limit int `url:"limit,omitempty"` | ||
} | ||
|
||
// CustomerList is a page of customers. | ||
type CustomerList struct { | ||
Values []Customer `json:"values,omitempty" structs:"values,omitempty"` | ||
Start int `json:"start,omitempty" structs:"start,omitempty"` | ||
Limit int `json:"limit,omitempty" structs:"limit,omitempty"` | ||
IsLast bool `json:"isLastPage,omitempty" structs:"isLastPage,omitempty"` | ||
Expands []string `json:"_expands,omitempty" structs:"_expands,omitempty"` | ||
} | ||
|
||
// CreateWithContext creates a ServiceDesk customer. | ||
// | ||
// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-customer/#api-rest-servicedeskapi-customer-post | ||
func (c *CustomerService) CreateWithContext(ctx context.Context, email, displayName string) (*Customer, *Response, error) { | ||
apiEndpoint := "rest/servicedeskapi/customer" | ||
|
||
payload := struct { | ||
Email string `json:"email"` | ||
DisplayName string `json:"displayName"` | ||
}{ | ||
Email: email, | ||
DisplayName: displayName, | ||
} | ||
|
||
req, err := c.client.NewRequestWithContext(ctx, "POST", apiEndpoint, payload) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
resp, err := c.client.Do(req, nil) | ||
if err != nil { | ||
return nil, resp, NewJiraError(resp, err) | ||
} | ||
defer resp.Body.Close() | ||
|
||
responseCustomer := new(Customer) | ||
if err := json.NewDecoder(resp.Body).Decode(responseCustomer); err != nil { | ||
return nil, resp, fmt.Errorf("could not unmarshall the data into struct") | ||
} | ||
|
||
return responseCustomer, resp, nil | ||
} | ||
|
||
// Create wraps CreateWithContext using the background context. | ||
func (c *CustomerService) Create(email, displayName string) (*Customer, *Response, error) { | ||
return c.CreateWithContext(context.Background(), email, displayName) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package jira | ||
|
||
import ( | ||
"fmt" | ||
"net/http" | ||
"testing" | ||
) | ||
|
||
func TestCustomerService_Create(t *testing.T) { | ||
setup() | ||
defer teardown() | ||
|
||
const ( | ||
wantDisplayName = "Fred F. User" | ||
wantEmailAddress = "fred@example.com" | ||
) | ||
|
||
testMux.HandleFunc("/rest/servicedeskapi/customer", func(w http.ResponseWriter, r *http.Request) { | ||
testMethod(t, r, "POST") | ||
testRequestURL(t, r, "/rest/servicedeskapi/customer") | ||
|
||
w.WriteHeader(http.StatusOK) | ||
fmt.Fprintf(w, `{ | ||
"accountId": "qm:a713c8ea-1075-4e30-9d96-891a7d181739:5ad6d3581db05e2a66fa80b", | ||
"name": "qm:a713c8ea-1075-4e30-9d96-891a7d181739:5ad6d3581db05e2a66fa80b", | ||
"key": "qm:a713c8ea-1075-4e30-9d96-891a7d181739:5ad6d3581db05e2a66fa80b", | ||
"emailAddress": "%s", | ||
"displayName": "%s", | ||
"active": true, | ||
"timeZone": "Australia/Sydney", | ||
"_links": { | ||
"jiraRest": "https://your-domain.atlassian.net/rest/api/2/user?username=qm:a713c8ea-1075-4e30-9d96-891a7d181739:5ad6d3581db05e2a66fa80b", | ||
"avatarUrls": { | ||
"48x48": "https://avatar-cdn.atlassian.com/image", | ||
"24x24": "https://avatar-cdn.atlassian.com/image", | ||
"16x16": "https://avatar-cdn.atlassian.com/image", | ||
"32x32": "https://avatar-cdn.atlassian.com/image" | ||
}, | ||
"self": "https://your-domain.atlassian.net/rest/api/2/user?username=qm:a713c8ea-1075-4e30-9d96-891a7d181739:5ad6d3581db05e2a66fa80b" | ||
} | ||
}`, wantEmailAddress, wantDisplayName) | ||
}) | ||
|
||
gotCustomer, _, err := testClient.Customer.Create(wantEmailAddress, wantDisplayName) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
if want, got := wantDisplayName, gotCustomer.DisplayName; want != got { | ||
t.Fatalf("want display name: %q, got %q", want, got) | ||
} | ||
|
||
if want, got := wantEmailAddress, gotCustomer.EmailAddress; want != got { | ||
t.Fatalf("want email address: %q, got %q", want, got) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
package jira | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
) | ||
|
||
// RequestService handles ServiceDesk customer requests for the Jira instance / API. | ||
type RequestService struct { | ||
client *Client | ||
} | ||
|
||
// Request represents a ServiceDesk customer request. | ||
type Request struct { | ||
IssueID string `json:"issueId,omitempty" structs:"issueId,omitempty"` | ||
IssueKey string `json:"issueKey,omitempty" structs:"issueKey,omitempty"` | ||
TypeID string `json:"requestTypeId,omitempty" structs:"requestTypeId,omitempty"` | ||
ServiceDeskID string `json:"serviceDeskId,omitempty" structs:"serviceDeskId,omitempty"` | ||
Reporter *Customer `json:"reporter,omitempty" structs:"reporter,omitempty"` | ||
FieldValues []RequestFieldValue `json:"requestFieldValues,omitempty" structs:"requestFieldValues,omitempty"` | ||
Status *RequestStatus `json:"currentStatus,omitempty" structs:"currentStatus,omitempty"` | ||
Links *SelfLink `json:"_links,omitempty" structs:"_links,omitempty"` | ||
Expands []string `json:"_expands,omitempty" structs:"_expands,omitempty"` | ||
} | ||
|
||
// RequestFieldValue is a request field. | ||
type RequestFieldValue struct { | ||
FieldID string `json:"fieldId,omitempty" structs:"fieldId,omitempty"` | ||
Label string `json:"label,omitempty" structs:"label,omitempty"` | ||
Value string `json:"value,omitempty" structs:"value,omitempty"` | ||
} | ||
|
||
// RequestDate is the date format used in requests. | ||
type RequestDate struct { | ||
ISO8601 string `json:"iso8601,omitempty" structs:"iso8601,omitempty"` | ||
Jira string `json:"jira,omitempty" structs:"jira,omitempty"` | ||
Friendly string `json:"friendly,omitempty" structs:"friendly,omitempty"` | ||
Epoch int64 `json:"epoch,omitempty" structs:"epoch,omitempty"` | ||
} | ||
|
||
// RequestStatus is the status for a request. | ||
type RequestStatus struct { | ||
Status string | ||
Category string | ||
Date RequestDate | ||
} | ||
|
||
// RequestComment is a comment for a request. | ||
type RequestComment struct { | ||
ID string `json:"id,omitempty" structs:"id,omitempty"` | ||
Body string `json:"body,omitempty" structs:"body,omitempty"` | ||
Public bool `json:"public" structs:"public"` | ||
Author *Customer `json:"author,omitempty" structs:"author,omitempty"` | ||
Created *RequestDate `json:"created,omitempty" structs:"created,omitempty"` | ||
Links *SelfLink `json:"_links,omitempty" structs:"_links,omitempty"` | ||
Expands []string `json:"_expands,omitempty" structs:"_expands,omitempty"` | ||
} | ||
|
||
// CreateWithContext creates a new request. | ||
// | ||
// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-request/#api-rest-servicedeskapi-request-post | ||
func (r *RequestService) CreateWithContext(ctx context.Context, requester string, participants []string, request *Request) (*Request, *Response, error) { | ||
apiEndpoint := "rest/servicedeskapi/request" | ||
|
||
payload := struct { | ||
*Request | ||
FieldValues map[string]string `json:"requestFieldValues,omitempty"` | ||
Requester string `json:"raiseOnBehalfOf,omitempty"` | ||
Participants []string `json:"requestParticipants,omitempty"` | ||
}{ | ||
Request: request, | ||
FieldValues: make(map[string]string), | ||
Requester: requester, | ||
Participants: participants, | ||
} | ||
|
||
for _, field := range request.FieldValues { | ||
payload.FieldValues[field.FieldID] = field.Value | ||
} | ||
|
||
req, err := r.client.NewRequestWithContext(ctx, "POST", apiEndpoint, payload) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
resp, err := r.client.Do(req, nil) | ||
if err != nil { | ||
return nil, resp, NewJiraError(resp, err) | ||
} | ||
|
||
defer resp.Body.Close() | ||
|
||
responseRequest := new(Request) | ||
if err := json.NewDecoder(resp.Body).Decode(responseRequest); err != nil { | ||
return nil, resp, fmt.Errorf("could not unmarshall the data into struct") | ||
} | ||
|
||
return responseRequest, resp, nil | ||
} | ||
|
||
// Create wraps CreateWithContext using the background context. | ||
func (r *RequestService) Create(requester string, participants []string, request *Request) (*Request, *Response, error) { | ||
return r.CreateWithContext(context.Background(), requester, participants, request) | ||
} | ||
|
||
// CreateCommentWithContext creates a comment on a request. | ||
// | ||
// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-request/#api-rest-servicedeskapi-request-issueidorkey-comment-post | ||
func (r *RequestService) CreateCommentWithContext(ctx context.Context, issueIDOrKey string, comment *RequestComment) (*RequestComment, *Response, error) { | ||
apiEndpoint := fmt.Sprintf("rest/servicedeskapi/request/%v/comment", issueIDOrKey) | ||
|
||
req, err := r.client.NewRequestWithContext(ctx, "POST", apiEndpoint, comment) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
resp, err := r.client.Do(req, nil) | ||
if err != nil { | ||
return nil, resp, NewJiraError(resp, err) | ||
} | ||
|
||
defer resp.Body.Close() | ||
|
||
responseComment := new(RequestComment) | ||
if err := json.NewDecoder(resp.Body).Decode(responseComment); err != nil { | ||
return nil, resp, fmt.Errorf("could not unmarshall the data into struct") | ||
} | ||
|
||
return responseComment, resp, nil | ||
} | ||
|
||
// CreateComment wraps CreateCommentWithContext using the background context. | ||
func (r *RequestService) CreateComment(issueIDOrKey string, comment *RequestComment) (*RequestComment, *Response, error) { | ||
return r.CreateCommentWithContext(context.Background(), issueIDOrKey, comment) | ||
} |
Oops, something went wrong.