renalware-core 2.0.146 → 2.0.147

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/renalware/charting.js +1 -1
  3. data/app/assets/javascripts/renalware/rollup_compiled.js +87 -0
  4. data/app/assets/stylesheets/renalware/partials/_forms.scss +5 -0
  5. data/app/components/renalware/system/admin_menu_component.html.slim +1 -0
  6. data/app/controllers/renalware/admin/playgrounds_controller.rb +65 -0
  7. data/app/controllers/renalware/deaths_controller.rb +6 -5
  8. data/app/controllers/renalware/medications/home_delivery/events_controller.rb +0 -3
  9. data/app/controllers/renalware/medications/home_delivery/prescriptions_controller.rb +43 -0
  10. data/app/controllers/renalware/patients/primary_care_physician_controller.rb +6 -0
  11. data/app/javascript/renalware/controllers/charts_controller.js +52 -0
  12. data/app/javascript/renalware/controllers/medications/prescriptions_controller.js +24 -0
  13. data/app/javascript/renalware/index.js +6 -0
  14. data/app/models/renalware/medications.rb +2 -0
  15. data/app/models/renalware/medications/delivery/prescriptions_due_for_delivery_query.rb +53 -0
  16. data/app/models/renalware/patient.rb +4 -0
  17. data/app/models/renalware/patients/deceased_patients_query.rb +42 -0
  18. data/app/models/renalware/ukrdc/create_encrypted_patient_xml_files.rb +44 -16
  19. data/app/models/renalware/ukrdc/create_patient_xml_file.rb +1 -1
  20. data/app/views/renalware/accesses/assessments/_form.html.slim +2 -2
  21. data/app/views/renalware/accesses/plans/new.html.slim +1 -1
  22. data/app/views/renalware/accesses/procedures/_form.html.slim +2 -2
  23. data/app/views/renalware/accesses/profiles/_form.html.slim +2 -2
  24. data/app/views/renalware/admin/playgrounds/pathology_chart_data.js.erb +1 -0
  25. data/app/views/renalware/admin/playgrounds/show.html.slim +59 -0
  26. data/app/views/renalware/admin/users/_filters.html.slim +1 -1
  27. data/app/views/renalware/admissions/admissions/index.html.slim +2 -2
  28. data/app/views/renalware/admissions/consults/_form.html.slim +1 -1
  29. data/app/views/renalware/admissions/consults/index.html.slim +2 -2
  30. data/app/views/renalware/deaths/index.html.slim +18 -10
  31. data/app/views/renalware/events/events/toggled_cell/_biopsy.html.slim +1 -1
  32. data/app/views/renalware/events/events/toggled_cell/_simple.html.slim +1 -1
  33. data/app/views/renalware/events/events/toggled_cell/_swab.html.slim +1 -1
  34. data/app/views/renalware/hd/transmission_logs/index.html.slim +1 -2
  35. data/app/views/renalware/letters/mailshots/mailshots/_form.html.slim +2 -1
  36. data/app/views/renalware/mdm_patients/_patient.html.slim +1 -2
  37. data/app/views/renalware/medications/drug_types/prescriptions/_filters.html.slim +1 -3
  38. data/app/views/renalware/medications/home_delivery/prescriptions/index.html.slim +51 -0
  39. data/app/views/renalware/medications/prescriptions/_filter_form.html.slim +1 -1
  40. data/app/views/renalware/medications/prescriptions/_form.html.slim +20 -12
  41. data/app/views/renalware/navigation/_renal.html.slim +2 -0
  42. data/app/views/renalware/patients/_header.html.slim +1 -1
  43. data/app/views/renalware/patients/alerts/_alert.html.slim +1 -1
  44. data/app/views/renalware/patients/alerts/_form.html.slim +1 -1
  45. data/app/views/renalware/patients/patients/_form.html.slim +1 -2
  46. data/app/views/renalware/patients/patients/new.html.slim +6 -5
  47. data/app/views/renalware/patients/patients/show/_primary_care_physician.html.slim +9 -1
  48. data/app/views/renalware/patients/primary_care_physician/destroy.js.erb +1 -0
  49. data/app/views/renalware/pd/dashboards/show/_page_actions.html.slim +2 -2
  50. data/app/views/renalware/pd/exit_site_infections/show.html.slim +1 -1
  51. data/app/views/renalware/pd/peritonitis_episodes/show.html.slim +1 -1
  52. data/app/views/renalware/reporting/audits/edit.html.slim +1 -3
  53. data/app/views/renalware/research/_alert.html.slim +1 -1
  54. data/app/views/renalware/snippets/snippets/_row.html.slim +3 -4
  55. data/app/views/renalware/system/downloads/index.html.slim +2 -3
  56. data/app/views/renalware/transplants/live_donors/_filters.html.slim +2 -2
  57. data/config/initializers/groupdate.rb +3 -0
  58. data/config/locales/renalware/medications/prescription.yml +2 -1
  59. data/config/locales/renalware/navigation/renal.en.yml +1 -0
  60. data/config/routes/admin.rb +5 -0
  61. data/config/routes/medications.rb +5 -0
  62. data/config/routes/patients.rb +1 -1
  63. data/db/functions/pathology_chart_data_v01.sql +13 -0
  64. data/db/migrate/20200313120655_create_pathology_chart_data_function.rb +13 -0
  65. data/lib/renalware/engine.rb +1 -0
  66. data/lib/renalware/version.rb +1 -1
  67. data/spec/support/pages/medications/prescription_fom.rb +2 -2
  68. data/vendor/assets/javascripts/renalware/highcharts.js +506 -0
  69. metadata +32 -5
  70. data/app/views/renalware/medications/home_delivery/prescriptions/index.pdf.slim +0 -103
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ea66f0da3fb417c2ff7f515964db415e68e61f447fdf742c97906d635aecb7a6
4
- data.tar.gz: a1f6203e5b3f637bd9a85413ddbfe25739916e1ac33dc1f44e080acb4303f533
3
+ metadata.gz: a0a85e291938153f0f3d994195230457b6550239d0e8dde9e7d4a0b8a72f7819
4
+ data.tar.gz: 34d8b8b3b54731448ec32c05c136e3f371e4725a5a7efc2f7946264d041153d0
5
5
  SHA512:
6
- metadata.gz: d0269f2b3d9fdda86ea868fdf074314cce11f647030768d922ebfe1650eaf67fcd8f22bf321bd4f409daf2e4c1f991934b1e817e4ef213ccf37d873ced1fe797
7
- data.tar.gz: 740773f49f38ab01bfea92f1a06dc0c1cc83af18ccc8a7d483bb1ea01aaff2a71501df866f28de44c21d178b81d59e204660dc7c9d7a7a085b33b7b9fbfc2eb9
6
+ metadata.gz: 2da7dbc33f709e9effcb837f78c0678bbe375d977e8c276aa70dbcb2f94366f5df7c518f554ccd9f8611a3b801a2e74c4a11ffb21a08356d6fcd77e15b0015ed
7
+ data.tar.gz: a1d6d42f2adf772b8201e982fd8cb850403ce6cd70c87820b96a581356f7dab2efdc826db6bc96ba628b8ae44a39790c236f725bfee3a68170cc75ca91941bd4
@@ -1,2 +1,2 @@
1
1
  //= require chartkick
2
- //= require Chart.bundle
2
+ //= require highcharts
@@ -3923,6 +3923,87 @@ var _default$4 = function(_Controller) {
3923
3923
 
3924
3924
  _defineProperty(_default$4, "targets", [ "trix" ]);
3925
3925
 
3926
+ var _default$5 = function(_Controller) {
3927
+ _inherits(_default, _Controller);
3928
+ function _default() {
3929
+ _classCallCheck(this, _default);
3930
+ return _possibleConstructorReturn(this, _getPrototypeOf(_default).apply(this, arguments));
3931
+ }
3932
+ _createClass(_default, [ {
3933
+ key: "connect",
3934
+ value: function connect() {
3935
+ var radio_value = this.providersTarget.querySelector("input:checked").value;
3936
+ this.toggleDeliveryDatesVisibility(radio_value);
3937
+ }
3938
+ }, {
3939
+ key: "toggleDeliveryDates",
3940
+ value: function toggleDeliveryDates(event) {
3941
+ this.toggleDeliveryDatesVisibility(event.target.value);
3942
+ }
3943
+ }, {
3944
+ key: "toggleDeliveryDatesVisibility",
3945
+ value: function toggleDeliveryDatesVisibility(radio_value) {
3946
+ if (radio_value == "home_delivery") {
3947
+ this.homeDeliveryDatesTarget.style.display = "block";
3948
+ } else {
3949
+ this.homeDeliveryDatesTarget.style.display = "none";
3950
+ }
3951
+ }
3952
+ } ]);
3953
+ return _default;
3954
+ }(Controller);
3955
+
3956
+ _defineProperty(_default$5, "targets", [ "homeDeliveryDates", "providers" ]);
3957
+
3958
+ var Chartkick = window.Chartkick;
3959
+
3960
+ var _default$6 = function(_Controller) {
3961
+ _inherits(_default, _Controller);
3962
+ function _default() {
3963
+ _classCallCheck(this, _default);
3964
+ return _possibleConstructorReturn(this, _getPrototypeOf(_default).apply(this, arguments));
3965
+ }
3966
+ _createClass(_default, [ {
3967
+ key: "redisplay",
3968
+ value: function redisplay(event) {
3969
+ var json = event.detail[0];
3970
+ if (this.chartCreated()) {
3971
+ this.chartTarget.getChartObject().updateData(json);
3972
+ } else {
3973
+ new Chartkick.LineChart("chart1", json, this.chartOptions);
3974
+ }
3975
+ }
3976
+ }, {
3977
+ key: "chartCreated",
3978
+ value: function chartCreated() {
3979
+ return Object.prototype.hasOwnProperty.call(this.chartTarget, "getChartObject");
3980
+ }
3981
+ }, {
3982
+ key: "chartOptions",
3983
+ get: function get() {
3984
+ return {
3985
+ curve: false,
3986
+ library: {
3987
+ chart: {
3988
+ zoomType: "x"
3989
+ },
3990
+ plotOptions: {
3991
+ series: {
3992
+ animation: {
3993
+ duration: 400
3994
+ }
3995
+ }
3996
+ },
3997
+ colors: [ "#005eb8", "#009639", "#434348", "#90ed7d", "#f7a35c", "#8085e9", "#f15c80", "#e4d354" ]
3998
+ }
3999
+ };
4000
+ }
4001
+ } ]);
4002
+ return _default;
4003
+ }(Controller);
4004
+
4005
+ _defineProperty(_default$6, "targets", [ "chart" ]);
4006
+
3926
4007
  var application = Application.start();
3927
4008
 
3928
4009
  application.register("toggle", _default);
@@ -3934,3 +4015,9 @@ application.register("home-delivery-modal", _default$2);
3934
4015
  application.register("snippets", _default$3);
3935
4016
 
3936
4017
  application.register("letters-form", _default$4);
4018
+
4019
+ application.register("prescriptions", _default$5);
4020
+
4021
+ application.register("charts", _default$6);
4022
+
4023
+ window.Chartkick.use(window.Highcharts);
@@ -207,6 +207,11 @@ article {
207
207
  float: right;
208
208
  padding: 0.3rem 0.4rem;
209
209
  text-decoration: none;
210
+ margin-left: 0.5rem;
211
+
212
+ &.button-danger {
213
+ background-color: $nhs-red;
214
+ }
210
215
  }
211
216
 
212
217
  .button:hover {
@@ -23,4 +23,5 @@ ul.side-nav.side-nav--admin
23
23
  = super_admin_menu_item "HD Cannulation Types", renalware.hd_cannulation_types_path, %r{hd/cannulation_types}
24
24
  = super_admin_menu_item "Print batches", renalware.letters_batches_path, %r{letters/batches}
25
25
  = admin_menu_item "Mailshots", renalware.letters_mailshots_path, %r{letters/mailshots}
26
+ = super_admin_menu_item "Playground", renalware.admin_playground_path, %r{admin/playground}
26
27
  = developer_menu_item "HL7 Test", renalware.new_feeds_hl7_test_message_path
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Renalware
4
+ class Admin::PlaygroundsController < BaseController
5
+ def show
6
+ authorize User, :index?
7
+ render locals: { form: ChartForm.new(obx_code: "CRE", period: "all") }
8
+ end
9
+
10
+ # Returns test json to display a chart of one obx code over time for a patient
11
+ def pathology_chart_data
12
+ authorize User, :index?
13
+ form = ChartForm.new(chart_params)
14
+ chart = Chart.new(form)
15
+ render json: chart.json
16
+ end
17
+
18
+ class ChartForm
19
+ include ActiveModel::Model
20
+ include Virtus::Model
21
+
22
+ attribute :patient_id, Integer
23
+ attribute :obx_code, String
24
+ attribute :period, String
25
+
26
+ # Map a period string to a date, eg 6m = 6 months ago
27
+ def start_date
28
+ time = case period
29
+ when "yr" then 1.year.ago
30
+ when "6m" then 6.months.ago
31
+ when "3m" then 3.months.ago
32
+ when "1m" then 1.month.ago
33
+ when "1wk" then 1.week.ago
34
+ else 100.years.ago
35
+ end
36
+ time.to_date.to_s
37
+ end
38
+ end
39
+
40
+ def chart_params
41
+ return {} unless params.key?(:chart)
42
+
43
+ params.require(:chart).permit!
44
+ end
45
+
46
+ class Chart
47
+ pattr_initialize :form
48
+
49
+ def json
50
+ return {} if form.patient_id.blank?
51
+
52
+ ActiveRecord::Base.connection.execute(
53
+ Arel.sql(<<-SQL)
54
+ select
55
+ observed_on as x,
56
+ result as y
57
+ from renalware.pathology_chart_data(#{form.patient_id},
58
+ '#{form.obx_code}',
59
+ '#{form.start_date}')
60
+ SQL
61
+ ).to_a.each_with_object({}) { |h, hash| hash[Date.parse(h["x"])] = h["y"] }
62
+ end
63
+ end
64
+ end
65
+ end
@@ -3,15 +3,16 @@
3
3
  module Renalware
4
4
  class DeathsController < BaseController
5
5
  include PresenterHelper
6
- include Renalware::Concerns::Pageable
6
+ include Pagy::Backend
7
7
 
8
8
  def index
9
- patients = Patient.dead.page(page).per(per_page)
10
- search = patients.ransack(params[:q])
9
+ query = Patients::DeceasedPatientsQuery.new(params[:q])
10
+ pagy, patients = pagy(query.call.includes(previous_modality: :description))
11
11
  authorize patients
12
12
  render locals: {
13
- patients: present(search.result, PatientPresenter),
14
- q: search
13
+ patients: present(patients, PatientPresenter),
14
+ q: query.search,
15
+ pagy: pagy
15
16
  }
16
17
  end
17
18
 
@@ -31,9 +31,7 @@ module Renalware
31
31
  authorize event
32
32
 
33
33
  event.prescriptions = prescriptions_for(event)
34
-
35
34
  event.valid?
36
- # byebug
37
35
  render(:edit, layout: false, locals: { event: event })
38
36
  end
39
37
 
@@ -64,7 +62,6 @@ module Renalware
64
62
  last_delivery_date: last_delivery_date,
65
63
  next_delivery_date: next_delivery_date
66
64
  )
67
-
68
65
  end
69
66
  render :update, locals: { event: event }
70
67
  else
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_dependency "renalware/medications"
4
+
5
+ module Renalware
6
+ module Medications
7
+ module HomeDelivery
8
+ class PrescriptionsController < BaseController
9
+ include Pagy::Backend
10
+
11
+ def index
12
+ form = SearchForm.new(search_params)
13
+ query = Medications::Delivery::PrescriptionsDueForDeliveryQuery.new(
14
+ drug_type_code: params[:named_filter],
15
+ modality_description_id: form.modality_description_id,
16
+ query: params[:q]
17
+ )
18
+ pagy, prescriptions = pagy(query.call)
19
+ authorize prescriptions
20
+ render :index, locals: {
21
+ prescriptions: prescriptions,
22
+ pagy: pagy,
23
+ query: query.search,
24
+ form: form
25
+ }
26
+ end
27
+
28
+ class SearchForm
29
+ include ActiveModel::Model
30
+ include Virtus::Model
31
+
32
+ attribute :modality_description_id, Integer
33
+ end
34
+
35
+ def search_params
36
+ return {} unless params.key?(:search)
37
+
38
+ params.require(:search).permit(:modality_description_id)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -26,6 +26,12 @@ module Renalware
26
26
  end
27
27
  end
28
28
 
29
+ def destroy
30
+ authorize patient
31
+ patient.update_by(current_user, primary_care_physician_id: nil, practice_id: nil)
32
+ render locals: { patient: patient }
33
+ end
34
+
29
35
  private
30
36
 
31
37
  # There maybe times (for instance after migration from a previous system) where the
@@ -0,0 +1,52 @@
1
+ // NB Chartkick and Highcharts are defined as global in rollup
2
+ const Chartkick = window.Chartkick
3
+
4
+ import { Controller } from "stimulus"
5
+
6
+ export default class extends Controller {
7
+ static targets = [ "chart" ]
8
+
9
+ // Called on ajax:success
10
+ redisplay(event) {
11
+ // let [json, status, xhr] = event.detail
12
+ let json = event.detail[0]
13
+ if (this.chartCreated()) {
14
+ this.chartTarget.getChartObject().updateData(json)
15
+ } else {
16
+ new Chartkick.LineChart("chart1", json, this.chartOptions)
17
+ }
18
+ }
19
+
20
+ // Returns true if the chart target has already been initialised
21
+ chartCreated() {
22
+ return Object.prototype.hasOwnProperty.call(this.chartTarget, "getChartObject")
23
+ }
24
+
25
+ get chartOptions() {
26
+ return {
27
+ curve: false,
28
+ library: {
29
+ chart: {
30
+ zoomType: "x"
31
+ },
32
+ plotOptions: {
33
+ series: {
34
+ animation: {
35
+ duration: 400
36
+ }
37
+ }
38
+ },
39
+ colors: [
40
+ "#005eb8",
41
+ "#009639",
42
+ "#434348",
43
+ "#90ed7d",
44
+ "#f7a35c",
45
+ "#8085e9",
46
+ "#f15c80",
47
+ "#e4d354"
48
+ ]
49
+ }
50
+ }
51
+ }
52
+ }
@@ -0,0 +1,24 @@
1
+ import { Controller } from "stimulus"
2
+
3
+ // Handles the modal dialog used for presenting Home Delivery print options to
4
+ // the user. Used on the prescrptions page.
5
+ export default class extends Controller {
6
+ static targets = [ "homeDeliveryDates", "providers" ]
7
+
8
+ connect() {
9
+ let radio_value = this.providersTarget.querySelector("input:checked").value
10
+ this.toggleDeliveryDatesVisibility(radio_value)
11
+ }
12
+
13
+ toggleDeliveryDates(event) {
14
+ this.toggleDeliveryDatesVisibility(event.target.value)
15
+ }
16
+
17
+ toggleDeliveryDatesVisibility(radio_value) {
18
+ if (radio_value == "home_delivery") {
19
+ this.homeDeliveryDatesTarget.style.display = "block"
20
+ } else {
21
+ this.homeDeliveryDatesTarget.style.display = "none"
22
+ }
23
+ }
24
+ }
@@ -18,6 +18,8 @@ import HDPrescriptionController from "./controllers/hd/prescription_administrati
18
18
  import MedicationsHomeDeliveryModalController from "./controllers/medications/home_delivery_modal_controller"
19
19
  import SnippetsController from "./controllers/snippets_controller"
20
20
  import LettersFormController from "./controllers/letters/form_controller"
21
+ import PrescriptionsController from "./controllers/medications/prescriptions_controller"
22
+ import ChartsController from "./controllers/charts_controller"
21
23
 
22
24
  const application = Application.start()
23
25
  application.register("toggle", ToggleController)
@@ -25,3 +27,7 @@ application.register("hd-prescription-administration", HDPrescriptionController)
25
27
  application.register("home-delivery-modal", MedicationsHomeDeliveryModalController)
26
28
  application.register("snippets", SnippetsController)
27
29
  application.register("letters-form", LettersFormController)
30
+ application.register("prescriptions", PrescriptionsController)
31
+ application.register("charts", ChartsController)
32
+
33
+ window.Chartkick.use(window.Highcharts)
@@ -9,6 +9,8 @@ module Renalware
9
9
  end
10
10
 
11
11
  module Delivery
12
+ DRUG_TYPE_FILTERS = %i(esa immunosuppressant).freeze
13
+
12
14
  def self.table_name_prefix
13
15
  "medication_delivery_"
14
16
  end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_dependency "renalware/medications"
4
+
5
+ module Renalware
6
+ module Medications
7
+ module Delivery
8
+ # Find current home delivery prescriptions with a next_delivery_date falling
9
+ # within the specified range.
10
+ class PrescriptionsDueForDeliveryQuery
11
+ attr_reader :drug_type_code, :from, :to, :query, :modality_description_id
12
+
13
+ def initialize(
14
+ drug_type_code: nil,
15
+ from: nil,
16
+ to: nil,
17
+ modality_description_id: nil,
18
+ query: {}
19
+ )
20
+ @from = (from || 4.weeks.ago).beginning_of_day
21
+ @to = (to || 2.weeks.since).end_of_day
22
+ @drug_type_code = drug_type_code
23
+ @query = query
24
+ @modality_description_id = modality_description_id
25
+ end
26
+
27
+ def call
28
+ query = search.result
29
+ .current
30
+ .includes(:patient)
31
+ .eager_load(drug: [:classifications, :drug_types])
32
+ .joins("inner join patient_current_modalities pcm on pcm.patient_id = patients.id")
33
+ .where(provider: :home_delivery)
34
+ .where(next_delivery_date: (from..to))
35
+ .order(next_delivery_date: :asc)
36
+
37
+ if drug_type_code.present?
38
+ query = query.where("lower(drug_types.code) = ?", drug_type_code)
39
+ end
40
+
41
+ if modality_description_id.present?
42
+ query = query.where("pcm.modality_description_id = ?", modality_description_id)
43
+ end
44
+ query
45
+ end
46
+
47
+ def search
48
+ @search ||= Medications::Prescription.ransack(query)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end