# rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Style/Documentation # frozen_string_literal: true require 'parallel' module MalawiHivProgramReports module Pepfar class TxCurrMmd include Utils include MalawiHivProgramReports::Utils::CommonSqlQueryUtils include MalawiHivProgramReports::Adapters::Moh::Custom attr_accessor :report, :start_date, :end_date, :org, :location def initialize(start_date:, end_date:, **kwargs) @start_date = start_date.to_date.strftime('%Y-%m-%d 00:00:00') @end_date = end_date.to_date.strftime('%Y-%m-%d 23:59:59') @org = kwargs[:definition] @location = kwargs[:location] raise 'Location is required' if @location.blank? @report = init_report end def find_report process_data flatten_the_report rescue StandardError => e Rails.logger.error e.message Rails.logger.error e.backtrace.join("\n") raise e end private GENDER = %w[Male Female Unknown].freeze def init_report pepfar_age_groups.each_with_object({}) do |age_group, report| report[age_group] = GENDER.each_with_object({}) do |gender, age_group_report| age_group_report[gender] = { less_than_three_months: [], three_to_five_months: [], greater_than_six_months: [] } end end end def process_age_group_report(age_group, gender, age_group_report) { age_group:, gender:, less_than_three_months: age_group_report[:less_than_three_months], three_to_five_months: age_group_report[:three_to_five_months], greater_than_six_months: age_group_report[:greater_than_six_months] } end def flatten_the_report result = [] report.each do |age_group, age_group_report| age_group_report.each_key do |gender| result << process_age_group_report(age_group, gender, age_group_report[gender]) end end new_group = pepfar_age_groups.map { |age_group| age_group } new_group << 'All' gender_scores = { 'Female' => 0, 'Male' => 1, 'FNP' => 3, 'FP' => 2, 'FBf' => 4 } result_scores = result.sort_by do |item| gender_score = gender_scores[item[:gender]] || 999 age_group_score = new_group.index(item[:age_group]) || 999 [gender_score, age_group_score] end # remove all unknown age groups result_scores.reject { |item| item[:age_group].match?(/unknown/i) } end def process_data patients = ActiveRecord::Base.connection.select_all <<~SQL SELECT tesd.patient_id, CASE tesd.gender WHEN 'M' THEN 'Male' WHEN 'F' THEN 'Female' ELSE 'Unknown' END gender, disaggregated_age_group(tesd.birthdate, '#{end_date}') age_group, TIMESTAMPDIFF(DAY, tcm.start_date, tcm.auto_expire_date) prescribed_days FROM cdr_temp_cohort_members #{current_partition} tesd#{' '} INNER JOIN cdr_temp_patient_outcomes #{current_partition} tpo ON tpo.patient_id = tesd.patient_id AND tpo.cum_outcome = 'On antiretrovirals' INNER JOIN cdr_temp_min_auto_expire_date #{current_partition} tcm ON tcm.patient_id = tesd.patient_id WHERE tesd.date_enrolled <= '#{end_date}' SQL return report if patients.blank? patients.each do |patient| prescribe_days = patient['prescribed_days'].to_i age_group = patient['age_group'] gender = patient['gender'] indicator = if prescribe_days < 90 'less_than_three_months' elsif prescribe_days >= 90 && prescribe_days <= 150 'three_to_five_months' elsif prescribe_days > 150 'greater_than_six_months' end report[age_group][gender][indicator.to_sym] << patient['patient_id'] end report end end end end # rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Style/Documentation