Class: Report::CampaignsReport::CampaignsReport

Inherits:
Object
  • Object
show all
Defined in:
app/services/report/campaigns_report/campaigns_report.rb

Overview

Service object: campaigns report.

Defined Under Namespace

Classes: Result

Class Method Summary collapse

Class Method Details

.campaigns_revenue(start_date, end_date, campaign_ids, list_months) ⇒ Object

Campaigns revenue.

Parameters:

  • start_date (Date)
  • end_date (Date)
  • campaign_ids (Array<Integer>)
  • list_months (Object)

Returns:

  • (Object)


117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'app/services/report/campaigns_report/campaigns_report.rb', line 117

def self.campaigns_revenue(start_date, end_date, campaign_ids, list_months)
  prev_start_date = start_date.years_ago(1)
  prev_end_date = end_date.years_ago(1)

  if campaign_ids.one?
    campaign_ids_sql = campaign_ids.empty? ? ' ' : " and coalesce(c.id,c2.id) = #{campaign_ids.first.to_i} "
    sql = <<-SQL.squish
      select coalesce(c.id,c2.id) as campaign_id,coalesce(c.name,c2.name) as campaign_name,
            sum(case when gl_date between '#{start_date}' and '#{end_date}' then quantity * discounted_price * consolidated_exchange_rate else 0 end) as cur_sales_amount,
            sum(case when gl_date between '#{prev_start_date}' and '#{prev_end_date}' then quantity * discounted_price * consolidated_exchange_rate else 0 end) as prev_sales_amount,
            dt.month
      from view_sales_facts vsf
      inner join analytic_date_time_dimensions dt on vsf.gl_date = dt.date
      left join campaigns c on vsf.source_id = c.source_id and c.state = 'active'
      left join campaigns c2 on vsf.source_parent_id = c2.source_id and c2.state = 'active'
      where coalesce(c.name,c2.name) is not null
      and (gl_date between '#{prev_start_date}' and '#{prev_end_date}' or gl_date between '#{start_date}' and '#{end_date}')
      #{campaign_ids_sql}
      group by coalesce(c.id,c2.id),coalesce(c.name,c2.name),dt.month
    SQL
  else
    campaign_ids_sql = campaign_ids.empty? ? ' ' : " and coalesce(c.id,c2.id) in (#{campaign_ids.map(&:to_i).join(',')}) "
    sql = <<-SQL.squish
      select coalesce(c.id,c2.id) as campaign_id,coalesce(c.name,c2.name) as campaign_name,sum(quantity * discounted_price * consolidated_exchange_rate) as cur_sales_amount,dt.month
      from view_sales_facts vsf
      inner join analytic_date_time_dimensions dt on vsf.gl_date = dt.date
      left join campaigns c on vsf.source_id = c.source_id and c.state = 'active'
      left join campaigns c2 on vsf.source_parent_id = c2.source_id and c2.state = 'active'
      where coalesce(c.name,c2.name) is not null
      and gl_date between '#{start_date}' and '#{end_date}'
      #{campaign_ids_sql}
      group by coalesce(c.id,c2.id),coalesce(c.name,c2.name),dt.month
    SQL
  end

  results = ActiveRecord::Base.lease_connection.execute(sql).to_a.map(&:symbolize_keys)

  campaign_sales = []
  if results.present?
    list_campaigns = results.pluck(:campaign_name).compact.uniq
    list_campaigns.each do |c|
      monthly_sales = []
      prev_monthly_sales = []
      list_months.each do |m|
        sales = 0
        prev_sales = 0
        results.map { |r| sales += r[:cur_sales_amount] if c == r[:campaign_name] && m == r[:month] }
        results.map { |r| prev_sales += r[:prev_sales_amount] if c == r[:campaign_name] && m == r[:month] } if campaign_ids.one?
        monthly_sales << sales.to_f.round
        prev_monthly_sales << prev_sales.to_f.round if campaign_ids.one?
      end
      campaign_sales << [c, monthly_sales, prev_monthly_sales]
    end
  else
    monthly_sales = []
    prev_monthly_sales = []
    list_months.each do |_m|
      monthly_sales << 0
      prev_monthly_sales << 0 if campaign_ids.one?
    end
    campaign_sales << ['', monthly_sales, prev_monthly_sales]
  end

  campaign_sales
end

.campaigns_revenue_and_num_customers_by_reps(start_date, end_date, campaign_ids) ⇒ Object

Campaigns revenue and num customers by reps.

Parameters:

  • start_date (Date)
  • end_date (Date)
  • campaign_ids (Array<Integer>)

Returns:

  • (Object)


188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'app/services/report/campaigns_report/campaigns_report.rb', line 188

def self.campaigns_revenue_and_num_customers_by_reps(start_date, end_date, campaign_ids)
  prev_start_date = start_date.years_ago(1)
  prev_end_date = end_date.years_ago(1)
  campaign_ids_sql = campaign_ids.empty? ? ' ' : " and coalesce(c.id,c2.id) in (#{campaign_ids.map(&:to_i).join(',')}) "

  sql = <<-SQL.squish
    select vsf.primary_sr_id,r.full_name,
          sum(case when gl_date between '#{start_date}' and '#{end_date}' then quantity * discounted_price * consolidated_exchange_rate else 0 end) as cur_sales_amount,
          count(distinct case when gl_date between '#{start_date}' and '#{end_date}' then vsf.customer_id else null end) as cur_num_customers,
          sum(case when gl_date between '#{prev_start_date}' and '#{prev_end_date}' then quantity * discounted_price * consolidated_exchange_rate else 0 end) as prev_sales_amount,
          count(distinct case when gl_date between '#{prev_start_date}' and '#{prev_end_date}' then vsf.customer_id else null end) as prev_num_customers
    from view_sales_facts vsf
    inner join analytic_date_time_dimensions dt on vsf.gl_date = dt.date
    inner join parties r on vsf.primary_sr_id = r.id and r.inactive = false
    left join campaigns c on vsf.source_id = c.source_id and c.state = 'active'
    left join campaigns c2 on vsf.source_parent_id = c2.source_id and c2.state = 'active'
    where coalesce(c.name,c2.name) is not null
    and (primary_sr_id is not null and primary_sr_id not in (92,85))
    and (gl_date between '#{prev_start_date}' and '#{prev_end_date}' or gl_date between '#{start_date}' and '#{end_date}')
    #{campaign_ids_sql}
    group by vsf.primary_sr_id,r.full_name
  SQL

  ActiveRecord::Base.lease_connection.execute(sql).to_a.map(&:symbolize_keys)
end

.campaigns_revenue_by_report_grouping(start_date, end_date, campaign_ids) ⇒ Object

Campaigns revenue by report grouping.

Parameters:

  • start_date (Date)
  • end_date (Date)
  • campaign_ids (Array<Integer>)

Returns:

  • (Object)


219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'app/services/report/campaigns_report/campaigns_report.rb', line 219

def self.campaigns_revenue_by_report_grouping(start_date, end_date, campaign_ids)
  prev_start_date = start_date.years_ago(1)
  prev_end_date = end_date.years_ago(1)
  campaign_ids_sql = campaign_ids.empty? ? ' ' : " and coalesce(c.id,c2.id) in (#{campaign_ids.map(&:to_i).join(',')}) "

  sql = <<-SQL.squish
    with months as (
        select distinct month,year
        from analytic_date_time_dimensions
        where (date between '#{prev_start_date}' and '#{prev_end_date}' or date between '#{start_date}' and '#{end_date}')
    ), sales as (
        select vsf.report_grouping,sum(quantity * discounted_price * consolidated_exchange_rate) as sales_amount,dt.month,dt.year
        from view_sales_facts vsf
        inner join analytic_date_time_dimensions dt on vsf.gl_date = dt.date
        left join campaigns c on vsf.source_id = c.source_id and c.state = 'active'
        left join campaigns c2 on vsf.source_parent_id = c2.source_id and c2.state = 'active'
        where coalesce(c.name,c2.name) is not null
        and (primary_sr_id is not null and primary_sr_id not in (92,85))
        and (gl_date between '#{prev_start_date}' and '#{prev_end_date}' or gl_date between '#{start_date}' and '#{end_date}')
        #{campaign_ids_sql}
        group by vsf.report_grouping,dt.month,dt.year
    ), sales_reps as (
        select distinct report_grouping
        from sales
    ), sales_reps_by_month as (
        select *
        from sales_reps,months
    )
    select rm.report_grouping,coalesce(sales_amount,0) as sales_amount,rm.month,rm.year
    from sales_reps_by_month rm
    left join sales s on rm.report_grouping = s.report_grouping and rm.month = s.month and rm.year = s.year
  SQL

  ActiveRecord::Base.lease_connection.execute(sql).to_a.map(&:symbolize_keys)
end

.campaigns_revenue_by_report_grouping_for_chart(start_date, end_date, campaign_ids) ⇒ Object

Campaigns revenue by report grouping for chart.

Parameters:

  • start_date (Date)
  • end_date (Date)
  • campaign_ids (Array<Integer>)

Returns:

  • (Object)


260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# File 'app/services/report/campaigns_report/campaigns_report.rb', line 260

def self.campaigns_revenue_by_report_grouping_for_chart(start_date, end_date, campaign_ids)
  campaign_ids_sql = campaign_ids.empty? ? ' ' : " and coalesce(c.id,c2.id) in (#{campaign_ids.map(&:to_i).join(',')}) "
  sql = <<-SQL.squish
    select vsf.report_grouping,sum(quantity * discounted_price * consolidated_exchange_rate) as sales_amount
    from view_sales_facts vsf
    inner join analytic_date_time_dimensions dt on vsf.gl_date = dt.date
    left join campaigns c on vsf.source_id = c.source_id and c.state = 'active'
    left join campaigns c2 on vsf.source_parent_id = c2.source_id and c2.state = 'active'
    where coalesce(c.name,c2.name) is not null
    and (primary_sr_id is not null and primary_sr_id not in (92,85))
    and gl_date between '#{start_date}' and '#{end_date}'
    #{campaign_ids_sql}
    group by vsf.report_grouping
  SQL

  ActiveRecord::Base.lease_connection.execute(sql).to_a.map(&:symbolize_keys)
end

.campaigns_revenue_by_reps(start_date, end_date, campaign_ids) ⇒ Object

Campaigns revenue by reps.

Parameters:

  • start_date (Date)
  • end_date (Date)
  • campaign_ids (Array<Integer>)

Returns:

  • (Object)


74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'app/services/report/campaigns_report/campaigns_report.rb', line 74

def self.campaigns_revenue_by_reps(start_date, end_date, campaign_ids)
  prev_start_date = start_date.years_ago(1)
  prev_end_date = end_date.years_ago(1)
  campaign_ids_sql = campaign_ids.empty? ? ' ' : " and coalesce(c.id,c2.id) in (#{campaign_ids.map(&:to_i).join(',')}) "

  sql = <<-SQL.squish
    with months as (
        select distinct month,year
        from analytic_date_time_dimensions
        where (date between '#{prev_start_date}' and '#{prev_end_date}' or date between '#{start_date}' and '#{end_date}')
    ), sales as (
        select vsf.primary_sr_id,sum(quantity * discounted_price * consolidated_exchange_rate) as sales_amount,count(distinct customer_id) as num_customers,dt.month,dt.year
        from view_sales_facts vsf
        inner join analytic_date_time_dimensions dt on vsf.gl_date = dt.date
        left join campaigns c on vsf.source_id = c.source_id and c.state = 'active'
        left join campaigns c2 on vsf.source_parent_id = c2.source_id and c2.state = 'active'
        where coalesce(c.name,c2.name) is not null
        and (primary_sr_id is not null and primary_sr_id not in (92,85))
        and (gl_date between '#{prev_start_date}' and '#{prev_end_date}' or gl_date between '#{start_date}' and '#{end_date}')
        #{campaign_ids_sql}
        group by vsf.primary_sr_id,dt.month,dt.year
    ), sales_reps as (
        select distinct primary_sr_id,full_name
        from sales sr
        inner join parties r on sr.primary_sr_id = r.id and r.inactive = false
    ), sales_reps_by_month as (
        select *
        from sales_reps,months
    )
    select rm.primary_sr_id,rm.full_name,coalesce(sales_amount,0) as sales_amount,coalesce(num_customers,0) as num_customers,rm.month,rm.year
    from sales_reps_by_month rm
    left join sales s on rm.primary_sr_id = s.primary_sr_id and rm.month = s.month and rm.year = s.year
  SQL

  ActiveRecord::Base.lease_connection.execute(sql).to_a.map(&:symbolize_keys)
end

.result(options = {}) ⇒ Result

Returns campaign performance data.

Parameters:

  • options (Hash) (defaults to: {})

    report filter options

Options Hash (options):

  • period1_gteq (Date)

    start of the reporting period

  • period1_lteq (Date)

    end of the reporting period

  • campaign_ids (Array<String>)

    campaigns to include (blank entries ignored)

Returns:

  • (Result)

    campaign performance data



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'app/services/report/campaigns_report/campaigns_report.rb', line 37

def self.result(options = {})
  start_date = options[:period1_gteq]
  end_date = options[:period1_lteq]
  campaign_ids = options[:campaign_ids].filter_map(&:presence)
  list_months = (1..12).map { |m| m }
  list_months = list_months.delete_if { |m| m > end_date.month }

  data_campaigns_revenue_by_reps = campaigns_revenue_by_reps(start_date, end_date, campaign_ids)
  list_reps = data_campaigns_revenue_by_reps.filter_map { |r| { rep_id: r[:primary_sr_id], rep_name: r[:full_name] } }.uniq
  data_campaigns_revenue_for_chart = campaigns_revenue(start_date, end_date, campaign_ids, list_months)
  data_campaigns_revenue_and_num_customers_by_reps_for_chart = campaigns_revenue_and_num_customers_by_reps(start_date, end_date, campaign_ids)

  data_campaigns_revenue_by_report_grouping = campaigns_revenue_by_report_grouping(start_date, end_date, campaign_ids)
  list_report_grouping = data_campaigns_revenue_by_report_grouping.pluck(:report_grouping).compact.uniq
  data_campaigns_revenue_by_report_grouping_for_chart = campaigns_revenue_by_report_grouping_for_chart(start_date, end_date, campaign_ids)

  Result.new(success: true,
             start_date: start_date,
             end_date: end_date,
             campaign_ids: campaign_ids,
             list_months: list_months,
             current_year: end_date.year,
             prev_year: end_date.years_ago(1).year,
             revenue_data_table: data_campaigns_revenue_by_reps,
             revenue_data_chart: data_campaigns_revenue_for_chart,
             revenue_and_num_customers_data_chart: data_campaigns_revenue_and_num_customers_by_reps_for_chart,
             list_reps: list_reps,
             report_grouping_data_table: data_campaigns_revenue_by_report_grouping,
             list_report_grouping: list_report_grouping,
             report_grouping_data_chart: data_campaigns_revenue_by_report_grouping_for_chart)
end