pvdgm_services 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 +29 -0
- data/Rakefile +40 -0
- data/app/contexts/services/accept_hl7_message_context.rb +32 -0
- data/app/contexts/services/application_mds_context.rb +21 -0
- data/app/contexts/services/complete_sltc_registration_process_context.rb +23 -0
- data/app/contexts/services/create_account_mapping_context.rb +23 -0
- data/app/contexts/services/create_configured_account_context.rb +26 -0
- data/app/contexts/services/create_configured_facility_context.rb +26 -0
- data/app/contexts/services/create_credential_context.rb +23 -0
- data/app/contexts/services/create_facility_mapping_context.rb +23 -0
- data/app/contexts/services/create_public_key_context.rb +22 -0
- data/app/contexts/services/create_service_context.rb +22 -0
- data/app/contexts/services/create_service_definition_context.rb +26 -0
- data/app/contexts/services/create_sltc_registration_context.rb +24 -0
- data/app/contexts/services/create_third_party_context.rb +22 -0
- data/app/contexts/services/hl7_message_trimming_context.rb +19 -0
- data/app/contexts/services/invoke_service_context.rb +21 -0
- data/app/contexts/services/list_sltc_providers_context.rb +22 -0
- data/app/contexts/services/mds_file_processing_context.rb +27 -0
- data/app/contexts/services/mds_file_upload_context.rb +25 -0
- data/app/contexts/services/mds_pull_context.rb +21 -0
- data/app/contexts/services/monthly_service_table_cleanup_context.rb +19 -0
- data/app/contexts/services/notify_new_registration_context.rb +22 -0
- data/app/contexts/services/notify_sltc_provider_change_context.rb +19 -0
- data/app/contexts/services/request_sltc_baseline_context.rb +23 -0
- data/app/contexts/services/update_account_mapping_context.rb +23 -0
- data/app/contexts/services/update_configured_account_context.rb +26 -0
- data/app/contexts/services/update_configured_facility_context.rb +26 -0
- data/app/contexts/services/update_credential_context.rb +23 -0
- data/app/contexts/services/update_facility_mapping_context.rb +23 -0
- data/app/contexts/services/update_public_key_context.rb +23 -0
- data/app/contexts/services/update_service_context.rb +23 -0
- data/app/contexts/services/update_service_definition_context.rb +26 -0
- data/app/contexts/services/update_third_party_context.rb +23 -0
- data/app/controllers/services/account_mappings_controller.rb +54 -0
- data/app/controllers/services/adts_controller.rb +35 -0
- data/app/controllers/services/application_controller.rb +17 -0
- data/app/controllers/services/assessment_requests_controller.rb +48 -0
- data/app/controllers/services/available_files_controller.rb +19 -0
- data/app/controllers/services/configured_account_base_controller.rb +17 -0
- data/app/controllers/services/configured_accounts_controller.rb +59 -0
- data/app/controllers/services/configured_facilities_controller.rb +65 -0
- data/app/controllers/services/facility_mappings_controller.rb +58 -0
- data/app/controllers/services/mds_files_controller.rb +75 -0
- data/app/controllers/services/mds_pull_accounts_controller.rb +57 -0
- data/app/controllers/services/public_keys_controller.rb +50 -0
- data/app/controllers/services/service_base_controller.rb +18 -0
- data/app/controllers/services/service_definition_base_controller.rb +31 -0
- data/app/controllers/services/service_definitions_controller.rb +59 -0
- data/app/controllers/services/services_controller.rb +56 -0
- data/app/controllers/services/sltc_providers_controller.rb +15 -0
- data/app/controllers/services/sltc_registrations_controller.rb +74 -0
- data/app/controllers/services/status_masking.rb +17 -0
- data/app/controllers/services/third_parties_controller.rb +47 -0
- data/app/controllers/services/third_party_base_controller.rb +17 -0
- data/app/controllers/services/validation_controller.rb +17 -0
- data/app/helpers/services/application_helper.rb +8 -0
- data/app/helpers/services/assessment_request_helper.rb +19 -0
- data/app/helpers/services/available_files_helper.rb +27 -0
- data/app/helpers/services/mds_pull_accounts_helper.rb +27 -0
- data/app/helpers/services/sltc_registrations_helper.rb +15 -0
- data/app/mailers/services_mailer.rb +57 -0
- data/app/models/services/abaqis_mds_push.rb +51 -0
- data/app/models/services/account_mapping.rb +10 -0
- data/app/models/services/application_api.rb +19 -0
- data/app/models/services/assessment_request.rb +18 -0
- data/app/models/services/available_file.rb +73 -0
- data/app/models/services/configured_account.rb +26 -0
- data/app/models/services/configured_facility.rb +16 -0
- data/app/models/services/credential.rb +9 -0
- data/app/models/services/facility_mapping.rb +12 -0
- data/app/models/services/ftp_server.rb +69 -0
- data/app/models/services/hl7_inbound_service.rb +47 -0
- data/app/models/services/hl7_message.rb +27 -0
- data/app/models/services/isc_code.rb +15 -0
- data/app/models/services/isc_code_lookup.rb +75 -0
- data/app/models/services/mds_assessment.rb +371 -0
- data/app/models/services/mds_content.rb +55 -0
- data/app/models/services/mds_pull.rb +41 -0
- data/app/models/services/mds_pull_account.rb +192 -0
- data/app/models/services/mds_push.rb +24 -0
- data/app/models/services/mds_upload.rb +64 -0
- data/app/models/services/mds_upload_content.rb +148 -0
- data/app/models/services/mds_ws_response.rb +21 -0
- data/app/models/services/mds_ws_response_handler.rb +31 -0
- data/app/models/services/pcc_mds_pull.rb +77 -0
- data/app/models/services/provider_change.rb +26 -0
- data/app/models/services/public_key.rb +11 -0
- data/app/models/services/service.rb +20 -0
- data/app/models/services/service_definition.rb +37 -0
- data/app/models/services/service_implementation.rb +29 -0
- data/app/models/services/sltc_api.rb +179 -0
- data/app/models/services/sltc_api_exception.rb +54 -0
- data/app/models/services/sltc_mds_pull.rb +230 -0
- data/app/models/services/sltc_registration.rb +23 -0
- data/app/models/services/third_party.rb +18 -0
- data/app/roles/services/account_mapping_creator.rb +13 -0
- data/app/roles/services/account_mapping_updator.rb +12 -0
- data/app/roles/services/configured_account_creator.rb +13 -0
- data/app/roles/services/configured_account_updater.rb +12 -0
- data/app/roles/services/configured_facility_creator.rb +13 -0
- data/app/roles/services/configured_facility_updater.rb +12 -0
- data/app/roles/services/credential_creator.rb +11 -0
- data/app/roles/services/credential_updater.rb +20 -0
- data/app/roles/services/facility_mapping_creator.rb +13 -0
- data/app/roles/services/facility_mapping_updater.rb +11 -0
- data/app/roles/services/hl7_adt_message_saver.rb +15 -0
- data/app/roles/services/hl7_message_trimmer.rb +14 -0
- data/app/roles/services/mds_assessment_categorizer.rb +71 -0
- data/app/roles/services/mds_file_processor.rb +86 -0
- data/app/roles/services/mds_notifications.rb +44 -0
- data/app/roles/services/monthly_service_table_cleaner.rb +19 -0
- data/app/roles/services/new_registration_notifier.rb +11 -0
- data/app/roles/services/public_key_creator.rb +14 -0
- data/app/roles/services/public_key_updater.rb +12 -0
- data/app/roles/services/service_creator.rb +13 -0
- data/app/roles/services/service_definition_creator.rb +13 -0
- data/app/roles/services/service_definition_updater.rb +12 -0
- data/app/roles/services/service_invoker.rb +25 -0
- data/app/roles/services/service_updater.rb +11 -0
- data/app/roles/services/sltc_baseline_requestor.rb +19 -0
- data/app/roles/services/sltc_provider_change_notifier.rb +25 -0
- data/app/roles/services/sltc_provider_lister.rb +13 -0
- data/app/roles/services/sltc_registration_completer.rb +81 -0
- data/app/roles/services/sltc_registration_saver.rb +13 -0
- data/app/roles/services/submit_mds_file_for_processing.rb +28 -0
- data/app/roles/services/third_party_creator.rb +13 -0
- data/app/roles/services/third_party_updater.rb +12 -0
- data/app/utils/services/file_upload_handler.rb +33 -0
- data/app/utils/services/mds_upload_filters.rb +26 -0
- data/app/utils/services/mds_xml_file_parser.rb +104 -0
- data/app/utils/services/upload_file.rb +13 -0
- data/app/validators/isc_code_validator.rb +42 -0
- data/app/validators/mds_birthdate_validator.rb +37 -0
- data/app/validators/mds_date_validator.rb +8 -0
- data/app/validators/mds_integer_validator.rb +15 -0
- data/app/validators/mds_version_validator.rb +16 -0
- data/app/validators/state_code_validator.rb +9 -0
- data/app/views/layouts/services/application.html.erb +14 -0
- data/app/views/services/account_mappings/index.json.jbuilder +9 -0
- data/app/views/services/account_mappings/show.json.jbuilder +7 -0
- data/app/views/services/assessment_requests/index.json.jbuilder +11 -0
- data/app/views/services/available_files/index.json.jbuilder +13 -0
- data/app/views/services/configured_accounts/index.json.jbuilder +13 -0
- data/app/views/services/configured_accounts/show.json.jbuilder +11 -0
- data/app/views/services/configured_facilities/index.json.jbuilder +13 -0
- data/app/views/services/configured_facilities/show.json.jbuilder +11 -0
- data/app/views/services/facility_mappings/index.json.jbuilder +10 -0
- data/app/views/services/facility_mappings/show.json.jbuilder +8 -0
- data/app/views/services/mds_files/create.builder +10 -0
- data/app/views/services/mds_pull_accounts/index.json.jbuilder +11 -0
- data/app/views/services/public_keys/index.json.jbuilder +8 -0
- data/app/views/services/public_keys/show.json.jbuilder +6 -0
- data/app/views/services/service_definitions/index.json.jbuilder +17 -0
- data/app/views/services/service_definitions/show.json.jbuilder +16 -0
- data/app/views/services/services/index.json.jbuilder +6 -0
- data/app/views/services/services/show.json.jbuilder +4 -0
- data/app/views/services/sltc_providers/index.json.jbuilder +10 -0
- data/app/views/services/sltc_registrations/index.json.jbuilder +10 -0
- data/app/views/services/third_parties/index.json.jbuilder +7 -0
- data/app/views/services/third_parties/show.json.jbuilder +5 -0
- data/app/views/services_mailer/burying_job.html.erb +20 -0
- data/app/views/services_mailer/delaying_job.html.erb +20 -0
- data/app/views/services_mailer/notify_sltc_client_registration.html.erb +39 -0
- data/app/views/services_mailer/notify_sltc_client_registration_invalid_request_type.html.erb +8 -0
- data/app/views/services_mailer/notify_sltc_client_registration_request_invalid.html.erb +10 -0
- data/app/views/services_mailer/notify_sltc_client_registration_validation_errors.html.erb +13 -0
- data/app/views/services_mailer/notify_sltc_provider_changes.html.erb +26 -0
- data/app/views/services_mailer/notify_support_about_no_mds_pull.html.erb +6 -0
- data/config/routes.rb +48 -0
- data/db/migrate/20140102000000_create_services_engine_tables.rb +131 -0
- data/db/migrate/20140517184450_new_services_columns.rb +24 -0
- data/db/migrate/20140525142842_new_configured_provider_table.rb +18 -0
- data/db/migrate/20140714172442_add_error_column_to_hl7_messages.rb +5 -0
- data/db/migrate/20140730164152_mds_upload_tables.rb +78 -0
- data/db/sql_data/service_data_setup.sql +24 -0
- data/lib/services/engine.rb +40 -0
- data/lib/services/version.rb +3 -0
- data/lib/services.rb +4 -0
- data/lib/tasks/services_tasks.rake +40 -0
- data/spec/dummy/README.rdoc +261 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config/application.rb +60 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +29 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +35 -0
- data/spec/dummy/config/environments/production.rb +68 -0
- data/spec/dummy/config/environments/test.rb +32 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/email.rb +1 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +4 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/schema.rb +237 -0
- data/spec/dummy/db/sql_data/services_isc_codes.sql +878 -0
- data/spec/dummy/log/test.log +3498 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/models/abaqis_mds_push_spec.rb +120 -0
- data/spec/models/available_file_spec.rb +234 -0
- data/spec/models/configured_account_spec.rb +39 -0
- data/spec/models/ftp_server_spec.rb +221 -0
- data/spec/models/isc_code_lookup_spec.rb +125 -0
- data/spec/models/isc_code_spec.rb +5 -0
- data/spec/models/mds_assessment_spec.rb +1070 -0
- data/spec/models/mds_pull_account_spec.rb +468 -0
- data/spec/models/mds_pull_spec.rb +48 -0
- data/spec/models/mds_push_spec.rb +43 -0
- data/spec/models/mds_ws_response_spec.rb +54 -0
- data/spec/models/pcc_mds_pull_spec.rb +273 -0
- data/spec/models/service_implementation_spec.rb +88 -0
- data/spec/models/sltc_api_exception_spec.rb +136 -0
- data/spec/models/sltc_api_spec.rb +192 -0
- data/spec/models/sltc_mds_pull_spec.rb +776 -0
- data/spec/roles/account_mapping_creator_spec.rb +40 -0
- data/spec/roles/account_mapping_updator_spec.rb +16 -0
- data/spec/roles/configured_account_creator_spec.rb +40 -0
- data/spec/roles/configured_account_updater_spec.rb +16 -0
- data/spec/roles/configured_facility_creator_spec.rb +40 -0
- data/spec/roles/configured_facility_updater_spec.rb +16 -0
- data/spec/roles/credential_creator_spec.rb +23 -0
- data/spec/roles/credential_updater_spec.rb +38 -0
- data/spec/roles/facility_mapping_creator_spec.rb +40 -0
- data/spec/roles/facility_mapping_updater_spec.rb +16 -0
- data/spec/roles/hl7_adt_message_saver_spec.rb +35 -0
- data/spec/roles/hl7_message_trimmer_spec.rb +31 -0
- data/spec/roles/monthly_service_table_cleaner_spec.rb +27 -0
- data/spec/roles/new_registration_notifier_spec.rb +18 -0
- data/spec/roles/service_ceator_spec.rb +34 -0
- data/spec/roles/service_definition_creator_spec.rb +40 -0
- data/spec/roles/service_definition_updater_spec.rb +16 -0
- data/spec/roles/service_invoker_spec.rb +22 -0
- data/spec/roles/service_updater_spec.rb +17 -0
- data/spec/roles/sltc_baseline_requestor_spec.rb +30 -0
- data/spec/roles/sltc_provider_lister_spec.rb +27 -0
- data/spec/roles/sltc_registration_completer_spec.rb +187 -0
- data/spec/roles/sltc_registration_saver_spec.rb +34 -0
- data/spec/roles/third_party_creator_spec.rb +34 -0
- data/spec/roles/third_party_updater_spec.rb +17 -0
- data/spec/spec_helper.rb +72 -0
- metadata +581 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module Services
|
|
2
|
+
|
|
3
|
+
module MdsNotifications
|
|
4
|
+
|
|
5
|
+
def handle_mds_notifications
|
|
6
|
+
logger.info "Fixing to notify the uploader: #{notify_the_uploader?}"
|
|
7
|
+
self.send_upload_confirmation if notify_the_uploader?
|
|
8
|
+
|
|
9
|
+
notification_type = self.account.mds_notification_type
|
|
10
|
+
return if notification_type == MdsNotification::NOTIFY_NONE
|
|
11
|
+
|
|
12
|
+
if notification_type == MdsNotification::NOTIFY_WHEN_UPLOADED
|
|
13
|
+
logger.info "Notifying for all uploads"
|
|
14
|
+
self.send_upload_confirmation(self.account.mds_notification_email)
|
|
15
|
+
else
|
|
16
|
+
# DS: Notice that an immediate account email will be sent out even if the notification
|
|
17
|
+
# type is set to NOTIFY_DAILY_DIGEST. THERE IS A REASON FOR THIS. Most accounts do not
|
|
18
|
+
# want to wait for the digest to be sent out to learn that there was an MDS upload error.
|
|
19
|
+
# These things don't happen very often, so it shouldn't be a major imposition to recieve
|
|
20
|
+
# these error emails.
|
|
21
|
+
#
|
|
22
|
+
# SO. DON'T CHANGE THIS UNLESS YOU HAVE BEEN EXPLICITLY ASKED TO CHANGE IT. I may have
|
|
23
|
+
# made a mistake here, but it was an _intentional_ mistake.
|
|
24
|
+
#
|
|
25
|
+
# Enjoy the rest of your day.
|
|
26
|
+
logger.info "Notifying for error uploads"
|
|
27
|
+
self.send_upload_confirmation(self.account.mds_notification_email) if has_errors?
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def notify_the_uploader?
|
|
33
|
+
self.notify_uploader? &&
|
|
34
|
+
self.upload_user.present? &&
|
|
35
|
+
self.upload_user.email.present?
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def send_upload_confirmation(notification_email=nil)
|
|
39
|
+
MDS_NOTIFICATION_MAILER.notify_mds_uploaded(self, notification_email).deliver
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Services
|
|
2
|
+
|
|
3
|
+
module MonthlyServiceTableCleaner
|
|
4
|
+
|
|
5
|
+
def clean_up_service_tables
|
|
6
|
+
Services::AssessmentRequest.destroy_all where_clause(Services::AssessmentRequest::STATUS_COMPLETED)
|
|
7
|
+
Services::AvailableFile.destroy_all where_clause(Services::AvailableFile::STATUS_CLEARED)
|
|
8
|
+
Services::MdsPullAccount.destroy_all where_clause(Services::MdsPullAccount::STATUS_REMOTE_CLEAN)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def where_clause(status)
|
|
14
|
+
"DATEDIFF(CURRENT_DATE, created_at) > 30 AND status = #{status}"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Services
|
|
2
|
+
|
|
3
|
+
module ServiceInvoker
|
|
4
|
+
|
|
5
|
+
#
|
|
6
|
+
# The async configuration options
|
|
7
|
+
#
|
|
8
|
+
ASYNC_SEND_OPTS = {
|
|
9
|
+
:priority => 100, # Pretty high priority; higher than MDS for sure
|
|
10
|
+
:time_to_run => 3600 # GIve it an hour
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
def invoke
|
|
14
|
+
service_definitions.each do | service_definition |
|
|
15
|
+
|
|
16
|
+
# Each service implementation is handled in a separate
|
|
17
|
+
# worker
|
|
18
|
+
service_definition.ayl_send_opts(:invoke, ASYNC_SEND_OPTS)
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Services
|
|
2
|
+
|
|
3
|
+
module SltcBaselineRequestor
|
|
4
|
+
|
|
5
|
+
def request_baseline(params)
|
|
6
|
+
provider_id = params[:provider_id]
|
|
7
|
+
uploaded_before = Time.parse(params[:uploaded_before])
|
|
8
|
+
uploaded_after = Time.parse(params[:uploaded_after])
|
|
9
|
+
|
|
10
|
+
sd = service_definition
|
|
11
|
+
|
|
12
|
+
si = sd.service_implementation
|
|
13
|
+
|
|
14
|
+
si.request_baseline(self, provider_id, uploaded_after, uploaded_before)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Services
|
|
2
|
+
|
|
3
|
+
module SltcProviderChangeNotifier
|
|
4
|
+
|
|
5
|
+
def notify
|
|
6
|
+
requiring_notification = ProviderChange.
|
|
7
|
+
where(status: ProviderChange::STATUS_NEW).
|
|
8
|
+
order("configured_account_id ASC, verb ASC")
|
|
9
|
+
|
|
10
|
+
return if requiring_notification.empty?
|
|
11
|
+
|
|
12
|
+
ServicesMailer.notify_sltc_provider_changes(requiring_notification).deliver
|
|
13
|
+
|
|
14
|
+
ids = requiring_notification.pluck(:id)
|
|
15
|
+
|
|
16
|
+
# Mark these guys as reported
|
|
17
|
+
ProviderChange.
|
|
18
|
+
connection.
|
|
19
|
+
execute("UPDATE services_provider_changes SET status = #{Services::ProviderChange::STATUS_REPORTED} WHERE id IN (#{ids.join(',')})")
|
|
20
|
+
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
module Services
|
|
2
|
+
|
|
3
|
+
module SltcRegistrationCompleter
|
|
4
|
+
|
|
5
|
+
def complete(params)
|
|
6
|
+
configure_only = params[:configure_only].present? && params[:configure_only] == 'true'
|
|
7
|
+
|
|
8
|
+
am = find_or_create_account_mapping(params[:third_party_id], params[:account_id])
|
|
9
|
+
|
|
10
|
+
ca = find_or_create_configured_account(params[:service_definition_id], params[:account_id], configure_only)
|
|
11
|
+
|
|
12
|
+
# The requestor only wants the account configured for operations. Does NOT
|
|
13
|
+
# want to process the registration any further at this time. The 'complete' method
|
|
14
|
+
# is re-entrant in that it will continue even if the account stuff has already been
|
|
15
|
+
# configured.
|
|
16
|
+
return if configure_only
|
|
17
|
+
|
|
18
|
+
si = ca.service_definition.service_implementation
|
|
19
|
+
|
|
20
|
+
# Take care of configuring all the facilities for the new account
|
|
21
|
+
si.identify_providers(ca)
|
|
22
|
+
|
|
23
|
+
# Now, request baselines for all the configured facilities
|
|
24
|
+
uploaded_before = Time.now
|
|
25
|
+
uploaded_after = uploaded_before - (params[:baseline_days].present? ? params[:baseline_days].to_i : 90).days
|
|
26
|
+
|
|
27
|
+
abaqis_facility_ids = ApplicationApi.api_impl.enabled_facilities_for_account_id(params[:account_id]).pluck(:id)
|
|
28
|
+
|
|
29
|
+
ca.service_definition.third_party.facility_mappings.where(facility_id: abaqis_facility_ids).each do | facility_mapping |
|
|
30
|
+
si.request_baseline(ca, facility_mapping.facility_code, uploaded_after, uploaded_before)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
update_attributes(status: Services::SltcRegistration::STATUS_REGISTERED)
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def find_or_create_account_mapping(third_party_id, account_id)
|
|
40
|
+
am = AccountMapping.where(third_party_id: third_party_id,
|
|
41
|
+
account_id: account_id,
|
|
42
|
+
account_code: account_code).first
|
|
43
|
+
unless am.present?
|
|
44
|
+
am = AccountMapping.create!(third_party_id: third_party_id,
|
|
45
|
+
account_id: account_id,
|
|
46
|
+
account_code: account_code)
|
|
47
|
+
|
|
48
|
+
end
|
|
49
|
+
am
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def find_or_create_configured_account(service_definition_id, account_id, configure_only=false)
|
|
53
|
+
ca = ConfiguredAccount.where(service_definition_id: service_definition_id,
|
|
54
|
+
account_id: account_id).first
|
|
55
|
+
|
|
56
|
+
account_enabled = configure_only ? false : true
|
|
57
|
+
|
|
58
|
+
if ca.present?
|
|
59
|
+
|
|
60
|
+
# Force the enabled flag to the correct value
|
|
61
|
+
ca.update_attribute(:enabled, account_enabled)
|
|
62
|
+
|
|
63
|
+
cred = ca.credentials.first
|
|
64
|
+
if cred.present?
|
|
65
|
+
cred.update_attributes(password: auth_password)
|
|
66
|
+
else
|
|
67
|
+
ca.credentials << Credential.new(password: auth_password)
|
|
68
|
+
end
|
|
69
|
+
else
|
|
70
|
+
ca = ConfiguredAccount.create!(service_definition_id: service_definition_id,
|
|
71
|
+
account_id: account_id,
|
|
72
|
+
enabled: account_enabled,
|
|
73
|
+
username: username)
|
|
74
|
+
ca.credentials << Credential.new(password: auth_password)
|
|
75
|
+
end
|
|
76
|
+
ca
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Services
|
|
2
|
+
|
|
3
|
+
module SubmitMdsFileForProcessing
|
|
4
|
+
TIME_TO_RUN = 36000
|
|
5
|
+
PRIORITY = 500
|
|
6
|
+
ASYNC_SEND_OPTIONS = { :priority => PRIORITY, :time_to_run => TIME_TO_RUN }
|
|
7
|
+
|
|
8
|
+
def submit_uploaded_file
|
|
9
|
+
errors = []
|
|
10
|
+
mds_upload = MdsUpload.new(:account => account,
|
|
11
|
+
:mds_file => uploaded_file,
|
|
12
|
+
:status => MdsUpload::NEW,
|
|
13
|
+
:upload_user => upload_user,
|
|
14
|
+
:file_errors => {},
|
|
15
|
+
:notify_uploader => notify_uploader)
|
|
16
|
+
|
|
17
|
+
if mds_upload.valid?
|
|
18
|
+
mds_upload.save!
|
|
19
|
+
MdsFileProcessingContext.ayl_send_opts(:call, ASYNC_SEND_OPTIONS, mds_upload)
|
|
20
|
+
else
|
|
21
|
+
errors.concat(mds_upload.errors[:mds_file])
|
|
22
|
+
end
|
|
23
|
+
errors
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#
|
|
2
|
+
# A mixin for controllers that want to clean out temporary files created
|
|
3
|
+
# for file uploads.
|
|
4
|
+
#
|
|
5
|
+
# Typically used as follows:
|
|
6
|
+
#
|
|
7
|
+
# class MyController < ApplicationController
|
|
8
|
+
# include FileUploadHandler
|
|
9
|
+
#
|
|
10
|
+
# after_filter :clear_temporary_files
|
|
11
|
+
#
|
|
12
|
+
# ...
|
|
13
|
+
#
|
|
14
|
+
# end
|
|
15
|
+
#
|
|
16
|
+
module Services
|
|
17
|
+
|
|
18
|
+
module FileUploadHandler
|
|
19
|
+
|
|
20
|
+
def clear_temporary_files(hash=params)
|
|
21
|
+
return if hash.nil?
|
|
22
|
+
hash.values.each do |v|
|
|
23
|
+
if v.is_a?(Hash)
|
|
24
|
+
clear_temporary_files(v)
|
|
25
|
+
elsif v.respond_to?(:path)
|
|
26
|
+
File.unlink(v.path) if File.exists?(v.path)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Services
|
|
2
|
+
|
|
3
|
+
module MdsUploadFilters
|
|
4
|
+
|
|
5
|
+
def must_have_uploaded_file
|
|
6
|
+
@uploaded_file = params[:composite_file]
|
|
7
|
+
if @uploaded_file.blank?
|
|
8
|
+
@errors = [ "Please select an MDS file for upload." ]
|
|
9
|
+
render action: :create
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def must_be_valid_mds_file
|
|
14
|
+
uv = UnzipmeValidator.new(@uploaded_file.path)
|
|
15
|
+
|
|
16
|
+
if ! uv.valid_zip?
|
|
17
|
+
@errors = [ "You have uploaded an invalid MDS 3.0 or MDS 3.0 Composite file." ]
|
|
18
|
+
error_stickie(@errors.first)
|
|
19
|
+
redirect_to stagei_mds_uploads_path
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
require 'libxml'
|
|
2
|
+
|
|
3
|
+
module Services
|
|
4
|
+
|
|
5
|
+
class MdsXmlFileParser
|
|
6
|
+
include LibXML
|
|
7
|
+
|
|
8
|
+
attr_reader :assessment_file, :file_errors
|
|
9
|
+
|
|
10
|
+
ROOT_NODE = "ASSESSMENT"
|
|
11
|
+
|
|
12
|
+
def initialize(assessment_file)
|
|
13
|
+
@assessment_file = assessment_file
|
|
14
|
+
@base_name = File.basename(assessment_file)
|
|
15
|
+
@file_errors = { @base_name => [] }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def parse
|
|
19
|
+
|
|
20
|
+
begin
|
|
21
|
+
sax_handler = MdsSaxHandler.new
|
|
22
|
+
File.open(assessment_file, "r") do | f |
|
|
23
|
+
parser = LibXML::XML::SaxParser.io(f)
|
|
24
|
+
parser.callbacks = sax_handler
|
|
25
|
+
parser.parse
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
rescue LibXML::XML::Error
|
|
29
|
+
add_error "XML root element ASSESSMENT not found."
|
|
30
|
+
return
|
|
31
|
+
rescue
|
|
32
|
+
add_error "There was a problem parsing this file. Please ensure that it has the correct MDS 3.0 XML format."
|
|
33
|
+
return
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
add_error(sax_handler.errors) if sax_handler.errors.present?
|
|
37
|
+
return if has_errors?
|
|
38
|
+
|
|
39
|
+
add_error("XML data elements were not found.") if sax_handler.assessment_hash.empty?
|
|
40
|
+
return if has_errors?
|
|
41
|
+
|
|
42
|
+
sax_handler.assessment_hash
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def add_error(error)
|
|
48
|
+
if error.is_a?(Array)
|
|
49
|
+
@file_errors[@base_name].concat(error)
|
|
50
|
+
else
|
|
51
|
+
@file_errors[@base_name] << error
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def has_errors?
|
|
56
|
+
@file_errors[@base_name].present?
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# ----------------------------------------------------------------------------#
|
|
62
|
+
# Using LibXML with SAX API for performance reasons. #
|
|
63
|
+
# ----------------------------------------------------------------------------#
|
|
64
|
+
|
|
65
|
+
class MdsSaxHandler
|
|
66
|
+
include LibXML::XML::SaxParser::Callbacks
|
|
67
|
+
|
|
68
|
+
attr_reader :assessment_hash, :errors
|
|
69
|
+
|
|
70
|
+
ROOT_NESTING_LEVEL = 0
|
|
71
|
+
ATTRIBUTE_NESTING_LEVEL = 1
|
|
72
|
+
TEXT_NESTING_LEVEL = 2
|
|
73
|
+
|
|
74
|
+
def initialize
|
|
75
|
+
@assessment_hash = {}
|
|
76
|
+
@file_errors = []
|
|
77
|
+
@xml_nesting_level = ROOT_NESTING_LEVEL
|
|
78
|
+
@element_text = nil
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def on_start_element(element_name, attributes)
|
|
82
|
+
if @xml_nesting_level == ROOT_NESTING_LEVEL
|
|
83
|
+
@file_errors << "XML root element ASSESSMENT not found." unless element_name == "ASSESSMENT"
|
|
84
|
+
end
|
|
85
|
+
@xml_nesting_level += 1
|
|
86
|
+
@element_text = ''
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def on_characters(text)
|
|
90
|
+
@element_text << text if @xml_nesting_level == TEXT_NESTING_LEVEL
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def on_end_element(element_name)
|
|
94
|
+
@assessment_hash[element_name.downcase] = @element_text.strip if !@element_text.nil? && @xml_nesting_level == TEXT_NESTING_LEVEL
|
|
95
|
+
@xml_nesting_level -= 1
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def on_error(error)
|
|
99
|
+
@file_errors << error.message
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
|
|
2
|
+
class IscCodeValidator < ActiveModel::EachValidator
|
|
3
|
+
|
|
4
|
+
def validate_each(object, attribute, value)
|
|
5
|
+
isc_lookup = Services::IscCodeLookup.new(object)
|
|
6
|
+
object.errors[attribute] << "The ISC Code provided: #{isc_lookup.isc_provided_value} is incorrect for this assessment." unless isc_lookup.valid_isc_value?
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
#-----------------------------------------------------------------#
|
|
12
|
+
# Removing the custom message below for performance reasons #
|
|
13
|
+
#-----------------------------------------------------------------#
|
|
14
|
+
def build_error_message(object, isc_lookup)
|
|
15
|
+
message = "The ISC value in this file (#{isc_lookup.isc_provided_value}), "
|
|
16
|
+
message += cms_table_message(isc_lookup)
|
|
17
|
+
message += "Please ensure these values are correct: "
|
|
18
|
+
message += attribute_message(isc_lookup, object)
|
|
19
|
+
message
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def cms_table_message(isc_lookup)
|
|
24
|
+
if isc_lookup.isc_lookup_value.nil?
|
|
25
|
+
message = "does not match any value provided in the CMS lookup table. "
|
|
26
|
+
else
|
|
27
|
+
message = "does not match the value provided in the CMS lookup table (#{isc_lookup.isc_lookup_value}). "
|
|
28
|
+
end
|
|
29
|
+
message
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def attribute_message(isc_lookup, object)
|
|
33
|
+
if isc_lookup.isc_lookup_value == IscCode.inactivation_code
|
|
34
|
+
message = "x0100 => #{object.x0100} "
|
|
35
|
+
else
|
|
36
|
+
message = "a0200 => #{object.a0200}, a0310a => #{object.a0310a}, a0310b => #{object.a0310b}, a0310c => #{object.a0310c}, a0310d => #{object.a0310d}, a0310f => #{object.a0310f}."
|
|
37
|
+
end
|
|
38
|
+
message
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
class MdsBirthdateValidator < ActiveModel::EachValidator
|
|
2
|
+
|
|
3
|
+
def validate_each(record, attribute, value)
|
|
4
|
+
return true if record.send("clean_#{attribute}").blank?
|
|
5
|
+
# return true if value.blank? || Resident.missing_attribute_values.include?(value)
|
|
6
|
+
record.errors[attribute] << "Invalid birth date entered in #{attribute}. Birth date may contain only numbers." and return if value =~ /\D/
|
|
7
|
+
record.errors[attribute] << "Invalid birth date entered in #{attribute}. Birth date must be formatted as YYYYMMDD, YYYYMM or YYYY." and return unless birthdate_correct_length?(value)
|
|
8
|
+
record.errors[attribute] << "Invalid birth date entered in #{attribute}. Birth date is not valid." unless birthdate_ymd_valid?(value)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def birthdate_correct_length?(birthdate)
|
|
15
|
+
return true if birthdate.blank?
|
|
16
|
+
return true if [4, 6, 8].include?(birthdate.length)
|
|
17
|
+
false
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
#----------------------------------------------------#
|
|
21
|
+
# If it gets here, then it is of correct length #
|
|
22
|
+
#----------------------------------------------------#
|
|
23
|
+
def birthdate_ymd_valid?(birthdate)
|
|
24
|
+
return true if birthdate.blank?
|
|
25
|
+
year, month, day = birthdate.slice(0,4), birthdate.slice(4,2), birthdate.slice(6,2)
|
|
26
|
+
year_valid?(year) && month_valid?(month) && day_valid?(day)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def year_valid?(year) year =~ /\A(18|19|20)\d\d/; end
|
|
30
|
+
|
|
31
|
+
def month_valid?(month) return true if month.blank?; month =~ /\A(0[1-9]|1[012])/; end
|
|
32
|
+
|
|
33
|
+
def day_valid?(day) return true if day.blank?; day =~ /\A(0[1-9]|[12][0-9]|3[01])/; end
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
end
|
|
37
|
+
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
class MdsDateValidator < ActiveModel::EachValidator
|
|
2
|
+
|
|
3
|
+
def validate_each(record, attribute, value)
|
|
4
|
+
return if value.is_a?(Date) # We store dates as Date's; don't validate if it is already a date.
|
|
5
|
+
record.errors[attribute] << "A valid date in item #{attribute} is required for this assessment type." if Date.safe_parse(value).blank?
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
end
|