petities/petitions.eu

View on GitHub
lib/tasks/petition.rake

Summary

Maintainability
Test Coverage
namespace :petition do
  desc 'Update signatures cache'
  task update_signatures_cache: :environment do
    Petition.find_each do |petition|
      UpdateSignaturesCacheJob.perform_later(petition)
    end
  end

  # Recalculate signature counter cache in Redis for live petitions. Remove the
  # counter cache for closed petitions.
  desc 'Update redis signature cache'
  task update_redis_signature_cache: :environment do
    Petition.find_each do |petition|
      UpdateRedisSignatureCacheJob.perform_later(petition)
    end
  end

  desc 'create redis signature counts'
  task set_redis_signature_counts: :environment do
    require 'benchmark'

    def delete_all
      r = Redis.new

      # delete old rankings
      r.del('petition_size')
      r.del('active_rate')

      # delete all petition related keys
      keys = r.keys('p*')
      puts "Delete old keys #{keys.size}"

      r.del(*keys) if keys.size > 0
    end

    #delete_all
    #
    Petition.live.find_each do |petition|

      count = petition.signatures.confirmed.count

      next if petition.name.blank?

      puts '%5s - %6s - %s' % [
        petition.id, count, petition.name]

      # general count
      RedisPetitionCounter.new(petition).update(count)
      # Main rankings
      redis = Redis.current
      redis.zrem('petition_size', petition.id)
      redis.zadd('petition_size', count, petition.id)

      # last hours activity rate
      puts
      puts Benchmark.measure {
        petition.create_hour_keys
      }

      # day barchart keys for graph
      puts
      puts Benchmark.measure {
        petition.delete_keys
        petition.create_raw_sql_barchart_keys
      }
      # call this only once!
      puts "Active rate: #{petition.update_active_rate!}"
    end
    # clear the cache
    Rails.cache.clear
  end

  desc 'Send warning of expiring due date'
  task send_warning_due_date: :environment do
    Rails.logger = ActiveSupport::Logger.new(
      'log/send_petition_due_date_warning.log'
    )

    almost_petitions = Petition.where('date_projected < ?', 7.days.from_now)
                               .where('date_projected > ?', 6.days.from_now)
                               .where(status: :live).limit(100)

    Rails.logger.debug("due date warnings #{almost_petitions.size}")

    almost_petitions.find_each do |petition|
      if almost_petitions.signatures.confirmed.size < 10
        PetitionMailer.due_next_week_warning_mail(petition).deliver_later
      end
    end
  end

  desc 'handle over due petitions'
  task handle_overdue_petitions: :environment do
    Rails.logger = ActiveSupport::Logger.new('log/clear_failed_petition.log')
    overdue_petitions = Petition.where('date_projected < ?', Time.now)
                                .where(status: :live).limit(100)

    overdue_petitions.find_each do |petition|
      if petition.signatures.size < 10
        Rails.logger.debug("withdrawn #{petition.id} #{petition.name}")
        petition.status = 'withdrawn'
      elsif petition.updates.size < 1
        # change status to orphan
        petition.status = 'orphan'
        Rails.logger.debug("orphaned #{petition.id} #{petition.name}")
      else
        Rails.logger.debug("request answer due date #{petition.id} #{petition.name}")
        # send request for answer due date to office
        # change status to to_process
        petition.status = 'to_process'
        PetitionMailer.ask_office_answer_due_date_mail(petition).deliver_later
      end
      petition.save
    end
  end

  desc 'help find new owners for orphan petitions'
  task find_new_owner: :environment do
    Rails.logger = ActiveSupport::Logger.new('log/find_new_owner.log')

    # find at most 100 orphans
    orphan_petitions = Petition
                       .where(status: :orphan).limit(100)

    orphan_petitions.each do |petition|
      task_status = TaskStatus.find_or_create_by(
        task_name: 'find_owner',
        petition_id: petition.id)

      if task_status.count
        # already launched a search before..
        if task_status.last_action < 7.days.ago
          # no owner found.
          petition.status = 'withdrawn'
          petition.save
          petition.email_answer(
            answer: t('petition.is.withdrawn', default: 'Petition is withdrawn'))
        end
        next
      end

      # find at most 100 candiates
      candidates = Pledge.where(petition_id: orphan.id)
                         .joins(:task_status)
                         .where(task_statuses: { inform_me: true }).limit(100)

      Rails.logger.debug(
        "found #{candidates.size} candidates for #{petition.name}"
      )

      # email each candiate to be admin
      candidates.each do |candidate|
        PetitionMailer.adoption_request_signatory_mail(petition, candidate.signature).deliver_later
      end
    end
  end

  desc 'Get reference number'
  task get_reference_number: :environment do
    Rails.logger = ActiveSupport::Logger.new('log/get_reference_number.log')

    missing_reference_number = Petition
                               .where('date_projected < ?', Time.now)
                               .where(reference_field: nil)
                               .where(status: :to_process).limit(110)

    Rails.logger.debug(missing_reference_number.size)

    missing_reference_number.each do |petition|
      # find task or create
      task_status = TaskStatus.find_or_create_by(
        task_name: 'get_reference_number',
        petition_id: petition.id)

      next unless task_status.should_execute?(7.days.ago, 3)
      PetitionMailer.reference_number_mail(petition).deliver_later
      Rails.logger.debug('sending reference mail.')
      task_status.count += 1
      task_status.save
      # save the current task status
    end
  end

  desc 'Get answer for petition from office'
  task get_answer_from_office: :environment do
    Rails.logger = ActiveSupport::Logger.new('log/get_answer.log')

    # find all petitions that not have an answer yet
    need_answers = Petition.where(status: 'in_process')
                           .where('date_projected < ?', Time.now)
                           .joins(:updates)
                           .where(newsitems: { show_on_petition: [nil, false] })
                           .limit(100)

    Rails.logger.debug(need_answers.size)

    need_answers.each do |petition|
      task_status = TaskStatus.find_or_create_by(
        task_name: 'get_answer',
        petition_id: petition.id)

      next unless task_status.should_execute(7.days.ago, 3)
      task_status.count += 1
      task_status.last_action = Time.now
      PetitionMailer.ask_office_for_answer_mail(petition).deliver_later
      Rails.logger.debug(
        'asked %s x %s for answer on %s' % [
          petition.office.name,
          task_status.count,
          petition.name])

      task_status.save
    end
  end

  desc 'publish news to subscribers'
  task publish_news_to_subscribers: :environment do
    Rails.logger = ActiveSupport::Logger.new('log/publish_news.log')

    has_news = Petition.where(status: 'live')
                       .joins(:updates)
                       .where('newsitems.created_at > ?', 1.day.ago).limit(10)

    has_news.each do |petition|
      publish_task = TaskStatus.find_or_create_by(
        task_name: 'publish_news',
        petition_id: petition.id)

      unless publish_task.should_execute?(2.days.ago, 3)
        # skip
        # publish_task.update(count: 0 ,last_action: 3.days.ago)
        # publish_task.save
        Rails.logger.debug('we only publish 3 times')
        Rails.logger.debug("and at most and once a day #{petition.name}")
        next
      end

      # find all people that want to be informed
      inform_me = Signature
                  .where(petition_id: petition.id)
                  .where(subscribe: true)

      message = "#{inform_me.size} people get newsupdate on #{petition.name}"
      Rails.logger.debug(message)
      publish_task.message = message

      # find the answer
      news_update = petition.updates.first

      # inform each pledged user of answer
      inform_me.find_each do |signature|
        SignatureMailer.inform_user_of_news_update_mail(
          signature, news_update
        ).deliver_later
      end
      # store progress
      publish_task.save
    end
  end

  desc 'publish answer to interested people'
  task publish_answer_to_subscribers: :environment do
    Rails.logger = ActiveSupport::Logger.new('log/publish_answer.log')

    # find all petitions with an answer and are not completed
    have_answer = Petition.where(status: 'in_process')
                          .where('answer_due_date < ?', Time.now)
                          .joins(:updates)
                          .where(newsitems: { show_on_petition: true })
                          .limit(10)

    # find users that want to know about the answer
    have_answer.find_each do |petition|
      publish_task = TaskStatus.find_or_create_by(
        task_name: 'publish_answer',
        petition_id: petition.id)

      unless publish_task.should_execute?(nil, 1)
        # skip
        Rails.logger.debug("we only publish once #{petition.name}")
        next
      end

      # find all people that want to be informed
      # inform_me = Pledge
      #             .where(petition_id: petition.id)
      #             .where(inform_me: true)

      message = "#{inform_me.size} people want answer on #{petition.name}"
      Rails.logger.debug(message)
      publish_task.message = message

      # find the answer
      answer = petition.updates.where(show_on_petition: true).first

      # inform each pledged user of answer
      inform_me.each do |pledge|
        SignatureMailer.inform_user_of_answer_mail(
          pledge.signature, answer
        ).deliver_later
      end

      # set petition status on completed
      petition.status = 'completed'
      Rails.logger.debug("completed publish #{petition.name}")
      petition.save
      publish_task.save
    end
  end

  desc 'update slugs from petition name'
  task update_slugs: :environment do
    Petition.find_each do |p|
      # NOTE maybe put true
      # Petition.should_generate_new_friendly_id?
      p.update(name: p.name) if p.slug.blank?
      puts p.friendly_id
    end
  end
end