updox 0.12.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
  SHA256:
3
- metadata.gz: fd8b2034246435b98b4d29ec70697b0d89d8d2ff6ec802cea01eb8ae70084eed
4
- data.tar.gz: 07ce5cb4a144d0c244b975105795e561e0006e2ec9e355b563cd680355302a4f
3
+ metadata.gz: 1f62aa99da193e378457e56e3a055b4d52973c4cae2bb4944f2e300e51287064
4
+ data.tar.gz: e399c7debeefac7f7608579f056db93cdf3ea24ace47e4173c96adb0d176f87f
5
5
  SHA512:
6
- metadata.gz: da03e1b1cf8aa70cb65e1e91b0147b2680f7e5307695c9ad071dd0f08d546ba122b43c3c5576b40d7699196d2121d0cffa9365822bca4c0b5a77b2def5f4c567
7
- data.tar.gz: 9afd1c083421450366536f88212a27ae2142dafff9c9f5928b9976a2faa3c2896ac7ede4cf18bdc16bc49001804f0ba415f23191d8960f427b3697553a7e805d
6
+ metadata.gz: 3654a26917f7d18de3661921fe72253fbdbc9b7d518f6a9465cde9ee84d5ef65b0ad62e480213618ad676cdf6b74ff6b510bad05e917603c5c2956b69d9c8318
7
+ data.tar.gz: 82f90067272574222de2a8009b49c0109696a626aea6800c0b415e842a17026b1efa75c8f65cddc5e7493d4616163cee0e4df9e12f44a60514488c7eadc4a611
data/CHANGELOG.md CHANGED
@@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [1.0.0] - [UNRELEASED]
8
+ ### Added
9
+ - Aliases canceled to cancelled
10
+ - Patient#exists?
11
+
12
+ ### Fixed
13
+ - `failure_action = :raise` works better
14
+ - README fix for `failure_action` method
15
+
7
16
  ## [0.12.0] - [2020-02-21]
8
17
  ### Added
9
18
  - Configuration to `raise` on non-success response
@@ -89,7 +98,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
89
98
  ### Added
90
99
  - Initial Release with ability to ping Updox api
91
100
 
92
- [0.12.0]: https://github.com/WeInfuse/updox/compare/v0.11.0...HEAD
101
+ [1.0.0]: https://github.com/WeInfuse/updox/compare/v0.12.0...HEAD
102
+ [0.12.0]: https://github.com/WeInfuse/updox/compare/v0.11.0...v0.12.0
93
103
  [0.11.0]: https://github.com/WeInfuse/updox/compare/v0.10.0...v0.11.0
94
104
  [0.10.0]: https://github.com/WeInfuse/updox/compare/v0.9.0...v0.10.0
95
105
  [0.9.0]: https://github.com/WeInfuse/updox/compare/v0.8.0...v0.9.0
data/README.md CHANGED
@@ -146,9 +146,9 @@ response.practices # Has the practices as Updox::Models::Practice model
146
146
  response.items # Same as practices, always exists on any model if alias is broken
147
147
  response.item # If there is no array, we populate this object
148
148
 
149
- resposne.successful? # Indicates Updox successful indication
150
- resposne.response_code? # Indicates Updox response code
151
- resposne.response_message? # Indicates Updox response message
149
+ response.successful? # Indicates Updox successful indication
150
+ response.response_code? # Indicates Updox response code
151
+ response.response_message? # Indicates Updox response message
152
152
 
153
153
  response.response # Raw HTTParty response is here
154
154
  ```
@@ -159,9 +159,9 @@ response.response # Raw HTTParty response is here
159
159
  Updox.configure do |c|
160
160
  c.application_id = ENV['UPDOX_APP_ID']
161
161
  c.application_password = ENV['UPDOX_APP_PASS']
162
- c.api_endpoint = 'http://hello.com' # Defaults to Updox endpoint
162
+ c.api_endpoint = Updox::Connection::PROD_ENDPOINT # Defaults to Updox QA endpoint
163
163
  c.parse_responses = false # Defaults to true
164
- c.failure_response = :raise # Defaults to do nothing and allows lambdas
164
+ c.failure_action = :raise # Defaults to do nothing and allows lambdas
165
165
  end
166
166
  ```
167
167
 
data/lib/updox.rb CHANGED
@@ -4,6 +4,8 @@ require 'updox/version'
4
4
  require 'updox/updox_exception'
5
5
  require 'updox/connection'
6
6
  require 'updox/models/model'
7
+ require 'updox/models/extensions/exists'
8
+ require 'updox/models/extensions/sync'
7
9
  require 'updox/models/auth'
8
10
  require 'updox/models/application'
9
11
  require 'updox/models/appointment'
@@ -11,6 +13,7 @@ require 'updox/models/appointment_status'
11
13
  require 'updox/models/calendar'
12
14
  require 'updox/models/location'
13
15
  require 'updox/models/patient'
16
+ require 'updox/models/patient_message'
14
17
  require 'updox/models/practice'
15
18
  require 'updox/models/reminder'
16
19
  require 'updox/models/status'
@@ -1,11 +1,13 @@
1
1
  module Updox
2
2
  class Connection
3
- TEST_HOST = 'updoxqa.com'
4
- PROD_HOST = 'xxxxxxx.com'
3
+ URI_BUILDER = ->(host) { "https://#{host}/api/io/".freeze }
4
+
5
+ QA_ENDPOINT = URI_BUILDER.call('updoxqa.com')
6
+ PROD_ENDPOINT = URI_BUILDER.call('myupdox.com')
5
7
 
6
8
  include HTTParty
7
9
 
8
- base_uri "https://#{TEST_HOST}/api/io/".freeze
10
+ base_uri QA_ENDPOINT
9
11
 
10
12
  headers 'Content-Type' => 'application/json'
11
13
 
@@ -0,0 +1,60 @@
1
+ module Updox
2
+ ERROR_CODES = {
3
+ "2000"=>"OK",
4
+ "4000"=>"Bad Request",
5
+ "4010"=>"Unauthorized",
6
+ "4011"=>"Unauthorized [Practice does not exist or is inactive]",
7
+ "4012"=>"Unauthorized [User does not exist or is inactive]",
8
+ "4060"=>"A validation error in the request. For example not including a required field, an invalid e-mail address, too long of a value, etc. A list of the errors is included in the message.",
9
+ "5000"=>"an unknown error has occurred",
10
+ "5100"=>"an unknown server error has occurred",
11
+ "5110"=>"an unknown server error has occurred",
12
+ "4130"=>"account already exists",
13
+ "4110"=>"no practice ID",
14
+ "4160"=>"direct domain is invalid",
15
+ "4621"=>"direct address error: domain does not match the direct domain for this vendor",
16
+ "4150"=>"direct domain is already taken",
17
+ "4163"=>"direct domain is unavailable",
18
+ "4610"=>"direct address error: direct address is taken",
19
+ "4161"=>"web address is invalid",
20
+ "4131"=>"account does not exist",
21
+ "4140"=>"web address is already taken",
22
+ "4230"=>"user already exists",
23
+ "4210"=>"no user ID",
24
+ "4241"=>"invalid user ID, user IDs starting with '@' are reserved for practice users",
25
+ "4251"=>"invalid NPI",
26
+ "4252"=>"invalid taxonomy code",
27
+ "4630"=>"direct address error: account does not have a direct domain configured",
28
+ "4232"=>"user password is required",
29
+ "4240"=>"user does not exist, use practice methods instead",
30
+ "4231"=>"user does not exist",
31
+ "4641"=>"direct address error: sending user does not have a direct address configured",
32
+ "4642"=>"direct address error: identity verification required to send to this address",
33
+ "4640"=>"direct address error: invalid direct address",
34
+ "4650"=>"direct error: send failed",
35
+ "4651"=>"direct error: send failed and/or invalid direct address",
36
+ "4430"=>"message type does not have any MDNs",
37
+ "4410"=>"message not found",
38
+ "4652"=>"direct error: either from or patientDemographics is required",
39
+ "4071"=>"Recipient not found",
40
+ "4070"=>"Invalid recipient",
41
+ "4831"=>"portal account does not exist",
42
+ "4830"=>"portal account already exists",
43
+ "4832"=>"patient has opted out of portal communications",
44
+ "4731"=>"patient account does not exist",
45
+ "4960"=>"image not found",
46
+ "4331"=>"contact does not exist",
47
+ "4931"=>"you sent zero bulk faxes with this bulkFaxId",
48
+ "4021"=>"Invalid date format",
49
+ "4930"=>"no fax found for this ID",
50
+ "4932"=>"fax number does not appear to be available",
51
+ "4933"=>"invalid fax number",
52
+ "4330"=>"contact already exists",
53
+ "6212"=>"at least one id must be specified for the request",
54
+ "4162"=>"ip is invalid",
55
+ "4165"=>"port is invalid",
56
+ "6210"=>"at least one value must be provided",
57
+ "6213"=>"record does not exist for ID",
58
+ "9010"=>"the date format must be in the format is yyyy-MM-dd"
59
+ }
60
+ end
@@ -1,6 +1,8 @@
1
1
  module Updox
2
2
  module Models
3
3
  class Appointment < Model
4
+ extend Updox::Models::Extensions::Sync
5
+
4
6
  SYNC_ENDPOINT = '/AppointmentsSync'.freeze
5
7
 
6
8
  SYNC_LIST_TYPE = 'appointments'.freeze
@@ -14,8 +16,8 @@ module Updox
14
16
  property :typeId, from: :type_id
15
17
  property :summary
16
18
  property :details
17
- property :blocked, required: true, transform_with: ->(v) { true == v }, default: false
18
- property :cancelled, required: true, transform_with: ->(v) { true == v }, default: false
19
+ property :blocked, required: true, default: false
20
+ property :cancelled, required: true, from: :canceled, default: false
19
21
  property :locationId, from: :location_id
20
22
  property :reminderTokens, from: :reminder_tokens
21
23
 
@@ -25,6 +27,7 @@ module Updox
25
27
  alias_method :type_id, :typeId
26
28
  alias_method :location_id, :locationId
27
29
  alias_method :reminder_tokens, :reminderTokens
30
+ alias_method :canceled, :cancelled
28
31
 
29
32
  def to_h
30
33
  result = super.to_h
@@ -1,6 +1,8 @@
1
1
  module Updox
2
2
  module Models
3
3
  class AppointmentStatus < Model
4
+ extend Updox::Models::Extensions::Exists
5
+
4
6
  LIST_ENDPOINT = '/AppointmentStatusesGetByIds'.freeze
5
7
 
6
8
  LIST_TYPE = 'appointmentStatuses'
@@ -1,6 +1,8 @@
1
1
  module Updox
2
2
  module Models
3
3
  class Calendar < Model
4
+ extend Updox::Models::Extensions::Exists
5
+
4
6
  SYNC_ENDPOINT = '/CalendarsSync'.freeze
5
7
  LIST_ENDPOINT = '/PracticeCalendarsRetrieve'.freeze
6
8
 
@@ -0,0 +1,17 @@
1
+ module Updox
2
+ module Models
3
+ module Extensions
4
+ module Exists
5
+ def exists?(item_id, account_id: , cached_query: nil)
6
+ raise UpdoxException.new('Not implemented on this model.') unless self.respond_to?(:find)
7
+ opts = { account_id: account_id }
8
+ opts[:cached_query] = cached_query unless cached_query.nil?
9
+
10
+ response = self.find(item_id, **opts)
11
+
12
+ false == response.nil?
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,32 @@
1
+ module Updox
2
+ module Models
3
+ module Extensions
4
+ module Sync
5
+ RECOMMENDED_BATCH_SIZE = 200
6
+
7
+ def sync(items, account_id: , batch_size: RECOMMENDED_BATCH_SIZE, endpoint: self.const_get(:SYNC_ENDPOINT))
8
+ response = nil
9
+ list_type = self.const_get(:SYNC_LIST_TYPE)
10
+
11
+ if 0 >= batch_size
12
+ response = request(endpoint: endpoint, body: { list_type => items }, auth: {accountId: account_id}, required_auths: Updox::Models::Auth::AUTH_ACCT)
13
+ else
14
+ items.each_slice(batch_size) do |batch|
15
+ r = request(endpoint: endpoint, body: { list_type => batch }, auth: {accountId: account_id}, required_auths: Updox::Models::Auth::AUTH_ACCT)
16
+
17
+ return r unless r.successful?
18
+
19
+ if response
20
+ response.items += r.items
21
+ else
22
+ response = r
23
+ end
24
+ end
25
+ end
26
+
27
+ return response
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,6 +1,9 @@
1
1
  module Updox
2
2
  module Models
3
3
  class Location < Model
4
+ extend Updox::Models::Extensions::Exists
5
+ extend Updox::Models::Extensions::Sync
6
+
4
7
  SYNC_ENDPOINT = '/LocationsSync'.freeze
5
8
  LIST_ENDPOINT = '/PracticeLocationsRetrieve'.freeze
6
9
 
@@ -1,9 +1,7 @@
1
1
  module Updox
2
2
  module Models
3
3
  DATETIME_FORMAT = '%Y-%m-%d %H:%M'.freeze
4
- DATETIME_OTHER_FORMAT = '%m/%d/%Y %H:%M:%s %z'.freeze
5
-
6
- RECOMMENDED_BATCH_SIZE = 200
4
+ DATETIME_TZ_FORMAT = '%m/%d/%Y %H:%M:%s %z'.freeze
7
5
 
8
6
  class Model < Hashie::Trash
9
7
  include Hashie::Extensions::IgnoreUndeclared
@@ -33,39 +31,6 @@ module Updox
33
31
  "#{response_code}: #{response_message}"
34
32
  end
35
33
 
36
- def self.exists?(item_id, account_id: , cached_query: nil)
37
- raise UpdoxException.new('Not implemented on this model.') unless self.respond_to?(:find)
38
- opts = { account_id: account_id }
39
- opts[:cached_query] = cached_query unless cached_query.nil?
40
-
41
- response = self.find(item_id, **opts)
42
-
43
- false == response.nil? && (false == self.const_defined?(:FIND_ENDPOINT) || response.successful?)
44
- end
45
-
46
- def self.sync(items, account_id: , batch_size: RECOMMENDED_BATCH_SIZE, endpoint: self.const_get(:SYNC_ENDPOINT))
47
- response = nil
48
- list_type = self.const_get(:SYNC_LIST_TYPE)
49
-
50
- if 0 >= batch_size
51
- response = request(endpoint: endpoint, body: { list_type => items }, auth: {accountId: account_id}, required_auths: Updox::Models::Auth::AUTH_ACCT)
52
- else
53
- items.each_slice(batch_size) do |batch|
54
- r = request(endpoint: endpoint, body: { list_type => batch }, auth: {accountId: account_id}, required_auths: Updox::Models::Auth::AUTH_ACCT)
55
-
56
- return r unless r.successful?
57
-
58
- if response
59
- response.items += r.items
60
- else
61
- response = r
62
- end
63
- end
64
- end
65
-
66
- return response
67
- end
68
-
69
34
  def self.request(**kwargs)
70
35
  from_response(UpdoxClient.connection.request(kwargs))
71
36
  end
@@ -88,15 +53,15 @@ module Updox
88
53
  model.item = klazz.new(data.dig(klazz.const_get(:ITEM_TYPE)))
89
54
  model.define_singleton_method(klazz.const_get(:ITEM_TYPE)) { self.item }
90
55
  else
91
- k = data&.keys&.find {|k| k.to_s.downcase.end_with?('statuses') }
92
- c = 'Updox::Models::' + k[0..-3].capitalize if k
56
+ status_key = data&.keys&.find {|k| k.to_s.downcase.end_with?('statuses') }
57
+ status_class = 'Updox::Models::' + status_key[0..-3].capitalize if status_key
93
58
 
94
- if k.nil? || false == Module.const_defined?(c)
59
+ if status_key.nil? || false == Module.const_defined?(status_class)
95
60
  model.items = [data]
96
61
  else
97
- statuses = data.delete(k)
62
+ statuses = data.delete(status_key)
98
63
 
99
- model.items = statuses.map {|status| Object.const_get(c).new(status) }
64
+ model.items = statuses.map {|status| Object.const_get(status_class).new(status) }
100
65
  model.define_singleton_method(:statuses) { self.items }
101
66
  end
102
67
 
@@ -1,6 +1,8 @@
1
1
  module Updox
2
2
  module Models
3
3
  class Patient < Model
4
+ extend Updox::Models::Extensions::Sync
5
+
4
6
  SYNC_ENDPOINT = '/PatientsSync'.freeze
5
7
  SYNC_LIST_TYPE = 'patients'.freeze
6
8
 
@@ -33,7 +35,7 @@ module Updox
33
35
  end
34
36
 
35
37
  def self.exists?(patient_id, account_id: )
36
- request(endpoint: MESSAGE_COUNT_ENDPOINT, body: { patientId: patient_id }, auth: {accountId: account_id}, required_auths: Updox::Models::Auth::AUTH_ACCT).successful?
38
+ Updox::Models::PatientMessage.exists?(patient_id, account_id: account_id)
37
39
  end
38
40
  end
39
41
  end
@@ -0,0 +1,15 @@
1
+ module Updox
2
+ module Models
3
+ class PatientMessage < Model
4
+ LIST_ENDPOINT = '/PatientMessageCountSince'.freeze
5
+
6
+ def self.query(patient_id, account_id: )
7
+ request(endpoint: LIST_ENDPOINT, body: { patientId: patient_id }, auth: {accountId: account_id}, required_auths: Updox::Models::Auth::AUTH_ACCT)
8
+ end
9
+
10
+ def self.exists?(patient_id, account_id: )
11
+ request(endpoint: LIST_ENDPOINT, body: { patientId: patient_id }, auth: {accountId: account_id}, required_auths: Updox::Models::Auth::AUTH_ACCT).successful?
12
+ end
13
+ end
14
+ end
15
+ end
@@ -40,11 +40,17 @@ module Updox
40
40
  end
41
41
 
42
42
  def self.exists?(account_id)
43
- self.find(account_id).successful?
43
+ false == self.find(account_id).nil?
44
44
  end
45
45
 
46
46
  def self.find(account_id)
47
- request(endpoint: FIND_ENDPOINT, body: {accountId: account_id}, required_auths: Updox::Models::Auth::AUTH_APP)
47
+ response = request(endpoint: FIND_ENDPOINT, body: {accountId: account_id}, required_auths: Updox::Models::Auth::AUTH_APP)
48
+
49
+ if response.successful?
50
+ response
51
+ else
52
+ nil
53
+ end
48
54
  end
49
55
 
50
56
  def self.query
@@ -3,7 +3,7 @@ module Updox
3
3
  class Reminder < Model
4
4
  property :reminderId
5
5
  property :reminderStatus
6
- property :reminderStatusDate, transform_with: ->(v) { DateTime.strptime(v, DATETIME_OTHER_FORMAT) unless v.nil? || v.empty? }
6
+ property :reminderStatusDate, transform_with: ->(v) { DateTime.strptime(v, DATETIME_TZ_FORMAT) unless v.nil? || v.empty? }
7
7
  property :reminderType
8
8
 
9
9
  alias_method :reminder_id, :reminderId
@@ -1,6 +1,8 @@
1
1
  module Updox
2
2
  module Models
3
3
  class User < Model
4
+ extend Updox::Models::Extensions::Exists
5
+
4
6
  SAVE_ENDPOINT = '/UserSave'.freeze
5
7
  QUERY_ENDPOINT = '/UserList'.freeze
6
8
  FIND_ENDPOINT = '/UserGet'.freeze
@@ -45,7 +47,13 @@ module Updox
45
47
  end
46
48
 
47
49
  def self.find(user_id, account_id: )
48
- request(endpoint: FIND_ENDPOINT, account_id: account_id, body: { userId: user_id}, required_auths: Updox::Models::Auth::AUTH_ACCT)
50
+ response = request(endpoint: FIND_ENDPOINT, account_id: account_id, body: { userId: user_id}, required_auths: Updox::Models::Auth::AUTH_ACCT)
51
+
52
+ if response.successful?
53
+ response
54
+ else
55
+ nil
56
+ end
49
57
  end
50
58
 
51
59
  def self.query
data/lib/updox/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Updox
2
- VERSION = '0.12.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: updox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Crockett
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-02-21 00:00:00.000000000 Z
11
+ date: 2020-02-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -142,14 +142,18 @@ files:
142
142
  - Rakefile
143
143
  - lib/updox.rb
144
144
  - lib/updox/connection.rb
145
+ - lib/updox/error_message.rb
145
146
  - lib/updox/models/application.rb
146
147
  - lib/updox/models/appointment.rb
147
148
  - lib/updox/models/appointment_status.rb
148
149
  - lib/updox/models/auth.rb
149
150
  - lib/updox/models/calendar.rb
151
+ - lib/updox/models/extensions/exists.rb
152
+ - lib/updox/models/extensions/sync.rb
150
153
  - lib/updox/models/location.rb
151
154
  - lib/updox/models/model.rb
152
155
  - lib/updox/models/patient.rb
156
+ - lib/updox/models/patient_message.rb
153
157
  - lib/updox/models/practice.rb
154
158
  - lib/updox/models/reminder.rb
155
159
  - lib/updox/models/status.rb