updox 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7eeab31e87fabd58b70a27bcf1a2012ba06ac93421d23861cc246d12bcf3614f
4
- data.tar.gz: c4969565b9a34f4f87afacf4bd1e26165e04e17bc931457dfebc9108acb037b7
3
+ metadata.gz: 0bbcd6275257fa4aec9f5d2ee479d2e40cc35c6c1554b0d6daa32edf9dec4cd5
4
+ data.tar.gz: e3358374b773851ce3958441b264a7983f7944ebfc93dfeb9b8e2a6036a6457a
5
5
  SHA512:
6
- metadata.gz: a32b3b74cc2f7afd897418274d8a041a02602c0fabf783ea2a6bcf172750cdbaa2af5873a8a7ac48e0e4ec047a5bcc26a50a8db8a759ceb662587cea54a19fd1
7
- data.tar.gz: 451421900c7777190b72db3c95a8124a3294c0b0c945ac28cb08b263015b7222c5d276252e80c9cbbab637c13273fa909aa91bbb6bee69ffa6297a0f546cca93
6
+ metadata.gz: e848a98e0ecefbd2578478a1ce22b69b5c41c1e3f4e56aecf4a7a864aec2cb4f42c6ae133a3649603c62b2b4a4b7793b4facf07a4a9d6e27ffa6185c4211a2b5
7
+ data.tar.gz: 2cbe79662dfe9ee1e237b29bd37c2f848bb828eb6336a5a03249460ce96642bbf952892bd013f4db2a7ed99a82be3463eeac6242f70ecb5a5a27537d59fdc285
data/CHANGELOG.md CHANGED
@@ -4,13 +4,23 @@ 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
- ## [0.1.x] - UNRELEASED
7
+ ## [0.3.0] - UNRELEASED
8
8
  ### Changed
9
9
  - None
10
10
 
11
- ## 0.1.0 - 2020-01-20
11
+ ## 0.2.0 - 2020-02-06
12
12
  ### Added
13
- - Initial Release
13
+ - Calendar
14
+ - Patient
15
+ - Location
16
+ - User
17
+ - Appointment
18
+ - Application
14
19
 
15
- [Unreleased]: https://github.com/WeInfuse/redox/compare/v1.0.2...HEAD
16
- [0.1.1]: https://github.com/WeInfuse/redox/compare/0.1.0...0.1.1
20
+ ## 0.1.0 - 2020-01-21
21
+ ### Added
22
+ - Initial Release with ability to ping Updox api
23
+
24
+ [Unreleased]: https://github.com/WeInfuse/updox/compare/v0.2.0...HEAD
25
+ [0.2.0]: https://github.com/WeInfuse/updox/compare/v0.1.0...v0.2.0
26
+ [0.1.0]: https://github.com/WeInfuse/updox/compare/v0.1.0
data/README.md CHANGED
@@ -26,74 +26,87 @@ Or install it yourself as:
26
26
  Make sure you're [configured](#configuration)!
27
27
 
28
28
  ```ruby
29
- patient = Updox::Models::Patient.new
30
- patient.demographics.first_name = 'Joe'
31
- patient.demographics['LastName'] = 'Joerson'
32
- patient.add_identifier(type: 'TheType', value: 'x13005')
33
-
34
- meta = Updox::Models::Meta.new
35
- meta.set_source(name: 'MySource', id: '123-584')
36
- meta.add_destination(name: 'TheDest', id: '973-238')
29
+ auth = Updox::Models::Auth.new
30
+
31
+ response = auth.ping # No authentication needed!
32
+
33
+ response = auth.ping_with_application_auth # Check if you're app auth is working!
37
34
  ```
38
35
 
39
- ### Create
36
+ ### Practice
37
+ The practice is what Updox calls 'Account' access so anywhere the `account_id` is required is relating back to this practice instance.
38
+
39
+ #### Create
40
+ ```ruby
41
+ practice = Updox::Models::Practice.new(name: 'LOL LTD', account_id: '0001', active: true)
42
+ practice.create
43
+ ```
40
44
 
45
+ #### List
41
46
  ```ruby
42
- response = patient.create(meta: meta)
47
+ practices = Updox::Models::Practice.query.practices
43
48
  ```
44
49
 
45
- ### Update
50
+ ### Location
51
+
52
+ #### Create
46
53
 
47
54
  ```ruby
48
- response = patient.update(meta: meta)
55
+ location = Updox::Models::Location.new(active: true, name: 'My Location', code: 'ML01', id: '27')
56
+ location.save(account_id: practice.account_id)
57
+
58
+ # Bulk
59
+ Location.sync([l0, l1], account_id: practice.account_id)
49
60
  ```
50
61
 
51
- ### Search
62
+ ### Calendar
63
+
64
+ #### Create
52
65
 
53
66
  ```ruby
54
- response = Updox::Models::Patient.query(patient, meta: meta)
67
+ calendar = Updox::Models::Calendar.new(active: true, title: 'My Calendar', id: 'C1')
68
+ calendar.create(account_id: practice.account_id)
55
69
  ```
56
70
 
57
- ### Response
71
+ ### Patient
72
+
73
+ #### Create
58
74
 
59
- The response object is a base `Updox::Models::Model` class.
75
+ ```ruby
76
+ patient = Updox::Models::Patient.new(id: 'X0001', internal_id: 'X0001', first_name: 'Brian', last_name: 'Brianson', mobile_number: 5126914360, active: true)
77
+ patient.save(account_id: practice.account_id)
78
+
79
+ # Bulk
80
+ Patient.sync([p0, p1, p2], account_id: practice.account_id)
81
+ ```
82
+
83
+ ### Appointment
84
+
85
+ #### Create
60
86
 
61
- With the HTTParty response object
62
87
  ```ruby
63
- response.response
64
- #<HTTParty::Response:0x7fa354c1fbe8>
88
+ appointment = Updox::Models::Appointment.new(id: 'A0001', calendar_id: calendar.id, date: Time.now + 20, duration: 60, location_id: location.id, patient_id: patient.id)
89
+ appointment.save(account_id: practice.account_id)
65
90
 
66
- response.response.ok?
67
- true
91
+ # Bulk
92
+ Appointment.sync([appt0, appt1, appt2], account_id: practice.account_id)
68
93
  ```
69
94
 
70
- And any `Model` objects that were returned
95
+ ### Response
96
+ By default we return `Updox::Models::Model.from_response`
97
+
98
+ This class throws if throw an exception on bad responses with a parsed error.
99
+
100
+ If successful it adds helper methods and converts each to the respective class.
101
+
102
+ The raw response is stored in the resulting model but you can get the raw response by setting config option to false
103
+
71
104
  ```ruby
72
- response.patient
73
- {
74
- "Identifiers"=> [
75
- {"IDType"=>"MR", "ID"=>"0000000003"},
76
- {"ID"=>"e3fedf48-c8bf-4728-845f-cb810001b571", "IDType"=>"EHRID"}
77
- ],
78
- "Demographics"=> {
79
- "Race"=>"Black",
80
- "SSN"=>"303-03-0003",
81
- "Nickname"=>"Walt"
82
- ...
83
- }
84
- "PCP"=> {
85
- "NPI"=>nil,
86
- }
87
- }
88
-
89
- response.meta
90
- {
91
- "EventDateTime"=>"2019-04-26T20:03:00.304866Z",
92
- "DataModel"=>"PatientAdmin",
93
- ...
94
- "Transmission"=>{"ID"=>797225234},
95
- "Message"=>{"ID"=>1095117817}
96
- }
105
+ response = Updox::Models::Practice.query
106
+ response.practices # Has the practices as Updox::Models::Practice model
107
+ response.items # Same as practices, always exists on any model if alias is broken
108
+ response.item # If there is no array, we populate this object
109
+ response.response # Raw HTTParty response is here
97
110
  ```
98
111
 
99
112
  ### Configuration
@@ -103,6 +116,7 @@ Updox.configure do |c|
103
116
  c.application_id = ENV['UPDOX_APP_ID']
104
117
  c.application_password = ENV['UPDOX_APP_PASS']
105
118
  c.api_endpoint = 'http://hello.com' # Defaults to Updox endpoint
119
+ c.parse_responses = false # Defaults to true
106
120
  end
107
121
  ```
108
122
 
data/lib/updox.rb CHANGED
@@ -3,16 +3,26 @@ require 'hashie'
3
3
  require 'updox/version'
4
4
  require 'updox/updox_exception'
5
5
  require 'updox/connection'
6
+ require 'updox/models/model'
6
7
  require 'updox/models/auth'
8
+ require 'updox/models/application'
9
+ require 'updox/models/appointment'
10
+ require 'updox/models/calendar'
11
+ require 'updox/models/location'
12
+ require 'updox/models/patient'
7
13
  require 'updox/models/practice'
14
+ require 'updox/models/user'
8
15
 
9
16
  module Updox
10
17
  class Configuration
11
- attr_accessor :application_id, :application_password
18
+ attr_accessor :application_id, :application_password, :parse_responses
19
+
20
+ alias_method :parse_responses?, :parse_responses
12
21
 
13
22
  def initialize
14
23
  @application_id = nil
15
24
  @application_password = nil
25
+ @parse_responses = true
16
26
  end
17
27
 
18
28
  def api_endpoint=(endpoint)
@@ -27,7 +37,8 @@ module Updox
27
37
  return {
28
38
  application_id: @application_id,
29
39
  application_password: @application_password,
30
- api_endpoint: api_endpoint
40
+ api_endpoint: api_endpoint,
41
+ parse_responses: @parse_responses
31
42
  }
32
43
  end
33
44
 
@@ -35,6 +46,7 @@ module Updox
35
46
  self.application_id = h[:application_id]
36
47
  self.application_password = h[:application_password]
37
48
  self.api_endpoint = h[:api_endpoint]
49
+ self.parse_responses = h[:parse_responses]
38
50
 
39
51
  return self
40
52
  end
@@ -0,0 +1,23 @@
1
+ module Updox
2
+ module Models
3
+ class Application < Model
4
+ OPEN_ENDPOINT = '/ApplicationOpen'.freeze
5
+
6
+ property :ipAddress
7
+ property :timeout
8
+ property :metadata
9
+
10
+ def url(account_id: , user_id: , base_uri: nil)
11
+ response = self.open(account_id: account_id, user_id: user_id)
12
+
13
+ base_uri ||= Updox.configuration.api_endpoint.split(URI.parse(Updox.configuration.api_endpoint).path).first
14
+
15
+ "#{base_uri}/sso/applicationOpen/#{Updox.configuration.application_id}/#{response.item.dig('token')}"
16
+ end
17
+
18
+ def open(account_id: , user_id: )
19
+ Model.from_response(UpdoxClient.connection.request(endpoint: OPEN_ENDPOINT, auth: {accountId: account_id, userId: user_id}, required_auths: Updox::Models::Auth::AUTH_FULL))
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,37 @@
1
+ module Updox
2
+ module Models
3
+ class Appointment < Model
4
+ SYNC_ENDPOINT = '/AppointmentsSync'.freeze
5
+
6
+ property :id, required: true
7
+ property :updoxId, from: :updox_id
8
+ property :calendarId, required: true, from: :calendar_id
9
+ property :date, required: true
10
+ property :duration
11
+ property :patientId
12
+ property :typeId
13
+ property :summary
14
+ property :details
15
+ property :blocked, required: true, transform_with: ->(v) { true == v }, default: false
16
+ property :cancelled, required: true, transform_with: ->(v) { true == v }, default: false
17
+ property :locationId, from: :location_id
18
+ property :reminderTokens, from: :reminder_tokens
19
+
20
+ def to_h
21
+ result = super.to_h
22
+
23
+ result['date'] = result['date'].strftime(Updox::Models::DATETIME_FORMAT) if result['date'].respond_to?(:strftime)
24
+
25
+ result
26
+ end
27
+
28
+ def save(account_id: )
29
+ self.class.sync([self], account_id: account_id)
30
+ end
31
+
32
+ def self.sync(appointments, account_id: )
33
+ from_response(UpdoxClient.connection.request(endpoint: SYNC_ENDPOINT, body: { appointments: appointments.map(&:to_h) }, auth: {accountId: account_id}, required_auths: Updox::Models::Auth::AUTH_ACCT), self)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -6,10 +6,10 @@ module Updox
6
6
  AUTH_ACCT = AUTH_APP + [:accountId]
7
7
  AUTH_FULL = AUTH_ACCT + [:userId]
8
8
 
9
- PING_ENDPOINT = '/ping'
10
- PING_APP_ENDPOINT = '/pingWithApplicationAuth'
11
- PING_ACCT_ENDPOINT = '/pingWithAccountAuth'
12
- PING_FULL_ENDPOINT = '/pingWithAuth'
9
+ PING_ENDPOINT = '/Ping'
10
+ PING_APP_ENDPOINT = PING_ENDPOINT + 'WithApplicationAuth'
11
+ PING_ACCT_ENDPOINT = PING_ENDPOINT + 'WithAccountAuth'
12
+ PING_FULL_ENDPOINT = PING_ENDPOINT + 'WithAuth'
13
13
 
14
14
  property :applicationId, from: :application_id
15
15
  property :applicationPassword, from: :application_password
@@ -0,0 +1,19 @@
1
+ module Updox
2
+ module Models
3
+ class Calendar < Model
4
+ SYNC_ENDPOINT = '/CalendarsSync'.freeze
5
+
6
+ property :id, required: true
7
+ property :title, required: true
8
+ property :color, required: true, default: '#000000'
9
+ property :textColor, required: true, default: '#FFFFFF'
10
+ property :publicCalendar, default: false, from: :public_calendar, with: ->(v) { true == v}, transform_with: ->(v) { true == v }
11
+ property :active, default: true
12
+ property :reminderTurnOff, default: false, from: :reminder_turn_off, with: ->(v) { true == v}, transform_with: ->(v) { true == v }
13
+
14
+ def create(account_id: )
15
+ self.class.from_response(UpdoxClient.connection.request(endpoint: SYNC_ENDPOINT, body: self.to_h, auth: {accountId: account_id}, required_auths: Updox::Models::Auth::AUTH_ACCT))
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,21 @@
1
+ module Updox
2
+ module Models
3
+ class Location < Model
4
+ SYNC_ENDPOINT = '/LocationsSync'.freeze
5
+
6
+ property :id
7
+ property :code
8
+ property :name
9
+ property :showInPortal, default: false, from: :show_in_portal, with: ->(v) { true == v }, transform_with: ->(v) { true == v }
10
+ property :active, default: true
11
+
12
+ def save(account_id: )
13
+ self.class.sync([self], account_id: account_id)
14
+ end
15
+
16
+ def self.sync(locations, account_id: )
17
+ from_response(UpdoxClient.connection.request(endpoint: SYNC_ENDPOINT, body: { locations: locations }, auth: {accountId: account_id}, required_auths: Updox::Models::Auth::AUTH_ACCT), self)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,41 @@
1
+ module Updox
2
+ module Models
3
+ DATETIME_FORMAT = '%Y-%m-%d %H:%M'.freeze
4
+
5
+ class Model < Hashie::Trash
6
+ include Hashie::Extensions::IgnoreUndeclared
7
+ include Hashie::Extensions::IndifferentAccess
8
+
9
+ LIST_TYPE = 'undefined'
10
+ LIST_NAME = 'models'
11
+
12
+ property :item, required: false
13
+ property :items, required: false
14
+
15
+ def self.from_response(response, klazz = self)
16
+ return response if false == Updox.configuration.parse_responses?
17
+
18
+ model = Model.new
19
+ model.define_singleton_method(:response) { response }
20
+
21
+ if (response.ok?)
22
+ data = response.parsed_response
23
+
24
+ if data.is_a?(Array)
25
+ model.items = data
26
+ elsif data&.include?(klazz.const_get(:LIST_TYPE))
27
+ model.items = data.dig(klazz.const_get(:LIST_TYPE)).map { |obj| klazz.new(obj) }
28
+ model.define_singleton_method(klazz.const_get(:LIST_NAME)) { self.items }
29
+ else
30
+ model.items = [data]
31
+ model.item = data
32
+ end
33
+ else
34
+ raise UpdoxException.from_response(response)
35
+ end
36
+
37
+ return model
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,26 @@
1
+ module Updox
2
+ module Models
3
+ class Patient < Model
4
+ SYNC_ENDPOINT = '/PatientsSync'.freeze
5
+
6
+ property :id
7
+ property :internalId, required: true, from: :internal_id
8
+ property :firstName, from: :first_name
9
+ property :middleName, from: :middle_name
10
+ property :lastName, from: :last_name
11
+ property :emailAddress, from: :email_address
12
+ property :homePhone, from: :home_phone
13
+ property :workPhone, from: :work_phone
14
+ property :mobileNumber, from: :mobile_number
15
+ property :active, default: true
16
+
17
+ def save(account_id: )
18
+ self.class.sync([self], account_id: account_id)
19
+ end
20
+
21
+ def self.sync(patients, account_id: )
22
+ from_response(UpdoxClient.connection.request(endpoint: SYNC_ENDPOINT, body: { patients: patients }, auth: {accountId: account_id}, required_auths: Updox::Models::Auth::AUTH_ACCT), self)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,12 +1,13 @@
1
1
  module Updox
2
2
  module Models
3
- class Practice < Hashie::Trash
4
- CREATE_ENDPOINT = '/practiceCreate'.freeze
3
+ class Practice < Model
4
+ CREATE_ENDPOINT = '/PracticeCreate'.freeze
5
+ QUERY_ENDPOINT = '/PracticeList'.freeze
5
6
 
6
- include Hashie::Extensions::IndifferentAccess
7
+ LIST_TYPE = 'practiceList'.freeze
8
+ LIST_NAME = 'practices'
7
9
 
8
10
  property :name, required: true
9
- property :active, default: false
10
11
  property :accountId, from: :account_id, with: ->(v) { v.to_s }
11
12
  property :address1
12
13
  property :address2
@@ -27,11 +28,16 @@ module Updox
27
28
  property :practiceSpecialtyCode, from: :practice_specialty_code
28
29
  property :practiceNpi, from: :practice_npi
29
30
  property :defaultConsentMethods
31
+ property :active, default: true
30
32
 
31
33
  alias_method :account_id, :accountId
32
34
 
33
35
  def create
34
- UpdoxClient.connection.request(endpoint: CREATE_ENDPOINT, body: self.to_h)
36
+ UpdoxClient.connection.request(endpoint: CREATE_ENDPOINT, body: self.to_h, required_auths: Updox::Models::Auth::AUTH_APP)
37
+ end
38
+
39
+ def self.query
40
+ from_response(UpdoxClient.connection.request(endpoint: QUERY_ENDPOINT, required_auths: Updox::Models::Auth::AUTH_APP), self)
35
41
  end
36
42
  end
37
43
  end
@@ -0,0 +1,39 @@
1
+ module Updox
2
+ module Models
3
+ class User < Model
4
+ SAVE_ENDPOINT = '/UserSave'.freeze
5
+ QUERY_ENDPOINT = '/UserList'.freeze
6
+
7
+ LIST_TYPE = 'userList'.freeze
8
+ LIST_NAME = 'users'
9
+
10
+ property :userId, from: :user_id
11
+ property :emrUserId, from: :emr_user_id
12
+ property :loginId, from: :login_id
13
+ property :loginPassword, from: :login_password
14
+ property :firstName, required: true, from: :first_name
15
+ property :middleName, from: :middle_name
16
+ property :lastName, required: true, from: :last_name
17
+ property :address1
18
+ property :address2
19
+ property :city
20
+ property :state
21
+ property :postal
22
+ property :provider, default: false
23
+ property :admin, default: false
24
+ property :searchOptOut, from: :search_opt_out, default: true
25
+
26
+ alias_method :user_id, :userId
27
+ alias_method :first_name, :firstName
28
+ alias_method :last_name, :lastName
29
+
30
+ def create
31
+ UpdoxClient.connection.request(endpoint: SAVE_ENDPOINT, body: self.to_h, required_auths: Updox::Models::Auth::AUTH_APP)
32
+ end
33
+
34
+ def self.query
35
+ from_response(UpdoxClient.connection.request(endpoint: QUERY_ENDPOINT, required_auths: Updox::Models::Auth::AUTH_APP), self)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -2,18 +2,24 @@ module Updox
2
2
  class UpdoxException < Exception
3
3
  def self.from_response(response, msg: nil)
4
4
  exception_msg = "Failed #{msg}:"
5
- exception_msg << " HTTP code: #{response.code} MSG: "
5
+ exception_msg << " HTTP code: #{response.code}"
6
6
 
7
7
  begin
8
8
  error_response = JSON.parse(response.body)
9
9
 
10
- #if (error_response.is_a?(Hash) && error_response.include?("Meta") && error_response["Meta"].include?("Errors"))
11
- #exception_msg << error_response["Meta"]["Errors"]
12
- #else
13
- exception_msg << error_response
14
- #end
10
+ if error_response.is_a?(Hash)
11
+ if error_response.include?('responseMessage')
12
+ exception_msg << " MSG: #{error_response['responseMessage']}"
13
+ end
14
+
15
+ if error_response.include?('responseCode')
16
+ exception_msg << " UPDOX CODE: #{error_response['responseCode']}"
17
+ end
18
+ else
19
+ exception_msg << " MSG: #{error_response}"
20
+ end
15
21
  rescue JSON::ParserError
16
- exception_msg << response.body
22
+ exception_msg << " MSG: #{response.body}"
17
23
  end
18
24
 
19
25
  return UpdoxException.new(exception_msg)
data/lib/updox/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Updox
2
- VERSION = '0.1.0'.freeze
2
+ VERSION = '0.2.0'.freeze
3
3
  end
data/updox.gemspec CHANGED
@@ -33,7 +33,7 @@ Gem::Specification.new do |spec|
33
33
  spec.add_development_dependency 'bundler', '>=1', '<3'
34
34
  spec.add_development_dependency 'byebug', '~> 11'
35
35
  spec.add_development_dependency 'minitest', '~> 5.0'
36
- spec.add_development_dependency 'rake', '~> 10.0'
36
+ spec.add_development_dependency 'rake', '~> 13.0'
37
37
  spec.add_development_dependency 'webmock', '~> 3.1'
38
38
  spec.add_development_dependency 'yard', '~> 0.9'
39
39
  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.1.0
4
+ version: 0.2.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-01-21 00:00:00.000000000 Z
11
+ date: 2020-02-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -92,14 +92,14 @@ dependencies:
92
92
  requirements:
93
93
  - - "~>"
94
94
  - !ruby/object:Gem::Version
95
- version: '10.0'
95
+ version: '13.0'
96
96
  type: :development
97
97
  prerelease: false
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - "~>"
101
101
  - !ruby/object:Gem::Version
102
- version: '10.0'
102
+ version: '13.0'
103
103
  - !ruby/object:Gem::Dependency
104
104
  name: webmock
105
105
  requirement: !ruby/object:Gem::Requirement
@@ -142,8 +142,15 @@ files:
142
142
  - Rakefile
143
143
  - lib/updox.rb
144
144
  - lib/updox/connection.rb
145
+ - lib/updox/models/application.rb
146
+ - lib/updox/models/appointment.rb
145
147
  - lib/updox/models/auth.rb
148
+ - lib/updox/models/calendar.rb
149
+ - lib/updox/models/location.rb
150
+ - lib/updox/models/model.rb
151
+ - lib/updox/models/patient.rb
146
152
  - lib/updox/models/practice.rb
153
+ - lib/updox/models/user.rb
147
154
  - lib/updox/updox_exception.rb
148
155
  - lib/updox/version.rb
149
156
  - updox.gemspec