git-svn-id: https://192.168.0.254/svn/Rodax.redmine_rodax_crm/trunk@4 ff88604e-da85-c949-a72f-fc3aa3ba3724
241 lines
10 KiB
Ruby
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
|