diff --git a/lib/hubspot/deal.rb b/lib/hubspot/deal.rb index e23d4deb..4785a25d 100644 --- a/lib/hubspot/deal.rb +++ b/lib/hubspot/deal.rb @@ -38,16 +38,15 @@ def create!(portal_id, company_ids, vids, params={}) new(response) end - # Associate a deal with a contact or company - # {http://developers.hubspot.com/docs/methods/deals/associate_deal} - # Usage - # Hubspot::Deal.associate!(45146940, [], [52]) - def associate!(deal_id, company_ids=[], vids=[]) - objecttype = company_ids.any? ? 'COMPANY' : 'CONTACT' - object_ids = (company_ids.any? ? company_ids : vids).join('&id=') - Hubspot::Connection.put_json(ASSOCIATE_DEAL_PATH, params: { deal_id: deal_id, OBJECTTYPE: objecttype, objectId: object_ids}, body: {}) - end - + # Associate a deal with contacts and/or companies + # {http://developers.hubspot.com/docs/methods/deals/associate_deal} + # Can make up to two API calls, one per object type. + # Usage + # Hubspot::Deal.associate!(45146940, [], [52]) + def associate!(deal_id, company_ids=[], vids=[]) + associate(deal_id, 'CONTACT', vids) if vids.any? + associate(deal_id, 'COMPANY', company_ids) if company_ids.any? + end def find(deal_id) response = Hubspot::Connection.get_json(DEAL_PATH, { deal_id: deal_id }) @@ -62,7 +61,7 @@ def recent(opts = {}) response = Hubspot::Connection.get_json(RECENT_UPDATED_PATH, opts) response['results'].map { |d| new(d) } end - + # Find all deals associated to a company # {http://developers.hubspot.com/docs/methods/deals/get-associated-deals} # @param company [Hubspot::Company] the company @@ -74,6 +73,15 @@ def find_by_company(company) response["results"].map { |deal_id| find(deal_id) } end + private + + def associate(deal_id, object_type, ids) + Hubspot::Connection.put_json( + ASSOCIATE_DEAL_PATH, + params: { deal_id: deal_id, OBJECTTYPE: object_type, objectId: ids.join('&id=') }, + body: {} + ) + end end # Archives the contact in hubspot diff --git a/spec/fixtures/vcr_cassettes/deal_associate.yml b/spec/fixtures/vcr_cassettes/deal_associate.yml new file mode 100644 index 00000000..15eba1d7 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/deal_associate.yml @@ -0,0 +1,270 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.hubapi.com/deals/v1/deal?hapikey=demo + body: + encoding: UTF-8 + string: '{"portalId":62515,"associations":{"associatedCompanyIds":[8954037],"associatedVids":[27136]},"properties":[{"name":"amount","value":"30"}]}' + headers: + Content-Type: + - application/json + response: + status: + code: 200 + message: OK + headers: + Date: + - Fri, 06 Jul 2018 14:32:52 GMT + Content-Type: + - application/json;charset=utf-8 + Content-Length: + - '1573' + Connection: + - keep-alive + Set-Cookie: + - __cfduid=d4fc25653f78fef92810e518a4c0984011530887572; expires=Sat, 06-Jul-19 + 14:32:52 GMT; path=/; domain=.hubapi.com; HttpOnly + Access-Control-Allow-Credentials: + - 'false' + X-Trace: + - 2BC4AB761836BFB2ACD9061338A7FBC5A17F51C5B1000000000000000000 + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Expect-Ct: + - max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct" + Server: + - cloudflare + Cf-Ray: + - 4362c87debaea875-CDG + body: + encoding: UTF-8 + string: '{"portalId":62515,"dealId":317824073,"isDeleted":false,"associations":{"associatedVids":[],"associatedCompanyIds":[],"associatedDealIds":[]},"associationCreateFailures":[{"association":{"fromObjectId":317824073,"toObjectId":8954037,"associationCategory":"HUBSPOT_DEFINED","associationTypeId":5,"associationType":"DEAL_TO_COMPANY","timestamp":null},"failReason":"INVALID_OBJECT_IDS","message":"COMPANY=8954037 + is not valid"},{"association":{"fromObjectId":317824073,"toObjectId":27136,"associationCategory":"HUBSPOT_DEFINED","associationTypeId":3,"associationType":"DEAL_TO_CONTACT","timestamp":null},"failReason":"INVALID_OBJECT_IDS","message":"CONTACT=27136 + is not valid"}],"properties":{"amount":{"value":"30","timestamp":1530887572220,"source":"API","sourceId":null,"versions":[{"name":"amount","value":"30","timestamp":1530887572220,"source":"API","sourceVid":[]}]},"hs_lastmodifieddate":{"value":"1530887572220","timestamp":1530887572220,"source":"CALCULATED","sourceId":null,"versions":[{"name":"hs_lastmodifieddate","value":"1530887572220","timestamp":1530887572220,"source":"CALCULATED","sourceVid":[]}]},"hs_createdate":{"value":"1530887572220","timestamp":1530887572220,"source":"API","sourceId":null,"versions":[{"name":"hs_createdate","value":"1530887572220","timestamp":1530887572220,"source":"API","sourceVid":[]}]},"createdate":{"value":"1530887572220","timestamp":1530887572220,"source":"API","sourceId":null,"versions":[{"name":"createdate","value":"1530887572220","timestamp":1530887572220,"source":"API","sourceVid":[]}]}},"imports":[],"stateChanges":[]}' + http_version: + recorded_at: Fri, 06 Jul 2018 14:32:52 GMT +- request: + method: post + uri: https://api.hubapi.com/companies/v2/companies/?hapikey=demo + body: + encoding: UTF-8 + string: '{"properties":[{"name":"name","value":"New Company 1530887572"}]}' + headers: + Content-Type: + - application/json + response: + status: + code: 200 + message: OK + headers: + Date: + - Fri, 06 Jul 2018 14:32:52 GMT + Content-Type: + - application/json;charset=utf-8 + Content-Length: + - '820' + Connection: + - keep-alive + Set-Cookie: + - __cfduid=d020856465a96c17baafdeecd12f23fbf1530887572; expires=Sat, 06-Jul-19 + 14:32:52 GMT; path=/; domain=.hubapi.com; HttpOnly + Access-Control-Allow-Credentials: + - 'false' + X-Trace: + - 2B2E3A967B3C035E3BCB321E536C458833B517A7FC000000000000000000 + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Expect-Ct: + - max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct" + Server: + - cloudflare + Cf-Ray: + - 4362c87ff804a8bd-CDG + body: + encoding: UTF-8 + string: '{"portalId":62515,"companyId":854210387,"isDeleted":false,"properties":{"hs_lastmodifieddate":{"value":"1530887572549","timestamp":1530887572549,"source":"CALCULATED","sourceId":null,"versions":[{"name":"hs_lastmodifieddate","value":"1530887572549","timestamp":1530887572549,"source":"CALCULATED","sourceVid":[]}]},"name":{"value":"New + Company 1530887572","timestamp":1530887572549,"source":"API","sourceId":null,"versions":[{"name":"name","value":"New + Company 1530887572","timestamp":1530887572549,"source":"API","sourceVid":[]}]},"createdate":{"value":"1530887572549","timestamp":1530887572549,"source":"API","sourceId":"API","versions":[{"name":"createdate","value":"1530887572549","timestamp":1530887572549,"sourceId":"API","source":"API","sourceVid":[]}]}},"additionalDomains":[],"stateChanges":[],"mergeAudits":[]}' + http_version: + recorded_at: Fri, 06 Jul 2018 14:32:52 GMT +- request: + method: post + uri: https://api.hubapi.com/contacts/v1/contact?hapikey=demo + body: + encoding: UTF-8 + string: '{"properties":[{"property":"email","value":"newcontact1530887572@hsgem.com"}]}' + headers: + Content-Type: + - application/json + response: + status: + code: 200 + message: OK + headers: + Date: + - Fri, 06 Jul 2018 14:32:53 GMT + Content-Type: + - application/json;charset=utf-8 + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Set-Cookie: + - __cfduid=d8a2b93df22aeb80f892ce3518293240f1530887572; expires=Sat, 06-Jul-19 + 14:32:52 GMT; path=/; domain=.hubapi.com; HttpOnly + Access-Control-Allow-Credentials: + - 'false' + Vary: + - Accept-Encoding + - Accept-Encoding + X-Trace: + - 2B1C7FA0D7115A67CC9FA13C465CD4D455ABD19554000000000000000000 + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Expect-Ct: + - max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct" + Server: + - cloudflare + Cf-Ray: + - 4362c881fda4bd79-CDG + body: + encoding: UTF-8 + string: '{"vid":7802824,"canonical-vid":7802824,"merged-vids":[],"portal-id":62515,"is-contact":true,"profile-token":"AO_T-mPDnTpIsRHz-tU268FcDFmOuw_M6KeF_jvOmkW7abRXBzP5W3pLheu2cw6mztBvw7KQ8PZJtSOjDZEq4bexOPAavPyxfApYcqCNYtvP83uogxGlT_GJWOvT-N2V8X_TOtPBY_vC","profile-url":"https://app.hubspot.com/contacts/62515/lists/public/contact/_AO_T-mPDnTpIsRHz-tU268FcDFmOuw_M6KeF_jvOmkW7abRXBzP5W3pLheu2cw6mztBvw7KQ8PZJtSOjDZEq4bexOPAavPyxfApYcqCNYtvP83uogxGlT_GJWOvT-N2V8X_TOtPBY_vC/","properties":{"email":{"value":"newcontact1530887572@hsgem.com","versions":[{"value":"newcontact1530887572@hsgem.com","source-type":"API","source-id":null,"source-label":null,"timestamp":1530887572881,"selected":false}]}},"form-submissions":[],"list-memberships":[],"identity-profiles":[{"vid":7802824,"is-deleted":false,"is-contact":false,"pointer-vid":0,"previous-vid":0,"linked-vids":[],"saved-at-timestamp":0,"deleted-changed-timestamp":0,"identities":[{"type":"EMAIL","value":"newcontact1530887572@hsgem.com","timestamp":1530887572886,"is-primary":true,"source":"UNSPECIFIED"},{"type":"LEAD_GUID","value":"d17f14b4-00a6-4337-8c2d-963a6eb80f2e","timestamp":1530887572896,"source":"UNSPECIFIED"}]}],"merge-audits":[]}' + http_version: + recorded_at: Fri, 06 Jul 2018 14:32:53 GMT +- request: + method: put + uri: https://api.hubapi.com/deals/v1/deal/317824073/associations/CONTACT?hapikey=demo&id=7802824 + body: + encoding: UTF-8 + string: "{}" + headers: + Content-Type: + - application/json + response: + status: + code: 204 + message: No Content + headers: + Date: + - Fri, 06 Jul 2018 14:32:53 GMT + Content-Type: + - application/json;charset=utf-8 + Connection: + - keep-alive + Set-Cookie: + - __cfduid=d8bf90dfeeee009071af6884dbccd059a1530887573; expires=Sat, 06-Jul-19 + 14:32:53 GMT; path=/; domain=.hubapi.com; HttpOnly + Access-Control-Allow-Credentials: + - 'false' + X-Trace: + - 2BE75680918097F05D4AC3C17173A7477FD470EA33000000000000000000 + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Expect-Ct: + - max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct" + Server: + - cloudflare + Cf-Ray: + - 4362c885d9efa863-CDG + body: + encoding: UTF-8 + string: '' + http_version: + recorded_at: Fri, 06 Jul 2018 14:32:53 GMT +- request: + method: put + uri: https://api.hubapi.com/deals/v1/deal/317824073/associations/COMPANY?hapikey=demo&id=854210387 + body: + encoding: UTF-8 + string: "{}" + headers: + Content-Type: + - application/json + response: + status: + code: 204 + message: No Content + headers: + Date: + - Fri, 06 Jul 2018 14:32:54 GMT + Content-Type: + - application/json;charset=utf-8 + Connection: + - keep-alive + Set-Cookie: + - __cfduid=dab99aa5759398480a970dbcf67515be41530887573; expires=Sat, 06-Jul-19 + 14:32:53 GMT; path=/; domain=.hubapi.com; HttpOnly + Access-Control-Allow-Credentials: + - 'false' + X-Trace: + - 2B2046BCCA82D247A9C70E865C875FA75F5BF31387000000000000000000 + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Expect-Ct: + - max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct" + Server: + - cloudflare + Cf-Ray: + - 4362c8883baeb7ad-CDG + body: + encoding: UTF-8 + string: '' + http_version: + recorded_at: Fri, 06 Jul 2018 14:32:54 GMT +- request: + method: get + uri: https://api.hubapi.com/deals/v1/deal/317824073?hapikey=demo + body: + encoding: US-ASCII + string: '' + headers: + 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: + - Fri, 06 Jul 2018 14:32:54 GMT + Content-Type: + - application/json;charset=utf-8 + Content-Length: + - '428' + Connection: + - keep-alive + Set-Cookie: + - __cfduid=d78bcd806c7999c52c5acca015e0143951530887574; expires=Sat, 06-Jul-19 + 14:32:54 GMT; path=/; domain=.hubapi.com; HttpOnly + Access-Control-Allow-Credentials: + - 'false' + Vary: + - Accept-Encoding, User-Agent + X-Trace: + - 2BFE43E5CB255E4DA96E6A2D2FD398FB17801212AA000000000000000000 + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Expect-Ct: + - max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct" + Server: + - cloudflare + Cf-Ray: + - 4362c88bcb16b7a1-CDG + body: + encoding: ASCII-8BIT + string: '{"portalId":62515,"dealId":317824073,"isDeleted":false,"associations":{"associatedVids":[7802824],"associatedCompanyIds":[854210387],"associatedDealIds":[]},"properties":{"amount":{"value":"30","timestamp":1530887572220,"source":"API","sourceId":null,"versions":[{"name":"amount","value":"30","timestamp":1530887572220,"source":"API","sourceVid":[]}]},"hs_lastmodifieddate":{"value":"1530887573375","timestamp":1530887573375,"source":"CALCULATED","sourceId":null,"versions":[{"name":"hs_lastmodifieddate","value":"1530887573375","timestamp":1530887573375,"source":"CALCULATED","sourceVid":[]}]},"hs_analytics_source":{"value":"","timestamp":1530887572588,"source":"DEALS","sourceId":"deal + sync with no associated contacts","versions":[{"name":"hs_analytics_source","value":"","timestamp":1530887572588,"sourceId":"deal + sync with no associated contacts","source":"DEALS","sourceVid":[]}]},"num_associated_contacts":{"value":"1","timestamp":0,"source":"CALCULATED","sourceId":null,"versions":[{"name":"num_associated_contacts","value":"1","source":"CALCULATED","sourceVid":[]}]},"hs_createdate":{"value":"1530887572220","timestamp":1530887572220,"source":"API","sourceId":null,"versions":[{"name":"hs_createdate","value":"1530887572220","timestamp":1530887572220,"source":"API","sourceVid":[]}]},"createdate":{"value":"1530887572220","timestamp":1530887572220,"source":"API","sourceId":null,"versions":[{"name":"createdate","value":"1530887572220","timestamp":1530887572220,"source":"API","sourceVid":[]}]},"hs_analytics_source_data_2":{"value":"","timestamp":1530887572588,"source":"DEALS","sourceId":"deal + sync with no associated contacts","versions":[{"name":"hs_analytics_source_data_2","value":"","timestamp":1530887572588,"sourceId":"deal + sync with no associated contacts","source":"DEALS","sourceVid":[]}]},"hs_analytics_source_data_1":{"value":"","timestamp":1530887572588,"source":"DEALS","sourceId":"deal + sync with no associated contacts","versions":[{"name":"hs_analytics_source_data_1","value":"","timestamp":1530887572588,"sourceId":"deal + sync with no associated contacts","source":"DEALS","sourceVid":[]}]}},"imports":[],"stateChanges":[]}' + http_version: + recorded_at: Fri, 06 Jul 2018 14:32:54 GMT +recorded_with: VCR 4.0.0 diff --git a/spec/lib/hubspot/deal_spec.rb b/spec/lib/hubspot/deal_spec.rb index 3692f3d1..12303fc4 100644 --- a/spec/lib/hubspot/deal_spec.rb +++ b/spec/lib/hubspot/deal_spec.rb @@ -28,6 +28,22 @@ its(:vids) { should eql [vid]} end + describe ".associate" do + cassette "deal_associate" + let(:deal) { Hubspot::Deal.create!(portal_id, [company_id], [vid], { amount: amount}) } + let(:company) { Hubspot::Company.create!("New Company #{Time.now.to_i}") } + let(:contact) { Hubspot::Contact.create!("newcontact#{Time.now.to_i}@hsgem.com") } + + subject { Hubspot::Deal.associate!(deal.deal_id, [company.vid], [contact.vid]) } + + it 'associates the deal to the contact and the company' do + subject + find_deal = Hubspot::Deal.find(deal.deal_id) + find_deal.company_ids.should eql [company.vid] + find_deal.vids.should eql [contact.vid] + end + end + describe ".find" do cassette "deal_find" let(:deal) {Hubspot::Deal.create!(portal_id, [company_id], [vid], { amount: amount})}