meurio/verdade-ou-consequencia

View on GitHub
app/models/user.rb

Summary

Maintainability
D
1 day
Test Coverage
class User < ActiveRecord::Base
  has_many :questions
  has_many :authorizations
  has_many :answers, :as => :responder

  belongs_to :candidate
  belongs_to :city
  
  validates_presence_of :email, :name, :city_id

  before_save :corrige_dados
  before_create :corrige_dados

  attr_accessible :candidate_id, :email, :name, :picture, :mobile_phone, :city_id

  def self.create_from_hash!(hash)
    user = User.new
    if hash['info']['email']
      user.email = hash['info']['email']
      user.email_validated = true
    else
      user.email = ''
      user.email_validated = false
    end
    user.name = "#{hash['info']['name']}"
    user.picture =hash['info']['image_url'] || hash['info']['image']
    user.save(:validate => false)
    user
  end

  def percent_care(qtde)
    qtde * 100 / answers.select{|a| a.weight > 0}.count
  end


  def matches
    ors = answers.select{|a| a.weight > 0}.map{|a| "ca.question_id = #{a.question_id}"}.join(" or ")
    ors = "1=1" if (ors == '')
    match_data = Candidate.
      select(
        %Q{
          (
            select
                count(*)
              from 
                answers ca 
              where 
                ca.responder_id = candidates.id and ca.responder_type='Candidate' and ca.short_answer = 'Sim' and 
                (#{ors})
          ) as score_eleitor
          ,(
            select
                count(*)
              from 
                answers ca 
              where 
                ca.responder_id = candidates.id and ca.responder_type='Candidate' and ca.short_answer = 'Sim'
          ) as score_direitos_humanos
          , candidates.nickname
          , candidates.id as id
          , (select u.score from parties_unions pu inner join unions u on pu.union_id = u.id where pu.party_id = candidates.party_id and u.city_id = candidates.city_id limit 1) as union_score
          , parties.score as party_score
          , (select count(*) from users us where us.candidate_id = candidates.id) as votos 
        }).
      joins(:party).
      where("candidates.finished_at is not null and candidates.city_id = #{self.city_id}").
      select { |dt| dt.score_direitos_humanos.to_i > 0 }

    match_data.map do |dt|
      {
        :id => dt.id.to_i,
        :score_final => dt.score_direitos_humanos.to_i * (dt.union_score ? dt.union_score.to_f : dt.party_score.to_f),
        :comp_score =>( dt.union_score ? dt.union_score.to_f : dt.party_score.to_f),
        :party_score => dt.party_score.to_f ,
        :score => dt.score_eleitor.to_i,
        :shuffler => Random.rand(1000)
      }
    end.sort { |a,b| 
      (ranking(a) != ranking(b) ) ? ranking(a) - ranking(b) : 
      (a[:shuffler] - b[:shuffler])
    }.reverse
  end


  def self.subscribe_all
    lista_segmentos = segment_list
    cidades = City.joins("inner join candidates on (candidates.city_id = cities.id) group by cities.id having count(*) > 1")

    usuarios = User.where("id not in (select id from candidates) and city_id is not null")
    usuarios.each{ |u|

        alvo = ''
        if u.candidate_id == nil
          if (cidades.select{|c| c.id == u.city_id}.count > 0 )
            alvo = :sem_candidato
          else
            alvo = :sem_candidato_na_cidade
          end
        elsif u.city.name == 'São Paulo' and u.city.state == 'SP'
          alvo = :sampa
        elsif u.city.name == 'Rio de Janeiro' and u.city.state == 'RJ'
          alvo = :rio
        elsif u.city.name == 'Porto Alegre' and u.city.state == 'RS'
          alvo = :poa
        elsif u.city.name == 'Recife' and u.city.state == 'PE'
          alvo = :recife
        else
          alvo = :brasil
        end

        e1_2 = u.email.strip.downcase
        merge_fields = nil
        if alvo == :sem_candidato or alvo == :sem_candidato_na_cidade
          merge_fields = {
            CIDADE: u.city ? "#{u.city.name}" : '',
            UF: u.city ? "#{u.city.state}" : '',
            FNAME: u.name,
            NOME: u.name
          }
        else
          merge_fields = {
            CIDADE: u.city ? "#{u.city.name}" : '',
            UF: u.city ? "#{u.city.state}" : '',
            FNAME: u.name,
            NOME: u.name,
            NOME_URNA: u.candidate.nickname,
            NUMERO: u.candidate.number,
            PARTIDO: u.candidate.party ? u.candidate.party.symbol : ''
          }
        end

        begin
          api_client.lists(list_id).members(Digest::MD5.hexdigest(e1_2)).upsert(body: {
              email_address: e1_2,
              status: :subscribed,
              merge_fields: merge_fields
            })
            api_client.lists(list_id).segments(lista_segmentos[alvo]).members.create body:{email_address: e1_2, status: :subscribed}
        rescue Exception => e
          logger.error(e)
        end
      }   
  end

  private

  def self.segment_list
    r = api_client.lists(list_id).segments.retrieve['segments']
    
    hash_segmentos = {
      sampa: insert_or_identify_segment(r, /^e_001/ , 'e_001 - Lista de eleitores COM CANDIDATO de SÃO PAULO'),
      rio: insert_or_identify_segment(r, /^e_002/ , 'e_002 - Lista de eleitores COM CANDIDATO de RIO DE JANEIRO'),
      poa: insert_or_identify_segment(r, /^e_003/ , 'e_003 - Lista de eleitores COM CANDIDATO de POA (PORTO ALEGRE)'),
      recife: insert_or_identify_segment(r, /^e_004/ , 'e_004 - Lista de eleitores COM CANDIDATO de RECIFE'),
      brasil: insert_or_identify_segment(r, /^e_005/ , 'e_005 - Lista de eleitores COM CANDIDATO de RESTANTE DO BRASIL'),
      sem_candidato: insert_or_identify_segment(r, /^e_006/ , 'e_006 - Lista de eleitores SEM CANDIDATO'),
      sem_candidato_na_cidade: insert_or_identify_segment(r, /^e_007/ , 'e_007 - Lista de eleitores SEM CANDIDATO NA CIDADE')
    }
  end

  def self.insert_or_identify_segment segmentos, match, titulo
    id = ''
    ss =  segmentos.select{|s| s['name'].match(match) }
    if ss.count == 0
      begin
        id = api_client.lists(list_id).segments.create(body: { name: titulo, static_segment: [] })['id']
      rescue Exception => e
        logger.error(e)
      end
    else
      id = ss[0]['id']
    end
    id
  end

  def self.api_client
    Gibbon::Request.new
  end

  def self.list_id
     # "845d564a12"
     # ENV['MAILCHIMP_LIST_ID']    
     "56203dedd8"
  end

  def corrige_dados
    self.mobile_phone.gsub! /\D/, '' if self.mobile_phone  != nil
  end

  def ranking( dt )
    (dt[:score_final] >= 9.8 ) ? 3 :
    (dt[:score_final] >= 5.6 ) ? 2 : 1
  end
end