mirah-ruby 0.1.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.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +93 -0
  3. data/.gitignore +14 -0
  4. data/.overcommit.yml +48 -0
  5. data/.overcommit_gems.rb +9 -0
  6. data/.rspec +3 -0
  7. data/.rubocop.yml +54 -0
  8. data/.yardopts +1 -0
  9. data/CODE_OF_CONDUCT.md +74 -0
  10. data/Gemfile +6 -0
  11. data/LICENSE.txt +21 -0
  12. data/README.md +187 -0
  13. data/Rakefile +24 -0
  14. data/bin/autocorrect +28 -0
  15. data/bin/console +14 -0
  16. data/bin/setup +8 -0
  17. data/bin/setup_overcommit +12 -0
  18. data/lib/mirah.rb +44 -0
  19. data/lib/mirah/base_input_object.rb +65 -0
  20. data/lib/mirah/base_object.rb +98 -0
  21. data/lib/mirah/client.rb +420 -0
  22. data/lib/mirah/collection.rb +98 -0
  23. data/lib/mirah/data/appointment.rb +65 -0
  24. data/lib/mirah/data/organization.rb +31 -0
  25. data/lib/mirah/data/page_info.rb +40 -0
  26. data/lib/mirah/data/patient.rb +46 -0
  27. data/lib/mirah/data/practitioner.rb +53 -0
  28. data/lib/mirah/errors.rb +39 -0
  29. data/lib/mirah/filters.rb +7 -0
  30. data/lib/mirah/filters/appointment_filters.rb +16 -0
  31. data/lib/mirah/filters/organization_filters.rb +16 -0
  32. data/lib/mirah/filters/paging.rb +33 -0
  33. data/lib/mirah/filters/patient_filters.rb +16 -0
  34. data/lib/mirah/filters/practitioner_filters.rb +16 -0
  35. data/lib/mirah/graphql.rb +33 -0
  36. data/lib/mirah/graphql/fragments.rb +97 -0
  37. data/lib/mirah/graphql/mutations.rb +72 -0
  38. data/lib/mirah/graphql/queries.rb +196 -0
  39. data/lib/mirah/inputs.rb +7 -0
  40. data/lib/mirah/inputs/appointment_input.rb +40 -0
  41. data/lib/mirah/inputs/organization_input.rb +20 -0
  42. data/lib/mirah/inputs/patient_input.rb +40 -0
  43. data/lib/mirah/inputs/practitioner_input.rb +44 -0
  44. data/lib/mirah/push_result.rb +40 -0
  45. data/lib/mirah/serializers.rb +57 -0
  46. data/lib/mirah/version.rb +5 -0
  47. data/mirah-ruby.gemspec +41 -0
  48. data/schema.json +8936 -0
  49. metadata +221 -0
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mirah
4
+ # Collections represent a pageable view into a given collection. They automatically let you iterate through
5
+ # record sets in a stable manner.
6
+ #
7
+ # @example Iterate through a collection of multiple pages
8
+ # while(collection.next_page?)
9
+ # collection = collection.next_page
10
+ # collection.records.each do |record|
11
+ # # process record
12
+ # end
13
+ # end
14
+ class Collection
15
+ def initialize(results:, page_info:, client:, query:)
16
+ @results = results
17
+ @page_info = page_info
18
+ @client = client
19
+ @query = query
20
+ end
21
+
22
+ # The Mirah client, used for sending additional paged requests.
23
+ attr_reader :client
24
+
25
+ # The current results of the query
26
+ attr_reader :results
27
+
28
+ # The information on the current page as returned by the server
29
+ attr_reader :page_info
30
+
31
+ # The current set of paging parameters
32
+ attr_reader :paging
33
+
34
+ # The original query, stored to allow us to retrigger a query with a new page.
35
+ attr_reader :query
36
+
37
+ def length
38
+ results&.length
39
+ end
40
+
41
+ def next_page?
42
+ page_info.next_page?
43
+ end
44
+
45
+ def prev_page?
46
+ page_info.prev_page?
47
+ end
48
+
49
+ def refresh_with_new_paging(paging)
50
+ # Update everything as before, but set the new paging.
51
+ client.query_connection(
52
+ query[:query],
53
+ query[:input],
54
+ paging,
55
+ query[:data_klass],
56
+ query[:path]
57
+ )
58
+ end
59
+
60
+ def next_page
61
+ raise Errors::InvalidPage, 'This collection does not have a next page' unless next_page?
62
+
63
+ return @next_page if @next_page
64
+
65
+ @next_page = refresh_with_new_paging(next_page_params)
66
+ end
67
+
68
+ def prev_page
69
+ raise Errors::InvalidPage, 'This collection does not have a previous page' unless prev_page?
70
+
71
+ return @prev_page if @prev_page
72
+
73
+ @prev_page = refresh_with_new_paging(prev_page_params)
74
+ end
75
+
76
+ private
77
+
78
+ def next_page_params
79
+ last = query[:paging]
80
+ Filters::Paging.new(
81
+ after: page_info.end_cursor,
82
+ before: nil,
83
+ first: last.first || last.last,
84
+ last: nil
85
+ )
86
+ end
87
+
88
+ def prev_page_params
89
+ last = query[:paging]
90
+ Filters::Paging.new(
91
+ before: page_info.start_cursor,
92
+ after: nil,
93
+ last: last.last || last.first,
94
+ first: nil
95
+ )
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mirah
4
+ module Data
5
+ # Appointments represent a planned or past meeting between a patient and a practitioner. This is based
6
+ # on https://www.hl7.org/fhir/appointment.html
7
+ # As part of the integration flow, Mirah will work out whether this appointments needs an accompanying measurement
8
+ # encounter and automatically create one as appropriate. Mirah's ETL will generally make a best effort to estimate
9
+ # where and what context the measurement should be taken. The more information (Episode of Care, Organization,
10
+ # etc) that you supply, the more likely it is to be correct.
11
+ # Note that as part of this processing, Mirah may immediately choose to create assessments and trigger
12
+ # communications with the patient or other participants, for example by text message or email.
13
+ # In order to keep adherence statistics up to date, Mirah also requires that updates on past
14
+ # appointments are sent, so that we can calculate whether e.g. the appointment was a no-show.
15
+ class Appointment < BaseObject
16
+ # @!attribute [r] id
17
+ # @return [string] The internal Mirah identifier
18
+ attribute :id
19
+
20
+ # @!attribute [r] external_id
21
+ # @return [string] The identifier provided by your system
22
+ attribute :external_id
23
+
24
+ # @!attribute [r] start_date
25
+ # @return [Date] The appointment start date
26
+ attribute :start_date, serializer: Serializers::DateTimeSerializer
27
+
28
+ # @!attribute [r] end_date
29
+ # @return [Date] The appointment end date
30
+ attribute :end_date, serializer: Serializers::DateTimeSerializer
31
+
32
+ # @!attribute [r] minutes_duration
33
+ # @return [Integer] The legnth of this appointment in minutes
34
+ attribute :minutes_duration
35
+
36
+ # @!attribute [r] status
37
+ # @return [string] The appointment status
38
+ attribute :status
39
+
40
+ # @!attribute [r] patient_id
41
+ # @return [string] The internal mirah id of the patient
42
+ attribute :patient_id, path: %w[patient], target: 'id'
43
+
44
+ # @!attribute [r] external_patient_id
45
+ # @return [string] Your system identifier for the patient
46
+ attribute :external_patient_id, path: %w[patient], target: 'externalId'
47
+
48
+ # @!attribute [r] practitioner_id
49
+ # @return [string] The internal mirah id of the practitioner this appointment is with
50
+ attribute :practitioner_id, path: %w[practitioner], target: 'id'
51
+
52
+ # @!attribute [r] external_practitioner_id
53
+ # @return [string] Your system identifier for the practitioner this appointment is with
54
+ attribute :external_practitioner_id, path: %w[practitioner], target: 'externalId'
55
+
56
+ # @!attribute [r] organization_id
57
+ # @return [string] The internal mirah id of the organization this appointment is with
58
+ attribute :organization_id, path: %w[organization], target: 'id'
59
+
60
+ # @!attribute [r] external_organization_id
61
+ # @return [string] Your system identifier for the organization this appointment is with
62
+ attribute :external_organization_id, path: %w[organization], target: 'externalId'
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mirah
4
+ module Data
5
+ # Organizations in the Mirah system currently represent a hierarchy of units/facilities
6
+ # requiring either different treatment configurations (e.g. inpatient facilities require different
7
+ # measurement protocols to outpatient) or useful for the purpose of analytics. It is roughly based on
8
+ # https://www.hl7.org/fhir/organization.html
9
+ class Organization < BaseObject
10
+ # @!attribute [r] id
11
+ # @return [string] The internal Mirah identifier
12
+ attribute :id
13
+
14
+ # @!attribute [r] external_id
15
+ # @return [string] The identifier provided by your system
16
+ attribute :external_id
17
+
18
+ # @!attribute [r] name
19
+ # @return [string] The organization's name
20
+ attribute :name
21
+
22
+ # @!attribute [r] part_of_id
23
+ # @return [string] The internal mirah id of the organization this organization is a child of
24
+ attribute :part_of_id, path: %w[partOf], target: 'id'
25
+
26
+ # @!attribute [r] external_part_of_id
27
+ # @return [string] Your system identifier for the organization this organization is a child of
28
+ attribute :external_part_of_id, path: %w[partOf], target: 'externalId'
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mirah
4
+ module Data
5
+ # PageInfo gives information on the current state of paging as returned by the server. This includes information
6
+ # about the start and the end cursors of the result set, and whether or not there are additiona pages.
7
+ # This can be used in combination with {Mirah::Filters::Paging} to make a stable cursor-based pagination call.
8
+ class PageInfo < BaseObject
9
+ # @!attribute [r] end_cursor
10
+ # @return [string] The cursor of the last record of the current set.
11
+ # This can be used as a starting point for the next page of the query.
12
+ attribute :end_cursor
13
+
14
+ # @!attribute [r] start_cursor
15
+ # @return [string] The cursor of the first record of the current set.
16
+ # This can be used to get the previous page.
17
+ attribute :start_cursor
18
+
19
+ # @!attribute [r] has_next_page
20
+ # @return [Boolean] Whether the data set has a next page
21
+ attribute :has_next_page
22
+
23
+ # @!attribute [r] has_previous_page
24
+ # @return [Boolean] Whether the data set has a next page
25
+ attribute :has_previous_page
26
+
27
+ # @see has_next_page
28
+ # @return [Boolean]
29
+ def next_page?
30
+ has_next_page
31
+ end
32
+
33
+ # @see has_previous_page
34
+ # @return [Boolean]
35
+ def prev_page?
36
+ has_previous_page
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mirah
4
+ module Data
5
+ # Patients represent people who are in treatment. They can have appointments, and be the target of assessments.
6
+ # Patients are only treated in the context of an episode of care.
7
+ class Patient < BaseObject
8
+ # @!attribute [r] id
9
+ # @return [string] The internal Mirah identifier
10
+ attribute :id
11
+
12
+ # @!attribute [r] external_id
13
+ # @return [string] The identifier provided by your system
14
+ attribute :external_id
15
+
16
+ # @!attribute [r] given_name
17
+ # @return [string] The patient's first or given name
18
+ attribute :given_name
19
+
20
+ # @!attribute [r] family_name
21
+ # @return [string] The patient's last or family name
22
+ attribute :family_name
23
+
24
+ # @!attribute [r] birth_date
25
+ # @return [Date] The patient's date of birth.
26
+ attribute :birth_date, serializer: Serializers::DateSerializer
27
+
28
+ # @!attribute [r] gender
29
+ # @return [string] The patient's gender
30
+ attribute :gender
31
+
32
+ # @!attribute [r] primary_language
33
+ # @return [string] The patient's primary language
34
+ attribute :primary_language
35
+
36
+ # @!attribute [r] email
37
+ # @return [string] The patient's primary email address
38
+ attribute :email
39
+
40
+ # @!attribute [r] phone_number
41
+ # @return [string] The patient's primary phone number that is suitable for receiving text messages.
42
+ # Please do not use a phone number which corresponds to a landline as text messages will not be received.
43
+ attribute :phone_number
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mirah
4
+ module Data
5
+ # FHIR Practitioners represent people directly involved in the provision of care.
6
+ # See https://www.hl7.org/fhir/practitioner.html for more details.
7
+ class Practitioner < BaseObject
8
+ # @!attribute [r] id
9
+ # @return [string] The internal Mirah identifier
10
+ attribute :id
11
+
12
+ # @!attribute [r] external_id
13
+ # @return [string] The identifier provided by your system
14
+ attribute :external_id
15
+
16
+ # @!attribute [r] given_name
17
+ # @return [string] The practitioner's first or given name
18
+ attribute :given_name
19
+
20
+ # @!attribute [r] family_name
21
+ # @return [string] The practitioner's last or family name
22
+ attribute :family_name
23
+
24
+ # @!attribute [r] title
25
+ # @return [string] The practitioner's title, e.g. 'Dr'
26
+ attribute :title
27
+
28
+ # @!attribute [r] suffix
29
+ # @return [string] The practitioner's suffix, e.g. 'MD'
30
+ attribute :suffix
31
+
32
+ # @!attribute [r] email
33
+ # @return [string] The practitioner's primary email address
34
+ attribute :email
35
+
36
+ # @!attribute [r] default_practitioner_role
37
+ # @return [string] The clinical role for this practitioner
38
+ attribute :default_practitioner_role
39
+
40
+ # @!attribute [r] sso_username
41
+ # @return [string] The username (nameid) used for single sign on by this practitioner.
42
+ attribute :sso_username
43
+
44
+ # @!attribute [r] organization_ids
45
+ # @return [Array<string>] The internal mirah organization ids this practitioner has a role in
46
+ attribute :organization_ids, path: %w[organization], target: 'id'
47
+
48
+ # @!attribute [r] external_organization_ids
49
+ # @return [Array<string>] The identifiers from your system of the organizations this practitioner has a role in
50
+ attribute :external_organization_ids, path: %w[organizations], target: 'externalId'
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mirah
4
+ # A top level error from the Mirah system. It is implemented in multiple places with a
5
+ class Error < StandardError; end
6
+
7
+ module Errors
8
+ # This exception is thrown when the credentials you have specified for the service are invalid.
9
+ class InvalidCredentials < Error; end
10
+
11
+ # This exception is thrown when an unknown error occurs on the server side.
12
+ class ServerError < Error; end
13
+
14
+ # This exception is thrown when an error happens in this process rather than on the server side.
15
+ class ClientError < Error; end
16
+
17
+ # A parameter you supplied as an input was not valid for the query.
18
+ # An error class that shows the record was invalid
19
+ class InvalidParameter < Error
20
+ def initialize(param)
21
+ @param = param
22
+ end
23
+
24
+ attr_reader :param
25
+ end
26
+
27
+ # A required parameter was not passed in
28
+ class MissingParameter < Error
29
+ def initialize(param)
30
+ @param = param
31
+ end
32
+
33
+ attr_reader :param
34
+ end
35
+
36
+ # You attempted to fetch a page that was not valid - you probably called `next_page` on the end of the collection.
37
+ class InvalidPage < Error; end
38
+ end
39
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mirah
4
+ # These filters represent ways of querying data. Each endpoint has a set of filters that you can apply.
5
+ module Filters
6
+ end
7
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mirah
4
+ module Filters
5
+ # Input parameters and filters for queries returning {Data::Appointment} objects.
6
+ class AppointmentFilters < BaseObject
7
+ # @!attribute [r] external_id
8
+ # @return [Array<string>] An array of external identifiers to match.
9
+ attribute :external_id
10
+
11
+ # @!attribute [r] status
12
+ # @return [string] The appointment status
13
+ attribute :status
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mirah
4
+ module Filters
5
+ # Input parameters and filters for queries returning {Data::Organization} objects.
6
+ class OrganizationFilters < BaseObject
7
+ # @!attribute [r] external_id
8
+ # @return [Array<string>] An array of external identifiers to match.
9
+ attribute :external_id
10
+
11
+ # @!attribute [r] search
12
+ # @return [string] Smart search by name and other fields where appropriate
13
+ attribute :search
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mirah
4
+ module Filters
5
+ # A set of input parameters designed to let you select how many and which records you want from a pagination cursor.
6
+ # It is based on Graphql's Relay specification.
7
+ # This can be used with {Data::PageInfo}, which will be provided by the results of a server query, to provide
8
+ # stable pagination framework.
9
+ class Paging < BaseObject
10
+ # @!attribute [r] first
11
+ # @return [string] Return the first N rows from either the start, or the current cursor position.
12
+ # Cannot be used at the same time as #last
13
+ attribute :first
14
+
15
+ # @!attribute [r] last
16
+ # @return [string] Return the last N rows from either the end, or the current cursor position.
17
+ # Cannot be used at the same time as #first
18
+ attribute :last
19
+
20
+ # @!attribute [r] before
21
+ # @return [string] Return rows before the given cursor position
22
+ attribute :before
23
+
24
+ # @!attribute [r] after
25
+ # @return [string] Return rows after the given cursor position
26
+ attribute :after
27
+
28
+ def self.default
29
+ new(first: 100)
30
+ end
31
+ end
32
+ end
33
+ end