diff --git a/History.md b/History.md index cb79324c..2332310e 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +## 0.19.0 + +* Add Task#search endpoint +* Add Task#update! endpoint + ## 0.18.0 * BREAKING CHANGE : Ticket#create! and Task#create now takes association param (array), build it using Association.build_association_param diff --git a/hubspot-api-ruby.gemspec b/hubspot-api-ruby.gemspec index ce14bf37..44843ea0 100644 --- a/hubspot-api-ruby.gemspec +++ b/hubspot-api-ruby.gemspec @@ -1,6 +1,6 @@ Gem::Specification.new do |s| s.name = "hubspot-api-ruby" - s.version = "0.18.0" + s.version = "0.19.0" s.require_paths = ["lib"] s.authors = ["Jonathan"] s.email = ["jonathan@hoggo.com"] diff --git a/lib/hubspot/task.rb b/lib/hubspot/task.rb index d297e9bd..02db722a 100644 --- a/lib/hubspot/task.rb +++ b/lib/hubspot/task.rb @@ -8,9 +8,10 @@ module Hubspot # class Task TASKS_PATH = '/crm/v3/objects/tasks' - TASK_PATH = '/crm/v3/objects/tasks/:task_id' - DEFAULT_TASK_FIELDS = 'hs_timestamp,hs_task_body,hubspot_owner_id,hs_task_subject,hs_task_status,hs_task_priority,'\ - 'hs_task_type,hs_task_reminders' + SEARCH_PATH = '/crm/v3/objects/tasks/search' + TASK_PATH = '/crm/v3/objects/tasks/:task_id' + DEFAULT_TASK_FIELDS = %w[hs_timestamp hs_task_body hubspot_owner_id hs_task_subject hs_task_status hs_task_priority + hs_task_type hs_task_reminders].freeze attr_reader :properties, :id @@ -33,6 +34,15 @@ def find(task_id, properties = DEFAULT_TASK_FIELDS) response = Hubspot::Connection.get_json(TASK_PATH, task_id: task_id, properties:) new(response) end + + def search(properties = DEFAULT_TASK_FIELDS, body: {}) + Hubspot::Connection.post_json(SEARCH_PATH, params: {}, body: { properties: }.merge(body)) + end + + def update!(task_id, properties = {}) + response = Hubspot::Connection.patch_json(TASK_PATH, params: { task_id: }, body: { properties: }) + new(response) + end end end end diff --git a/spec/fixtures/vcr_cassettes/task_search.yml b/spec/fixtures/vcr_cassettes/task_search.yml new file mode 100644 index 00000000..676ed18e --- /dev/null +++ b/spec/fixtures/vcr_cassettes/task_search.yml @@ -0,0 +1,63 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.hubapi.com/crm/v3/objects/tasks/search + body: + encoding: UTF-8 + string: '{"properties":["hs_task_subject","hs_task_status"],"filterGroups":[{"filters":[{"propertyName":"associations.ticket","operator":"EQ","value":"16676542642"}]}]}' + headers: + Authorization: + - Bearer + Content-Type: + - application/json + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Tue, 10 Dec 2024 10:58:44 GMT + Content-Type: + - application/json;charset=utf-8 + Content-Length: + - '668' + Connection: + - keep-alive + Cf-Ray: + - 8efcb8b1495ebb66-CDG + Cf-Cache-Status: + - DYNAMIC + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - origin, Accept-Encoding + Access-Control-Allow-Credentials: + - 'false' + X-Content-Type-Options: + - nosniff + X-Hubspot-Correlation-Id: + - d376baf0-c1bf-485e-a9e0-2e3465050ed0 + X-Hubspot-Ratelimit-Daily: + - '250000' + X-Hubspot-Ratelimit-Daily-Remaining: + - '249951' + Report-To: + - '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=BrX7U8DWQkvjKCExKZK23mBYb7LFsekY3TVQQlWQIiDxiLnYpWEloGa26RxB4Rx67WIwmGfgZSpU5QNdm2evj4kFbISEB%2F8%2BVvK2%2B3z8ZBbDSE%2FnIvUwXB7mS5S1TVqpbXdGHcJgdnY8j1oa"}],"group":"cf-nel","max_age":604800}' + Nel: + - '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}' + Server: + - cloudflare + body: + encoding: ASCII-8BIT + string: '{"total":2,"results":[{"id":"65090432307","properties":{"hs_createdate":"2024-11-21T13:00:55.209Z","hs_lastmodifieddate":"2024-12-10T10:07:17.005Z","hs_object_id":"65090432307","hs_task_status":"COMPLETED","hs_task_subject":"Nouveau + message client"},"createdAt":"2024-11-21T13:00:55.209Z","updatedAt":"2024-12-10T10:07:17.005Z","archived":false},{"id":"65476695429","properties":{"hs_createdate":"2024-11-27T11:07:45.738Z","hs_lastmodifieddate":"2024-11-28T11:07:46.573Z","hs_object_id":"65476695429","hs_task_status":"NOT_STARTED","hs_task_subject":"Nouvelle + commande"},"createdAt":"2024-11-27T11:07:45.738Z","updatedAt":"2024-11-28T11:07:46.573Z","archived":false}]}' + recorded_at: Tue, 10 Dec 2024 10:58:44 GMT +recorded_with: VCR 6.3.1 diff --git a/spec/fixtures/vcr_cassettes/task_update.yml b/spec/fixtures/vcr_cassettes/task_update.yml new file mode 100644 index 00000000..0016f144 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/task_update.yml @@ -0,0 +1,71 @@ +--- +http_interactions: +- request: + method: patch + uri: https://api.hubapi.com/crm/v3/objects/tasks/64483143324 + body: + encoding: UTF-8 + string: '{"properties":{"hs_task_status":"COMPLETED"}}' + headers: + Authorization: + - Bearer + Content-Type: + - application/json + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Tue, 10 Dec 2024 11:06:00 GMT + Content-Type: + - application/json;charset=utf-8 + Content-Length: + - '1091' + Connection: + - keep-alive + Cf-Ray: + - 8efcc356ff020214-CDG + Cf-Cache-Status: + - DYNAMIC + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - origin, Accept-Encoding + Access-Control-Allow-Credentials: + - 'false' + X-Content-Type-Options: + - nosniff + X-Hubspot-Correlation-Id: + - cc683884-44eb-420c-9709-7ba07fd69c53 + X-Hubspot-Ratelimit-Daily: + - '250000' + X-Hubspot-Ratelimit-Daily-Remaining: + - '249950' + X-Hubspot-Ratelimit-Interval-Milliseconds: + - '10000' + X-Hubspot-Ratelimit-Max: + - '100' + X-Hubspot-Ratelimit-Remaining: + - '99' + X-Hubspot-Ratelimit-Secondly: + - '10' + X-Hubspot-Ratelimit-Secondly-Remaining: + - '9' + Report-To: + - '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=I7rnO5qbdvsw0jMEswzfVrjIg3WAYqgf0JA8YJVZRpB74D1RCcsv3UMAM9wvh05JVToKpelwO6yZ10QpOmm%2FK75Vi2ij4h23%2BAMx627KIF6nl8urZQ7ZZcZz1%2FdZcnjAxho6%2FkhkYq6BteW1"}],"group":"cf-nel","max_age":604800}' + Nel: + - '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}' + Server: + - cloudflare + body: + encoding: ASCII-8BIT + string: '{"id":"64483143324","properties":{"hs_all_owner_ids":"31871900","hs_createdate":"2024-11-13T15:17:14.590Z","hs_lastmodifieddate":"2024-12-10T11:06:00.427Z","hs_object_id":"64483143324","hs_object_source":"INTEGRATION","hs_object_source_id":"1024738","hs_object_source_label":"INTEGRATION","hs_pipeline":"3d314325-1b2a-4225-9388-375f49c57ec3","hs_pipeline_stage":"af0e6a5c-2ea3-4c72-b69f-7c6cb3fdb591","hs_task_completion_count":"1","hs_task_completion_date":"2024-12-10T11:06:00.427Z","hs_task_is_completed":"1","hs_task_is_completed_call":"0","hs_task_is_completed_email":"0","hs_task_is_completed_linked_in":"0","hs_task_is_completed_sequence":"0","hs_task_is_overdue":"false","hs_task_is_past_due_date":"true","hs_task_missed_due_date":"true","hs_task_missed_due_date_count":"1","hs_task_status":"COMPLETED","hs_task_type":"TODO","hs_timestamp":"2024-11-12T00:00:00Z","hs_user_ids_of_all_owners":"5555888","hubspot_owner_assigneddate":"2024-11-13T15:17:14.590Z","hubspot_owner_id":"31871900"},"createdAt":"2024-11-13T15:17:14.590Z","updatedAt":"2024-12-10T11:06:00.427Z","archived":false}' + recorded_at: Tue, 10 Dec 2024 11:06:00 GMT +recorded_with: VCR 6.3.1 diff --git a/spec/lib/hubspot/task_spec.rb b/spec/lib/hubspot/task_spec.rb index 343cef8d..89f61c74 100644 --- a/spec/lib/hubspot/task_spec.rb +++ b/spec/lib/hubspot/task_spec.rb @@ -10,7 +10,7 @@ Hubspot::Association.build_association_param('Task', 'Ticket', 16_174_569_112), Hubspot::Association.build_association_param('Task', 'Contact', 75_761_595_194), Hubspot::Association.build_association_param('Task', 'Company', 25_571_271_600), - Hubspot::Association.build_association_param('Task', 'Deal', 28_806_796_888), + Hubspot::Association.build_association_param('Task', 'Deal', 28_806_796_888) ] described_class.create!(params, associations:) end @@ -47,4 +47,35 @@ end end end + + describe 'search' do + subject(:search) do + body = { filterGroups: [ + { filters: [{ propertyName: 'associations.ticket', operator: 'EQ', + value: '16676542642' }] } + ] } + described_class.search(%w[hs_task_subject hs_task_status], body:) + end + + it 'returns list of tasks matching search body' do + VCR.use_cassette 'task_search' do + expect(search['total']).to eq(2) + expect(search['results'].map { |r| r['id'] }).to contain_exactly('65090432307', '65476695429') + end + end + end + + describe 'update!' do + let(:task_id) { 64_483_143_324 } + let(:properties) { { hs_task_status: 'COMPLETED' } } + + subject(:update_task) { described_class.update!(task_id, properties) } + + it 'updates existing task, returns the updated entity' do + VCR.use_cassette 'task_update' do + task = update_task + expect(task.properties[:hs_task_status]).to eq('COMPLETED') + end + end + end end