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 +4 -4
- data/CHANGELOG.md +11 -1
- data/README.md +5 -5
- data/lib/updox.rb +3 -0
- data/lib/updox/connection.rb +5 -3
- data/lib/updox/error_message.rb +60 -0
- data/lib/updox/models/appointment.rb +5 -2
- data/lib/updox/models/appointment_status.rb +2 -0
- data/lib/updox/models/calendar.rb +2 -0
- data/lib/updox/models/extensions/exists.rb +17 -0
- data/lib/updox/models/extensions/sync.rb +32 -0
- data/lib/updox/models/location.rb +3 -0
- data/lib/updox/models/model.rb +6 -41
- data/lib/updox/models/patient.rb +3 -1
- data/lib/updox/models/patient_message.rb +15 -0
- data/lib/updox/models/practice.rb +8 -2
- data/lib/updox/models/reminder.rb +1 -1
- data/lib/updox/models/user.rb +9 -1
- data/lib/updox/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1f62aa99da193e378457e56e3a055b4d52973c4cae2bb4944f2e300e51287064
|
4
|
+
data.tar.gz: e399c7debeefac7f7608579f056db93cdf3ea24ace47e4173c96adb0d176f87f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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
|
-
|
150
|
-
|
151
|
-
|
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 =
|
162
|
+
c.api_endpoint = Updox::Connection::PROD_ENDPOINT # Defaults to Updox QA endpoint
|
163
163
|
c.parse_responses = false # Defaults to true
|
164
|
-
c.
|
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'
|
data/lib/updox/connection.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
module Updox
|
2
2
|
class Connection
|
3
|
-
|
4
|
-
|
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
|
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,
|
18
|
-
property :cancelled, required: true,
|
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
|
@@ -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
|
data/lib/updox/models/model.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
module Updox
|
2
2
|
module Models
|
3
3
|
DATETIME_FORMAT = '%Y-%m-%d %H:%M'.freeze
|
4
|
-
|
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
|
-
|
92
|
-
|
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
|
59
|
+
if status_key.nil? || false == Module.const_defined?(status_class)
|
95
60
|
model.items = [data]
|
96
61
|
else
|
97
|
-
statuses = data.delete(
|
62
|
+
statuses = data.delete(status_key)
|
98
63
|
|
99
|
-
model.items = statuses.map {|status| Object.const_get(
|
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
|
|
data/lib/updox/models/patient.rb
CHANGED
@@ -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
|
-
|
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).
|
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,
|
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
|
data/lib/updox/models/user.rb
CHANGED
@@ -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
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.
|
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-
|
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
|