This repository has been archived on 2024-12-01. You can view files and clone it, but cannot push or open issues or pull requests.
redmine_rodax_crm/app/models/contact.rb
2012-01-03 21:11:44 +00:00

241 lines
10 KiB
Ruby

class Contact < ActiveRecord::Base
unloadable
CONTACT_FORMATS = {
:lastname_firstname_middlename => '#{last_name} #{first_name} #{middle_name}',
:firstname_middlename_lastname => '#{first_name} #{middle_name} #{last_name}',
:firstname_lastname => '#{first_name} #{last_name}',
:lastname_coma_firstname => '#{last_name}, #{first_name}'
}
has_many :notes, :as => :source, :class_name => 'ContactNote', :dependent => :delete_all, :order => "created_on DESC"
belongs_to :assigned_to, :class_name => 'User', :foreign_key => 'assigned_to_id'
has_and_belongs_to_many :issues, :order => "#{Issue.table_name}.due_date", :uniq => true
has_many :deals, :order => "#{Deal.table_name}.status_id", :uniq => true
has_many :contracts, :order => "#{Contract.table_name}.status_id", :uniq => true
has_and_belongs_to_many :related_deals, :class_name => 'Deal', :order => "#{Deal.table_name}.status_id", :uniq => true
has_and_belongs_to_many :related_contracts, :class_name => 'Contract', :order => "#{Contract.table_name}.status_id", :uniq => true
has_and_belongs_to_many :projects, :uniq => true
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
has_one :avatar, :class_name => "Attachment", :as => :container, :conditions => "#{Attachment.table_name}.description = 'avatar'", :dependent => :destroy
attr_accessor :phones
attr_accessor :emails
acts_as_customizable
acts_as_viewable
acts_as_taggable
acts_as_watchable
acts_as_attachable :view_permission => :view_contacts,
:delete_permission => :edit_contacts
acts_as_event :datetime => :created_on,
:url => Proc.new {|o| {:controller => 'contacts', :action => 'show', :id => o}},
:type => 'icon-user',
:title => Proc.new {|o| o.name },
:description => Proc.new {|o| [o.info, o.company, o.email, o.address, o.background].join(' ') }
acts_as_searchable :columns => ["#{table_name}.first_name",
"#{table_name}.middle_name",
"#{table_name}.last_name",
"#{table_name}.company",
"#{table_name}.address",
"#{table_name}.background"],
:project_key => "#{Project.table_name}.id",
:include => [:projects],
# sort by id so that limited eager loading doesn't break with postgresql
:order_column => "#{table_name}.id"
named_scope :visible, lambda {|*args| { :include => :projects,
:conditions => Contact.allowed_to_condition(args.first || User.current, :view_contacts) }}
named_scope :deletable, lambda {|*args| { :include => :projects,
:conditions => Project.allowed_to_condition(args.first || User.current, :delete_contacts) }}
named_scope :editable, lambda {|*args| { :include => :projects,
:conditions => Project.allowed_to_condition(args.first || User.current, :edit_contacts) }}
named_scope :in_project, lambda {|*args| { :include => :projects, :conditions => ["#{Project.table_name}.id = ?", args.first]}}
named_scope :like_by, lambda {|field, search| {:conditions => ["#{Contact.table_name}.#{field} LIKE ?", search + "%"] }}
named_scope :live_search, lambda {|search| {:conditions => ["(#{Contact.table_name}.first_name LIKE ? or
#{Contact.table_name}.last_name LIKE ? or
#{Contact.table_name}.middle_name LIKE ? or
#{Contact.table_name}.company LIKE ? or
#{Contact.table_name}.job_title LIKE ?)",
"%" + search + "%",
"%" + search + "%",
"%" + search + "%",
"%" + search + "%",
"%" + search + "%"] }}
named_scope :order_by_name, :order => "#{Contact.table_name}.last_name, #{Contact.table_name}.first_name"
named_scope :order_by_creation, :order => "#{Contact.table_name}.created_on DESC"
# name or company is mandatory
validates_presence_of :first_name
validates_uniqueness_of :first_name, :scope => [:last_name, :middle_name, :company]
validates_associated :projects
def self.allowed_to_condition(user, permission, options={})
Project.allowed_to_condition(user, permission)
end
def all_deals
@all_deals ||= (self.deals + self.related_deals ).uniq.sort!{|x, y| x.status_id <=> y.status_id }
end
def all_contracts
@all_contracts ||= (self.contracts + self.related_contracts ).uniq.sort!{|x, y| x.status_id <=> y.status_id }
end
def all_visible_deals(usr=User.current)
@all_deals ||= (self.deals.visible(usr) + self.related_deals.visible(usr)).uniq.sort!{|x, y| x.status_id <=> y.status_id }
end
def all_visible_contracts(usr=User.current)
@all_contracts ||= (self.contracts.visible(usr) + self.related_contracts.visible(usr)).uniq.sort!{|x, y| x.status_id <=> y.status_id }
end
def self.available_tags(options = {})
name_like = options[:name_like]
limit = options[:limit]
options = {}
if name_like
options[:conditions] = ["#{ActsAsTaggableOn::Tag.table_name}.name LIKE ?", "%#{name_like.downcase}%"]
end
options[:limit] = limit if limit
self.all_tag_counts(options)
end
def duplicates(limit=5)
scope = Contact.scoped({})
scope = scope.like_by("first_name", self.first_name.strip) if !self.first_name.blank?
scope = scope.like_by("middle_name", self.middle_name.strip) if !self.middle_name.blank?
scope = scope.like_by("last_name", self.last_name.strip) if !self.last_name.blank?
scope = scope.scoped(:conditions => ["#{Contact.table_name}.id <> ?", self.id]) if !self.new_record?
@duplicates ||= (self.first_name.blank? && self.last_name.blank? && self.middle_name.blank?) ? [] : scope.visible.find(:all, :limit => limit)
end
def employees
@employees ||= Contact.order_by_name.find(:all, :conditions => ["#{Contact.table_name}.company = ? AND #{Contact.table_name}.id <> ?", self.first_name, self.id])
end
def redmine_user
@redmine_user ||= User.find(:first, :conditions => {:mail => emails}) unless self.email.blank?
end
def contact_company
@contact_company ||= Contact.find_by_first_name(self.company)
end
def notes_attachments
@contact_attachments ||= Attachment.find(:all,
:conditions => { :container_type => "Note", :container_id => self.notes.map(&:id)},
:order => "created_on DESC")
end
# usr for mailer
def visible?(usr=nil)
usr ||= User.current
@visible ||= 0 < self.projects.visible(usr).count(:conditions => Project.allowed_to_condition(usr, :view_contacts))
end
def editable?(usr=nil)
usr ||= User.current
@editable ||= 0 < self.projects.visible(usr).count(:conditions => Project.allowed_to_condition(usr, :edit_contacts))
end
def deletable?(usr=nil)
usr ||= User.current
@deletable ||= 0 < self.projects.visible(usr).count(:conditions => Project.allowed_to_condition(usr, :delete_contacts))
end
def send_mail_allowed?(usr=nil)
usr ||= User.current
@send_mail_allowed ||= 0 < self.projects.visible(usr).count(:conditions => Project.allowed_to_condition(usr, :send_contacts_mail))
end
def self.projects_joins
joins = []
joins << ["JOIN contacts_projects ON contacts_projects.contact_id = #{self.table_name}.id"]
joins << ["JOIN #{Project.table_name} ON contacts_projects.project_id = #{Project.table_name}.id"]
end
def project(current_project=nil)
return @project if @project
if current_project && self.projects.visible.include?(current_project)
@project = current_project
else
@project = self.projects.visible.find(:first, :conditions => Project.allowed_to_condition(User.current, :view_contacts))
end
@project ||= self.projects.first
end
def self.find_by_emails(emails)
contact = nil
cond = "(1 = 0)"
emails.each do |mail|
cond << " OR (#{Contact.table_name}.email LIKE '%#{mail.downcase}%')"
end
Contact.find(:all, :conditions => cond)
end
def name(formatter=nil)
if !self.is_company
if formatter
eval('"' + (CONTACT_FORMATS[formatter] || CONTACT_FORMATS[:firstname_lastname]) + '"')
else
@name ||= eval('"' + (Setting.plugin_contacts[:name_format] && CONTACT_FORMATS[Setting.plugin_contacts[:name_format].to_sym] || CONTACT_FORMATS[:firstname_lastname]) + '"')
end
# [self.last_name, self.first_name, self.middle_name].each {|field| result << field unless field.blank?}
else
self.first_name
end
end
def info
self.job_title
end
def phones
@phones || self.phone ? self.phone.split( /, */) : []
end
def emails
@emails || self.email ? self.email.split( /, */).map{|m| m.strip} : []
end
def age
return nil if birthday.blank?
now = Time.now
# how many years?
# has their birthday occured this year yet?
# subtract 1 if so, 0 if not
age = now.year - birthday.year - (birthday.to_time.change(:year => now.year) > now ? 1 : 0)
end
def website_address
self.website.match("^https?://") ? self.website : self.website.gsub(/^/, "http://") unless self.website.blank?
end
private
def assign_phone
if @phones
self.phone = @phones.uniq.map {|s| s.strip.delete(',').squeeze(" ")}.join(', ')
end
end
end