renalware-core 2.0.109 → 2.0.110

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/renalware/loading-gears-animation.gif +0 -0
  3. data/app/assets/javascripts/renalware/drugs.js +3 -4
  4. data/app/assets/javascripts/renalware/letters.js +47 -2
  5. data/app/assets/pdf/blank_page.pdf +56 -0
  6. data/app/assets/stylesheets/renalware/modules/_letters.scss +46 -0
  7. data/app/assets/stylesheets/renalware/partials/_tables.scss +2 -2
  8. data/app/controllers/renalware/base_controller.rb +9 -2
  9. data/app/controllers/renalware/clinics/appointments_controller.rb +8 -3
  10. data/app/controllers/renalware/letters/batches_controller.rb +106 -0
  11. data/app/controllers/renalware/letters/completed_batches_controller.rb +32 -0
  12. data/app/controllers/renalware/letters/lists_controller.rb +34 -5
  13. data/app/controllers/renalware/pathology/requests/requests_controller.rb +1 -1
  14. data/app/jobs/renalware/hd/update_rolling_patient_statistics_dj_job.rb +38 -0
  15. data/app/jobs/renalware/hd/update_rolling_patient_statistics_job.rb +4 -2
  16. data/app/jobs/renalware/letters/printing/batch_print_job.rb +27 -0
  17. data/app/models/concerns/renalware/patients_ransack_helper.rb +1 -1
  18. data/app/models/concerns/renalware/using_temp_folder.rb +14 -0
  19. data/app/models/renalware/clinics/appointment.rb +2 -3
  20. data/app/models/renalware/clinics/appointment_query.rb +5 -1
  21. data/app/models/renalware/hd/sessions/save_session.rb +5 -1
  22. data/app/models/renalware/hd/update_rolling_patient_statistics.rb +1 -1
  23. data/app/models/renalware/letters/batch.rb +37 -0
  24. data/app/models/renalware/letters/batch_item.rb +17 -0
  25. data/app/models/renalware/letters/lists/form.rb +101 -0
  26. data/app/models/renalware/letters/pdf_letter_cache.rb +1 -1
  27. data/app/models/renalware/letters/printing/batch_compile_pdfs.rb +121 -0
  28. data/app/models/renalware/letters/printing/complete_batch.rb +24 -0
  29. data/app/models/renalware/letters/printing/create_pdf_by_interleaving_address_sheet_and_letter_for_each_recipient.rb.dead +90 -0
  30. data/app/models/renalware/letters/printing/duplex_interleaved_pdf_renderer.rb +1 -1
  31. data/app/models/renalware/letters/printing/pdf_combining.rb +24 -21
  32. data/app/models/renalware/pathology/{consultant.rb → consultant.rb.dead} +0 -0
  33. data/app/models/renalware/pathology/observations_grouped_by_date_query.rb +1 -1
  34. data/app/models/renalware/pathology/relevant_observation_description.rb +1 -1
  35. data/app/models/renalware/pathology/requests/global_rule/transplant_date_within_weeks.rb +1 -1
  36. data/app/models/renalware/pathology/requests/global_rule/transplant_registration_status.rb +3 -1
  37. data/app/models/renalware/pathology/requests/request.rb +1 -1
  38. data/app/models/renalware/pathology/requests/request_params_factory.rb +11 -12
  39. data/app/models/renalware/patient.rb +3 -2
  40. data/app/models/renalware/pd/apd_regime.rb +6 -6
  41. data/app/models/renalware/renal/consultant.rb +16 -0
  42. data/app/models/renalware/transplants/registrations/wait_list_query.rb +4 -10
  43. data/app/models/renalware/ukrdc/treatment_timeline/generator_factory.rb +1 -1
  44. data/app/pdfs/renalware/letters/printing/recipient_address_page_pdf.rb +50 -0
  45. data/app/policies/renalware/letters/batch_policy.rb +13 -0
  46. data/app/presenters/renalware/letters/recipient_presenter.rb +1 -1
  47. data/app/presenters/renalware/pathology/requests/request_presenter.rb +1 -1
  48. data/app/presenters/renalware/transplants/mdm_presenter.rb +1 -1
  49. data/app/presenters/renalware/virology/dashboard_presenter.rb +2 -1
  50. data/app/views/renalware/api/ukrdc/patients/_hd_session_observations.xml.builder +2 -2
  51. data/app/views/renalware/clinics/appointments/index.html.slim +5 -4
  52. data/app/views/renalware/clinics/appointments/new.html.slim +3 -0
  53. data/app/views/renalware/letters/batches/_create.html.slim +27 -0
  54. data/app/views/renalware/letters/batches/create.js.erb +3 -0
  55. data/app/views/renalware/letters/batches/index.html.slim +20 -0
  56. data/app/views/renalware/letters/batches/show.html.slim +7 -0
  57. data/app/views/renalware/letters/completed_batches/create.js.erb +9 -0
  58. data/app/views/renalware/letters/completed_batches/new.html.slim +26 -0
  59. data/app/views/renalware/letters/lists/_table.html.slim +1 -1
  60. data/app/views/renalware/letters/lists/_tabs.html.slim +9 -0
  61. data/app/views/renalware/letters/lists/index.html.slim.dead +101 -0
  62. data/app/views/renalware/letters/lists/index.html.slim.dead1 +90 -0
  63. data/app/views/renalware/letters/lists/show.html.slim +57 -11
  64. data/app/views/renalware/medications/prescriptions/_form.html.slim +1 -0
  65. data/app/views/renalware/navigation/_super_admin.html.slim +1 -0
  66. data/app/views/renalware/pathology/requests/requests/_pdf_header.html.slim +2 -3
  67. data/app/views/renalware/pathology/requests/requests/index.html.slim +1 -1
  68. data/app/views/renalware/pathology/requests/requests/new.html.slim +0 -1
  69. data/config/locales/renalware/letters/letter.en.yml +5 -0
  70. data/config/routes/letters.rb +18 -1
  71. data/db/migrate/20190830153416_create_letter_batches.rb +14 -0
  72. data/db/migrate/20190902085216_create_letter_batch_items.rb +13 -0
  73. data/db/migrate/20190919073410_add_filepath_to_letter_batches.rb +7 -0
  74. data/db/migrate/20190920063447_add_status_to_letter_batch_items.rb +15 -0
  75. data/db/migrate/20190925104902_remove_user_from_appointments.rb +19 -0
  76. data/db/migrate/20190925130052_add_telephone_to_renal_consultants.rb +7 -0
  77. data/db/migrate/20190925161724_change_path_request_consultant_id.rb +19 -0
  78. data/db/migrate/20190925173849_renal_consultants_changes.rb +9 -0
  79. data/db/migrate/20190928131032_add_some_more_missing_indexes.rb +18 -0
  80. data/db/views/pathology_observation_digests_v01.sql +1 -1
  81. data/lib/renalware/configuration.rb +2 -0
  82. data/lib/renalware/engine.rb +1 -0
  83. data/lib/renalware/version.rb +1 -1
  84. data/lib/tasks/demo_data.rake +66 -0
  85. data/lib/tasks/pd.rake +32 -0
  86. data/spec/factories/clinics/appointments.rb +1 -1
  87. data/spec/factories/medications/medication_route.rb +5 -0
  88. data/spec/factories/renal/consultants.rb +9 -0
  89. data/spec/support/pages/medications/prescription_fom.rb +54 -0
  90. metadata +43 -7
  91. data/app/models/renalware/letters/printing/create_pdf_by_interleaving_address_sheet_and_letter_for_each_recipient.rb +0 -140
  92. data/spec/factories/pathology/consultant.rb +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c997818b4731d4dacc650d1ee21da4bc8d0731612f4b6afb6992375ad8ab5ebe
4
- data.tar.gz: ca7fb8bb184625a629f68e685a8af2ed8a931e597496d3ad4f47f4cd7dd20f83
3
+ metadata.gz: d299c658864be00fd2bb5e32766ca4bb07f92e4d1e3cac36536bbb351dc13132
4
+ data.tar.gz: d405e456e7f324d56d2d9b10cd4643dd7d20721967d1126461d4f287150b83e1
5
5
  SHA512:
6
- metadata.gz: 1f78547330d9e31903a14a2c794f782589ce3624888912a84bc3204d8e939091e503b29def2e06c7d835db8c70d9cb840986480ae77fbbd57bdf8d6bc7837ff2
7
- data.tar.gz: 341dd6ad0f4f7c298de70c14b47cae472524fcd502d084c89c24a9020cdc37dde51970b517cd20eb7d2e3c31e4ec77bd31b59c354b72b88e376dd6e50c5884f7
6
+ metadata.gz: 22d08baf9693562abd1048245c849a2015d1210594b1f7821f78820a626ac58b21442f742c702add9798b4dde1ea33e2b423703dee6e94622aa340c0ce4a689d
7
+ data.tar.gz: fcb3ddb0e16d5bc177dace948ea795659523d196086967a0743b0a98843561b325bcc9b148b2f31123324a00d9817c13ca4575d4f5bc096cab95fc0469b23544
@@ -39,7 +39,7 @@ $(document).ready(function(){
39
39
  data: { medication_switch: selectedMedicationType },
40
40
  success: function(json) {
41
41
  var $drugSelectBox = $medForm.find('.drug-select');
42
- var option_template = "<option class='drug-select-link' value=<%=id%>><%=name%></option>"
42
+ var option_template = "<option value=<%=id%>><%=name%></option>"
43
43
 
44
44
  $drugSelectBox.html('');
45
45
  $drugSelectBox.append(_.template(option_template)({ id: null, name: 'Please select' }));
@@ -79,7 +79,7 @@ $(document).ready(function(){
79
79
  if (query.length > 2) {
80
80
  $.ajax({
81
81
  url: '/drugs/drugs.json',
82
- data: { q : { name_or_drug_types_name_start : query } },
82
+ data: { q : { name_or_drug_types_name_cont : query } },
83
83
  success: function(json) {
84
84
  $drugResults.html('').show();
85
85
  for (var i = 0; i < json.length; i++) {
@@ -115,7 +115,7 @@ $(document).ready(function(){
115
115
  $medForm.find('.selected-drug-id').val(selectedDrug);
116
116
  }, delay);
117
117
 
118
- $('.drug-select').change(function(e) {
118
+ $('.drug-select').unbind().change(function(e) {
119
119
  var $bullet = $(e.currentTarget);
120
120
  var $medForm = $bullet.closest('.med-form');
121
121
  var selectedDrug = $medForm.find('.drug-select').val();
@@ -125,4 +125,3 @@ $(document).ready(function(){
125
125
  });
126
126
 
127
127
  });
128
-
@@ -24,6 +24,15 @@ Renalware.Letters = (function() {
24
24
  });
25
25
  }
26
26
 
27
+ var bindOnLetterAboutToBatchPrint = function() {
28
+ $(document).on("click", ".print-batch-letter", function(e) {
29
+ var modal = $("#letter-print-modal");
30
+ url = $(this).data("modal-url");
31
+ modal.load(url).foundation('reveal', 'open');
32
+ true;
33
+ });
34
+ }
35
+
27
36
  var bindOnSalutationChange = function() {
28
37
 
29
38
  $("#letter-form").on("click", ".has_salutation", function(e) {
@@ -91,7 +100,41 @@ Renalware.Letters = (function() {
91
100
  alert("There are no notes to insert");
92
101
  }
93
102
  });
94
- }
103
+ };
104
+
105
+ var pollBatchStatus = function(url) {
106
+ var POLL_INTERVAL = 2000; // ms
107
+ var batch = {};
108
+
109
+ // Check the current status of the TaskStatus object.
110
+ var updateStatus = function() {
111
+ $.ajax({
112
+ method: 'GET',
113
+ url: url,
114
+ contentType: 'json'
115
+ }).fail(function(e, x, a) {
116
+ // Possible network glitch or perhaps a re-deploy causing the site to be down momentarily.
117
+ // Anyway, not enough for us to give up polling.
118
+ // TODO: examine the response code to see if we should in fact give up and show an
119
+ // appropriate message.
120
+ setTimeout(updateStatus, POLL_INTERVAL);
121
+ }).done(function(batch) {
122
+ // Done!
123
+ $(".modal .percent_complete").html(batch.percent_complete + "%");
124
+ if(batch.status == 'awaiting_printing') {
125
+ $(".batch_results_container .preparing").hide();
126
+ $(".batch_results_container .generated-batch-print-pdf-container").show();
127
+ }
128
+ // Not done!
129
+ else {
130
+ // Could update a progress/100% tracker here
131
+ // Ask again in POLL_INTERVAL ms.
132
+ setTimeout(updateStatus, POLL_INTERVAL);
133
+ }
134
+ });
135
+ };
136
+ setTimeout(updateStatus, POLL_INTERVAL);
137
+ };
95
138
 
96
139
  return {
97
140
  init: function () {
@@ -101,8 +144,10 @@ Renalware.Letters = (function() {
101
144
  initNewContactAsMainRecipient();
102
145
  initNewContactAsCC();
103
146
  initInsertEventNotesIntoTextEditor();
147
+ bindOnLetterAboutToBatchPrint();
104
148
  bindOnLetterAboutToPrint();
105
- }
149
+ },
150
+ pollBatchStatus: pollBatchStatus
106
151
  };
107
152
  }());
108
153
 
@@ -0,0 +1,56 @@
1
+ %PDF-1.3
2
+ %����
3
+ 1 0 obj
4
+ << /Creator <feff0050007200610077006e>
5
+ /Producer <feff0050007200610077006e>
6
+ >>
7
+ endobj
8
+ 2 0 obj
9
+ << /Type /Catalog
10
+ /Pages 3 0 R
11
+ >>
12
+ endobj
13
+ 3 0 obj
14
+ << /Type /Pages
15
+ /Count 1
16
+ /Kids [5 0 R]
17
+ >>
18
+ endobj
19
+ 4 0 obj
20
+ << /Length 4
21
+ >>
22
+ stream
23
+ q
24
+ Q
25
+
26
+ endstream
27
+ endobj
28
+ 5 0 obj
29
+ << /Type /Page
30
+ /Parent 3 0 R
31
+ /MediaBox [0 0 595.28 841.89]
32
+ /CropBox [0 0 595.28 841.89]
33
+ /BleedBox [0 0 595.28 841.89]
34
+ /TrimBox [0 0 595.28 841.89]
35
+ /ArtBox [0 0 595.28 841.89]
36
+ /Contents 4 0 R
37
+ /Resources << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
38
+ >>
39
+ >>
40
+ endobj
41
+ xref
42
+ 0 6
43
+ 0000000000 65535 f
44
+ 0000000015 00000 n
45
+ 0000000109 00000 n
46
+ 0000000158 00000 n
47
+ 0000000215 00000 n
48
+ 0000000268 00000 n
49
+ trailer
50
+ << /Size 6
51
+ /Root 2 0 R
52
+ /Info 1 0 R
53
+ >>
54
+ startxref
55
+ 540
56
+ %%EOF
@@ -112,3 +112,49 @@ table.letters {
112
112
  }
113
113
  }
114
114
  }
115
+
116
+ #batch-print-modal {
117
+ .cancel-link {
118
+ margin-bottom: 0.5em;
119
+ display: inline-block;
120
+ font-size: 1rem;
121
+ }
122
+
123
+ .percent_complete {
124
+ font-size: 1.3rem;
125
+ float: right;
126
+ }
127
+
128
+ .modal__footer {
129
+ .left {
130
+ color: $dashboard-muted-color;
131
+ }
132
+ }
133
+ }
134
+
135
+ .batch_results_container {
136
+ text-align: center;
137
+ }
138
+
139
+ .generated-batch-print-pdf-container {
140
+ text-align: center;
141
+ padding: 1.5rem 0;
142
+ font-size: 1.3rem;
143
+
144
+ .print-batch-letter {
145
+ padding: .5rem 1rem;
146
+ text-decoration: underline;
147
+ color: $nhs-green;
148
+
149
+ &:hover {
150
+ color: $nhs-dark-green;
151
+ }
152
+
153
+ i {
154
+ padding: 1rem 1rem 1rem 0;
155
+ vertical-align: sub;
156
+ color: $nhs-green;
157
+ font-size: 1.8rem;
158
+ }
159
+ }
160
+ }
@@ -218,8 +218,8 @@ table {
218
218
  }
219
219
 
220
220
  &.col-width-date-time {
221
- min-width: 9.5rem;
222
- width: 9.5rem;
221
+ min-width: 9.6rem;
222
+ width: 9.6rem;
223
223
  }
224
224
 
225
225
  &.col-width-reference-without-prefix {
@@ -9,9 +9,16 @@ module Renalware
9
9
 
10
10
  before_action :set_paper_trail_whodunnit
11
11
  after_action :verify_authorized
12
+
13
+ # A note on ahoy tracking:
12
14
  # has_user_timed_out is defined on SessionTimeoutController
13
- # Perhaps we should define #has_user_timed_out here and override in SessionTimeoutController?
14
- after_action :track_action, except: [:has_user_timed_out]
15
+ # using this in the that controller
16
+ # skip_before_action :track_ahoy_visit, only: has_user_timed_out
17
+ # does not seem to work hence this global blacklist
18
+
19
+ # rubocop:disable Rails/LexicallyScopedActionFilter
20
+ after_action :track_action, except: [:has_user_timed_out, :status]
21
+ # rubocop:enable Rails/LexicallyScopedActionFilter
15
22
 
16
23
  rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
17
24
 
@@ -27,9 +27,8 @@ module Renalware
27
27
 
28
28
  def create
29
29
  appointment = Appointment.new(appointment_params)
30
- appointment.user = current_user
31
30
  authorize appointment
32
- if appointment.save
31
+ if appointment.save_by(current_user)
33
32
  redirect_to appointments_path, notice: t(".success", model_name: "Appointment")
34
33
  else
35
34
  render_new(appointment)
@@ -56,7 +55,13 @@ module Renalware
56
55
  def appointment_params
57
56
  params
58
57
  .require(:clinics_appointment)
59
- .permit(:patient_id, :clinic_id, :starts_at, :outcome_notes, :dna_notes, :clinician_id)
58
+ .permit(
59
+ :patient_id,
60
+ :clinic_id,
61
+ :starts_at,
62
+ :outcome_notes,
63
+ :dna_notes,
64
+ :consultant_id)
60
65
  end
61
66
  end
62
67
  end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_dependency "renalware/letters"
4
+
5
+ module Renalware
6
+ module Letters
7
+ class BatchesController < BaseController
8
+ include Renalware::Concerns::Pageable
9
+
10
+ def create
11
+ batch = create_unprocessed_batch_and_batch_items(ids_of_letters_to_batch_print)
12
+ authorize batch
13
+ Printing::BatchPrintJob.perform_later(batch, current_user)
14
+ respond_to do |format|
15
+ format.js {
16
+ render locals: { batch: batch }
17
+ }
18
+ end
19
+ end
20
+
21
+ # rubocop:disable Metrics/MethodLength
22
+ def status
23
+ batch = find_and_authorize_batch(params[:batch_id])
24
+ respond_to do |format|
25
+ format.json {
26
+ render(
27
+ status: :ok,
28
+ json: {
29
+ id: batch.id,
30
+ status: batch.status,
31
+ percent_complete: batch.percent_complete
32
+ }
33
+ )
34
+ }
35
+ end
36
+ end
37
+ # rubocop:enable Metrics/MethodLength
38
+
39
+ # rubocop:disable Metrics/MethodLength
40
+ def show
41
+ batch = find_and_authorize_batch
42
+ respond_to do |format|
43
+ format.pdf do
44
+ # Returns the PDF itself using path saved in the Batch - provided status is correct
45
+ send_file(
46
+ batch.filepath,
47
+ type: "application/pdf",
48
+ disposition: "inline",
49
+ filename: "letter_batch_#{batch.id}.pdf"
50
+ )
51
+ end
52
+ format.html do
53
+ # Returns a partial with a link to the compiled batch pdf
54
+ render layout: false, locals: { batch: find_and_authorize_batch }
55
+ end
56
+ end
57
+ end
58
+ # rubocop:enable Metrics/MethodLength
59
+
60
+ def index
61
+ batches = Batch.order(created_at: :desc)
62
+ authorize batches
63
+ render locals: { batches: batches.page(page).per(per_page) }
64
+ end
65
+
66
+ private
67
+
68
+ def find_and_authorize_batch(id = nil)
69
+ id ||= params[:id]
70
+ Letters::Batch.find(id).tap do |batch|
71
+ authorize batch
72
+ end
73
+ end
74
+
75
+ def ids_of_letters_to_batch_print
76
+ LetterQuery
77
+ .new(q: batch_params)
78
+ .call
79
+ .select(:id, :event_type, :event_id)
80
+ .map(&:id)
81
+ end
82
+
83
+ def create_unprocessed_batch_and_batch_items(letter_ids)
84
+ batch = Batch.new
85
+ Batch.transaction do
86
+ letter_ids.each { |letter_id| batch.items.build(letter_id: letter_id) }
87
+ batch.save_by!(current_user)
88
+ end
89
+ batch
90
+ end
91
+
92
+ def batch_params
93
+ params
94
+ .require(:batch)
95
+ .permit(
96
+ :enclosures_present,
97
+ :state_eq,
98
+ :author_id_eq,
99
+ :created_by_id_eq,
100
+ :letterhead_id_eq,
101
+ :page_count_in_array
102
+ )
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_dependency "renalware/letters"
4
+
5
+ module Renalware
6
+ module Letters
7
+ class CompletedBatchesController < BaseController
8
+ include Renalware::Concerns::Pageable
9
+
10
+ # Renders a modal asking the user if they want to complete (ie mark as printed)
11
+ # the batch.
12
+ def new
13
+ batch = find_and_authorize_batch
14
+ render layout: false, locals: { batch: batch }
15
+ end
16
+
17
+ def create
18
+ batch = find_and_authorize_batch
19
+ Printing::CompleteBatch.new(user: current_user, batch: batch).call
20
+ render layout: false, locals: { batch: batch }
21
+ end
22
+
23
+ private
24
+
25
+ def find_and_authorize_batch
26
+ Letters::Batch.find(params[:batch_id]).tap do |batch|
27
+ authorize batch
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -10,16 +10,24 @@ module Renalware
10
10
  # rubocop:disable Metrics/MethodLength
11
11
  # TODO: Use a presenter here
12
12
  def show
13
- query = LetterQuery.new(q: params[:q])
13
+ named_filter = params.fetch(:named_filter, "all").to_sym
14
+ form = form_for(named_filter)
15
+ query = LetterQuery.new(q: form.attributes)
14
16
  letters = find_and_authorize_letters(query)
15
17
 
18
+ q = query.search
19
+
16
20
  locals = {
17
21
  letters: letters,
18
- authors: User.author.ordered,
19
- typists: User.ordered,
20
- letterheads: Letters::Letterhead.ordered,
21
- q: query.search
22
+ q: q,
23
+ form: form_for(named_filter)
22
24
  }
25
+
26
+ # Could pass back a batchprint summary
27
+ # {
28
+ # count: 123,
29
+ # excluded_enc: 3
30
+ # }
23
31
  respond_to do |format|
24
32
  format.html { render(locals: locals) }
25
33
  format.js { render(locals: locals, layout: false) }
@@ -29,6 +37,10 @@ module Renalware
29
37
 
30
38
  private
31
39
 
40
+ def form_for(named_filter)
41
+ Lists::Form.new(named_filter: named_filter, params: filter_parameters)
42
+ end
43
+
32
44
  def find_and_authorize_letters(query)
33
45
  collection = call_query(query).page(page).per(per_page)
34
46
  present_letters(collection).tap { |letters| authorize letters }
@@ -47,6 +59,23 @@ module Renalware
47
59
  .with_author
48
60
  .with_created_by
49
61
  end
62
+
63
+ # These are used also when creating a batch.
64
+ def filter_parameters
65
+ return {} unless params.key?(:q)
66
+
67
+ params
68
+ .require(:q)
69
+ .permit(
70
+ :enclosures_present,
71
+ :state_eq,
72
+ :author_id_eq,
73
+ :created_by_id_eq,
74
+ :letterhead_id_eq,
75
+ :page_count_in_array,
76
+ :s
77
+ )
78
+ end
50
79
  end
51
80
  end
52
81
  end