vtiger 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +4 -0
- data/Manifest.txt +22 -0
- data/PostInstall.txt +7 -0
- data/README.rdoc +234 -0
- data/Rakefile +40 -0
- data/Rakefile.orig +30 -0
- data/lib/vtiger.rb +6 -0
- data/lib/vtiger/base.rb +155 -0
- data/lib/vtiger/commands.rb +126 -0
- data/lib/vtiger/support.rb +99 -0
- data/test/test_helper.rb +6 -0
- data/test/test_vtiger.rb +80 -0
- metadata +80 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest.txt
|
3
|
+
PostInstall.txt
|
4
|
+
README.rdoc
|
5
|
+
Rakefile
|
6
|
+
lib/vtiger.rb
|
7
|
+
lib/vtiger/base.rb
|
8
|
+
lib/vtiger/support.rb
|
9
|
+
lib/vtiger/commands.rb
|
10
|
+
bin/add_contact.rb
|
11
|
+
bin/yahoo_csv.rb
|
12
|
+
bin/update_stock_inventory.rb
|
13
|
+
bin/add_lead.rb
|
14
|
+
bin/describe_object.rb
|
15
|
+
bin/helloworld.rb
|
16
|
+
bin/query.rb
|
17
|
+
bin/list_types.rb
|
18
|
+
script/console
|
19
|
+
script/destroy
|
20
|
+
script/generate
|
21
|
+
test/test_helper.rb
|
22
|
+
test/test_vtiger.rb
|
data/PostInstall.txt
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,234 @@
|
|
1
|
+
= vtiger
|
2
|
+
* http://estormtech.com
|
3
|
+
This gem provides access to vtiger from ruby. It uses the vtiger web services to access the data in vtiger system.
|
4
|
+
|
5
|
+
See the binary files to test the system.
|
6
|
+
|
7
|
+
== DESCRIPTION:
|
8
|
+
|
9
|
+
There are a set of base commands (eg hpttp get, http post, login, challenge etc)
|
10
|
+
And commands which are more specific to the actual usage such as addlead, describe object
|
11
|
+
|
12
|
+
Options can be passed as hash or preset using a Class variable (which is why the cattr_accessor definition is required from activesupport)
|
13
|
+
|
14
|
+
Vtiger::API.api_settings = {
|
15
|
+
:username => 'admin',
|
16
|
+
:key => 'ssss'
|
17
|
+
:url => 'democrm.estormtech.com'
|
18
|
+
}
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
== FEATURES/PROBLEMS:
|
23
|
+
|
24
|
+
* TBD
|
25
|
+
|
26
|
+
== SYNOPSIS:
|
27
|
+
|
28
|
+
Vtiger::Api.api_settings = {
|
29
|
+
:username => 'admin',
|
30
|
+
:key => 'ssss',
|
31
|
+
:url => 'democrm.estormtech.com',
|
32
|
+
:element_type => 'Contacts'
|
33
|
+
}
|
34
|
+
cmd = Vtiger::Commands.new()
|
35
|
+
challenge=cmd.challenge({})
|
36
|
+
login=cmd.login({})
|
37
|
+
cmd.add_lead etc...
|
38
|
+
|
39
|
+
== REQUIREMENTS:
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
== INSTALL:
|
44
|
+
|
45
|
+
find userid from vtiger_users (supposed to be in preferences section)
|
46
|
+
select username,accessKey from vtiger_users;
|
47
|
+
|
48
|
+
|
49
|
+
tokens are stored in
|
50
|
+
vtiger_ws_userauthtoken
|
51
|
+
|
52
|
+
==== Usage:
|
53
|
+
Server Types: list types on the server
|
54
|
+
list_types.rb -u democrm.estormtech.com -n scott -k xxxxx
|
55
|
+
|
56
|
+
Describe Object:
|
57
|
+
describe_object.rb -u crm.estormtech.com -n admin -k xx -e Contacts
|
58
|
+
|
59
|
+
Getting the custom field ids
|
60
|
+
describe_object.rb -u crm.estormtech.com -n admin -k xxx -e Contacts | grep for the label name
|
61
|
+
|
62
|
+
|
63
|
+
== Testing via Curl
|
64
|
+
Testing via curl
|
65
|
+
|
66
|
+
|
67
|
+
curl -d username=scott -d accessKey=xxx http://crm.yoururl.com/webservice.php?operation=login
|
68
|
+
Name":"3a8b6b834a63eb909ecfa","userId":"19x5","version":"0.2","vtigerVersion":"5.1.0 RC"}}
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
List types
|
73
|
+
|
74
|
+
|
75
|
+
{
|
76
|
+
"success": true,
|
77
|
+
"result": {
|
78
|
+
"types": [
|
79
|
+
"Calendar",
|
80
|
+
"Leads",
|
81
|
+
"Accounts",
|
82
|
+
"Contacts",
|
83
|
+
"Potentials",
|
84
|
+
"Products",
|
85
|
+
"Documents",
|
86
|
+
"Emails",
|
87
|
+
"HelpDesk",
|
88
|
+
"Faq",
|
89
|
+
"Vendors",
|
90
|
+
"PriceBooks",
|
91
|
+
"Quotes",
|
92
|
+
"PurchaseOrder",
|
93
|
+
"SalesOrder",
|
94
|
+
"Invoice",
|
95
|
+
"Campaigns",
|
96
|
+
"Events",
|
97
|
+
"Users",
|
98
|
+
"ServiceContracts",
|
99
|
+
"PBXManager",
|
100
|
+
"Services",
|
101
|
+
"Groups",
|
102
|
+
"Currency",
|
103
|
+
"DocumentFolders"
|
104
|
+
],
|
105
|
+
"information": {
|
106
|
+
"Calendar": {
|
107
|
+
"isEntity": true,
|
108
|
+
"label": "Calendar",
|
109
|
+
"singular": "To Do"
|
110
|
+
},
|
111
|
+
"Leads": {
|
112
|
+
"isEntity": true,
|
113
|
+
"label": "Leads",
|
114
|
+
"singular": "Lead"
|
115
|
+
},
|
116
|
+
"Accounts": {
|
117
|
+
"isEntity": true,
|
118
|
+
"label": "Accounts",
|
119
|
+
"singular": "Account"
|
120
|
+
},
|
121
|
+
"Contacts": {
|
122
|
+
"isEntity": true,
|
123
|
+
"label": "Contacts",
|
124
|
+
"singular": "Contact"
|
125
|
+
},
|
126
|
+
"Potentials": {
|
127
|
+
"isEntity": true,
|
128
|
+
"label": "Potentials",
|
129
|
+
"singular": "Potential"
|
130
|
+
},
|
131
|
+
"Products": {
|
132
|
+
"isEntity": true,
|
133
|
+
"label": "Products",
|
134
|
+
"singular": "Product"
|
135
|
+
},
|
136
|
+
"Documents": {
|
137
|
+
"isEntity": true,
|
138
|
+
"label": "Documents",
|
139
|
+
"singular": "Document"
|
140
|
+
},
|
141
|
+
"Emails": {
|
142
|
+
"isEntity": true,
|
143
|
+
"label": "Email",
|
144
|
+
"singular": "Email"
|
145
|
+
},
|
146
|
+
"HelpDesk": {
|
147
|
+
"isEntity": true,
|
148
|
+
"label": "Trouble Tickets",
|
149
|
+
"singular": "Ticket"
|
150
|
+
},
|
151
|
+
"Faq": {
|
152
|
+
"isEntity": true,
|
153
|
+
"label": "FAQ",
|
154
|
+
"singular": "Faq"
|
155
|
+
},
|
156
|
+
"Vendors": {
|
157
|
+
"isEntity": true,
|
158
|
+
"label": "Vendors",
|
159
|
+
"singular": "Vendor"
|
160
|
+
},
|
161
|
+
"PriceBooks": {
|
162
|
+
"isEntity": true,
|
163
|
+
"label": "Price Books",
|
164
|
+
"singular": "PriceBook"
|
165
|
+
},
|
166
|
+
"Quotes": {
|
167
|
+
"isEntity": true,
|
168
|
+
"label": "Quotes",
|
169
|
+
"singular": "Quote"
|
170
|
+
},
|
171
|
+
"PurchaseOrder": {
|
172
|
+
"isEntity": true,
|
173
|
+
"label": "Purchase Order",
|
174
|
+
"singular": "PurchaseOrder"
|
175
|
+
},
|
176
|
+
"SalesOrder": {
|
177
|
+
"isEntity": true,
|
178
|
+
"label": "Sales Order",
|
179
|
+
"singular": "SalesOrder"
|
180
|
+
},
|
181
|
+
"Invoice": {
|
182
|
+
"isEntity": true,
|
183
|
+
"label": "Invoice",
|
184
|
+
"singular": "Invoice"
|
185
|
+
},
|
186
|
+
"Campaigns": {
|
187
|
+
"isEntity": true,
|
188
|
+
"label": "Campaigns",
|
189
|
+
"singular": "Campaign"
|
190
|
+
},
|
191
|
+
"Events": {
|
192
|
+
"isEntity": true,
|
193
|
+
"label": "Events",
|
194
|
+
"singular": "Event"
|
195
|
+
},
|
196
|
+
"Users": {
|
197
|
+
"isEntity": true,
|
198
|
+
"label": "Users",
|
199
|
+
"singular": "User"
|
200
|
+
},
|
201
|
+
"ServiceContracts": {
|
202
|
+
"isEntity": true,
|
203
|
+
"label": "Service Contracts",
|
204
|
+
"singular": "Service Contract"
|
205
|
+
},
|
206
|
+
"PBXManager": {
|
207
|
+
"isEntity": true,
|
208
|
+
"label": "PBX Manager",
|
209
|
+
"singular": "SINGLE_PBXManager"
|
210
|
+
},
|
211
|
+
"Services": {
|
212
|
+
"isEntity": true,
|
213
|
+
"label": "Services",
|
214
|
+
"singular": "Service"
|
215
|
+
},
|
216
|
+
"Groups": {
|
217
|
+
"isEntity": false,
|
218
|
+
"label": "Groups",
|
219
|
+
"singular": "Groups"
|
220
|
+
},
|
221
|
+
"Currency": {
|
222
|
+
"isEntity": false,
|
223
|
+
"label": "Currency",
|
224
|
+
"singular": "Currency"
|
225
|
+
},
|
226
|
+
"DocumentFolders": {
|
227
|
+
"isEntity": false,
|
228
|
+
"label": "DocumentFolders",
|
229
|
+
"singular": "DocumentFolders"
|
230
|
+
}
|
231
|
+
}
|
232
|
+
}
|
233
|
+
}
|
234
|
+
-------------finished processing!!!
|
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
gem 'hoe', '>= 2.1.0'
|
3
|
+
require 'hoe'
|
4
|
+
require 'fileutils'
|
5
|
+
#require './lib/test'
|
6
|
+
|
7
|
+
Hoe.plugin :newgem
|
8
|
+
# Hoe.plugin :website
|
9
|
+
# Hoe.plugin :cucumberfeatures
|
10
|
+
|
11
|
+
# Generate all the Rake tasks
|
12
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
13
|
+
$hoe = Hoe.spec 'vtiger' do
|
14
|
+
self.developer 'scott sproule', 'scott.sproule@ficonab.com'
|
15
|
+
self.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
|
16
|
+
self.rubyforge_name = self.name # TODO this is default value
|
17
|
+
# self.extra_deps = [['activesupport','>= 2.0.2']]
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'newgem/tasks'
|
22
|
+
Dir['tasks/**/*.rake'].each { |t| load t }
|
23
|
+
|
24
|
+
# TODO - want other tests/tasks run by default? Add them to the list
|
25
|
+
# remove_task :default
|
26
|
+
# task :default => [:spec, :features]
|
27
|
+
begin
|
28
|
+
require 'jeweler'
|
29
|
+
Jeweler::Tasks.new do |gemspec|
|
30
|
+
gemspec.name = "vtiger"
|
31
|
+
gemspec.summary = "Vtiger support of webservices from ruby"
|
32
|
+
gemspec.description = "vtiger webservice calls"
|
33
|
+
gemspec.email = "scott.sproule@estormtech.com"
|
34
|
+
gemspec.homepage = "http://github.com/semdinsp/vtiger-ruby-webservices"
|
35
|
+
gemspec.authors = ["Scott Sproule"]
|
36
|
+
end
|
37
|
+
Jeweler::GemcutterTasks.new
|
38
|
+
rescue LoadError
|
39
|
+
puts "Jeweler not available. Install it with: sudo gem install jeweler -s http://gemcutter.org"
|
40
|
+
end
|
data/Rakefile.orig
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
%w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
|
2
|
+
require File.dirname(__FILE__) + '/lib/vtiger'
|
3
|
+
|
4
|
+
# Generate all the Rake tasks
|
5
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
6
|
+
gem 'hoe'
|
7
|
+
require 'hoe'
|
8
|
+
$hoe = Hoe.new('vtiger', Vtiger::VERSION) do |p|
|
9
|
+
p.developer('scott sproule', 'scott.sproule@ficonab.com')
|
10
|
+
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
11
|
+
p.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
|
12
|
+
p.rubyforge_name = p.name # TODO this is default value
|
13
|
+
# p.extra_deps = [
|
14
|
+
# ['activesupport','>= 2.0.2'],
|
15
|
+
# ]
|
16
|
+
p.extra_dev_deps = [
|
17
|
+
['newgem', ">= #{::Newgem::VERSION}"]
|
18
|
+
]
|
19
|
+
|
20
|
+
p.clean_globs |= %w[**/.DS_Store tmp *.log]
|
21
|
+
path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
|
22
|
+
p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
|
23
|
+
p.rsync_args = '-av --delete --ignore-errors'
|
24
|
+
end
|
25
|
+
|
26
|
+
require 'newgem/tasks' # load /tasks/*.rake
|
27
|
+
Dir['tasks/**/*.rake'].each { |t| load t }
|
28
|
+
|
29
|
+
# TODO - want other tests/tasks run by default? Add them to the list
|
30
|
+
# task :default => [:spec, :features]
|
data/lib/vtiger.rb
ADDED
data/lib/vtiger/base.rb
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'json'
|
3
|
+
require 'digest/md5'
|
4
|
+
require 'erb'
|
5
|
+
class Hash
|
6
|
+
def url_encode
|
7
|
+
to_a.map do |name_value|
|
8
|
+
name_value.map { |e| CGI.escape e.to_s }.join '='
|
9
|
+
end.join '&'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module Vtiger
|
14
|
+
class Base
|
15
|
+
attr_accessor :md5,:token, :endpoint_url, :access_key, :session_name, :url, :username, :userid
|
16
|
+
|
17
|
+
def challenge(options)
|
18
|
+
|
19
|
+
#puts "in challenge"
|
20
|
+
self.url=options[:url] || Vtiger::Api.api_settings[:url]
|
21
|
+
self.username = options[:username]|| Vtiger::Api.api_settings[:username]
|
22
|
+
self.access_key = options[:key] || Vtiger::Api.api_settings[:key]
|
23
|
+
self.endpoint_url="http://#{self.url}/webservice.php?"
|
24
|
+
operation = "operation=getchallenge&username=#{self.username}";
|
25
|
+
#puts "challenge: " + self.endpoint_url + operation
|
26
|
+
r=http_ask_get(self.endpoint_url+operation)
|
27
|
+
# puts JSON.pretty_generate(r)
|
28
|
+
# puts "success is: " + r["success"].to_s #==true
|
29
|
+
self.token = r["result"]["token"] #if r["success"]==true
|
30
|
+
|
31
|
+
#puts "token is: " + self.token
|
32
|
+
create_digest
|
33
|
+
#puts "digest is: #{self.md5} token #{self.token}"
|
34
|
+
self.token!=nil
|
35
|
+
end
|
36
|
+
def create_digest
|
37
|
+
#access key from my_preferences page of vtiger
|
38
|
+
digest_string="#{self.token}#{self.access_key}"
|
39
|
+
self.md5=Digest::MD5.hexdigest(digest_string)
|
40
|
+
puts "#{self.url}: string #{digest_string} results in digest: "+self.md5 + " access key: "+ self.access_key + " token: " + self.token
|
41
|
+
end
|
42
|
+
def http_crm_post(operation, body)
|
43
|
+
response = nil
|
44
|
+
response_header = {"Content-type" => "application/x-www-form-urlencoded"}
|
45
|
+
#puts " endpoint: #{self.endpoint_url}"
|
46
|
+
t=URI.split(self.endpoint_url.to_s)
|
47
|
+
# puts "host is: " + t[2] #FIX THIS.
|
48
|
+
ht =Net::HTTP.start(t[2],80)
|
49
|
+
|
50
|
+
body_enc=body.url_encode
|
51
|
+
# puts "attemping post: #{self.endpoint_url}#{operation} body: #{body} body_enc= #{body_enc}"
|
52
|
+
response=ht.post(self.endpoint_url+operation,body_enc,response_header)
|
53
|
+
|
54
|
+
# p response.body.to_s
|
55
|
+
r=JSON.parse response.body
|
56
|
+
r
|
57
|
+
end
|
58
|
+
def http_ask_get(input_url)
|
59
|
+
# puts "about to HTTP.get on '#{input_url}'"
|
60
|
+
# url=ERB::Util.url_encode(input_url)
|
61
|
+
# resp= Net::HTTP.get(URI.parse(url))
|
62
|
+
url = URI.parse(input_url)
|
63
|
+
# puts "inspect url: " + url.inspect
|
64
|
+
req = Net::HTTP::Get.new("#{url.path}?#{url.query}")
|
65
|
+
resp = Net::HTTP.start(url.host, url.port) {|http|
|
66
|
+
# puts "url path is #{url.path}"
|
67
|
+
http.request(req)
|
68
|
+
}
|
69
|
+
# puts resp.body
|
70
|
+
|
71
|
+
|
72
|
+
# puts "resp: " + resp
|
73
|
+
r=JSON.parse resp.body
|
74
|
+
r
|
75
|
+
end
|
76
|
+
|
77
|
+
def login(options)
|
78
|
+
# puts "in login"
|
79
|
+
input_array ={'operation'=>'login', 'username'=>self.username, 'accessKey'=>self.md5} # removed the true
|
80
|
+
puts "input array:" + input_array.to_s #&username=#{self.username}&accessKey=#{self.md5}
|
81
|
+
# scott not working -- JSON.generate(input_array,{'array_nl'=>'true'})
|
82
|
+
result = http_crm_post("operation=login",input_array)
|
83
|
+
self.session_name=result["result"]["sessionName"] if result["result"]!=nil
|
84
|
+
self.userid = result["result"]["userId"] if result["result"]!=nil
|
85
|
+
puts "session name is: #{self.session_name} userid #{self.userid}"
|
86
|
+
self.userid!=nil
|
87
|
+
end
|
88
|
+
def retrieve_object(objid)
|
89
|
+
puts "in retrieve object"
|
90
|
+
#&username=#{self.username}&accessKey=#{self.md5}
|
91
|
+
# scott not working -- JSON.generate(input_array,{'array_nl'=>'true'})
|
92
|
+
result = http_ask_get(self.endpoint_url+"operation=retrieve&sessionName=#{self.session_name}&id=#{objid}")
|
93
|
+
# puts JSON.pretty_generate(result)
|
94
|
+
values=result["result"]
|
95
|
+
values
|
96
|
+
end
|
97
|
+
def query(options)
|
98
|
+
puts "in query object"
|
99
|
+
#&username=#{self.username}&accessKey=#{self.md5}
|
100
|
+
# scott not working -- JSON.generate(input_array,{'array_nl'=>'true'})
|
101
|
+
action_string=ERB::Util.url_encode("#{options[:query]}")
|
102
|
+
result = http_ask_get(self.endpoint_url+"operation=query&sessionName=#{self.session_name}&query="+action_string)
|
103
|
+
# http_ask_get(self.endpoint_url+"operation=query&sessionName=#{self.session_name}&userId=#{self.userid}&query="+action_string)
|
104
|
+
# puts JSON.pretty_generate(result)
|
105
|
+
end
|
106
|
+
def describe_object(options)
|
107
|
+
puts "in describe object"
|
108
|
+
#&username=#{self.username}&accessKey=#{self.md5}
|
109
|
+
# scott not working -- JSON.generate(input_array,{'array_nl'=>'true'})
|
110
|
+
result = http_ask_get(self.endpoint_url+"operation=describe&sessionName=#{self.session_name}&elementType=#{options[:element_type]}")
|
111
|
+
# puts JSON.pretty_generate(result)
|
112
|
+
if defined? RAILS_ENV
|
113
|
+
puts "in JSON code rails env: #{RAILS_ENV}"
|
114
|
+
puts object_map.to_json
|
115
|
+
else
|
116
|
+
puts "rails env is not defined"
|
117
|
+
puts self.json_please(result) #scott tmp=JSON.generate(object_map)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
def addobject(options)
|
121
|
+
puts "in addobject"
|
122
|
+
object_map= { 'assigned_user_id'=>"#{self.userid}",'lastname'=>"#{options[:contact]}",'cf_554'=>"1234"}
|
123
|
+
# 'tsipid'=>"1234"
|
124
|
+
tmp=self.json_please(object_map)
|
125
|
+
input_array ={'operation'=>'create','elementType'=>"#{options[:element_type]}",'sessionName'=>"#{self.session_name}", 'element'=>tmp} # removed the true
|
126
|
+
puts "input array:" + input_array.to_s #&username=#{self.username}&accessKey=#{self.md5}
|
127
|
+
# scott not working -- JSON.generate(input_array,{'array_nl'=>'true'})
|
128
|
+
result = http_crm_post("operation=create",input_array)
|
129
|
+
# self.session_name=result["result"]["sessionName"]
|
130
|
+
# puts JSON.pretty_generate(result)
|
131
|
+
end
|
132
|
+
def json_please(object_map)
|
133
|
+
if defined? RAILS_ENV
|
134
|
+
#puts "in JSON code rails env: #{RAILS_ENV}"
|
135
|
+
tmp=object_map.to_json
|
136
|
+
else
|
137
|
+
puts "rails env is not defined"
|
138
|
+
tmp=JSON.fast_generate(object_map) #scott tmp=JSON.generate(object_map)
|
139
|
+
end
|
140
|
+
tmp
|
141
|
+
end
|
142
|
+
def updateobject(values)
|
143
|
+
#puts "in updateobject"
|
144
|
+
object_map= { 'assigned_user_id'=>"#{self.userid}",'id'=>"#{self.object_id}" }.merge values.to_hash
|
145
|
+
# 'tsipid'=>"1234"
|
146
|
+
tmp=self.json_please(object_map)
|
147
|
+
input_array ={'operation'=>'update','sessionName'=>"#{self.session_name}", 'element'=>tmp} # removed the true
|
148
|
+
#puts "input array:" + input_array.to_s #&username=#{self.username}&accessKey=#{self.md5}
|
149
|
+
# scott not working -- JSON.generate(input_array,{'array_nl'=>'true'})
|
150
|
+
result = http_crm_post("operation=update",input_array)
|
151
|
+
# self.session_name=result["result"]["sessionName"]
|
152
|
+
# puts JSON.pretty_generate(result)
|
153
|
+
end
|
154
|
+
end #clase base
|
155
|
+
end #moduble
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'json'
|
3
|
+
#require 'digest/md5'
|
4
|
+
require 'erb'
|
5
|
+
gem 'activesupport'
|
6
|
+
require 'active_support/core_ext/class/attribute_accessors'
|
7
|
+
|
8
|
+
|
9
|
+
module Vtiger
|
10
|
+
class Api
|
11
|
+
@@api_settings = {}
|
12
|
+
cattr_accessor :api_settings
|
13
|
+
end
|
14
|
+
class Commands < Vtiger::Base
|
15
|
+
attr_accessor :product_id, :qty_in_stock, :new_quantity, :object_id, :account_name
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
# scott was: def updateobject(options,values)
|
20
|
+
# add a lead with ln last name, co company, and hashv a hash of other values you want to set
|
21
|
+
def addlead(options,ln,co,hashv)
|
22
|
+
puts "in addobject"
|
23
|
+
object_map= { 'assigned_user_id'=>"#{self.userid}",'lastname'=>"#{ln}", 'company'=>"#{co}"}
|
24
|
+
object_map=object_map.merge hashv
|
25
|
+
# 'tsipid'=>"1234"
|
26
|
+
tmp=self.json_please(object_map)
|
27
|
+
input_array ={'operation'=>'create','elementType'=>"Leads",'sessionName'=>"#{self.session_name}", 'element'=>tmp} # removed the true
|
28
|
+
puts "input array:" + input_array.to_s #&username=#{self.username}&accessKey=#{self.md5}
|
29
|
+
# scott not working -- JSON.generate(input_array,{'array_nl'=>'true'})
|
30
|
+
result = http_crm_post("operation=create",input_array)
|
31
|
+
# self.session_name=result["result"]["sessionName"]
|
32
|
+
# puts JSON.pretty_generate(result)
|
33
|
+
result["success"]
|
34
|
+
end
|
35
|
+
def action(options)
|
36
|
+
puts "in action"
|
37
|
+
end
|
38
|
+
def list_types(options)
|
39
|
+
puts "in list types"
|
40
|
+
#&username=#{self.username}&accessKey=#{self.md5}
|
41
|
+
# scott not working -- JSON.generate(input_array,{'array_nl'=>'true'})
|
42
|
+
result = http_ask_get(self.endpoint_url+"operation=listtypes&sessionName=#{self.session_name}")
|
43
|
+
# puts JSON.pretty_generate(result)
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
def update_yahoo(fieldmapping,values,referring_domain,traffic_source, campaign,revenue,actions,search_phrase)
|
48
|
+
#self.object id found in query_tsipid
|
49
|
+
# puts "fm: #{fieldmapping[:traffic_source]} ts: #{traffic_source} values: #{values} "
|
50
|
+
# values[fieldmapping[:traffic_source].to_s]=traffic_source
|
51
|
+
# values[fieldmapping[:campaign].to_s]=campaign
|
52
|
+
values[fieldmapping[:referring_domain].to_s]=referring_domain
|
53
|
+
values[fieldmapping[:revenue].to_s]=revenue #revenue
|
54
|
+
values[fieldmapping[:unique_actions].to_s]=actions #campaign
|
55
|
+
values[fieldmapping[:search_phrase].to_s]=search_phrase
|
56
|
+
updateobject(values)
|
57
|
+
end
|
58
|
+
def process_row(row,fieldmapping,options)
|
59
|
+
result_summary=""
|
60
|
+
success=false
|
61
|
+
member_label="Member"
|
62
|
+
refering_domain_label="Referring URL (Direct)"
|
63
|
+
traffic_src_label="Traffic Sources (Intelligent)"
|
64
|
+
campaign_label="Campaign"
|
65
|
+
unique_label="Unique Actions"
|
66
|
+
rev_label="Revenue"
|
67
|
+
search_label="Search Phrases (Direct)"
|
68
|
+
account_id = self.query_tsipid(row[member_label].to_s,fieldmapping,options)
|
69
|
+
#puts "database id: #{account_id}"
|
70
|
+
if account_id!='failed'
|
71
|
+
values=self.retrieve_object(account_id)
|
72
|
+
self.update_yahoo(fieldmapping,values,row[refering_domain_label],
|
73
|
+
row[traffic_src_label], row[campaign_label],row[rev_label],row[unique_label],row[search_label])
|
74
|
+
result_summary = " Success: row of yahoo csv with TSIPID: #{row[member_label].to_s}\n"
|
75
|
+
success=true
|
76
|
+
else
|
77
|
+
result_summary =" Failure: row of yahoo csv with Member: #{row[member_label].to_s}\n"
|
78
|
+
# else
|
79
|
+
end #if
|
80
|
+
return success,result_summary
|
81
|
+
end
|
82
|
+
def query_tsipid(id,fieldmapping,options)
|
83
|
+
puts "in query id"
|
84
|
+
#&username=#{self.username}&accessKey=#{self.md5}
|
85
|
+
# scott not working -- JSON.generate(input_array,{'array_nl'=>'true'})
|
86
|
+
action_string=ERB::Util.url_encode("select id,lastname from #{options[:element_type]} where #{fieldmapping[:tsipid]} = '#{id}';")
|
87
|
+
# action_string=ERB::Util.url_encode("select id,accountname from #{options[:element_type]} where #{fieldmapping[:tsipid]} = '#{id}';") ACCOUNTS
|
88
|
+
puts "action string:" +action_string
|
89
|
+
res = http_ask_get(self.endpoint_url+"operation=query&sessionName=#{self.session_name}&query="+action_string)
|
90
|
+
# http_ask_get(self.endpoint_url+"operation=query&sessionName=#{self.session_name}&userId=#{self.userid}&query="+action_string)
|
91
|
+
# puts JSON.pretty_generate(res)
|
92
|
+
values=res["result"][0] #comes back as array
|
93
|
+
#puts values.inspect
|
94
|
+
# return the account id
|
95
|
+
self.object_id = 'failed'
|
96
|
+
if values!= nil
|
97
|
+
self.object_id=values["id"]
|
98
|
+
self.account_name=values["accountname"]
|
99
|
+
end
|
100
|
+
self.object_id
|
101
|
+
# self.new_quantity = self.qty_in_stock.to_i + options[:quantity].to_i
|
102
|
+
# updateobject(options,{'qtyinstock'=> "#{self.new_quantity}","productname"=>"#{options[:productname]}"})
|
103
|
+
end
|
104
|
+
def query_product_inventory(options)
|
105
|
+
puts "in query product count"
|
106
|
+
#&username=#{self.username}&accessKey=#{self.md5}
|
107
|
+
# scott not working -- JSON.generate(input_array,{'array_nl'=>'true'})
|
108
|
+
action_string=ERB::Util.url_encode("select id, qtyinstock, productname from Products where productname like '#{options[:productname]}';")
|
109
|
+
puts "action string:" +action_string
|
110
|
+
res = http_ask_get(self.endpoint_url+"operation=query&sessionName=#{self.session_name}&query="+action_string)
|
111
|
+
# http_ask_get(self.endpoint_url+"operation=query&sessionName=#{self.session_name}&userId=#{self.userid}&query="+action_string)
|
112
|
+
puts JSON.pretty_generate(res)
|
113
|
+
values=res["result"][0] #comes back as array
|
114
|
+
puts values.inspect
|
115
|
+
self.product_id = values["id"]
|
116
|
+
self.object_id=self.product_id
|
117
|
+
self.qty_in_stock = values["qtyinstock"]
|
118
|
+
# NOTE INTEGER VALUES
|
119
|
+
self.new_quantity = self.qty_in_stock.to_i + options[:quantity].to_i
|
120
|
+
# NEEDS TO RETREIVE OBEJCT
|
121
|
+
puts "#{self.product_id}, #{self.qty_in_stock} New quantity should be: #{self.new_quantity}"
|
122
|
+
updateobject({'qtyinstock'=> "#{self.new_quantity}","productname"=>"#{options[:productname]}"})
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# basic format for stomp messages
|
2
|
+
require 'rexml/document'
|
3
|
+
#require 'xml_helper.rb'
|
4
|
+
#require 'rubygems'
|
5
|
+
#gem 'stomp_message'
|
6
|
+
#require 'stomp_message'
|
7
|
+
require 'optparse'
|
8
|
+
require 'rdoc/usage'
|
9
|
+
gem 'fastercsv'
|
10
|
+
require 'fastercsv'
|
11
|
+
|
12
|
+
module Vtiger
|
13
|
+
class Misc
|
14
|
+
def self.read_csv_file(filepath)
|
15
|
+
FasterCSV.read( filepath, { :headers => true})
|
16
|
+
end
|
17
|
+
end
|
18
|
+
class Options
|
19
|
+
def self.parse_options(params)
|
20
|
+
opts = OptionParser.new
|
21
|
+
# puts "argv are #{params}"
|
22
|
+
temp_hash = {}
|
23
|
+
temp_hash[:ack]= 'false' # no ack by default
|
24
|
+
temp_hash[:msisdn] = 'not_defined'
|
25
|
+
email_flag=false
|
26
|
+
opts.on("-u","--url VAL", String) {|val| temp_hash[:url ] = val
|
27
|
+
puts "url is #{val}"
|
28
|
+
}
|
29
|
+
# takes ruby hash code and converts to yaml
|
30
|
+
|
31
|
+
opts.on("-H","--body_hash VAL", String) {|val| temp=eval(val)
|
32
|
+
temp_hash[:body ] = temp.to_yaml
|
33
|
+
# puts "host is #{val}"
|
34
|
+
}
|
35
|
+
opts.on("-D","--email VAL", String) {|val| temp_hash[:email ] = val
|
36
|
+
temp_hash[:destination]=val }
|
37
|
+
|
38
|
+
|
39
|
+
opts.on("-c","--contact VAL", String) {|val| temp_hash[:contact ] = val
|
40
|
+
puts "contact #{val}" }
|
41
|
+
opts.on("-p","--productname VAL", String) {|val| temp_hash[:productname ] = val
|
42
|
+
puts "productname #{val}" }
|
43
|
+
opts.on("-Q","--quantity VAL", String) {|val| temp_hash[:quantity ] = val
|
44
|
+
puts "stock to change #{val}" }
|
45
|
+
opts.on("-i","--objectid VAL", String) {|val| temp_hash[:objectid ] = val
|
46
|
+
puts "objectid #{val}" }
|
47
|
+
opts.on("-q","--query VAL", String) {|val| temp_hash[:query ] = val
|
48
|
+
puts "contact #{val}" }
|
49
|
+
opts.on("-e","--elementtype VAL", String) {|val| temp_hash[:element_type ] = val
|
50
|
+
puts "elementtype #{val}" }
|
51
|
+
opts.on("-k","--access_key VAL", String) {|val| temp_hash[:key ] = val
|
52
|
+
puts "key #{val}" }
|
53
|
+
opts.on("-n","--username VAL", String) {|val| temp_hash[:username ] = val
|
54
|
+
puts "username #{val}" }
|
55
|
+
opts.on("-f","--filename VAL", String) {|val| temp_hash[:filename ] = val
|
56
|
+
puts "filename #{val}" }
|
57
|
+
opts.on("-d","--debug", "turn on debug") { |val| temp_hash[:debug ] = true }
|
58
|
+
|
59
|
+
|
60
|
+
opts.parse(params)
|
61
|
+
# puts " in HTTP #{hostname} port #{port} url: #{url}"
|
62
|
+
|
63
|
+
return temp_hash
|
64
|
+
|
65
|
+
end # parse options
|
66
|
+
end #class
|
67
|
+
# help build xml commands from messages
|
68
|
+
|
69
|
+
end #module
|
70
|
+
|
71
|
+
def RDoc.usage_no_exit(*args)
|
72
|
+
# main_program_file = caller[1].sub(/:\d+$/, '')
|
73
|
+
main_program_file = caller[1].split(':')[0]
|
74
|
+
#puts "main program is #{main_program_file}"
|
75
|
+
# puts " caller is #{caller.inspect}"
|
76
|
+
comment = File.open(main_program_file) do |file|
|
77
|
+
find_comment(file)
|
78
|
+
end
|
79
|
+
|
80
|
+
comment = comment.gsub(/^\s*#/, '')
|
81
|
+
|
82
|
+
markup = SM::SimpleMarkup.new
|
83
|
+
flow_convertor = SM::ToFlow.new
|
84
|
+
|
85
|
+
flow = markup.convert(comment, flow_convertor)
|
86
|
+
|
87
|
+
format = "plain"
|
88
|
+
|
89
|
+
unless args.empty?
|
90
|
+
flow = extract_sections(flow, args)
|
91
|
+
end
|
92
|
+
|
93
|
+
options = RI::Options.instance
|
94
|
+
if args = ENV["RI"]
|
95
|
+
options.parse(args.split)
|
96
|
+
end
|
97
|
+
formatter = options.formatter.new(options, "")
|
98
|
+
formatter.display_flow(flow)
|
99
|
+
end
|
data/test/test_helper.rb
ADDED
data/test/test_vtiger.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
|
+
|
3
|
+
class TestVtiger < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@options={}
|
7
|
+
@options[:url]='democrm.estormtech.com'
|
8
|
+
@options[:key]='xBY6leZ5kZHQm2Y'
|
9
|
+
@options[:username]="admin"
|
10
|
+
@options[:element_type]="Contacts"
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_login
|
14
|
+
cmd = Vtiger::Commands.new()
|
15
|
+
challenge=cmd.challenge(@options)
|
16
|
+
login=cmd.login(@options)
|
17
|
+
assert challenge,"challenge is false"
|
18
|
+
assert login,"login is false"
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_api_login
|
22
|
+
Vtiger::Api.api_settings = {
|
23
|
+
:username => 'admin',
|
24
|
+
:key => 'xBY6leZ5kZHQm2Y',
|
25
|
+
:url => 'democrm.estormtech.com',
|
26
|
+
:element_type => 'Contacts'
|
27
|
+
}
|
28
|
+
cmd = Vtiger::Commands.new()
|
29
|
+
challenge=cmd.challenge({})
|
30
|
+
login=cmd.login({})
|
31
|
+
assert challenge,"challenge is false"
|
32
|
+
assert login,"login is false"
|
33
|
+
end
|
34
|
+
def test_api_login2
|
35
|
+
Vtiger::Api.api_settings = {
|
36
|
+
:username => 'admin',
|
37
|
+
:key => 'xBY6leZ5kZHQm2Y',
|
38
|
+
:url => 'democrm.estormtech.com',
|
39
|
+
:element_type => 'Contacts'
|
40
|
+
}
|
41
|
+
cmd = Vtiger::Commands.new()
|
42
|
+
options={}
|
43
|
+
options[:username]='admin'
|
44
|
+
challenge=cmd.challenge(options)
|
45
|
+
login=cmd.login(options)
|
46
|
+
assert challenge,"challenge is false"
|
47
|
+
assert login,"login is false"
|
48
|
+
end
|
49
|
+
def test_bad_login
|
50
|
+
cmd = Vtiger::Commands.new()
|
51
|
+
@options[:username]='test'
|
52
|
+
challenge=cmd.challenge(@options)
|
53
|
+
login=cmd.login(@options)
|
54
|
+
assert challenge,"challenge is false "
|
55
|
+
assert !login,"login should not succeed"
|
56
|
+
end
|
57
|
+
def test_add_lead
|
58
|
+
cmd = Vtiger::Commands.new()
|
59
|
+
challenge=cmd.challenge(@options)
|
60
|
+
login=cmd.login(@options)
|
61
|
+
hv={}
|
62
|
+
hv[:firstname]='test'
|
63
|
+
lead=cmd.addlead(@options,"testlastname","testco",hv)
|
64
|
+
assert challenge,"challenge is false "
|
65
|
+
assert login,"login should succeed"
|
66
|
+
assert lead,"lead should succeed"
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
def test_describe_object
|
71
|
+
cmd = Vtiger::Commands.new()
|
72
|
+
challenge=cmd.challenge(@options)
|
73
|
+
login=cmd.login(@options)
|
74
|
+
@options[:element_type]="Leads"
|
75
|
+
cmd.describe_object(@options)
|
76
|
+
assert challenge,"challenge is false "
|
77
|
+
assert login,"login should succeed"
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vtiger
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 3
|
9
|
+
- 4
|
10
|
+
version: 0.3.4
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Scott Sproule
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-05-23 00:00:00 +08:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: Use to access vtiger crm system from ruby.
|
23
|
+
email: scott.sproule@estormtech.com
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files: []
|
29
|
+
|
30
|
+
files:
|
31
|
+
- lib/vtiger/base.rb
|
32
|
+
- lib/vtiger/commands.rb
|
33
|
+
- lib/vtiger/support.rb
|
34
|
+
- lib/vtiger.rb
|
35
|
+
- test/test_helper.rb
|
36
|
+
- test/test_vtiger.rb
|
37
|
+
- History.txt
|
38
|
+
- Manifest.txt
|
39
|
+
- PostInstall.txt
|
40
|
+
- Rakefile
|
41
|
+
- Rakefile.orig
|
42
|
+
- README.rdoc
|
43
|
+
has_rdoc: true
|
44
|
+
homepage: http://github.com/semdinsp/vtiger-ruby-webservices
|
45
|
+
licenses: []
|
46
|
+
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
hash: 19
|
67
|
+
segments:
|
68
|
+
- 1
|
69
|
+
- 3
|
70
|
+
- 4
|
71
|
+
version: 1.3.4
|
72
|
+
requirements: []
|
73
|
+
|
74
|
+
rubyforge_project: vtiger
|
75
|
+
rubygems_version: 1.3.7
|
76
|
+
signing_key:
|
77
|
+
specification_version: 3
|
78
|
+
summary: Vtiger web service support via ruby
|
79
|
+
test_files: []
|
80
|
+
|