From 47df59f5200223a700ee2a2aa0eca4be9cd13424 Mon Sep 17 00:00:00 2001 From: Paolo Romolini Date: Wed, 22 Feb 2023 17:19:59 +0100 Subject: [PATCH] Add custom organization fields (list and create) methods --- fixture/GET/organization_fields.json | 58 +++++++++++++++++++++ fixture/POST/organization_fields.json | 38 ++++++++++++++ zendesk/api.go | 1 + zendesk/custom_field_option.go | 12 +++++ zendesk/mock/client.go | 31 +++++++++++ zendesk/organization_field.go | 75 +++++++++++++++++++++++++++ zendesk/organization_field_test.go | 32 ++++++++++++ 7 files changed, 247 insertions(+) create mode 100644 fixture/GET/organization_fields.json create mode 100644 fixture/POST/organization_fields.json create mode 100644 zendesk/organization_field.go create mode 100644 zendesk/organization_field_test.go diff --git a/fixture/GET/organization_fields.json b/fixture/GET/organization_fields.json new file mode 100644 index 00000000..ff83a506 --- /dev/null +++ b/fixture/GET/organization_fields.json @@ -0,0 +1,58 @@ +{ + "organization_fields": [ + { + "id": 1110988024701, + "url": "https://example.zendesk.com/api/v2/organization_fields/1110988024701.json", + "title": "Title", + "type": "lookup", + "relationship_target_type": "zen:user", + "relationship_filter": { + "all": [ + { + "field": "role", + "operator": "is", + "value": "4" + }, + { + "field": "tags", + "operator": "includes", + "value": "goofy" + } + ], + "any": [ + { + "field": "role", + "operator": "is_not", + "value": "0" + } + ] + }, + "active": true, + "description": "Test description", + "key": "test_key", + "raw_description": "This is just at test description", + "raw_title": "Raw test title", + "created_at": "2023-02-02T15:36:25Z", + "updated_at": "2023-02-23T10:24:49Z" + }, + { + "id": 9170294642017, + "url": "https://example.zendesk.com/api/v2/organization_fields/9170294642017.json", + "title": "External Test ID", + "type": "text", + "relationship_target_type": "", + "relationship_filter": { + "all": null, + "any": null + }, + "active": true, + "description": "This field contains an external testing ID", + "key": "test_external_id", + "position": 1, + "raw_description": "This field contains an external testing ID", + "raw_title": "External testing ID", + "created_at": "2023-02-06T14:43:05Z", + "updated_at": "2023-02-06T14:43:05Z" + } + ] +} \ No newline at end of file diff --git a/fixture/POST/organization_fields.json b/fixture/POST/organization_fields.json new file mode 100644 index 00000000..1fc3a43c --- /dev/null +++ b/fixture/POST/organization_fields.json @@ -0,0 +1,38 @@ +{ + "organization_field": + { + "id": 1110988024701, + "url": "https://example.zendesk.com/api/v2/organization_fields/1110988024701.json", + "title": "Title", + "type": "lookup", + "relationship_target_type": "zen:user", + "relationship_filter": { + "all": [ + { + "field": "role", + "operator": "is", + "value": "4" + }, + { + "field": "tags", + "operator": "includes", + "value": "goofy" + } + ], + "any": [ + { + "field": "role", + "operator": "is_not", + "value": "0" + } + ] + }, + "active": true, + "description": "Test description", + "key": "test_key", + "raw_description": "This is just at test description", + "raw_title": "Raw test title", + "created_at": "2023-02-02T15:36:25Z", + "updated_at": "2023-02-23T10:24:49Z" + } +} \ No newline at end of file diff --git a/zendesk/api.go b/zendesk/api.go index 5c1b30b2..55878560 100644 --- a/zendesk/api.go +++ b/zendesk/api.go @@ -17,6 +17,7 @@ type API interface { LocaleAPI MacroAPI OrganizationAPI + OrganizationFieldAPI OrganizationMembershipAPI SearchAPI SLAPolicyAPI diff --git a/zendesk/custom_field_option.go b/zendesk/custom_field_option.go index 1c8c12b7..edb0c6a6 100644 --- a/zendesk/custom_field_option.go +++ b/zendesk/custom_field_option.go @@ -9,3 +9,15 @@ type CustomFieldOption struct { URL string `json:"url,omitempty"` Value string `json:"value"` } + +type relationshipFilterObject struct { + Field string `json:"field"` + Operator string `json:"operator"` + Value string `json:"value"` +} + +// RelationshipFilter is struct for value of `relationship_filter` +type RelationshipFilter struct { + All []relationshipFilterObject `json:"all"` + Any []relationshipFilterObject `json:"any"` +} diff --git a/zendesk/mock/client.go b/zendesk/mock/client.go index 19f76d3c..6f4245b7 100644 --- a/zendesk/mock/client.go +++ b/zendesk/mock/client.go @@ -185,6 +185,21 @@ func (mr *ClientMockRecorder) CreateOrganization(arg0, arg1 interface{}) *gomock return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOrganization", reflect.TypeOf((*Client)(nil).CreateOrganization), arg0, arg1) } +// CreateOrganizationField mocks base method. +func (m *Client) CreateOrganizationField(arg0 context.Context, arg1 zendesk.OrganizationField) (zendesk.OrganizationField, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateOrganizationField", arg0, arg1) + ret0, _ := ret[0].(zendesk.OrganizationField) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CreateOrganizationField indicates an expected call of CreateOrganizationField. +func (mr *ClientMockRecorder) CreateOrganizationField(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOrganizationField", reflect.TypeOf((*Client)(nil).CreateOrganizationField), arg0, arg1) +} + // CreateOrganizationMembership mocks base method. func (m *Client) CreateOrganizationMembership(arg0 context.Context, arg1 zendesk.OrganizationMembershipOptions) (zendesk.OrganizationMembership, error) { m.ctrl.T.Helper() @@ -838,6 +853,22 @@ func (mr *ClientMockRecorder) GetOrganizationByExternalID(arg0, arg1 interface{} return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetOrganizationByExternalID", reflect.TypeOf((*Client)(nil).GetOrganizationByExternalID), arg0, arg1) } +// GetOrganizationFields mocks base method. +func (m *Client) GetOrganizationFields(arg0 context.Context) ([]zendesk.OrganizationField, zendesk.Page, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetOrganizationFields", arg0) + ret0, _ := ret[0].([]zendesk.OrganizationField) + ret1, _ := ret[1].(zendesk.Page) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// GetOrganizationFields indicates an expected call of GetOrganizationFields. +func (mr *ClientMockRecorder) GetOrganizationFields(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetOrganizationFields", reflect.TypeOf((*Client)(nil).GetOrganizationFields), arg0) +} + // GetOrganizationMemberships mocks base method. func (m *Client) GetOrganizationMemberships(arg0 context.Context, arg1 *zendesk.OrganizationMembershipListOptions) ([]zendesk.OrganizationMembership, zendesk.Page, error) { m.ctrl.T.Helper() diff --git a/zendesk/organization_field.go b/zendesk/organization_field.go new file mode 100644 index 00000000..e9ba15b3 --- /dev/null +++ b/zendesk/organization_field.go @@ -0,0 +1,75 @@ +package zendesk + +import ( + "context" + "encoding/json" + "time" +) + +// OrganizationField represents the Organization Custom field structure +type OrganizationField struct { + ID int64 `json:"id,omitempty"` + URL string `json:"url,omitempty"` + Title string `json:"title"` + Type string `json:"type"` + RelationshipTargetType string `json:"relationship_target_type"` + RelationshipFilter RelationshipFilter `json:"relationship_filter"` + Active bool `json:"active,omitempty"` + CustomFieldOptions []CustomFieldOption `json:"custom_field_options,omitempty"` + Description string `json:"description,omitempty"` + Key string `json:"key"` + Position int64 `json:"position,omitempty"` + RawDescription string `json:"raw_description,omitempty"` + RawTitle string `json:"raw_title,omitempty"` + RegexpForValidation string `json:"regexp_for_validation,omitempty"` + System bool `json:"system,omitempty"` + Tag string `json:"tag,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` +} + +// OrganizationFieldAPI an interface containing all the organization field related zendesk methods +type OrganizationFieldAPI interface { + GetOrganizationFields(ctx context.Context) ([]OrganizationField, Page, error) + CreateOrganizationField(ctx context.Context, organizationField OrganizationField) (OrganizationField, error) +} + +// GetOrganizationFields fetches organization field list +// ref: https://developer.zendesk.com/api-reference/ticketing/organizations/organization_fields/#list-organization-fields +func (z *Client) GetOrganizationFields(ctx context.Context) ([]OrganizationField, Page, error) { + var data struct { + OrganizationFields []OrganizationField `json:"organization_fields"` + Page + } + + body, err := z.get(ctx, "/organization_fields.json") + if err != nil { + return []OrganizationField{}, Page{}, err + } + + err = json.Unmarshal(body, &data) + if err != nil { + return []OrganizationField{}, Page{}, err + } + return data.OrganizationFields, data.Page, nil +} + +// CreateOrganizationField creates new organization field +// ref: https://developer.zendesk.com/api-reference/ticketing/organizations/organization_fields/#create-organization-field +func (z *Client) CreateOrganizationField(ctx context.Context, organizationField OrganizationField) (OrganizationField, error) { + var data, result struct { + OrganizationField OrganizationField `json:"organization_field"` + } + data.OrganizationField = organizationField + + body, err := z.post(ctx, "/organization_fields.json", data) + if err != nil { + return OrganizationField{}, err + } + + err = json.Unmarshal(body, &result) + if err != nil { + return OrganizationField{}, err + } + return result.OrganizationField, nil +} diff --git a/zendesk/organization_field_test.go b/zendesk/organization_field_test.go new file mode 100644 index 00000000..e375cebc --- /dev/null +++ b/zendesk/organization_field_test.go @@ -0,0 +1,32 @@ +package zendesk + +import ( + "net/http" + "testing" +) + +func TestGetOrganizationFields(t *testing.T) { + mockAPI := newMockAPI(http.MethodGet, "organization_fields.json") + client := newTestClient(mockAPI) + defer mockAPI.Close() + + ticketFields, _, err := client.GetOrganizationFields(ctx) + if err != nil { + t.Fatalf("Failed to get organization fields: %s", err) + } + + if len(ticketFields) != 2 { + t.Fatalf("expected length of organization fields is , but got %d", len(ticketFields)) + } +} + +func TestOrganizationField(t *testing.T) { + mockAPI := newMockAPIWithStatus(http.MethodPost, "organization_fields.json", http.StatusCreated) + client := newTestClient(mockAPI) + defer mockAPI.Close() + + _, err := client.CreateOrganizationField(ctx, OrganizationField{}) + if err != nil { + t.Fatalf("Failed to send request to create organization field: %s", err) + } +}