renalware-core 2.0.113 → 2.0.115
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +0 -2
- data/app/assets/javascripts/renalware/application.js.erb +0 -1
- data/app/assets/javascripts/renalware/feed_only_inputs.js.erb +26 -0
- data/app/assets/javascripts/renalware/feeds.js +50 -0
- data/app/assets/javascripts/renalware/person_ajax_search.js +43 -0
- data/app/assets/stylesheets/renalware/application.scss +0 -1
- data/app/assets/stylesheets/renalware/modules/_admin.scss +7 -0
- data/app/assets/stylesheets/renalware/modules/_pathology.scss +1 -1
- data/app/assets/stylesheets/renalware/modules/_patients.scss +6 -0
- data/app/assets/stylesheets/renalware/modules/_snippets.scss +2 -2
- data/app/assets/stylesheets/renalware/partials/_forms.scss +5 -1
- data/app/assets/stylesheets/renalware/partials/_layout.scss +4 -0
- data/app/{views/renalware/patients/_side_menu.html.slim → components/renalware/patients/side_menu_component.html.slim} +0 -0
- data/app/components/renalware/patients/side_menu_component.rb +18 -0
- data/app/controllers/renalware/clinical/body_compositions_controller.rb +6 -0
- data/app/controllers/renalware/feeds/hl7_test_messages_controller.rb +60 -0
- data/app/controllers/renalware/hd/mdm_patients_controller.rb +16 -6
- data/app/controllers/renalware/hd/scheduling/diaries_controller.rb +91 -0
- data/app/controllers/renalware/hd/scheduling/diary_slots_controller.rb +169 -0
- data/app/controllers/renalware/hd/session_forms/batches_controller.rb +1 -1
- data/app/controllers/renalware/pathology/observation_requests_controller.rb +23 -4
- data/app/controllers/renalware/pathology/requests/requests_controller.rb +0 -4
- data/app/controllers/renalware/patients/abridgements_controller.rb +39 -0
- data/app/controllers/renalware/pd/regimes_controller.rb +26 -0
- data/app/controllers/renalware/problems/problems_controller.rb +2 -2
- data/app/helpers/renalware/application_helper.rb +9 -0
- data/app/helpers/renalware/article_helper.rb +18 -0
- data/app/helpers/renalware/form_helper.rb +3 -2
- data/app/helpers/renalware/users_helper.rb +5 -1
- data/app/javascript/controllers/clipboard_controller.js +16 -0
- data/app/javascript/packs/renalware_core.js +20 -0
- data/app/jobs/feed_job.rb +1 -3
- data/app/jobs/hl7_message_example.yml +2 -2
- data/app/models/renalware/feeds/files/practice_memberships/import_job.rb +3 -0
- data/app/models/renalware/feeds/files/primary_care_physicians/import_job.rb +2 -0
- data/app/models/renalware/feeds/hl7_message.rb +57 -6
- data/app/models/renalware/feeds/hl7_test_form.rb +10 -0
- data/app/models/renalware/feeds/hl7_test_message.rb +11 -0
- data/app/models/renalware/feeds/message_parser.rb +6 -2
- data/app/models/renalware/feeds/message_processor.rb +44 -32
- data/app/models/renalware/feeds/persist_message.rb +9 -3
- data/app/models/renalware/feeds.rb +2 -0
- data/app/models/renalware/hd/scheduling/archive_arguments.rb +19 -0
- data/app/models/renalware/hd/scheduling/diary.rb +54 -0
- data/app/models/renalware/hd/scheduling/diary_housekeeping_job.rb +84 -0
- data/app/models/renalware/hd/scheduling/diary_range.rb +69 -0
- data/app/models/renalware/hd/scheduling/diary_slot.rb +88 -0
- data/app/models/renalware/hd/scheduling/find_or_create_diary_by_week_query.rb +52 -0
- data/app/models/renalware/hd/scheduling/find_or_create_master_diary.rb +27 -0
- data/app/models/renalware/hd/scheduling/master_diary.rb +35 -0
- data/app/models/renalware/hd/scheduling/weekly_diary.rb +47 -0
- data/app/models/renalware/pathology/message_listener.rb +2 -2
- data/app/models/renalware/pathology/requests/global_rule/latest_crf_older_than_weeks.rb +38 -0
- data/app/models/renalware/pathology/requests/global_rule/patient_is_diabetic.rb +1 -1
- data/app/models/renalware/patient.rb +1 -1
- data/app/models/renalware/patients/abridgement.rb +18 -0
- data/app/models/renalware/patients/abridgement_search_form.rb +12 -0
- data/app/models/renalware/patients/ingestion/command.rb +25 -0
- data/app/models/renalware/patients/ingestion/command_factory.rb +135 -0
- data/app/models/renalware/patients/ingestion/commands/add_or_update_patient.rb +65 -0
- data/app/models/renalware/patients/ingestion/message_listener.rb +21 -0
- data/app/models/renalware/patients/ingestion/message_mapper.rb +26 -0
- data/app/models/renalware/patients/ingestion/message_mappers/patient.rb +73 -0
- data/app/models/renalware/patients/ingestion/update_master_patient_index.rb +60 -0
- data/app/models/renalware/patients/ingestion/update_master_patient_index_job.rb.dead +20 -0
- data/app/models/renalware/patients.rb +4 -3
- data/app/models/renalware/problems/problem.rb +6 -2
- data/app/models/renalware/ukrdc/incoming/paths.rb +6 -7
- data/app/policies/renalware/admin/devops_policy.rb +18 -0
- data/app/policies/renalware/hd/{diary_policy.rb → scheduling/diary_policy.rb} +3 -1
- data/app/presenters/renalware/clinical/profile_presenter.rb +2 -1
- data/app/presenters/renalware/directory/person_auto_complete_presenter.rb +1 -1
- data/app/presenters/renalware/hd/scheduling/diary_presenter.rb +84 -0
- data/app/presenters/renalware/hd/scheduling/diary_slot_presenter.rb +74 -0
- data/app/presenters/renalware/hd/scheduling/null_slot.rb +42 -0
- data/app/presenters/renalware/pd/dashboard_presenter.rb +3 -2
- data/app/views/renalware/accesses/procedures/_form.html.slim +5 -1
- data/app/views/renalware/accesses/procedures/_list.html.slim +11 -4
- data/app/views/renalware/accesses/procedures/show.html.slim +17 -19
- data/app/views/renalware/addresses/_form.html.slim +17 -12
- data/app/views/renalware/admin/cache/show.html.slim +24 -0
- data/app/views/renalware/clinical/body_compositions/_list.html.slim +7 -43
- data/app/views/renalware/clinical/body_compositions/_table.html.slim +42 -0
- data/app/views/renalware/clinical/body_compositions/index.html.slim +9 -0
- data/app/views/renalware/clinical/dry_weights/_list.html.slim +2 -8
- data/app/views/renalware/clinical/dry_weights/_table.html.slim +7 -0
- data/app/views/renalware/clinical/profiles/show.html.slim +4 -2
- data/app/views/renalware/feeds/hl7_test_messages/create.js.erb +10 -0
- data/app/views/renalware/feeds/hl7_test_messages/new.slim +18 -0
- data/app/views/renalware/hd/mdm_patients/_filters.html.slim +0 -11
- data/app/views/renalware/hd/mdm_patients/_page_actions.html.slim +29 -0
- data/app/views/renalware/hd/mdm_patients/index.html.slim +7 -4
- data/app/views/renalware/hd/{diaries → scheduling/diaries}/_page_actions.html.slim +4 -4
- data/app/views/renalware/hd/{diaries → scheduling/diaries}/_table.html.slim +0 -0
- data/app/views/renalware/hd/{diaries → scheduling/diaries}/_weekly_diary.html.slim +1 -1
- data/app/views/renalware/hd/{diaries → scheduling/diaries}/edit.html.slim +6 -6
- data/app/views/renalware/hd/{diaries → scheduling/diaries}/index.html.slim +0 -0
- data/app/views/renalware/hd/{diaries → scheduling/diaries}/show.pdf.slim +0 -0
- data/app/views/renalware/hd/{diary_slots → scheduling/diary_slots}/_form.html.slim +15 -6
- data/app/views/renalware/hd/{diary_slots → scheduling/diary_slots}/_slot.html.slim +2 -2
- data/app/views/renalware/hd/{diary_slots → scheduling/diary_slots}/_tab.html.slim +1 -1
- data/app/views/renalware/hd/{diary_slots → scheduling/diary_slots}/create.js.erb +1 -1
- data/app/views/renalware/hd/{diary_slots → scheduling/diary_slots}/destroy.js.erb +1 -1
- data/app/views/renalware/hd/{diary_slots → scheduling/diary_slots}/edit.html.slim +2 -2
- data/app/views/renalware/hd/{diary_slots → scheduling/diary_slots}/new.html.slim +0 -0
- data/app/views/renalware/hd/{diary_slots → scheduling/diary_slots}/new.js.erb +0 -0
- data/app/views/renalware/hd/{diary_slots → scheduling/diary_slots}/show.js.erb +0 -0
- data/app/views/renalware/hd/{diary_slots → scheduling/diary_slots}/update.js.erb +1 -1
- data/app/views/renalware/hospitals/units/index.html.slim +2 -2
- data/app/views/renalware/layouts/_patient.html.slim +2 -1
- data/app/views/renalware/letters/contacts/_form.html.slim +10 -13
- data/app/views/renalware/letters/letters/_form.html.slim +2 -9
- data/app/views/renalware/navigation/_developer.html.slim +4 -0
- data/app/views/renalware/navigation/_menu.html.slim +2 -0
- data/app/views/renalware/pathology/observation_requests/_filters.html.slim +17 -0
- data/app/views/renalware/pathology/observation_requests/index.html.slim +2 -1
- data/app/views/renalware/patients/_layout.html.slim +1 -1
- data/app/views/renalware/patients/_side_menu.html.slim.dead +7 -0
- data/app/views/renalware/patients/abridgements/_abridgement.html.slim +8 -0
- data/app/views/renalware/patients/abridgements/_table.html.slim +12 -0
- data/app/views/renalware/patients/abridgements/index.html.slim +22 -0
- data/app/views/renalware/patients/alerts/create.json +3 -0
- data/app/views/renalware/patients/patients/_form.html.slim +36 -17
- data/app/views/renalware/patients/patients/edit.html.slim +1 -1
- data/app/views/renalware/patients/patients/new.html.slim +1 -1
- data/app/views/renalware/patients/side_menu/_actions.html.slim +2 -0
- data/app/views/renalware/pd/_apd_regimes.html.slim +1 -1
- data/app/views/renalware/pd/_capd_regimes.html.slim +1 -1
- data/app/views/renalware/pd/dashboards/show/_apd_regimes.html.slim +11 -2
- data/app/views/renalware/pd/dashboards/show/_capd_regimes.html.slim +11 -2
- data/app/views/renalware/pd/regimes/index.html.slim +7 -0
- data/app/views/renalware/renal/profiles/_form.html.slim +7 -24
- data/app/views/renalware/shared/documents/_binary_marker_input.html.slim +2 -2
- data/app/views/renalware/shared/documents/_blood_group_input.html.slim +4 -2
- data/app/views/renalware/transplants/registrations/_form.html.slim +22 -17
- data/config/locales/renalware/clinical/body_composition.yml +6 -3
- data/config/locales/renalware/clinical/dry_weight.en.yml +4 -3
- data/config/locales/renalware/hd/diary_slots.en.yml +3 -2
- data/config/locales/renalware/letters/contact.en.yml +0 -2
- data/config/routes/feeds.rb +5 -0
- data/config/routes/hd.rb +11 -7
- data/config/routes/letters.rb +0 -5
- data/config/routes/patients.rb +1 -0
- data/config/routes/pd.rb +2 -2
- data/config/routes/renal.rb +0 -5
- data/config/routes.rb +1 -0
- data/config/webpack/development.js +5 -0
- data/config/webpack/environment.js +3 -0
- data/config/webpack/production.js +5 -0
- data/config/webpack/test.js +5 -0
- data/config/webpacker.yml +103 -0
- data/db/functions/hd_diary_archive_elapsed_master_slots_v01.sql +40 -0
- data/db/migrate/20190322120025_create_feed_hl7_test_messages.rb +12 -0
- data/db/migrate/20190325134823_create_patients_master_index.rb +24 -0
- data/db/migrate/20190327100851_add_handled_to_feed_messages.rb +5 -0
- data/db/migrate/20191012121433_add_consultant_to_users.rb +7 -0
- data/db/migrate/20191018143635_create_hd_diary_matrix_view.rb +7 -0
- data/db/migrate/20191018144917_create_fn_to_archive_master_slots.rb +9 -0
- data/db/views/hd_diary_matrix_v01.sql +38 -0
- data/lib/core_extensions/active_record/sort.rb +27 -9
- data/lib/renalware/configuration.rb +3 -0
- data/lib/renalware/engine.rb +31 -0
- data/lib/renalware/version.rb +1 -1
- data/lib/renalware/week_period.rb +8 -7
- data/lib/renalware.rb +13 -1
- data/lib/tasks/hd.rake +7 -0
- data/lib/tasks/pathology.rake +1 -1
- data/lib/tasks/renalware.rake +89 -4
- data/spec/factories/hd/scheduling/diaries.rb +18 -0
- data/spec/factories/hd/{slots.rb → scheduling/slots.rb} +1 -1
- data/spec/factories/patients/abridgements.rb +9 -0
- data/spec/support/hl7_helpers.rb +13 -0
- data/spec/support/pages/letters/form.rb +4 -1
- metadata +126 -50
- data/app/assets/javascripts/renalware/auto_complete.js +0 -63
- data/app/controllers/renalware/hd/diaries_controller.rb +0 -89
- data/app/controllers/renalware/hd/diary_slots_controller.rb +0 -175
- data/app/controllers/renalware/letters/descriptions_controller.rb +0 -22
- data/app/controllers/renalware/renal/prd_descriptions_controller.rb +0 -15
- data/app/models/renalware/hd/archive_yesterdays_slots_job.rb +0 -69
- data/app/models/renalware/hd/diary.rb +0 -41
- data/app/models/renalware/hd/diary_slot.rb +0 -83
- data/app/models/renalware/hd/find_or_create_diary_by_week_query.rb +0 -50
- data/app/models/renalware/hd/find_or_create_master_diary.rb +0 -26
- data/app/models/renalware/hd/master_diary.rb +0 -32
- data/app/models/renalware/hd/weekly_diary.rb +0 -45
- data/app/models/renalware/renal/prd_descriptions/search_query.rb +0 -35
- data/app/presenters/renalware/hd/diary_presenter.rb +0 -79
- data/app/presenters/renalware/hd/diary_slot_presenter.rb +0 -72
- data/app/presenters/renalware/hd/null_slot.rb +0 -40
- data/app/views/renalware/renal/prd_descriptions/search.json.jbuilder +0 -6
- data/lib/test_support/autocomplete_helpers.rb +0 -14
- data/spec/factories/hd/diaries.rb +0 -14
@@ -1,89 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_dependency "renalware/hd/base_controller"
|
4
|
-
|
5
|
-
# The route to the edit route for this controller takes /:year/:week_number segments
|
6
|
-
# rather than an id. THat is because when we load the diary, and when we navigate back and forth
|
7
|
-
# through diaries, we are concerned with the week more then an id. Its easier to navigate to the
|
8
|
-
# next week with /2017/52 than by looking up the id of the next diary ahead of time.
|
9
|
-
module Renalware
|
10
|
-
module HD
|
11
|
-
class DiariesController < BaseController
|
12
|
-
include Renalware::Concerns::PdfRenderable
|
13
|
-
include Renalware::Concerns::Pageable
|
14
|
-
|
15
|
-
def edit
|
16
|
-
authorize weekly_diary, :show?
|
17
|
-
render locals: {
|
18
|
-
unit: unit,
|
19
|
-
diary: DiaryPresenter.new(current_user, weekly_diary)
|
20
|
-
}
|
21
|
-
end
|
22
|
-
|
23
|
-
# Renders a list of diaries for a hospital unit
|
24
|
-
def index
|
25
|
-
authorize WeeklyDiary, :index?
|
26
|
-
render locals: { unit: unit, diaries: weekly_diaries }
|
27
|
-
end
|
28
|
-
|
29
|
-
def show
|
30
|
-
diary = WeeklyDiary.find(params[:id])
|
31
|
-
respond_to do |format|
|
32
|
-
format.pdf do
|
33
|
-
authorize diary
|
34
|
-
options = default_pdf_options.merge!(
|
35
|
-
pdf: pdf_filename,
|
36
|
-
locals: { unit: unit, diary: DiaryPresenter.new(current_user, diary) }
|
37
|
-
)
|
38
|
-
render options
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
private
|
44
|
-
|
45
|
-
# TODO: give a sensible name
|
46
|
-
def pdf_filename
|
47
|
-
"hd_unit_diary"
|
48
|
-
end
|
49
|
-
|
50
|
-
def weekly_diary
|
51
|
-
@weekly_diary ||= begin
|
52
|
-
FindOrCreateDiaryByWeekQuery.new(
|
53
|
-
relation: WeeklyDiary.eager_load(
|
54
|
-
slots: [:patient, :station, :diurnal_period_code],
|
55
|
-
master_diary: { slots: [:patient, :station, :diurnal_period_code] }
|
56
|
-
),
|
57
|
-
unit_id: unit_id,
|
58
|
-
week_period: week_period,
|
59
|
-
by: current_user
|
60
|
-
).call
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
# The route segments are /:year/:week_number
|
65
|
-
# We use a WeekPeriod value object to wrap those two things.
|
66
|
-
def week_period
|
67
|
-
WeekPeriod.new(
|
68
|
-
week_number: params[:week_number],
|
69
|
-
year: params[:year]
|
70
|
-
)
|
71
|
-
end
|
72
|
-
|
73
|
-
def unit_id
|
74
|
-
params[:unit_id]
|
75
|
-
end
|
76
|
-
|
77
|
-
def unit
|
78
|
-
Hospitals::Unit.find(unit_id)
|
79
|
-
end
|
80
|
-
|
81
|
-
def weekly_diaries
|
82
|
-
WeeklyDiary
|
83
|
-
.where(hospital_unit_id: unit_id)
|
84
|
-
.ordered
|
85
|
-
.page(page).per(per_page)
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
@@ -1,175 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# rubocop:disable Metrics/ClassLength
|
4
|
-
require_dependency "renalware/hd/base_controller"
|
5
|
-
|
6
|
-
module Renalware
|
7
|
-
module HD
|
8
|
-
class DiarySlotsController < BaseController
|
9
|
-
# GET html - renders a form
|
10
|
-
# Here we will have been passed in the query string:
|
11
|
-
# - the unit id
|
12
|
-
# - the dirunal_period_code id
|
13
|
-
# - the week and year (and thus the diary)
|
14
|
-
# and from that lot we could look up the master and weekly diaries
|
15
|
-
def new
|
16
|
-
# Be default this assume we are going to add a slot to the weekly diary
|
17
|
-
# but in which button is clicked in the modal dialog determines which diary
|
18
|
-
# (master or weekly) the slot will be added to.
|
19
|
-
slot = DiarySlot.new(
|
20
|
-
diary: weekly_diary,
|
21
|
-
station_id: params[:station_id],
|
22
|
-
day_of_week: params[:day_of_week],
|
23
|
-
diurnal_period_code_id: params[:diurnal_period_code_id]
|
24
|
-
)
|
25
|
-
authorize slot
|
26
|
-
render locals: locals_for(slot), layout: false
|
27
|
-
end
|
28
|
-
|
29
|
-
# POST create js
|
30
|
-
# Here we may be adding a slot to the weekly or master diary.
|
31
|
-
# That should be transparent to us - we make the change and render
|
32
|
-
# create.js.erb which, on the client, will cause an ajax js call to #show. That secondary call
|
33
|
-
# is the one that refreshes the slot in the table with its latest state.
|
34
|
-
# We do this to avoid having to to a check (in each action in this controller) to see if we
|
35
|
-
# are on the master or weekly diary; if we always refresh the diary slot in the ui after any
|
36
|
-
# action, then it will always update correctly.
|
37
|
-
def create
|
38
|
-
diary = Diary.find(params[:diary_id])
|
39
|
-
slot = diary.slots.new(slot_params)
|
40
|
-
slot.patient_id = posted_patient_id
|
41
|
-
authorize slot
|
42
|
-
if slot.save_by(current_user)
|
43
|
-
render locals: { diary: diary, slot: diary.decorate_slot(slot) }
|
44
|
-
else
|
45
|
-
render :new, locals: { slot: DiarySlotPresenter.new(slot) }, layout: false
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
# GET .js refresh a slot in a *weekly* diary
|
50
|
-
# See comment on #create.
|
51
|
-
# See show.js.erb where we refresh the slot in the diary
|
52
|
-
# To get here we will have manufactured a url like this
|
53
|
-
# hd/diaries/2/slots/day/1/period/1/station/1
|
54
|
-
# as those bit are will we know.
|
55
|
-
# Basically we are saying find for this weekly diary, find the matching
|
56
|
-
# slot for the station/day/period combo and render the weekly slot if there is
|
57
|
-
# one, or the master behind it if there is one of those, otherwise render an Add button.
|
58
|
-
def show
|
59
|
-
authorize DiarySlot, :show?
|
60
|
-
slot = weekly_then_master_then_empty_slot
|
61
|
-
render layout: false, locals: { slot: DiarySlotPresenter.new(slot) }
|
62
|
-
end
|
63
|
-
|
64
|
-
def edit
|
65
|
-
authorize slot
|
66
|
-
render layout: false, locals: { slot: DiarySlotPresenter.new(slot) }
|
67
|
-
end
|
68
|
-
|
69
|
-
# DELETE js
|
70
|
-
# Delete the slot (we don't know if its on the master or weekly diary).
|
71
|
-
# NB as per #create and #update, the rendered js file (destroy.js.erb) will make a secondary
|
72
|
-
# back into #show to refresh the UI (i.e. we don't attempt to update the UI in destroy.js.erb)
|
73
|
-
def destroy
|
74
|
-
authorize slot
|
75
|
-
slot.destroy!
|
76
|
-
render locals: { slot: DiarySlotPresenter.new(slot) }
|
77
|
-
end
|
78
|
-
|
79
|
-
# PATCH js
|
80
|
-
# See also comments in #create and #destroy.
|
81
|
-
def update
|
82
|
-
authorize slot
|
83
|
-
slot.patient_id = slot_params[:patient_id]
|
84
|
-
slot.save_by!(current_user)
|
85
|
-
diary = slot.diary
|
86
|
-
render locals: { diary: diary, slot: diary.decorate_slot(slot) }
|
87
|
-
end
|
88
|
-
|
89
|
-
private
|
90
|
-
|
91
|
-
# Find the corresponding slot in the master if there is one, otherwise an empty slot
|
92
|
-
# with an 'Add' button ready to set up a new patient
|
93
|
-
def weekly_then_master_then_empty_slot
|
94
|
-
empty_slot = build_empty_weekly_slot
|
95
|
-
find_weekly_slot(empty_slot) || find_master_slot(empty_slot) || empty_slot
|
96
|
-
end
|
97
|
-
|
98
|
-
def find_master_slot(args)
|
99
|
-
slot = master_diary.slots.find_by(
|
100
|
-
diurnal_period_code_id: args.diurnal_period_code_id,
|
101
|
-
station_id: args.station_id,
|
102
|
-
day_of_week: args.day_of_week
|
103
|
-
)
|
104
|
-
slot && master_diary.decorate_slot(slot)
|
105
|
-
end
|
106
|
-
|
107
|
-
def find_weekly_slot(args)
|
108
|
-
slot = weekly_diary.slots.find_by(
|
109
|
-
diurnal_period_code_id: args.diurnal_period_code_id,
|
110
|
-
station_id: args.station_id,
|
111
|
-
day_of_week: args.day_of_week
|
112
|
-
)
|
113
|
-
slot && weekly_diary.decorate_slot(slot)
|
114
|
-
end
|
115
|
-
|
116
|
-
# Used for searching etc
|
117
|
-
def build_empty_weekly_slot
|
118
|
-
weekly_diary.slots.new(
|
119
|
-
day_of_week: params[:day_of_week],
|
120
|
-
station_id: params[:station_id],
|
121
|
-
diurnal_period_code_id: params[:diurnal_period_code_id]
|
122
|
-
)
|
123
|
-
end
|
124
|
-
|
125
|
-
def slot
|
126
|
-
@slot ||= HD::DiarySlot.find(params[:id])
|
127
|
-
end
|
128
|
-
|
129
|
-
# In the url the :diary_id param is always the weekly diary id!
|
130
|
-
def weekly_diary
|
131
|
-
@weekly_diary ||= WeeklyDiary.find(params[:diary_id])
|
132
|
-
end
|
133
|
-
|
134
|
-
def master_diary
|
135
|
-
weekly_diary.master_diary
|
136
|
-
end
|
137
|
-
|
138
|
-
def locals_for(slot)
|
139
|
-
{
|
140
|
-
slot: DiarySlotPresenter.new(slot),
|
141
|
-
weekly_diary: weekly_diary
|
142
|
-
}
|
143
|
-
end
|
144
|
-
|
145
|
-
# In the modal dialog that submits the patient_id there are several (select2) dropdown
|
146
|
-
# a user can use to choose the patient. Each one has the name patient_id[] so they are
|
147
|
-
# submitted in the form as an array. However the array can only hold one id value ie we
|
148
|
-
# might get posted patient_id: ["", "123", ""] but never ["2", "123", ""].
|
149
|
-
# Here we reduce that array down to one patient id.
|
150
|
-
def posted_patient_id
|
151
|
-
patient_ids = Array(slot_params[:patient_id]).reject(&:blank?).uniq
|
152
|
-
if patient_ids.length > 1
|
153
|
-
raise ArgumentError, "More than one id submitted in patient_id[] : #{patient_ids}"
|
154
|
-
end
|
155
|
-
|
156
|
-
patient_ids.first
|
157
|
-
end
|
158
|
-
|
159
|
-
def slot_params
|
160
|
-
params
|
161
|
-
.require(:hd_diary_slot)
|
162
|
-
.permit(
|
163
|
-
:master_slot,
|
164
|
-
:day_of_week,
|
165
|
-
:diurnal_period_code_id,
|
166
|
-
:station_id,
|
167
|
-
:target_diary_id,
|
168
|
-
:change_type,
|
169
|
-
patient_id: []
|
170
|
-
)
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|
175
|
-
# rubocop:enable Metrics/ClassLength
|
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_dependency "renalware/letters"
|
4
|
-
|
5
|
-
module Renalware
|
6
|
-
module Letters
|
7
|
-
class DescriptionsController < ApplicationController
|
8
|
-
def search
|
9
|
-
query = Letters::Descriptions::SearchQuery.new(params[:term])
|
10
|
-
render json: DescriptionAutocompleteResponse.to_json(query.call)
|
11
|
-
end
|
12
|
-
|
13
|
-
class DescriptionAutocompleteResponse
|
14
|
-
def self.to_json(collection)
|
15
|
-
collection.map do |item|
|
16
|
-
{ id: item.id, label: item.text }
|
17
|
-
end.to_json
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_dependency "renalware/renal"
|
4
|
-
|
5
|
-
module Renalware
|
6
|
-
module Renal
|
7
|
-
class PRDDescriptionsController < BaseController
|
8
|
-
skip_after_action :verify_authorized, only: [:search]
|
9
|
-
|
10
|
-
def search
|
11
|
-
@prd_descriptions = PRDDescriptions::SearchQuery.new(term: params[:term]).call
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
@@ -1,69 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "renalware/hd"
|
4
|
-
|
5
|
-
# A cron job creates this delayed job, which does the following:
|
6
|
-
# For all Weekly Diaries in the past, plus this week
|
7
|
-
# for each day that is in the past
|
8
|
-
# mark any slots in the weekly diary as archived
|
9
|
-
# and where the weekly diary is inheriting slots from the master diary
|
10
|
-
# create corresponding slots in the weekly diary (ie migrate thos slots from master to weekly)
|
11
|
-
# and archive them.
|
12
|
-
# Not slots before the current day (or the up_until: arg) should be touched
|
13
|
-
#
|
14
|
-
#
|
15
|
-
# OK we have a problem,
|
16
|
-
# If last week there was no weekly diary created... then there is nothing to archive if eg today is
|
17
|
-
# Monday.
|
18
|
-
# So really whats the query for finding slots to archive?
|
19
|
-
# We need to really always inner join onto weekly diaryies, and within tose for their slots
|
20
|
-
# select unarchved onces in the past.
|
21
|
-
# So we MUST always have weekly diaries for every possible week and not rely om a user working te UI
|
22
|
-
# to create these JIT - because if they don't, unless we have a fn to creatae missing diaries,
|
23
|
-
# (from which date?) then we can't query
|
24
|
-
# So either
|
25
|
-
# - seed next 10 years (520 per unit)
|
26
|
-
# - have a fn to generate missing diaries - might be better and safer in the long run?
|
27
|
-
# - Otherwise after 5 or 10 years or whatever its bound to have cased a problem.
|
28
|
-
|
29
|
-
module Renalware
|
30
|
-
module HD
|
31
|
-
class ArchiveYesterdaysSlotsJob < ApplicationJob
|
32
|
-
attr_reader :up_until
|
33
|
-
|
34
|
-
# :reek:UtilityFunction
|
35
|
-
def perform(up_until: nil)
|
36
|
-
@up_until = up_until&.to_date
|
37
|
-
@up_until ||= (Time.zone.today - 1.day)
|
38
|
-
|
39
|
-
diary = Diary.find_by(year: @up_until.year, week_number: @up_until.cweek)
|
40
|
-
return unless diary
|
41
|
-
|
42
|
-
diary
|
43
|
-
.slots
|
44
|
-
.unarchived
|
45
|
-
.where(day_of_week: @up_until.cwday)
|
46
|
-
.update_all(archived: true, archived_at: Time.zone.now)
|
47
|
-
# DiarySlot
|
48
|
-
# .unarchived
|
49
|
-
# .joins(:diary)
|
50
|
-
# .where(hd_diaries: { year: up_until.year, week_number: up_until.cweek)
|
51
|
-
|
52
|
-
# .update_all(archived: true, archived_at: Time.zone.now)
|
53
|
-
end
|
54
|
-
|
55
|
-
private
|
56
|
-
|
57
|
-
def create_missing_weekly_diaries
|
58
|
-
# intering query
|
59
|
-
# basic implemenraiton
|
60
|
-
# select all weeklydiaries pluch year week from installation start date??? to now
|
61
|
-
# loop through
|
62
|
-
# diary year 2017 week 1
|
63
|
-
# MISSING diary year 2017 week 1 - so create
|
64
|
-
# diary year 2017 week 3
|
65
|
-
# select
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_dependency "renalware/hd"
|
4
|
-
|
5
|
-
# A Diary is the schedule of HD Station/Patients assignments for one week for a particular unit.
|
6
|
-
# A Diary is split into Periods (eg. am pm eve), and each Period has a matrix of slots
|
7
|
-
# Imagine Days eg 1 to 6 on the X axis and Stations on the Y axis, and into each 'slot' we
|
8
|
-
# put a patient.
|
9
|
-
# A patient can only be in one slot in any period.
|
10
|
-
#
|
11
|
-
# Do not create instances of this class explicity, always use the STI sub classes eg MasterDiary.
|
12
|
-
module Renalware
|
13
|
-
module HD
|
14
|
-
class Diary < ApplicationRecord
|
15
|
-
include Accountable
|
16
|
-
|
17
|
-
has_many :slots, class_name: "Renalware::HD::DiarySlot"
|
18
|
-
has_many :patients, through: :slots, class_name: "Renalware::HD::Patient"
|
19
|
-
validates :hospital_unit_id, presence: true
|
20
|
-
validates :master, inclusion: { in: [true, false], allow_nil: true }
|
21
|
-
composed_of :week,
|
22
|
-
mapping: [%w(week_number week_number), %w(year year)],
|
23
|
-
constructor: lambda { |week_number, year|
|
24
|
-
WeekPeriod.new(week_number: week_number, year: year)
|
25
|
-
}
|
26
|
-
|
27
|
-
def self.policy_class
|
28
|
-
DiaryPolicy
|
29
|
-
end
|
30
|
-
|
31
|
-
# Searchs the object graph rather than a SQL search
|
32
|
-
def slot_for(diurnal_period_code_id, station_id, day_of_week)
|
33
|
-
slots.find do |slot|
|
34
|
-
slot.diurnal_period_code_id == diurnal_period_code_id &&
|
35
|
-
slot.station_id == station_id &&
|
36
|
-
slot.day_of_week == day_of_week
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
@@ -1,83 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_dependency "renalware/hd"
|
4
|
-
|
5
|
-
module Renalware
|
6
|
-
module HD
|
7
|
-
# TODO: Document
|
8
|
-
class DiarySlot < ApplicationRecord
|
9
|
-
# Changing to_ary from private to public here is a hack required to remove a SimpleDelgator
|
10
|
-
# warning in eg Renalware::HD::WeeklyDiary::WeeklySlotDecorator:
|
11
|
-
#
|
12
|
-
# `respond_to?': delegator does not forward private method #to_ary
|
13
|
-
#
|
14
|
-
# Yielding a slot from DiaryPresenter to the view seems to want to call #to_ary on it, (have
|
15
|
-
# not looked into why) and as the slot is wrapped in a decorator using SimpleDelegator,
|
16
|
-
# SimpleDelegatr complains it can't delegate to a private method.
|
17
|
-
# An alternative is to define the following in each Slot decorator
|
18
|
-
#
|
19
|
-
# def respond_to?(method, include_private = false)
|
20
|
-
# return false if method == :to_ary
|
21
|
-
# super
|
22
|
-
# end
|
23
|
-
#
|
24
|
-
# or to use method_missnig instead of SimpleDelegator in Slot Decorators.
|
25
|
-
#
|
26
|
-
public :to_ary
|
27
|
-
|
28
|
-
# Virtual attribute used on a form to determine what action as preformed on the slot
|
29
|
-
attr_accessor :change_type
|
30
|
-
|
31
|
-
include Accountable
|
32
|
-
belongs_to :diary, class_name: "Renalware::HD::Diary", touch: true
|
33
|
-
belongs_to :patient, touch: true
|
34
|
-
belongs_to :station, class_name: "Renalware::HD::Station"
|
35
|
-
belongs_to :diurnal_period_code
|
36
|
-
|
37
|
-
validates :diary, presence: true
|
38
|
-
validates :patient, presence: true
|
39
|
-
validates :station, presence: true
|
40
|
-
validates :diurnal_period_code, presence: true
|
41
|
-
validates :day_of_week, presence: true, inclusion: { in: 1..7 }
|
42
|
-
|
43
|
-
scope :weekly, -> { joins(:diary).where(hd_diaries: { master: false }) }
|
44
|
-
scope :archived, -> { weekly.where(archived: true) }
|
45
|
-
scope :unarchived, -> { weekly.where(archived: false) }
|
46
|
-
|
47
|
-
# A patient can only be assigned to one station in any period (e.g. am)/day combination
|
48
|
-
# for a diary. I.e. they can't be on two stations on Monday morning.
|
49
|
-
validates :patient_id,
|
50
|
-
uniqueness: { scope: [:diary, :diurnal_period_code, :day_of_week] }
|
51
|
-
|
52
|
-
# Scoped to a diary, the combination of day + station + diurnal_period is unique
|
53
|
-
validates :diurnal_period_code_id, uniqueness: { scope: [:diary, :station_id, :day_of_week] }
|
54
|
-
|
55
|
-
delegate :id, to: :diary, prefix: true
|
56
|
-
|
57
|
-
def self.policy_class
|
58
|
-
DiaryPolicy
|
59
|
-
end
|
60
|
-
|
61
|
-
def on_master_diary?
|
62
|
-
diary&.master?
|
63
|
-
end
|
64
|
-
|
65
|
-
def description
|
66
|
-
period = diurnal_period_code.code.upcase # e.g. AM
|
67
|
-
if diary.master
|
68
|
-
"Recurring every #{day_of_week_name} #{period}"
|
69
|
-
else
|
70
|
-
"This week only on #{day_of_week_name} #{period}"
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def day_of_week_name
|
75
|
-
Time::DAYS_INTO_WEEK.keys[day_of_week - 1].capitalize
|
76
|
-
end
|
77
|
-
|
78
|
-
def cell_id
|
79
|
-
"#{diurnal_period_code&.id}-#{station&.id}-#{day_of_week}"
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_dependency "renalware/hd"
|
4
|
-
require "renalware/week_period"
|
5
|
-
##
|
6
|
-
# Returns a hospital unit's diary for the requested week (passed to #new as a WeekPeriod
|
7
|
-
# value object).
|
8
|
-
#
|
9
|
-
module Renalware
|
10
|
-
module HD
|
11
|
-
class FindOrCreateDiaryByWeekQuery
|
12
|
-
attr_reader :unit_id, :period, :by, :relation
|
13
|
-
|
14
|
-
def initialize(unit_id:, week_period:, by:, relation: WeeklyDiary.all)
|
15
|
-
@relation = relation
|
16
|
-
@period = week_period
|
17
|
-
@unit_id = unit_id
|
18
|
-
@by = by
|
19
|
-
end
|
20
|
-
|
21
|
-
def call
|
22
|
-
find_or_create_diary
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
# Find the diary for the current unit/week/year, or, if for example if a user wants to fill
|
28
|
-
# next week's diary and it does not yet exist, create it
|
29
|
-
# NB we _always_ return a diary from this method - whether it is found or built just-in-time,
|
30
|
-
def find_or_create_diary
|
31
|
-
attrs = {
|
32
|
-
hospital_unit_id: unit_id,
|
33
|
-
week_number: period.week_number,
|
34
|
-
year: period.year,
|
35
|
-
master: false
|
36
|
-
}
|
37
|
-
relation.find_by(**attrs) || build_diary(**attrs)
|
38
|
-
end
|
39
|
-
|
40
|
-
# Create a new Weekly diary for the current week/year/unit
|
41
|
-
# Add in DiaryPeriods for each currently defined diurnal period eg am pm eve
|
42
|
-
def build_diary(attrs)
|
43
|
-
master_diary = FindOrCreateMasterDiary.for_unit(unit_id, by)
|
44
|
-
diary = WeeklyDiary.create!(**attrs, by: by, master_diary: master_diary)
|
45
|
-
# Reload the diary using the supplied relation (might be egager_loads etc)
|
46
|
-
relation.find(diary.id)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Renalware
|
4
|
-
module HD
|
5
|
-
class FindOrCreateMasterDiary
|
6
|
-
attr_reader :unit_id, :user
|
7
|
-
|
8
|
-
def self.for_unit(unit_id, user)
|
9
|
-
new(unit_id, user).call
|
10
|
-
end
|
11
|
-
|
12
|
-
def initialize(unit_id, user)
|
13
|
-
@unit_id = unit_id
|
14
|
-
@user = user
|
15
|
-
end
|
16
|
-
|
17
|
-
# TODO: !alwasy suing first :0)
|
18
|
-
def call
|
19
|
-
MasterDiary.find_or_initialize_by(hospital_unit_id: unit_id).tap do |master|
|
20
|
-
master.by = user
|
21
|
-
master.save!
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_dependency "renalware/hd"
|
4
|
-
|
5
|
-
module Renalware
|
6
|
-
module HD
|
7
|
-
class MasterDiary < Diary
|
8
|
-
# Overwrite the existing master attribute to ensure it defaults to true
|
9
|
-
attribute :master, :boolean, default: true
|
10
|
-
validates :hospital_unit_id, uniqueness: true
|
11
|
-
has_many :weekly_diaries, class_name: "Renalware::HD::WeeklyDiary"
|
12
|
-
# While out DB constraints could check for the string "Renalware::HD::MasterDiary" in the type
|
13
|
-
# column, this feels a bit fragile, so instead a MasterDiary must have a corresponding
|
14
|
-
# master = TRUE column
|
15
|
-
validates :master, inclusion: { in: [true], allow_nil: false }
|
16
|
-
|
17
|
-
class MasterSlotDecorator < SimpleDelegator
|
18
|
-
def master?
|
19
|
-
true
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def decorate_slot(slot)
|
24
|
-
MasterSlotDecorator.new(slot)
|
25
|
-
end
|
26
|
-
|
27
|
-
def slot_for(*args)
|
28
|
-
(slot = super) && decorate_slot(slot)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_dependency "renalware/hd"
|
4
|
-
|
5
|
-
module Renalware
|
6
|
-
module HD
|
7
|
-
class WeeklyDiary < Diary
|
8
|
-
# Overwrite the existing master attribute to ensure it defaults to false
|
9
|
-
attribute :master, :boolean, default: false
|
10
|
-
belongs_to :master_diary, class_name: "Renalware::HD::MasterDiary"
|
11
|
-
validates :week_number,
|
12
|
-
presence: true,
|
13
|
-
uniqueness: { scope: [:year, :hospital_unit_id] },
|
14
|
-
inclusion: { in: 1..53 }
|
15
|
-
validates :year, presence: true
|
16
|
-
validates :master, inclusion: { in: [false], allow_nil: false }
|
17
|
-
validates :master_diary, presence: true
|
18
|
-
delegate :to_s, to: :week
|
19
|
-
scope :ordered, -> { order(year: :desc, week_number: :desc) }
|
20
|
-
|
21
|
-
def applies_to_current_week?
|
22
|
-
today = Time.zone.today
|
23
|
-
[today.cweek, today.year] == [week.week_number, week.year]
|
24
|
-
end
|
25
|
-
|
26
|
-
def archived?
|
27
|
-
false
|
28
|
-
end
|
29
|
-
|
30
|
-
class WeeklySlotDecorator < SimpleDelegator
|
31
|
-
def master?
|
32
|
-
false
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def decorate_slot(slot)
|
37
|
-
WeeklySlotDecorator.new(slot)
|
38
|
-
end
|
39
|
-
|
40
|
-
def slot_for(*args)
|
41
|
-
(slot = super) && decorate_slot(slot)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_dependency "renalware/renal"
|
4
|
-
|
5
|
-
module Renalware
|
6
|
-
module Renal
|
7
|
-
module PRDDescriptions
|
8
|
-
class SearchQuery
|
9
|
-
attr_reader :term, :page, :per_page
|
10
|
-
|
11
|
-
def initialize(term:, page: 1, per_page: 50)
|
12
|
-
@term = term
|
13
|
-
@page = page
|
14
|
-
@per_page = per_page
|
15
|
-
end
|
16
|
-
|
17
|
-
def call
|
18
|
-
search.result.page(page).per(per_page).select(fields)
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def search
|
24
|
-
@search ||= PRDDescription.ransack(term_or_code_cont: term).tap do |s|
|
25
|
-
s.sorts = ["term"]
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def fields
|
30
|
-
%i(id code term)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|