renalware-core 2.0.41 → 2.0.42

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/renalware/aki_alerts.js +27 -0
  3. data/app/assets/javascripts/renalware/application.js.erb +1 -1
  4. data/app/assets/javascripts/renalware/behaviours.js +5 -0
  5. data/app/assets/stylesheets/renalware/modules/_hd.scss +9 -0
  6. data/app/assets/stylesheets/renalware/partials/_button.scss +4 -0
  7. data/app/assets/stylesheets/renalware/partials/_tables.scss +6 -0
  8. data/app/controllers/renalware/events/events_controller.rb +3 -15
  9. data/app/controllers/renalware/hd/transmission_logs_controller.rb +32 -0
  10. data/app/controllers/renalware/renal/aki_alerts_controller.rb +2 -2
  11. data/app/controllers/renalware/research/study_participants_controller.rb +5 -0
  12. data/app/documents/renalware/hd/session_document.rb +13 -0
  13. data/app/jobs/feed_job.rb +4 -1
  14. data/app/models/concerns/renalware/patients_ransack_helper.rb +4 -0
  15. data/app/models/renalware/events/event_query.rb +0 -1
  16. data/app/models/renalware/feeds/message_processor.rb +30 -6
  17. data/app/models/renalware/feeds/persist_message.rb +7 -6
  18. data/app/models/renalware/hd/provider.rb +12 -0
  19. data/app/models/renalware/hd/provider_unit.rb +15 -0
  20. data/app/models/renalware/hd/transmission_log.rb +26 -0
  21. data/app/models/renalware/letters/letter/pending_review.rb +8 -1
  22. data/app/models/renalware/medications/prescriptions_by_drug_type_query.rb +0 -1
  23. data/app/models/renalware/pathology/message_listener.rb +7 -7
  24. data/app/models/renalware/pathology/observation_requests_attributes_builder.rb +5 -5
  25. data/app/models/renalware/pathology/observations_jsonb_serializer.rb +0 -1
  26. data/app/models/renalware/patients/message_param_parser.rb +2 -2
  27. data/app/models/renalware/patients/patient_search.rb +2 -2
  28. data/app/models/renalware/renal/aki_alert.rb +4 -0
  29. data/app/models/renalware/renal/aki_alert_query.rb +0 -1
  30. data/app/models/renalware/renal/aki_alert_search_form.rb +2 -2
  31. data/app/models/renalware/renal.rb +0 -2
  32. data/app/views/renalware/hd/transmission_logs/index.html.slim +42 -0
  33. data/app/views/renalware/medications/drug_types/prescriptions/_filters.html.slim +1 -3
  34. data/app/views/renalware/navigation/_admin.html.slim +1 -2
  35. data/app/views/renalware/navigation/_renal.html.slim +1 -1
  36. data/app/views/renalware/navigation/_super_admin.html.slim +2 -0
  37. data/app/views/renalware/renal/aki_alerts/_aki_alert.html.slim +1 -3
  38. data/app/views/renalware/renal/aki_alerts/_filters.html.slim +35 -15
  39. data/app/views/renalware/renal/aki_alerts/_filters.pdf.slim +4 -1
  40. data/app/views/renalware/renal/aki_alerts/edit.html.slim +2 -2
  41. data/app/views/renalware/renal/aki_alerts/index.html.slim +1 -1
  42. data/app/views/renalware/renal/aki_alerts/index.pdf.slim +0 -5
  43. data/config/initializers/ransack.rb +15 -1
  44. data/config/permissions.yml +3 -0
  45. data/config/routes.rb +2 -4
  46. data/db/migrate/20151116170200_create_transplant_versions.rb +3 -3
  47. data/db/migrate/20180622130552_add_external_id_to_hd_sessions.rb +6 -0
  48. data/db/migrate/20180625124431_add_patient_identifier_to_feed_messages.rb +7 -0
  49. data/db/migrate/20180702091222_create_hd_providers.rb +8 -0
  50. data/db/migrate/20180702091237_create_hd_provider_units.rb +11 -0
  51. data/db/migrate/20180702091352_create_hd_transmission_log.rb +18 -0
  52. data/db/migrate/20180730154454_add_external_session_id_to_hd_transmission_logs.rb +9 -0
  53. data/db/migrate/20180802132417_add_missing_indexes_2.rb +18 -0
  54. data/db/migrate/20180802144507_add_missing_foreign_key_indexes.rb +17 -0
  55. data/db/migrate/20180803131157_add_uuid_to_hd_transmission_logs.rb +5 -0
  56. data/db/migrate/20180814103916_create_index_on_lower_patient_family_name.rb +7 -0
  57. data/db/migrate/20180815144429_update_hd_overall_audit_to_version_8.rb +6 -0
  58. data/db/views/reporting_hd_overall_audit_v08.sql +46 -0
  59. data/lib/renalware/version.rb +1 -1
  60. data/lib/tasks/db.rake +13 -0
  61. data/lib/tasks/pathology.rake +29 -0
  62. data/spec/factories/hd/transmission_logs.rb +15 -0
  63. data/spec/support/capybara.rb +16 -15
  64. data/vendor/assets/javascripts/renalware/moment.min.js +1 -0
  65. metadata +25 -4
@@ -10,6 +10,6 @@ li.has-dropdown
10
10
  li= link_to t(".letters"), letters_list_path
11
11
  li= link_to t(".esa_prescriptions"), medications_esa_prescriptions_path
12
12
  li= link_to t(".audits"), reporting_audits_path
13
- li= link_to t(".aki_alerts"), renal_filtered_aki_alerts_path(named_filter: :today)
13
+ li= link_to t(".aki_alerts"), renal_aki_alerts_path
14
14
  li= link_to t(".studies"), research_studies_path
15
15
  li= link_to t(".renal_registry_checks"), patients_renal_registry_preflight_checks_path
@@ -11,3 +11,5 @@ li.has-dropdown
11
11
  li= link_to "User Feedback", system_user_feedback_index_path
12
12
  li= link_to "System Messages", system_messages_path
13
13
  li= link_to "HD Dialysates", hd_dialysates_path
14
+ li= link_to "HD Dialysers", hd_dialysers_path
15
+ li= link_to "HD Cannulation Types", hd_cannulation_types_path
@@ -12,8 +12,7 @@ tr(class="#{'aki_alert--hotlist' if aki_alert.hotlist?}")
12
12
  td= aki_alert.patient.sex
13
13
  td= aki_alert.patient.age
14
14
  td= aki_alert.action
15
- td= [aki_alert.hospital_ward, aki_alert.hospital_ward&.hospital_unit&.unit_code]\
16
- .compact.join(" - ")
15
+ td= "#{aki_alert.hospital_ward} @#{aki_alert.hospital_ward&.hospital_unit&.unit_code}"
17
16
  td= yes_no aki_alert.hotlist?
18
17
  td= aki_alert.max_aki
19
18
  td= l(aki_alert.aki_date)
@@ -23,4 +22,3 @@ tr(class="#{'aki_alert--hotlist' if aki_alert.hotlist?}")
23
22
  td(colspan=10)
24
23
  .quick-preview
25
24
  =aki_alert.notes
26
-
@@ -4,36 +4,56 @@ ruby:
4
4
  suspended: "All"
5
5
  }
6
6
 
7
- h2.print-only= filters[path_params[:named_filter].to_sym]
7
+ scss:
8
+ .link_to_right_of_input_label {
9
+ position: absolute;
10
+ top: 0;
11
+ right: 0;
12
+ padding-right: .2rem;
13
+ }
14
+
15
+ /h2.print-only= filters[path_params[:named_filter].to_sym]
8
16
 
9
- dl.sub-nav
10
- - Renalware::Renal::AKI_ALERT_FILTERS.each do |key|
11
- - options = path_params.merge(named_filter: key).to_h.symbolize_keys
12
- - path = Renalware::Engine.routes.url_for(options.merge!(only_path: true))
13
- = sub_nav_item(key.to_s.humanize, path)
17
+ / dl.sub-nav
18
+ / - Renalware::Renal::AKI_ALERT_FILTERS.each do |key|
19
+ / - options = path_params.merge(named_filter: key).to_h.symbolize_keys
20
+ / - path = Renalware::Engine.routes.url_for(options.merge!(only_path: true))
21
+ / = sub_nav_item(key.to_s.humanize, path)
14
22
 
15
23
  .search-form.filters
16
24
  = simple_form_for form,
17
25
  as: :q,
18
- url: renal_filtered_aki_alerts_path,
26
+ url: renal_aki_alerts_path,
19
27
  method: :get do |f|
20
28
 
21
29
  .row
22
- .columns.medium-2.large-3
23
- = f.input :term, label: "Hosp/NHS no or name"
30
+ .columns.medium-3.large-2
31
+ = f.input :term, label: "Hosp/NHS No. or name"
32
+ .columns.medium-2.large-2
33
+ = f.input :date, as: :date_picker
34
+ .link_to_right_of_input_label
35
+ a.set_filter_date_to_today(href="") Today
36
+ |  | 
37
+ a.set_filter_date_to_any_date(href="") Clear
24
38
  .columns.medium-1.large-1
25
39
  = f.input :on_hotlist,
26
- collection: [["Yes",true],["No",false]]
40
+ collection: [["Yes",true],["No",false]],
41
+ label: "Hotlist"
27
42
  .columns.medium-2.large-2
28
43
  = f.input :action,
29
44
  collection: Renalware::Renal::AKIAlertAction.pluck(:name, :id)
30
- .columns.medium-3.large-2
31
- = f.input :hospital_unit_id,
32
- collection: Renalware::Hospitals::Unit.pluck(:name, :id)
33
45
  .columns.medium-2.large-2
34
46
  = f.input :hospital_ward_id,
35
- collection: Renalware::Hospitals::Ward.pluck(:name, :id)
47
+ as: :grouped_select,
48
+ group_method: :wards,
49
+ collection: Renalware::Hospitals::Unit.joins(:wards).includes(:wards).ordered,
50
+ label_method: ->(s) { "#{s.name} @#{s.hospital_unit.unit_code}" },
51
+ input_html: { class: "searchable_select" },
52
+ label: "Ward"
53
+
54
+ a.link_to_right_of_input_label(href="javascript:$('#q_hospital_ward_id').val(null).trigger('change');") Clear
36
55
  .columns.medium-2.large-2.actions.end
37
56
  = f.submit "Filter", class: "button"
38
57
  span= " or "
39
- = link_to t("helpers.reset"), renal_filtered_aki_alerts_path
58
+ = link_to t("helpers.reset"), renal_aki_alerts_path
59
+ br
@@ -8,6 +8,9 @@
8
8
  - if filters.empty?
9
9
  td None
10
10
  - else
11
+ - if filters[:date].present?
12
+ th Date:
13
+ td= filters[:date]
11
14
  - if filters[:term].present?
12
15
  th Query:
13
16
  td= filters[:term]
@@ -16,7 +19,7 @@
16
19
  td= yes_no(filters[:on_hotlist] == "true")
17
20
  - if filters[:action].present?
18
21
  th Action:
19
- td= Renalware::Renal::AKIAlertAction.find(filters[:action])&.to_s
22
+ td= Renalware::Renal::AKIAlertAction.find(filters[:action])&.to_s
20
23
  - if filters[:hospital_unit_id].present?
21
24
  th Site:
22
25
  td= Renalware::Hospitals::Unit.find_by(id: filters[:hospital_unit_id])
@@ -1,5 +1,5 @@
1
1
  = within_admin_layout(title: "Edit",
2
- breadcrumbs: breadcrumb_for("AKI Alerts", renal_filtered_aki_alerts_path(named_filter: :today))) do
2
+ breadcrumbs: breadcrumb_for("AKI Alerts", renal_aki_alerts_path)) do
3
3
 
4
4
  = simple_form_for(alert, wrapper: :horizontal_form) do |f|
5
5
  = f.association :action, wrapper: :horizontal_small
@@ -17,4 +17,4 @@
17
17
  = f.input :notes, wrapper: :horizontal_large, input_html: { rows: 5 }
18
18
  = f.submit class: "button"
19
19
  span= " or "
20
- = link_to "cancel", renal_filtered_aki_alerts_path(named_filter: :today)
20
+ = link_to "cancel", renal_aki_alerts_path
@@ -3,7 +3,7 @@
3
3
  / An alternative to what we have used here is to use
4
4
  / url_for(request.filtered_parameters&.merge({format: :pdf})
5
5
  / however this seems to loose the ransack sort option in params[:q][:s]
6
- = link_to(renal_filtered_aki_alerts_path(q: params[:q]&.permit!, format: :pdf), class: "button secondary") do
6
+ = link_to(renal_aki_alerts_path(q: params[:q]&.permit!, format: :pdf), class: "button secondary") do
7
7
  i.fa.fa-print
8
8
  | Print (PDF)
9
9
 
@@ -4,11 +4,6 @@
4
4
  .pdf
5
5
  .header
6
6
  h1 AKI Alerts
7
- - if params[:named_filter].present?
8
- h1.muted
9
- |  / 
10
- = params[:named_filter]&.humanize
11
7
  h2.muted= I18n.l(Time.zone.today)
12
8
  = render "filters"
13
9
  = render "table", alerts: alerts
14
-
@@ -7,10 +7,24 @@ Ransack.configure do |config|
7
7
 
8
8
  # Raise errors if a query contains an unknown predicate or attribute.
9
9
  # Default is true (do not raise error on unknown conditions).
10
- # config.ignore_unknown_conditions = false
10
+ config.ignore_unknown_conditions = !Rails.env.development?
11
11
 
12
12
  # Globally display sort links without the order indicator arrow.
13
13
  # Default is false (sort order indicators are displayed).
14
14
  # This can also be configured individually in each sort link (see the README).
15
15
  # config.hide_sort_order_indicators = true
16
+ #
17
+
18
+ # Add a predicate to allow a datepicker for instance to find all items
19
+ # with a certain created_at. It ensures the datetime is resolved as a date.
20
+ # See
21
+ # - https://github.com/activerecord-hackery/ransack/issues/101
22
+ # - https://github.com/activerecord-hackery/ransack/wiki/Custom-Predicates
23
+ config.add_predicate(
24
+ "date_equals",
25
+ arel_predicate: "eq",
26
+ formatter: proc { |val| val&.to_date },
27
+ validator: proc { |val| val.present? },
28
+ type: :string
29
+ )
16
30
  end
@@ -2,6 +2,8 @@ super_admin:
2
2
  - Renalware::Role
3
3
  - Renalware::Hospitals::Ward
4
4
  - Renalware::HD::Dialysate
5
+ - Renalware::HD::Dialyser
6
+ - Renalware::HD::CannulationType
5
7
  admin:
6
8
  - Renalware::User
7
9
  - Renalware::BagType
@@ -15,3 +17,4 @@ admin:
15
17
  - Renalware::PRDDescription
16
18
  - Renalware::Hospitals::Unit
17
19
  - Renalware::HD::Station
20
+ - Renalware::HD::TransmissionLog
data/config/routes.rb CHANGED
@@ -156,6 +156,7 @@ Renalware::Engine.routes.draw do
156
156
  get "patients_dialysing_at_hospital" => "patients#dialysing_at_hospital"
157
157
  end
158
158
 
159
+ resources :transmission_logs, only: [:show, :index]
159
160
  resources :cannulation_types, except: :show
160
161
  resources :dialysers, except: :show
161
162
  resources :dialysates, except: :show
@@ -247,10 +248,7 @@ Renalware::Engine.routes.draw do
247
248
  get :search
248
249
  end
249
250
  end
250
- resources :aki_alerts, only: [:edit, :update]
251
- constraints(named_filter: /#{Renalware::Renal::AKI_ALERT_FILTERS.join("|")}/) do
252
- get "aki_alerts/:named_filter", to: "aki_alerts#index", as: :filtered_aki_alerts
253
- end
251
+ resources :aki_alerts, only: [:edit, :update, :index]
254
252
  resources :registry_preflight_checks, only: [] do
255
253
  collection do
256
254
  get :patients
@@ -1,9 +1,9 @@
1
1
  class CreateTransplantVersions < ActiveRecord::Migration[4.2]
2
2
  def change
3
3
  create_table :transplant_versions do |t|
4
- t.string :item_type, :null => false
5
- t.integer :item_id, :null => false
6
- t.string :event, :null => false
4
+ t.string :item_type, null: false
5
+ t.integer :item_id, null: false
6
+ t.string :event, null: false
7
7
  t.string :whodunnit
8
8
  t.jsonb :object
9
9
  t.jsonb :object_changes
@@ -0,0 +1,6 @@
1
+ class AddExternalIdToHDSessions < ActiveRecord::Migration[5.1]
2
+ def change
3
+ add_column :hd_sessions, :external_id, :bigint
4
+ add_index :hd_sessions, :external_id, unique: true
5
+ end
6
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddPatientIdentifierToFeedMessages < ActiveRecord::Migration[5.1]
4
+ def change
5
+ add_column :feed_messages, :patient_identifier, :string, index: true
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ class CreateHDProviders < ActiveRecord::Migration[5.1]
2
+ def change
3
+ create_table "renalware.hd_providers" do |t|
4
+ t.string :name
5
+ t.timestamps null: false
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ class CreateHDProviderUnits < ActiveRecord::Migration[5.1]
2
+ def change
3
+ create_table "renalware.hd_provider_units" do |t|
4
+ t.references :hospital_unit, foreign_key: true, null: false
5
+ t.references :hd_provider, foreign_key: true, null: false
6
+ t.string :providers_reference, index: true
7
+ t.timestamps null: false
8
+ end
9
+ add_index :hd_provider_units, [:hd_provider_id, :hospital_unit_id], unique: true
10
+ end
11
+ end
@@ -0,0 +1,18 @@
1
+ class CreateHDTransmissionLog < ActiveRecord::Migration[5.1]
2
+ def change
3
+ create_table "renalware.hd_transmission_logs" do |t|
4
+ t.references :parent, index: true
5
+ t.string :direction, null: false, index: true
6
+ t.string :format, null: false, index: true
7
+ t.string :status, index: true
8
+ t.references :hd_provider_unit, foreign_key: true, index: true
9
+ t.references :patient, foreign_key: true, index: true
10
+ t.string :filepath
11
+ t.text :payload
12
+ t.jsonb :result, index: { using: :gin }, default: {}
13
+ t.text :error_messages, array: true, default: []
14
+ t.datetime :transmitted_at, index: true
15
+ t.timestamps null: false
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,9 @@
1
+ class AddExternalSessionIdToHDTransmissionLogs < ActiveRecord::Migration[5.1]
2
+ def change
3
+ add_column :hd_transmission_logs,
4
+ :external_session_id,
5
+ :string,
6
+ index: true
7
+ add_reference :hd_transmission_logs, :session, index: true, null: true
8
+ end
9
+ end
@@ -0,0 +1,18 @@
1
+ class AddMissingIndexes2 < ActiveRecord::Migration[5.1]
2
+ def change
3
+ # These indexes where missed as we had used the add_column method passing in index: true
4
+ # but that is not supported so no index was created
5
+ add_index :addresses, :country_id
6
+ add_index :patients, :country_of_birth_id
7
+ add_index :patients, :sent_to_ukrdc_at
8
+ add_index :patients, :send_to_renalreg
9
+ add_index :patients, :send_to_rpv
10
+ add_index :patient_bookmarks, :urgent
11
+ add_index :letter_recipients, :emailed_at
12
+ add_index :letter_recipients, :printed_at
13
+ add_index :hospital_wards, :code
14
+ add_index :feed_messages, :patient_identifier
15
+ add_index :access_procedures, :performed_by
16
+ add_index :patient_ethnicities, :cfh_name
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ class AddMissingForeignKeyIndexes < ActiveRecord::Migration[5.1]
2
+ # Found using https://github.com/gregnavis/active_record_doctor
3
+ def change
4
+ add_index :drug_types_drugs, :drug_type_id
5
+ add_index :hd_stations, :location_id
6
+ add_index :letter_contacts, :patient_id
7
+ add_index :messaging_messages, :replying_to_message_id
8
+ add_index :pathology_observation_descriptions, :measurement_unit_id
9
+ add_index :patient_bookmarks, :user_id
10
+ add_index(
11
+ :pd_peritonitis_episode_types, :peritonitis_episode_type_description_id,
12
+ name: "index_pd_peritonitis_episode_types_description_id"
13
+ )
14
+ add_index :pd_pet_adequacy_results, :patient_id
15
+ add_index :roles_users, :role_id
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ class AddUuidToHDTransmissionLogs < ActiveRecord::Migration[5.1]
2
+ def change
3
+ add_column :hd_transmission_logs, :uuid, :uuid, default: "uuid_generate_v4()", null: false
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ class CreateIndexOnLowerPatientFamilyName < ActiveRecord::Migration[5.1]
2
+ def change
3
+ add_index :patients,
4
+ "lower(family_name), given_name",
5
+ name: "idx_patients_on_lower_family_name"
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ class UpdateHDOverallAuditToVersion8 < ActiveRecord::Migration[5.1]
2
+ update_view :reporting_hd_overall_audit,
3
+ materialized: true,
4
+ version: 8,
5
+ revert_to_version: 7
6
+ end
@@ -0,0 +1,46 @@
1
+ WITH fistula_or_graft_access_types AS (
2
+ select id from access_types where name ilike '%fistula%' or name ilike '%graft%'
3
+ )
4
+ , patients_w_fistula_or_graft as (
5
+ select patient_id from access_profiles where type_id in (select id from fistula_or_graft_access_types)
6
+ ),
7
+ stats as (
8
+ select
9
+ s.patient_id,
10
+ s.hospital_unit_id,
11
+ s.month,
12
+ s.year,
13
+ s.session_count,
14
+ s.number_of_missed_sessions,
15
+ s.number_of_sessions_with_dialysis_minutes_shortfall_gt_5_pct,
16
+ exists(select x.patient_id from patients_w_fistula_or_graft x where x.patient_id = s.patient_id) as has_fistula_or_graft,
17
+ ((number_of_missed_sessions::float / NULLIF(session_count::float, 0)) * 100.0) > 10.0 as missed_sessions_gt_10_pct,
18
+ s.dialysis_minutes_shortfall::float,
19
+ convert_to_float(s.pathology_snapshot -> 'HGB' ->> 'result') > 100 as hgb_gt_100,
20
+ convert_to_float(s.pathology_snapshot -> 'HGB' ->> 'result') > 130 as hgb_gt_130,
21
+ convert_to_float(s.pathology_snapshot -> 'PTH' ->> 'result') < 300 as pth_lt_300,
22
+ convert_to_float(s.pathology_snapshot -> 'URR' ->> 'result') > 64 as urr_gt_64,
23
+ convert_to_float(s.pathology_snapshot -> 'URR' ->> 'result') > 69 as urr_gt_69,
24
+ convert_to_float(s.pathology_snapshot -> 'PHOS' ->> 'result') < 1.8 as phos_lt_1_8
25
+ from hd_patient_statistics s
26
+ where s.rolling is null
27
+ )
28
+ select
29
+ hu.name,
30
+ stats.year,
31
+ stats.month,
32
+ count(*) as patient_count,
33
+ round(avg(stats.dialysis_minutes_shortfall)::decimal, 2) as avg_missed_hd_time,
34
+ round(avg(number_of_sessions_with_dialysis_minutes_shortfall_gt_5_pct),2) as pct_shortfall_gt_5_pct,
35
+ round(((count(*) filter(where missed_sessions_gt_10_pct = true))::float / count(*)::float * 100)::decimal, 2) as pct_missed_sessions_gt_10_pct,
36
+ round(((count(*) filter(where hgb_gt_100 = true))::float / count(*)::float * 100)::decimal, 2) as percentage_hgb_gt_100,
37
+ round(((count(*) filter(where hgb_gt_130 = true))::float / count(*)::float * 100)::decimal, 2) as percentage_hgb_gt_130,
38
+ round(((count(*) filter(where pth_lt_300 = true))::float / count(*)::float * 100)::decimal, 2) as percentage_pth_lt_300,
39
+ round(((count(*) filter(where urr_gt_64 = true))::float / count(*)::float * 100)::decimal, 2) as percentage_urr_gt_64,
40
+ round(((count(*) filter(where urr_gt_69 = true))::float / count(*)::float * 100)::decimal, 2) as percentage_urr_gt_69,
41
+ round(((count(*) filter(where phos_lt_1_8 = true))::float / count(*)::float * 100)::decimal, 2) as percentage_phosphate_lt_1_8,
42
+ round(((((count(*) FILTER (WHERE (stats.has_fistula_or_graft = true)))::double precision / (count(*))::double precision) * (100)::double precision))::numeric, 2) AS percentage_access_fistula_or_graft
43
+ from stats
44
+ inner join hospital_units hu on hu.id = stats.hospital_unit_id
45
+ group by hu.name, stats.year, stats.month
46
+ order by hu.name, stats.year asc, stats.month asc;
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Renalware
4
- VERSION = "2.0.41"
4
+ VERSION = "2.0.42"
5
5
  end
data/lib/tasks/db.rake CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "benchmark"
2
4
 
3
5
  namespace :db do
@@ -8,4 +10,15 @@ namespace :db do
8
10
  end
9
11
  puts "Refreshing materialized views took #{ms}"
10
12
  end
13
+
14
+ namespace :demo do
15
+ desc "Loads demo seed data from the renalware-core gem"
16
+ task seed: :environment do
17
+ if Rails.env.development?
18
+ require Renalware::Engine.root.join("spec/dummy/db/seeds")
19
+ else
20
+ puts "Task currently only possible in development environment"
21
+ end
22
+ end
23
+ end
11
24
  end
@@ -0,0 +1,29 @@
1
+ require "benchmark"
2
+
3
+ namespace :pathology do
4
+ namespace :test do
5
+ desc "In development only, import a test HL7 message. Useful for testing listeners."
6
+ task import_one: :environment do
7
+ raise NotImplementedError unless Rails.env.development?
8
+
9
+ # Load the example HL7 file.
10
+ path = Renalware::Engine.root.join("app", "jobs", "hl7_message_example.yml")
11
+ raw_message = File.read(path)
12
+
13
+ # It has a struct header at the top so it can also be dumped into
14
+ # the delayed_job queue, but we want to skip queuing so strip out that header and simulate
15
+ # the message being passed directly to the FeedJob which will persist and process the message.
16
+ raw_message = raw_message.gsub("--- !ruby/struct:FeedJob\n", "")
17
+
18
+ # Replace the MSH date with now() to guarantee a unique message. not doing so results in
19
+ # an index violation becuase we calc am MD5 hash of the message and this has to be unique -
20
+ # this prevents us importing the same message twice.
21
+ raw_message = raw_message.gsub("20091112164645", Time.zone.now.strftime("%Y%m%d%H%M%S"))
22
+
23
+ # Load the message into a hash as delayed_Job would do and splat the hash keys as keyword args
24
+ # into the FeedJob ctor.
25
+ hash = YAML.safe_load(*raw_message).symbolize_keys
26
+ FeedJob.new(hash[:raw_message]).perform
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ FactoryBot.define do
4
+ factory :hd_transmission_log, class: "Renalware::HD::TransmissionLog" do
5
+ trait :outgoing_hl7 do
6
+ direction :out
7
+ format :hl7
8
+ end
9
+
10
+ trait :incoming_xml do
11
+ direction :in
12
+ format :xml
13
+ end
14
+ end
15
+ end
@@ -1,22 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # # frozen_string_literal: true
4
+ if defined?(Capybara)
5
+ Capybara.register_driver(:headless_chrome) do |app|
6
+ capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
7
+ chromeOptions: { args: %w(headless disable-gpu window-size=1366,1768) }
8
+ )
4
9
 
5
- Capybara.register_driver(:headless_chrome) do |app|
6
- capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
7
- chromeOptions: { args: %w(headless disable-gpu window-size=1366,1768) }
8
- )
9
-
10
- Capybara::Selenium::Driver.new(
11
- app,
12
- browser: :chrome,
13
- desired_capabilities: capabilities
14
- )
15
- end
10
+ Capybara::Selenium::Driver.new(
11
+ app,
12
+ browser: :chrome,
13
+ desired_capabilities: capabilities
14
+ )
15
+ end
16
16
 
17
- if RUBY_PLATFORM.match?(/darwin/)
18
- Capybara::Screenshot.register_driver(:headless_chrome) do |driver, path|
19
- driver.browser.save_screenshot(path)
17
+ if RUBY_PLATFORM.match?(/darwin/)
18
+ Capybara::Screenshot.register_driver(:headless_chrome) do |driver, path|
19
+ driver.browser.save_screenshot(path)
20
+ end
20
21
  end
22
+ Capybara.javascript_driver = :headless_chrome
21
23
  end
22
- Capybara.javascript_driver = :headless_chrome