Skip to content

Commit

Permalink
Tickets and tasks (#24)
Browse files Browse the repository at this point in the history
* add some associations code to ASSOCIATION_DEFINITIONS

* add patch to connection

* create new ticket api file

* add some ticket spec

* ticket update spec

* add task endpoint (get/create

* add ticket_properties.rb

* drop old ruby versions

* replace deprecated Faker::Internet.safe_email by Faker::Internet.email

* add missing newlines

* update test matrix

* rubocop -A

* adapt gemfiles

* fix actions.yml

* nicer ticket_properties_spec.rb

* fix ruby versions

* add default value to task fields in Task#find

* add missing newline

* fix spec

* dry connection post, put and patch methods

* dry connection.modification_query send instead of public_send
  • Loading branch information
Paul-Yves authored Nov 8, 2024
1 parent 54fb692 commit 45531e9
Show file tree
Hide file tree
Showing 24 changed files with 966 additions and 48 deletions.
11 changes: 4 additions & 7 deletions .github/workflows/actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,15 @@ jobs:
strategy:
matrix:
ruby:
- '2.7.x'
- '3.0.x'
- '3.1.x'
- '3.2.6'
- '3.3.6'
active_support:
- 'active_support_6.0.x'
- 'active_support_6.1.x'
- 'active_support_7.0.x'
- 'active_support_7.2.x'
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Setup Ruby
uses: actions/setup-ruby@v1
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
- name: Bundle
Expand Down
7 changes: 7 additions & 0 deletions History.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 0.17.0

* Add various Ticket endpoints (#create!, #update!, #find)
* Add TicketProperties#create!
* Add Task#create! and Task#find
* BREAKING CHANGE : requires ruby 3.2+, as we're not testing against olders versions

## 0.16.0

* Added the possibility to add custom properties to `Meeting#find` and `Meeting#find_by_contact`. #17
Expand Down
5 changes: 0 additions & 5 deletions gemfiles/active_support_6.1.x.gemfile

This file was deleted.

5 changes: 0 additions & 5 deletions gemfiles/active_support_7.0.x.gemfile

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true
source 'https://rubygems.org'

gem "activesupport", "~> 6.0.0"
gem "activesupport", "~> 7.2.0"
gemspec path: '../'
4 changes: 2 additions & 2 deletions hubspot-api-ruby.gemspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Gem::Specification.new do |s|
s.name = "hubspot-api-ruby"
s.version = "0.16.0"
s.version = "0.17.0"
s.require_paths = ["lib"]
s.authors = ["Jonathan"]
s.email = ["[email protected]"]
Expand All @@ -15,7 +15,7 @@ Gem::Specification.new do |s|
"changelog_uri" => "https://github.com/captaincontrat/hubspot-api-ruby/blob/master/History.md"
}

s.required_ruby_version = ">= 2.7"
s.required_ruby_version = ">= 3.1"

# Add runtime dependencies here
s.add_runtime_dependency "activesupport", ">= 4.2.2"
Expand Down
3 changes: 3 additions & 0 deletions lib/hubspot-api-ruby.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
require 'hubspot/oauth'
require 'hubspot/file'
require 'hubspot/meeting'
require 'hubspot/ticket'
require 'hubspot/ticket_properties'
require 'hubspot/task'

module Hubspot
def self.configure(config={})
Expand Down
12 changes: 12 additions & 0 deletions lib/hubspot/association.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,18 @@ class Hubspot::Association
},
"Contact" => {
"Deal" => 4
},
"Ticket" => {
"Contact" => 16,
"Deal" => 28,
"Company" => 339,
"Task" => 229
},
"Task" => {
"Contact" => 204,
"Deal" => 216,
"Company" => 192,
"Ticket" => 230
}
}.freeze

Expand Down
44 changes: 19 additions & 25 deletions lib/hubspot/connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,33 @@ def get_json(path, opts)
handle_response(response).parsed_response
end

def post_json(path, opts)
no_parse = opts[:params].delete(:no_parse) { false }
def post_json(path, options)
modification_query(:post, path, options)
end

url = generate_url(path, opts[:params])
response = post(
url,
body: opts[:body].to_json,
headers: { 'Content-Type' => 'application/json' },
format: :json,
read_timeout: read_timeout(opts),
open_timeout: open_timeout(opts)
)
def put_json(path, options)
modification_query(:put, path, options)
end

def patch_json(path, options)
modification_query(:patch, path, options)
end

def delete_json(path, opts)
url = generate_url(path, opts)
response = delete(url, format: :json, read_timeout: read_timeout(opts), open_timeout: open_timeout(opts))
log_request_and_response url, response, opts[:body]
handle_response(response).yield_self do |r|
no_parse ? r : r.parsed_response
end
handle_response(response)
end

def put_json(path, options)
protected

def modification_query(verb, path, options)
no_parse = options[:params].delete(:no_parse) { false }
url = generate_url(path, options[:params])

response = put(
response = send(
verb,
url,
body: options[:body].to_json,
headers: { "Content-Type" => "application/json" },
Expand All @@ -48,15 +51,6 @@ def put_json(path, options)
end
end

def delete_json(path, opts)
url = generate_url(path, opts)
response = delete(url, format: :json, read_timeout: read_timeout(opts), open_timeout: open_timeout(opts))
log_request_and_response url, response, opts[:body]
handle_response(response)
end

protected

def read_timeout(opts = {})
opts.delete(:read_timeout) || Hubspot::Config.read_timeout
end
Expand Down
46 changes: 46 additions & 0 deletions lib/hubspot/task.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
require 'hubspot/utils'

module Hubspot
#
# HubSpot Tasks API
#
# {https://developers.hubspot.com/beta-docs/guides/api/crm/engagements/tasks}
#
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'

attr_reader :properties, :id

def initialize(response_hash)
@id = response_hash['id']
@properties = response_hash['properties'].deep_symbolize_keys
end

class << self
def create!(params = {}, ticket_id: nil)
associations_hash = { 'associations' => [] }
if ticket_id.present?
associations_hash['associations'] << {
"to": { "id": ticket_id },
"types": [{ "associationCategory": 'HUBSPOT_DEFINED',
"associationTypeId": Hubspot::Association::ASSOCIATION_DEFINITIONS['Task']['Ticket'] }]
}
end
properties = { hs_task_status: 'NOT_STARTED', hs_task_type: 'TODO' }.merge(params)
post_data = associations_hash.merge({ properties: properties })

response = Hubspot::Connection.post_json(TASKS_PATH, params: {}, body: post_data)
new(response)
end

def find(task_id, properties = DEFAULT_TASK_FIELDS)
response = Hubspot::Connection.get_json(TASK_PATH, { task_id: task_id,
properties: properties })
new(response)
end
end
end
end
62 changes: 62 additions & 0 deletions lib/hubspot/ticket.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
require 'hubspot/utils'

module Hubspot
#
# HubSpot Tickets API
#
# {https://developers.hubspot.com/beta-docs/guides/api/crm/objects/tickets}
#
class Ticket
TICKETS_PATH = '/crm/v3/objects/tickets'
TICKET_PATH = '/crm/v3/objects/tickets/:ticket_id'

attr_reader :properties, :id

def initialize(response_hash)
@id = response_hash['id']
@properties = response_hash['properties'].deep_symbolize_keys
end

class << self
def create!(params = {}, contact_id: nil, company_id: nil, deal_id: nil)
associations_hash = { 'associations' => [] }
if contact_id.present?
associations_hash['associations'] << {
"to": { "id": contact_id },
"types": [{ "associationCategory": 'HUBSPOT_DEFINED',
"associationTypeId": Hubspot::Association::ASSOCIATION_DEFINITIONS['Ticket']['Contact'] }]
}
end
if company_id.present?
associations_hash['associations'] << {
"to": { "id": company_id },
"types": [{ "associationCategory": 'HUBSPOT_DEFINED',
"associationTypeId": Hubspot::Association::ASSOCIATION_DEFINITIONS['Ticket']['Company'] }]
}
end
if deal_id.present?
associations_hash['associations'] << {
"to": { "id": deal_id },
"types": [{ "associationCategory": 'HUBSPOT_DEFINED',
"associationTypeId": Hubspot::Association::ASSOCIATION_DEFINITIONS['Ticket']['Deal'] }]
}
end
post_data = associations_hash.merge({ properties: params })

response = Hubspot::Connection.post_json(TICKETS_PATH, params: {}, body: post_data)
new(response)
end

def update!(id, properties = {})
request = { properties: properties }
response = Hubspot::Connection.patch_json(TICKET_PATH, params: { ticket_id: id }, body: request)
new(response)
end

def find(ticket_id)
response = Hubspot::Connection.get_json(TICKET_PATH, { ticket_id: ticket_id })
new(response)
end
end
end
end
10 changes: 10 additions & 0 deletions lib/hubspot/ticket_properties.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module Hubspot
class TicketProperties < Properties
CREATE_PROPERTY_PATH = '/crm/v3/properties/ticket'
class << self
def create!(params = {})
superclass.create!(CREATE_PROPERTY_PATH, params)
end
end
end
end
2 changes: 1 addition & 1 deletion spec/factories/contacts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@

firstname { Faker::Name.first_name }
lastname { Faker::Name.last_name }
email { Faker::Internet.safe_email(name: "#{Time.new.to_i.to_s[-5..-1]}#{(0..3).map { (65 + rand(26)).chr }.join}") }
email { Faker::Internet.email(name: "#{Time.new.to_i.to_s[-5..-1]}#{(0..3).map { (65 + rand(26)).chr }.join}") }
end
end
77 changes: 77 additions & 0 deletions spec/fixtures/vcr_cassettes/task.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 45531e9

Please sign in to comment.