app/models/campaign.rb in e9_crm-0.1.21 vs app/models/campaign.rb in e9_crm-0.1.22
- old
+ new
@@ -20,14 +20,10 @@
has_many :dated_costs, :as => :costable
# NOTE tracking cookie code changes with new visits
has_many :tracking_cookies, :foreign_key => :code, :primary_key => :code, :class_name => 'TrackingCookie'
- def self.default
- NoCampaign.first || NoCampaign.create
- end
-
validates :name, :presence => true,
:uniqueness => { :allow_blank => true, :case_sensitive => false }
validates :code, :presence => { :unless => lambda {|r| r.is_a?(NoCampaign) } },
:length => { :maximum => 32 },
@@ -37,14 +33,86 @@
validates :affiliate_fee, :numericality => true
validates :sales_fee, :numericality => true
scope :active, lambda {|val=true| where(:active => val) }
scope :inactive, lambda { active(false) }
- scope :of_group, lambda {|val| where(:campaign_group_id => val.to_param) }
+ scope :of_group, lambda {|val| joins(:campaign_group).where(:campaign_group_id => val.to_param) }
scope :typed, lambda { where(arel_table[:type].not_eq('NoCampaign')) }
scope :ordered, lambda { order(arel_table[:name].asc) }
+
+ scope :reports, lambda {|*args|
+ options = args.extract_options!
+ selects = <<-SQL.gsub(/\s+/, ' ')
+ campaigns.*,
+
+ SUM(IF(deals.status != 'lead',1,0)) deal_count,
+
+ COUNT(deals.id) lead_count,
+
+ SUM(IF(deals.status='won',1,0)) won_deal_count,
+ SUM(IF(deals.status='won',deals.value,0)) total_value,
+ AVG(IF(deals.status='won',deals.value,NULL)) average_value,
+
+ SUM(costs.total) total_cost,
+ SUM(costs.total) /
+ SUM(IF(deals.status='won',1,0)) average_cost,
+
+ rv.count repeat_visits,
+ nv.count new_visits,
+
+ FLOOR(AVG(
+ DATEDIFF(
+ deals.closed_at,
+ deals.created_at))) average_elapsed
+ SQL
+
+ select(selects)
+ .joins(
+ 'LEFT OUTER JOIN deals ' +
+ 'ON deals.campaign_id = campaigns.id ' +
+ "#{ 'AND ' + Deal.for_time_range_conditions(*args, options).to_sql if args.present?}")
+ .joins(
+ 'LEFT OUTER JOIN ( ' +
+ 'SELECT SUM(cost) total, costable_id dc_cid ' +
+ 'FROM dated_costs ' +
+ 'WHERE costable_type="Campaign" ' +
+ "#{ 'AND ' + DatedCost.for_time_range_conditions(*args, options).to_sql if args.present?}" +
+ ' GROUP BY dc_cid) costs ' +
+ 'ON costs.dc_cid = campaigns.id')
+ .joins(
+ 'LEFT OUTER JOIN ( ' +
+ 'SELECT COUNT(DISTINCT session) count, campaign_id nv_cid ' +
+ 'FROM page_views ' +
+ 'WHERE page_views.new_visit = 1 ' +
+ "#{ 'AND ' + PageView.for_time_range_conditions(*args, options).to_sql if args.present?}" +
+ ' GROUP BY nv_cid ) nv ' +
+ 'ON nv.nv_cid = campaigns.id')
+ .joins(
+ 'LEFT OUTER JOIN ( ' +
+ 'SELECT COUNT(DISTINCT session) count, campaign_id rv_cid ' +
+ 'FROM page_views ' +
+ 'WHERE page_views.new_visit = 0 ' +
+ "#{ 'AND ' + PageView.for_time_range_conditions(*args, options).to_sql if args.present?}" +
+ ' GROUP BY rv_cid ) rv ' +
+ 'ON rv.rv_cid = campaigns.id')
+ .group('campaigns.id')
+ }
+
+ def self.default
+ NoCampaign.first || NoCampaign.create
+ end
+
+ # money column definitions for pseudo attributes (added on the reports scope)
+ %w(total_value average_value total_cost average_cost).each do |money_column|
+ class_eval("def #{money_column}; (r = read_attribute(:#{money_column})) && Money.new(r) end")
+ end
+
+ %w(new_visits repeat_visits).each do |count_column|
+ class_eval("def #{count_column}; (r = read_attribute(:#{count_column})) || 0 end")
+ end
+
def new_visit_session_count
page_views.new_visits.group(:session).count.keys.length
end
def new_visit_page_view_count
@@ -53,10 +121,10 @@
def repeat_visit_session_count
page_views.repeat_visits.group(:session).count.keys.length
end
- def repeat_visit_session_count
+ def repeat_visit_page_view_count
page_views.repeat_visits.group(:session).count.values.sum
end
##
# The sum cost of this campaign