kodgemisi/confdeck

View on GitHub
app/models/conference.rb

Summary

Maintainability
A
0 mins
Test Coverage
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

class Conference < ActiveRecord::Base
  extend FriendlyId
  friendly_id :name, use: :slugged

  has_attached_file :logo, :styles => { :medium => "400x400>", :thumb => "200x100>" }, :default_url => "/assets/missing_:style.png"
  has_attached_file :heading_image, :styles => { :default => "1900x254", :thumb => "200x100"}, :default_url => "/assets/heading_missing_:style.png"

  MODULES = %w{ application sponsors map organizators speakers schedule }

  #== Callbacks
  after_save :create_days_and_slot
  before_validation :set_dates
  before_save :set_default_settings
  after_create :set_virtual_dates

  #== Virtual Attributes
  attr_accessor :from_date
  attr_accessor :to_date
  attr_accessor :start_time
  attr_accessor :end_time

  serialize :settings

  #== Relations
  has_one :address
  has_and_belongs_to_many :organizations
  has_many :conference_roles
  has_many :users, through: :conference_roles
  has_many :conference_admins, -> { where(conference_roles: {role: ConferenceRole.roles[:confadmin] }) },
           :through => :conference_roles,
           :source => :user
  has_many :conference_users, -> { where(conference_roles: {role: ConferenceRole.roles[:confuser] }) },
           :through => :conference_roles,
           :source => :user

  has_and_belongs_to_many :days, -> { order 'date ASC' }
  has_many :sponsors
  has_many :rooms
  has_many :slots
  has_many :speeches
  has_many :activities
  #FIXME old one is
  #has_many :waiting_speeches, class_name: "Speech", conditions: {:state => "waiting_review"}
  has_many :waiting_speeches, class_name: "Speech"
  #FIXME old one is
  #has_many :accepted_speeches, class_name: "Speech", conditions: {:state => "accepted"}
  has_many :accepted_speeches, class_name: "Speech"
  has_many :speech_types
  has_many :topics, through: :speeches
  has_many :email_templates
  has_many :speakers, through: :topics do
    def accepted
      where("speeches.state = ?", "accepted")
    end
  end

  #== Nested Attributes
  accepts_nested_attributes_for :sponsors
  accepts_nested_attributes_for :address
  accepts_nested_attributes_for :organizations
  accepts_nested_attributes_for :days
  accepts_nested_attributes_for :email_templates
  accepts_nested_attributes_for :speech_types, :reject_if => :all_blank, :allow_destroy => true
  accepts_nested_attributes_for :users
  accepts_nested_attributes_for :conference_roles, allow_destroy: :true
  accepts_nested_attributes_for :conference_admins, allow_destroy: :true
  accepts_nested_attributes_for :conference_users, allow_destroy: :true

  #== Validations
  validates_attachment_content_type :logo, :content_type => /\Aimage\/.*\Z/
  validates_attachment_content_type :heading_image, :content_type => /\Aimage\/.*\Z/
  validates_presence_of :name, :slug, :summary, :organizations, :email, :from_date, :to_date
  validates_uniqueness_of :slug
  validates_format_of :start_time, :with => /([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]/, :if => :one_day?
  validates_format_of :end_time, :with => /([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]/, :if => :one_day?
  validate :check_date_formats, if: "to_date.present? && from_date.present? "
  validate :check_date_interval, if: "to_date.present? && from_date.present?"


  def should_generate_new_friendly_id?
    name_changed?
  end

  def generate_slug_preview
    set_slug
  end

  def create_days_and_slot
    #FIXME should be refactored
    if (self.from_date && self.to_date)
      self.days.destroy_all
    end

    self.create_days(self.from_date, self.to_date)

    if one_day?
      create_one_day_slot!
    end
  end

  def create_days(from_date, to_date)
    _from_date = DateTime.strptime(from_date, I18n.t("date.formats.default"))
    _to_date = DateTime.strptime(to_date, I18n.t("date.formats.default"))

    current_date = _from_date
    begin
      day = Day.where(date: current_date.to_date).first_or_create
      self.days << day
      current_date = current_date.next_day
    end while current_date != _to_date.next_day
  end

  def one_day?
    (self.from_date == self.to_date)
  end

  def create_one_day_slot!
    self.slots.destroy_all #FIXME might be need to removed
    slot = self.slots.build
    slot.day = self.days.first

    from_date = slot.day.date
    start_time = Time.parse(self.start_time)
    end_time = Time.parse(self.end_time)
    slot.start_time = (from_date + start_time.seconds_since_midnight.seconds).to_datetime
    slot.end_time = (from_date + end_time.seconds_since_midnight.seconds).to_datetime
    slot.save
  end

  def unassigned_topics
    self.speeches.accepted.map {|a| a unless self.slots.pluck(:topic_id).include? a.topic_id }.reject { |a| a.nil? }
  end

  def module_enabled?(module_name)
    (self.settings["#{module_name}_module"] == "true")
  end

  def set!(key, val)
    self.settings ||= {}
    self.settings[key] = val
  end

  def get(key)
    self.settings[key]
  end

  def to_liquid
    liquid_vars = {
        'name' => name,
        'summary' => summary,
        'description' => description,
        'twitter' => twitter,
        'facebook' => facebook,
        'website' => website,
        'logo_path' => logo.url,
        'email' => email,
        'phone' => phone,
        'organizations' => organizations
    }

    liquid_vars[:organization] = organizations.first if organizations.count == 1
    liquid_vars
  end

  def start_date
    self.days.first.date
  end

  def end_date
    self.days.last.date
  end

  def accept_application?
    self.application_end == nil || DateTime.now < self.application_end
  end

  private

  def set_dates
    if self.from_date.nil? && self.to_date.nil?
      self.from_date = self.days.first.try(:formatted)
      self.to_date = self.days.last.try(:formatted)
    end
  end

  # Checks from_date and to_date formats and converts String to Date type
  # Also checks 60 days time range validation
  def check_date_formats
    begin
      DateTime.strptime(self.from_date, I18n.t("date.formats.default"))
    rescue
      self.errors.add(:from_date, "invalid");
      #return false
    end

    begin
      DateTime.strptime(self.to_date, I18n.t("date.formats.default"))
    rescue
      self.errors.add(:to_date, "invalid");
    end
  end

  def check_date_interval
    _from_date = DateTime.strptime(self.from_date, I18n.t("date.formats.default"))
    _to_date = DateTime.strptime(self.to_date, I18n.t("date.formats.default"))

    if (_to_date < _from_date)
      self.errors.add(:to_date, "must be after from date")
    end

  end

  def set_virtual_dates
    set_dates
  end

  def set_default_settings
    if self.settings.nil?
      _settings = {}
      Conference::MODULES.each do |m|
        _settings["#{m}_module"] = "true".to_s
      end
      _settings["conference_site"] = "true"
      self.settings = _settings
    end
  end


end