sharetribe/sharetribe

View on GitHub
app/services/admin/communities/membership_service.rb

Summary

Maintainability
D
2 days
Test Coverage
class Admin::Communities::MembershipService
  attr_reader :community, :params, :current_user, :error_message

  PER_PAGE = 50

  def initialize(community:, params:, current_user:)
    @params = params
    @community = community
    @current_user = current_user
    @error_message = nil
  end

  def memberships
    @memberships ||= filtered_scope.not_deleted_user
                                   .paginate(page: params[:page], per_page: PER_PAGE)
                                   .order("#{sort_column} #{sort_direction}")
  end

  def memberships_csv
    Enumerator.new do |yielder|
      generate_csv_for(yielder)
    end
  end

  def membership
    @membership ||= resource_scope.find_by(id: params[:id])
  end

  def membership_current_user?
    membership.person == current_user
  end

  def ban
    membership.update(status: "banned")
    membership.update(admin: 0) if membership.admin == 1
    community.close_listings_by_author(membership.person)
    membership
  end

  def unban
    membership.update(status: "accepted")
    membership
  end

  def removes_itself?
    ids = params[:remove_admin] || []
    ids.include?(current_user.id) && current_user.is_marketplace_admin?(community)
  end

  def promote_admin
    resource_scope.where(person_id: params[:add_admin]).update_all("admin = 1")
    resource_scope.where(person_id: params[:remove_admin]).update_all("admin = 0")
  end

  def posting_allowed
    resource_scope.where(person_id: params[:allowed_to_post]).update_all("can_post_listings = 1")
    resource_scope.where(person_id: params[:disallowed_to_post]).update_all("can_post_listings = 0")
  end

  def resend_confirmation
    email_to_confirm = membership.person.latest_pending_email_address(community)
    to_confirm = Email.find_by_address_and_community_id(email_to_confirm, community.id)
    Email.send_confirmation(to_confirm, community)
  end

  def destroy
    person = membership.person
    unless membership.banned? || membership.pending_consent? || membership.pending_email_confirmation?
      @error_message = I18n.t('admin.communities.manage_members.only_delete_disabled')
      return false
    end
    has_unfinished = Transaction.unfinished_for_person(person).any?
    if has_unfinished
      @error_message = I18n.t('admin.communities.manage_members.have_ongoing_transactions')
      return false
    end
    only_admin = community.is_person_only_admin(person)
    return false if only_admin

    stripe_del = StripeService::API::Api.accounts.delete_seller_account(community_id: community.id,
                                                                        person_id: person.id)
    unless stripe_del[:success]
      display_name = person.display_name.present? ? " (#{person.display_name})" : ''
      person_name = "#{person.given_name} #{person.family_name}#{display_name}"
      @error_message = I18n.t("layouts.notifications.stripe_balance_for_username_is_not_0", username: person_name)
      return false
    end
    ActiveRecord::Base.transaction do
      Person.delete_user(person.id)
      Listing.delete_by_author(person.id)
      PaypalAccount.where(person_id: person.id, community_id: person.community_id).delete_all
      Invitation.where(community: person.community, inviter: person).update_all(deleted: true)
    end
  end

  private

  def all_memberships
    resource_scope.not_deleted_user.includes(
      person: [:emails, :location, :stripe_account,
               {paypal_account: [:order_permission, :billing_agreement] }])
  end

  def generate_csv_for(yielder)
    # first line is column names
    header_row = %w{
      user_id
      first_name
      last_name
      display_name
      username
      phone_number
      address
      email_address
      email_address_confirmed
      joined_at
      status
      is_admin
      accept_emails_from_admin
      language
    }
    header_row.push("can_post_listings") if community.require_verification_to_post_listings
    header_row += %w{has_connected_paypal has_connected_stripe}
    header_row += community.person_custom_fields.map{|f| f.name}
    yielder << header_row.to_csv(force_quotes: true)
    all_memberships.find_each do |membership|
      user = membership.person
      unless user.blank?
        user_data = {
          id: user.id,
          first_name: user.given_name,
          last_name: user.family_name,
          display_name: user.display_name,
          username: user.username,
          phone_number: user.phone_number,
          address: user.location ? user.location.address : "",
          email_address: nil,
          email_address_confirmed: nil,
          joined_at: membership.created_at && I18n.l(membership.created_at, format: '%Y-%m-%d %H:%M:%S'),
          status: membership.status,
          is_admin: membership.admin,
          accept_emails_from_admin: nil,
          language: user.locale
        }
        user_data[:can_post_listings] = membership.can_post_listings if community.require_verification_to_post_listings
        paypal_account = paypal_accounts_api.get(community_id: community.id, person_id: user.id).data || {}
        stripe_account = stripe_accounts_api.get(community_id: community.id, person_id: user.id).data || {}
        user_data[:has_connected_paypal] = paypal_account[:state] == :verified
        user_data[:has_connected_stripe] = stripe_account[:stripe_seller_id].present? && stripe_account[:stripe_bank_id].present?
        community.person_custom_fields.each do |field|
          field_value = user.custom_field_values.by_question(field).first
          user_data[field.name] = field_value.try(:display_value)
        end
        user.emails.each do |email|
          accept_emails_from_admin = user.preferences["email_from_admins"] && email.send_notifications
          data = user_data.clone
          data[:email_address] = email.address
          data[:email_address_confirmed] = !!email.confirmed_at
          data[:accept_emails_from_admin] = !!accept_emails_from_admin
          yielder << data.values.to_csv(force_quotes: true)
        end
      end
    end
  end

  def sort_column
    case params[:sort]
    when "name"
      "people.given_name"
    when "display_name"
      "people.display_name"
    when "email"
      "emails.address"
    when "join_date"
      "created_at"
    when "posting_allowed"
      "can_post_listings"
    else
      "created_at"
    end
  end

  def sort_direction
    if params[:direction] == "asc"
      "asc"
    else
      "desc" #default
    end
  end

  def resource_scope
    community.community_memberships
  end

  def filtered_scope
    scope = resource_scope.includes(person: :emails)
    if params[:q].present?
      person_ids = Person
        .search_name_or_email(community.id, "%#{params[:q]}%")
        .select('people.id')

      scope = scope.where(person_id: person_ids)
    end
    if params[:status].present? && params[:status].is_a?(Array)
      statuses = []
      statuses.push(CommunityMembership.admin) if params[:status].include?('admin')
      statuses.push(CommunityMembership.banned) if params[:status].include?(CommunityMembership::BANNED)
      statuses.push(CommunityMembership.posting_allowed) if params[:status].include?('posting_allowed')
      statuses.push(CommunityMembership.accepted) if params[:status].include?(CommunityMembership::ACCEPTED)
      statuses.push(CommunityMembership.pending_email_confirmation) if params[:status].include?('unconfirmed')
      statuses.push(CommunityMembership.pending_consent) if params[:status].include?('pending')
      if statuses.size > 1
        status_scope = statuses.slice!(0)
        statuses.map{|x| status_scope = status_scope.or(x)}
        scope = scope.merge(status_scope)
      elsif statuses.size == 1
        scope = scope.merge(statuses.first)
      end
    end
    scope
  end

  def paypal_accounts_api
    PaypalService::API::Api.accounts
  end

  def stripe_accounts_api
    StripeService::API::Api.accounts
  end

end