Skip to content

Commit

Permalink
Add support for CRM Schemas and CRM Properties API
Browse files Browse the repository at this point in the history
  • Loading branch information
sblackstone committed Apr 26, 2023
1 parent bf87cc8 commit 1190267
Show file tree
Hide file tree
Showing 9 changed files with 520 additions and 9 deletions.
2 changes: 1 addition & 1 deletion contact.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ func (s *ContactServiceOp) Update(contactID string, contact interface{}) (*Respo

// Delete deletes a contact.
func (s *ContactServiceOp) Delete(contactID string) error {
return s.client.Delete(s.contactPath + "/" + contactID)
return s.client.Delete(s.contactPath+"/"+contactID, nil)
}

// AssociateAnotherObj associates Contact with another HubSpot objects.
Expand Down
16 changes: 13 additions & 3 deletions crm.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ const (
)

type CRM struct {
Contact ContactService
Deal DealService
Imports CrmImportsService
Contact ContactService
Deal DealService
Imports CrmImportsService
Schemas CrmSchemasService
Properties CrmPropertiesService
}

func newCRM(c *Client) *CRM {
Expand All @@ -29,5 +31,13 @@ func newCRM(c *Client) *CRM {
crmImportsPath: fmt.Sprintf("%s/%s", crmPath, crmImportsBasePath),
client: c,
},
Schemas: &CrmSchemasServiceOp{
crmSchemasPath: fmt.Sprintf("%s/%s", crmPath, crmSchemasPath),
client: c,
},
Properties: &CrmPropertiesServiceOp{
crmPropertiesPath: fmt.Sprintf("%s/%s", crmPath, crmPropertiesPath),
client: c,
},
}
}
7 changes: 4 additions & 3 deletions crm_imports_start.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ import (
)

type CrmImportConfig struct {
Name string `json:"name"`
ImportOperations map[string]string `json:"importOperations"`
Files []CrmImportFileConfig `json:"files"`
Name string `json:"name"`
MarketableContactImport bool `json:"marketableContactImport"`
ImportOperations map[string]string `json:"importOperations"`
Files []CrmImportFileConfig `json:"files"`
}

type CrmImportFilePageConfig struct {
Expand Down
114 changes: 114 additions & 0 deletions crm_properties.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package hubspot

import (
"fmt"
)

const (
crmPropertiesPath = "properties"
)

type CrmPropertiesList struct {
Results []*CrmProperty `json:"results,omitempty"`
}

type CrmProperty struct {
UpdatedAt *HsTime `json:"updatedAt,omitempty"`
CreatedAt *HsTime `json:"createdAt,omitempty"`
ArchivedAt *HsTime `json:"archivedAt,omitempty"`
Name *HsStr `json:"name,omitempty"`
Label *HsStr `json:"label,omitempty"`
Type *HsStr `json:"type,omitempty"`
FieldType *HsStr `json:"fieldType,omitempty"`
Description *HsStr `json:"description,omitempty"`
GroupName *HsStr `json:"groupName,omitempty"`
Options []*CrmPropertyOptions `json:"options,omitempty"`
CreatedUserId *HsStr `json:"createdUserId,omitempty"`
UpdatedUserId *HsStr `json:"updatedUserId,omitempty"`
ReferencedObjectType *HsStr `json:"referencedObjectType,omitempty"`
DisplayOrder *HsInt `json:"displayOrder,omitempty"`
Calculated *HsBool `json:"calculated,omitempty"`
ExternalOptions *HsBool `json:"externalOptions,omitempty"`
Archived *HsBool `json:"archived,omitempty"`
HasUniqueValue *HsBool `json:"hasUniqueValue,omitempty"`
Hidden *HsBool `json:"hidden,omitempty"`
HubspotDefined *HsBool `json:"hubspotDefined,omitempty"`
ShowCurrencySymbol *HsBool `json:"showCurrencySymbol,omitempty"`
ModificationMetaData *CrmPropertyModificationMeta `json:"modificationMetadata,omitempty"`
FormField *HsBool `json:"formField,omitempty"`
CalculationFormula *HsStr `json:"calculationFormula,omitempty"`
}

type CrmPropertyModificationMeta struct {
Archivable *HsBool `json:"archivable,omitempty"`
ReadOnlyDefition *HsBool `json:"readOnlyDefinition,omitempty"`
ReadOnlyValue *HsBool `json:"readOnlyValue,omitempty"`
ReadOnlyOptions *HsBool `json:"readOnlyOptions,omitempty"`
}

type CrmPropertyOptions struct {
Label *HsStr `json:"label,omitempty"`
Value *HsStr `json:"value,omitempty"`
Description *HsStr `json:"description,omitempty"`
DisplayOrder *HsInt `json:"displayOrder,omitempty"`
Hidden *HsBool `json:"hidden,omitempty"`
}

// CrmPropertiesService is an interface of CRM properties endpoints of the HubSpot API.
// Reference: https://developers.hubspot.com/docs/api/crm/properties
type CrmPropertiesService interface {
List(objectType string) (*CrmPropertiesList, error)
Create(objectType string, reqData interface{}) (*CrmProperty, error)
Get(objectType string, propertyName string) (*CrmProperty, error)
Delete(objectType string, propertyName string) error
Update(objectType string, propertyName string, reqData interface{}) (*CrmProperty, error)
}

// CrmPropertiesServiceOp handles communication with the CRM properties endpoint.
type CrmPropertiesServiceOp struct {
client *Client
crmPropertiesPath string
}

var _ CrmPropertiesService = (*CrmPropertiesServiceOp)(nil)

func (s *CrmPropertiesServiceOp) List(objectType string) (*CrmPropertiesList, error) {
var resource CrmPropertiesList
path := fmt.Sprintf("%s/%s", s.crmPropertiesPath, objectType)
if err := s.client.Get(path, &resource, nil); err != nil {
return nil, err
}
return &resource, nil
}

func (s *CrmPropertiesServiceOp) Get(objectType, propertyName string) (*CrmProperty, error) {
var resource CrmProperty
path := fmt.Sprintf("%s/%s/%s", s.crmPropertiesPath, objectType, propertyName)
if err := s.client.Get(path, &resource, nil); err != nil {
return nil, err
}
return &resource, nil
}

func (s *CrmPropertiesServiceOp) Create(objectType string, reqData interface{}) (*CrmProperty, error) {
var resource CrmProperty
path := fmt.Sprintf("%s/%s", s.crmPropertiesPath, objectType)
if err := s.client.Post(path, reqData, &resource); err != nil {
return nil, err
}
return &resource, nil
}

func (s *CrmPropertiesServiceOp) Delete(objectType string, propertyName string) error {
path := fmt.Sprintf("%s/%s/%s", s.crmPropertiesPath, objectType, propertyName)
return s.client.Delete(path, nil)
}

func (s *CrmPropertiesServiceOp) Update(objectType string, propertyName string, reqData interface{}) (*CrmProperty, error) {
var resource CrmProperty
path := fmt.Sprintf("%s/%s/%s", s.crmPropertiesPath, objectType, propertyName)
if err := s.client.Patch(path, reqData, &resource); err != nil {
return nil, err
}
return &resource, nil
}
81 changes: 81 additions & 0 deletions crm_properties_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package hubspot

import (
"fmt"
"os"
"testing"
"time"
)

func TestListCrmProperties(t *testing.T) {
t.SkipNow()
cli, _ := NewClient(SetPrivateAppToken(os.Getenv("PRIVATE_APP_TOKEN")))
// Use crm_schemas:TestCreate() to generate this...
res, err := cli.CRM.Properties.List("cars")
if err != nil {
t.Error(err)
}

if len(res.Results) < 1 {
t.Error("expected len(res.Results) to be > 1")
}
}

func TestGetCrmProperty(t *testing.T) {
t.SkipNow()

cli, _ := NewClient(SetPrivateAppToken(os.Getenv("PRIVATE_APP_TOKEN")))
// Use crm_schemas:TestCreate() to generate this...
res, err := cli.CRM.Properties.Get("cars", "model")
if err != nil {
t.Error(err)
}
if *res.Name != "model" {
t.Errorf("expected res.Name to be model, got %s", res.Name)
}
}

func TestCreateProperty(t *testing.T) {
t.SkipNow()
cli, _ := NewClient(SetPrivateAppToken(os.Getenv("PRIVATE_APP_TOKEN")))
newProp := &CrmProperty{
Name: NewString("mileage"),
Label: NewString("Mileage Label"),
Type: NewString("number"),
FieldType: NewString("number"),
GroupName: NewString("cars_information"),
}

_, err := cli.CRM.Properties.Create("cars", newProp)
if err != nil {
t.Error(err)
return
}
}

func TestUpdateProperty(t *testing.T) {
t.SkipNow()
cli, _ := NewClient(SetPrivateAppToken(os.Getenv("PRIVATE_APP_TOKEN")))

updateProp := make(map[string]interface{})
updateProp["label"] = fmt.Sprintf("Updated Label %s", time.Now().String())

res, err := cli.CRM.Properties.Update("cars", "mileage", &updateProp)
if err != nil {
t.Error(err)
return
}

if res.Label != updateProp["label"] {
t.Errorf("expected res.Label to be %s, got %s", updateProp["label"], res.Label)
}
}

func TestDeleteProperty(t *testing.T) {
t.SkipNow()
cli, _ := NewClient(SetPrivateAppToken(os.Getenv("PRIVATE_APP_TOKEN")))
err := cli.CRM.Properties.Delete("cars", "mileage")
if err != nil {
t.Error(err)
}
}
106 changes: 106 additions & 0 deletions crm_schemas.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package hubspot

import (
"fmt"
)

const (
crmSchemasPath = "schemas"
)

type CrmSchemaAssociation struct {
FromObjectTypeId *HsStr `json:"fromObjectTypeId"`
ToObjectTypeId *HsStr `json:"toObjectTypeId"`
Name *HsStr `json:"name"`
ID *HsStr `json:"id"`
CreatedAt *HsTime `json:"createdAt"`
UpdatedAt *HsTime `json:"updatedAt"`
Cardinality *HsStr `json:"cardinality"`
InverseCardinality *HsStr `json:"inverseCardinality"`
}

type CrmSchemaLabels struct {
Singular *HsStr `json:"singular"`
Plural *HsStr `json:"plural"`
}

type CrmSchemasList struct {
Results []*CrmSchema
}

type CrmSchema struct {
Labels *CrmSchemaLabels `json:"labels,omitempty"`
PrimaryDisplayProperty *HsStr `json:"primaryDisplayProperty,omitempty"`
Archived *HsBool `json:"archived,omitempty"`
ID *HsStr `json:"id,omitempty"`
FullyQualifiedName *HsStr `json:"fullyQualifiedName,omitempty"`
CreatedAt *HsTime `json:"createdAt,omitempty"`
UpdatedAt *HsTime `json:"updatedAt,omitempty"`
ObjectTypeId *HsStr `json:"objectTypeId,omitempty"`
Properties []*CrmProperty `json:"properties,omitempty"`
Associations []*CrmSchemaAssociation `json:"associations,omitempty"`
Name *HsStr `json:"name,omitempty"`
MetaType *HsStr `json:"metaType,omitempty"`
RequiredProperties []*HsStr `json:"requiredProperties,omitempty"`
Restorable *HsBool `json:"restorable,omitempty"`
SearchableProperties []*HsStr `json:"searchableProperties,omitempty"`
SecondaryDisplayProperties []*HsStr `json:"secondaryDisplayProperties,omitempty"`
PortalId *HsInt `json:"portalId"`
}

// CrmSchemasService is an interface of CRM schemas endpoints of the HubSpot API.
// Reference: https://developers.hubspot.com/docs/api/crm/crm-custom-objects
type CrmSchemasService interface {
List() (*CrmSchemasList, error)
Create(reqData interface{}) (*CrmSchema, error)
Get(objectType string) (*CrmSchema, error)
Delete(objectType string, option *RequestQueryOption) error
Update(objectType string, reqData interface{}) (*CrmSchema, error)
}

// CrmSchemasServiceOp handles communication with the CRM schemas endpoint.
type CrmSchemasServiceOp struct {
client *Client
crmSchemasPath string
}

var _ CrmSchemasService = (*CrmSchemasServiceOp)(nil)

func (s *CrmSchemasServiceOp) List() (*CrmSchemasList, error) {
var resource CrmSchemasList
if err := s.client.Get(s.crmSchemasPath, &resource, nil); err != nil {
return nil, err
}
return &resource, nil
}

func (s *CrmSchemasServiceOp) Create(reqData interface{}) (*CrmSchema, error) {
var resource CrmSchema
if err := s.client.Post(s.crmSchemasPath, reqData, &resource); err != nil {
return nil, err
}
return &resource, nil
}

func (s *CrmSchemasServiceOp) Get(objectType string) (*CrmSchema, error) {
var resource CrmSchema
path := fmt.Sprintf("%s/%s", s.crmSchemasPath, objectType)
if err := s.client.Get(path, &resource, nil); err != nil {
return nil, err
}
return &resource, nil
}

func (s *CrmSchemasServiceOp) Delete(objectType string, option *RequestQueryOption) error {
path := fmt.Sprintf("%s/%s", s.crmSchemasPath, objectType)
return s.client.Delete(path, option)
}

func (s *CrmSchemasServiceOp) Update(objectType string, reqData interface{}) (*CrmSchema, error) {
var resource CrmSchema
path := fmt.Sprintf("%s/%s", s.crmSchemasPath, objectType)
if err := s.client.Patch(path, reqData, &resource); err != nil {
return nil, err
}
return &resource, nil
}
Loading

0 comments on commit 1190267

Please sign in to comment.