intacct_ruby 0.2.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d42a536100b60ef09ae692e1ca89d06cf8842684
4
- data.tar.gz: 451891434ad91b2f70873d30c64a790170c733a6
3
+ metadata.gz: baaffa6dd9353222e537633286a01ebdbbc0e196
4
+ data.tar.gz: 4f174bbff844a691902f8e6cf9059d0f4c11b86c
5
5
  SHA512:
6
- metadata.gz: 9dbd0f7d721c24e1eca287937f417f22ad9b204d6d77a6e17286188982d808a531805a77ccd3cb8ec29c974197423d27959947b68f390b9bcd9110c711d3de69
7
- data.tar.gz: b75ce4f70c468cce6fd67bf715a4daa75bfd004389fc5752f84d792ca1707c7257c6bf4bcfbbfb2b821dad078381233b73d42cdf3fd4bbab97d386681d480625
6
+ metadata.gz: 33f2fc22db5cbc9dc1b4f0bbc65b37cbd674411e8c0972309c7d77b6d46e431b33a677429383b7ad17ce84dcd7b084ecc386361dc4754fd0564eb8f813ad8510
7
+ data.tar.gz: c03c9f4b18d77285b6c333fbeb0d8097ce256004a44d9814a150194485d8a3251740f9424d24d903827f6853f7ccd0d8304a4ca2d83f1fdbfb859fd88f756166
data/README.md CHANGED
@@ -34,7 +34,7 @@ create_project = IntacctRuby::Functions::CreateProject.new(
34
34
  }
35
35
  )
36
36
 
37
- request = IntacctRuby::Request.new(create_customer, create_project)
37
+ request = IntacctRuby::Request.new(create_customer, create_project, authentication_params)
38
38
  request.send
39
39
  ```
40
40
 
@@ -91,25 +91,78 @@ This will fire off a request that looks something like this:
91
91
  ```
92
92
  If there are function errors (e.g. you omitted a required field) you'll see an error on response. Same if you see an internal server error, or any error outside of the 2xx range.
93
93
 
94
- ## Customizing Calls
95
-
94
+ ## Authentication
96
95
  Before we go any further, make sure you've read the [Intacct API Quickstart Guide](https://developer.intacct.com/wiki/constructing-web-services-request#The%20Intacct%20DTDs).
97
96
 
97
+ In IntacctRuby - as with the Intacct API that the gem wraps - your system credentials are pass along with each separate `Request` instance. The functions that define a request are followed by a hash that spells out each piece of information required by Intacct for authentication. These fields are:
98
+
99
+ - `senderid`
100
+ - `sender_password`\*
101
+ - `userid`
102
+ - `companyid`
103
+ - `user_password`\*
104
+
105
+ \* _In [Intacct's documentation](https://developer.intacct.com/wiki/constructing-web-services-request), these are referred to only as `password`. This won't work in Rubyland, though, because we're unable to have multiple hash entries with the same key._
106
+
107
+ ### Authentication Example:
108
+
109
+ ```ruby
110
+ IntacctRuby::Request.new(
111
+ some_function,
112
+ another_function,
113
+ senderid: 'some_senderid_value',
114
+ sender_password: 'some_sender_password_value',
115
+ userid: 'some_userid_value',
116
+ companyid: 'some_companyid_value',
117
+ user_password: 'some_user_password_value'
118
+ )
119
+ ```
120
+
121
+ Though, it probably makes more sense to keep all of these in some handy constant for easy reuse:
122
+ ```ruby
123
+ REQUEST_OPTS = {
124
+ senderid: 'some_senderid_value',
125
+ sender_password: 'some_sender_password_value',
126
+ userid: 'some_userid_value',
127
+ companyid: 'some_companyid_value',
128
+ user_password: 'some_user_password_value'
129
+ }
130
+
131
+ IntacctRuby::Request.new(some_function, another_function, REQUEST_OPTS)
132
+ ```
133
+
134
+ ### Important Notes on Authentication
135
+ #### These Are Required!
136
+ Obviously, Intacct won't do anything if you don't tell it who you are. To save you the bandwidth, this gem will throw errors if any of these auth params are not provided.
137
+
138
+ #### BE SAFE!
139
+ Though the examples above show hard-coded username/password pairs, this is a really bad idea to do in production code. Instead, we recommend storing these variables in ENVs, using a tool like [Figaro](https://github.com/laserlemon/figaro) to bring it all together.
140
+
141
+ ## Customizing Calls
142
+
98
143
  This gem creates calls using the following defaults:
99
144
  - **uniqueid:** false,
100
145
  - **dtdversion:** 3.0,
101
146
  - **includewhitespace:** false,
102
147
  - **transaction:** true
103
148
 
104
- If you'd like to override any of these, you can do so when you create a new request:
149
+ If you'd like to override any of these, you can do so when you create a new request by adding additional fields to the options hash passed into `Request#new`:
105
150
 
106
151
  ```ruby
107
- IntacctRuby::Request.new(
108
- function_1,
109
- function_2,
152
+ REQUEST_OPTS = {
153
+ senderid: 'some_senderid_value',
154
+ sender_password: 'some_sender_password_value',
155
+ userid: 'some_userid_value',
156
+ companyid: 'some_companyid_value',
157
+ user_password: 'some_user_password_value'
158
+ }
159
+
160
+ REQUEST_OPTS.merge!(
110
161
  uniqueid: 'some_uniqueid_override',
111
162
  dtdversion: 'some_dtd_override'
112
163
  )
164
+
165
+ IntacctRuby::Request.new(some_function, another_function, REQUEST_OPTS)
113
166
  ```
114
167
  ## Installation
115
168
 
@@ -128,28 +181,6 @@ Or install it yourself as:
128
181
 
129
182
  $ gem install intacct_ruby
130
183
 
131
- ### The Configuration (Don't Skip This Part!)
132
- Once the gem's in place, you'll have it teach it your company secrets.
133
-
134
- Intacct requires that the following credentials be passed along in the `<control>` block of each request:
135
- - `senderid`
136
- - (sender) `password`
137
-
138
- and that the following be sent in the `<authentication>` block, too:
139
- - `userid`
140
- - `companyid`
141
- - `password`
142
-
143
- IntacctRuby handles all this for you, but you'll need to tell it which is which. The gem pulls these values from Environmental variables, and it uses [Figaro](https://github.com/laserlemon/figaro) to manage the whole process. In order to get this to work, you'll need to have an `application.yml` file in your project directory with the following definitions:
144
- ```yaml
145
- intacct_senderid: 'some senderid'
146
- intacct_sender_password: 'some password'
147
- intacct_userid: 'some userid'
148
- intacct_user_password: 'some password'
149
- intacct_companyid: 'some companyid'
150
- ```
151
- Once those are in place, IntacctRuby will suck 'em up and deposit them in the requests that you generate. Eeeasy squeezey.
152
-
153
184
  ## Adding New Functions
154
185
  This gem was designed, as so many are, for a specific use case. The Intacct API has hundreds of API calls, though I only built out a dozen or so. Within that dozen, I only built out the fields that I needed in each call.
155
186
 
@@ -33,5 +33,4 @@ Gem::Specification.new do |spec|
33
33
  spec.add_development_dependency 'pry-byebug', '~> 3.4', '>= 3.4.2'
34
34
 
35
35
  spec.add_runtime_dependency 'builder', '~> 3.0', '>= 3.0.4'
36
- spec.add_runtime_dependency 'figaro', '~> 1.1', '>= 1.1.1'
37
36
  end
@@ -0,0 +1,5 @@
1
+ module IntacctRuby
2
+ module Exceptions
3
+ class EmptyRequestException < StandardError; end
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module IntacctRuby
2
+ module Exceptions
3
+ class InsufficientCredentialsException < StandardError; end
4
+ end
5
+ end
@@ -1,8 +1,9 @@
1
1
  require 'builder'
2
- require 'figaro'
3
2
 
4
3
  require 'intacct_ruby/api'
5
4
  require 'intacct_ruby/response'
5
+ require 'intacct_ruby/exceptions/insufficient_credentials_exception'
6
+ require 'intacct_ruby/exceptions/empty_request_exception'
6
7
 
7
8
  module IntacctRuby
8
9
  # An outgoing request to the Intacct API. Can have multiple functions.
@@ -15,15 +16,21 @@ module IntacctRuby
15
16
  transaction: true
16
17
  }.freeze
17
18
 
18
- def initialize(*args)
19
- @opts = DEFAULTS.dup
19
+ REQUIRED_AUTHENTICATION_KEYS = [
20
+ :senderid,
21
+ :sender_password,
22
+ :userid,
23
+ :companyid,
24
+ :user_password
25
+ ].freeze
20
26
 
21
- # `args` should be a list of Intacct::Function objects, with the last
22
- # argument optionally providing overrides to request defaults
23
- @opts.merge!(args.pop) if args.last.is_a? Hash
27
+ def initialize(*functions, request_params)
28
+ # request_params should contain all req'd authentication information. If
29
+ # not, an error will be thrown on #send
30
+ @opts = DEFAULTS.dup.merge request_params
24
31
 
25
32
  # If a hash is provided + popped, the remaining attrs are functions
26
- @functions = args
33
+ @functions = functions
27
34
  end
28
35
 
29
36
  def to_xml
@@ -39,6 +46,9 @@ module IntacctRuby
39
46
  def send(api = nil)
40
47
  api ||= Api.new
41
48
 
49
+ validate_keys!
50
+ validate_functions!
51
+
42
52
  Response.new api.send(self)
43
53
  end
44
54
 
@@ -46,14 +56,34 @@ module IntacctRuby
46
56
 
47
57
  attr_reader :request, :functions
48
58
 
59
+ def validate_functions!
60
+ unless functions.any?
61
+ raise Exceptions::EmptyRequestException,
62
+ 'a successful request must contain at least one function'
63
+ end
64
+ end
65
+
66
+ def validate_keys!
67
+ missing_keys = REQUIRED_AUTHENTICATION_KEYS - @opts.keys
68
+
69
+ unless missing_keys.empty?
70
+ missing_keys.map! { |s| ":#{s}" } # so they appear as symbols in output
71
+
72
+ raise Exceptions::InsufficientCredentialsException,
73
+ "[#{missing_keys.join(', ')}] required for a valid request. "
74
+ 'All authentication-related keys should be provided on ' \
75
+ 'instantiation in IntacctRuby::Request#new'
76
+ end
77
+ end
78
+
49
79
  def timestamp
50
80
  @timestamp ||= Time.now.utc.to_s
51
81
  end
52
82
 
53
83
  def control_block
54
84
  request.control do
55
- request.senderid Figaro.env.intacct_senderid
56
- request.password Figaro.env.intacct_sender_password
85
+ request.senderid @opts[:senderid]
86
+ request.password @opts[:sender_password]
57
87
 
58
88
  # As recommended by Intacct API reference. This ID should be unique
59
89
  # to the call: it's used to associate a response with a request.
@@ -67,9 +97,9 @@ module IntacctRuby
67
97
  def authentication_block
68
98
  request.authentication do
69
99
  request.login do
70
- request.userid Figaro.env.intacct_userid
71
- request.companyid Figaro.env.intacct_companyid
72
- request.password Figaro.env.intacct_user_password
100
+ request.userid @opts[:userid]
101
+ request.companyid @opts[:companyid]
102
+ request.password @opts[:user_password]
73
103
  end
74
104
  end
75
105
  end
@@ -1,3 +1,3 @@
1
1
  module IntacctRuby
2
- VERSION = '0.2.0'.freeze
2
+ VERSION = '1.0.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: intacct_ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Zornow
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-04-14 00:00:00.000000000 Z
11
+ date: 2017-04-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -126,26 +126,6 @@ dependencies:
126
126
  - - ">="
127
127
  - !ruby/object:Gem::Version
128
128
  version: 3.0.4
129
- - !ruby/object:Gem::Dependency
130
- name: figaro
131
- requirement: !ruby/object:Gem::Requirement
132
- requirements:
133
- - - "~>"
134
- - !ruby/object:Gem::Version
135
- version: '1.1'
136
- - - ">="
137
- - !ruby/object:Gem::Version
138
- version: 1.1.1
139
- type: :runtime
140
- prerelease: false
141
- version_requirements: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - "~>"
144
- - !ruby/object:Gem::Version
145
- version: '1.1'
146
- - - ">="
147
- - !ruby/object:Gem::Version
148
- version: 1.1.1
149
129
  description: Allows for multi-function API calls, the addition of custom fields, and
150
130
  more. All in an easy-to-use package!
151
131
  email:
@@ -167,7 +147,9 @@ files:
167
147
  - intacct_ruby.gemspec
168
148
  - lib/intacct_ruby.rb
169
149
  - lib/intacct_ruby/api.rb
150
+ - lib/intacct_ruby/exceptions/empty_request_exception.rb
170
151
  - lib/intacct_ruby/exceptions/function_failure_exception.rb
152
+ - lib/intacct_ruby/exceptions/insufficient_credentials_exception.rb
171
153
  - lib/intacct_ruby/functions/base_function.rb
172
154
  - lib/intacct_ruby/functions/create_aradjustment.rb
173
155
  - lib/intacct_ruby/functions/create_customer.rb