autotask_api 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6021a61922f1e9db170a6d2bddc4f3b12b2ec204e38e6a34441aee39fa1c0482
4
+ data.tar.gz: 641aa14f45bd254a197b7b111c8aa9d81e6bbf0b6a79abf6ae98221a82724b12
5
+ SHA512:
6
+ metadata.gz: 407cff3284b60e5ddd0d4bc95f16b8d6dec3ec0853c5bfca8191d8b05d39e3555f8ee0579673ae6a72445e71ac94fd9d1707633274b59add8f42fe5bcff45bae
7
+ data.tar.gz: 36eb930031433176d1a5374cc05774dc882ebdd66f4763cd2e3b61821a1189275b321cfc1968380e9df77946d6af3060a0e3efa15468965d07a227df7d81f61a
@@ -0,0 +1,20 @@
1
+ Copyright 2016 Kevin Pheasey
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,182 @@
1
+ # AutotaskApi
2
+ Short description and motivation.
3
+
4
+ ## Usage
5
+ How to use my plugin.
6
+
7
+ ## Installation
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'autotask_api'
12
+ ```
13
+
14
+ And then execute:
15
+ ```bash
16
+ $ bundle
17
+ ```
18
+
19
+ Or install it yourself as:
20
+ ```bash
21
+ $ gem install autotask_api
22
+ ```
23
+
24
+ ## Query
25
+
26
+ ### Simple field test
27
+
28
+ SQL:
29
+ ```sql
30
+ firstname = 'Joe'
31
+ ```
32
+
33
+ Objects:
34
+ ```ruby
35
+ e1 = AutotaskApi::Expression.new('firstname', 'equals', 'Joe')
36
+ c = AutotaskApi::Condition.new(e1)
37
+
38
+ AutotaskApi::Contact.where(c)
39
+ ```
40
+
41
+ Hash:
42
+ ```ruby
43
+ AutotaskApi::Condition.from_hash(
44
+ expressions: [
45
+ { field: 'firstname', operator: 'equals', value: 'Joe' }
46
+ ]
47
+ )
48
+ ```
49
+
50
+ ### Multiple Field Test
51
+
52
+ SQL:
53
+ ```sql
54
+ firstname = ‘Joe’ AND lastname = ‘Smith’
55
+ ```
56
+
57
+ Objects:
58
+ ```ruby
59
+ e1 = AutotaskApi::Expression.new('firstname', 'equals', 'Joe')
60
+ e2 = AutotaskApi::Expression.new('lastname', 'equals', 'Smith')
61
+ c = AutotaskApi::Condition.new([e1, e2])
62
+
63
+ AutotaskApi::Contact.where(c)
64
+ ```
65
+
66
+ Hash:
67
+ ```ruby
68
+ c = AutotaskApi::Condition.from_hash(
69
+ expressions: [
70
+ { field: 'firstname', operator: 'equals', value: 'Joe' },
71
+ { field: 'lastname', operator: 'equals', value: 'Smith' }
72
+ ]
73
+ )
74
+
75
+ AutotaskApi::Contact.where(c)
76
+ ```
77
+
78
+ ### Multiple Fields combined with OR
79
+
80
+ SQL:
81
+ ```sql
82
+ firstname = ‘Joe’ OR lastname = ‘Brown’
83
+ ```
84
+
85
+ Objects:
86
+ ```ruby
87
+ e1 = AutotaskApi::Expression.new('firstname', 'equals', 'Joe')
88
+ e2 = AutotaskApi::Expression.new('lastname', 'equals', 'Brown')
89
+ c = AutotaskApi::Condition.new([e1, e2], 'OR')
90
+
91
+ AutotaskApi::Contact.where(c)
92
+ ```
93
+
94
+ Hash:
95
+ ```ruby
96
+ c = AutotaskApi::Condition.from_hash(
97
+ expressions: [
98
+ { field: 'firstname', operator: 'equals', value: 'Joe' },
99
+ { field: 'lastname', operator: 'equals', value: 'Brown' }
100
+ ],
101
+ operator: 'OR'
102
+ )
103
+
104
+ AutotaskApi::Contact.where(c)
105
+ ```
106
+
107
+ ### Nested Conditions
108
+
109
+ SQL:
110
+ ```sql
111
+ (
112
+ firstname = ‘Joe’
113
+ OR
114
+ (
115
+ (firstname = ‘Larry’ and lastname = ‘Brown’)
116
+ OR
117
+ (firstname = ‘Mary’ and lastname = ‘Smith’)
118
+ )
119
+ )
120
+ # AND city != 'Albany'
121
+ ```
122
+
123
+ Objects:
124
+ ```ruby
125
+ e1 = AutotaskApi::Expression.new('firstname', 'equals', 'Larry')
126
+ e2 = AutotaskApi::Expression.new('lastname', 'equals', 'Brown')
127
+ c1 = AutotaskApi::Condition.new([e1, e2])
128
+
129
+ e3 = AutotaskApi::Expression.new('firstname', 'equals', 'Mary')
130
+ e4 = AutotaskApi::Expression.new('lastname', 'equals', 'Smith')
131
+ c2 = AutotaskApi::Condition.new([e3, e4])
132
+
133
+ c3 = AutotaskApi::Condition.new([c1, c2], 'OR')
134
+
135
+ e5 = AutotaskApi::Expression.new('firstname', 'equals', 'Joe')
136
+ c4 = AutotaskApi::Condition.new([e5, c3], 'OR')
137
+
138
+ e6 = AutotaskApi::Expression.new('city', 'notequal', 'Albany')
139
+ c5 = AutotaskApi::Condition.new([c4, e6])
140
+
141
+ AutotaskApi::Query.new('contact', c5).fetch
142
+ ```
143
+
144
+ Hash:
145
+ ```
146
+ c = AutotaskApi::Condition.from_hash(
147
+ expressions: [
148
+ {
149
+ expressions: [
150
+ { field: 'firstname', operator: 'equals', value: 'Joe' },
151
+ {
152
+ expressions: [
153
+ {
154
+ expressions: [
155
+ { field: 'firstname', operator: 'equals', value: 'Larry' },
156
+ { field: 'lastname', operator: 'equals', value: 'Brown' }
157
+ ]
158
+ },
159
+ {
160
+ expressions: [
161
+ { field: 'firstname', operator: 'equals', value: 'Marry' },
162
+ { field: 'lastname', operator: 'equals', value: 'Smith' }
163
+ ]
164
+ }
165
+ ],
166
+ operator: 'OR'
167
+ }
168
+ ],
169
+ operator: 'OR'
170
+ },
171
+ { field: 'city', operator: 'notequal', value: 'Albany' }
172
+ ]
173
+ )
174
+
175
+ AutotaskApi::Contact.where(c)
176
+ ```
177
+
178
+ ## Contributing
179
+ Contribution directions go here.
180
+
181
+ ## License
182
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,34 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'AutotaskApi'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+
18
+
19
+
20
+
21
+
22
+ require 'bundler/gem_tasks'
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'lib'
28
+ t.libs << 'test'
29
+ t.pattern = 'test/**/*_test.rb'
30
+ t.verbose = false
31
+ end
32
+
33
+
34
+ task default: :test
@@ -0,0 +1,22 @@
1
+ require 'nokogiri'
2
+ require 'savon'
3
+
4
+ require 'autotask_api/version'
5
+ require 'autotask_api/config'
6
+ require 'autotask_api/client'
7
+ require 'autotask_api/query'
8
+ require 'autotask_api/entity'
9
+ require 'autotask_api/entity_collection'
10
+
11
+ module AutotaskApi
12
+ class Error < StandardError
13
+ def initialize(msg)
14
+ # extract SOAP Exception message if present
15
+ if msg.include?('[SoapException:')
16
+ msg = msg[/\[SoapException:(.*?)\]/, 1]&.strip
17
+ end
18
+
19
+ super(msg)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,37 @@
1
+ module AutotaskApi
2
+
3
+ class << self
4
+ attr_accessor :client
5
+ end
6
+
7
+ def self.client
8
+ @client ||= Client.new
9
+ end
10
+
11
+ class Client
12
+
13
+ NAMESPACE = 'http://autotask.net/ATWS/v1_5/'
14
+
15
+ attr_reader :config
16
+
17
+ def initialize
18
+ @config = AutotaskApi.config
19
+ yield @config if block_given?
20
+ end
21
+
22
+ def savon_client
23
+ @savon_client ||= Savon.client(
24
+ wsdl: config.wsdl,
25
+ logger: Rails.logger,
26
+ log_level: :debug,
27
+ log: config.debug,
28
+ basic_auth: [config.username, config.password]
29
+ )
30
+ end
31
+
32
+ def call(operation, message = {})
33
+ savon_client.call(operation, message: message, attributes: { xmlns: NAMESPACE })
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,37 @@
1
+ module AutotaskApi
2
+
3
+ class << self
4
+ attr_accessor :config
5
+ end
6
+
7
+ def self.config
8
+ @config ||= Configuration.new
9
+ end
10
+
11
+ def self.configure
12
+ yield(config)
13
+ end
14
+
15
+ class Configuration
16
+ attr_accessor :wsdl, :username, :password, :read_timeout, :open_timeout, :debug
17
+
18
+ def initialize
19
+ @wsdl = 'https://webservices.autotask.net/atservices/1.5/atws.wsdl'
20
+ @read_timeout = 30
21
+ @open_timeout = 30
22
+ @debug = false
23
+ end
24
+
25
+ def set(options = {})
26
+ options.each { |k, v| self.send("#{k.to_s}=", v) }
27
+ end
28
+
29
+ def to_hash
30
+ hash = {}
31
+ instance_variables.each { |var| hash[var.to_s.delete('@').to_sym] = instance_variable_get(var) }
32
+ hash
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,322 @@
1
+ module AutotaskApi
2
+ class Entity
3
+
4
+ def self.all(client = AutotaskApi.client, id = 1)
5
+ where(Condition.new(Expression.new('id', 'GreaterThanorEquals', id)), client)
6
+ end
7
+
8
+ # @param conditions [Hash]
9
+ def self.where(condition, client = AutotaskApi.client)
10
+ query = Query.new(self::NAME, condition, client)
11
+
12
+ begin
13
+ response = query.fetch
14
+ rescue RuntimeError => e
15
+ raise Error.new(e.message)
16
+ end
17
+
18
+ # return empty collection if there were no results
19
+ return EntityCollection.new(self, [], condition, client) if response[:entity_results].nil?
20
+
21
+ results = response[:entity_results][:entity]
22
+ results = [results] unless results.is_a?(Array)
23
+ results = clean_results(results)
24
+
25
+ EntityCollection.new(self, results, condition, client)
26
+ end
27
+
28
+ def self.expression(value)
29
+ case value.class
30
+ when TrueClass
31
+ 1
32
+ when FalseClass
33
+ 0
34
+ else
35
+ value
36
+ end
37
+ end
38
+
39
+ # @param results [Array(Hash)]
40
+ def self.clean_results(results)
41
+ results.each do |record|
42
+ record.update(record) { |_k, v| v == { :"@xsi:type" => "xsd:string" } ? nil : v }
43
+ .delete('@xsi:type'.to_sym)
44
+ end
45
+
46
+ return results
47
+ end
48
+
49
+ end
50
+
51
+ class Account < Entity
52
+ NAME = 'Account'
53
+ end
54
+
55
+ class AccountLocation < Entity
56
+ NAME = 'AccountLocation'
57
+ end
58
+
59
+ class AccountTeam < Entity
60
+ NAME = 'AccountTeam'
61
+ end
62
+
63
+ class AllocationCode < Entity
64
+ NAME = 'AllocationCode'
65
+ end
66
+
67
+ class BillingItem < Entity
68
+ NAME = 'BillingItem'
69
+ end
70
+
71
+ class Contact < Entity
72
+ NAME = 'Contact'
73
+ end
74
+
75
+ class Contract < Entity
76
+ NAME = 'Contract'
77
+ end
78
+
79
+ class ContractBlock < Entity
80
+ NAME = 'ContractBlock'
81
+ end
82
+
83
+ class ContractCost < Entity
84
+ NAME = 'ContractCost'
85
+ end
86
+
87
+ class ContractExclusionAllocationCode < Entity
88
+ NAME = 'ContractExclusionAllocationCode'
89
+ end
90
+
91
+ class ContractExclusionRole < Entity
92
+ NAME = 'ContractExclusionRole'
93
+ end
94
+
95
+ class ContractFactor < Entity
96
+ NAME = 'ContractFactor'
97
+ end
98
+
99
+ class ContractMilestone < Entity
100
+ NAME = 'ContractMilestone'
101
+ end
102
+
103
+ class ContractRate < Entity
104
+ NAME = 'ContractRate'
105
+ end
106
+
107
+ class ContractRetainer < Entity
108
+ NAME = 'ContractRetainer'
109
+ end
110
+
111
+ class ContractRoleCost < Entity
112
+ NAME = 'ContractRoleCost'
113
+ end
114
+
115
+ class ContractService < Entity
116
+ NAME = 'ContractService'
117
+ end
118
+
119
+ class ContractServiceAdjustment < Entity
120
+ NAME = 'ContractServiceAdjustment'
121
+ end
122
+
123
+ class ContractServiceBundle < Entity
124
+ NAME = 'ContractServiceBundle'
125
+ end
126
+
127
+ class ContractServiceBundleAdjustment < Entity
128
+ NAME = 'ContractServiceBundleAdjustment'
129
+ end
130
+
131
+ class ContractServiceBundleUnit < Entity
132
+ NAME = 'ContractServiceBundleUnit'
133
+ end
134
+
135
+ class ContractServiceUnit < Entity
136
+ NAME = 'ContractServiceUnit'
137
+ end
138
+
139
+ class ContractTicketPurchase < Entity
140
+ NAME = 'ContractTicketPurchase'
141
+ end
142
+
143
+ class Country < Entity
144
+ NAME = 'Country'
145
+ end
146
+
147
+ class Department < Entity
148
+ NAME = 'Department'
149
+ end
150
+
151
+ class ExpenseItem < Entity
152
+ NAME = 'ExpenseItem'
153
+ end
154
+
155
+ class ExpenseReport < Entity
156
+ NAME = 'ExpenseReport'
157
+ end
158
+
159
+ class InstalledProduct < Entity
160
+ NAME = 'InstalledProduct'
161
+ end
162
+
163
+ class InstalledProductType < Entity
164
+ NAME = 'InstalledProductType'
165
+ end
166
+
167
+ class InternalLocation < Entity
168
+ NAME = 'InternalLocation'
169
+ end
170
+
171
+ class InventoryItem < Entity
172
+ NAME = 'InventoryItem'
173
+ end
174
+
175
+ class InventoryLocation < Entity
176
+ NAME = 'InventoryLocation'
177
+ end
178
+
179
+ class Invoice < Entity
180
+ NAME = 'Invoice'
181
+ end
182
+
183
+ class Opportunity < Entity
184
+ NAME = 'Opportunity'
185
+ end
186
+
187
+ class PaymentTerm < Entity
188
+ NAME = 'PaymentTerm'
189
+ end
190
+
191
+ class Phase < Entity
192
+ NAME = 'Phase'
193
+ end
194
+
195
+ class Product < Entity
196
+ NAME = 'Product'
197
+ end
198
+
199
+ class Project < Entity
200
+ NAME = 'Project'
201
+ end
202
+
203
+ class ProjectCost < Entity
204
+ NAME = 'ProjectCost'
205
+ end
206
+
207
+ class ProjectNote < Entity
208
+ NAME = 'ProjectNote'
209
+ end
210
+
211
+ class PurchaseOrderItem < Entity
212
+ NAME = 'PurchaseOrderItem'
213
+ end
214
+
215
+ class Quote < Entity
216
+ NAME = 'Quote'
217
+ end
218
+
219
+ class QuoteItem < Entity
220
+ NAME = 'QuoteItem'
221
+ end
222
+
223
+ class QuoteLocation < Entity
224
+ NAME = 'QuoteLocation'
225
+ end
226
+
227
+ class Resource < Entity
228
+ NAME = 'Resource'
229
+ end
230
+
231
+ class ResourceRole < Entity
232
+ NAME = 'ResourceRole'
233
+ end
234
+
235
+ class ResourceSkill < Entity
236
+ NAME = 'ResourceSkill'
237
+ end
238
+
239
+ class Role < Entity
240
+ NAME = 'Role'
241
+ end
242
+
243
+ class SalesOrder < Entity
244
+ NAME = 'SalesOrder'
245
+ end
246
+
247
+ class Service < Entity
248
+ NAME = 'Service'
249
+ end
250
+
251
+ class ServiceBundle < Entity
252
+ NAME = 'ServiceBundle'
253
+ end
254
+
255
+ class ServiceBundleService < Entity
256
+ NAME = 'ServiceBundleService'
257
+ end
258
+
259
+ class ServiceCall < Entity
260
+ NAME = 'ServiceCall'
261
+ end
262
+
263
+ class ServiceCallTask < Entity
264
+ NAME = 'ServiceCallTask'
265
+ end
266
+
267
+ class ServiceCallTaskResource < Entity
268
+ NAME = 'ServiceCallTaskResource'
269
+ end
270
+
271
+ class ServiceCallTicket < Entity
272
+ NAME = 'ServiceCallTicket'
273
+ end
274
+
275
+ class ServiceCallTicketResource < Entity
276
+ NAME = 'ServiceCallTicketResource'
277
+ end
278
+
279
+ class Skill < Entity
280
+ NAME = 'Skill'
281
+ end
282
+
283
+ class Task < Entity
284
+ NAME = 'Task'
285
+ end
286
+
287
+ class TaskPredecessor < Entity
288
+ NAME = 'TaskPredecessor'
289
+ end
290
+
291
+ class TaskSecondaryResource < Entity
292
+ NAME = 'TaskSecondaryResource'
293
+ end
294
+
295
+ class Tax < Entity
296
+ NAME = 'Tax'
297
+ end
298
+
299
+ class TaxCategory < Entity
300
+ NAME = 'TaxCategory'
301
+ end
302
+
303
+ class TaxRegion < Entity
304
+ NAME = 'TaxRegion'
305
+ end
306
+
307
+ class Ticket < Entity
308
+ NAME = 'Ticket'
309
+ end
310
+
311
+ class TicketCost < Entity
312
+ NAME = 'TicketCost'
313
+ end
314
+
315
+ class TicketSecondaryResource < Entity
316
+ NAME = 'TicketSecondaryResource'
317
+ end
318
+
319
+ class TimeEntry < Entity
320
+ NAME = 'TimeEntry'
321
+ end
322
+ end
@@ -0,0 +1,45 @@
1
+ module AutotaskApi
2
+ class EntityCollection
3
+ include Enumerable
4
+
5
+ PAGE_SIZE = 500
6
+
7
+ attr_accessor :condition
8
+
9
+ attr_reader :entities, :client, :class_name
10
+
11
+ def initialize(class_name, entities, condition, client = AutotaskApi.client)
12
+ @class_name = class_name
13
+ @entities = entities
14
+ @condition = condition
15
+ @client = client
16
+ end
17
+
18
+ def each(&block)
19
+ entities.each(&block)
20
+ end
21
+
22
+ def last(&block)
23
+ entities.last(&block)
24
+ end
25
+
26
+ def next_page?
27
+ entities.size >= PAGE_SIZE
28
+ end
29
+
30
+ def next_page
31
+ new_expression = Expression.new('id', 'GreaterThan', entities.last[:id])
32
+
33
+ condition.remove_expression_by_field('id')
34
+ params = condition.expressions.empty? ? new_expression : [condition, new_expression]
35
+
36
+ new_condition = Condition.new(params)
37
+
38
+ class_name.where(new_condition, client)
39
+ end
40
+
41
+ def empty?
42
+ entities.empty?
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,93 @@
1
+ module AutotaskApi
2
+ class Query
3
+ attr_accessor :entity, :client, :condition
4
+
5
+ def initialize(entity, condition = nil, client = AutotaskApi.client)
6
+ @entity = entity
7
+ @client = client
8
+ @condition = condition
9
+ end
10
+
11
+ def fetch
12
+ response = client.call :query, query_string
13
+
14
+ result = response.body[:query_response][:query_result]
15
+
16
+ if result[:return_code].to_i == -1
17
+ raise result[:errors][:atws_error][:message]
18
+ else
19
+ return result
20
+ end
21
+ end
22
+
23
+ def query_string
24
+ Nokogiri::XML::Builder.new do
25
+ sXML do
26
+ cdata(Nokogiri::XML::Builder.new do |xml|
27
+ xml.queryxml do
28
+ xml.entity entity
29
+ xml.query do
30
+ condition.to_xml(xml)
31
+ end
32
+ end
33
+ end.doc.root)
34
+ end
35
+ end.doc.root.to_s
36
+ end
37
+
38
+ end
39
+
40
+ class Condition
41
+
42
+ attr_reader :expressions, :operator
43
+
44
+ def initialize(expressions, operator = 'AND')
45
+ @expressions = expressions.is_a?(Array) ? expressions : [expressions]
46
+ @operator = operator
47
+ end
48
+
49
+ def to_xml(xml)
50
+ xml.condition operator: operator do
51
+ expressions.each { |expression| expression.to_xml(xml) }
52
+ end
53
+ end
54
+
55
+ def self.from_hash(condition = {})
56
+ expressions = condition[:expressions].map do |exprnewession|
57
+ expression.has_key?(:expressions) ? Condition.from_hash(expression) : Expression.from_hash(expression)
58
+ end
59
+
60
+ new expressions, condition[:operator] || 'AND'
61
+ end
62
+
63
+ def remove_expression_by_field(field)
64
+ expressions.reject! do |expression|
65
+ expression.is_a?(Condition) ? expression.remove_expression_by_field(field) : expression.field == field
66
+ end
67
+ end
68
+
69
+ end
70
+
71
+ class Expression
72
+
73
+ attr_reader :field, :operator, :value
74
+
75
+ def initialize(field, operator, value)
76
+ @field = field
77
+ @operator = operator
78
+ @value = value
79
+ end
80
+
81
+ def to_xml(xml)
82
+ xml.field field do
83
+ xml.expression value, op: operator
84
+ end
85
+ end
86
+
87
+ def self.from_hash(expression = {})
88
+ new(expression[:field], expression[:operator], expression[:value])
89
+ end
90
+
91
+ end
92
+
93
+ end
@@ -0,0 +1,3 @@
1
+ module AutotaskApi
2
+ VERSION = '0.3.0'
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :autotask_api do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: autotask_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ platform: ruby
6
+ authors:
7
+ - Kevin Pheasey
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-08-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nokogiri
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '1'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '2'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '1'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '2'
33
+ - !ruby/object:Gem::Dependency
34
+ name: savon
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '2'
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: '3'
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '2'
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: '3'
53
+ description: Abstracted Autotask API 1.5 wrapper
54
+ email:
55
+ - kevin@kpsoftware.io
56
+ executables: []
57
+ extensions: []
58
+ extra_rdoc_files: []
59
+ files:
60
+ - MIT-LICENSE
61
+ - README.md
62
+ - Rakefile
63
+ - lib/autotask_api.rb
64
+ - lib/autotask_api/client.rb
65
+ - lib/autotask_api/config.rb
66
+ - lib/autotask_api/entity.rb
67
+ - lib/autotask_api/entity_collection.rb
68
+ - lib/autotask_api/query.rb
69
+ - lib/autotask_api/version.rb
70
+ - lib/tasks/autotask_api_tasks.rake
71
+ homepage: https://github.com/MSPCFO/autotask_api
72
+ licenses:
73
+ - MIT
74
+ metadata: {}
75
+ post_install_message:
76
+ rdoc_options: []
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ requirements: []
90
+ rubyforge_project:
91
+ rubygems_version: 2.7.6
92
+ signing_key:
93
+ specification_version: 4
94
+ summary: Autotask API wrapper
95
+ test_files: []