earlymarket/CoPosition

View on GitHub
app/admin/device_distribution.rb

Summary

Maintainability
A
2 hrs
Test Coverage
ActiveAdmin.register_page "Device Distribution" do
  DEVICE_NUMBERS = [0, 1, 2, 3, 4, 5]
  DISTRIBUTION_TYPES = %i(full active).freeze
  DEVICE_DISTRIBUTION_HEADERS = %w[Devices Consumers Percent]

  menu parent: "Reports"

  content do
    render "index", layout: "active_admin"
  end

  controller do
    def index
      DISTRIBUTION_TYPES.each do |type|
        params[type] = public_send("#{type}_distribution")
      end
    end

    def full_distribution
      build_collection(full_device_distribution, User.active_users.count)
    end

    def active_distribution
      total = ActiveRecord::Base.connection.execute(
        "select distinct ds.id \
        from #{ItemsByMonthsQuery::ACTIVE_USERS_BY_MONTHS} ds \
        where EXTRACT(MONTH from ds.created_at) = EXTRACT(MONTH from now())"
      ).count

      build_collection(active_device_distribution, total)
    end

    private

    def build_collection(distribution, total)
      [].tap do |collection|
        DEVICE_NUMBERS.each do |number|
          distr = distribution.select{ |item| item["dev_count"] == number }.size
          collection << new_item(number, distr, total)
        end

        distr = distribution.select{ |item| item["dev_count"] > DEVICE_NUMBERS.last }.size
        collection << new_item("6+", distr, total)
      end
    end

    def new_item(number, distr, total)
      {
        devices: number,
        consumers: distr,
        percent: total.zero? ? "n/a" : "%.2f %" % (distr.to_f * 100 / total)
      }
    end

    def full_device_distribution
      ActiveRecord::Base.connection.execute(
        <<-DEV_DISTR
          select users.id, count(devices) dev_count
          from users
          left join devices on devices.user_id = users.id
          where (users.is_active = true)
          group by users.id
        DEV_DISTR
      )
    end

    def active_device_distribution
      ActiveRecord::Base.connection.execute(
        <<-DEV_DISTR
          select ds.id, count(devices) dev_count
          from #{ItemsByMonthsQuery::ACTIVE_USERS_BY_MONTHS} ds
          left join devices on devices.user_id = ds.id
          where EXTRACT(MONTH from ds.created_at) = EXTRACT(MONTH from now())
          group by ds.id
        DEV_DISTR
      )
    end
  end

  page_action :full_csv, method: :get do
    collection = full_distribution

    csv = CSV.generate(encoding: "UTF-8") do |csv|
      # add headers
      csv << HEADERS
      collection.each do |item|
        csv << [item[:devices], item[:consumers], item[:percent]]
      end
    end
    # send file to user
    send_data csv.encode("UTF-8"),
      type: "text/csv; charset=windows-1251; header=present",
      disposition: "attachment; filename=full_device_distribution_#{DateTime.now.to_s}.csv"
  end

  page_action :active_csv, method: :get do
    collection = active_distribution

    csv = CSV.generate(encoding: "UTF-8") do |csv|
      # add headers
      csv << HEADERS
      collection.each do |item|
        csv << [item[:devices], item[:consumers], item[:percent]]
      end
    end
    # send file to user
    send_data csv.encode("UTF-8"),
      type: "text/csv; charset=windows-1251; header=present",
      disposition: "attachment; filename=active_device_distribution_#{DateTime.now.to_s}.csv"
  end

  action_item :full_csv do
    link_to "All to CSV", admin_device_distribution_full_csv_path, method: :get
  end

  action_item :active_csv do
    link_to "Active to CSV", admin_device_distribution_active_csv_path, method: :get
  end
end