vtiger 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|