Repository: nukosuke/go-zendesk
Pull request #265 (2023-02-23 17:08:46)

Add custom organization fields (list and create) methods
Add methods to list and create Organization custom fields.


Patch:
diff --git a/fixture/GET/organization_fields.json b/fixture/GET/organization_fields.json
new file mode 100644
index 0000000..ff83a50
--- /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 0000000..1fc3a43
--- /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 5c1b30b..5587856 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 1c8c12b..edb0c6a 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 19f76d3..6f4245b 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 0000000..e9ba15b
--- /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
+}


Test patch:
diff --git a/zendesk/organization_field_test.go b/zendesk/organization_field_test.go
new file mode 100644
index 0000000..e375ceb
--- /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)
+	}
+}