Advertisement
andrey_zavyalov

Untitled

Mar 6th, 2024
16
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.35 KB | None | 0 0
  1. # frozen_string_literal: true
  2.  
  3. require 'csv'
  4.  
  5. class GenerateAggregateReportQwerty
  6. def perform(admin_id:, include_incomplete_assessment_data: true, current_user_id: 1, start_date: nil, end_date: nil)
  7. @admin_id = admin_id
  8. @start_date = start_date
  9. @end_date = end_date
  10. @include_incomplete_assessment_data = include_incomplete_assessment_data
  11. @current_user_id = current_user_id
  12.  
  13. generate_report
  14. media_file = create_media_file(current_user_id)
  15. puts media_file.path
  16. # send_email(media_file, AdminUser.find(current_user_id).dmail)
  17. delete_tmp_files
  18. end
  19.  
  20. private
  21.  
  22. # def send_email(media_file, email)
  23. # ServiceMailer.aggregate_report(media_file, email).deliver
  24. # end
  25.  
  26. def create_media_file(current_user_id)
  27. media_file = MediaFile.find_or_create_by(name: csv_file_name,
  28. admin_user_id: current_user_id)
  29. media_file.asset.attach(
  30. io: File.open(tmp_file_name),
  31. filename: csv_file_name,
  32. content_type: 'text/csv'
  33. )
  34. media_file.update!(
  35. asset_file_name: csv_file_name,
  36. allow_others_to_copy: NO,
  37. public: false,
  38. category: :admin_report
  39. )
  40. media_file
  41. end
  42.  
  43. def protocol_ids
  44. @protocol_ids ||= ::Health::Protocol.where(owner_id: clinic_admin_ids).ids
  45. end
  46.  
  47. def test_ids
  48. @test_ids ||= tests.ids
  49. end
  50.  
  51. def tests
  52. @tests ||= Test.format_html5.where.not(id: Test::Sar.id).order(:id)
  53. end
  54.  
  55. def questionnaires
  56. return @questionnaires if @questionnaires
  57.  
  58. @questionnaires = {}
  59. ::Health::Questionnaire.where(id: questionnaire_ids).each do |questionnaire|
  60. @questionnaires[questionnaire.id] = I18n.t(questionnaire.questionnaire_type)
  61. end
  62.  
  63. @questionnaires
  64. end
  65.  
  66. def questionnaire_ids
  67. @questionnaire_ids ||= BatchPage.joins(:questionnaire).where(admin_user_id: clinic_admin_ids)
  68. .pluck(:questionnaire_id).uniq.compact.sort
  69. end
  70.  
  71. def clinic_admin_ids
  72. @clinic_admin_ids ||= ::Health::ClinicAdmin.find(@admin_id).related_clinic_admins.ids
  73. end
  74.  
  75. def scope
  76. return @scope if @scope
  77.  
  78. @scope = ::Health::ProtocolSession.where(protocol_id: protocol_ids)
  79. @scope = @scope.includes(user: :admin_user_detail, protocol: :assessments)
  80. .includes(:status_trackings)
  81. .includes(reports: :test_scores)
  82. .includes(reports: :user_answers)
  83. .includes(reports: :batch)
  84.  
  85. @scope = @scope.where('health_protocol_sessions.created_at >= ?', @start_date) if @start_date
  86. @scope = @scope.where('health_protocol_sessions.created_at <= ?', @end_date) if @end_date
  87.  
  88. unless @include_incomplete_assessment_data
  89. @scope = @scope.joins(:reports).where.not(sessions: { id: nil }).distinct
  90. end
  91.  
  92. @scope
  93. end
  94.  
  95. def comparative_group(patient, date)
  96. details = patient.details
  97.  
  98. return nil if details&.age.nil? || details&.gender.nil?
  99.  
  100. age = details.age(date)
  101. gender = details.gender.pluralize
  102. data = ::Experiment::Healthcare.demographic_options(age, gender)
  103. "#{data[:gender]}, #{data[:age]}"
  104. end
  105.  
  106. def questionnaire_score(report, questionnaire)
  107. return if questionnaire.nil?
  108.  
  109. answers = report.user_answers.map do |answer|
  110. { question_position: answer.question.position, answer: answer.question_type_casted_value }
  111. end
  112.  
  113. calculation = Health::Questionnaire.calculation(
  114. questionnaire.questionnaire_type,
  115. { answers: answers, gender: report.admin_user.details.gender }
  116. ).to_h
  117.  
  118. calculation[:score]
  119. end
  120.  
  121. # rubocop:disable Metrics/CyclomaticComplexity.
  122. # rubocop:disable Metrics/PerceivedComplexity.
  123. def session_row(protocol_session)
  124. patient = protocol_session.user
  125. protocol = protocol_session.protocol
  126.  
  127. return [] if patient.nil? || protocol.nil?
  128.  
  129. status_trackings = protocol_session.status_trackings
  130. started_at = status_trackings.find_by(status_update: :session_started)&.created_at
  131. completed_at = status_trackings.find_by(status_update: :session_completed)&.created_at
  132.  
  133. row = [patient.client_id, patient.birthdate, comparative_group(patient, protocol_session.created_at)]
  134. row += [patient.owner&.dmail, protocol_session.created_by, protocol_session.created_at, started_at, completed_at]
  135. row += [protocol.name, "#{protocol_session.reports.count}/#{protocol.assessments.count}"]
  136.  
  137. session_questionnaires = {}
  138. protocol_session.reports.each do |report|
  139. questionnaire = report.batch.main_questionnaire
  140. next unless questionnaire
  141.  
  142. session_questionnaires[questionnaire.id] = questionnaire_score(report, questionnaire)
  143. end
  144.  
  145. questionnaires.each do |questionnaire_id, _name|
  146. row << (session_questionnaires[questionnaire_id] if session_questionnaires.key?(questionnaire_id))
  147. end
  148.  
  149. test_scores = protocol_session.reports.flat_map(&:test_scores)
  150. test_ids.each do |test_id|
  151. score = test_scores.find { |test_score| test_score.test_id == test_id }
  152.  
  153. row += if score
  154. score_data = score.calc_score_data
  155. [score_data[:raw], score_data[:standard], score_data[:percentile],
  156. score_data[:adjusted_raw], score_data[:adjusted_standard],
  157. score_data[:adjusted_percentile], (score.test_duration / 1000).round]
  158. else
  159. Array.new(7, '')
  160. end
  161. end
  162.  
  163. row
  164. end
  165. # rubocop:enable Metrics/CyclomaticComplexity.
  166. # rubocop:enable Metrics/PerceivedComplexity.
  167.  
  168. def generate_report
  169. CSV.open(tmp_file_name, 'w') do |csv|
  170. csv << csv_titles
  171.  
  172. clinic_admin_ids.each do |clinic_admin_id|
  173. clinic_admin = ::Health::ClinicAdmin.find(clinic_admin_id)
  174. clinic_name = clinic_admin.clinic_name
  175. clinic_protocols = ::Health::Protocol.where(owner_id: clinic_admin_id)
  176. clinic_scope = scope.where(protocol_id: clinic_protocols.ids)
  177.  
  178. p_bar = ProgressBar.new(clinic_scope.count)
  179. clinic_scope.find_each.with_index do |protocol_session, index|
  180. p_bar.increment!
  181. csv << ([clinic_admin_id, clinic_name] + session_row(protocol_session))
  182. csv.flush
  183. sleep(0.5) if (index % 50).zero?
  184. end
  185. end
  186. end
  187. end
  188.  
  189. def tmp_file_name
  190. @tmp_file_name ||= "tmp/#{UUID.generate}_aggregate_report.csv"
  191. end
  192.  
  193. def csv_file_name
  194. @csv_file_name ||= "aggregate_report_#{@admin_id}_#{Time.current.to_formatted_s(:number)}.csv"
  195. end
  196.  
  197. def delete_tmp_files
  198. FileUtils.rm_f(tmp_file_name)
  199. end
  200.  
  201. def csv_titles
  202. titles = ['Admin ID', 'Clinic Name', 'Patient ID', 'Date of Birth', 'Comparative Group', 'Provider/Practitioner',
  203. 'Administration Method', 'Time administered at', 'Session Start', 'Session Completed',
  204. 'Protocol Name', 'Assessments Completed']
  205.  
  206. questionnaires.each do |_questionnaire_id, questionnaire_name|
  207. titles << "#{questionnaire_name} Score"
  208. end
  209.  
  210. tests.each do |test|
  211. test_name = test.name
  212. titles += ["#{test_name} Raw", "#{test_name} standard", "#{test_name} percentile", "#{test_name} adjusted_raw",
  213. "#{test_name} adjusted_standard", "#{test_name} adjusted_percentile", "#{test_name} duration (time)"]
  214. end
  215.  
  216. titles
  217. end
  218. end
  219.  
  220. GenerateAggregateReportQwerty.new(admin_id: 866244)
  221.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement