redox 0.1.5 → 1.1.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: b6ab25d3f19478659e8b289237cfc384ac214d2ac2fe880a4e5ea324b16488e0
4
- data.tar.gz: 035f903ba8152429b06c1ab2e1a6a17bc7639974bd483440448a391bab7c7763
3
+ metadata.gz: 451221082b696c7421fa2feacde94c0235bbd78348c416d904cba8df3d1ff67b
4
+ data.tar.gz: 9934ade2a99d85628444a8845b15bf14c79cb595f1307da196d57d1faa2a2668
5
5
  SHA512:
6
- metadata.gz: de4c1669a46c1cc4257d84ae12a8a3243679bf6d264e58383519a57cc405ab71fa870d098903b92edd322a672f6901481e9e824d259c6f1d86e8223d642f25e7
7
- data.tar.gz: e98d7dfdfd023b845dcffadfcf46e17f8e21d2f1357f88cc0e0454cb377d2f7e6dad179a9c206f75be9432630cc6ccfcb6ec6ab6d73da8e06f73f43657e88de4
6
+ metadata.gz: 192db714b76ee2a5d197577e21c2907f50d211667b1d16f7ee468af71196655da67fc593771e1f713419bc5a382e8b196b315660dba62c4563ee553bc9581e8d
7
+ data.tar.gz: 2f72e880e360b4d74e6b8b27b25baf0f9a4bb867615723afa9c40089d1a4debaf42c96aa6ee5997f2bc432d315bcbd6c02d9612c9f73aa096dffed1e6cb18cb9
@@ -4,9 +4,51 @@ 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
- ## [Unreleased]
7
+ ## [1.1.0] - 2020-06-15
8
+ ### Changed
9
+ - Moving to Requst classes instead of mixing in logic to models (kept backwards compatibility)
10
+ - Added potential matches to responses and implemented for patient search
11
+
12
+ =======
13
+ ### Added
14
+ - PotentialMatches class
15
+
16
+ ## [1.0.2] - 2019-06-04
17
+ ### Changed
18
+ - Added Extensions to all Redox models
19
+ - Fixed warnings in gemspec
20
+ - Fixed author emails in gemspec
21
+ - Removed packaging of bin and files starting with '.'
22
+ - Added helper file to translate Redox JSON to Hashie model.
23
+
24
+ ### Removed
25
+ - Unused response model.
26
+
27
+ ## [1.0.1] - 2019-05-02
28
+ ### Changed
29
+ - Check for high-level key as symbol
30
+
31
+ ## [1.0.0] - 2019-05-01
32
+ ### Changed
33
+ - How it works
34
+
8
35
  ### Added
9
- - <TBD>
36
+ - Connection, RedoxClient, Authorization
37
+ - Global configuration block
38
+ - Gems httparty, hashie
39
+
40
+ ### Removed
41
+ - Identifiers, Demographics
42
+
43
+ ## [0.1.6] - 2019-04-22
44
+ ### Added
45
+ - Meta model
46
+ - Response and Authentication classes
47
+
48
+ ### Changed
49
+ - Created a single request method
50
+ - Allow caller to override all Meta
51
+ - Made calls consistent in return and call signature
10
52
 
11
53
  ## [0.1.5] - 2019-04-09
12
54
  ### Added
@@ -52,7 +94,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
52
94
  ### Added
53
95
  - Initial Release
54
96
 
55
- [Unreleased]: https://github.com/WeInfuse/redox/compare/v0.1.5...HEAD
97
+ [1.1.0]: https://github.com/WeInfuse/redox/compare/v1.0.2...v1.1.0
98
+ [1.0.2]: https://github.com/WeInfuse/redox/compare/v1.0.1...v1.0.2
99
+ [1.0.1]: https://github.com/WeInfuse/redox/compare/v1.0.0...v1.0.1
100
+ [1.0.0]: https://github.com/WeInfuse/redox/compare/v0.1.6...v1.0.0
101
+ [0.1.6]: https://github.com/WeInfuse/redox/compare/v0.1.5...v0.1.6
56
102
  [0.1.5]: https://github.com/WeInfuse/redox/compare/v0.1.4...v0.1.5
57
103
  [0.1.4]: https://github.com/WeInfuse/redox/compare/0.1.3...v0.1.4
58
104
  [0.1.3]: https://github.com/WeInfuse/redox/compare/0.1.2...0.1.3
data/README.md CHANGED
@@ -21,34 +21,90 @@ Or install it yourself as:
21
21
 
22
22
  ## Usage
23
23
 
24
+ ### Setup
25
+
26
+ Make sure you're [configured](#configuration)!
27
+
24
28
  ```ruby
25
- source = {
26
- Name: 'Redox Dev Tools',
27
- ID: ENV['REDOX_SRC_ID']
28
- }
29
+ patient = Redox::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 = Redox::Models::Meta.new
35
+ meta.set_source(name: 'MySource', id: '123-584')
36
+ meta.add_destination(name: 'TheDest', id: '973-238')
37
+ ```
38
+
39
+ ### Create
40
+
41
+ ```ruby
42
+ response = patient.create(meta: meta)
43
+ ```
44
+
45
+ ### Update
46
+
47
+ ```ruby
48
+ response = patient.update(meta: meta)
49
+ ```
50
+
51
+ ### Search
52
+
53
+ ```ruby
54
+ response = Redox::Models::Patient.query(patient, meta: meta)
55
+ ```
56
+
57
+ ### Response
58
+
59
+ The response object is a base `Redox::Models::Model` class.
60
+
61
+ With the HTTParty response object
62
+ ```ruby
63
+ response.response
64
+ #<HTTParty::Response:0x7fa354c1fbe8>
65
+
66
+ response.response.ok?
67
+ true
68
+ ```
29
69
 
30
- destinations = [
31
- {
32
- Name: 'Redox EMR',
33
- ID: ENV['REDOX_DEST_ID']
70
+ And any `Model` objects that were returned
71
+ ```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
+ ...
34
83
  }
35
- ]
36
-
37
- redox = Redox::Redox.new(
38
- api_key: ENV['REDOX_KEY'],
39
- secret: ENV['REDOX_SECRET'],
40
- source: source,
41
- destinations: destinations,
42
- test: true
43
- )
44
-
45
- redox.add_patient(
46
- Identifiers: [...],
47
- Demographics: {
48
- FirstName: 'Joe'
49
- ...
84
+ "PCP"=> {
85
+ "NPI"=>nil,
50
86
  }
51
- )
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
+ }
97
+ ```
98
+
99
+ ### Configuration
100
+
101
+ ```ruby
102
+ Redox.configure do |c|
103
+ c.api_key = ENV['REDOX_API_KEY']
104
+ c.secret = ENV['REDOX_SECRET']
105
+ c.api_endpoint = 'http://hello.com' # Defaults to Redox endpoint
106
+ c.token_expiry_padding = 120 # Defaults to 60 seconds
107
+ end
52
108
  ```
53
109
 
54
110
  ## Development
@@ -1,167 +1,85 @@
1
- require 'json'
2
- require 'net/http'
3
- require 'uri'
4
- require 'openssl'
1
+ require 'httparty'
2
+ require 'hashie'
5
3
  require 'redox/version'
6
4
  require 'redox/redox_exception'
5
+ require 'redox/connection'
6
+ require 'redox/authentication'
7
7
  require 'redox/models/model'
8
+ require 'redox/models/meta'
8
9
  require 'redox/models/patient'
9
- require 'redox/models/demographics'
10
- require 'redox/models/identifiers'
10
+ require 'redox/models/patient/demographics'
11
+ require 'redox/models/patient/identifier'
12
+ require 'redox/models/patient/insurance'
13
+ require 'redox/models/patient/p_c_p'
14
+ require 'redox/models/potential_matches'
15
+ require 'redox/request/patient_admin'
16
+ require 'redox/request/patient_search'
11
17
 
12
18
  module Redox
13
- # Redox API client
14
- class Redox
15
- # Instantiates a new Redox connection object
16
- #
17
- # @param [String] api_key API key for the connection
18
- # @param [String] secret API secret for the connection
19
- # @param [Hash] source source information
20
- # @param [Array<Hash>] destinations list of destinations
21
- # @param [Boolean] test whether to use test mode
22
- # @example
23
- # redox = Redox::Redox.new(
24
- # api_key: ENV['REDOX_KEY'],
25
- # secret: ENV['REDOX_SECRET'],
26
- # source: source,
27
- # destinations: destinations,
28
- # test: true
29
- # )
30
- def initialize(api_key:, secret:, source:, destinations:, facility_code: nil, test: true)
31
- @api_key = api_key
32
- @secret = secret
33
- @source = source
34
- @destinations = destinations
35
- @facility_code = facility_code
36
- @test = test
37
- @connection = nil
38
- @access_token = nil
39
- end
40
-
41
- # Send NewPatient message
42
- #
43
- # @param [Hash] patient_params data to send in the Patient JSON object
44
- # @return [Hash] parsed response object
45
- # @example
46
- # Redox::Redox.new(*connection_params).add_patient(
47
- # Identifiers: [],
48
- # Demographics: {
49
- # FirstName: 'Joe'
50
- # }
51
- # )
52
- def add_patient(patient_params)
53
- patient_request = Net::HTTP::Post.new('/endpoint', auth_header)
54
- request_body = request_meta(
55
- data_model: 'PatientAdmin', event_type: 'NewPatient'
56
- ).merge(Patient: patient_params)
57
- patient_request.body = request_body.to_json
58
-
59
- response = connection.request(patient_request)
19
+ class Configuration
20
+ attr_accessor :api_key, :secret
60
21
 
61
- JSON.parse(response.body)
22
+ def initialize
23
+ @api_key = nil
24
+ @secret = nil
62
25
  end
63
26
 
64
- # Send PatientUpdate message
65
- #
66
- # @param [Hash] patient_params data to send in the Patient JSON object
67
- # @return [Hash] parsed response object
68
- # @example
69
- # Redox::Redox.new(*connection_params).update_patient(
70
- # Identifiers: [],
71
- # Demographics: {
72
- # FirstName: 'Joe'
73
- # }
74
- # )
75
- def update_patient(patient_params)
76
- patient_request = Net::HTTP::Post.new('/endpoint', auth_header)
77
- request_body = request_meta(
78
- data_model: 'PatientAdmin', event_type: 'PatientUpdate'
79
- ).merge(Patient: patient_params)
80
- patient_request.body = request_body.to_json
81
-
82
- response = connection.request(patient_request)
83
-
84
- JSON.parse(response.body)
27
+ def api_endpoint=(endpoint)
28
+ Connection.base_uri(endpoint.freeze)
85
29
  end
86
30
 
87
- # Send PatientSearch query
88
- #
89
- # @param [Hash] patient_params data to send in the Patient JSON object
90
- # @return [Hash] Redox Patient object
91
- # @example
92
- # Redox::Redox.new(*connection_params).search_patients(
93
- # Identifiers: [],
94
- # Demographics: {
95
- # FirstName: 'Joe'
96
- # }
97
- # )
98
- def search_patients(patient_params)
99
- patient_request = Net::HTTP::Post.new(Models::Patient::SEARCH[:endpoint], auth_header)
100
- request_body = request_meta(Models::Patient::SEARCH[:meta])
101
- .merge(Patient: patient_params)
102
- patient_request.body = request_body.to_json
103
-
104
- response = connection.request(patient_request)
105
-
106
- return Models::Patient.new(JSON.parse(response.body))
31
+ def api_endpoint
32
+ return Connection.base_uri
107
33
  end
108
34
 
109
- private
110
-
111
- attr_reader :api_key, :secret, :source, :destinations, :facility_code, :test
112
-
113
- def access_token
114
- return @access_token if @access_token
115
-
116
- login_request = Net::HTTP::Post.new(
117
- '/auth/authenticate', 'Content-Type' => 'application/json'
118
- )
119
- login_request.body = { apiKey: api_key, secret: secret }.to_json
120
- response = connection.request(login_request)
121
-
122
- if (false == response.is_a?(Net::HTTPOK))
123
- raise RedoxException.from_response(response, msg: 'Authentication')
124
- end
125
-
126
- body = JSON.parse(response.body)
35
+ def token_expiry_padding=(time_in_seconds)
36
+ Authentication.token_expiry_padding = time_in_seconds
37
+ end
127
38
 
128
- @access_token = body['accessToken']
39
+ def token_expiry_padding
40
+ return Authentication.token_expiry_padding
129
41
  end
130
42
 
131
- def connection
132
- return @connection if @connection
43
+ def to_h
44
+ return {
45
+ api_key: @api_key,
46
+ secret: @secret,
47
+ api_endpoint: api_endpoint,
48
+ token_expiry_padding: token_expiry_padding
49
+ }
50
+ end
133
51
 
134
- uri = URI.parse('https://api.redoxengine.com/')
135
- http = Net::HTTP.new(uri.host, uri.port)
136
- http.use_ssl = true
137
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
138
- http.verify_depth = 5
52
+ def from_h(h)
53
+ self.api_key = h[:api_key]
54
+ self.secret = h[:secret]
55
+ self.api_endpoint = h[:api_endpoint]
56
+ self.token_expiry_padding = h[:token_expiry_padding]
139
57
 
140
- @connection = http
58
+ return self
141
59
  end
60
+ end
142
61
 
143
- def auth_header
144
- {
145
- 'Authorization' => "Bearer #{access_token}",
146
- 'Content-Type' => 'application/json'
147
- }
62
+ class << self
63
+ def configuration
64
+ @configuration ||= Configuration.new
148
65
  end
149
66
 
150
- def request_meta(data_model:, event_type:)
151
- meta_object = {
152
- Meta: {
153
- DataModel: data_model,
154
- EventType: event_type,
155
- EventDateTime: nil,
156
- Test: test,
157
- }
158
- }
67
+ def configure
68
+ yield(configuration)
69
+ end
70
+ end
159
71
 
160
- meta_object[:Meta][:FacilityCode] = facility_code if facility_code
161
- meta_object[:Meta][:Source] = source if source
162
- meta_object[:Meta][:Destinations] = destinations if destinations && !destinations.empty?
72
+ # Redox API client
73
+ class RedoxClient
74
+ class << self
75
+ def connection
76
+ Redox.configuration.token_expiry_padding = 60 if Redox.configuration.token_expiry_padding.nil?
77
+ @connection ||= Connection.new
78
+ end
163
79
 
164
- meta_object
80
+ def release
81
+ @connection = nil
82
+ end
165
83
  end
166
84
  end
167
85
  end
@@ -0,0 +1,77 @@
1
+ module Redox
2
+ class Authentication < Connection
3
+ attr_accessor :response
4
+
5
+ BASE_ENDPOINT = '/auth'.freeze
6
+
7
+ AUTH_ENDPOINT = "#{BASE_ENDPOINT}/authenticate".freeze
8
+ REFRESH_ENDPOINT = "#{BASE_ENDPOINT}/refreshToken".freeze
9
+
10
+ class << self
11
+ attr_accessor :token_expiry_padding
12
+
13
+ @@token_expiry_padding = 0
14
+ end
15
+
16
+ def initialize
17
+ @response = nil
18
+ end
19
+
20
+ def authenticate
21
+ if (self.expires?)
22
+ if (self.refresh_token)
23
+ request = {
24
+ body: { apiKey: Redox.configuration.api_key, refreshToken: self.refresh_token },
25
+ endpoint: REFRESH_ENDPOINT
26
+ }
27
+ else
28
+ request = {
29
+ body: { apiKey: Redox.configuration.api_key, secret: Redox.configuration.secret },
30
+ endpoint: AUTH_ENDPOINT
31
+ }
32
+ end
33
+
34
+ response = self.request(**request, auth: false)
35
+
36
+ if (false == response.ok?)
37
+ @response = nil
38
+ raise RedoxException.from_response(response, msg: 'Authentication')
39
+ else
40
+ @response = response
41
+ end
42
+ end
43
+
44
+ return self
45
+ end
46
+
47
+ def access_token
48
+ return @response['accessToken'] if @response
49
+ end
50
+
51
+ def expiry
52
+ return @response['expires'] if @response
53
+ end
54
+
55
+ def refresh_token
56
+ return @response['refreshToken'] if @response
57
+ end
58
+
59
+ def expires?(seconds_from_now = Authentication.token_expiry_padding)
60
+ if (self.expiry)
61
+ return DateTime.strptime(self.expiry, Models::Meta::FROM_DATETIME_FORMAT).to_time.utc <= (Time.now + seconds_from_now).utc
62
+ else
63
+ return true
64
+ end
65
+ end
66
+
67
+ def access_header
68
+ return {
69
+ 'Authorization' => "Bearer #{self.access_token}",
70
+ }
71
+ end
72
+
73
+ def expire!
74
+ @response = nil
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,28 @@
1
+ module Redox
2
+ class Connection
3
+ DEFAULT_ENDPOINT = '/endpoint'.freeze
4
+
5
+ include HTTParty
6
+
7
+ base_uri 'https://api.redoxengine.com/'.freeze
8
+
9
+ headers 'Content-Type' => 'application/json'
10
+
11
+ format :json
12
+
13
+ def request(endpoint: DEFAULT_ENDPOINT, body: nil, headers: {}, auth: true)
14
+ body = body.to_json if body.is_a?(Hash)
15
+ headers = auth_header.merge(headers) if auth
16
+
17
+ self.class.post(endpoint, body: body, headers: headers)
18
+ end
19
+
20
+ private
21
+
22
+ def auth_header
23
+ @auth ||= Authentication.new
24
+
25
+ return @auth.authenticate.access_header
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,46 @@
1
+ module Redox
2
+ module Models
3
+ class Meta < Model
4
+ TO_DATETIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%6NZ'.freeze
5
+ FROM_DATETIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%N%Z'.freeze
6
+
7
+ property :DataModel, from: :data_model, required: false
8
+ property :EventType, from: :event_type, required: false
9
+ property :EventDateTime, from: :event_date_time, default: ->() { Time.now.utc.strftime(TO_DATETIME_FORMAT) }
10
+ property :Test, from: :test, default: true
11
+ property :Source, from: :source, required: false
12
+ property :Destinations, from: :destinations, required: false
13
+ property :FacilityCode, from: :facility_code, required: false
14
+
15
+ alias_method :data_model, :DataModel
16
+ alias_method :event_type, :EventType
17
+ alias_method :event_date_time, :EventDateTime
18
+ alias_method :test, :Test
19
+ alias_method :source, :Source
20
+ alias_method :destinations, :Destinations
21
+ alias_method :facility_code, :FacilityCode
22
+
23
+ def add_destination(name: , id: )
24
+ self[:Destinations] ||= []
25
+ self[:Destinations] << Meta.build_subscription(name: name, id: id)
26
+
27
+ return self
28
+ end
29
+
30
+ def set_source(name: , id: )
31
+ self[:Source] = Meta.build_subscription(name: name, id: id)
32
+
33
+ return self
34
+ end
35
+
36
+ class << self
37
+ def build_subscription(name: , id:)
38
+ return {
39
+ 'ID' => id,
40
+ 'Name' => name
41
+ }
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -1,48 +1,59 @@
1
1
  module Redox
2
2
  module Models
3
- class Model
4
- KEY = nil
3
+ class Model < Hashie::Trash
4
+ include Hashie::Extensions::IgnoreUndeclared
5
+ include Hashie::Extensions::IndifferentAccess
5
6
 
6
- def initialize(data)
7
- @data = data.freeze
7
+ property :Meta, from: :meta, required: false
8
+ property :Patient, from: :patient, required: false
9
+ property :PotentialMatches, from: :potential_matches, required: false
10
+ property :Extensions, from: :extensions, required: false
11
+ property :response, required: false
12
+
13
+ alias_method :potential_matches, :PotentialMatches
14
+ alias_method :patient, :Patient
15
+ alias_method :meta, :Meta
16
+
17
+ def initialize(data = {})
18
+ if data.is_a?(Hash)
19
+ if data.include?(key)
20
+ data = data[key]
21
+ elsif data.include?(key.to_sym)
22
+ data = data[key.to_sym]
23
+ end
24
+ end
25
+
26
+ super(data)
8
27
  end
9
28
 
10
- def valid?
11
- return @data.is_a?(Hash) && @data.include?(self.class::KEY)
29
+ def to_h
30
+ return { key => super.to_h }
12
31
  end
13
32
 
14
- def raw(key: self.class::KEY)
15
- if key.nil?
16
- return @data
17
- else
18
- return @data[key]
19
- end
33
+ def to_json
34
+ return self.to_h.to_json
20
35
  end
21
36
 
22
- def map(mapper: {}, data: self.raw)
23
- result = {}
24
-
25
- if (true == mapper.is_a?(Hash))
26
- mapper.each do |key, value|
27
- if (true == value.is_a?(Hash))
28
- result = result.merge(self.map(data: data[key], mapper: value))
29
- elsif (true == value.respond_to?(:call))
30
- lambda_result = value.call(data[key])
31
-
32
- if (true == lambda_result.is_a?(Hash))
33
- result = result.merge(lambda_result)
34
- else
35
- raise "lambda must return hash"
36
- end
37
- else
38
- result[value] = data[key]
37
+ class << self
38
+ def from_response(response)
39
+ model = Model.new
40
+ model.response = response
41
+
42
+ %w[Meta Patient PotentialMatches].each do |k|
43
+ begin
44
+ model.send("#{k}=", Module.const_get("Redox::Models::#{k}").new(response[k])) if response[k]
45
+ rescue
39
46
  end
40
47
  end
41
- else
42
- raise "mapper must be a hash, got '#{mapper}'"
48
+
49
+ return model
43
50
  end
51
+ end
52
+
53
+ private
44
54
 
45
- return result
55
+ def key
56
+ return self.class.to_s.split('::').last.to_s
46
57
  end
47
58
  end
48
59
  end
@@ -1,24 +1,50 @@
1
1
  module Redox
2
2
  module Models
3
3
  class Patient < Model
4
- attr_reader :demographics, :identifiers
4
+ property :Identifiers, from: :identifiers, required: false, default: []
5
+ property :Insurances, from: :insurances, required: false, default: []
6
+ property :Demographics, from: :demographics, required: false
7
+ property :PCP, from: :primary_care_provider, required: false
5
8
 
6
- KEY = 'Patient'
9
+ alias_method :identifiers, :Identifiers
10
+ alias_method :insurances, :Insurances
7
11
 
8
- SEARCH = {
9
- meta: {
10
- data_model: 'PatientSearch',
11
- event_type: 'Query'
12
- },
13
- endpoint: '/query'
14
- }
12
+ def demographics
13
+ self[:Demographics] = Demographics.new(self[:Demographics]) unless self[:Demographics].is_a?(Redox::Models::Demographics)
14
+ self[:Demographics] ||= Demographics.new
15
+ end
16
+
17
+ def insurances
18
+ self[:Insurances] = self[:Insurances].map {|ins| ins.is_a?(Redox::Models::Insurance) ? ins : Insurance.new(ins) }
19
+ end
20
+
21
+ def primary_care_provider
22
+ self[:PCP] ||= PCP.new
23
+ end
24
+
25
+ def add_identifier(type: , value: )
26
+ self[:Identifiers] << Identifier.new({'ID' => value, 'IDType' => type})
27
+
28
+ return self
29
+ end
30
+
31
+ def add_insurance(data = {})
32
+ self[:Insurances] << Insurance.new(data)
33
+
34
+ return self
35
+ end
15
36
 
16
- def initialize(data)
17
- super(data)
37
+ def update(meta: Meta.new)
38
+ Redox::Request::PatientAdmin.update(patient: self, meta: meta)
39
+ end
40
+
41
+ def create(meta: Meta.new)
42
+ Redox::Request::PatientAdmin.create(patient: self, meta: meta)
43
+ end
18
44
 
19
- if (self.valid?)
20
- @demographics = Demographics.new(self.raw)
21
- @identifiers = Identifiers.new(self.raw)
45
+ class << self
46
+ def query(params, meta: Meta.new)
47
+ return Redox::Request::PatientSearch.query(params, meta: meta)
22
48
  end
23
49
  end
24
50
  end
@@ -0,0 +1,34 @@
1
+ module Redox
2
+ module Models
3
+ class Demographics < Model
4
+ property :FirstName, required: false, from: :first_name
5
+ property :MiddleName, required: false, from: :middle_name
6
+ property :LastName, required: false, from: :last_name
7
+ property :DOB, required: false, from: :dob
8
+ property :SSN, required: false, from: :ssn
9
+ property :Sex, required: false, from: :sex
10
+ property :Race, required: false, from: :race
11
+ property :IsHispanic, required: false
12
+ property :MaritalStatus, required: false, from: :martial_status
13
+ property :IsDeceased, required: false
14
+ property :DeathDateTime, required: false
15
+ property :Language, required: false, from: :language
16
+ property :EmailAddresses, required: false, default: []
17
+ property :Citizenship, required: false, default: []
18
+ property :Address, required: false, default: {}
19
+ property :PhoneNumber, required: false, default: {}
20
+
21
+ alias_method :first_name, :FirstName
22
+ alias_method :middle_name, :MiddleName
23
+ alias_method :last_name, :LastName
24
+ alias_method :dob, :DOB
25
+ alias_method :ssn, :SSN
26
+ alias_method :sex, :Sex
27
+ alias_method :race, :Race
28
+ alias_method :martial_status, :MaritalStatus
29
+ alias_method :language, :Language
30
+ alias_method :address, :Address
31
+ alias_method :phone_number, :PhoneNumber
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,11 @@
1
+ module Redox
2
+ module Models
3
+ class Identifier < Model
4
+ property :ID, from: :id
5
+ property :IDType, from: :id_type
6
+
7
+ alias_method :id, :ID
8
+ alias_method :id_type, :IDType
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,29 @@
1
+ module Redox
2
+ module Models
3
+ class Insurance < Model
4
+ property :Plan, required: false, from: :plan, default: {}
5
+ property :MemberNumber, required: false, from: :member_number
6
+ property :Company, required: false, from: :company, default: {}
7
+ property :GroupNumber, required: false, from: :group_number
8
+ property :GroupName, required: false, from: :group_name
9
+ property :EffectiveDate, required: false, from: :effective_date
10
+ property :ExpirationDate, required: false, from: :expiration_date
11
+ property :PolicyNumber, required: false, from: :policy_number
12
+ property :AgreementType, required: false, from: :agreement_type
13
+ property :CoverageType, required: false, from: :coverage_type
14
+ property :Insured, required: false, from: :insured, default: {}
15
+
16
+ alias_method :plan, :Plan
17
+ alias_method :member_number, :MemberNumber
18
+ alias_method :company, :Company
19
+ alias_method :group_number, :GroupNumber
20
+ alias_method :group_name, :GroupName
21
+ alias_method :effective_date, :EffectiveDate
22
+ alias_method :expiration_date, :ExpirationDate
23
+ alias_method :policy_number, :PolicyNumber
24
+ alias_method :agreement_type, :AgreementType
25
+ alias_method :coverage_type, :CoverageType
26
+ alias_method :insured, :Insured
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,13 @@
1
+ module Redox
2
+ module Models
3
+ class PCP < Model
4
+ property :NPI, from: :npi
5
+ property :FirstName, required: false, from: :first_name
6
+ property :LastName, required: false, from: :last_name
7
+
8
+ alias_method :npi, :NPI
9
+ alias_method :first_name, :FirstName
10
+ alias_method :last_name, :LastName
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Redox
2
+ module Models
3
+ class PotentialMatches < Array
4
+ def initialize(data = [])
5
+ if false == data.nil?
6
+ super(data.map {|patient| Redox::Models::Patient.new(patient) })
7
+ else
8
+ super([])
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,24 @@
1
+ module Redox
2
+ module Request
3
+ class PatientAdmin
4
+ CREATE_META = Redox::Models::Meta.new(EventType: 'NewPatient', DataModel: 'PatientAdmin')
5
+ UPDATE_META = Redox::Models::Meta.new(EventType: 'PatientUpdate', DataModel: 'PatientAdmin')
6
+
7
+ def self.create(patient: p, meta: Redox::Models::Meta.new)
8
+ meta = CREATE_META.merge(meta)
9
+ return Redox::Models::Model.from_response((RedoxClient.connection.request(body: Redox::Request::PatientAdmin.build_body(p, meta))))
10
+ end
11
+
12
+ def self.update(patient: p, meta: Redox::Models::Meta.new)
13
+ meta = UPDATE_META.merge(meta)
14
+ return Redox::Models::Model.from_response((RedoxClient.connection.request(body: Redox::Request::PatientAdmin.build_body(p, meta))))
15
+ end
16
+
17
+ def self.build_body(params, meta)
18
+ meta = Redox::Models::Meta.new.merge(meta)
19
+
20
+ return meta.to_h.merge(params.to_h)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,13 @@
1
+ module Redox
2
+ module Request
3
+ class PatientSearch
4
+ QUERY_ENDPOINT = '/query'.freeze
5
+ QUERY_META = Redox::Models::Meta.new(EventType: 'Query', DataModel: 'PatientSearch')
6
+
7
+ def self.query(params, meta: Redox::Models::Meta.new)
8
+ meta = QUERY_META.merge(meta)
9
+ return Redox::Models::Model.from_response((RedoxClient.connection.request(endpoint: QUERY_ENDPOINT, body: Redox::Request::PatientAdmin.build_body(params, meta))))
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,3 +1,3 @@
1
1
  module Redox
2
- VERSION = '0.1.5'.freeze
2
+ VERSION = '1.1.0'.freeze
3
3
  end
@@ -5,8 +5,8 @@ require 'redox/version'
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = 'redox'
7
7
  spec.version = Redox::VERSION
8
- spec.authors = ['Alexander Clark']
9
- spec.email = ['sasha.jackal@gmail.com']
8
+ spec.authors = ['Alexander Clark', 'Mike Crockett']
9
+ spec.email = ['alexander.clark@weinfuse.com', 'mike.crockett@weinfuse.com']
10
10
 
11
11
  spec.summary = 'Ruby wrapper for the Redox Engine API'
12
12
  spec.homepage = 'https://github.com/WeInfuse/redox'
@@ -20,13 +20,18 @@ Gem::Specification.new do |spec|
20
20
  end
21
21
 
22
22
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
23
- f.match(%r{^(test|spec|features)/})
23
+ f.match?(%r{^(test|spec|features|bin|helpers|)/}) || f.match?(%r{^(\.[[:alnum:]]+)})
24
24
  end
25
+
25
26
  spec.bindir = 'exe'
26
27
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
28
  spec.require_paths = ['lib']
29
+ spec.licenses = ['MIT']
28
30
 
29
- spec.add_development_dependency 'bundler'
31
+ spec.add_dependency 'httparty', '~> 0.17'
32
+ spec.add_dependency 'hashie', '~> 3.5'
33
+ spec.add_development_dependency 'bundler', '>=1', '<3'
34
+ spec.add_development_dependency 'byebug', '~> 11'
30
35
  spec.add_development_dependency 'minitest', '~> 5.0'
31
36
  spec.add_development_dependency 'rake', '~> 10.0'
32
37
  spec.add_development_dependency 'webmock', '~> 3.1'
metadata CHANGED
@@ -1,29 +1,78 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Clark
8
+ - Mike Crockett
8
9
  autorequire:
9
10
  bindir: exe
10
11
  cert_chain: []
11
- date: 2019-04-09 00:00:00.000000000 Z
12
+ date: 2020-06-15 00:00:00.000000000 Z
12
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: httparty
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '0.17'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '0.17'
28
+ - !ruby/object:Gem::Dependency
29
+ name: hashie
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '3.5'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '3.5'
13
42
  - !ruby/object:Gem::Dependency
14
43
  name: bundler
15
44
  requirement: !ruby/object:Gem::Requirement
16
45
  requirements:
17
46
  - - ">="
18
47
  - !ruby/object:Gem::Version
19
- version: '0'
48
+ version: '1'
49
+ - - "<"
50
+ - !ruby/object:Gem::Version
51
+ version: '3'
20
52
  type: :development
21
53
  prerelease: false
22
54
  version_requirements: !ruby/object:Gem::Requirement
23
55
  requirements:
24
56
  - - ">="
25
57
  - !ruby/object:Gem::Version
26
- version: '0'
58
+ version: '1'
59
+ - - "<"
60
+ - !ruby/object:Gem::Version
61
+ version: '3'
62
+ - !ruby/object:Gem::Dependency
63
+ name: byebug
64
+ requirement: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '11'
69
+ type: :development
70
+ prerelease: false
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '11'
27
76
  - !ruby/object:Gem::Dependency
28
77
  name: minitest
29
78
  requirement: !ruby/object:Gem::Requirement
@@ -82,31 +131,36 @@ dependencies:
82
131
  version: '0.9'
83
132
  description:
84
133
  email:
85
- - sasha.jackal@gmail.com
134
+ - alexander.clark@weinfuse.com
135
+ - mike.crockett@weinfuse.com
86
136
  executables: []
87
137
  extensions: []
88
138
  extra_rdoc_files: []
89
139
  files:
90
- - ".circleci/config.yml"
91
- - ".editorconfig"
92
- - ".gitignore"
93
140
  - CHANGELOG.md
94
141
  - CODE_OF_CONDUCT.md
95
142
  - Gemfile
96
143
  - README.md
97
144
  - Rakefile
98
- - bin/console
99
- - bin/setup
100
145
  - lib/redox.rb
101
- - lib/redox/models/demographics.rb
102
- - lib/redox/models/identifiers.rb
146
+ - lib/redox/authentication.rb
147
+ - lib/redox/connection.rb
148
+ - lib/redox/models/meta.rb
103
149
  - lib/redox/models/model.rb
104
150
  - lib/redox/models/patient.rb
151
+ - lib/redox/models/patient/demographics.rb
152
+ - lib/redox/models/patient/identifier.rb
153
+ - lib/redox/models/patient/insurance.rb
154
+ - lib/redox/models/patient/p_c_p.rb
155
+ - lib/redox/models/potential_matches.rb
105
156
  - lib/redox/redox_exception.rb
157
+ - lib/redox/request/patient_admin.rb
158
+ - lib/redox/request/patient_search.rb
106
159
  - lib/redox/version.rb
107
160
  - redox.gemspec
108
161
  homepage: https://github.com/WeInfuse/redox
109
- licenses: []
162
+ licenses:
163
+ - MIT
110
164
  metadata:
111
165
  allowed_push_host: https://rubygems.org
112
166
  post_install_message:
@@ -1,23 +0,0 @@
1
- version: 2
2
- jobs:
3
- build:
4
- working_directory: ~/weinfuse_api
5
- docker:
6
- - image: circleci/ruby:2.4
7
- steps:
8
- - checkout
9
- - type: restore-cache
10
- key: redox_{{ checksum "Gemfile.lock" }}
11
- key: redox
12
- - run: bundle install --path vendor/bundle --jobs 20 --retry 5
13
- - type: cache-save
14
- key: redox_{{ checksum "Gemfile.lock" }}
15
- key: redox
16
- paths:
17
- - vendor/bundle
18
- - type: shell
19
- command: |
20
- bundle exec rake test
21
- - type: store_test_results
22
- path: /tmp/test-results
23
-
@@ -1,10 +0,0 @@
1
- root=true
2
-
3
- [*]
4
- indent_style = space
5
- indent_size = 2
6
- end_of_line = lf
7
- charset = utf-8
8
- trim_trailing_whitespace = true
9
- insert_final_newline = true
10
-
data/.gitignore DELETED
@@ -1,10 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /Gemfile.lock
4
- /_yardoc/
5
- /coverage/
6
- /doc/
7
- /pkg/
8
- /spec/reports/
9
- /tmp/
10
- /redox*.gem
@@ -1,15 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'bundler/setup'
4
- require 'json'
5
- require 'redox'
6
-
7
- # You can add fixtures and/or initialization code here to make experimenting
8
- # with your gem easier. You can also use a different console, if you like.
9
-
10
- # (If you use this, don't forget to add pry to your Gemfile!)
11
- # require "pry"
12
- # Pry.start
13
-
14
- require 'irb'
15
- IRB.start
data/bin/setup DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here
@@ -1,7 +0,0 @@
1
- module Redox
2
- module Models
3
- class Demographics < Model
4
- KEY = 'Demographics'
5
- end
6
- end
7
- end
@@ -1,7 +0,0 @@
1
- module Redox
2
- module Models
3
- class Identifiers < Model
4
- KEY = 'Identifiers'
5
- end
6
- end
7
- end