renalware-core 2.0.139 → 2.0.140

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/renalware/rollup_compiled.js +50 -0
  3. data/app/assets/stylesheets/renalware/medications_pdf.scss +17 -1
  4. data/app/assets/stylesheets/renalware/modules/_medications.scss +17 -0
  5. data/app/assets/stylesheets/renalware/partials/_utilities.scss +8 -0
  6. data/app/controllers/renalware/medications/home_delivery/events_controller.rb +134 -0
  7. data/app/javascript/renalware/controllers/foundation_modal_controller.js +19 -0
  8. data/app/javascript/renalware/controllers/medications/home_delivery_modal_controller.js +24 -0
  9. data/app/javascript/renalware/index.js +4 -0
  10. data/app/models/renalware/drugs/homecare_form.rb +17 -0
  11. data/app/models/renalware/drugs/supplier.rb +12 -0
  12. data/app/models/renalware/feeds/hl7_message.rb +2 -2
  13. data/app/models/renalware/medications.rb +6 -0
  14. data/app/models/renalware/medications/delivery/event.rb +48 -0
  15. data/app/models/renalware/medications/delivery/event_prescription.rb +24 -0
  16. data/app/models/renalware/medications/delivery/homecare_forms_adapter.rb +104 -0
  17. data/app/models/renalware/medications/delivery/purchase_order_number.rb +27 -0
  18. data/app/models/renalware/medications/prescriptions_by_drug_type_id_query.rb +21 -0
  19. data/app/models/renalware/medications/provider.rb +20 -0
  20. data/app/views/renalware/medications/home_delivery/events/_edit.html.slim +71 -0
  21. data/app/views/renalware/medications/home_delivery/events/edit.html.slim +1 -0
  22. data/app/views/renalware/medications/home_delivery/events/edit.js.erb +4 -0
  23. data/app/views/renalware/medications/home_delivery/events/new.js.erb +3 -0
  24. data/app/views/renalware/medications/home_delivery/events/update.js.erb +5 -0
  25. data/app/views/renalware/medications/home_delivery/prescriptions/index.pdf.slim +4 -1
  26. data/app/views/renalware/medications/prescriptions/_form.html.slim +4 -0
  27. data/app/views/renalware/medications/prescriptions/index.html.slim +15 -5
  28. data/app/views/renalware/shared/_modal_close_link.html.slim +1 -1
  29. data/config/routes/medications.rb +5 -4
  30. data/db/migrate/20200301113102_create_drug_homecare_suppliers.rb +73 -0
  31. data/db/migrate/20200301124200_create_medication_delivery_events.rb +49 -0
  32. data/db/migrate/20200301124300_create_medication_delivery_event_prescriptions.rb +35 -0
  33. data/db/migrate/20200306183423_add_next_delivery_date_to_prescriptions.rb +7 -0
  34. data/lib/renalware/configuration.rb +7 -0
  35. data/lib/renalware/engine.rb +1 -0
  36. data/lib/renalware/version.rb +1 -1
  37. data/spec/factories/drugs/homecare_forms.rb +13 -0
  38. data/spec/factories/drugs/suppliers.rb +7 -0
  39. data/spec/factories/medications/delivery/events.rb +13 -0
  40. data/spec/support/pages/medications/home_delivery_dialog.rb +77 -0
  41. metadata +39 -13
  42. data/app/controllers/renalware/medications/home_delivery/prescriptions_controller.rb +0 -51
  43. data/app/models/renalware/letters/printing/create_pdf_by_interleaving_address_sheet_and_letter_for_each_recipient.rb.dead +0 -90
  44. data/app/models/renalware/pathology/consultant.rb.dead +0 -10
  45. data/app/models/renalware/pathology/view_observation_results.rb.dead +0 -64
  46. data/app/models/renalware/patients/ingestion/update_master_patient_index_job.rb.dead +0 -20
  47. data/app/presenters/renalware/admin/users/summary_part.rb.dead +0 -25
  48. data/app/presenters/renalware/ukrdc/modality_presenter.rb.dead +0 -8
  49. data/app/views/renalware/admin/users/_summary_part.html.slim.dead +0 -4
  50. data/app/views/renalware/letters/lists/index.html.slim.dead +0 -101
  51. data/app/views/renalware/letters/lists/index.html.slim.dead1 +0 -90
  52. data/app/views/renalware/mdm/_biopsies.html.slim.dead +0 -18
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_dependency "renalware/medications"
4
+
5
+ module Renalware
6
+ module Medications
7
+ module Delivery
8
+ # Takes
9
+ # - a patient
10
+ # - a homecare delivery_event
11
+ # and build Args used to pass to Renalware::Forms::Homecare::Pdf.generate
12
+ class HomecareFormsAdapter
13
+ pattr_initialize [:delivery_event!]
14
+ delegate :homecare_form, :patient, to: :delivery_event
15
+
16
+ def call
17
+ Forms::Homecare::Pdf.generate(build_args)
18
+ end
19
+
20
+ def valid?(args)
21
+ Forms::Homecare::Pdf.valid?(args)
22
+ end
23
+
24
+ def build_args
25
+ args = Forms::Homecare::Args.new(
26
+ provider: homecare_form.form_name,
27
+ version: homecare_form.form_version,
28
+ family_name: patient.family_name,
29
+ given_name: patient.given_name,
30
+ title: patient.title,
31
+ born_on: patient.born_on,
32
+ nhs_number: patient.nhs_number,
33
+ telephone: patient.telephone1,
34
+ hospital_number: patient.local_patient_id,
35
+ address: [],
36
+ modality: patient.current_modality&.description&.to_s,
37
+ po_number: delivery_event.reference_number,
38
+ drug_type: delivery_event.drug_type.name,
39
+ selected_prescription_duration: selected_prescription_duration,
40
+ prescription_durations: prescription_durations,
41
+ consultant: patient.named_consultant&.to_s,
42
+ generated_at: Time.zone.now,
43
+ hospital_name: Renalware.config.hospital_name,
44
+ hospital_address: hospital_address
45
+ )
46
+
47
+ if patient.current_address
48
+ add = patient.current_address
49
+ args.address = [
50
+ add.street_1,
51
+ add.street_2,
52
+ add.street_3,
53
+ add.town
54
+ ]
55
+ args.postcode = add.postcode
56
+ end
57
+
58
+ prescriptions.each do |prescription|
59
+ args.medications << Forms::Homecare::Args::Medication.new(
60
+ date: prescription.prescribed_on,
61
+ drug: prescription.drug.name,
62
+ dose: "#{prescription.dose_amount} #{prescription.dose_unit}",
63
+ route: prescription.medication_route&.name,
64
+ frequency: prescription.frequency
65
+ )
66
+ end
67
+
68
+ clinical_patient = Clinical.cast_patient(patient)
69
+ args.no_known_allergies = (clinical_patient.allergy_status == :no_known_allergies)
70
+ args.allergies = Array(clinical_patient.allergies).map(&:description)
71
+ args
72
+ end
73
+
74
+ private
75
+
76
+ def hospital_address
77
+ Renalware.config.hospital_address&.split(",")&.map(&:strip)
78
+ end
79
+
80
+ # Return e.g. "3 months"
81
+ def selected_prescription_duration
82
+ duration = delivery_event.prescription_duration.to_i
83
+ unit = delivery_event.homecare_form.prescription_duration_unit
84
+
85
+ "#{duration} #{unit.pluralize(duration)}"
86
+ end
87
+
88
+ def prescription_durations
89
+ homecare_form.prescription_durations.map do |dur|
90
+ "#{dur} #{homecare_form.prescription_duration_unit.pluralize(dur)}"
91
+ end
92
+ end
93
+
94
+ def prescriptions
95
+ PrescriptionsByDrugTypeIdQuery.new(
96
+ patient: delivery_event.patient,
97
+ drug_type_id: delivery_event.drug_type_id,
98
+ provider: :home_delivery
99
+ ).call
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_dependency "renalware/medications"
4
+
5
+ module Renalware
6
+ module Medications
7
+ module Delivery
8
+ class PurchaseOrderNumber
9
+ SEQ_NAME = "renalware.medication_delivery_purchase_order_number_seq"
10
+
11
+ class << self
12
+ def next_number
13
+ result = ApplicationRecord.connection.execute("SELECT nextval('#{SEQ_NAME}');")
14
+ result.first["nextval"]
15
+ end
16
+
17
+ def next
18
+ [
19
+ Renalware.config.medication_delivery_purchase_order_prefix,
20
+ next_number
21
+ ].join
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Renalware
4
+ module Medications
5
+ class PrescriptionsByDrugTypeIdQuery
6
+ pattr_initialize [:drug_type_id!, :patient!, provider: nil]
7
+
8
+ def call
9
+ results = patient
10
+ .prescriptions
11
+ .current
12
+ .includes(:medication_route, :drug)
13
+ .includes(patient: { current_modality: :description })
14
+ .eager_load(drug: [:drug_types])
15
+ .where("drug_types.id": drug_type_id)
16
+
17
+ provider.present? ? results.where(provider: provider) : results
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # frozen_string_literal: true
4
+
3
5
  require_dependency "renalware/medications"
4
6
 
5
7
  module Renalware
@@ -11,3 +13,21 @@ module Renalware
11
13
  end
12
14
  end
13
15
  end
16
+
17
+ # require_dependency "renalware/medications"
18
+
19
+ # module Renalware
20
+ # module Medications
21
+ # class Provider < ApplicationRecord
22
+ # validates :name, presence: true
23
+ # validates :code, presence: true
24
+ # has_many :provider_drug_types, dependent: :restrict_with_exception
25
+ # has_many :drug_types, through: :provider_drug_types
26
+
27
+ # # TODOL: read from db
28
+ # def self.codes
29
+ # %i(gp hospital home_delivery)
30
+ # end
31
+ # end
32
+ # end
33
+ # end
@@ -0,0 +1,71 @@
1
+ / This modal asks the user whether they successfully printed the homecare delivery form.
2
+ / If it was successful, we make a call to update event#printed = true and then dismiss the form
3
+ / (see update.js.erb)
4
+ .modal
5
+ = simple_form_for(event,
6
+ url: patient_medications_home_delivery_event_path(id: event.id),
7
+ remote: true,
8
+ authenticity_token: true,
9
+ method: :patch,
10
+ data: { target: "home-delivery-modal.form" },
11
+ as: :event) do |f|
12
+
13
+ .modal__header
14
+ h2
15
+ | Print home delivery drugs
16
+ span= " PO: #{event.reference_number}"
17
+ = render "renalware/shared/modal_close_link"
18
+
19
+ .modal__body
20
+ #error-message
21
+ = render "renalware/shared/errors", model: event
22
+
23
+ / There are 2 main divs in the modal
24
+ / - the first is initially displayed and has the print options and a print button
25
+ / - the second is displayed once Print has been clicked, and asked asks for feedback as to
26
+ / whether printing was successful or not. It it was successful we set
27
+ .form-fields data-target="home-delivery-modal.printOptions"
28
+ - homecare_forms = Renalware::Drugs::HomecareForm.all
29
+ = f.association :drug_type,
30
+ collection: Renalware::Drugs::Type.where(id: homecare_forms.map(&:drug_type_id)),
31
+ include_blank: false,
32
+ input_html: { \
33
+ data: { \
34
+ action: "change->home-delivery-modal#refreshForm", \
35
+ target: "home-delivery-modal.drugtype" \
36
+ } \
37
+ },
38
+ wrapper: :horizontal_medium
39
+
40
+ = f.input :prescription_duration,
41
+ collection: event.homecare_form.prescription_durations,
42
+ include_blank: false,
43
+ label_method: lambda { |dur| \
44
+ "#{dur} #{event.homecare_form.prescription_duration_unit.pluralize(dur)}" \
45
+ },\
46
+ wrapper: :horizontal_medium,
47
+ input_html: { data: { action: "change->home-delivery-modal#refreshForm" } }
48
+
49
+ .panel
50
+ u= "Homecare supply form"
51
+ br
52
+ = "#{event.homecare_form&.supplier&.name} '#{event.homecare_form&.form_name} version #{event.homecare_form&.form_version}'"
53
+
54
+ - disabled_args = event.errors.any? ? { disabled: "disabled" } : {}
55
+ = link_to "Print",
56
+ renalware.patient_medications_home_delivery_event_path(id: event.id, format: :pdf),
57
+ target: "_blank",
58
+ class: "button primary right home-delivery--print",
59
+ data: { action: "click->home-delivery-modal#askForPrintFeedback" },
60
+ **disabled_args
61
+
62
+ .show-after-printing.visuallyhidden data-target="home-delivery-modal.printFeedback"
63
+
64
+ h2 Was printing successful?
65
+ .right
66
+ = link_to "No - I didnt print anything",
67
+ "#",
68
+ class: "button secondary reveal-modal-close",
69
+ "aria-label" => "Close"
70
+
71
+ = f.submit "Yes - mark as printed", class: "button primary ", name: "event[printed]"
@@ -0,0 +1 @@
1
+ = render "edit", event: event
@@ -0,0 +1,4 @@
1
+ // Something about the form changed (eg drugtype dropdown changed) causing a submission
2
+ // so we re re-display the form here.
3
+ var modal = $("#print-home-delivery-drugs-modal")
4
+ $(modal).html("<%= j(render 'edit', event: event, format: :html) %>");
@@ -0,0 +1,3 @@
1
+ $("#print-home-delivery-drugs-modal #error-message").html(
2
+ '<%= message + ": " + event.errors.full_messages.join(", ") %>'
3
+ );
@@ -0,0 +1,5 @@
1
+ // User indicated the homecare form was successfully printed, so we updated
2
+ // the printed flag to true and are no dismissing the dialog.
3
+ // TODO: Ideally we would call the stimulus controller action here
4
+ $("#print-home-delivery-drugs-modal").foundation('reveal', 'close');
5
+ $("#print-home-delivery-drugs-modal").html("")
@@ -7,7 +7,10 @@ html
7
7
  head
8
8
  = wicked_pdf_stylesheet_link_tag "renalware/medications_pdf"
9
9
  heading
10
- .our-ref= "RW ref: #{patient.hospital_identifier}"
10
+ .references
11
+ .purchase_order_no= "PO: #{purchase_order_number}"
12
+ .our-ref= "RW ref: #{patient.hospital_identifier}"
13
+ .drug_types= "Drug types: #{drug_types.map(&:name).join(", ")}"
11
14
  span.logo
12
15
  = wicked_pdf_image_tag "renalware/NHS-Black.jpg", width: 50
13
16
  .address
@@ -48,6 +48,10 @@ ruby:
48
48
  as: :date_picker,
49
49
  wrapper: :horizontal_datepicker
50
50
 
51
+ = f.input :next_delivery_date,
52
+ as: :date_picker,
53
+ wrapper: :horizontal_datepicker
54
+
51
55
  .row.actions
52
56
  .small-9.columns
53
57
  = f.button :submit, "Save"
@@ -12,11 +12,21 @@
12
12
  i.fas.fa-print
13
13
  | Print
14
14
  |&nbsp;
15
- = link_to patient_medications_home_delivery_prescriptions_path(@patient),
16
- class: "button secondary with-icon",
17
- target: :blank do
18
- i.fa.fa-print
19
- | Print home delivery drugs
15
+
16
+ span(data-controller="foundation-modal",
17
+ data-foundation-modal-url=new_patient_medications_home_delivery_event_path(patient))
18
+ = link_to "#",
19
+ class: "button secondary with-icon",
20
+ target: :blank,
21
+ id: "show-home-delivery-modal",
22
+ data: { action: "click->foundation-modal#openRemotePartial" } do
23
+ i.fa.fa-print
24
+ | Print home delivery drugs
25
+ #print-home-delivery-drugs-modal.reveal-modal.small(data-reveal
26
+ data-refresh-url=request.original_fullpath
27
+ data-target="foundation-modal.container"
28
+ data-controller="home-delivery-modal"
29
+ data-home-delivery-url1=new_patient_medications_home_delivery_event_url(@patient))
20
30
 
21
31
  = within_patient_layout(title: "Prescriptions") do
22
32
  = render "filter_form", search: current_search, drug_types: drug_types, treatable: treatable
@@ -1,4 +1,4 @@
1
1
  = link_to "#",
2
2
  "aria-label" => "Close",
3
- class: "reveal-modal-close" do
3
+ class: "reveal-modal-close close-x" do
4
4
  i.fas.fa-window-close
@@ -4,10 +4,11 @@ resources :patients, only: [] do
4
4
  resources :prescriptions, controller: "medications/prescriptions", except: [:destroy]
5
5
  namespace :medications do
6
6
  namespace :home_delivery do
7
- resources :prescriptions,
8
- only: [:index],
9
- constraints: { format: /(pdf)/ },
10
- defaults: { format: :pdf }
7
+ resources :events, only: [:new, :create, :edit, :update, :show]
8
+ # resources :prescriptions,
9
+ # only: [:index],
10
+ # constraints: { format: /(pdf)/ },
11
+ # defaults: { format: :pdf }
11
12
  end
12
13
  resources :prescriptions, only: [] do
13
14
  resource :termination, only: [:new, :create]
@@ -0,0 +1,73 @@
1
+ class CreateDrugHomecareSuppliers < ActiveRecord::Migration[5.2]
2
+ def change
3
+ within_renalware_schema do
4
+ create_enum :duration, %w(minute hour day week month year)
5
+
6
+ create_table(
7
+ :drug_suppliers,
8
+ comment: "A list of suppliers who deliver drugs eg for homecare"
9
+ ) do |t|
10
+ t.string(
11
+ :name,
12
+ null: false,
13
+ comment: "The providers display name e.g. 'Fresenius'"
14
+ )
15
+ t.timestamps
16
+ end
17
+
18
+ # Has many through
19
+ create_table(
20
+ :drug_homecare_forms,
21
+ comment: "X-ref table that says which drug_type is supplied by which (homecare) supplier "\
22
+ "and the data required (see form_name and form_version) to programmatically "\
23
+ "select and create the right PDF Homecare Supply form for them (using the " \
24
+ "renalware-forms gem) so this can be printed out and signed."
25
+ ) do |t|
26
+ t.references :drug_type, null: false
27
+ t.references :supplier, null: false, foreign_key: { to_table: :drug_suppliers }
28
+
29
+ t.string(
30
+ :form_name,
31
+ null: false,
32
+ comment: "The lower-case programmatic name used for this provider, eg 'fresenius'"
33
+ )
34
+ t.string(
35
+ :form_version,
36
+ null: false,
37
+ comment: "A number e.g. '1' that specified what version of the homecare supply form" \
38
+ "should be created"
39
+ )
40
+ t.string(
41
+ :prescription_durations,
42
+ null: false,
43
+ array: true,
44
+ default: [],
45
+ comment: "An array of options where each integer is a number of units - these will be "\
46
+ "displayed as dropdown options presented to the user, and checkboxes "\
47
+ "on the homecare delivery form PDF. E.g [3,6] will "\
48
+ "be displayed as options '3 months' and '6 months' (see also "\
49
+ "prescription_duration_unit)"
50
+ )
51
+ t.integer(
52
+ :prescription_duration_default,
53
+ null: true,
54
+ comment: "The default option to pre-select when displaying prescription_duration_options"
55
+ )
56
+ t.enum(
57
+ :prescription_duration_unit,
58
+ null: false,
59
+ enum_name: :duration,
60
+ comment: "E.g. 'week' or 'month'"
61
+ )
62
+ t.timestamps null: false
63
+ end
64
+
65
+ add_index(
66
+ :drug_homecare_forms,
67
+ [:drug_type_id, :supplier_id],
68
+ unique: true,
69
+ comment: "A supplier can only have one form active for any drug type"
70
+ )
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,49 @@
1
+ class CreateMedicationDeliveryEvents < ActiveRecord::Migration[5.2]
2
+ def change
3
+ within_renalware_schema do
4
+ create_table :medication_delivery_events do |t|
5
+ t.references(
6
+ :homecare_form,
7
+ foreign_key: { to_table: :drug_homecare_forms },
8
+ index: true,
9
+ null: false
10
+ )
11
+ t.references(
12
+ :drug_type,
13
+ foreign_key: { to_table: :drug_types },
14
+ index: true,
15
+ null: false
16
+ )
17
+ t.references(:patient, index: true, null: false)
18
+ t.string :reference_number, null: true
19
+ t.integer :prescription_duration
20
+ t.boolean :printed, default: false, null: false
21
+ t.references :created_by, foreign_key: { to_table: :users }, index: true, null: false
22
+ t.references :updated_by, foreign_key: { to_table: :users }, index: true, null: false
23
+ t.datetime :deleted_at, index: true
24
+ t.timestamps null: false
25
+ end
26
+
27
+ # Create a sequence to generate home_delivery etc purchase order numbers.
28
+ # These aren't guaranteed to be contiguous because of the way we use them.
29
+ reversible do |direction|
30
+ direction.up do
31
+ connection.execute(<<-SQL.squish)
32
+ CREATE SEQUENCE renalware.medication_delivery_purchase_order_number_seq
33
+ AS integer
34
+ START WITH 100
35
+ INCREMENT BY 1
36
+ NO MINVALUE
37
+ NO MAXVALUE
38
+ CACHE 1;
39
+ SQL
40
+ end
41
+ direction.down do
42
+ connection.execute(
43
+ "drop sequence if exists renalware.medication_delivery_purchase_order_number_seq;"
44
+ )
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end