dde_client 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.
- checksums.yaml +7 -0
- data/README.md +37 -0
- data/Rakefile +12 -0
- data/app/assets/config/dde_client_manifest.js +1 -0
- data/app/assets/stylesheets/dde_client/application.css +15 -0
- data/app/controllers/dde_client/api/v1/dde_controller.rb +92 -0
- data/app/controllers/dde_client/api/v1/rollback_controller.rb +25 -0
- data/app/controllers/dde_client/application_controller.rb +4 -0
- data/app/helpers/dde/application_helper.rb +4 -0
- data/app/jobs/dde/application_job.rb +4 -0
- data/app/mailers/dde/application_mailer.rb +6 -0
- data/app/models/dde/application_record.rb +5 -0
- data/app/services/dde_client/dde_client.rb +162 -0
- data/app/services/dde_client/dde_service.rb +643 -0
- data/app/services/dde_client/matcher.rb +92 -0
- data/app/services/dde_client/merging_service.rb +769 -0
- data/app/services/dde_client/rollback_service.rb +320 -0
- data/app/services/merge_audit_service.rb +56 -0
- data/app/utils/model_utils.rb +62 -0
- data/app/views/layouts/dde/application.html.erb +15 -0
- data/config/routes.rb +14 -0
- data/lib/dde_client/client_error.rb +3 -0
- data/lib/dde_client/engine.rb +5 -0
- data/lib/dde_client/version.rb +5 -0
- data/lib/dde_client.rb +9 -0
- metadata +100 -0
@@ -0,0 +1,320 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# this class will basically handle rolling back patients that were merged
|
4
|
+
# rubocop:disable Metrics/ClassLength
|
5
|
+
class DdeClient::RollbackService
|
6
|
+
attr_accessor :primary_patient, :secondary_patient, :merge_type, :visit_type
|
7
|
+
|
8
|
+
Dde_CONFIG_PATH = 'config/application.yml'
|
9
|
+
|
10
|
+
# rubocop:disable Metrics/MethodLength
|
11
|
+
def rollback_merged_patient(patient_id, visit_type_id)
|
12
|
+
@visit_type = VisitType.find(visit_type_id)
|
13
|
+
tree = DdeClient::MergeAuditService.new.fetch_merge_audit(patient_id)
|
14
|
+
ActiveRecord::Base.transaction do
|
15
|
+
tree.each do |record|
|
16
|
+
@primary_patient = record['primary_id']
|
17
|
+
@secondary_patient = record['secondary_id']
|
18
|
+
@merge_type = record['merge_type']
|
19
|
+
Rails.logger.debug("Processing rollback for patients: #{primary_patient} <=> #{secondary_patient}")
|
20
|
+
process_rollback
|
21
|
+
MergeAudit.find(record['id']).void("Rolling back to #{secondary_patient}")
|
22
|
+
@common_void_reason = nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
Patient.find(patient_id)
|
26
|
+
end
|
27
|
+
# rubocop:enable Metrics/MethodLength
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def process_rollback
|
32
|
+
rollback_dde
|
33
|
+
rollback_patient
|
34
|
+
rollback_encounter
|
35
|
+
rollback_order
|
36
|
+
rollback_observation
|
37
|
+
rollback_address
|
38
|
+
rollback_attributes
|
39
|
+
rollback_identifiers
|
40
|
+
rollback_remote_identifiers
|
41
|
+
rollback_name
|
42
|
+
end
|
43
|
+
|
44
|
+
# fetch patient doc id
|
45
|
+
def fetch_patient_doc_id(patient_id)
|
46
|
+
result = ActiveRecord::Base.connection.select_one <<~SQL
|
47
|
+
SELECT identifier
|
48
|
+
FROM patient_identifier
|
49
|
+
WHERE patient_id = #{patient_id}
|
50
|
+
AND identifier_type = #{PatientIdentifierType.find_by_name!('Dde person document ID').id}
|
51
|
+
SQL
|
52
|
+
result.blank? ? nil : result['identifier']
|
53
|
+
end
|
54
|
+
|
55
|
+
def rollback_dde
|
56
|
+
return unless merge_type.match(/remote/i)
|
57
|
+
|
58
|
+
response, status = dde_client.post('rollback_merge',
|
59
|
+
primary_person_doc_id: fetch_patient_doc_id(primary_patient),
|
60
|
+
secondary_person_doc_id: fetch_patient_doc_id(secondary_patient))
|
61
|
+
|
62
|
+
raise "Failed to rollback patients on Dde side: #{status} - #{response}" unless status == 200
|
63
|
+
end
|
64
|
+
|
65
|
+
# this is the method to rollback patient name
|
66
|
+
def rollback_name
|
67
|
+
result = ActiveRecord::Base.connection.select_all <<~SQL
|
68
|
+
SELECT * FROM person_name
|
69
|
+
WHERE voided = 1
|
70
|
+
AND person_id = #{secondary_patient}
|
71
|
+
AND void_reason LIKE 'Merged into patient ##{primary_patient}:%'
|
72
|
+
SQL
|
73
|
+
process_name(voided_names: result)
|
74
|
+
ActiveRecord::Base.connection.execute <<~SQL
|
75
|
+
UPDATE person_name SET #{common_void_columns} #{extra_fields} WHERE person_id = #{common_void_reason}
|
76
|
+
SQL
|
77
|
+
end
|
78
|
+
|
79
|
+
def rollback_identifiers
|
80
|
+
result = ActiveRecord::Base.connection.select_all <<~SQL
|
81
|
+
SELECT * FROM patient_identifier
|
82
|
+
WHERE patient_id = #{secondary_patient} AND voided = 1
|
83
|
+
AND void_reason LIKE 'Merged into patient ##{primary_patient}:%'
|
84
|
+
SQL
|
85
|
+
process_identifiers(voided_identifiers: result)
|
86
|
+
ActiveRecord::Base.connection.execute <<~SQL
|
87
|
+
UPDATE patient_identifier SET #{common_void_columns} WHERE patient_id = #{common_void_reason}
|
88
|
+
SQL
|
89
|
+
end
|
90
|
+
|
91
|
+
def rollback_remote_identifiers
|
92
|
+
return unless merge_type.match(/remote/i)
|
93
|
+
|
94
|
+
ActiveRecord::Base.connection.execute <<~SQL
|
95
|
+
UPDATE patient_identifier SET #{common_void_columns} WHERE patient_id = #{secondary_patient} AND void_reason = 'Assigned new id: #{fetch_patient_doc_id(primary_patient)}'
|
96
|
+
SQL
|
97
|
+
end
|
98
|
+
|
99
|
+
def rollback_attributes
|
100
|
+
result = ActiveRecord::Base.connection.select_all <<~SQL
|
101
|
+
SELECT * FROM person_attribute
|
102
|
+
WHERE person_id = #{secondary_patient} AND voided = 1
|
103
|
+
AND void_reason LIKE 'Merged into patient ##{primary_patient}:%'
|
104
|
+
SQL
|
105
|
+
process_attributes(voided_attributes: result)
|
106
|
+
ActiveRecord::Base.connection.execute <<~SQL
|
107
|
+
UPDATE person_attribute SET #{common_void_columns} #{extra_fields} WHERE person_id = #{common_void_reason}
|
108
|
+
SQL
|
109
|
+
end
|
110
|
+
|
111
|
+
def rollback_address
|
112
|
+
result = ActiveRecord::Base.connection.select_all <<~SQL
|
113
|
+
SELECT * FROM person_address
|
114
|
+
WHERE person_id = #{secondary_patient} AND voided = 1
|
115
|
+
AND void_reason LIKE 'Merged into patient ##{primary_patient}:%'
|
116
|
+
SQL
|
117
|
+
process_addresses(voided_addresses: result)
|
118
|
+
ActiveRecord::Base.connection.execute <<~SQL
|
119
|
+
UPDATE person_address SET #{common_void_columns} WHERE person_id = #{common_void_reason}
|
120
|
+
SQL
|
121
|
+
end
|
122
|
+
|
123
|
+
def rollback_encounter
|
124
|
+
result = ActiveRecord::Base.connection.select_all <<~SQL
|
125
|
+
SELECT * FROM encounter
|
126
|
+
WHERE patient_id = #{secondary_patient} AND voided = 1
|
127
|
+
AND void_reason LIKE 'Merged into patient ##{primary_patient}:%'
|
128
|
+
SQL
|
129
|
+
process_encounters(voided_encounters: result)
|
130
|
+
ActiveRecord::Base.connection.execute <<~SQL
|
131
|
+
UPDATE encounter SET #{common_void_columns} #{extra_fields} WHERE patient_id = #{common_void_reason}
|
132
|
+
SQL
|
133
|
+
end
|
134
|
+
|
135
|
+
def rollback_observation
|
136
|
+
result = ActiveRecord::Base.connection.select_all <<~SQL
|
137
|
+
SELECT * FROM obs
|
138
|
+
WHERE person_id = #{secondary_patient} AND voided = 1
|
139
|
+
AND void_reason LIKE 'Merged into patient ##{primary_patient}:%'
|
140
|
+
SQL
|
141
|
+
process_observations(voided_observations: result)
|
142
|
+
ActiveRecord::Base.connection.execute <<~SQL
|
143
|
+
UPDATE obs SET #{common_void_columns} WHERE person_id = #{common_void_reason}
|
144
|
+
SQL
|
145
|
+
end
|
146
|
+
|
147
|
+
def rollback_order
|
148
|
+
result = ActiveRecord::Base.connection.select_all <<~SQL
|
149
|
+
SELECT * FROM orders
|
150
|
+
WHERE patient_id = #{secondary_patient} AND voided = 1
|
151
|
+
AND void_reason LIKE 'Merged into patient ##{primary_patient}:%'
|
152
|
+
SQL
|
153
|
+
process_orders(voided_orders: result)
|
154
|
+
ActiveRecord::Base.connection.execute <<~SQL
|
155
|
+
UPDATE orders SET #{common_void_columns} WHERE patient_id = #{common_void_reason}
|
156
|
+
SQL
|
157
|
+
end
|
158
|
+
|
159
|
+
def rollback_patient
|
160
|
+
ActiveRecord::Base.connection.execute <<~SQL
|
161
|
+
UPDATE patient SET #{common_void_columns} #{extra_fields} WHERE patient_id = #{common_void_reason}
|
162
|
+
SQL
|
163
|
+
rollback_person
|
164
|
+
end
|
165
|
+
|
166
|
+
def rollback_person
|
167
|
+
ActiveRecord::Base.connection.execute <<~SQL
|
168
|
+
UPDATE person SET #{common_void_columns} #{extra_fields} WHERE person_id = #{common_void_reason}
|
169
|
+
SQL
|
170
|
+
rollback_patient_visit_type_and_state
|
171
|
+
rollback_relationship
|
172
|
+
end
|
173
|
+
|
174
|
+
def rollback_patient_visit_type_and_state
|
175
|
+
ActiveRecord::Base.connection.execute <<~SQL
|
176
|
+
UPDATE patient_state ps
|
177
|
+
INNER JOIN patient_visit_type pp ON ps.patient_visit_type_id = pp.patient_visit_type_id
|
178
|
+
SET ps.date_voided = NULL, ps.void_reason = NULL, ps.voided_by = NULL, ps.voided = 0, ps.date_changed = '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', ps.changed_by = #{User.current.id},
|
179
|
+
pp.date_voided = NULL, pp.void_reason = NULL, pp.voided_by = NULL, pp.voided = 0, pp.date_changed = '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', pp.changed_by = #{User.current.id}
|
180
|
+
WHERE pp.patient_id = #{secondary_patient}
|
181
|
+
AND ps.void_reason = 'Merged into patient ##{primary_patient}:0'
|
182
|
+
AND pp.void_reason = 'Merged into patient ##{primary_patient}:0'
|
183
|
+
SQL
|
184
|
+
end
|
185
|
+
|
186
|
+
def rollback_relationship
|
187
|
+
ActiveRecord::Base.connection.execute <<~SQL
|
188
|
+
UPDATE relationship SET #{common_void_columns} WHERE person_a = #{common_void_reason}
|
189
|
+
SQL
|
190
|
+
end
|
191
|
+
|
192
|
+
def process_name(voided_names: nil)
|
193
|
+
return if voided_names.blank?
|
194
|
+
|
195
|
+
voided_names.each do |name|
|
196
|
+
patient_id, row_id = process_patient_id_and_row_id(name['void_reason'])
|
197
|
+
record = PersonName.find_by(person_name_id: row_id, person_id: patient_id)
|
198
|
+
record&.void("Rollback to patient ##{name['person_id']}:#{name['person_name_id']}")
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def process_identifiers(voided_identifiers: nil)
|
203
|
+
return if voided_identifiers.blank?
|
204
|
+
|
205
|
+
voided_identifiers.each do |identifier|
|
206
|
+
patient_id, row_id = process_patient_id_and_row_id(identifier['void_reason'])
|
207
|
+
record = PatientIdentifier.find_by(patient_identifier_id: row_id, patient_id: patient_id)
|
208
|
+
record&.void("Rollback to patient ##{identifier['patient_id']}:#{identifier['patient_identifier_id']}")
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def process_attributes(voided_attributes: nil)
|
213
|
+
return if voided_attributes.blank?
|
214
|
+
|
215
|
+
voided_attributes.each do |attribute|
|
216
|
+
patient_id, row_id = process_patient_id_and_row_id(attribute['void_reason'])
|
217
|
+
record = PersonAttribute.find_by(person_attribute_id: row_id, person_id: patient_id)
|
218
|
+
record&.void("Rollback to patient ##{attribute['person_id']}:#{attribute['person_attribute_id']}")
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def process_addresses(voided_addresses: nil)
|
223
|
+
return if voided_addresses.blank?
|
224
|
+
|
225
|
+
voided_addresses.each do |address|
|
226
|
+
patient_id, row_id = process_patient_id_and_row_id(address['void_reason'])
|
227
|
+
record = PersonAddress.find_by(person_address_id: row_id, person_id: patient_id)
|
228
|
+
record&.void("Rollback to patient ##{address['person_id']}:#{address['person_address_id']}")
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def process_encounters(voided_encounters: nil)
|
233
|
+
return if voided_encounters.blank?
|
234
|
+
|
235
|
+
voided_encounters.each do |encounter|
|
236
|
+
patient_id, row_id = process_patient_id_and_row_id(encounter['void_reason'])
|
237
|
+
record = Encounter.find_by(encounter_id: row_id, patient_id: patient_id)
|
238
|
+
record&.void("Rollback to patient ##{encounter['patient_id']}:#{encounter['encounter_id']}")
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def process_observations(voided_observations: nil)
|
243
|
+
return if voided_observations.blank?
|
244
|
+
|
245
|
+
voided_observations.each do |obs|
|
246
|
+
patient_id, row_id = process_patient_id_and_row_id(obs['void_reason'])
|
247
|
+
record = Observation.find_by(obs_id: row_id, person_id: patient_id)
|
248
|
+
record&.void("Rollback to patient ##{obs['person_id']}:#{obs['obs_id']}")
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
def process_orders(voided_orders: nil)
|
253
|
+
return if voided_orders.blank?
|
254
|
+
|
255
|
+
voided_orders.each do |order|
|
256
|
+
patient_id, row_id = process_patient_id_and_row_id(order['void_reason'])
|
257
|
+
record = Order.find_by(order_id: row_id, patient_id: patient_id)
|
258
|
+
record&.void("Rollback to patient ##{order['patient_id']}:#{order['order_id']}")
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
def process_patient_id_and_row_id(reason)
|
263
|
+
reason.split('#')[1].split(':')
|
264
|
+
end
|
265
|
+
|
266
|
+
def remove_common_field(record)
|
267
|
+
record.delete('uuid')
|
268
|
+
record.delete('voided')
|
269
|
+
record.delete('voided_by')
|
270
|
+
record.delete('date_voided')
|
271
|
+
@reason = record.delete('void_reason')
|
272
|
+
record
|
273
|
+
end
|
274
|
+
|
275
|
+
def common_void_columns
|
276
|
+
@common_void_columns ||= 'date_voided = NULL, void_reason = NULL, voided_by = NULL, voided = 0'
|
277
|
+
end
|
278
|
+
|
279
|
+
def extra_fields
|
280
|
+
@extra_fields ||= ", date_changed = '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', changed_by = #{User.current.id}"
|
281
|
+
end
|
282
|
+
|
283
|
+
def common_void_reason
|
284
|
+
@common_void_reason ||= " #{secondary_patient} AND void_reason LIKE 'Merged into patient ##{primary_patient}:%'"
|
285
|
+
end
|
286
|
+
|
287
|
+
def dde_client
|
288
|
+
client = DdeClient.new
|
289
|
+
|
290
|
+
connection = dde_connections[visit_type.id]
|
291
|
+
|
292
|
+
dde_connections[visit_type.id] = if connection
|
293
|
+
client.restore_connection(connection)
|
294
|
+
else
|
295
|
+
client.connect(dde_config)
|
296
|
+
end
|
297
|
+
|
298
|
+
client
|
299
|
+
end
|
300
|
+
|
301
|
+
def dde_connections
|
302
|
+
@dde_connections ||= {}
|
303
|
+
end
|
304
|
+
|
305
|
+
# Loads a dde client into the dde_clients_cache for the
|
306
|
+
def dde_config
|
307
|
+
main_config = YAML.load_file(Dde_CONFIG_PATH)['dde']
|
308
|
+
raise 'No configuration for Dde found' unless main_config
|
309
|
+
|
310
|
+
visit_type_config = main_config[visit_type.name.downcase]
|
311
|
+
raise "No Dde config for visit_type #{visit_type.name} found" unless visit_type_config
|
312
|
+
|
313
|
+
{
|
314
|
+
url: main_config['url'],
|
315
|
+
username: visit_type_config['username'],
|
316
|
+
password: visit_type_config['password']
|
317
|
+
}
|
318
|
+
end
|
319
|
+
end
|
320
|
+
# rubocop:enable Metrics/ClassLength
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This service will handle merge audits with their tree structure
|
4
|
+
class MergeAuditService
|
5
|
+
# This method a merge audit for us
|
6
|
+
def create_merge_audit(primary_patient, secondary_patient, merge_type)
|
7
|
+
recent_merge_id = MergeAudit.where(primary_id: secondary_patient).last&.id
|
8
|
+
merge_audit = MergeAudit.create({ primary_id: primary_patient, secondary_id: secondary_patient,
|
9
|
+
creator: User.current.id, merge_type: merge_type,
|
10
|
+
secondary_previous_merge_id: recent_merge_id })
|
11
|
+
raise "Could not create audit trail due to #{merge_audit.errors.as_json}" unless merge_audit.errors.empty?
|
12
|
+
end
|
13
|
+
|
14
|
+
# this uses the patient identifier to get the audit tree
|
15
|
+
def get_patient_audit(identifier)
|
16
|
+
fetch_merge_audit(find_voided_identifier(identifier))
|
17
|
+
end
|
18
|
+
|
19
|
+
# this uses the patient id to get the audit tree and it is used by get patient_audit
|
20
|
+
def fetch_merge_audit(secondary)
|
21
|
+
first_merge = common_merge_fetch('ma.secondary_id', secondary)
|
22
|
+
raise NotFoundError, "There is no merge for #{secondary}" if first_merge.blank?
|
23
|
+
|
24
|
+
count = 0
|
25
|
+
tree = [first_merge.merge({ 'merge_number' => count += 1 })]
|
26
|
+
merge_id = MergeAudit.where(primary_id: first_merge['primary_id']).last&.id
|
27
|
+
until merge_id.blank?
|
28
|
+
parent = common_merge_fetch('ma.secondary_previous_merge_id', merge_id)
|
29
|
+
tree << parent.merge({ 'merge_number' => count += 1 }) unless parent.blank?
|
30
|
+
merge_id = parent.blank? ? nil : MergeAudit.where(primary_id: parent['primary_id']).last&.id
|
31
|
+
end
|
32
|
+
tree.reverse
|
33
|
+
end
|
34
|
+
|
35
|
+
def common_merge_fetch(field, fetch_value)
|
36
|
+
ActiveRecord::Base.connection.select_one <<~SQL
|
37
|
+
SELECT ma.id, ma.primary_id, ma.secondary_id, ma.created_at merge_date, ma.merge_type, pn.given_name primary_first_name, pn.family_name primary_surname, p.gender primary_gender, p.birthdate primary_birthdate,
|
38
|
+
spn.given_name secondary_first_name, spn.family_name secondary_surname, sp.gender secondary_gender, sp.birthdate secondary_birthdate
|
39
|
+
FROM merge_audits ma
|
40
|
+
INNER JOIN person_name pn ON pn.person_id = ma.primary_id
|
41
|
+
INNER JOIN person p ON p.person_id = ma.primary_id
|
42
|
+
INNER JOIN person_name spn ON spn.person_id = ma.secondary_id AND spn.voided = 1
|
43
|
+
INNER JOIN person sp ON sp.person_id = ma.secondary_id AND sp.voided = 1
|
44
|
+
WHERE #{field} = #{fetch_value} AND ma.voided = 0
|
45
|
+
SQL
|
46
|
+
end
|
47
|
+
|
48
|
+
def find_voided_identifier(identifier)
|
49
|
+
result = ActiveRecord::Base.connection.select_one <<~SQL
|
50
|
+
SELECT patient_id FROM patient_identifier WHERE identifier = '#{identifier}' AND identifier_type = 3 AND voided = 1 ORDER BY date_voided ASC
|
51
|
+
SQL
|
52
|
+
raise NotFoundError, "Failed to find voided identifier: #{identifier}" if result.blank?
|
53
|
+
|
54
|
+
result['patient_id']
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This module contains utility methods for retrieving models
|
4
|
+
module ModelUtils
|
5
|
+
# Retrieve concept by its name
|
6
|
+
#
|
7
|
+
# Parameters:
|
8
|
+
# name - A string repr of the concept name
|
9
|
+
def concept(name)
|
10
|
+
Concept.joins(:concept_names).where('concept_name.name = ?', name).first
|
11
|
+
end
|
12
|
+
|
13
|
+
def concept_name(name)
|
14
|
+
ConceptName.find_by(name: name)
|
15
|
+
end
|
16
|
+
|
17
|
+
def concept_name_to_id(name)
|
18
|
+
return nil if name.blank?
|
19
|
+
|
20
|
+
concept_name(name)&.concept_id
|
21
|
+
end
|
22
|
+
|
23
|
+
def concept_id_to_name(id)
|
24
|
+
return nil if id.blank?
|
25
|
+
|
26
|
+
concept = Concept.find_by_concept_id(id)
|
27
|
+
concept&.fullname
|
28
|
+
end
|
29
|
+
|
30
|
+
def visit_type(name)
|
31
|
+
VisitType.find_by_name(name)
|
32
|
+
end
|
33
|
+
|
34
|
+
def encounter_type(name)
|
35
|
+
EncounterType.find_by name: name
|
36
|
+
end
|
37
|
+
|
38
|
+
def global_property(name)
|
39
|
+
GlobalProperty.find_by property: name
|
40
|
+
end
|
41
|
+
|
42
|
+
def user_property(name, user_id: nil)
|
43
|
+
user_id ||= User.current.user_id
|
44
|
+
UserProperty.find_by(user_id: user_id, property: name)
|
45
|
+
end
|
46
|
+
|
47
|
+
def order_type(name)
|
48
|
+
OrderType.find_by_name(name)
|
49
|
+
end
|
50
|
+
|
51
|
+
def report_type(name)
|
52
|
+
ReportType.find_by_name(name)
|
53
|
+
end
|
54
|
+
|
55
|
+
def patient_identifier_type(name)
|
56
|
+
PatientIdentifierType.find_by_name(name)
|
57
|
+
end
|
58
|
+
|
59
|
+
def drug(name)
|
60
|
+
Drug.find_by_name(name)
|
61
|
+
end
|
62
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
DdeClient::Engine.routes.draw do
|
2
|
+
get '/patients/find_by_npid', to: 'api/v1/dde#find_patients_by_npid'
|
3
|
+
get '/patients/find_by_name_and_gender', to: 'api/v1/dde#find_patients_by_name_and_gender'
|
4
|
+
get '/patients/import_by_doc_id', to: 'api/v1/dde#import_patients_by_doc_id'
|
5
|
+
get '/patients/import_by_npid', to: 'api/v1/dde#import_patients_by_npid'
|
6
|
+
get '/patients/match_by_demographics', to: 'api/v1/dde#match_patients_by_demographics'
|
7
|
+
get '/patients/diff', to: 'api/v1/dde#patient_diff'
|
8
|
+
get '/patients/refresh', to: 'api/v1/dde#refresh_patient'
|
9
|
+
post '/patients/reassign_npid', to: 'api/v1/dde#reassign_patient_npid'
|
10
|
+
post '/patients/merge', to: 'api/v1/dde#merge_patients'
|
11
|
+
get '/patients/remaining_npids', to: 'api/v1/dde#remaining_npids'
|
12
|
+
get '/rollback/merge_history', to: 'rollback#merge_history'
|
13
|
+
post '/rollback/rollback_patient', to: 'rollback#rollback_patient'
|
14
|
+
end
|
data/lib/dde_client.rb
ADDED
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dde_client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- bryan-mw
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-07-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 7.0.8
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 7.0.8
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rest-client
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description:
|
42
|
+
email:
|
43
|
+
- brianmsyamboza@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- README.md
|
49
|
+
- Rakefile
|
50
|
+
- app/assets/config/dde_client_manifest.js
|
51
|
+
- app/assets/stylesheets/dde_client/application.css
|
52
|
+
- app/controllers/dde_client/api/v1/dde_controller.rb
|
53
|
+
- app/controllers/dde_client/api/v1/rollback_controller.rb
|
54
|
+
- app/controllers/dde_client/application_controller.rb
|
55
|
+
- app/helpers/dde/application_helper.rb
|
56
|
+
- app/jobs/dde/application_job.rb
|
57
|
+
- app/mailers/dde/application_mailer.rb
|
58
|
+
- app/models/dde/application_record.rb
|
59
|
+
- app/services/dde_client/dde_client.rb
|
60
|
+
- app/services/dde_client/dde_service.rb
|
61
|
+
- app/services/dde_client/matcher.rb
|
62
|
+
- app/services/dde_client/merging_service.rb
|
63
|
+
- app/services/dde_client/rollback_service.rb
|
64
|
+
- app/services/merge_audit_service.rb
|
65
|
+
- app/utils/model_utils.rb
|
66
|
+
- app/views/layouts/dde/application.html.erb
|
67
|
+
- config/routes.rb
|
68
|
+
- lib/dde_client.rb
|
69
|
+
- lib/dde_client/client_error.rb
|
70
|
+
- lib/dde_client/engine.rb
|
71
|
+
- lib/dde_client/version.rb
|
72
|
+
homepage: https://github.com/orgs/Malawi-Ministry-of-Health/dde_client
|
73
|
+
licenses:
|
74
|
+
- MIT
|
75
|
+
metadata:
|
76
|
+
homepage_uri: https://github.com/orgs/Malawi-Ministry-of-Health/dde_client
|
77
|
+
source_code_uri: https://github.com/orgs/Malawi-Ministry-of-Health/dde_client
|
78
|
+
changelog_uri: https://github.com/orgs/Malawi-Ministry-of-Health/dde_client/CHANGELOG.md
|
79
|
+
post_install_message:
|
80
|
+
rdoc_options: []
|
81
|
+
require_paths:
|
82
|
+
- lib
|
83
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
requirements: []
|
94
|
+
rubyforge_project:
|
95
|
+
rubygems_version: 2.7.6
|
96
|
+
signing_key:
|
97
|
+
specification_version: 4
|
98
|
+
summary: DDE stands for Demographics Data Exchange. Its main purpose is to manage
|
99
|
+
patient IDs.
|
100
|
+
test_files: []
|