lifen_fhir 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +9 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +74 -0
- data/License.txt +22 -0
- data/README.md +131 -0
- data/lib/lifen_fhir/app_authenticated_client.rb +38 -0
- data/lib/lifen_fhir/attachment.rb +26 -0
- data/lib/lifen_fhir/base.rb +7 -0
- data/lib/lifen_fhir/binary.rb +29 -0
- data/lib/lifen_fhir/category.rb +26 -0
- data/lib/lifen_fhir/channel.rb +31 -0
- data/lib/lifen_fhir/client.rb +107 -0
- data/lib/lifen_fhir/communication_request.rb +67 -0
- data/lib/lifen_fhir/configuration.rb +22 -0
- data/lib/lifen_fhir/content_string.rb +15 -0
- data/lib/lifen_fhir/error.rb +27 -0
- data/lib/lifen_fhir/medium.rb +15 -0
- data/lib/lifen_fhir/patient.rb +27 -0
- data/lib/lifen_fhir/practitioner.rb +97 -0
- data/lib/lifen_fhir/user_authenticated_client.rb +39 -0
- data/lib/lifen_fhir/version.rb +3 -0
- data/lib/lifen_fhir.rb +29 -0
- data/lifen_fhir.gemspec +30 -0
- data/spec/binary_spec.rb +29 -0
- data/spec/cassettes/binary/download/invalid.yml +65 -0
- data/spec/cassettes/binary/download/valid.yml +1320 -0
- data/spec/cassettes/communication_request/send/invalid_medium.yml +69 -0
- data/spec/cassettes/communication_request/send/valid_attributes.yml +75 -0
- data/spec/cassettes/communication_request/send/valid_attributes_binary.yml +74 -0
- data/spec/cassettes/practitionner/create_channel/address/old_valid_attributes.yml +71 -0
- data/spec/cassettes/practitionner/create_channel/address/valid_attributes.yml +71 -0
- data/spec/cassettes/practitionner/create_channel/telecom/valid_attributes.yml +70 -0
- data/spec/cassettes/practitionner/find_by_rpps/existing_rpps.yml +125 -0
- data/spec/cassettes/practitionner/find_by_rpps/missing_line_attribute.yml +122 -0
- data/spec/cassettes/practitionner/find_by_rpps/wrong_rpps.yml +68 -0
- data/spec/category_spec.rb +21 -0
- data/spec/communication_request_spec.rb +64 -0
- data/spec/practitionner_spec.rb +76 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/support/master_plan.pdf +0 -0
- metadata +232 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1db22fe4077504ea3f23585828eb697f22763c39
|
4
|
+
data.tar.gz: 5fcccdd90ef76bea15800c296280788d02c3f168
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 392a47b43059e7eb3f844f7ab5244290697b815734db38403c895f2acba03d52f75bd45e52ae91732535be5d6a84e22da3e2e8b4cb362acbc5120a7c2f2ce2d0
|
7
|
+
data.tar.gz: 6ca727e4b24cdbeda29c4b00ade9223700109dfc3e2904f7ff366ac460c0966e5ada293439a0956ef702dce97ad23df74febc81ffadef47d66781750685adf75
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.4.1
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
lifen_fhir (0.1.1)
|
5
|
+
faraday (>= 0.9)
|
6
|
+
inflecto
|
7
|
+
virtus (>= 1.0)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
addressable (2.5.1)
|
13
|
+
public_suffix (~> 2.0, >= 2.0.2)
|
14
|
+
awesome_print (1.7.0)
|
15
|
+
axiom-types (0.1.1)
|
16
|
+
descendants_tracker (~> 0.0.4)
|
17
|
+
ice_nine (~> 0.11.0)
|
18
|
+
thread_safe (~> 0.3, >= 0.3.1)
|
19
|
+
coercible (1.0.0)
|
20
|
+
descendants_tracker (~> 0.0.1)
|
21
|
+
crack (0.4.3)
|
22
|
+
safe_yaml (~> 1.0.0)
|
23
|
+
descendants_tracker (0.0.4)
|
24
|
+
thread_safe (~> 0.3, >= 0.3.1)
|
25
|
+
diff-lcs (1.3)
|
26
|
+
equalizer (0.0.11)
|
27
|
+
faraday (0.12.1)
|
28
|
+
multipart-post (>= 1.2, < 3)
|
29
|
+
hashdiff (0.3.4)
|
30
|
+
ice_nine (0.11.2)
|
31
|
+
inflecto (0.0.2)
|
32
|
+
multipart-post (2.0.0)
|
33
|
+
public_suffix (2.0.5)
|
34
|
+
rake (10.5.0)
|
35
|
+
rspec (3.6.0)
|
36
|
+
rspec-core (~> 3.6.0)
|
37
|
+
rspec-expectations (~> 3.6.0)
|
38
|
+
rspec-mocks (~> 3.6.0)
|
39
|
+
rspec-core (3.6.0)
|
40
|
+
rspec-support (~> 3.6.0)
|
41
|
+
rspec-expectations (3.6.0)
|
42
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
43
|
+
rspec-support (~> 3.6.0)
|
44
|
+
rspec-mocks (3.6.0)
|
45
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
46
|
+
rspec-support (~> 3.6.0)
|
47
|
+
rspec-support (3.6.0)
|
48
|
+
safe_yaml (1.0.4)
|
49
|
+
thread_safe (0.3.6)
|
50
|
+
vcr (3.0.3)
|
51
|
+
virtus (1.0.5)
|
52
|
+
axiom-types (~> 0.1)
|
53
|
+
coercible (~> 1.0)
|
54
|
+
descendants_tracker (~> 0.0, >= 0.0.3)
|
55
|
+
equalizer (~> 0.0, >= 0.0.9)
|
56
|
+
webmock (1.24.6)
|
57
|
+
addressable (>= 2.3.6)
|
58
|
+
crack (>= 0.3.2)
|
59
|
+
hashdiff
|
60
|
+
|
61
|
+
PLATFORMS
|
62
|
+
ruby
|
63
|
+
|
64
|
+
DEPENDENCIES
|
65
|
+
awesome_print
|
66
|
+
bundler (~> 1.12)
|
67
|
+
lifen_fhir!
|
68
|
+
rake (~> 10.5)
|
69
|
+
rspec (~> 3.5)
|
70
|
+
vcr (~> 3.0)
|
71
|
+
webmock (~> 1.24)
|
72
|
+
|
73
|
+
BUNDLED WITH
|
74
|
+
1.14.6
|
data/License.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2017 Honestica
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
# Lifen
|
2
|
+
|
3
|
+
Lifen is a Ruby client for [Lifen](http://developers.lifen.fr/) FHIR API (over JSON).
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'lifen_fhir'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install lifen_fhir
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
### Configuration
|
24
|
+
|
25
|
+
Lifen can be configured (ideally inside an initializer) like so:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
LifenFhir.configure do |config|
|
29
|
+
config.site = "https://demo.lifen.fr/"
|
30
|
+
config.application_access_token = "application_access_token"
|
31
|
+
|
32
|
+
# optionnal
|
33
|
+
config.proxy_url = "http://my.proxy.fr/"
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
37
|
+
Optionnal configuration:
|
38
|
+
|
39
|
+
- `proxy_url`: enables you to route all your requests via a proxy
|
40
|
+
|
41
|
+
### Internal
|
42
|
+
|
43
|
+
#### Managing a Binary
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
binary = LifenFhir::Binary.new(uuid: "b7c7dae671b93e951ce6a4f530736276")
|
47
|
+
binary.download
|
48
|
+
```
|
49
|
+
|
50
|
+
### Communication Request
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
sender = LifenFhir::Practitioner.find_by_rpps("899900018483")
|
54
|
+
|
55
|
+
recipient = LifenFhir::Practitioner.find_by_rpps("899900018484")
|
56
|
+
channel = recipient.channels.first
|
57
|
+
|
58
|
+
binary = LifenFhir::Binary.new(uuid: "b7c7dae671b93e951ce6a4f530736276")
|
59
|
+
|
60
|
+
communication_request = LifenFhir::CommunicationRequest.new(sender: sender, recipient: recipient, channel: channel, binary: binary, patient: patient, category: category)
|
61
|
+
|
62
|
+
communication_request.send
|
63
|
+
|
64
|
+
```
|
65
|
+
|
66
|
+
#### Communication Request with multiple recipients
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
sender = LifenFhir::Practitioner.find_by_rpps("899900018483")
|
70
|
+
|
71
|
+
recipient = LifenFhir::Practitioner.find_by_rpps("899900018484")
|
72
|
+
medium = LifenFhir::Medium(uuid: recipient.channels.first.uuid)
|
73
|
+
|
74
|
+
other_recipient = LifenFhir::Practitioner.find_by_rpps("899900018484")
|
75
|
+
other_medium = LifenFhir::Medium(uuid: other_recipient.channels.first.uuid)
|
76
|
+
|
77
|
+
binary = LifenFhir::Binary.new(uuid: "b7c7dae671b93e951ce6a4f530736276")
|
78
|
+
|
79
|
+
communication_request_request = LifenFhir::CommunicationRequest.new(sender: sender, recipients: [recipient, other_recipient], medium: [medium, other_medium], binary: binary, patient: patient, category: category)
|
80
|
+
|
81
|
+
communication_request_request.send
|
82
|
+
|
83
|
+
```
|
84
|
+
|
85
|
+
#### Custom Channels management
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
recipient = LifenFhir::Practitioner.new(uuid: "valid-user-uuid")
|
89
|
+
|
90
|
+
# To create a new mailing address channel
|
91
|
+
channel = recipient.create_address(type: "address", lines: ["39 rue Aboukir"], city: "Paris", postal_code: "75002", country: "France")
|
92
|
+
|
93
|
+
# To create a new telecom channel fax
|
94
|
+
channel = recipient.create_telecom(type: "telecom", system: "fax", value: "+33102030405")
|
95
|
+
```
|
96
|
+
|
97
|
+
## Deploying to Rubygems
|
98
|
+
|
99
|
+
Once the new version is validated, the deployment follows those steps :
|
100
|
+
|
101
|
+
1. update `lib/lifen/version.rb`
|
102
|
+
2. run `bundle install` to update `Gemfile.lock`
|
103
|
+
3. update `CHANGELOG.md` with the additional features of the new version
|
104
|
+
4. commit changes to Github
|
105
|
+
5. build the gem using `gem build lifen_fhir.gemspec`
|
106
|
+
6. publish the gem using `gem publish lifen_fhir-X.X.X.gem`
|
107
|
+
7. run `bundle update lifen` in related projects :)
|
108
|
+
|
109
|
+
## License
|
110
|
+
|
111
|
+
The MIT License (MIT)
|
112
|
+
|
113
|
+
Copyright (c) 2016-2017 Honestica
|
114
|
+
|
115
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
116
|
+
of this software and associated documentation files (the "Software"), to deal
|
117
|
+
in the Software without restriction, including without limitation the rights
|
118
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
119
|
+
copies of the Software, and to permit persons to whom the Software is
|
120
|
+
furnished to do so, subject to the following conditions:
|
121
|
+
|
122
|
+
The above copyright notice and this permission notice shall be included in
|
123
|
+
all copies or substantial portions of the Software.
|
124
|
+
|
125
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
126
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
127
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
128
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
129
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
130
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
131
|
+
THE SOFTWARE.
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module LifenFhir
|
2
|
+
|
3
|
+
class AppAuthenticatedClient < Client
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
def handle_errors(response, params)
|
8
|
+
super(response, params)
|
9
|
+
|
10
|
+
case response.status
|
11
|
+
when 400
|
12
|
+
raise Error, "Error 400, Unknown error, #{response_error(response, params)}"
|
13
|
+
when 401
|
14
|
+
raise InvalidSecretTokenError, "Error 401, Invalid app bearer, #{response_error(response, params)}"
|
15
|
+
when 403
|
16
|
+
raise UserAlreadyExistingError, "Error 403, User already existing, #{response_error(response, params)}"
|
17
|
+
when 404
|
18
|
+
raise Error, "Error 404, Page not found, #{response_error(response, params)}"
|
19
|
+
when 422
|
20
|
+
json = JSON.parse response.body
|
21
|
+
|
22
|
+
diagnostic = json["issue"][0]["diagnostics"]
|
23
|
+
|
24
|
+
raise Error, "Error 422, Unprocessable Entity, Diagnostic: '#{diagnostic}', #{response_error(response, params)}"
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
def response_error(response, params)
|
30
|
+
"App Client, #{super(response, params)}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def bearer
|
34
|
+
LifenFhir.configuration.application_access_token
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module LifenFhir
|
2
|
+
|
3
|
+
class Attachment < Base
|
4
|
+
|
5
|
+
attribute :title, String
|
6
|
+
attribute :path, String
|
7
|
+
attribute :content_type, String
|
8
|
+
|
9
|
+
def fhir_payload
|
10
|
+
{
|
11
|
+
contentAttachment: {
|
12
|
+
data: base_64_encoded_content,
|
13
|
+
title: title,
|
14
|
+
contentType: "{#{content_type}}"
|
15
|
+
}
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def base_64_encoded_content
|
22
|
+
Base64.encode64(File.open(path, "rb").read)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module LifenFhir
|
2
|
+
class Binary < Base
|
3
|
+
|
4
|
+
attribute :uuid, String
|
5
|
+
|
6
|
+
def fhir_payload
|
7
|
+
{
|
8
|
+
contentReference: {
|
9
|
+
reference: reference
|
10
|
+
}
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
def download
|
15
|
+
application_client.get("fhir/#{reference}", { accept: "application/pdf" })
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def application_client
|
21
|
+
@application_client ||= AppAuthenticatedClient.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def reference
|
25
|
+
"Binary/#{uuid}"
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module LifenFhir
|
2
|
+
class Category < Base
|
3
|
+
|
4
|
+
CODES = ["MEDICAL_REPORT", "MESSAGE", "MEDICATION_ORDER", "REFERRAL_REQUEST", "OTHER"]
|
5
|
+
|
6
|
+
attribute :code, String, default: "MEDICAL_REPORT"
|
7
|
+
|
8
|
+
def fhir_payload
|
9
|
+
raise LifenFhir::Error, "Invalid category: code must be in the authorized values" if !valid?
|
10
|
+
|
11
|
+
{
|
12
|
+
coding: [
|
13
|
+
{
|
14
|
+
system: "http://honestica.com/fhir/communication/category",
|
15
|
+
code: code
|
16
|
+
}
|
17
|
+
]
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
def valid?
|
22
|
+
CODES.include? code
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module LifenFhir
|
2
|
+
class Channel < Base
|
3
|
+
|
4
|
+
attribute :uuid, String
|
5
|
+
attribute :type, String
|
6
|
+
attribute :value, String
|
7
|
+
|
8
|
+
def fhir_payload(user)
|
9
|
+
raise LifenFhir::Error, "Invalid channel: an UUID is required" if !valid?
|
10
|
+
|
11
|
+
{
|
12
|
+
id: user.uuid,
|
13
|
+
resourceType: "Practitioner",
|
14
|
+
type => [
|
15
|
+
{
|
16
|
+
id: uuid
|
17
|
+
}
|
18
|
+
]
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def valid?
|
23
|
+
uuid and uuid.length != 0
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.from_json(json, type = nil)
|
27
|
+
new(uuid: json["id"], type: type, value: json["value"] || "#{Array(json["line"]).join(", ")}, #{json["postalCode"]} #{json["city"]}")
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
module LifenFhir
|
2
|
+
class Client
|
3
|
+
|
4
|
+
def request(mode, url, params = {})
|
5
|
+
before_request
|
6
|
+
|
7
|
+
response = faraday_client.send(mode) do |req|
|
8
|
+
req.url url
|
9
|
+
|
10
|
+
req.headers['Authorization'] = "Bearer #{bearer}"
|
11
|
+
req.headers['Accept'] = use_and_remove_accept(params)
|
12
|
+
|
13
|
+
if mode == :post
|
14
|
+
req.headers['Content-Type'] = "application/json"
|
15
|
+
end
|
16
|
+
|
17
|
+
req.body = JSON.generate(params)
|
18
|
+
end
|
19
|
+
|
20
|
+
handle_errors(response, params)
|
21
|
+
|
22
|
+
handle_response(response)
|
23
|
+
end
|
24
|
+
|
25
|
+
def post(url, params = {})
|
26
|
+
request(:post, url, params)
|
27
|
+
end
|
28
|
+
|
29
|
+
def put(url, params = {})
|
30
|
+
request(:put, url, params)
|
31
|
+
end
|
32
|
+
|
33
|
+
def get(url, params = {})
|
34
|
+
request(:get, url, params)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def handle_errors(response, params)
|
40
|
+
if response.status == 500
|
41
|
+
|
42
|
+
json = JSON.parse response.body
|
43
|
+
|
44
|
+
trace_id = json.fetch("X-B3-TraceId", "unknown")
|
45
|
+
|
46
|
+
raise Error, "Error 500, Internal server error (trace ID: #{trace_id}), #{response_error(response, params)}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def handle_response(response)
|
51
|
+
if response.headers['Content-Type'].match "json"
|
52
|
+
JSON.parse response.body
|
53
|
+
else
|
54
|
+
response.body
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def faraday_client
|
59
|
+
@faraday_client ||= Faraday.new(faraday_options) do |faraday|
|
60
|
+
faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def faraday_options
|
65
|
+
options = {url: site}
|
66
|
+
|
67
|
+
options[:proxy] = proxy_url if !proxy_url.nil?
|
68
|
+
|
69
|
+
options
|
70
|
+
end
|
71
|
+
|
72
|
+
def site
|
73
|
+
LifenFhir.configuration.site
|
74
|
+
end
|
75
|
+
|
76
|
+
def proxy_url
|
77
|
+
LifenFhir.configuration.proxy_url
|
78
|
+
end
|
79
|
+
|
80
|
+
def before_request
|
81
|
+
end
|
82
|
+
|
83
|
+
def response_error(response, params)
|
84
|
+
params[:payload] = "filtered" if params.is_a?(Hash) and params.has_key? :payload
|
85
|
+
|
86
|
+
"#{response.env.method.upcase} '#{response.env.url}' with params '#{params.inspect}' and bearer '#{trucanted_bearer}'"
|
87
|
+
end
|
88
|
+
|
89
|
+
def trucanted_bearer
|
90
|
+
if m = /^(.{24})(.*)$/.match(bearer)
|
91
|
+
"#{m[1]}#{"*" * m[2].length}"
|
92
|
+
else
|
93
|
+
bearer
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def bearer
|
98
|
+
raise "A bearer method must be defined"
|
99
|
+
end
|
100
|
+
|
101
|
+
def use_and_remove_accept(params)
|
102
|
+
return params.delete :accept if params.is_a?(Hash) and params.has_key? :accept
|
103
|
+
|
104
|
+
"application/json"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module LifenFhir
|
2
|
+
class CommunicationRequest < Base
|
3
|
+
|
4
|
+
attribute :uuid, String
|
5
|
+
attribute :number_communications, Integer
|
6
|
+
|
7
|
+
attribute :sender, LifenFhir::Practitioner
|
8
|
+
attribute :recipients, [LifenFhir::Practitioner]
|
9
|
+
|
10
|
+
attribute :category, LifenFhir::Category, default: LifenFhir::Category.new
|
11
|
+
attribute :medium, [LifenFhir::Medium]
|
12
|
+
attribute :patient, LifenFhir::Patient
|
13
|
+
attribute :attachment, LifenFhir::Attachment
|
14
|
+
attribute :binary, LifenFhir::Binary
|
15
|
+
attribute :content_string, LifenFhir::ContentString
|
16
|
+
|
17
|
+
def send
|
18
|
+
json = application_client.post("fhir/CommunicationRequest", fhir_payload)
|
19
|
+
|
20
|
+
self.uuid = json["id"]
|
21
|
+
self.number_communications = Array(json["issue"]).length
|
22
|
+
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def fhir_payload
|
29
|
+
|
30
|
+
payload = {
|
31
|
+
resourceType: "CommunicationRequest",
|
32
|
+
sender: [ sender.fhir_payload ],
|
33
|
+
recipient: recipients.map(&:fhir_payload),
|
34
|
+
contained: [],
|
35
|
+
medium: medium.map(&:fhir_payload) ,
|
36
|
+
category: [ category.fhir_payload],
|
37
|
+
payload: [ document_content ]
|
38
|
+
}
|
39
|
+
|
40
|
+
if patient
|
41
|
+
payload[:contained] << patient.fhir_payload
|
42
|
+
payload[:subject] = [
|
43
|
+
{reference: "patient"}
|
44
|
+
]
|
45
|
+
end
|
46
|
+
|
47
|
+
if content_string
|
48
|
+
payload[:payload] << content_string.fhir_payload
|
49
|
+
end
|
50
|
+
|
51
|
+
payload
|
52
|
+
end
|
53
|
+
|
54
|
+
def document_content
|
55
|
+
if !attachment.nil?
|
56
|
+
attachment.fhir_payload
|
57
|
+
else
|
58
|
+
binary.fhir_payload
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def application_client
|
63
|
+
@application_client ||= AppAuthenticatedClient.new
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module LifenFhir
|
2
|
+
class Configuration
|
3
|
+
|
4
|
+
attr_accessor :site, :application_access_token, :proxy_url
|
5
|
+
|
6
|
+
def site=(url)
|
7
|
+
if !/(.*)\/$/.match(url)
|
8
|
+
raise LifenFhir::Error, "Invalid 'site' provided in configuration: '#{url}', a trailing slash is missing"
|
9
|
+
end
|
10
|
+
|
11
|
+
@site = url
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.configuration
|
16
|
+
@configuration ||= Configuration.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.configure
|
20
|
+
yield(configuration) if block_given?
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module LifenFhir
|
2
|
+
|
3
|
+
class Error < StandardError
|
4
|
+
end
|
5
|
+
|
6
|
+
class UnauthorizedError < Error
|
7
|
+
end
|
8
|
+
|
9
|
+
class InvalidCredentialsError < Error
|
10
|
+
end
|
11
|
+
|
12
|
+
class InvalidParamsError < Error
|
13
|
+
end
|
14
|
+
|
15
|
+
class InvalidSecretTokenError < Error
|
16
|
+
end
|
17
|
+
|
18
|
+
class InvalidTokenError < Error
|
19
|
+
end
|
20
|
+
|
21
|
+
class UserAlreadyExistingError < Error
|
22
|
+
end
|
23
|
+
|
24
|
+
class CantRefreshTokenError < Error
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|