pvdgm_services 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (256) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +29 -0
  3. data/Rakefile +40 -0
  4. data/app/contexts/services/accept_hl7_message_context.rb +32 -0
  5. data/app/contexts/services/application_mds_context.rb +21 -0
  6. data/app/contexts/services/complete_sltc_registration_process_context.rb +23 -0
  7. data/app/contexts/services/create_account_mapping_context.rb +23 -0
  8. data/app/contexts/services/create_configured_account_context.rb +26 -0
  9. data/app/contexts/services/create_configured_facility_context.rb +26 -0
  10. data/app/contexts/services/create_credential_context.rb +23 -0
  11. data/app/contexts/services/create_facility_mapping_context.rb +23 -0
  12. data/app/contexts/services/create_public_key_context.rb +22 -0
  13. data/app/contexts/services/create_service_context.rb +22 -0
  14. data/app/contexts/services/create_service_definition_context.rb +26 -0
  15. data/app/contexts/services/create_sltc_registration_context.rb +24 -0
  16. data/app/contexts/services/create_third_party_context.rb +22 -0
  17. data/app/contexts/services/hl7_message_trimming_context.rb +19 -0
  18. data/app/contexts/services/invoke_service_context.rb +21 -0
  19. data/app/contexts/services/list_sltc_providers_context.rb +22 -0
  20. data/app/contexts/services/mds_file_processing_context.rb +27 -0
  21. data/app/contexts/services/mds_file_upload_context.rb +25 -0
  22. data/app/contexts/services/mds_pull_context.rb +21 -0
  23. data/app/contexts/services/monthly_service_table_cleanup_context.rb +19 -0
  24. data/app/contexts/services/notify_new_registration_context.rb +22 -0
  25. data/app/contexts/services/notify_sltc_provider_change_context.rb +19 -0
  26. data/app/contexts/services/request_sltc_baseline_context.rb +23 -0
  27. data/app/contexts/services/update_account_mapping_context.rb +23 -0
  28. data/app/contexts/services/update_configured_account_context.rb +26 -0
  29. data/app/contexts/services/update_configured_facility_context.rb +26 -0
  30. data/app/contexts/services/update_credential_context.rb +23 -0
  31. data/app/contexts/services/update_facility_mapping_context.rb +23 -0
  32. data/app/contexts/services/update_public_key_context.rb +23 -0
  33. data/app/contexts/services/update_service_context.rb +23 -0
  34. data/app/contexts/services/update_service_definition_context.rb +26 -0
  35. data/app/contexts/services/update_third_party_context.rb +23 -0
  36. data/app/controllers/services/account_mappings_controller.rb +54 -0
  37. data/app/controllers/services/adts_controller.rb +35 -0
  38. data/app/controllers/services/application_controller.rb +17 -0
  39. data/app/controllers/services/assessment_requests_controller.rb +48 -0
  40. data/app/controllers/services/available_files_controller.rb +19 -0
  41. data/app/controllers/services/configured_account_base_controller.rb +17 -0
  42. data/app/controllers/services/configured_accounts_controller.rb +59 -0
  43. data/app/controllers/services/configured_facilities_controller.rb +65 -0
  44. data/app/controllers/services/facility_mappings_controller.rb +58 -0
  45. data/app/controllers/services/mds_files_controller.rb +75 -0
  46. data/app/controllers/services/mds_pull_accounts_controller.rb +57 -0
  47. data/app/controllers/services/public_keys_controller.rb +50 -0
  48. data/app/controllers/services/service_base_controller.rb +18 -0
  49. data/app/controllers/services/service_definition_base_controller.rb +31 -0
  50. data/app/controllers/services/service_definitions_controller.rb +59 -0
  51. data/app/controllers/services/services_controller.rb +56 -0
  52. data/app/controllers/services/sltc_providers_controller.rb +15 -0
  53. data/app/controllers/services/sltc_registrations_controller.rb +74 -0
  54. data/app/controllers/services/status_masking.rb +17 -0
  55. data/app/controllers/services/third_parties_controller.rb +47 -0
  56. data/app/controllers/services/third_party_base_controller.rb +17 -0
  57. data/app/controllers/services/validation_controller.rb +17 -0
  58. data/app/helpers/services/application_helper.rb +8 -0
  59. data/app/helpers/services/assessment_request_helper.rb +19 -0
  60. data/app/helpers/services/available_files_helper.rb +27 -0
  61. data/app/helpers/services/mds_pull_accounts_helper.rb +27 -0
  62. data/app/helpers/services/sltc_registrations_helper.rb +15 -0
  63. data/app/mailers/services_mailer.rb +57 -0
  64. data/app/models/services/abaqis_mds_push.rb +51 -0
  65. data/app/models/services/account_mapping.rb +10 -0
  66. data/app/models/services/application_api.rb +19 -0
  67. data/app/models/services/assessment_request.rb +18 -0
  68. data/app/models/services/available_file.rb +73 -0
  69. data/app/models/services/configured_account.rb +26 -0
  70. data/app/models/services/configured_facility.rb +16 -0
  71. data/app/models/services/credential.rb +9 -0
  72. data/app/models/services/facility_mapping.rb +12 -0
  73. data/app/models/services/ftp_server.rb +69 -0
  74. data/app/models/services/hl7_inbound_service.rb +47 -0
  75. data/app/models/services/hl7_message.rb +27 -0
  76. data/app/models/services/isc_code.rb +15 -0
  77. data/app/models/services/isc_code_lookup.rb +75 -0
  78. data/app/models/services/mds_assessment.rb +371 -0
  79. data/app/models/services/mds_content.rb +55 -0
  80. data/app/models/services/mds_pull.rb +41 -0
  81. data/app/models/services/mds_pull_account.rb +192 -0
  82. data/app/models/services/mds_push.rb +24 -0
  83. data/app/models/services/mds_upload.rb +64 -0
  84. data/app/models/services/mds_upload_content.rb +148 -0
  85. data/app/models/services/mds_ws_response.rb +21 -0
  86. data/app/models/services/mds_ws_response_handler.rb +31 -0
  87. data/app/models/services/pcc_mds_pull.rb +77 -0
  88. data/app/models/services/provider_change.rb +26 -0
  89. data/app/models/services/public_key.rb +11 -0
  90. data/app/models/services/service.rb +20 -0
  91. data/app/models/services/service_definition.rb +37 -0
  92. data/app/models/services/service_implementation.rb +29 -0
  93. data/app/models/services/sltc_api.rb +179 -0
  94. data/app/models/services/sltc_api_exception.rb +54 -0
  95. data/app/models/services/sltc_mds_pull.rb +230 -0
  96. data/app/models/services/sltc_registration.rb +23 -0
  97. data/app/models/services/third_party.rb +18 -0
  98. data/app/roles/services/account_mapping_creator.rb +13 -0
  99. data/app/roles/services/account_mapping_updator.rb +12 -0
  100. data/app/roles/services/configured_account_creator.rb +13 -0
  101. data/app/roles/services/configured_account_updater.rb +12 -0
  102. data/app/roles/services/configured_facility_creator.rb +13 -0
  103. data/app/roles/services/configured_facility_updater.rb +12 -0
  104. data/app/roles/services/credential_creator.rb +11 -0
  105. data/app/roles/services/credential_updater.rb +20 -0
  106. data/app/roles/services/facility_mapping_creator.rb +13 -0
  107. data/app/roles/services/facility_mapping_updater.rb +11 -0
  108. data/app/roles/services/hl7_adt_message_saver.rb +15 -0
  109. data/app/roles/services/hl7_message_trimmer.rb +14 -0
  110. data/app/roles/services/mds_assessment_categorizer.rb +71 -0
  111. data/app/roles/services/mds_file_processor.rb +86 -0
  112. data/app/roles/services/mds_notifications.rb +44 -0
  113. data/app/roles/services/monthly_service_table_cleaner.rb +19 -0
  114. data/app/roles/services/new_registration_notifier.rb +11 -0
  115. data/app/roles/services/public_key_creator.rb +14 -0
  116. data/app/roles/services/public_key_updater.rb +12 -0
  117. data/app/roles/services/service_creator.rb +13 -0
  118. data/app/roles/services/service_definition_creator.rb +13 -0
  119. data/app/roles/services/service_definition_updater.rb +12 -0
  120. data/app/roles/services/service_invoker.rb +25 -0
  121. data/app/roles/services/service_updater.rb +11 -0
  122. data/app/roles/services/sltc_baseline_requestor.rb +19 -0
  123. data/app/roles/services/sltc_provider_change_notifier.rb +25 -0
  124. data/app/roles/services/sltc_provider_lister.rb +13 -0
  125. data/app/roles/services/sltc_registration_completer.rb +81 -0
  126. data/app/roles/services/sltc_registration_saver.rb +13 -0
  127. data/app/roles/services/submit_mds_file_for_processing.rb +28 -0
  128. data/app/roles/services/third_party_creator.rb +13 -0
  129. data/app/roles/services/third_party_updater.rb +12 -0
  130. data/app/utils/services/file_upload_handler.rb +33 -0
  131. data/app/utils/services/mds_upload_filters.rb +26 -0
  132. data/app/utils/services/mds_xml_file_parser.rb +104 -0
  133. data/app/utils/services/upload_file.rb +13 -0
  134. data/app/validators/isc_code_validator.rb +42 -0
  135. data/app/validators/mds_birthdate_validator.rb +37 -0
  136. data/app/validators/mds_date_validator.rb +8 -0
  137. data/app/validators/mds_integer_validator.rb +15 -0
  138. data/app/validators/mds_version_validator.rb +16 -0
  139. data/app/validators/state_code_validator.rb +9 -0
  140. data/app/views/layouts/services/application.html.erb +14 -0
  141. data/app/views/services/account_mappings/index.json.jbuilder +9 -0
  142. data/app/views/services/account_mappings/show.json.jbuilder +7 -0
  143. data/app/views/services/assessment_requests/index.json.jbuilder +11 -0
  144. data/app/views/services/available_files/index.json.jbuilder +13 -0
  145. data/app/views/services/configured_accounts/index.json.jbuilder +13 -0
  146. data/app/views/services/configured_accounts/show.json.jbuilder +11 -0
  147. data/app/views/services/configured_facilities/index.json.jbuilder +13 -0
  148. data/app/views/services/configured_facilities/show.json.jbuilder +11 -0
  149. data/app/views/services/facility_mappings/index.json.jbuilder +10 -0
  150. data/app/views/services/facility_mappings/show.json.jbuilder +8 -0
  151. data/app/views/services/mds_files/create.builder +10 -0
  152. data/app/views/services/mds_pull_accounts/index.json.jbuilder +11 -0
  153. data/app/views/services/public_keys/index.json.jbuilder +8 -0
  154. data/app/views/services/public_keys/show.json.jbuilder +6 -0
  155. data/app/views/services/service_definitions/index.json.jbuilder +17 -0
  156. data/app/views/services/service_definitions/show.json.jbuilder +16 -0
  157. data/app/views/services/services/index.json.jbuilder +6 -0
  158. data/app/views/services/services/show.json.jbuilder +4 -0
  159. data/app/views/services/sltc_providers/index.json.jbuilder +10 -0
  160. data/app/views/services/sltc_registrations/index.json.jbuilder +10 -0
  161. data/app/views/services/third_parties/index.json.jbuilder +7 -0
  162. data/app/views/services/third_parties/show.json.jbuilder +5 -0
  163. data/app/views/services_mailer/burying_job.html.erb +20 -0
  164. data/app/views/services_mailer/delaying_job.html.erb +20 -0
  165. data/app/views/services_mailer/notify_sltc_client_registration.html.erb +39 -0
  166. data/app/views/services_mailer/notify_sltc_client_registration_invalid_request_type.html.erb +8 -0
  167. data/app/views/services_mailer/notify_sltc_client_registration_request_invalid.html.erb +10 -0
  168. data/app/views/services_mailer/notify_sltc_client_registration_validation_errors.html.erb +13 -0
  169. data/app/views/services_mailer/notify_sltc_provider_changes.html.erb +26 -0
  170. data/app/views/services_mailer/notify_support_about_no_mds_pull.html.erb +6 -0
  171. data/config/routes.rb +48 -0
  172. data/db/migrate/20140102000000_create_services_engine_tables.rb +131 -0
  173. data/db/migrate/20140517184450_new_services_columns.rb +24 -0
  174. data/db/migrate/20140525142842_new_configured_provider_table.rb +18 -0
  175. data/db/migrate/20140714172442_add_error_column_to_hl7_messages.rb +5 -0
  176. data/db/migrate/20140730164152_mds_upload_tables.rb +78 -0
  177. data/db/sql_data/service_data_setup.sql +24 -0
  178. data/lib/services/engine.rb +40 -0
  179. data/lib/services/version.rb +3 -0
  180. data/lib/services.rb +4 -0
  181. data/lib/tasks/services_tasks.rake +40 -0
  182. data/spec/dummy/README.rdoc +261 -0
  183. data/spec/dummy/Rakefile +7 -0
  184. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  185. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  186. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  187. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  188. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  189. data/spec/dummy/config/application.rb +60 -0
  190. data/spec/dummy/config/boot.rb +10 -0
  191. data/spec/dummy/config/database.yml +29 -0
  192. data/spec/dummy/config/environment.rb +5 -0
  193. data/spec/dummy/config/environments/development.rb +35 -0
  194. data/spec/dummy/config/environments/production.rb +68 -0
  195. data/spec/dummy/config/environments/test.rb +32 -0
  196. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  197. data/spec/dummy/config/initializers/email.rb +1 -0
  198. data/spec/dummy/config/initializers/inflections.rb +15 -0
  199. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  200. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  201. data/spec/dummy/config/initializers/session_store.rb +8 -0
  202. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  203. data/spec/dummy/config/locales/en.yml +5 -0
  204. data/spec/dummy/config/routes.rb +4 -0
  205. data/spec/dummy/config.ru +4 -0
  206. data/spec/dummy/db/schema.rb +237 -0
  207. data/spec/dummy/db/sql_data/services_isc_codes.sql +878 -0
  208. data/spec/dummy/log/test.log +3498 -0
  209. data/spec/dummy/public/404.html +26 -0
  210. data/spec/dummy/public/422.html +26 -0
  211. data/spec/dummy/public/500.html +25 -0
  212. data/spec/dummy/public/favicon.ico +0 -0
  213. data/spec/dummy/script/rails +6 -0
  214. data/spec/models/abaqis_mds_push_spec.rb +120 -0
  215. data/spec/models/available_file_spec.rb +234 -0
  216. data/spec/models/configured_account_spec.rb +39 -0
  217. data/spec/models/ftp_server_spec.rb +221 -0
  218. data/spec/models/isc_code_lookup_spec.rb +125 -0
  219. data/spec/models/isc_code_spec.rb +5 -0
  220. data/spec/models/mds_assessment_spec.rb +1070 -0
  221. data/spec/models/mds_pull_account_spec.rb +468 -0
  222. data/spec/models/mds_pull_spec.rb +48 -0
  223. data/spec/models/mds_push_spec.rb +43 -0
  224. data/spec/models/mds_ws_response_spec.rb +54 -0
  225. data/spec/models/pcc_mds_pull_spec.rb +273 -0
  226. data/spec/models/service_implementation_spec.rb +88 -0
  227. data/spec/models/sltc_api_exception_spec.rb +136 -0
  228. data/spec/models/sltc_api_spec.rb +192 -0
  229. data/spec/models/sltc_mds_pull_spec.rb +776 -0
  230. data/spec/roles/account_mapping_creator_spec.rb +40 -0
  231. data/spec/roles/account_mapping_updator_spec.rb +16 -0
  232. data/spec/roles/configured_account_creator_spec.rb +40 -0
  233. data/spec/roles/configured_account_updater_spec.rb +16 -0
  234. data/spec/roles/configured_facility_creator_spec.rb +40 -0
  235. data/spec/roles/configured_facility_updater_spec.rb +16 -0
  236. data/spec/roles/credential_creator_spec.rb +23 -0
  237. data/spec/roles/credential_updater_spec.rb +38 -0
  238. data/spec/roles/facility_mapping_creator_spec.rb +40 -0
  239. data/spec/roles/facility_mapping_updater_spec.rb +16 -0
  240. data/spec/roles/hl7_adt_message_saver_spec.rb +35 -0
  241. data/spec/roles/hl7_message_trimmer_spec.rb +31 -0
  242. data/spec/roles/monthly_service_table_cleaner_spec.rb +27 -0
  243. data/spec/roles/new_registration_notifier_spec.rb +18 -0
  244. data/spec/roles/service_ceator_spec.rb +34 -0
  245. data/spec/roles/service_definition_creator_spec.rb +40 -0
  246. data/spec/roles/service_definition_updater_spec.rb +16 -0
  247. data/spec/roles/service_invoker_spec.rb +22 -0
  248. data/spec/roles/service_updater_spec.rb +17 -0
  249. data/spec/roles/sltc_baseline_requestor_spec.rb +30 -0
  250. data/spec/roles/sltc_provider_lister_spec.rb +27 -0
  251. data/spec/roles/sltc_registration_completer_spec.rb +187 -0
  252. data/spec/roles/sltc_registration_saver_spec.rb +34 -0
  253. data/spec/roles/third_party_creator_spec.rb +34 -0
  254. data/spec/roles/third_party_updater_spec.rb +17 -0
  255. data/spec/spec_helper.rb +72 -0
  256. metadata +581 -0
@@ -0,0 +1,54 @@
1
+ module Services
2
+
3
+ class SltcApiException < StandardError
4
+
5
+ attr_reader :inner_exception
6
+ attr_reader :raw_json, :error_code, :error_message, :error_response
7
+
8
+ def initialize(exception)
9
+ @inner_exception = exception
10
+ @raw_json = exception.response if exception && exception.respond_to?(:response)
11
+ @error_code = -1
12
+ super format_exception_message
13
+ end
14
+
15
+ def http_code
16
+ inner_exception.http_code if inner_exception && inner_exception.respond_to?(:http_code)
17
+ end
18
+
19
+ def http_message
20
+ inner_exception.message if inner_exception && inner_exception.respond_to?(:message)
21
+ end
22
+
23
+ private
24
+
25
+ def format_exception_message
26
+ return "Unknown SimpleLTC API Error (#{basic_message_fmt})" if raw_json.nil?
27
+
28
+ extract_sltc_error_information
29
+ end
30
+
31
+ def extract_sltc_error_information
32
+ @error_response = JSON.parse(raw_json)
33
+
34
+ return "No error message in SimpleLTC error response (#{raw_json}) (#{basic_message_fmt})" unless @error_response.is_a?(Hash) && @error_response.has_key?('Message')
35
+
36
+ @error_message = @error_response['Message']
37
+ @error_code = @error_response['ErrorCode']
38
+
39
+ "SimpleLTC error response: (#{@error_code.present? ? @error_code : 'N/A'}) #{@error_message} (#{basic_message_fmt})"
40
+ rescue Exception => ex
41
+ "Error parsing SimpleLTC API Error JSON (#{raw_json}): #{ex.message} (#{basic_message_fmt})"
42
+ end
43
+
44
+ def basic_message_fmt
45
+ if http_code.present?
46
+ "#{http_code}: #{http_message}"
47
+ else
48
+ "no http_code associated with inner exception"
49
+ end
50
+ end
51
+ end
52
+
53
+ end
54
+
@@ -0,0 +1,230 @@
1
+ module Services
2
+
3
+ class SltcMdsPull < MdsPull
4
+ include FileUtils
5
+
6
+ #
7
+ # Overridden from MdsPull
8
+ #
9
+ def identify_providers(configured_account)
10
+ api = api_impl(configured_account)
11
+ provider_list = api.list_providers
12
+ process_provider_list(configured_account, provider_list)
13
+ end
14
+
15
+ #
16
+ # Overridden from MdsPull
17
+ #
18
+ def request_assessments(configured_account)
19
+ enabled_providers = providers_for_account(configured_account)
20
+
21
+ enabled_providers.each do | provider_id |
22
+ request_assessments_to_pull(configured_account, provider_id)
23
+ end
24
+ end
25
+
26
+ def providers_for_account(configured_account)
27
+ enabled_facility_ids = ApplicationApi.api_impl.enabled_facilities_for_account_id(configured_account.account_id).pluck(:id)
28
+ FacilityMapping.
29
+ joins('LEFT OUTER JOIN services_configured_facilities ON services_configured_facilities.facility_id = services_facility_mappings.facility_id').
30
+ where('services_facility_mappings.facility_id IN (?) AND services_configured_facilities.enabled = 1', enabled_facility_ids).
31
+ pluck(:facility_code)
32
+ end
33
+
34
+ def list_available_files(configured_account)
35
+ api = api_impl(configured_account)
36
+
37
+ list_available_assessment_requests api, configured_account
38
+ end
39
+
40
+ def list_available_assessment_requests(api, configured_account)
41
+ assessment_request_ids = []
42
+ enabled_providers = providers_for_account(configured_account)
43
+
44
+ AssessmentRequest.available.where(facility_code: enabled_providers).each do | assessment_request |
45
+ status_response = api.assessment_request_status(assessment_request.request_id)
46
+ case status_response['status']
47
+ when 'Complete'
48
+ assessment_request_ids << [ assessment_request.request_id, "#{assessment_request.request_id}.zip" ]
49
+ assessment_request.update_attribute :status, AssessmentRequest::STATUS_COMPLETED
50
+ when 'Empty'
51
+ assessment_request.update_attribute :status, AssessmentRequest::STATUS_EMPTY
52
+ when 'Error'
53
+ assessment_request.update_attribute :status, AssessmentRequest::STATUS_ERROR
54
+ else
55
+ # Do nothing ... Must be processing so we leave the status as 'Active'
56
+ end
57
+ end
58
+
59
+ assessment_request_ids
60
+ end
61
+
62
+ def perform_file_downloads(configured_account, files_to_download)
63
+ api = api_impl(configured_account)
64
+ downloaded_files = []
65
+ files_to_download.each do | available_file |
66
+ downloaded_files << download_file(api, available_file)
67
+ end
68
+ downloaded_files.compact
69
+ end
70
+
71
+ def perform_cleanup_on_remote_server(configured_account)
72
+ configured_account.available_files.deleted.pluck(:id)
73
+ end
74
+
75
+ def download_file(api, available_file)
76
+ mkdir_p available_file.download_path
77
+ File.open(available_file.downloaded_file_path, "wb") do |f|
78
+ f.write(api.download_assessment_request(available_file.request_id))
79
+ end
80
+ available_file.id
81
+ end
82
+
83
+ def request_baseline(configured_account, provider_id, uploaded_after, uploaded_before)
84
+ api = api_impl(configured_account)
85
+ result = api.assessment_request(provider_id, uploaded_after, uploaded_before, 'Accepted')
86
+ Rails.logger.info "Response from baseline request: #{result.inspect}"
87
+ request_id = result['requestId']
88
+ # Create a new row in the assessment request table
89
+ AssessmentRequest.create!(request_id: request_id,
90
+ facility_code: provider_id,
91
+ pull_from: uploaded_after,
92
+ pull_to: uploaded_before,
93
+ status: AssessmentRequest::STATUS_AVAILABLE)
94
+ request_id
95
+ end
96
+
97
+ def api_impl(configured_account)
98
+ SltcApi.for_configured_account(configured_account)
99
+ end
100
+
101
+ def process_provider_list(configured_account, provider_list)
102
+ # The provider Ids need to be converted to strings because we store
103
+ # the provider_codes as strings in the db.
104
+ sltc_provider_ids = provider_list.map { | provider_info | provider_info['id'].to_s }
105
+ # Get the provider ids that are currently enabled for this account
106
+ mapped_facility_ids = providers_for_account(configured_account)
107
+
108
+ facilities_removed = mapped_facility_ids - sltc_provider_ids
109
+ facilities_added = sltc_provider_ids - mapped_facility_ids
110
+
111
+ added_facility_info = provider_list.select { | provider | facilities_added.include?(provider['id'].to_s) }
112
+
113
+ still_to_add = facilities_added - ProviderChange.
114
+ added_providers(configured_account.id, facilities_added).
115
+ pluck(:facility_code)
116
+
117
+ register_provider_deltas configured_account, provider_list.select { |p| still_to_add.include?(p['id'].to_s) }, ProviderChange::VERB_ADD
118
+
119
+ still_to_remove = facilities_removed - ProviderChange.
120
+ deleted_providers(configured_account.id, facilities_removed).
121
+ pluck(:facility_code)
122
+
123
+ mappings = FacilityMapping.sltc_provider_mappings(still_to_remove).
124
+ map do | fm |
125
+ facility = fm.facility
126
+ {
127
+ 'id' => fm.facility_code,
128
+ 'name' => facility.name,
129
+ 'state' => facility.state,
130
+ 'npi' => facility.npi,
131
+ 'ccn' => facility.govid,
132
+ 'mdsFacilityId' => facility.fac_id
133
+ }
134
+ end
135
+
136
+ register_provider_deltas configured_account, mappings, ProviderChange::VERB_DELETE
137
+
138
+ disable_removed_facilities(facilities_removed) unless facilities_removed.empty?
139
+ configure_added_facilities(added_facility_info)
140
+ end
141
+
142
+ def register_provider_deltas(configured_account, provider_list, verb)
143
+ provider_list.each do |pi|
144
+ ProviderChange.create!(configured_account_id: configured_account.id,
145
+ facility_code: pi['id'],
146
+ name: pi['name'],
147
+ state: pi['state'],
148
+ npi: pi['npi'],
149
+ ccn: pi['ccn'],
150
+ fac_id: pi['mdsFacilityId'],
151
+ verb: verb)
152
+ end
153
+ end
154
+
155
+ def disable_removed_facilities(facility_codes)
156
+ fac_mappings = FacilityMapping.
157
+ sltc_provider_mappings(facility_codes)
158
+
159
+ facility_ids = fac_mappings.pluck(:facility_id)
160
+ mapping_ids = fac_mappings.pluck(:id)
161
+
162
+ # Delete all the facility configuration entries
163
+ ConfiguredFacility.where(facility_id: facility_ids).destroy_all
164
+
165
+ # Remove all the facility mappings
166
+ FacilityMapping.where(id: mapping_ids).destroy_all
167
+ end
168
+
169
+ def configure_added_facilities(added_facility_info)
170
+ configure_existing_enabled_facilities(added_facility_info)
171
+
172
+ # We will not be creating new facilities based on the information from
173
+ # SLTC. It will only configure existing, enabled facilities that have
174
+ # not yet been configured
175
+ end
176
+
177
+ def configure_existing_enabled_facilities(added_facility_info)
178
+ govids = added_facility_info.map { | facility_info | facility_info['ccn'] }
179
+ facilities = ApplicationApi.api_impl.enabled_facilities_with_govids(govids)
180
+ facilities.each do | facility |
181
+ facility_info = added_facility_info.detect { | fi | fi['ccn'] == facility.govid }
182
+ # Set the state code/fac_id if not already set.
183
+ if facility.state != facility_info['state'] ||
184
+ facility.fac_id != facility_info['mdsFacilityId']
185
+ facility.update_attributes(fac_id: facility_info['mdsFacilityId'],
186
+ state: facility_info['state'])
187
+ end
188
+ # Create the facility mappings we need
189
+ FacilityMapping.create!(third_party_id: service_definition.third_party_id,
190
+ facility_id: facility.id,
191
+ facility_code: facility_info['id'],
192
+ top_level: false)
193
+
194
+ # Create the configured facility we need
195
+ ConfiguredFacility.create!(service_definition_id: service_definition.id,
196
+ facility_id: facility.id,
197
+ enabled: true)
198
+ end
199
+ end
200
+
201
+ def request_assessments_to_pull(configured_account, provider_code)
202
+ # Find the latest assessment request that we pulled to. We do this because
203
+ # we want to know from when to start our requested range.
204
+ latest_assessment_request = AssessmentRequest.
205
+ where(facility_code: provider_code).
206
+ order('pull_to DESC').
207
+ limit(1).
208
+ first
209
+
210
+ # Set the date range for the request
211
+ pull_to = Time.now
212
+ pull_from = latest_assessment_request.present? ? latest_assessment_request.pull_to - 1.second : Time.now - 24.hours
213
+
214
+ api = api_impl(configured_account)
215
+ response = api.assessment_request(provider_code,
216
+ pull_from,
217
+ pull_to,
218
+ 'Accepted')
219
+
220
+ # Register that we made the request
221
+ AssessmentRequest.create(facility_code: provider_code,
222
+ request_id: response['requestId'],
223
+ pull_from: pull_from,
224
+ pull_to: pull_to,
225
+ status: AssessmentRequest::STATUS_AVAILABLE)
226
+ end
227
+
228
+ end
229
+
230
+ end
@@ -0,0 +1,23 @@
1
+ module Services
2
+
3
+ class SltcRegistration < ActiveRecord::Base
4
+
5
+ STATUS_NEW = 0
6
+ STATUS_REGISTERED = 1
7
+
8
+ validates :company_name, presence: true, length: { maximum: 255 }, allow_nil: true, allow_blank: true
9
+ validates :initiated_by, presence: true, length: { maximum: 255 }, allow_nil: true, allow_blank: true
10
+
11
+ attr_encrypted :auth_password, :auth_username
12
+
13
+ def account_code
14
+ auth_username.split('@').last if auth_username.present?
15
+ end
16
+
17
+ def username
18
+ auth_username.split('@').first if auth_username.present?
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,18 @@
1
+ module Services
2
+
3
+ class ThirdParty < ActiveRecord::Base
4
+ has_many :account_mappings, dependent: :destroy
5
+ has_many :facility_mappings, dependent: :destroy
6
+ has_many :service_definitions, dependent: :destroy
7
+
8
+ PROVIDIGM = 'pvdgm'
9
+ POINTCLICKCARE = 'pcc'
10
+ SLTC = 'sltc'
11
+
12
+ validates :name, presence: true, uniqueness: true, length: { maximum: 255 }
13
+ validates :key, presence: true, uniqueness: true, length: { maximum: 255 }
14
+ validates :contact_email, presence: true, length: { maximum: 255 }
15
+
16
+ end
17
+
18
+ end
@@ -0,0 +1,13 @@
1
+ module Services
2
+
3
+ module AccountMappingCreator
4
+
5
+ def create(params)
6
+ account_mappings.new(params).tap do | account_mapping |
7
+ account_mapping.save if account_mapping.valid?
8
+ end
9
+ end
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,12 @@
1
+ module Services
2
+
3
+ module AccountMappingUpdator
4
+
5
+ def update(params)
6
+ update_attributes(params)
7
+ self
8
+ end
9
+
10
+ end
11
+
12
+ end
@@ -0,0 +1,13 @@
1
+ module Services
2
+
3
+ module ConfiguredAccountCreator
4
+
5
+ def create(params)
6
+ configured_accounts.new(params).tap do | configured_account |
7
+ configured_account.save if configured_account.valid?
8
+ end
9
+ end
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,12 @@
1
+ module Services
2
+
3
+ module ConfiguredAccountUpdater
4
+
5
+ def update(params)
6
+ update_attributes(params)
7
+ self
8
+ end
9
+
10
+ end
11
+
12
+ end
@@ -0,0 +1,13 @@
1
+ module Services
2
+
3
+ module ConfiguredFacilityCreator
4
+
5
+ def create(params)
6
+ configured_facilities.new(params).tap do | configured_facility |
7
+ configured_facility.save if configured_facility.valid?
8
+ end
9
+ end
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,12 @@
1
+ module Services
2
+
3
+ module ConfiguredFacilityUpdater
4
+
5
+ def update(params)
6
+ update_attributes(params)
7
+ self
8
+ end
9
+
10
+ end
11
+
12
+ end
@@ -0,0 +1,11 @@
1
+ module Services
2
+
3
+ module CredentialCreator
4
+
5
+ def add_credential(params)
6
+ credentials << Services::Credential.new(params)
7
+ end
8
+
9
+ end
10
+
11
+ end
@@ -0,0 +1,20 @@
1
+ module Services
2
+
3
+ module CredentialUpdater
4
+
5
+ def update_credential(params)
6
+ credential = credentials.first
7
+ if credential.present?
8
+ if params.present?
9
+ credential.update_attributes(params)
10
+ else
11
+ credential.destroy
12
+ end
13
+ elsif params.present?
14
+ credentials << Credential.new(params)
15
+ end
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -0,0 +1,13 @@
1
+ module Services
2
+
3
+ module FacilityMappingCreator
4
+
5
+ def create(params)
6
+ facility_mappings.new(params).tap do | facility_mapping |
7
+ facility_mapping.save if facility_mapping.valid?
8
+ end
9
+ end
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,11 @@
1
+ module Services
2
+
3
+ module FacilityMappingUpdater
4
+
5
+ def update(params)
6
+ update_attributes(params)
7
+ end
8
+
9
+ end
10
+
11
+ end
@@ -0,0 +1,15 @@
1
+ module Services
2
+
3
+ module Hl7AdtMessageSaver
4
+
5
+ def persist(message_type, message_body)
6
+ Services::Hl7Message.new.tap do | msg |
7
+ msg.message_type = message_type
8
+ msg.message = message_body
9
+ msg.save if msg.valid?
10
+ end
11
+ end
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,14 @@
1
+ module Services
2
+
3
+ module Hl7MessageTrimmer
4
+
5
+ def trim_messages
6
+ Hl7Message.
7
+ where(status: Hl7Message::STATUS_PROCESSED).
8
+ where("updated_at < ?", Time.now - 30.days).
9
+ destroy_all
10
+ end
11
+
12
+ end
13
+
14
+ end
@@ -0,0 +1,71 @@
1
+ module Services
2
+
3
+ module MdsAssessmentCategorizer
4
+
5
+ def significant_correction_assessment?
6
+ responses.present? && %w{ 05 06 }.include?(a0310a)
7
+ end
8
+
9
+ def admission_assessment?
10
+ a0310a.to_i == 1
11
+ end
12
+
13
+ def any_type_of_correction_assessment?
14
+ significant_correction_assessment? || correction_record?
15
+ end
16
+
17
+ def correction_record?
18
+ responses.present? && version == MdsAssessment::VERSION1_0 ? x0100 == "2" : a0050 == "2"
19
+ end
20
+
21
+ def correction_applied?
22
+ responses.present? && prior_isc_cd.present?
23
+ end
24
+
25
+ def inactivated?
26
+ responses.present? && (corrected? && prior_isc_cd.blank?)
27
+ end
28
+
29
+ def entry_assessment?
30
+ responses.present? && a0310f.to_i == 1
31
+ end
32
+
33
+ def discharge_assessment?
34
+ responses.present? && a0310f.to_i == 10 || a0310f.to_i == 11
35
+ end
36
+
37
+ def death_assessment?
38
+ responses.present? && a0310f.to_i == 12
39
+ end
40
+
41
+ def discharge_or_death_assessment?
42
+ discharge_assessment? || death_assessment?
43
+ end
44
+
45
+ def tracking_assessment?
46
+ responses.present? && %w{ NT ST }.include?(itm_sbst_cd)
47
+ end
48
+
49
+ def quarterly?
50
+ responses.present? && a0310a == "02"
51
+ end
52
+
53
+ def ninety_day?
54
+ responses.present? && a0310b == "05"
55
+ end
56
+
57
+ def inactivation_assessment?
58
+ responses.present? && itm_sbst_cd == IscCode.inactivation_code
59
+ end
60
+
61
+ def entered_from_hospital?
62
+ responses.present? && a1800 == "03"
63
+ end
64
+
65
+ def a0310f_99?
66
+ responses.present? && a0310f == "99"
67
+ end
68
+
69
+ end
70
+
71
+ end
@@ -0,0 +1,86 @@
1
+ module Services
2
+
3
+ module MdsFileProcessor
4
+ PCC_METADATA_FILE_RE = %r{PCC_.+_metadata.xml\z}
5
+
6
+ # So, the work we're going to do here is to crack open the
7
+ # MDS file and save each of the assessments to the MDS
8
+ # assessments table. We won't process it any further at this
9
+ # point.
10
+ def process
11
+ # Do nothing if we dont' have a status of NEW
12
+ return unless self.status == MdsUpload::NEW
13
+ return unless self.mds_content.present?
14
+
15
+ start_time = Time.now
16
+ num_records = 0
17
+ num_duplicated = 0
18
+ num_rejected = 0
19
+
20
+ # Loop over all the files in the upload file
21
+ self.mds_content.each_entry do | entry, relative_path |
22
+
23
+ next if File.directory?(entry)
24
+ basename = File.basename(entry)
25
+ next if basename =~ PCC_METADATA_FILE_RE
26
+
27
+ num_records += 1
28
+
29
+ parser = MdsXmlFileParser.new(entry)
30
+ assessment_data = parser.parse
31
+
32
+ if assessment_data.blank?
33
+ num_rejected += 1
34
+ self.file_errors.merge!(parser.file_errors) if parser.file_errors.present?
35
+ else
36
+ # We use the relative_path to the file from the extration
37
+ # directory so that the error report will properly show
38
+ # the path to the file with the problem, even if the file
39
+ # was located in an embedded zip file.
40
+ begin
41
+ mds = create_assessment(relative_path, assessment_data)
42
+ if mds.blank?
43
+ num_duplicated += 1
44
+ add_file_errors(relative_path, "Duplicate assessment")
45
+ elsif !mds.valid?
46
+ num_rejected += 1
47
+ add_file_errors(relative_path, mds.errors.values.flatten)
48
+ end
49
+ rescue => ex
50
+ num_rejected += 1
51
+ add_file_errors(relative_path, ex.message)
52
+ end
53
+ end
54
+ end
55
+
56
+ # Need to save any errors
57
+ update_attributes(status: MdsUpload::ASSESSMENTS_LOADED,
58
+ num_records: num_records,
59
+ num_duplicated: num_duplicated,
60
+ num_rejected: num_rejected,
61
+ parse_time: ((Time.now - start_time) * 1000).round)
62
+ rescue => ex
63
+ Rails.logger.error("#{ex.message}\n#{ex.backtrace.join("\n")}")
64
+ update_attribute(:fatal_error, "#{ex.message}\n#{ex.backtrace.join("\n")}")
65
+ end
66
+
67
+ private
68
+
69
+ def create_assessment(filename, assessment_data)
70
+ # Don't bother with duplicates
71
+ md5_checksum = Digest::MD5.hexdigest(assessment_data.to_s)
72
+ return if MdsAssessment.where(md5_checksum: md5_checksum).count > 0
73
+
74
+ mds_assessment = MdsAssessment.new(mds_upload: self,
75
+ md5_checksum: md5_checksum,
76
+ filename: filename,
77
+ responses: assessment_data)
78
+ if mds_assessment.valid?
79
+ mds_assessment.save
80
+ end
81
+ mds_assessment
82
+ end
83
+
84
+ end
85
+
86
+ end