pokitdok-ruby 0.7.4 → 0.8.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: eec04d8678df0b571cc7a591479a22e0a7e73499
4
- data.tar.gz: 8b3fc476ba113e13fd494656810a0b3f038723a9
3
+ metadata.gz: 39fe6e6cd01f6b839d325c3f36a8c431f4bb28e1
4
+ data.tar.gz: 8eb46680810f6453958ae8d914861aa30e4150d4
5
5
  SHA512:
6
- metadata.gz: b1b269d7a96ccdc7ef731a9845d19b9432226d9894e668d9743f67ac9850ffdd6ecfe0ec7a82661e45831fb9f41d4a4fc308d391017ad0470d60b4c9ac915403
7
- data.tar.gz: 91f3d356570058b1ed4bbf751fb33c7693fe94dd7dd2b8e1d41ea467b5f340f147ef39a92eba8a79a3d25feed55720197b7c1c398110ee8d11cb4b151b6eae64
6
+ metadata.gz: c87e045eecc7c3e9b663da64bc18cc546cb17c77e09c0cdaff5076ca764f9fe87f6fd92b268d98f089985d412befd793db2fe81906740201e7e0f73ff2671a84
7
+ data.tar.gz: 81923ed48261191bb967eaead0278e6f5308f56b7bc2f93d29f816af28b9836c24071843ae928edc6c07a1c7b9cd0bba832d76bff067db9bc6046843bb4e2189
data/Gemfile CHANGED
@@ -12,7 +12,6 @@ group :development do
12
12
  gem 'jeweler', '~> 2.0'
13
13
  gem 'ansi', '~> 1.4'
14
14
  gem 'minitest-reporters', '~> 1.0'
15
- gem 'vcr', '~> 2.9'
16
15
  gem 'webmock', '~> 1.17'
17
16
  gem 'guard', '~> 2.6'
18
17
  gem 'guard-minitest', '~> 2.2'
@@ -1,7 +1,7 @@
1
1
  GEM
2
2
  remote: https://rubygems.org/
3
3
  specs:
4
- addressable (2.3.8)
4
+ addressable (2.4.0)
5
5
  ansi (1.5.0)
6
6
  ast (2.0.0)
7
7
  astrolabe (1.3.0)
@@ -26,15 +26,14 @@ GEM
26
26
  faraday (0.9.2)
27
27
  multipart-post (>= 1.2, < 3)
28
28
  ffi (1.9.8)
29
+ ffi (1.9.8-java)
29
30
  formatador (0.2.5)
30
- git (1.2.9.1)
31
- github_api (0.12.3)
32
- addressable (~> 2.3)
31
+ git (1.3.0)
32
+ github_api (0.14.1)
33
+ addressable (~> 2.4.0)
33
34
  descendants_tracker (~> 0.0.4)
34
35
  faraday (~> 0.8, < 0.10)
35
- hashie (>= 3.3)
36
- multi_json (>= 1.7.5, < 2.0)
37
- nokogiri (~> 1.6.3)
36
+ hashie (>= 3.4)
38
37
  oauth2
39
38
  guard (2.12.5)
40
39
  formatador (>= 0.2.4)
@@ -52,12 +51,13 @@ GEM
52
51
  guard-rubocop (1.2.0)
53
52
  guard (~> 2.0)
54
53
  rubocop (~> 0.20)
55
- hashie (3.4.1)
56
- highline (1.7.2)
54
+ hashie (3.4.4)
55
+ highline (1.7.8)
57
56
  hitimes (1.2.2)
57
+ hitimes (1.2.2-java)
58
58
  http-cookie (1.0.2)
59
59
  domain_name (~> 0.5)
60
- jeweler (2.0.1)
60
+ jeweler (2.1.1)
61
61
  builder
62
62
  bundler (>= 1.0)
63
63
  git (>= 1.2.5)
@@ -66,7 +66,9 @@ GEM
66
66
  nokogiri (>= 1.5.10)
67
67
  rake
68
68
  rdoc
69
- json (1.8.2)
69
+ semver
70
+ json (1.8.3)
71
+ json (1.8.3-java)
70
72
  jwt (1.5.1)
71
73
  listen (2.10.0)
72
74
  celluloid (~> 0.16.0)
@@ -76,7 +78,7 @@ GEM
76
78
  metaclass (0.0.4)
77
79
  method_source (0.8.2)
78
80
  mime-types (2.5)
79
- mini_portile (0.6.2)
81
+ mini_portile2 (2.1.0)
80
82
  minitest (5.6.1)
81
83
  minitest-reporters (1.0.16)
82
84
  ansi
@@ -85,13 +87,15 @@ GEM
85
87
  ruby-progressbar
86
88
  mocha (1.1.0)
87
89
  metaclass (~> 0.0.1)
88
- multi_json (1.12.0)
90
+ multi_json (1.12.1)
89
91
  multi_xml (0.5.5)
90
92
  multipart-post (2.0.0)
91
93
  nenv (0.2.0)
92
94
  netrc (0.10.3)
93
- nokogiri (1.6.6.2)
94
- mini_portile (~> 0.6.0)
95
+ nokogiri (1.6.8)
96
+ mini_portile2 (~> 2.1.0)
97
+ pkg-config (~> 1.1.7)
98
+ nokogiri (1.6.8-java)
95
99
  notiffany (0.0.6)
96
100
  nenv (~> 0.1)
97
101
  shellany (~> 0.0)
@@ -103,18 +107,24 @@ GEM
103
107
  rack (>= 1.2, < 3)
104
108
  parser (2.2.2.3)
105
109
  ast (>= 1.1, < 3.0)
110
+ pkg-config (1.1.7)
106
111
  powerpack (0.1.1)
107
112
  pry (0.10.1)
108
113
  coderay (~> 1.1.0)
109
114
  method_source (~> 0.8.1)
110
115
  slop (~> 3.4)
116
+ pry (0.10.1-java)
117
+ coderay (~> 1.1.0)
118
+ method_source (~> 0.8.1)
119
+ slop (~> 3.4)
120
+ spoon (~> 0.0)
111
121
  rack (1.6.4)
112
122
  rainbow (2.0.0)
113
- rake (10.4.2)
123
+ rake (11.2.2)
114
124
  rb-fsevent (0.9.5)
115
125
  rb-inotify (0.9.5)
116
126
  ffi (>= 0.5.0)
117
- rdoc (4.2.0)
127
+ rdoc (4.2.2)
118
128
  json (~> 1.4)
119
129
  rest-client (1.8.0)
120
130
  http-cookie (>= 1.0.2, < 2.0)
@@ -128,6 +138,7 @@ GEM
128
138
  ruby-progressbar (~> 1.4)
129
139
  ruby-progressbar (1.7.5)
130
140
  safe_yaml (1.0.4)
141
+ semver (1.0.1)
131
142
  shellany (0.0.1)
132
143
  simplecov (0.10.0)
133
144
  docile (~> 1.1.0)
@@ -135,24 +146,28 @@ GEM
135
146
  simplecov-html (~> 0.10.0)
136
147
  simplecov-html (0.10.0)
137
148
  slop (3.6.0)
149
+ spoon (0.0.4)
150
+ ffi
138
151
  term-ansicolor (1.3.0)
139
152
  tins (~> 1.0)
140
153
  terminal-notifier (1.6.3)
141
154
  terminal-notifier-guard (1.6.4)
142
155
  thor (0.19.1)
143
156
  thread_safe (0.3.5)
157
+ thread_safe (0.3.5-java)
144
158
  timers (4.0.1)
145
159
  hitimes
146
160
  tins (1.5.1)
147
161
  unf (0.1.4)
148
162
  unf_ext
163
+ unf (0.1.4-java)
149
164
  unf_ext (0.0.7.1)
150
- vcr (2.9.3)
151
165
  webmock (1.21.0)
152
166
  addressable (>= 2.3.6)
153
167
  crack (>= 0.3.2)
154
168
 
155
169
  PLATFORMS
170
+ java
156
171
  ruby
157
172
 
158
173
  DEPENDENCIES
@@ -173,8 +188,7 @@ DEPENDENCIES
173
188
  simplecov (~> 0.8)
174
189
  terminal-notifier
175
190
  terminal-notifier-guard (~> 1.5)
176
- vcr (~> 2.9)
177
191
  webmock (~> 1.17)
178
192
 
179
193
  BUNDLED WITH
180
- 1.12.1
194
+ 1.12.5
data/README.md CHANGED
@@ -135,14 +135,38 @@ you can pass a third parameter to PokitDok::Pokitdok.new, like this:
135
135
  This library aims to support and is tested against these Ruby versions,
136
136
  using travis-ci:
137
137
 
138
+ * 2.2.3
138
139
  * 2.1.1
139
140
  * 2.0.0
140
141
  * 1.9.3
141
142
  * JRuby in 1.9 mode
142
- * Rubinius 2.2.7
143
143
 
144
144
  You may have luck with other interpreters - let us know how it goes.
145
145
 
146
+ ## Development/Debugging
147
+
148
+ ##### Prerequisite: Make sure to have the RubyMine plugin installed with IntelliJ.
149
+
150
+ #### Steps to getting setup in the IntelliJ IDE:
151
+ 1. Fork and/or clone the `pokitdok-ruby` github repository onto your local machine.
152
+ 2. Open IntelliJ IDE.
153
+ 3. Select `File > New > Project From Existing Sources` and select the directory of the cloned `pokitdok-ruby` project.
154
+ 4. In the pop-up GUI select `Create project from existing sources` and continue selecting next/finish with the default settings.
155
+ 5. Next you want to make sure ruby has selected the correct ruby SDK. It is recommended to use rvm for ruby version management.
156
+ * Select `File > Project Structure`. Then under the Project -> SDK settings select the ruby version you wish to use with the project (i.e.- `RVM: ruby-1.9.3-p551 [global]`).
157
+ 6. You will probably be prompted to install the project dependencies with bundler which you should do.
158
+ 7. Now to debug tests you need to create a `run configuration`.
159
+ * Select `Run > Edit Configurations`.
160
+ * We use `rake` to run our project tasks. So select the `+` button and add a new `Rake` configuration.
161
+ * A few properties you need to set:
162
+ * Task Name: `spec`
163
+ * Ruby SDK -> Use other SDK and 'rake' gem: `Whichever ruby version you chose in step 5`
164
+ * Bundler Tab: Check the box labeled `Run the script in the context of the bundle (bundle exec)`
165
+ 8. You can now run/debug the project tests in the IntelliJ IDE.
166
+ * NOTE: Currently the tests will not finish executing though all are completed. This is a known issue with RubyMine.
167
+
168
+ NOTE: If you would just like to run the test framework outside of the IDE make sure to have all the dependencies installed via bundle in the project directory then run the following command: `bundle exec rake spec`.
169
+
146
170
  ## License
147
171
  Copyright (c) 2014 PokitDok Inc. See [LICENSE][] for details.
148
172
 
data/Rakefile CHANGED
@@ -29,6 +29,7 @@ Rake::TestTask.new(:spec) do |spec|
29
29
  spec.libs << 'lib' << 'spec'
30
30
  spec.pattern = 'spec/**/*_spec.rb'
31
31
  spec.verbose = true
32
+ spec.warning = false
32
33
  end
33
34
 
34
35
  require 'coveralls'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.4
1
+ 0.8.0
@@ -0,0 +1,149 @@
1
+ require 'oauth2'
2
+
3
+ # OAuth 2.0 Client implementation for Ruby.
4
+ class OAuthApplicationClient
5
+ attr_accessor :token, :user_agent
6
+
7
+ # Connect to the PokitDok API with the specified Client ID and Client
8
+ # Authentication logic located within this class.
9
+ #
10
+ # +client_id+ your client ID, provided by PokitDok
11
+ # +client_secret+ your client secret, provided by PokitDok
12
+ # +token_url+ token url to be appended for authentication. Defaults to '/oauth2/token'
13
+ # +redirect_uri+ the Redirect URI set for the PokitDok Platform Application.
14
+ # This value is managed at https://platform.pokitdok.com in the App Settings
15
+ # +scope+ a list of scope names that should be used when requesting authorization
16
+ # +code+ code value received from an authorization code grant
17
+ # +token+ The current API access token for your PokitDok Platform Application. If not provided a new token is generated.
18
+ # +user_agent+ user agent to be used as a header in HTTP requests
19
+ def initialize(client_id, client_secret, token_url, redirect_uri, scope, code, token, user_agent)
20
+ @client_id = client_id
21
+ @client_secret = client_secret
22
+ @token_url = token_url
23
+ @redirect_uri = redirect_uri
24
+ @scope = scope
25
+ @code = code
26
+ @user_agent = user_agent
27
+ @token = token
28
+
29
+ @api_client = OAuth2::Client.new(@client_id, @client_secret, site: @api_url, token_url: @token_url, raise_errors: false)
30
+ if @token.nil?
31
+ fetch_access_token(@code)
32
+ end
33
+ end
34
+
35
+ # Perform a GET request given the http request path and optional params
36
+ #
37
+ # +path+ request path
38
+ # +params+ an optional hash of parameters that will be sent in the request
39
+ def get_request(path, params, &block)
40
+ if isAccessTokenExpired?
41
+ fetch_access_token()
42
+ end
43
+ @token.get(path, params: params, headers: headers, &block)
44
+ end
45
+
46
+ # Perform a PUT request given the http request path and optional params
47
+ #
48
+ # +path+ request path
49
+ # +params+ an optional hash of parameters that will be sent in the request
50
+ def put_request(path, params = {}, &block)
51
+ if isAccessTokenExpired?
52
+ fetch_access_token()
53
+ end
54
+ headers.merge({ headers: { :'Content-Type' => 'application/json'}})
55
+ @token.put(path, body: params.to_json, headers: headers({:'Content-Type' => 'application/json'}), &block)
56
+ end
57
+
58
+ # Perform a POST request given the http request path and optional params
59
+ #
60
+ # +path+ request path
61
+ # +params+ an optional hash of parameters that will be sent in the request
62
+ def post_request(path, params = {}, &block)
63
+ if isAccessTokenExpired?
64
+ fetch_access_token()
65
+ end
66
+ headers.merge({ headers: { :'Content-Type' => 'application/json'}})
67
+ @token.post(path, body: params.to_json, headers: headers({:'Content-Type' => 'application/json'}), &block)
68
+ end
69
+
70
+ # Perform a POST request given the http request path, a file and optional params
71
+ #
72
+ # +path+ request path
73
+ # +file+ the file to be sent with the request
74
+ # +params+ an optional hash of parameters that will be sent in the request
75
+ def post_file(endpoint, file=nil, params={})
76
+ if isAccessTokenExpired?
77
+ fetch_access_token()
78
+ end
79
+ url = URI.parse(@api_url + endpoint)
80
+
81
+ File.open(file) do |f|
82
+ additional_params = params.merge({'file' => UploadIO.new(f, 'application/EDI-X12', file)})
83
+ req = Net::HTTP::Post::Multipart.new(url.path, additional_params)
84
+
85
+ req['Authorization'] = "Bearer #{self.token.token}"
86
+ req['User-Agent'] = @user_agent
87
+
88
+ @response = Net::HTTP.start(url.host, url.port) do |http|
89
+ http.request(req)
90
+ end
91
+ JSON.parse(@response.body)
92
+ end
93
+ end
94
+
95
+ # Perform a DELETE request given the http request path and optional params
96
+ #
97
+ # +path+ request path
98
+ # +params+ an optional hash of parameters that will be sent in the request
99
+ def delete_request(path, params = {}, &block)
100
+ if isAccessTokenExpired?
101
+ fetch_access_token()
102
+ end
103
+ @token.delete(path, body: params.to_json, headers: headers({:'Content-Type' => 'application/json'}), &block)
104
+ end
105
+
106
+ # Construct OAuth2 Authorization Grant URL
107
+ def authorization_url()
108
+ if @redirect_uri.nil? || @scope.nil?
109
+ raise 'A redirect_uri and scope must be specified when the client is instantiated in order to get a working authorization URL'
110
+ end
111
+ @api_client.auth_code.authorize_url(redirect_uri: @redirect_uri, scope: @scope)
112
+ end
113
+
114
+ ### PRIVATE METHODS ###
115
+
116
+ # Retrieves an OAuth2 access token. If `code` is not specified, the client_credentials
117
+ # grant type will be used based on the client_id and client_secret. If `code` is not None,
118
+ # an authorization_code grant type will be used.
119
+ #
120
+ # +code+ optional authorization code used for scope purposes
121
+ def fetch_access_token(code = nil)
122
+ if code
123
+ # Currently non functioning as our OAuth2 authorization_code grant type is not implemented on the server
124
+ params = {
125
+ headers: { 'Authorization' => 'Basic' },
126
+ scope: @scope,
127
+ redirect_uri: @redirect_uri
128
+ }
129
+ @token = @api_client.auth_code.get_token(code, params)
130
+ else
131
+ @token = @api_client.client_credentials.get_token(headers: { 'Authorization' => 'Basic' })
132
+ end
133
+ end
134
+
135
+ # Returns a standard set of headers to be passed along with all requests
136
+ def headers(additional_headers = {})
137
+ { 'User-Agent' => @user_agent }.merge(additional_headers)
138
+ end
139
+
140
+ # Check if the access token is expired
141
+ def isAccessTokenExpired?
142
+ if !@token.is_a?(OAuth2::AccessToken)
143
+ return true
144
+ end
145
+ @token.expired?
146
+ end
147
+
148
+ private :headers, :isAccessTokenExpired?, :fetch_access_token
149
+ end
@@ -11,15 +11,13 @@ require 'rubygems'
11
11
  require 'bundler/setup'
12
12
  require 'base64'
13
13
  require 'json'
14
- require 'oauth2'
14
+ require 'OAuthApplicationClient'
15
15
  require 'net/http/post/multipart'
16
16
 
17
17
  module PokitDok
18
18
  # PokitDok API client implementation for Ruby.
19
- class PokitDok
20
- POKITDOK_URL_BASE = 'https://platform.pokitdok.com' # :nodoc:
21
-
22
- attr_reader :client # :nodoc:
19
+ class PokitDok < OAuthApplicationClient
20
+ attr_reader :api_client # :nodoc:
23
21
  attr_reader :api_url
24
22
  attr_reader :version
25
23
 
@@ -27,36 +25,19 @@ module PokitDok
27
25
  # Secret.
28
26
  #
29
27
  # +client_id+ your client ID, provided by PokitDok
30
- #
31
28
  # +client_secret+ your client secret, provided by PokitDok
29
+ # +version+ The API version that should be used for requests. Defaults to the latest version.
30
+ # +base+ The base URL to use for API requests. Defaults to https://platform.pokitdok.com
32
31
  #
33
- def initialize(client_id, client_secret, version='v4')
34
- @client_id = client_id
35
- @client_secret = client_secret
32
+ # TODO: Make it simpler to pass in params out of order (also so you don't have to do init(..., nil, nil, nil, param))
33
+ #
34
+ def initialize(client_id, client_secret, version='v4', base='https://platform.pokitdok.com',
35
+ redirect_uri=nil, scope= nil, code=nil, token= nil)
36
36
  @version = version
37
+ @api_url = "#{base}/api/#{version}"
38
+ @user_agent = "pokitdok-ruby 0.8 #{RUBY_DESCRIPTION}"
37
39
 
38
- @api_url = "#{url_base}/api/#{version}"
39
- @client = OAuth2::Client.new(@client_id, @client_secret,
40
- site: @api_url, token_url: '/oauth2/token')
41
-
42
-
43
- @scopes = {}
44
- @scopes['default'] = { scope: refresh_token }
45
- scope 'default'
46
- end
47
-
48
- # Accessor for the PokitDok Platform URL, overridable for testing.
49
- def url_base
50
- POKITDOK_URL_BASE
51
- end
52
-
53
- # Adds an authorization code for a given OAuth2 scope.
54
- #
55
- # +name+ the scope name
56
- # +code+ the authorization code
57
- #
58
- def scope_code(name, code)
59
- @scopes[name] = { code: code }
40
+ super(client_id, client_secret, '/oauth2/token', redirect_uri, scope, code, token, user_agent)
60
41
  end
61
42
 
62
43
  # Invokes the appointments endpoint, to query for open appointment slots
@@ -66,7 +47,6 @@ module PokitDok
66
47
  # +params+ an optional Hash of parameters
67
48
  #
68
49
  def activities(params = {})
69
- scope 'default'
70
50
  get('activities/', params)
71
51
  end
72
52
 
@@ -75,7 +55,6 @@ module PokitDok
75
55
  # +params+ an optional hash of parameters that will be sent in the POST body
76
56
  #
77
57
  def authorizations(params = {})
78
- scope 'default'
79
58
  post('authorizations/', params)
80
59
  end
81
60
 
@@ -84,7 +63,6 @@ module PokitDok
84
63
  # +params+ an optional hash of parameters that will be sent in the POST body
85
64
  #
86
65
  def cash_prices(params = {})
87
- scope 'default'
88
66
  get('prices/cash', params)
89
67
  end
90
68
 
@@ -93,7 +71,6 @@ module PokitDok
93
71
  # +params+ an optional hash of parameters that will be sent in the POST body
94
72
  #
95
73
  def claims(params = {})
96
- scope 'default'
97
74
  post('claims/', params)
98
75
  end
99
76
 
@@ -102,16 +79,39 @@ module PokitDok
102
79
  # +params+ an optional hash of parameters that will be sent in the POST body
103
80
  #
104
81
  def claims_status(params = {})
105
- scope 'default'
106
82
  post('claims/status', params)
107
83
  end
108
84
 
85
+ # Invokes the ICD convert endpoint.
86
+ #
87
+ # +params+ an optional hash of parameters
88
+ #
89
+ def icd_convert(params = {})
90
+ get("icd/convert/#{params[:code]}")
91
+ end
92
+
93
+ # Invokes the mpc endpoint.
94
+ #
95
+ # +params+ an optional hash of parameters
96
+ #
97
+ def mpc(params = {})
98
+ get('mpc/', params)
99
+ end
100
+
101
+ # Uploads an .837 file to the claims convert endpoint.
102
+ # Uses the multipart-post gem, since oauth2 doesn't support multipart.
103
+ #
104
+ # +x12_claims_file+ the path to the file to transmit
105
+ #
106
+ def claims_convert(x12_claims_file)
107
+ request('/claims/convert', 'POST', x12_claims_file)
108
+ end
109
+
109
110
  # Invokes the eligibility endpoint.
110
111
  #
111
112
  # +params+ an optional hash of parameters that will be sent in the POST body
112
113
  #
113
114
  def eligibility(params = {})
114
- scope 'default'
115
115
  post('eligibility/', params)
116
116
  end
117
117
 
@@ -120,10 +120,36 @@ module PokitDok
120
120
  # +params+ an optional hash of parameters that will be sent in the POST body
121
121
  #
122
122
  def enrollment(params = {})
123
- scope 'default'
124
123
  post('enrollment/', params)
125
124
  end
126
125
 
126
+ # Uploads an .834 file to the enrollment snapshot endpoint.
127
+ # Uses the multipart-post gem, since oauth2 doesn't support multipart.
128
+ #
129
+ # +trading_partner_id+ the trading partner to transmit to
130
+ # +x12_file+ the path to the file to transmit
131
+ #
132
+ def enrollment_snapshot(trading_partner_id, x12_file)
133
+ request("/enrollment/snapshot/#{trading_partner_id}", "POST", x12_file)
134
+ end
135
+
136
+ # Invokes the enrollment snapshots endpoint.
137
+ #
138
+ # +params+ an optional Hash of parameters
139
+ #
140
+ def enrollment_snapshots(params = {})
141
+ snapshot_id = params.delete :snapshot_id
142
+ get("enrollment/snapshot" + (snapshot_id ? "/#{snapshot_id}" : ''), params)
143
+ end
144
+
145
+ # Invokes the enrollment snapshots data endpoint.
146
+ #
147
+ # +params+ an optional Hash of parameters
148
+ #
149
+ def enrollment_snapshot_data(params = {})
150
+ get("enrollment/snapshot/#{params[:snapshot_id]}/data")
151
+ end
152
+
127
153
  # Uploads an EDI file to the files endpoint.
128
154
  # Uses the multipart-post gem, since oauth2 doesn't support multipart.
129
155
  #
@@ -131,22 +157,7 @@ module PokitDok
131
157
  # +filename+ the path to the file to transmit
132
158
  #
133
159
  def files(trading_partner_id, filename)
134
- scope 'default'
135
- url = URI.parse(@api_url + '/files/')
136
-
137
- File.open(filename) do |f|
138
- req = Net::HTTP::Post::Multipart.new url.path,
139
- 'file' => UploadIO.new(f, 'application/EDI-X12', filename),
140
- 'trading_partner_id' => trading_partner_id
141
- req['Authorization'] = "Bearer #{default_scope.token}"
142
- req['User-Agent'] = user_agent
143
-
144
- @response = Net::HTTP.start(url.host, url.port) do |http|
145
- http.request(req)
146
- end
147
- end
148
-
149
- JSON.parse(@response.body)
160
+ request('/files/', 'POST', filename, { trading_partner_id: trading_partner_id})
150
161
  end
151
162
 
152
163
  # Invokes the insurance prices endpoint.
@@ -154,7 +165,6 @@ module PokitDok
154
165
  # +params+ an optional hash of parameters
155
166
  #
156
167
  def insurance_prices(params = {})
157
- scope 'default'
158
168
  get('prices/insurance', params)
159
169
  end
160
170
 
@@ -163,7 +173,6 @@ module PokitDok
163
173
  # +params+ an optional hash of parameters
164
174
  #
165
175
  def payers(params = {})
166
- scope 'default'
167
176
  get('payers/', params)
168
177
  end
169
178
 
@@ -172,7 +181,6 @@ module PokitDok
172
181
  # +params+ an optional Hash of parameters
173
182
  #
174
183
  def plans(params = {})
175
- scope 'default'
176
184
  get('plans/', params)
177
185
  end
178
186
 
@@ -181,10 +189,7 @@ module PokitDok
181
189
  # +params+ an optional Hash of parameters
182
190
  #
183
191
  def providers(params = {})
184
- response = default_scope.get('providers/') do |request|
185
- request.params = params
186
- end
187
- JSON.parse(response.body)
192
+ get('providers/', params)
188
193
  end
189
194
 
190
195
  # Invokes the referrals endpoint.
@@ -192,7 +197,6 @@ module PokitDok
192
197
  # +params+ an optional Hash of parameters
193
198
  #
194
199
  def referrals(params = {})
195
- scope 'default'
196
200
  post('referrals/', params)
197
201
  end
198
202
 
@@ -202,12 +206,7 @@ module PokitDok
202
206
  #
203
207
  def trading_partners(params = {})
204
208
  trading_partner_id = params.delete :trading_partner_id
205
-
206
- response =
207
- default_scope.get("tradingpartners/#{trading_partner_id}") do |request|
208
- request.params = params
209
- end
210
- JSON.parse(response.body)
209
+ get("tradingpartners/#{trading_partner_id}")
211
210
  end
212
211
 
213
212
  # Scheduling endpoints
@@ -219,23 +218,18 @@ module PokitDok
219
218
  # +params+ an optional Hash of parameters
220
219
  #
221
220
  def appointment(params = {})
222
- @appointment_id = params.delete :appointment_id
223
- scope 'user_schedule'
224
-
225
- get_one('schedule/appointmenttypes/', @appointment_id, params)
221
+ appointment_id = params.delete :appointment_id
222
+ get("schedule/appointmenttypes/#{appointment_id}", params)
226
223
  end
227
224
 
228
225
  # Invokes the activities endpoint.
229
226
  #
230
227
  # This endpoint uses the user_schedule OAuth2 scope. You'll need to
231
- # get the user's authorization via our OAuth2 provider, and pass the
232
- # authorization code you received into
233
- # scope_code('user_schedule', '(the authorization code)')
228
+ # get the user's authorization via our OAuth2 provider
234
229
  #
235
230
  # +params+ an optional Hash of parameters
236
231
  #
237
232
  def appointments(params = {})
238
- scope 'user_schedule'
239
233
  get('schedule/appointments/', params)
240
234
  end
241
235
 
@@ -246,13 +240,7 @@ module PokitDok
246
240
  #
247
241
  def appointment_type(params = {})
248
242
  appointment_type = params.delete :uuid
249
-
250
- response =
251
- default_scope.get("schedule/appointmenttypes/#{appointment_type}") do |request|
252
- request.params = params
253
- end
254
-
255
- JSON.parse(response.body)
243
+ get("schedule/appointmenttypes/#{appointment_type}")
256
244
  end
257
245
 
258
246
  # Invokes the appointment_types endpoint.
@@ -260,51 +248,39 @@ module PokitDok
260
248
  # +params+ an optional hash of parameters
261
249
  #
262
250
  def appointment_types(params = {})
263
- scope 'default'
264
251
  get('schedule/appointmenttypes/', params)
265
252
  end
266
253
 
267
254
  # Books an appointment.
268
255
  #
269
256
  # This endpoint uses the user_schedule OAuth2 scope. You'll need to
270
- # get the user's authorization via our OAuth2 provider, and pass the
271
- # authorization code you received into
272
- # scope_code('user_schedule', '(the authorization code)')
257
+ # get the user's authorization via our OAuth2 provider
273
258
  #
274
259
  # +params+ an optional hash of parameters that will be sent in the POST body
275
260
  #
276
261
  def book_appointment(appointment_uuid, params = {})
277
- scope 'user_schedule'
278
-
279
- put_one("schedule/appointments", appointment_uuid, params)
262
+ put("schedule/appointments/#{appointment_uuid}", params)
280
263
  end
281
264
 
282
265
  # Cancels the specified appointment.
283
266
  #
284
267
  # This endpoint uses the user_schedule OAuth2 scope. You'll need to
285
- # get the user's authorization via our OAuth2 provider, and pass the
286
- # authorization code you received into
287
- # scope_code('user_schedule', '(the authorization code)')
268
+ # get the user's authorization via our OAuth2 provider
288
269
  #
289
270
  # +params+ an optional Hash of parameters
290
271
  #
291
272
  def cancel_appointment(appointment_uuid, params={})
292
- scope 'user_schedule'
293
-
294
- delete_one("schedule/appointments", appointment_uuid, params)
273
+ delete("schedule/appointments/#{appointment_uuid}", params)
295
274
  end
296
275
 
297
276
  # Invokes the schedule/appointments endpoint.
298
277
  #
299
278
  # This endpoint uses the user_schedule OAuth2 scope. You'll need to
300
- # get the user's authorization via our OAuth2 provider, and pass the
301
- # authorization code you received into
302
- # scope_code('user_schedule', '(the authorization code)')
279
+ # get the user's authorization via our OAuth2 provider
303
280
  #
304
281
  # +params+ an optional hash of parameters
305
282
  #
306
283
  def open_appointment_slots(params = {})
307
- scope 'user_schedule'
308
284
  get('schedule/appointments', params)
309
285
  end
310
286
 
@@ -313,7 +289,6 @@ module PokitDok
313
289
  # +params an optional Hash of parameters
314
290
  #
315
291
  def schedulers(params = {})
316
- scope 'default'
317
292
  get('schedule/schedulers/', params)
318
293
  end
319
294
 
@@ -324,25 +299,18 @@ module PokitDok
324
299
  #
325
300
  def scheduler(params = {})
326
301
  scheduler_id = params.delete :uuid
327
-
328
- response =
329
- default_scope.get("schedule/schedulers/#{scheduler_id}") do |request|
330
- request.params = params
331
- end
332
- JSON.parse(response.body)
302
+ get("schedule/schedulers/#{scheduler_id}")
333
303
  end
334
304
 
335
305
  # Invokes the slots endpoint.
336
306
  #
337
307
  # This endpoint uses the user_schedule OAuth2 scope. You'll need to
338
- # get the user's authorization via our OAuth2 provider, and pass the
339
- # authorization code you received into
340
- # scope_code('user_schedule', '(the authorization code)')
308
+ # get the user's authorization via our OAuth2 provider
341
309
  #
342
310
  # +params+ an optional Hash of parameters
343
311
  #
344
- def slots(params = {})
345
- scope 'user_schedule'
312
+ def schedule_slots(params = {})
313
+ post('/schedule/slots/', params)
346
314
  end
347
315
 
348
316
  # Invokes the pharmacy plans endpoint.
@@ -350,10 +318,7 @@ module PokitDok
350
318
  # +params+ an optional Hash of parameters
351
319
  #
352
320
  def pharmacy_plans(params = {})
353
- response = default_scope.get('pharmacy/plans') do |request|
354
- request.params = params
355
- end
356
- JSON.parse(response.body)
321
+ get('pharmacy/plans', params)
357
322
  end
358
323
 
359
324
  # Invokes the pharmacy formulary endpoint.
@@ -361,10 +326,7 @@ module PokitDok
361
326
  # +params+ an optional Hash of parameters
362
327
  #
363
328
  def pharmacy_formulary(params = {})
364
- response = default_scope.get('pharmacy/formulary') do |request|
365
- request.params = params
366
- end
367
- JSON.parse(response.body)
329
+ get('pharmacy/formulary', params)
368
330
  end
369
331
 
370
332
  # Invokes the pharmacy network cost endpoint.
@@ -374,76 +336,110 @@ module PokitDok
374
336
  def pharmacy_network(params = {})
375
337
  npi = params.delete :npi
376
338
  endpoint = npi ? "pharmacy/network/#{npi}" : "pharmacy/network"
377
- response = default_scope.get(endpoint) do |request|
378
- request.params = params
379
- end
380
- JSON.parse(response.body)
339
+ get(endpoint, params)
381
340
  end
382
341
 
383
342
  # Updates the specified appointment.
384
343
  #
385
344
  # This endpoint uses the user_schedule OAuth2 scope. You'll need to
386
- # get the user's authorization via our OAuth2 provider, and pass the
387
- # authorization code you received into
388
- # scope_code('user_schedule', '(the authorization code)')
345
+ # get the user's authorization via our OAuth2 provider
389
346
  #
390
347
  # +params+ an optional Hash of parameters
391
348
  #
392
349
  def update_appointment(appointment_uuid, params={})
393
- scope 'user_schedule'
350
+ put("schedule/appointments/#{appointment_uuid}", params)
351
+ end
394
352
 
395
- put_one("schedule/appointments", appointment_uuid, params)
396
- end
353
+ # Invokes the identity endpoint for creation
354
+ #
355
+ # +params+ a hash of parameters that will be sent in the POST body
356
+ #
357
+ def create_identity(params = {})
358
+ post('identity/', params)
359
+ end
397
360
 
398
- private
399
- # Returns a standard User-Agent string to be passed along with all requests
400
- def user_agent
401
- "pokitdok-ruby 0.8 #{RUBY_DESCRIPTION}"
402
- end
361
+ # Invokes the identity endpoint for updating
362
+ #
363
+ # +identity_uuid+ unique id of the identity to be updated
364
+ # +params+ a hash of parameters that will be sent in the PUT body
365
+ #
366
+ def update_identity(identity_uuid, params = {})
367
+ put("identity/#{identity_uuid}", params)
368
+ end
403
369
 
404
- # Returns a standard set of headers to be passed along with all requests
405
- def headers
406
- { 'User-Agent' => user_agent }
407
- end
370
+ # Invokes the identity endpoint for querying
371
+ #
372
+ # +params+ an optional hash of parameters that will be sent in the GET body
373
+ #
374
+ def identity(params = {})
375
+ identity_uuid = params.delete :identity_uuid
376
+ get("identity" + (identity_uuid ? "/#{identity_uuid}" : ''), params)
377
+ end
408
378
 
409
- def get(endpoint, params = {})
410
- response = current_scope.get(endpoint, headers: headers, params: params)
379
+ # Invokes the identity history endpoint
380
+ #
381
+ # +identity_uuid+ unique id of the identity to be updated
382
+ # +historical_version+ historical version of the identity being requested
383
+ #
384
+ def identity_history(identity_uuid, historical_version=nil)
385
+ get("identity/#{identity_uuid}/history" + (historical_version ? "/#{historical_version}" : ''))
386
+ end
411
387
 
412
- JSON.parse(response.body)
413
- end
388
+ # Invokes the identity endpoint for querying
389
+ #
390
+ # +params+ hash of parameters that will be sent in the POST body
391
+ #
392
+ def identity_match(params = {})
393
+ post("identity/match", params)
394
+ end
414
395
 
415
- def get_one(endpoint, id, params = {})
416
- response = current_scope.get("#{endpoint}/#{id}", headers: headers,
417
- body: params.to_json) do |request|
418
- request.headers['Content-Type'] = 'application/json'
396
+ # Invokes the the general request method for submitting API request.
397
+ #
398
+ # +endpoint+ the API request path
399
+ # +method+ the http request method that should be used
400
+ # +file+ file when the API accepts file uploads as input
401
+ # +params+ an optional Hash of parameters
402
+ #
403
+ # NOTE: There might be a better way of achieving the seperation of get/get_request
404
+ # but currently using the "send" method will go down the ancestor chain until the correct
405
+ # method is found. In this case the 'httpMethod'_request
406
+ def request(endpoint, method='get', file=nil, params={})
407
+ method = method.downcase
408
+ if file
409
+ self.send('post_file', endpoint, file, params)
410
+ else
411
+ # Work around to delete the leading slash on the request endpoint
412
+ # Currently the module we're using appends a slash to the base url
413
+ # so an additional url will break the request.
414
+ # Refer to ...faraday/connection.rb L#404
415
+ if endpoint[0] == '/'
416
+ endpoint[0] = ''
419
417
  end
418
+ self.send("#{method}_request", endpoint, params)
419
+ end
420
+ end
421
+
422
+ private
423
+ def get(endpoint, params = {})
424
+ response = request(endpoint, 'GET', nil, params)
420
425
 
421
426
  JSON.parse(response.body)
422
427
  end
423
428
 
424
429
  def post(endpoint, params = {})
425
- response = current_scope.post(endpoint, headers: headers,
426
- body: params.to_json) do |request|
427
- request.headers['Content-Type'] = 'application/json'
428
- end
430
+ response = request(endpoint, 'POST', nil, params)
429
431
 
430
432
  JSON.parse(response.body)
431
433
  end
432
434
 
433
- def put_one(endpoint, id, params = {})
434
- response = current_scope.put("#{endpoint}/#{id}", headers: headers,
435
- body: params.to_json) do |request|
436
- request.headers['Content-Type'] = 'application/json'
437
- end
435
+ def put(endpoint, params = {})
436
+ response = request(endpoint, 'PUT', nil, params)
438
437
 
439
438
  JSON.parse(response.body)
440
439
  end
441
440
 
442
- def delete_one(endpoint, id, params = {})
443
- response = current_scope.delete("#{endpoint}/#{id}", headers: headers,
444
- body: params.to_json) do |request|
445
- request.headers['Content-Type'] = 'application/json'
446
- end
441
+ def delete(endpoint, params = {})
442
+ response = request(endpoint, 'DELETE', nil, params)
447
443
 
448
444
  if response.body.empty?
449
445
  response.status == 204
@@ -451,38 +447,5 @@ module PokitDok
451
447
  JSON.parse(response.body)
452
448
  end
453
449
  end
454
-
455
- # Refreshes the client token associated with this PokitDok connection
456
- #
457
- # FIXME: automatic refresh on expiration
458
- #
459
- def refresh_token(code=nil)
460
- body = {}
461
- body[:code] = code unless code.nil?
462
-
463
- @client.client_credentials.get_token(
464
- headers: { 'Authorization' => 'Basic' })
465
- end
466
-
467
- def scope(name)
468
- raise ArgumentError, "You need to provide an authorization code for " \
469
- "the scope #{name} with the scope_code method" if @scopes[name].nil?
470
-
471
- @current_scope = name
472
-
473
- if @scopes[name][:scope].nil?
474
- @scopes[name][:scope] = refresh_token(@scopes[name][:code])
475
- end
476
-
477
- @scopes[name][:scope]
478
- end
479
-
480
- def current_scope
481
- @scopes[@current_scope][:scope]
482
- end
483
-
484
- def default_scope
485
- @scopes['default'][:scope]
486
- end
487
450
  end
488
451
  end