class Admins::UserStatisticQuery < ApplicationQuery include CustomSortable attr_reader :params sort_columns :study_challenge_count, :finish_challenge_count, :study_shixun_count, :finish_shixun_count, default_by: :finish_shixun_count, default_direction: :desc def initialize(params) @params = params end def call users = User.where(type: 'User').group(:id) users = users.joins(:user_extension).where(user_extensions: { school_id: params[:school_id] }) if params[:school_id].present? total = users.count.count # 根据排序字段进行查询 users = query_by_sort_column(users, params[:sort_by]) users = custom_sort(users, params[:sort_by], params[:sort_direction]) users = users.includes(user_extension: [:school, :department]) users = users.limit(page_size).offset(offset).to_a # 查询并组装其它数据 users = package_other_data(users) [total, users] end private def package_other_data(users) ids = users.map(&:id) study_myshixun = Myshixun.where(user_id: ids) finish_myshixun = Myshixun.where(user_id: ids, status: 1) study_challenge = Game.where(user_id: ids).where(status: [0, 1, 2]) finish_challenge = Game.where(user_id: ids).where(status: 2) if time_range.present? study_myshixun = study_myshixun.where(updated_at: time_range) finish_myshixun = finish_myshixun.where(updated_at: time_range) study_challenge = study_challenge.where(updated_at: time_range) finish_challenge = finish_challenge.where(updated_at: time_range) end study_myshixun_map = study_myshixun.reorder(nil).group(:user_id).count finish_myshixun_map = finish_myshixun.reorder(nil).group(:user_id).count study_challenge_map = study_challenge.reorder(nil).group(:user_id).count finish_challenge_map = finish_challenge.reorder(nil).group(:user_id).count evaluate_count_map = study_challenge.reorder(nil).group(:user_id).sum(:evaluate_count) cost_time_map = study_challenge.reorder(nil).group(:user_id).sum(:cost_time) users.each do |user| user._extra_data = { study_shixun_count: study_myshixun_map.fetch(user.id, 0), finish_shixun_count: finish_myshixun_map.fetch(user.id, 0), study_challenge_count: study_challenge_map.fetch(user.id, 0), finish_challenge_count: finish_challenge_map.fetch(user.id, 0), evaluate_count: evaluate_count_map.fetch(user.id, 0), cost_time: cost_time_map.fetch(user.id, 0), } end users end def query_by_sort_column(users, sort_by_column) base_query_column = 'users.*' case sort_by_column.to_s when 'study_shixun_count' then users = if time_range.present? users.joins("LEFT JOIN myshixuns ON myshixuns.user_id = users.id "\ "AND myshixuns.updated_at BETWEEN '#{time_range.min}' AND '#{time_range.max}'") else users.left_joins(:myshixuns) end users.select("#{base_query_column}, COUNT(*) study_shixun_count") when 'finish_shixun_count' then users = if time_range.present? users.joins("LEFT JOIN myshixuns ON myshixuns.user_id = users.id AND myshixuns.status = 1 AND "\ "myshixuns.updated_at BETWEEN '#{time_range.min}' AND '#{time_range.max}'") else users.joins('LEFT JOIN myshixuns ON myshixuns.user_id = users.id AND myshixuns.status = 1') end users.select("#{base_query_column}, COUNT(*) finish_shixun_count") when 'study_challenge_count' then users = if time_range.present? users.joins('LEFT JOIN myshixuns ON myshixuns.user_id = users.id') .joins("LEFT JOIN games ON games.myshixun_id = myshixuns.id "\ "AND games.status IN (0,1,2) AND games.updated_at BETWEEN '#{time_range.min}' AND '#{time_range.max}'") else users.joins('LEFT JOIN myshixuns ON myshixuns.user_id = users.id') .joins("LEFT JOIN games ON games.myshixun_id = myshixuns.id AND games.status IN (0,1,2)") end users.select("#{base_query_column}, COUNT(*) study_challenge_count") when 'finish_challenge_count' then users = if time_range.present? users#.joins('LEFT JOIN myshixuns ON myshixuns.user_id = users.id') .joins("LEFT JOIN games ON games.user_id = users.id "\ "AND games.status = 2 AND games.updated_at BETWEEN '#{time_range.min}' AND '#{time_range.max}'") else users#.joins('LEFT JOIN myshixuns ON myshixuns.user_id = users.id') .joins("LEFT JOIN games ON games.user_id = users.id AND games.status = 2") end users.select("#{base_query_column}, COUNT(*) finish_challenge_count") else users end end def time_range @_time_range ||= begin case params[:date] when 'weekly' then 1.weeks.ago..Time.now when 'monthly' then 1.months.ago..Time.now when 'quarterly' then 3.months.ago..Time.now when 'yearly' then 1.years.ago..Time.now else '' end end end def page_size params[:per_page].to_i.zero? ? 20 : params[:per_page].to_i end def offset (params[:page].to_i.zero? ? 0 : params[:page].to_i - 1) * page_size end end