Class: ZohoApi::Crm

Inherits:
Object
  • Object
show all
Includes:
HTTMultiParty, ZohoApiFieldUtils, ZohoApiFinders
Defined in:
lib/zoho_api.rb

Overview

noinspection RubyStringKeysInHashInspection

Constant Summary

Constants included from ZohoApiFinders

ZohoApiFinders::NUMBER_OF_RECORDS_TO_GET

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from ZohoApiFinders

#find_record_by_field, #find_record_by_id, #find_record_by_related_id, #find_records

Methods included from ZohoApiFieldUtils

#add_field, #adjust_tag_case, #clean_field_name?, #create_and_add_field_value_pair, #extract_field, #extract_fields_from_response, #fields, #fields_from_api, #fields_from_record, #fields_original, #hashed_field_value_pairs, #reflect_module_fields, #to_hash, #to_hash_with_id, #update_module_fields, #user_fields

Constructor Details

#initialize(auth_token, modules, ignore_fields, fields = nil) ⇒ Crm

Returns a new instance of Crm.



30
31
32
33
34
35
# File 'lib/zoho_api.rb', line 30

def initialize(auth_token, modules, ignore_fields, fields = nil)
  @auth_token = auth_token
  @modules = %w(Accounts Contacts Events Leads Potentials Tasks Users).concat(modules).uniq
  @module_fields = fields.nil? ? reflect_module_fields : fields
  @ignore_fields = ignore_fields
end

Instance Attribute Details

#auth_tokenObject (readonly)

debug_output $stderr



28
29
30
# File 'lib/zoho_api.rb', line 28

def auth_token
  @auth_token
end

#module_fieldsObject (readonly)

debug_output $stderr



28
29
30
# File 'lib/zoho_api.rb', line 28

def module_fields
  @module_fields
end

Instance Method Details

#add_record(module_name, fields_values_hash) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/zoho_api.rb', line 37

def add_record(module_name, fields_values_hash)
  x = REXML::Document.new
  element = x.add_element module_name
  row = element.add_element 'row', {'no' => '1'}
  fields_values_hash.each_pair { |k, v| add_field(row, ApiUtils.symbol_to_string(k), v) }
  r = self.class.post(create_url(module_name, 'insertRecords'),
                      :query => {:newFormat => 1, :authtoken => @auth_token,
                                 :scope => 'crmapi', :xmlData => x, :wfTrigger => 'true'},
                      :headers => {'Content-length' => '0'})
  check_for_errors(r)
  x_r = REXML::Document.new(r.body).elements.to_a('//recorddetail')
  to_hash(x_r, module_name)[0]
end

#attach_file(module_name, record_id, file_path, file_name) ⇒ Object

Raises:

  • (RuntimeError)


51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/zoho_api.rb', line 51

def attach_file(module_name, record_id, file_path, file_name)
  mime_type = (MIME::Types.type_for(file_path)[0] || MIME::Types['application/octet-stream'][0])
  url_path = create_url(module_name, "uploadFile?authtoken=#{@auth_token}&scope=crmapi&id=#{record_id}")
  url = URI.parse(create_url(module_name, url_path))
  io = UploadIO.new(file_path, mime_type, file_name)
  req = Net::HTTP::Post::Multipart.new url_path, 'content' => io
  http = Net::HTTP.new(url.host, url.port)
  http.use_ssl = true
  res = http.start do |h|
    h.request(req)
  end
  raise(RuntimeError, "[RubyZoho] Attach of file #{file_path} to module #{module_name} failed.") unless res.code == '200'
  res.code
end

#check_for_errors(response) ⇒ Object

Raises:

  • (RuntimeError)


66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/zoho_api.rb', line 66

def check_for_errors(response)
  raise(RuntimeError, "Web service call failed with #{response.code}") unless response.code == 200
  x = REXML::Document.new(response.body)

  # updateRelatedRecords returns two codes one in the status tag and another in a success tag, we want the
  # code under the success tag in this case
  code = REXML::XPath.first(x, '//success/code') || REXML::XPath.first(x, '//code')

  # 4422 code is no records returned, not really an error
  # TODO: find out what 5000 is
  # 4800 code is returned when building an association. i.e Adding a product to a lead. Also this doesn't return a message
  raise(RuntimeError, "Zoho Error Code #{code.text}: #{REXML::XPath.first(x, '//message').text}.") unless code.nil? || %w(4422 5000 4800).index(code.text)

  return code.text unless code.nil?
  response.code
end

#create_url(module_name, api_call) ⇒ Object



83
84
85
# File 'lib/zoho_api.rb', line 83

def create_url(module_name, api_call)
  "https://crm.zoho.com/crm/private/xml/#{module_name}/#{api_call}"
end

#delete_record(module_name, record_id) ⇒ Object



87
88
89
# File 'lib/zoho_api.rb', line 87

def delete_record(module_name, record_id)
  post_action(module_name, record_id, 'deleteRecords')
end

#extract_user_name_and_attribs(node) ⇒ Object



203
204
205
206
207
208
209
210
# File 'lib/zoho_api.rb', line 203

def extract_user_name_and_attribs(node)
  record = {}
  record.merge!({:user_name => node.text})
  node.attributes.each_pair do |k, v|
    record.merge!({k.to_s.to_sym => v.to_string.match(/'(.*?)'/).to_s.gsub('\'', '')})
  end
  record
end

#extract_users_from_xml_response(response) ⇒ Object



191
192
193
194
195
196
197
198
199
200
201
# File 'lib/zoho_api.rb', line 191

def extract_users_from_xml_response(response)
  x = REXML::Document.new(response.body).elements.to_a('/users')
  result = []
  x.each do |e|
    e.elements.to_a.each do |node|
      record = extract_user_name_and_attribs(node)
      result << record
    end
  end
  result
end

#first(module_name) ⇒ Object



91
92
93
# File 'lib/zoho_api.rb', line 91

def first(module_name)
  some(module_name, 1, 1)
end

#method_name?(n) ⇒ Boolean

Returns:

  • (Boolean)


95
96
97
# File 'lib/zoho_api.rb', line 95

def method_name?(n)
  /[@$"]/ !~ n.inspect
end

#post_action(module_name, record_id, action_type) ⇒ Object

Raises:

  • ('Adding contact failed')


99
100
101
102
103
104
105
106
# File 'lib/zoho_api.rb', line 99

def post_action(module_name, record_id, action_type)
  r = self.class.post(create_url(module_name, action_type),
                      :query => {:newFormat => 1, :authtoken => @auth_token,
                                 :scope => 'crmapi', :id => record_id},
                      :headers => {'Content-length' => '0'})
  raise('Adding contact failed', RuntimeError, r.response.body.to_s) unless r.response.code == '200'
  check_for_errors(r)
end

#primary_key(module_name) ⇒ Object



108
109
110
111
112
# File 'lib/zoho_api.rb', line 108

def primary_key(module_name)
  activity_keys = {'Tasks' => :activityid, 'Events' => :activityid, 'Calls' => :activityid}
  return activity_keys[module_name] unless activity_keys[module_name].nil?
  (module_name.downcase.chop + 'id').to_sym
end

#primary_key?(module_name, field_name) ⇒ Boolean

Returns:

  • (Boolean)


114
115
116
117
118
119
120
# File 'lib/zoho_api.rb', line 114

def primary_key?(module_name, field_name)
  return nil if field_name.nil? || module_name.nil?
  fn = field_name.class == String ? field_name : field_name.to_s
  return true if fn == 'id'
  return true if %w[Calls Events Tasks].index(module_name) && fn.downcase == 'activityid'
  fn.downcase.gsub('id', '') == module_name.chop.downcase
end

Returns:

  • (Boolean)


122
123
124
125
126
127
# File 'lib/zoho_api.rb', line 122

def related_id?(module_name, field_name)
  field = field_name.to_s
  return false if field.rindex('id').nil?
  return false if %w[Calls Events Tasks].index(module_name) && field_name.downcase == 'activityid'
  field.downcase.gsub('id', '') != module_name.chop.downcase
end


129
130
131
132
133
134
135
136
# File 'lib/zoho_api.rb', line 129

def related_records(parent_module, parent_record_id, related_module)
  r = self.class.get(create_url("#{related_module}", 'getRelatedRecords'),
                     :query => {:newFormat => 1, :authtoken => @auth_token, :scope => 'crmapi',
                                :parentModule => parent_module, :id => parent_record_id})

  REXML::Document.new(r.body).elements.to_a("/response/result/#{parent_module}/row")
  check_for_errors(r)
end

#some(module_name, index = 1, number_of_records = nil, sort_column = :id, sort_order = :asc) ⇒ Object



138
139
140
141
142
143
144
145
146
147
# File 'lib/zoho_api.rb', line 138

def some(module_name, index = 1, number_of_records = nil, sort_column = :id, sort_order = :asc)
  r = self.class.get(create_url(module_name, 'getRecords'),
                     :query => {:newFormat => 2, :authtoken => @auth_token, :scope => 'crmapi',
                                :sortColumnString => sort_column, :sortOrderString => sort_order,
                                :fromIndex => index, :toIndex => index + (number_of_records || NUMBER_OF_RECORDS_TO_GET) - 1})
  return nil unless r.response.code == '200'
  check_for_errors(r)
  x = REXML::Document.new(r.body).elements.to_a("/response/result/#{module_name}/row")
  to_hash(x, module_name)
end

#update_record(module_name, id, fields_values_hash) ⇒ Object



166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/zoho_api.rb', line 166

def update_record(module_name, id, fields_values_hash)
  x = REXML::Document.new
  contacts = x.add_element module_name
  row = contacts.add_element 'row', {'no' => '1'}
  fields_values_hash.each_pair { |k, v| add_field(row, ApiUtils.symbol_to_string(k), v) }
  r = self.class.post(create_url(module_name, 'updateRecords'),
                      :query => {:newFormat => 1, :authtoken => @auth_token,
                                 :scope => 'crmapi', :id => id,
                                 :xmlData => x, :wfTrigger => 'true'},
                      :headers => {'Content-length' => '0'})
  check_for_errors(r)
  x_r = REXML::Document.new(r.body).elements.to_a('//recorddetail')
  to_hash_with_id(x_r, module_name)[0]
end


149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/zoho_api.rb', line 149

def update_related_records(parent_module, parent_record_id, related_module_fields)
  x = REXML::Document.new
  leads = x.add_element related_module_fields[:related_module]
  row = leads.add_element 'row', {'no' => '1'}
  related_module_fields[:xml_data].each_pair { |k, v| add_field(row, ApiUtils.symbol_to_string(k), v) }

  r = self.class.post(create_url("#{parent_module}", 'updateRelatedRecords'),
                      :query => {:newFormat => 1,
                                 :id => parent_record_id,
                                 :authtoken => @auth_token, :scope => 'crmapi',
                                 :relatedModule => related_module_fields[:related_module],
                                 :xmlData => x, :wfTrigger => 'true'},
                      :headers => {'Content-length' => '0'})

  check_for_errors(r)
end

#users(user_type = 'AllUsers') ⇒ Object



181
182
183
184
185
186
187
188
189
# File 'lib/zoho_api.rb', line 181

def users(user_type = 'AllUsers')
  return @@users unless @@users == [] || user_type == 'Refresh'
  r = self.class.get(create_url('Users', 'getUsers'),
                     :query => {:newFormat => 1, :authtoken => @auth_token, :scope => 'crmapi',
                                :type => 'AllUsers'})
  check_for_errors(r)
  result = extract_users_from_xml_response(r)
  @@users = result
end

#valid_related?(module_name, field) ⇒ Boolean

Returns:

  • (Boolean)


212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/zoho_api.rb', line 212

def valid_related?(module_name, field)
  return nil if field.downcase == 'smownerid'
  valid_relationships = {
      'Leads' => %w(email),
      'Accounts' => %w(accountid accountname),
      'Contacts' => %w(contactid accountid vendorid email),
      'Potentials' => %w(potentialid accountid campaignid contactid potentialname),
      'Campaigns' => %w(campaignid campaignname),
      'Cases' => %w(caseid productid accountid potentialid),
      'Solutions' => %w(solutionid productid),
      'Products' => %w(productid vendorid productname),
      'Purchase Order' => %w(purchaseorderid contactid vendorid),
      'Quotes' => %w(quoteid potentialid accountid contactid),
      'Sales Orders' => %w(salesorderid potentialid accountid contactid quoteid),
      'Invoices' => %w(invoiceid accountid salesorderid contactid),
      'Vendors' => %w(vendorid vendorname),
      'Tasks' => %w(taskid),
      'Events' => %w(eventid),
      'Notes' => %w(notesid)
  }
  valid_relationships[module_name].index(field.downcase)
end