diff --git a/lib/basecrm/services/contacts_service.rb b/lib/basecrm/services/contacts_service.rb index 19e1556..d199519 100644 --- a/lib/basecrm/services/contacts_service.rb +++ b/lib/basecrm/services/contacts_service.rb @@ -103,6 +103,28 @@ def update(contact) Contact.new(root[:data]) end + # Upsert a contact + # + # post '/contacts/upsert?filter_param=filter_value + # + # Create a new contact or update an existing, based on a value of a filter or a set of filters. + # At least a single filter - query parameter - is required. If no parameters are present, the request will return an error. + # See full docs https://developers.getbase.com/docs/rest/reference/contacts + # + # @param filters [Hash] - hash contain filters, one level deep e.g. { name: 'string', 'custom_fields[field]': 'value' } + # @param contact [Contact, Hash] - This object's attributes describe the object to be updated or created + # @return [Contact] The resulting object representing updated or created resource. + def upsert(filters, contact) + validate_upsert_filters!(filters) + validate_type!(contact) + + attributes = sanitize(contact) + query_string = URI.encode_www_form(filters) + _, _, root = @client.post("/contacts/upsert?#{query_string}", attributes) + + Contact.new(root[:data]) + end + # Delete a contact # @@ -125,6 +147,11 @@ def validate_type!(contact) raise TypeError unless contact.is_a?(Contact) || contact.is_a?(Hash) end + def validate_upsert_filters!(filters) + raise TypeError unless filters.is_a?(Hash) + raise ArgumentError, "at least one filter is required" if filters.empty? + end + def extract_params!(contact, *args) params = contact.to_h.select{ |k, _| args.include?(k) } raise ArgumentError, "one of required attributes is missing. Expected: #{args.join(',')}" if params.count != args.length diff --git a/lib/basecrm/services/deals_service.rb b/lib/basecrm/services/deals_service.rb index 581bd20..d062ff8 100644 --- a/lib/basecrm/services/deals_service.rb +++ b/lib/basecrm/services/deals_service.rb @@ -105,6 +105,28 @@ def update(deal) Deal.new(root[:data]) end + # Upsert a deal + # + # post '/deals/upsert?filter_param=filter_value + # + # Create a new deal or update an existing, based on a value of a filter or a set of filters. + # At least a single filter - query parameter - is required. If no parameters are present, the request will return an error. + # See full docs https://developers.getbase.com/docs/rest/reference/deals + # + # @param filters [Hash] - hash contain filters, one level deep e.g. { name: 'string', 'custom_fields[field]': 'value' } + # @param deal [Deal, Hash] - This object's attributes describe the object to be updated or created + # @return [Deal] The resulting object representing updated or created resource. + def upsert(filters, deal) + validate_upsert_filters!(filters) + validate_type!(deal) + + attributes = sanitize(deal) + query_string = URI.encode_www_form(filters) + _, _, root = @client.post("/deals/upsert?#{query_string}", attributes) + + Deal.new(root[:data]) + end + # Delete a deal # @@ -127,6 +149,11 @@ def validate_type!(deal) raise TypeError unless deal.is_a?(Deal) || deal.is_a?(Hash) end + def validate_upsert_filters!(filters) + raise TypeError unless filters.is_a?(Hash) + raise ArgumentError, "at least one filter is required" if filters.empty? + end + def extract_params!(deal, *args) params = deal.to_h.select{ |k, _| args.include?(k) } raise ArgumentError, "one of required attributes is missing. Expected: #{args.join(',')}" if params.count != args.length diff --git a/spec/services/contacts_service_spec.rb b/spec/services/contacts_service_spec.rb index 46b81ce..a3532fb 100644 --- a/spec/services/contacts_service_spec.rb +++ b/spec/services/contacts_service_spec.rb @@ -9,6 +9,7 @@ it { should respond_to :destroy } it { should respond_to :find } it { should respond_to :update } + it { should respond_to :upsert } it { should respond_to :where } end @@ -48,6 +49,22 @@ end end + describe :upsert do + it 'raises a TypeError if filters is nil' do + expect(client.contacts.upsert(nil, { name: 'unique_name' }).to raise_error(TypeError) + end + + it 'raises an ArgumentError if filters is empty' do + expect(client.contacts.upsert({}, { name: 'unique_name' }).to raise_error(ArgumentError) + end + + it 'calls the upsert route with encoded filters' do + filters = { last_name: 'unique_name', 'custom_fields[external_id]': 'unique-1' } + contact = create(:contact, last_name: 'unique_name', custom_fields: { external_id: 'unique-1'}) + expect(client.contacts.upsert(filters, contact)).to be_instance_of BaseCRM::Contact + end + end + describe :destroy do it "returns true on success" do @contact = create(:contact) diff --git a/spec/services/deals_service_spec.rb b/spec/services/deals_service_spec.rb index 8f5b0c6..a8e187d 100644 --- a/spec/services/deals_service_spec.rb +++ b/spec/services/deals_service_spec.rb @@ -9,6 +9,7 @@ it { should respond_to :destroy } it { should respond_to :find } it { should respond_to :update } + it { should respond_to :upsert } it { should respond_to :where } end @@ -59,6 +60,22 @@ end end + describe :upsert do + it 'raises a TypeError if filters is nil' do + expect(client.deals.upsert(nil, { name: 'unique_name' }).to raise_error(TypeError) + end + + it 'raises an ArgumentError if filters is empty' do + expect(client.deals.upsert({}, { name: 'unique_name' }).to raise_error(ArgumentError) + end + + it 'calls the upsert route with encoded filters' do + filters = { name: 'unique_name', 'custom_fields[external_id]': 'unique-1' } + deal = create(:deal, name: 'unique_name', custom_fields: { external_id: 'unique-1'}) + expect(client.deals.upsert(filters, deal)).to be_instance_of BaseCRM::Deal + end + end + describe :destroy do it "returns true on success" do @deal = create(:deal)