From 7247042070104f084e893d97a9c5fbdcd7255dfe Mon Sep 17 00:00:00 2001 From: Johannes Degn Date: Mon, 18 Dec 2023 10:14:46 +0100 Subject: [PATCH 1/7] Fix default properties --- company_model.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/company_model.go b/company_model.go index 1dbb5f2..59e3207 100644 --- a/company_model.go +++ b/company_model.go @@ -37,8 +37,8 @@ type Company struct { HsAnalyticsLatestSourceData1 *HsStr `json:"hs_analytics_latest_source_data_1,omitempty"` HsAnalyticsLatestSourceData2 *HsStr `json:"hs_analytics_latest_source_data_2,omitempty"` HsAnalyticsLatestSourceTimestamp *HsTime `json:"hs_analytics_latest_source_timestamp,omitempty"` - HsAnalyticsNumPageViews *HsInt `json:"hs_analytics_num_page_views,omitempty"` - HsAnalyticsNumVisits *HsInt `json:"hs_analytics_num_visits,omitempty"` + HsAnalyticsNumPageViews *HsStr `json:"hs_analytics_num_page_views,omitempty"` + HsAnalyticsNumVisits *HsStr `json:"hs_analytics_num_visits,omitempty"` HsAnalyticsSource *HsStr `json:"hs_analytics_source,omitempty"` HsAnalyticsSourceData1 *HsStr `json:"hs_analytics_source_data_1,omitempty"` HsAnalyticsSourceData2 *HsStr `json:"hs_analytics_source_data_2,omitempty"` @@ -53,12 +53,12 @@ type Company struct { HsLastmodifieddate *HsTime `json:"hs_lastmodifieddate,omitempty"` HsLeadStatus *HsStr `json:"hs_lead_status,omitempty"` HsMergedObjectIds *HsStr `json:"hs_merged_object_ids,omitempty"` - HsNumBlockers *HsInt `json:"hs_num_blockers,omitempty"` + HsNumBlockers *HsStr `json:"hs_num_blockers,omitempty"` HsNumChildCompanies *HsInt `json:"hs_num_child_companies,omitempty"` HsNumContactsWithBuyingRoles *HsInt `json:"hs_num_contacts_with_buying_roles,omitempty"` HsNumDecisionMakers *HsInt `json:"hs_num_decision_makers,omitempty"` HsNumOpenDeals *HsInt `json:"hs_num_open_deals,omitempty"` - HsObjectId *HsInt `json:"hs_object_id,omitempty"` + HsObjectId *HsStr `json:"hs_object_id,omitempty"` HsParentCompanyId *HsInt `json:"hs_parent_company_id,omitempty"` HsTotalDealValue *HsInt `json:"hs_total_deal_value,omitempty"` HubspotOwnerAssigneddate *HsTime `json:"hubspot_owner_assigneddate,omitempty"` From eac4b948e6e422aedb2b63be9b40e7136b1de10d Mon Sep 17 00:00:00 2001 From: Johannes Degn Date: Mon, 18 Dec 2023 11:10:37 +0100 Subject: [PATCH 2/7] Add ability to list company associations --- association.go | 11 +++++ company.go | 9 ++++ company_test.go | 109 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+) diff --git a/association.go b/association.go index ad85b5c..a0508c8 100644 --- a/association.go +++ b/association.go @@ -70,3 +70,14 @@ type AssociationResult struct { ID string `json:"id"` Type string `json:"type"` } + +type AssocationType struct { + Category string `json:"category"` + TypeID int `json:"typeId"` + Label string `json:"label"` +} + +// AssociationsResponse is the response from the GET associations endpoint. +type AssociationsResponse struct { + Results []AssociationResult `json:"results"` +} diff --git a/company.go b/company.go index 1865063..8f7f235 100644 --- a/company.go +++ b/company.go @@ -10,6 +10,7 @@ const ( // Reference: https://developers.hubspot.com/docs/api/crm/companies type CompanyService interface { Get(companyID string, company interface{}, option *RequestQueryOption) (*ResponseResource, error) + GetAssociations(companyID, toObjectType string, result *AssociationsResponse) (*AssociationsResponse, error) Create(company interface{}) (*ResponseResource, error) Update(companyID string, company interface{}) (*ResponseResource, error) Delete(companyID string) error @@ -37,6 +38,14 @@ func (s *CompanyServiceOp) Get(companyID string, company interface{}, option *Re return resource, nil } +// GetAssociations gets company associations +func (s *CompanyServiceOp) GetAssociations(companyID, toObjectType string, result *AssociationsResponse) (*AssociationsResponse, error) { + if err := s.client.Get(s.companyPath+"/"+companyID+"/associations/"+toObjectType, result, nil); err != nil { + return nil, err + } + return result, nil +} + // Create creates a new company. // In order to bind the created content, a structure must be specified as an argument. // When using custom fields, please embed hubspot.Company in your own structure. diff --git a/company_test.go b/company_test.go index 0ee2eb2..da01a7f 100644 --- a/company_test.go +++ b/company_test.go @@ -304,6 +304,115 @@ func TestCompanyServiceOp_Get(t *testing.T) { } } +func TestCompanyServiceOp_GetAssociations(t *testing.T) { + type fields struct { + companyPath string + client *hubspot.Client + } + type args struct { + companyID string + toObjectType string + result *hubspot.AssociationsResponse + } + tests := []struct { + name string + fields fields + args args + want *hubspot.AssociationsResponse + wantErr error + }{ + { + name: "Successfully get associations", + fields: fields{ + companyPath: hubspot.ExportCompanyBasePath, + client: hubspot.NewMockClient(&hubspot.MockConfig{ + Status: http.StatusOK, + Header: http.Header{}, + Body: []byte(`{"results":[{"toObjectId":"company002","associationTypes":[{"category":"HUBSPOT_DEFINED","typeId":13,"label":"Child Company"},{"category":"HUBSPOT_DEFINED","typeId":450,"label":null}]},{"toObjectId":"company003","associationTypes":[{"category":"HUBSPOT_DEFINED","typeId":13,"label":"Child Company"},{"category":"HUBSPOT_DEFINED","typeId":450,"label":null}]}]}`), + }), + }, + args: args{ + companyID: "company001", + toObjectType: "company", + result: &hubspot.AssociationsResponse{}, + }, + want: &hubspot.AssociationsResponse{ + Results: []hubspot.AssociationResult{ + { + ID: "company002", + Type: []hubspot.AssocationType{ + { + Category: "HUBSPOT_DEFINED", + TypeID: 13, + Label: "Child Company", + }, + { + Category: "HUBSPOT_DEFINED", + TypeID: 450, + Label: "", + }, + }, + }, + { + ID: "company003", + Type: []hubspot.AssocationType{ + { + Category: "HUBSPOT_DEFINED", + TypeID: 13, + Label: "Child Company", + }, + { + Category: "HUBSPOT_DEFINED", + TypeID: 450, + Label: "", + }, + }, + }, + }, + }, + wantErr: nil, + }, + { + name: "Received invalid request", + fields: fields{ + companyPath: hubspot.ExportCompanyBasePath, + client: hubspot.NewMockClient(&hubspot.MockConfig{ + Status: http.StatusBadRequest, + Header: http.Header{}, + Body: []byte(`{"message": "Invalid input (details will vary based on the error)","correlationId": "aeb5f871-7f07-4993-9211-075dc63e7cbf","category": "VALIDATION_ERROR","links": {"knowledge-base": "https://www.hubspot.com/products/service/knowledge-base"}}`), + }), + }, + args: args{ + companyID: "company001", + toObjectType: "company", + result: nil, + }, + want: nil, + wantErr: &hubspot.APIError{ + HTTPStatusCode: http.StatusBadRequest, + Message: "Invalid input (details will vary based on the error)", + CorrelationID: "aeb5f871-7f07-4993-9211-075dc63e7cbf", + Category: "VALIDATION_ERROR", + Links: hubspot.ErrLinks{ + KnowledgeBase: "https://www.hubspot.com/products/service/knowledge-base", + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := tt.fields.client.CRM.Company.GetAssociations(tt.args.companyID, tt.args.toObjectType, tt.args.result) + if !reflect.DeepEqual(tt.wantErr, err) { + t.Errorf("Get() error mismatch: want %s got %s", tt.wantErr, err) + return + } + if diff := cmp.Diff(tt.want, got, cmpTimeOption); diff != "" { + t.Errorf("Get() response mismatch (-want +got):%s", diff) + } + }) + } +} + func TestCompanyServiceOp_Delete(t *testing.T) { type fields struct { companyPath string From bf63c4717985865ed635d096b917f4ed51206269 Mon Sep 17 00:00:00 2001 From: Johannes Degn Date: Mon, 18 Dec 2023 14:01:38 +0100 Subject: [PATCH 3/7] Add company to company association types --- association.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/association.go b/association.go index a0508c8..f379f1f 100644 --- a/association.go +++ b/association.go @@ -42,6 +42,10 @@ const ( AssociationTypeCompanyToContact AssociationType = "company_to_contact" AssociationTypeCompanyToDeal AssociationType = "company_to_deal" + + AssociationTypeCompanyToCompany AssociationType = "company_to_company" + AssociationTypeChildToParentCompany AssociationType = "child_to_parent_company" + AssociationTypeParentToChildCompany AssociationType = "parent_to_child_company" ) type AssociationConfig struct { From 1be68d1e6e3a9aed585d91a85f7a57f7580500f6 Mon Sep 17 00:00:00 2001 From: Johannes Degn Date: Mon, 18 Dec 2023 14:06:01 +0100 Subject: [PATCH 4/7] Adjust tests --- company_test.go | 32 +++++--------------------------- 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/company_test.go b/company_test.go index da01a7f..727ea76 100644 --- a/company_test.go +++ b/company_test.go @@ -328,7 +328,7 @@ func TestCompanyServiceOp_GetAssociations(t *testing.T) { client: hubspot.NewMockClient(&hubspot.MockConfig{ Status: http.StatusOK, Header: http.Header{}, - Body: []byte(`{"results":[{"toObjectId":"company002","associationTypes":[{"category":"HUBSPOT_DEFINED","typeId":13,"label":"Child Company"},{"category":"HUBSPOT_DEFINED","typeId":450,"label":null}]},{"toObjectId":"company003","associationTypes":[{"category":"HUBSPOT_DEFINED","typeId":13,"label":"Child Company"},{"category":"HUBSPOT_DEFINED","typeId":450,"label":null}]}]}`), + Body: []byte(`{"results":[{"id":"company002","type":"parent_to_child_company"},{"id":"company003","type":"parent_to_child_company"}]}`), }), }, args: args{ @@ -339,34 +339,12 @@ func TestCompanyServiceOp_GetAssociations(t *testing.T) { want: &hubspot.AssociationsResponse{ Results: []hubspot.AssociationResult{ { - ID: "company002", - Type: []hubspot.AssocationType{ - { - Category: "HUBSPOT_DEFINED", - TypeID: 13, - Label: "Child Company", - }, - { - Category: "HUBSPOT_DEFINED", - TypeID: 450, - Label: "", - }, - }, + ID: "company002", + Type: string(hubspot.AssociationTypeParentToChildCompany), }, { - ID: "company003", - Type: []hubspot.AssocationType{ - { - Category: "HUBSPOT_DEFINED", - TypeID: 13, - Label: "Child Company", - }, - { - Category: "HUBSPOT_DEFINED", - TypeID: 450, - Label: "", - }, - }, + ID: "company003", + Type: string(hubspot.AssociationTypeParentToChildCompany), }, }, }, From 1a9edaf44dfc307944036ffa62114de758d3658d Mon Sep 17 00:00:00 2001 From: Johannes Degn Date: Mon, 15 Jan 2024 14:12:27 +0100 Subject: [PATCH 5/7] Remove unused struct --- association.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/association.go b/association.go index f379f1f..943e129 100644 --- a/association.go +++ b/association.go @@ -75,12 +75,6 @@ type AssociationResult struct { Type string `json:"type"` } -type AssocationType struct { - Category string `json:"category"` - TypeID int `json:"typeId"` - Label string `json:"label"` -} - // AssociationsResponse is the response from the GET associations endpoint. type AssociationsResponse struct { Results []AssociationResult `json:"results"` From 2c7677c299ba25d3968c0818b2d54177b778cf39 Mon Sep 17 00:00:00 2001 From: Johannes Degn Date: Thu, 18 Jan 2024 12:42:48 +0100 Subject: [PATCH 6/7] Remove result from argument of GetAssociation --- company.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/company.go b/company.go index 8f7f235..8a20d5a 100644 --- a/company.go +++ b/company.go @@ -10,7 +10,7 @@ const ( // Reference: https://developers.hubspot.com/docs/api/crm/companies type CompanyService interface { Get(companyID string, company interface{}, option *RequestQueryOption) (*ResponseResource, error) - GetAssociations(companyID, toObjectType string, result *AssociationsResponse) (*AssociationsResponse, error) + GetAssociations(companyID, toObjectType string) (*AssociationsResponse, error) Create(company interface{}) (*ResponseResource, error) Update(companyID string, company interface{}) (*ResponseResource, error) Delete(companyID string) error @@ -39,7 +39,8 @@ func (s *CompanyServiceOp) Get(companyID string, company interface{}, option *Re } // GetAssociations gets company associations -func (s *CompanyServiceOp) GetAssociations(companyID, toObjectType string, result *AssociationsResponse) (*AssociationsResponse, error) { +func (s *CompanyServiceOp) GetAssociations(companyID, toObjectType string) (*AssociationsResponse, error) { + result := &AssociationsResponse{} if err := s.client.Get(s.companyPath+"/"+companyID+"/associations/"+toObjectType, result, nil); err != nil { return nil, err } From b66728d946f29fb7b0ab7411d687cc81e20b53bf Mon Sep 17 00:00:00 2001 From: Johannes Degn Date: Thu, 18 Jan 2024 12:45:52 +0100 Subject: [PATCH 7/7] Use ObjectType instead of string --- company.go | 6 +++--- company_test.go | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/company.go b/company.go index 8a20d5a..bb6ee7d 100644 --- a/company.go +++ b/company.go @@ -10,7 +10,7 @@ const ( // Reference: https://developers.hubspot.com/docs/api/crm/companies type CompanyService interface { Get(companyID string, company interface{}, option *RequestQueryOption) (*ResponseResource, error) - GetAssociations(companyID, toObjectType string) (*AssociationsResponse, error) + GetAssociations(companyID string, toObjectType ObjectType) (*AssociationsResponse, error) Create(company interface{}) (*ResponseResource, error) Update(companyID string, company interface{}) (*ResponseResource, error) Delete(companyID string) error @@ -39,9 +39,9 @@ func (s *CompanyServiceOp) Get(companyID string, company interface{}, option *Re } // GetAssociations gets company associations -func (s *CompanyServiceOp) GetAssociations(companyID, toObjectType string) (*AssociationsResponse, error) { +func (s *CompanyServiceOp) GetAssociations(companyID string, toObjectType ObjectType) (*AssociationsResponse, error) { result := &AssociationsResponse{} - if err := s.client.Get(s.companyPath+"/"+companyID+"/associations/"+toObjectType, result, nil); err != nil { + if err := s.client.Get(s.companyPath+"/"+companyID+"/associations/"+string(toObjectType), result, nil); err != nil { return nil, err } return result, nil diff --git a/company_test.go b/company_test.go index 727ea76..2f26de2 100644 --- a/company_test.go +++ b/company_test.go @@ -311,7 +311,7 @@ func TestCompanyServiceOp_GetAssociations(t *testing.T) { } type args struct { companyID string - toObjectType string + toObjectType hubspot.ObjectType result *hubspot.AssociationsResponse } tests := []struct { @@ -379,7 +379,7 @@ func TestCompanyServiceOp_GetAssociations(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := tt.fields.client.CRM.Company.GetAssociations(tt.args.companyID, tt.args.toObjectType, tt.args.result) + got, err := tt.fields.client.CRM.Company.GetAssociations(tt.args.companyID, tt.args.toObjectType) if !reflect.DeepEqual(tt.wantErr, err) { t.Errorf("Get() error mismatch: want %s got %s", tt.wantErr, err) return