Class: Report::LeadReport::LeadReport

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

Class Method Summary collapse

Class Method Details

.calls_data(dates) ⇒ Object



776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
# File 'app/services/report/lead_report/lead_report.rb', line 776

def self.calls_data(dates)
  date_from_lm = dates[:date_from].to_date.last_month.beginning_of_month
  date_to_lm = date_from_lm.end_of_month
  date_from_prev_lm = dates[:date_from_prev].to_date.last_month.beginning_of_month
  date_to_prev_lm = date_from_prev_lm.end_of_month

  sql = <<-SQL
      WITH current_period as (
          select (week_id::varchar || extract(dow from dt2.date)::varchar)::int as date_id,dt2.date as c_date
          from (
              select (row_number() over (ORDER BY a.week_num))::int as week_id,week_num
              from (
                  select distinct extract(week from dt1.date) as week_num
                  from analytic_date_time_dimensions dt1
                  where dt1.date between '#{dates[:date_from]}' and '#{dates[:date_to]}'
                  and weekend = 'Weekday'
                  order by 1
              )a
          )b
          inner join analytic_date_time_dimensions dt2 on b.week_num = extract(week from dt2.date)
          where weekend = 'Weekday'
          and dt2.date between '#{dates[:date_from]}' and '#{dates[:date_to]}'

      ), previous_period as (
          select (week_id::varchar || extract(dow from dt2.date)::varchar)::int as date_id,dt2.date as p_date
          from (
              select (row_number() over (ORDER BY a.week_num))::int as week_id,week_num
              from (
                  select distinct extract(week from dt1.date) as week_num
                  from analytic_date_time_dimensions dt1
                  where dt1.date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}'
                  and weekend = 'Weekday'
                  order by 1
              )a
          )b
          inner join analytic_date_time_dimensions dt2 on b.week_num = extract(week from dt2.date)
          where weekend = 'Weekday'
          and dt2.date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}'

      ), periods as (
          select cp.date_id,c_date,p_date
          from current_period cp
          inner join previous_period pp on cp.date_id = pp.date_id

      ), calls as (
          select date,sum(outbounds) as outbounds,sum(inbounds) as inbounds,sum(missed) as missed
          from view_kpis_time_on_tasks
          where department in ('Sales','Customer Service','Business Development','Tech Support')
          and (date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}') or (date between '#{dates[:date_from]}' and '#{dates[:date_to]}')
          group by date

      )
      select date_id,c_date,c1.outbounds as c_outbounds,c1.inbounds as c_inbounds,c1.missed as c_missed,p_date,c2.outbounds as p_outbounds,c2.inbounds as p_inbounds,c2.missed as p_missed
      from periods p
      left join calls c1 on p.c_date = c1.date
      left join calls c2 on p.p_date = c2.date
      order by c_date
  SQL

  results = ActiveRecord::Base.connection.execute(sql).to_a.map { |r| r.symbolize_keys }
end

.calls_totals(data) ⇒ Object



838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
# File 'app/services/report/lead_report/lead_report.rb', line 838

def self.calls_totals(data)
  ttlc_outbounds = data.map { |i| i[:c_outbounds].to_i }.sum
  ttlc_inbounds = data.map { |i| i[:c_inbounds].to_i }.sum
  ttlc_missed = data.map { |i| i[:c_missed].to_i }.sum
  ttlp_outbounds = data.map { |i| i[:p_outbounds].to_i }.sum
  ttlp_inbounds = data.map { |i| i[:p_inbounds].to_i }.sum
  ttlp_missed = data.map { |i| i[:p_missed].to_i }.sum
  ttlc_calls = ttlc_outbounds + ttlc_inbounds + ttlc_missed
  ttlp_calls = ttlp_outbounds + ttlp_inbounds + ttlp_missed
  var_ttl_calls = ttlp_calls.zero? ? 0.0 : ((ttlc_calls.to_f - ttlp_calls.to_f) / ttlp_calls.to_f) * 100
  var_outbounds = ttlp_outbounds.zero? ? 0.0 : ((ttlc_outbounds.to_f - ttlp_outbounds.to_f) / ttlp_outbounds.to_f) * 100
  var_inbounds = ttlp_inbounds.zero? ? 0.0 : ((ttlc_inbounds.to_f - ttlp_inbounds.to_f) / ttlp_inbounds.to_f) * 100
  var_missed = ttlp_missed.zero? ? 0.0 : ((ttlc_missed.to_f - ttlp_missed.to_f) / ttlp_missed.to_f) * 100
  { ttlc_calls: ttlc_calls, ttlp_calls: ttlp_calls, var_ttl_calls: var_ttl_calls,
                   ttlc_outbounds: ttlc_outbounds, ttlc_inbounds: ttlc_inbounds, ttlc_missed: ttlc_missed,
                   ttlp_outbounds: ttlp_outbounds, ttlp_inbounds: ttlp_inbounds, ttlp_missed: ttlp_missed,
                   var_outbounds: var_outbounds, var_inbounds: var_inbounds, var_missed: var_missed }
end

.communications_data(dates) ⇒ Object



857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
# File 'app/services/report/lead_report/lead_report.rb', line 857

def self.communications_data(dates)
  sql = <<-SQL
      with current_period as (
          select (week_id::varchar || extract(dow from dt2.date)::varchar)::int as date_id,dt2.date as c_date
          from (
              select (row_number() over (ORDER BY a.week_num))::int as week_id,week_num
              from (
                  select distinct extract(week from dt1.date) as week_num
                  from analytic_date_time_dimensions dt1
                  where dt1.date between '#{dates[:date_from]}' and '#{dates[:date_to]}'
                  and weekend = 'Weekday'
                  order by 1
              )a
          )b
          inner join analytic_date_time_dimensions dt2 on b.week_num = extract(week from dt2.date)
          where weekend = 'Weekday'
          and dt2.date between '#{dates[:date_from]}' and '#{dates[:date_to]}'

      ), previous_period as (
          select (week_id::varchar || extract(dow from dt2.date)::varchar)::int as date_id,dt2.date as p_date
          from (
              select (row_number() over (ORDER BY a.week_num))::int as week_id,week_num
              from (
                  select distinct extract(week from dt1.date) as week_num
                  from analytic_date_time_dimensions dt1
                  where dt1.date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}'
                  and weekend = 'Weekday'
                  order by 1
              )a
          )b
          inner join analytic_date_time_dimensions dt2 on b.week_num = extract(week from dt2.date)
          where weekend = 'Weekday'
          and dt2.date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}'

      ), periods as (
          select cp.date_id,c_date,p_date
          from current_period cp
          inner join previous_period pp on cp.date_id = pp.date_id

      ), communications as (
          select date,sum(emails) as num_communications
          from view_kpis_time_on_tasks
          where department in ('Sales','Customer Service','Business Development','Tech Support')
          and ((date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}') or (date between '#{dates[:date_from]}' and '#{dates[:date_to]}'))
          group by date

      )
      select c_date,coalesce(c1.num_communications,0) as c_num_communications,p_date,coalesce(c2.num_communications,0) as p_num_communications,(coalesce(c1.num_communications,0) - coalesce(c2.num_communications,0)) as var
      from periods p
      left join communications c1 on p.c_date = c1.date
      left join communications c2 on p.p_date = c2.date
      order by c_date;
  SQL

  results = ActiveRecord::Base.connection.execute(sql).to_a.map { |r| r.symbolize_keys }
end

.communications_totals(data) ⇒ Object



914
915
916
917
918
919
# File 'app/services/report/lead_report/lead_report.rb', line 914

def self.communications_totals(data)
  ttlc_num_communications = data.map { |i| i[:c_num_communications].to_i }.sum
  ttlp_num_communications = data.map { |i| i[:p_num_communications].to_i }.sum
  var_num_communications = ttlc_num_communications - ttlp_num_communications
  { ttlc_num_communications: ttlc_num_communications, ttlp_num_communications: ttlp_num_communications, var_num_communications: var_num_communications }
end

.customer_data(dates) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
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
# File 'app/services/report/lead_report/lead_report.rb', line 88

def self.customer_data(dates)
  date_from_prev = dates[:date_from_prev] + (dates[:date_from].wday - dates[:date_from_prev].wday)
  date_to_prev = dates[:date_to_prev] + 5

  sql = <<-SQL
    with current_period as (
          select (week_id::varchar || extract(dow from dt2.date)::varchar)::int as date_id,dt2.date as c_date
          from (
              select (row_number() over (ORDER BY a.week_num))::int as week_id,week_num
              from (
                  select distinct extract(week from dt1.date) as week_num
                  from analytic_date_time_dimensions dt1
                  where dt1.date between '#{dates[:date_from]}' and '#{dates[:date_to]}'
                  -- and weekend = 'Weekday'
                  order by 1
              )a
          )b
          inner join analytic_date_time_dimensions dt2 on b.week_num = extract(week from dt2.date)
          where dt2.date between '#{dates[:date_from]}' and '#{dates[:date_to]}'

      ), previous_period as (
          select (week_id::varchar || extract(dow from dt2.date)::varchar)::int as date_id,dt2.date as p_date
          from (
              select (row_number() over (ORDER BY a.week_num))::int as week_id,week_num
              from (
                  select distinct extract(week from dt1.date) as week_num
                  from analytic_date_time_dimensions dt1
                  where dt1.date between '#{date_from_prev}' and '#{date_to_prev}'
                  -- and weekend = 'Weekday'
                  order by 1
              )a
          )b
          inner join analytic_date_time_dimensions dt2 on b.week_num = extract(week from dt2.date)
          where dt2.date between '#{date_from_prev}' and '#{date_to_prev}'

      ), periods as (
          select cp.date_id,c_date,p_date
          from current_period cp
          inner join previous_period pp on cp.date_id = pp.date_id

      ), customers as (
          select timezone('America/Chicago', timestamptz(created_at))::date as date_of_change,count(distinct id) as to_customer
          from parties
          where type = 'Customer'
          and state in ('lead','prospect','customer','lead_qualify')
          and (timezone('America/Chicago', timestamptz(created_at))::date between '#{date_from_prev}' and '#{date_to_prev}' or timezone('America/Chicago', timestamptz(created_at))::date between '#{dates[:date_from]}' and '#{dates[:date_to]}')
          and creation_method = 1
          group by timezone('America/Chicago', timestamptz(created_at))::date

      ), customers_created as (
          select date_id,c_date,coalesce(cc.to_customer,0) as c_customer,p_date,coalesce(cp.to_customer,0) as p_customer,(coalesce(cc.to_customer,0) - coalesce(cp.to_customer,0)) as var
          from periods p
          left join customers cc on p.c_date = cc.date_of_change
          left join customers cp on p.p_date = cp.date_of_change
          order by c_date

      )
      select * from customers_created;
  SQL

  results = ActiveRecord::Base.connection.execute(sql).to_a.map { |r| r.symbolize_keys }
end

.customer_totals(data) ⇒ Object



151
152
153
154
155
156
157
158
159
160
# File 'app/services/report/lead_report/lead_report.rb', line 151

def self.customer_totals(data)
  ttlc_customers = data.map { |i| i[:c_customer].to_i }.sum
  ttlp_customers = data.map { |i| i[:p_customer].to_i }.sum
  ttlc_purchase_value = data.map { |i| i[:c_purchase_value].to_f }.sum
  var_customers = ttlc_customers - ttlp_customers
  var_ptg_customers = ttlp_customers.zero? ? 0.0 : ((ttlc_customers.to_f - ttlp_customers.to_f) / ttlp_customers.to_f) * 100
  avg_purchase = ttlc_customers.to_f.zero? ? 0.0 : (ttlc_purchase_value / ttlc_customers.to_f)
  { ttlc_customers: ttlc_customers, ttlp_customers: ttlp_customers, ttlc_purchase_value: ttlc_purchase_value,
                      var_customers: var_customers, avg_purchase: avg_purchase, var_ptg_customers: var_ptg_customers }
end

.dates_to_check(start_date, end_date, compare_start_date, compare_end_date) ⇒ Object



80
81
82
83
84
85
86
# File 'app/services/report/lead_report/lead_report.rb', line 80

def self.dates_to_check(start_date, end_date, compare_start_date, compare_end_date)
  date_from = start_date
  date_to = end_date
  date_from_prev = compare_start_date
  date_to_prev = compare_end_date + 5
  { date_from: date_from, date_to: date_to, date_from_prev: date_from_prev, date_to_prev: date_to_prev }
end

.opportunities_conversion_time(dates) ⇒ Object



312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
# File 'app/services/report/lead_report/lead_report.rb', line 312

def self.opportunities_conversion_time(dates)
  sql = <<-SQL
      with current_period as (
          select (week_id::varchar || extract(dow from dt2.date)::varchar)::int as date_id,dt2.date as c_date
          from (
              select (row_number() over (ORDER BY a.week_num))::int as week_id,week_num
              from (
                  select distinct extract(week from dt1.date) as week_num
                  from analytic_date_time_dimensions dt1
                  where dt1.date between '#{dates[:date_from]}' and '#{dates[:date_to]}'
                  order by 1
              )a
          )b
          inner join analytic_date_time_dimensions dt2 on b.week_num = extract(week from dt2.date)
          where weekend = 'Weekday'
          and dt2.date between '#{dates[:date_from]}' and '#{dates[:date_to]}'

      ), previous_period as (
          select (week_id::varchar || extract(dow from dt2.date)::varchar)::int as date_id,dt2.date as p_date
          from (
              select (row_number() over (ORDER BY a.week_num))::int as week_id,week_num
              from (
                  select distinct extract(week from dt1.date) as week_num
                  from analytic_date_time_dimensions dt1
                  where dt1.date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}'
                  order by 1
              )a
          )b
          inner join analytic_date_time_dimensions dt2 on b.week_num = extract(week from dt2.date)
          where weekend = 'Weekday'
          and dt2.date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}'

      ), periods as (
          select cp.date_id,c_date,p_date
          from current_period cp
          inner join previous_period pp on cp.date_id = pp.date_id

      ), won_opps as (
          select opportunity_id,creation_date,won_date,state,(won_date - creation_date) as conversion_time
          from (
              select id as opportunity_id,
              case when extract(dow from timezone('America/Chicago', timestamptz(created_at))::date) = 6 then (timezone('America/Chicago', timestamptz(created_at))::date + interval '2 day')::date
                  when extract(dow from timezone('America/Chicago', timestamptz(created_at))::date) = 0 then (timezone('America/Chicago', timestamptz(created_at))::date + interval '1 day')::date else timezone('America/Chicago', timestamptz(created_at))::date end as creation_date,
              case when extract(dow from timezone('America/Chicago', timestamptz(won_lost_date))::date) = 6 then (timezone('America/Chicago', timestamptz(won_lost_date))::date + interval '2 day')::date
                  when extract(dow from timezone('America/Chicago', timestamptz(won_lost_date))::date) = 0 then (timezone('America/Chicago', timestamptz(won_lost_date))::date + interval '1 day')::date else timezone('America/Chicago', timestamptz(won_lost_date))::date end as won_date,
              state
              from view_opportunities vo
              where state = 'won'
              and ((timezone('America/Chicago', timestamptz(created_at))::date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}') or (timezone('America/Chicago', timestamptz(created_at))::date between '#{dates[:date_from]}' and '#{dates[:date_to]}'))
              and ((timezone('America/Chicago', timestamptz(won_lost_date))::date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}') or (timezone('America/Chicago', timestamptz(won_lost_date))::date between '#{dates[:date_from]}' and '#{dates[:date_to]}'))
          )a
          order by creation_date

      ), conversion_time as (
          select avg(coalesce(wo1.conversion_time,0)) as c_avg_time,avg(coalesce(wo2.conversion_time,0)) as p_avg_time,
              case when avg(wo2.conversion_time) = 0.0 then 0.0 else (((avg(wo1.conversion_time) - avg(wo2.conversion_time)) / avg(wo2.conversion_time)) * 100) end as var_ptg
          from periods p
          left join won_opps wo1 on p.c_date = wo1.creation_date
          left join won_opps wo2 on p.p_date = wo2.creation_date

      )
      select * from conversion_time;
  SQL

  results = ActiveRecord::Base.connection.execute(sql).to_a.map { |r| r.symbolize_keys }[0]
end

.opportunities_data(dates, report_type) ⇒ Object



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
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
213
214
215
216
217
218
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
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
# File 'app/services/report/lead_report/lead_report.rb', line 162

def self.opportunities_data(dates, report_type)
  select_sql = 'select * from opps_created' if report_type == 1
  select_sql = 'select * from opps_product_line' if report_type == 2

  sql = <<-SQL
      with current_period as (
          select (week_id::varchar || extract(dow from dt2.date)::varchar)::int as date_id,dt2.date as c_date
          from (
              select (row_number() over (ORDER BY a.week_num))::int as week_id,week_num
              from (
                  select distinct extract(week from dt1.date) as week_num
                  from analytic_date_time_dimensions dt1
                  where dt1.date between '#{dates[:date_from]}' and '#{dates[:date_to]}'
                  and weekend = 'Weekday'
                  order by 1
              )a
          )b
          inner join analytic_date_time_dimensions dt2 on b.week_num = extract(week from dt2.date)
          where weekend = 'Weekday'
          and dt2.date between '#{dates[:date_from]}' and '#{dates[:date_to]}'

      ), previous_period as (
          select (week_id::varchar || extract(dow from dt2.date)::varchar)::int as date_id,dt2.date as p_date
          from (
              select (row_number() over (ORDER BY a.week_num))::int as week_id,week_num
              from (
                  select distinct extract(week from dt1.date) as week_num
                  from analytic_date_time_dimensions dt1
                  where dt1.date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}'
                  and weekend = 'Weekday'
                  order by 1
              )a
          )b
          inner join analytic_date_time_dimensions dt2 on b.week_num = extract(week from dt2.date)
          where weekend = 'Weekday'
          and dt2.date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}'

      ), periods as (
          select cp.date_id,c_date,p_date
          from current_period cp
          inner join previous_period pp on cp.date_id = pp.date_id

      ), opps as (
          select id as opportunity_id,
              case when extract(dow from timezone('America/Chicago', timestamptz(created_at))::date) = 6 then (timezone('America/Chicago', timestamptz(created_at))::date + interval '2 day')::date
                      when extract(dow from timezone('America/Chicago', timestamptz(created_at))::date) = 0 then (timezone('America/Chicago', timestamptz(created_at))::date + interval '1 day')::date else timezone('America/Chicago', timestamptz(created_at))::date end as date,
              state,a.quote_id
          from view_opportunities vo
          inner join (
              select opportunity_id,max(id) as quote_id
              from quotes
              group by opportunity_id
          )a on vo.id = a.opportunity_id
          where (timezone('America/Chicago', timestamptz(created_at))::date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}') or (timezone('America/Chicago', timestamptz(created_at))::date between '#{dates[:date_from]}' and '#{dates[:date_to]}')

      ), opps_quotes as (
          select op.opportunity_id,op.quote_id,op.date,op.state,coalesce((line_total * coalesce(avg_rate,1)),0) as line_total
          from quotes q
          inner join opps op on op.opportunity_id = q.opportunity_id and op.quote_id = q.id
          left join (
              select from_currency,to_char(effective_date,'YYYY')::int as year,to_char(effective_date,'MM')::int as month,avg(rate) as avg_rate
              from exchange_rates
              where from_currency = 'CAD' and to_currency = 'USD'
              group by from_currency,to_char(effective_date,'YYYY')::int,to_char(effective_date,'MM')::int
          )a on to_char(timezone('America/Chicago', timestamptz(q.created_at))::date,'YYYY')::int = year and to_char(timezone('America/Chicago', timestamptz(q.created_at))::date,'MM')::int = month and currency = a.from_currency

      ), opps_invoices as (
          select op.opportunity_id,op.quote_id,sum(revenue_consolidated) as invoiced_value
          from orders o
          inner join invoices i on o.id = i.order_id
          inner join opps op on o.opportunity_id = op.opportunity_id
          where o.state = 'invoiced'
          and order_type = 'SO'
          and i.state in ('paid','unpaid')
          group by op.opportunity_id,op.quote_id

      ), quotes_rank as (
          select opportunity_id,amount_rank,amount,group1
          from (
              select q.opportunity_id,rank() over (partition by q.id order by sum(quantity * coalesce(unit_cogs,discounted_price)) desc) as amount_rank,sum(quantity * coalesce(unit_cogs,discounted_price)) as amount,trim(split_part(lineage_expanded,'>',1)) as group1
              from quotes q
              inner join line_items li on q.id = li.resource_id and resource_type = 'Quote'
              inner join items i on li.item_id = i.id
              inner join product_lines pl on i.primary_product_line_id = pl.id
              inner join opps_quotes oq on q.id = oq.quote_id
              where li.tax_class = 'g'
              group by q.id,group1
          )qk
          where amount_rank = 1

      ), orders_rank as (
          select opportunity_id,amount_rank,amount,group1
          from (
              select o.opportunity_id,rank() over (partition by o.id order by sum(quantity * coalesce(unit_cogs,discounted_price)) desc) as amount_rank,sum(quantity * coalesce(unit_cogs,discounted_price)) as amount,trim(split_part(lineage_expanded,'>',1)) as group1
              from orders o
              inner join line_items li on o.id = li.resource_id and resource_type = 'Order'
              inner join items i on li.item_id = i.id
              inner join product_lines pl on i.primary_product_line_id = pl.id
              inner join opps_invoices oi on o.opportunity_id = oi.opportunity_id
              where li.tax_class = 'g'
              and o.order_type in ('SO','CI')
              group by o.id,group1
          )ok
          where amount_rank = 1

      ), opps_pl_rank as (
          select date,group1,count(opportunity_id) as num_opps,sum(opp_amount) as opp_amount
          from (
              select distinct date,coalesce(rk.group1,qr.group1,'FloorHeating') as group1,oq.opportunity_id,coalesce(invoiced_value,line_total) as opp_amount
              from opps_quotes oq
              left join opps_invoices oi on oq.opportunity_id = oi.opportunity_id
              left join quotes_rank qr on oq.opportunity_id = qr.opportunity_id
              left join orders_rank rk on oq.opportunity_id = rk.opportunity_id
          )pl
          group by date,group1

      ), opps_product_line as (
          select group1,
              sum(case when date between (select min(c_date) from periods) and (select max(c_date) from periods) then opp_amount else 0 end) as c_total,
              sum(case when date between (select min(c_date) from periods) and (select max(c_date) from periods) then num_opps else 0 end) as c_num_opp_total,
              sum(case when date between (select min(p_date) from periods) and (select max(p_date) from periods) then opp_amount else 0 end) as p_total,
              sum(case when date between (select min(p_date) from periods) and (select max(p_date) from periods) then num_opps else 0 end) as p_num_opp_total
          from opps_pl_rank
          group by group1
          order by 2 desc

      ), opps_result as (
          select date,count(oq.opportunity_id) as num_opp,sum(line_total) as value_opp,
              sum(case when state = 'won' then 1 else 0 end) as num_won_opp,
              sum(case when state = 'won' then invoiced_value else 0 end) as value_won_opp,
              sum(case when state = 'lost' then 1 else 0 end) as num_lost_opp,
              sum(case when state = 'lost' then line_total else 0 end) as value_lost_opp
          from opps_quotes oq
          left join opps_invoices oi on oq.opportunity_id = oi.opportunity_id
          group by date

      ), opps_created as (
          select c_date,pt1.num_opp as c_num_opp,pt1.value_opp as c_value_opp,pt1.num_won_opp as c_num_won_opp,pt1.value_won_opp as c_value_won_opp,pt1.num_lost_opp as c_num_lost_opp,pt1.value_lost_opp as c_value_lost_opp,
              p_date,pt2.num_opp as p_num_opp,pt2.value_opp as p_value_opp,pt2.num_won_opp as p_num_won_opp,pt2.value_won_opp as p_value_won_opp,pt2.num_lost_opp as p_num_lost_opp,pt2.value_lost_opp as p_value_lost_opp
          from periods p
          left join opps_result pt1 on p.c_date = pt1.date
          left join opps_result pt2 on p.p_date = pt2.date

      )
      #{select_sql};
  SQL

  results = ActiveRecord::Base.connection.execute(sql).to_a.map { |r| r.symbolize_keys }
end

.opportunities_totals(data) ⇒ Object



379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
# File 'app/services/report/lead_report/lead_report.rb', line 379

def self.opportunities_totals(data)
  ttlc_num_opp = data.map { |i| i[:c_num_opp].to_i }.sum
  ttlc_num_won_opp = data.map { |i| i[:c_num_won_opp].to_i }.sum
  ttlc_num_lost_opp = data.map { |i| i[:c_num_lost_opp].to_i }.sum
  ttlc_value_opp = data.map { |i| i[:c_value_opp].to_i }.sum
  ttlc_value_won_opp = data.map { |i| i[:c_value_won_opp].to_i }.sum
  ttlc_value_lost_opp = data.map { |i| i[:c_value_lost_opp].to_i }.sum
  ttlp_num_opp = data.map { |i| i[:p_num_opp].to_i }.sum
  ttlp_num_won_opp = data.map { |i| i[:p_num_won_opp].to_i }.sum
  ttlp_num_lost_opp = data.map { |i| i[:p_num_lost_opp].to_i }.sum
  ttlp_value_opp = data.map { |i| i[:p_value_opp].to_i }.sum
  ttlp_value_won_opp = data.map { |i| i[:p_value_won_opp].to_i }.sum
  ttlp_value_lost_opp = data.map { |i| i[:p_value_lost_opp].to_i }.sum
  ttlc_num_opp_conv = ttlc_num_opp.zero? ? 0.0 : (ttlc_num_won_opp.to_f / ttlc_num_opp.to_f) * 100
  ttlp_num_opp_conv = ttlp_num_opp.zero? ? 0.0 : (ttlp_num_won_opp.to_f / ttlp_num_opp.to_f) * 100
  ttlc_value_opp_conv = ttlc_value_opp.zero? ? 0.0 : (ttlc_value_won_opp.to_f / ttlc_value_opp.to_f) * 100
  ttlp_value_opp_conv = ttlp_value_opp.zero? ? 0.0 : (ttlp_value_won_opp.to_f / ttlp_value_opp.to_f) * 100
  var_num_opp = ttlp_num_opp.zero? ? 0.0 : ((ttlc_num_opp.to_f - ttlp_num_opp.to_f) / ttlp_num_opp.to_f) * 100
  var_num_won_opp = ttlp_num_won_opp.zero? ? 0.0 : ((ttlc_num_won_opp.to_f - ttlp_num_won_opp.to_f) / ttlp_num_won_opp.to_f) * 100
  var_num_lost_opp = ttlp_num_lost_opp.zero? ? 0.0 : ((ttlc_num_lost_opp.to_f - ttlp_num_lost_opp.to_f) / ttlp_num_lost_opp.to_f) * 100
  var_value_opp = ttlp_value_opp.zero? ? 0.0 : ((ttlc_value_opp.to_f - ttlp_value_opp.to_f) / ttlp_value_opp.to_f) * 100
  var_value_won_opp = ttlp_value_won_opp.zero? ? 0.0 : ((ttlc_value_won_opp.to_f - ttlp_value_won_opp.to_f) / ttlp_value_won_opp.to_f) * 100
  var_value_lost_opp = ttlp_value_lost_opp.zero? ? 0.0 : ((ttlc_value_lost_opp.to_f - ttlp_value_lost_opp.to_f) / ttlp_value_lost_opp.to_f) * 100
  var_num_conv = ttlp_num_opp_conv.zero? ? 0.0 : ((ttlc_num_opp_conv - ttlp_num_opp_conv) / ttlp_num_opp_conv) * 100
  var_value_conv = ttlp_value_opp_conv.zero? ? 0.0 : ((ttlc_value_opp_conv - ttlp_value_opp_conv) / ttlp_value_opp_conv) * 100
  { ttlc_num_opp: ttlc_num_opp, ttlc_num_won_opp: ttlc_num_won_opp, ttlc_num_lost_opp: ttlc_num_lost_opp,
                           ttlp_num_opp: ttlp_num_opp, ttlp_num_won_opp: ttlp_num_won_opp, ttlp_num_lost_opp: ttlp_num_lost_opp,
                           var_num_opp: var_num_opp, var_num_won_opp: var_num_won_opp, var_num_lost_opp: var_num_lost_opp,
                           ttlc_value_opp: ttlc_value_opp, ttlc_value_won_opp: ttlc_value_won_opp, ttlc_value_lost_opp: ttlc_value_lost_opp,
                           ttlp_value_opp: ttlp_value_opp, ttlp_value_won_opp: ttlp_value_won_opp, ttlp_value_lost_opp: ttlp_value_lost_opp,
                           var_value_opp: var_value_opp, var_value_won_opp: var_value_won_opp, var_value_lost_opp: var_value_lost_opp,
                           ttlc_num_opp_conv: ttlc_num_opp_conv, ttlp_num_opp_conv: ttlp_num_opp_conv, ttlc_value_opp_conv: ttlc_value_opp_conv,
                           ttlp_value_opp_conv: ttlp_value_opp_conv, var_num_conv: var_num_conv, var_value_conv: var_value_conv }
end

.orders_data(dates, report_type) ⇒ Object



414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
# File 'app/services/report/lead_report/lead_report.rb', line 414

def self.orders_data(dates, report_type)
  select_sql = 'select * from orders_created' if report_type == 1
  select_sql = 'select * from orders_product_line' if report_type == 2

  sql = <<-SQL
      with current_period as (
          select (week_id::varchar || extract(dow from dt2.date)::varchar)::int as date_id,dt2.date as c_date
          from (
              select (row_number() over (ORDER BY a.week_num))::int as week_id,week_num
              from (
                  select distinct extract(week from dt1.date) as week_num
                  from analytic_date_time_dimensions dt1
                  where dt1.date between '#{dates[:date_from]}' and '#{dates[:date_to]}'
                  and weekend = 'Weekday'
                  order by 1
              )a
          )b
          inner join analytic_date_time_dimensions dt2 on b.week_num = extract(week from dt2.date)
          where weekend = 'Weekday'
          and dt2.date between '#{dates[:date_from]}' and '#{dates[:date_to]}'

      ), previous_period as (
          select (week_id::varchar || extract(dow from dt2.date)::varchar)::int as date_id,dt2.date as p_date
          from (
              select (row_number() over (ORDER BY a.week_num))::int as week_id,week_num
              from (
                  select distinct extract(week from dt1.date) as week_num
                  from analytic_date_time_dimensions dt1
                  where dt1.date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}'
                  and weekend = 'Weekday'
                  order by 1
              )a
          )b
          inner join analytic_date_time_dimensions dt2 on b.week_num = extract(week from dt2.date)
          where weekend = 'Weekday'
          and dt2.date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}'

      ), periods as (
          select cp.date_id,c_date,p_date
          from current_period cp
          inner join previous_period pp on cp.date_id = pp.date_id

      ), total_orders as (
          select id as order_id,
              case when extract(dow from timezone('America/Chicago', timestamptz(created_at))::date) = 6 then (timezone('America/Chicago', timestamptz(created_at))::date + interval '2 day')::date
                      when extract(dow from timezone('America/Chicago', timestamptz(created_at))::date) = 0 then (timezone('America/Chicago', timestamptz(created_at))::date + interval '1 day')::date else timezone('America/Chicago', timestamptz(created_at))::date end as o_date,
              state,coalesce((line_total * coalesce(avg_rate,1)),0) as line_total
          from orders o
          left join (
              select from_currency,to_char(effective_date,'YYYY')::int as year,to_char(effective_date,'MM')::int as month,avg(rate) as avg_rate
              from exchange_rates
              where from_currency = 'CAD' and to_currency = 'USD'
              group by from_currency,to_char(effective_date,'YYYY')::int,to_char(effective_date,'MM')::int
          )a on to_char(timezone('America/Chicago', timestamptz(o.created_at))::date,'YYYY')::int = year and to_char(timezone('America/Chicago', timestamptz(o.created_at))::date,'MM')::int = month and currency = a.from_currency
          where o.order_type in ('SO','CI')
          and ((timezone('America/Chicago', timestamptz(created_at))::date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}') or (timezone('America/Chicago', timestamptz(created_at))::date between '#{dates[:date_from]}' and '#{dates[:date_to]}'))

      ), orders_invoiced as (
          select o_date,i.order_id,sum(consolidated_exchange_rate * quantity * discounted_price) as iv_line_total
          from invoices i
          inner join total_orders td on i.order_id = td.order_id
          inner join line_items li on li.resource_type = 'Invoice' and li.resource_id = i.id
          and i.state in ('paid','unpaid')
          and li.tax_class = 'g'
          group by o_date,i.order_id

      ), orders_pl_rank as (
          select order_id,amount_rank,amount,group1
          from (
              select o.id as order_id,rank() over (partition by o.id order by sum(quantity * coalesce(unit_cogs,discounted_price)) desc) as amount_rank,sum(quantity * coalesce(unit_cogs,discounted_price)) as amount,trim(split_part(lineage_expanded,'>',1)) as group1
              from orders o
              inner join line_items li on o.id = li.resource_id and resource_type = 'Order'
              inner join items i on li.item_id = i.id
              inner join product_lines pl on i.primary_product_line_id = pl.id
              where li.tax_class = 'g'
              and o.order_type in ('SO','CI')
              and ((timezone('America/Chicago', timestamptz(o.created_at))::date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}') or (timezone('America/Chicago', timestamptz(o.created_at))::date between '#{dates[:date_from]}' and '#{dates[:date_to]}'))
              group by o.id,group1
          )k
          where amount_rank = 1

      ), orders_product_line as (
          select group1,
              sum(case when o_date between (select min(c_date) from periods) and (select max(c_date) from periods) then iv_line_total else 0 end) as c_total,
              sum(case when o_date between (select min(c_date) from periods) and (select max(c_date) from periods) then num_orders else 0 end) as c_num_ord_total,
              sum(case when o_date between (select min(p_date) from periods) and (select max(p_date) from periods) then iv_line_total else 0 end) as p_total,
              sum(case when o_date between (select min(p_date) from periods) and (select max(p_date) from periods) then num_orders else 0 end) as p_num_ord_total
          from (
              select o_date,r.group1,sum(iv_line_total) as iv_line_total,count(distinct oi.order_id) as num_orders
              from orders_invoiced oi
              inner join orders_pl_rank r on oi.order_id = r.order_id
              left join periods p1 on oi.o_date = p1.c_date
              left join periods p2 on oi.o_date = p2.p_date
              where coalesce(p1.c_date,p2.p_date) is not null
              and r.group1 <> 'Marketing'
              group by o_date,r.group1
          )a
          group by group1
          order by 2 desc

      ), data_orders as (
          select o_date,count(order_id) as ttl_ord,sum(case when state = 'invoiced' then iv_line_total else line_total end) as ttl_val_ord,
              sum(case when state = 'invoiced' then 1 else 0 end) as ttl_inv_ord,sum(case when state = 'invoiced' then iv_line_total else 0 end) as ttl_inv_val_ord
          from (
              select tr.o_date,tr.order_id,tr.state,tr.line_total,sum(od.iv_line_total) as iv_line_total
              from total_orders tr
              left join orders_invoiced od on tr.order_id = od.order_id
              group by tr.o_date,tr.order_id,tr.state,tr.line_total
          )a
          group by o_date

      ), orders_created as (
          select c_date,dc.ttl_ord as ttlc_ord,dc.ttl_val_ord as ttlc_val_ord,dc.ttl_inv_ord as ttlc_inv_ord,dc.ttl_inv_val_ord as ttlc_inv_val_ord,
              p_date,dp.ttl_ord as ttlp_ord,dp.ttl_val_ord as ttlp_val_ord,dp.ttl_inv_ord as ttlp_inv_ord,dp.ttl_inv_val_ord as ttlp_inv_val_ord
          from periods p
          left join data_orders dc on p.c_date = dc.o_date
          left join data_orders dp on p.p_date = dp.o_date
          order by c_date

      )
      #{select_sql};
  SQL

  results = ActiveRecord::Base.connection.execute(sql).to_a.map { |r| r.symbolize_keys }
end

.orders_totals(data) ⇒ Object



540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
# File 'app/services/report/lead_report/lead_report.rb', line 540

def self.orders_totals(data)
  num_days = data.map { |i| i[:c_date].to_i }.count
  ttlc_orders = data.map { |i| i[:ttlc_ord].to_i }.sum
  ttlc_value = data.map { |i| i[:ttlc_val_ord].to_i }.sum
  ttlc_inv_orders = data.map { |i| i[:ttlc_inv_ord].to_i }.sum
  ttlc_inv_value = data.map { |i| i[:ttlc_inv_val_ord].to_i }.sum
  ttlp_orders = data.map { |i| i[:ttlp_ord].to_i }.sum
  ttlp_value = data.map { |i| i[:ttlp_val_ord].to_i }.sum
  ttlp_inv_orders = data.map { |i| i[:ttlp_inv_ord].to_i }.sum
  ttlp_inv_value = data.map { |i| i[:ttlp_inv_val_ord].to_i }.sum

  c_orders_by_day = num_days.zero? ? 0.0 : (ttlc_orders / num_days)
  c_value_by_day = num_days.zero? ? 0.0 : (ttlc_value / num_days)
  c_inv_orders_by_day = num_days.zero? ? 0.0 : (ttlc_inv_orders / num_days)
  c_inv_value_by_day = num_days.zero? ? 0.0 : (ttlc_inv_value / num_days)
  p_orders_by_day = num_days.zero? ? 0.0 : (ttlp_orders / num_days)
  p_value_by_day = num_days.zero? ? 0.0 : (ttlp_value / num_days)
  p_inv_orders_by_day = num_days.zero? ? 0.0 : (ttlp_inv_orders / num_days)
  p_inv_value_by_day = num_days.zero? ? 0.0 : (ttlp_inv_value / num_days)

  var_orders = ttlp_orders.zero? ? 0.0 : (((ttlc_orders.to_f - ttlp_orders.to_f) / ttlp_orders.to_f) * 100)
  var_value = ttlp_value.zero? ? 0.0 : (((ttlc_value.to_f - ttlp_value.to_f) / ttlp_value.to_f) * 100)
  var_inv_orders = ttlp_inv_orders.zero? ? 0.0 : (((ttlc_inv_orders.to_f - ttlp_inv_orders.to_f) / ttlp_inv_orders.to_f) * 100)
  var_inv_value = ttlp_inv_value.zero? ? 0.0 : (((ttlc_inv_value.to_f - ttlp_inv_value.to_f) / ttlp_inv_value.to_f) * 100)

  var_orders_by_day = p_orders_by_day.zero? ? 0.0 : (((c_orders_by_day.to_f - p_orders_by_day.to_f) / p_orders_by_day.to_f) * 100)
  var_value_by_day = p_value_by_day.zero? ? 0.0 : (((c_value_by_day.to_f - p_value_by_day.to_f) / p_value_by_day.to_f) * 100)
  var_inv_orders_by_day = p_inv_orders_by_day.zero? ? 0.0 : (((c_inv_orders_by_day.to_f - p_inv_orders_by_day.to_f) / p_inv_orders_by_day.to_f) * 100)
  var_inv_value_by_day = p_inv_value_by_day.zero? ? 0.0 : (((c_inv_value_by_day.to_f - p_inv_value_by_day.to_f) / p_inv_value_by_day.to_f) * 100)
  { ttlc_orders: ttlc_orders, ttlc_value: ttlc_value, ttlc_inv_orders: ttlc_inv_orders, ttlc_inv_value: ttlc_inv_value,
                    ttlp_orders: ttlp_orders, ttlp_value: ttlp_value, ttlp_inv_orders: ttlp_inv_orders, ttlp_inv_value: ttlp_inv_value,
                    var_orders: var_orders, var_value: var_value, var_inv_orders: var_inv_orders, var_inv_value: var_inv_value,
                    c_orders_by_day: c_orders_by_day, c_value_by_day: c_value_by_day, c_inv_orders_by_day: c_inv_orders_by_day, c_inv_value_by_day: c_inv_value_by_day,
                    p_orders_by_day: p_orders_by_day, p_value_by_day: p_value_by_day, p_inv_orders_by_day: p_inv_orders_by_day, p_inv_value_by_day: p_inv_value_by_day,
                    var_orders_by_day: var_orders_by_day, var_value_by_day: var_value_by_day, var_inv_orders_by_day: var_inv_orders_by_day, var_inv_value_by_day: var_inv_value_by_day }
end

.results(options = {}, type) ⇒ Object

Result = Data.define( :success?, :date_from, :date_to, :date_from_prev, :date_to_prev,
[:customer_created], :customer_summary,
[:opportunities_created], [:opps_by_product_line], :opps_conversion_time, :opportunities_summary,
[:orders_created], [:orders_by_product_line], :orders_summary,
[:services_by_pl], [:services_by_date],
[:rooms_created], :rooms_summary,
[:calls], :calls_summary,
[:communications], :communications_summary,
[:sms], :sms_summary,
[:website_visits], [:website_traffic], :website_visits_summary) do



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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
68
69
70
71
72
73
74
75
76
77
78
# File 'app/services/report/lead_report/lead_report.rb', line 12

def self.results(options = {}, type)
  start_date = options[:period1_gteq].to_date
  end_date = options[:period1_lteq].to_date
  compare_start_date = options[:period2_gteq].to_date
  compare_end_date = options[:period2_lteq].to_date

  # dates = dates_to_check(start_date,end_date,compare_start_date,compare_end_date)
  # customer_created = customer_data(dates)
  # customer_summary = customer_totals(customer_created)

  # opportunities_created = opportunities_data(dates,1)
  # opps_by_product_line = opportunities_data(dates,2)
  # opps_conversion_time = opportunities_conversion_time(dates)
  # opportunities_summary = opportunities_totals(opportunities_created)

  # orders_created = orders_data(dates,1)
  # orders_by_product_line = orders_data(dates,2)
  # orders_summary = orders_totals(orders_created)

  # services_by_pl = services_data(dates,1)
  # services_by_date = services_data(dates,2)

  # rooms_created = rooms_data(dates)
  # rooms_summary = rooms_totals(rooms_created)

  # calls = calls_data(dates)
  # calls_summary = calls_totals(calls)

  # communications = communications_data(dates)
  # communications_summary = communications_totals(communications)

  # sms = sms_data(dates)
  # sms_summary = sms_totals(sms)

  # website_visits = website_visits_data(dates,1)
  # website_traffic = website_visits_data(dates,2)
  # website_visits_summary = website_visits_totals(website_visits)

  # Result.new( success: true,
  #             date_from: start_date,
  #             date_to: end_date,
  #             date_from_prev: compare_start_date,
  #             date_to_prev: compare_end_date,
  #             customer_created: customer_created,
  #             customer_summary: customer_summary,
  #             opportunities_created: opportunities_created,
  #             opps_by_product_line: opps_by_product_line,
  #             opps_conversion_time: opps_conversion_time,
  #             opportunities_summary: opportunities_summary,
  #             orders_created: orders_created,
  #             orders_by_product_line: orders_by_product_line,
  #             orders_summary: orders_summary,
  #             services_by_pl: services_by_pl,
  #             services_by_date: services_by_date,
  #             rooms_created: rooms_created,
  #             rooms_summary: rooms_summary,
  #             calls: calls,
  #             calls_summary: calls_summary,
  #             communications: communications,
  #             communications_summary: communications_summary,
  #             sms: sms,
  #             sms_summary: sms_summary,
  #             website_visits: website_visits,
  #             website_traffic: website_traffic,
  #             website_visits_summary: website_visits_summary
  # )
end

.rooms_data(dates) ⇒ Object



670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
# File 'app/services/report/lead_report/lead_report.rb', line 670

def self.rooms_data(dates)
  sql = <<-SQL
      with current_period as (
          select (week_id::varchar || extract(dow from dt2.date)::varchar)::int as date_id,dt2.date as c_date
          from (
              select (row_number() over (ORDER BY a.week_num))::int as week_id,week_num
              from (
                  select distinct extract(week from dt1.date) as week_num
                  from analytic_date_time_dimensions dt1
                  where dt1.date between '#{dates[:date_from]}' and '#{dates[:date_to]}'
                  and weekend = 'Weekday'
                  order by 1
              )a
          )b
          inner join analytic_date_time_dimensions dt2 on b.week_num = extract(week from dt2.date)
          where weekend = 'Weekday'
          and dt2.date between '#{dates[:date_from]}' and '#{dates[:date_to]}'

      ), previous_period as (
          select (week_id::varchar || extract(dow from dt2.date)::varchar)::int as date_id,dt2.date as p_date
          from (
              select (row_number() over (ORDER BY a.week_num))::int as week_id,week_num
              from (
                  select distinct extract(week from dt1.date) as week_num
                  from analytic_date_time_dimensions dt1
                  where dt1.date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}'
                  and weekend = 'Weekday'
                  order by 1
              )a
          )b
          inner join analytic_date_time_dimensions dt2 on b.week_num = extract(week from dt2.date)
          where weekend = 'Weekday'
          and dt2.date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}'

      ), periods as (
          select cp.date_id,c_date,p_date
          from current_period cp
          inner join previous_period pp on cp.date_id = pp.date_id

      ), rooms as (
          select rc_date,count(rc_id) as rc_total,
              sum(case when state = 'complete' then 1 else 0 end) as rc_complete,
              sum(case when reference_number like '%-R%' then 1 else 0 end) as rc_revised,
              sum(case when coalesce(system1,system2) = 'Floor Heating' then 1 else 0 end) as rc_floor_heating,
              sum(case when coalesce(system1,system2) = 'Snow Melting' then 1 else 0 end) as rc_snow_melting,
              sum(case when coalesce(system1,system2) not in ('Floor Heating','Snow Melting')  then 1 else 0 end) as rc_others

          from (
              select
                  case when extract(dow from timezone('America/Chicago', timestamptz(rc.created_at))::date) = 6 then (timezone('America/Chicago', timestamptz(rc.created_at))::date + interval '2 day')::date
                      when extract(dow from timezone('America/Chicago', timestamptz(rc.created_at))::date) = 0 then (timezone('America/Chicago', timestamptz(rc.created_at))::date + interval '1 day')::date else timezone('America/Chicago', timestamptz(rc.created_at))::date end as rc_date,
                  rc.id as rc_id,reference_number,rc.state,
                  rtrim(split_part(lineage_expanded,'>', 1)) as system1,
                  case when ft.environment = 'Countertop' then 'Countertop Heater'
                          when ft.environment = 'Outdoor' then 'Snow Melting'
                          when ft.environment = 'Roof' then 'Roof & Gutter Deicing'
                          when ft.environment = 'Indoor' and rt.name = 'Driveway' then 'Snow Melting'
                          when ft.environment = 'Indoor' and rt.name = 'Walkway' then 'Snow Melting'
                          when ft.environment = 'Pipe' then 'Pipe Freeze Protection'
                          when ft.environment = 'Indoor' and rt.name not in ('Driveway','Walkway') then 'Floor Heating' end as system2
              from room_configurations rc
              left join product_lines pl on rc.heating_system_product_line_id = pl.id
              left join floor_types ft on rc.floor_type_id = ft.id
              left join room_types rt on rc.room_type_id = rt.id
              where (timezone('America/Chicago', timestamptz(rc.created_at))::date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}') or (timezone('America/Chicago', timestamptz(rc.created_at))::date between '#{dates[:date_from]}' and '#{dates[:date_to]}')
          )a
          group by rc_date

      ), rooms_created as (
          select c_date,rc.rc_total as rcc_total,rc.rc_complete as rcc_complete,rc.rc_revised as rcc_revised,rc.rc_floor_heating as rcc_floor_heating,rc.rc_snow_melting as rcc_snow_melting,rc.rc_others as rcc_others,
              p_date,rp.rc_total as rcp_total,rp.rc_complete as rcp_complete,rp.rc_revised as rcp_revised,rp.rc_floor_heating as rcp_floor_heating,rp.rc_snow_melting as rcp_snow_melting,rp.rc_others as rcp_others
          from periods p
          left join rooms rc on p.c_date = rc.rc_date
          left join rooms rp on p.p_date = rp.rc_date
          order by c_date
      )
      select * from rooms_created;
  SQL

  results = ActiveRecord::Base.connection.execute(sql).to_a.map { |r| r.symbolize_keys }
end

.rooms_totals(data) ⇒ Object



752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
# File 'app/services/report/lead_report/lead_report.rb', line 752

def self.rooms_totals(data)
  ttlc_rooms = data.map { |i| i[:rcc_total].to_i }.sum
  ttlc_complete = data.map { |i| i[:rcc_complete].to_i }.sum
  ttlc_revised = data.map { |i| i[:rcc_revised].to_i }.sum
  ttlc_fh = data.map { |i| i[:rcc_floor_heating].to_i }.sum
  ttlc_sm = data.map { |i| i[:rcc_snow_melting].to_i }.sum
  ttlc_others = data.map { |i| i[:rcc_others].to_i }.sum
  ttlp_rooms = data.map { |i| i[:rcp_total].to_i }.sum
  ttlp_complete = data.map { |i| i[:rcp_complete].to_i }.sum
  ttlp_revised = data.map { |i| i[:rcp_revised].to_i }.sum
  ttlp_fh = data.map { |i| i[:rcp_floor_heating].to_i }.sum
  ttlp_sm = data.map { |i| i[:rcp_snow_melting].to_i }.sum
  ttlp_others = data.map { |i| i[:rcp_others].to_i }.sum
  var_rooms = ttlc_rooms - ttlp_rooms
  var_complete = ttlc_complete - ttlp_complete
  var_revised = ttlc_revised - ttlp_revised
  var_fh = ttlc_fh - ttlp_fh
  var_sm = ttlc_sm - ttlp_sm
  var_others = ttlc_others - ttlp_others
  { ttlc_rooms: ttlc_rooms, ttlc_complete: ttlc_complete, ttlc_revised: ttlc_revised, ttlc_fh: ttlc_fh, ttlc_sm: ttlc_sm, ttlc_others: ttlc_others,
                   ttlp_rooms: ttlp_rooms, ttlp_complete: ttlp_complete, ttlp_revised: ttlp_revised, ttlp_fh: ttlp_fh, ttlp_sm: ttlp_sm, ttlp_others: ttlp_others,
                   var_rooms: var_rooms, var_complete: var_complete, var_revised: var_revised, var_fh: var_fh, var_sm: var_sm, var_others: var_others }
end

.services_data(dates, report_type) ⇒ Object



577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
# File 'app/services/report/lead_report/lead_report.rb', line 577

def self.services_data(dates, report_type)
  select_sql = 'select * from result_by_pl' if report_type == 1
  select_sql = 'select * from result_by_date' if report_type == 2
  start_date = dates[:date_from].years_ago(1)
  end_date = dates[:date_to].years_ago(1)

  sql = <<-SQL
      with current_period as (
          select (week_id::varchar || extract(dow from dt2.date)::varchar)::int as date_id,dt2.date as c_date
          from (
              select (row_number() over (ORDER BY a.week_num))::int as week_id,week_num
              from (
                  select distinct extract(week from dt1.date) as week_num
                  from analytic_date_time_dimensions dt1
                  where dt1.date between '#{dates[:date_from]}' and '#{dates[:date_to]}'
                  and weekend = 'Weekday'
                  order by 1
              )a
          )b
          inner join analytic_date_time_dimensions dt2 on b.week_num = extract(week from dt2.date)
          where weekend = 'Weekday'
          and dt2.date between '#{dates[:date_from]}' and '#{dates[:date_to]}'

      ), previous_period as (
          select (week_id::varchar || extract(dow from dt2.date)::varchar)::int as date_id,dt2.date as p_date
          from (
              select (row_number() over (ORDER BY a.week_num))::int as week_id,week_num
              from (
                  select distinct extract(week from dt1.date) as week_num
                  from analytic_date_time_dimensions dt1
                  where dt1.date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}'
                  and weekend = 'Weekday'
                  order by 1
              )a
          )b
          inner join analytic_date_time_dimensions dt2 on b.week_num = extract(week from dt2.date)
          where weekend = 'Weekday'
          and dt2.date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}'

      ), periods as (
          select cp.date_id,c_date,p_date
          from current_period cp
          inner join previous_period pp on cp.date_id = pp.date_id

      ), sales_by_date as (
          select gl_date,sum(qty_shipped) as qty,sum(qty_shipped * discounted_price * consolidated_exchange_rate) as amount
          from invoices iv
          inner join line_items li on iv.id = li.resource_id and li.resource_type = 'Invoice'
          inner join items i on li.item_id = i.id
          inner join product_lines pl on i.primary_product_line_id = pl.id
          where pl.parent_id = 88
          and iv.state not in ('draft','requested')
          and (gl_date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}' or gl_date between '#{dates[:date_from]}' and '#{dates[:date_to]}')
          group by gl_date

      ), pl as (
          select id,name
          from product_lines
          where parent_id = 88

      ), sales_by_pl as (
          select primary_product_line_id,
              case when gl_date between '#{dates[:date_from]}' and '#{dates[:date_to]}' then sum(qty_shipped * discounted_price * consolidated_exchange_rate) else 0 end cur_amount,
              case when gl_date between '#{start_date}' and '#{end_date}' then sum(qty_shipped * discounted_price * consolidated_exchange_rate) else 0 end prev_amount
          from invoices iv
          inner join line_items li on iv.id = li.resource_id and li.resource_type = 'Invoice'
          inner join items i on li.item_id = i.id
          inner join product_lines pl on i.primary_product_line_id = pl.id
          where pl.parent_id = 88
          and iv.state not in ('draft','requested')
          and (gl_date between '#{start_date}' and '#{end_date}' or gl_date between '#{dates[:date_from]}' and '#{dates[:date_to]}')
          group by gl_date,primary_product_line_id

      ), result_by_date as (
          select c_date,coalesce(sc.qty,0) as c_qty,coalesce(sc.amount,0) as c_amount,p_date,coalesce(sp.qty,0) as p_qty,coalesce(sp.amount,0) as p_amount
          from periods p
          left join sales_by_date sc on p.c_date = sc.gl_date
          left join sales_by_date sp on p.p_date = sp.gl_date
          order by c_date

      ), result_by_pl as (
          select id,name,sum(coalesce(cur_amount,0)) as cur_amount,sum(coalesce(prev_amount,0)) as prev_amount,(sum(coalesce(cur_amount,0)) - sum(coalesce(prev_amount,0))) as var
          from pl
          left join sales_by_pl on pl.id = sales_by_pl.primary_product_line_id
          group by id,name

      )
      #{select_sql};
  SQL

  results = ActiveRecord::Base.connection.execute(sql).to_a.map { |r| r.symbolize_keys }
end

.sms_data(dates) ⇒ Object



921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
# File 'app/services/report/lead_report/lead_report.rb', line 921

def self.sms_data(dates)
  sql = <<-SQL
      with current_period as (
          select (week_id::varchar || extract(dow from dt2.date)::varchar)::int as date_id,dt2.date as c_date
          from (
              select (row_number() over (ORDER BY a.week_num))::int as week_id,week_num
              from (
                  select distinct extract(week from dt1.date) as week_num
                  from analytic_date_time_dimensions dt1
                  where dt1.date between '#{dates[:date_from]}' and '#{dates[:date_to]}'
                  and weekend = 'Weekday'
                  order by 1
              )a
          )b
          inner join analytic_date_time_dimensions dt2 on b.week_num = extract(week from dt2.date)
          where weekend = 'Weekday'
          and dt2.date between '#{dates[:date_from]}' and '#{dates[:date_to]}'

      ), previous_period as (
          select (week_id::varchar || extract(dow from dt2.date)::varchar)::int as date_id,dt2.date as p_date
          from (
              select (row_number() over (ORDER BY a.week_num))::int as week_id,week_num
              from (
                  select distinct extract(week from dt1.date) as week_num
                  from analytic_date_time_dimensions dt1
                  where dt1.date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}'
                  and weekend = 'Weekday'
                  order by 1
              )a
          )b
          inner join analytic_date_time_dimensions dt2 on b.week_num = extract(week from dt2.date)
          where weekend = 'Weekday'
          and dt2.date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}'

      ), periods as (
          select cp.date_id,c_date,p_date
          from current_period cp
          inner join previous_period pp on cp.date_id = pp.date_id

      ), sms_data as (
          select
          timezone('America/Chicago', timestamptz(created_at))::date as date,
          sum(case when state = 'received' then 1 else 0 end) as sms_received,
          sum(case when state = 'delivered' then 1 else 0 end) as sms_delivered
          from sms_messages
          where state in ('received','delivered')
          and ((timezone('America/Chicago', timestamptz(created_at))::date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}') or (timezone('America/Chicago', timestamptz(created_at))::date between '#{dates[:date_from]}' and '#{dates[:date_to]}'))
          group by timezone('America/Chicago', timestamptz(created_at))

      ), sms_result as (
          select c_date,coalesce(s1.sms_received,0) as c_sms_received,coalesce(s1.sms_delivered,0) as c_sms_delivered,
              p_date,coalesce(s2.sms_received,0) as p_sms_received,coalesce(s2.sms_delivered,0) as p_sms_delivered
          from periods p
          left join sms_data s1 on p.c_date = s1.date
          left join sms_data s2 on p.p_date = s2.date
      )
      select c_date,sum(c_sms_received) as c_sms_received,sum(c_sms_delivered) as c_sms_delivered,
             p_date,sum(p_sms_received) as p_sms_received,sum(p_sms_delivered) as p_sms_delivered
      from sms_result
      group by c_date,p_date;
  SQL

  results = ActiveRecord::Base.connection.execute(sql).to_a.map { |r| r.symbolize_keys }
end

.sms_totals(data) ⇒ Object



986
987
988
989
990
991
992
993
994
995
996
997
# File 'app/services/report/lead_report/lead_report.rb', line 986

def self.sms_totals(data)
  num_days = data.map { |i| i[:c_date].to_i }.count
  ttlc_received = data.map { |i| i[:c_sms_received].to_i }.sum
  ttlc_delivered = data.map { |i| i[:c_sms_delivered].to_i }.sum
  ttlp_received = data.map { |i| i[:p_sms_received].to_i }.sum
  ttlp_delivered = data.map { |i| i[:p_sms_delivered].to_i }.sum

  var_received = ttlp_received.zero? ? 0.0 : (((ttlc_received.to_f - ttlp_received.to_f) / ttlp_received.to_f) * 100)
  var_delivered = ttlp_delivered.zero? ? 0.0 : (((ttlc_delivered.to_f - ttlp_delivered.to_f) / ttlp_delivered.to_f) * 100)
  { ttlc_received: ttlc_received, ttlc_delivered: ttlc_delivered, ttlp_received: ttlp_received,
                 ttlp_delivered: ttlp_delivered, var_received: var_received, var_delivered: var_delivered }
end

.website_visits_data(dates, report_type) ⇒ Object



999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
# File 'app/services/report/lead_report/lead_report.rb', line 999

def self.website_visits_data(dates, report_type)
  select_sql = 'select * from visits_result' if report_type == 1
  select_sql = 'select * from traffic_result' if report_type == 2

  sql = <<-SQL
      with current_period as (
          select (week_id::varchar || extract(dow from dt2.date)::varchar)::int as date_id,dt2.date as c_date
          from (
              select (row_number() over (ORDER BY a.week_num))::int as week_id,week_num
              from (
                  select distinct extract(week from dt1.date) as week_num
                  from analytic_date_time_dimensions dt1
                  where dt1.date between '#{dates[:date_from]}' and '#{dates[:date_to]}'
                  and weekend = 'Weekday'
                  order by 1
              )a
          )b
          inner join analytic_date_time_dimensions dt2 on b.week_num = extract(week from dt2.date)
          and dt2.date between '#{dates[:date_from]}' and '#{dates[:date_to]}'

      ), previous_period as (
          select (week_id::varchar || extract(dow from dt2.date)::varchar)::int as date_id,dt2.date as p_date
          from (
              select (row_number() over (ORDER BY a.week_num))::int as week_id,week_num
              from (
                  select distinct extract(week from dt1.date) as week_num
                  from analytic_date_time_dimensions dt1
                  where dt1.date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}'
                  and weekend = 'Weekday'
                  order by 1
              )a
          )b
          inner join analytic_date_time_dimensions dt2 on b.week_num = extract(week from dt2.date)
          and dt2.date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}'

      ), periods as (
          select cp.date_id,c_date,p_date
          from current_period cp
          inner join previous_period pp on cp.date_id = pp.date_id

      ), visits as (
          select
          visit_date,
          sum(number_visits) as visits,
          sum(case when country_code = 'us' then number_visits else 0 end) as us_visits,
          sum(case when country_code = 'ca' then number_visits else 0 end) as ca_visits
          from view_visits_facts
          where ((visit_date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}') or (visit_date between '#{dates[:date_from]}' and '#{dates[:date_to]}'))
          group by visit_date

      ), visits_result as (
          select c_date,v1.visits as c_visits,v1.us_visits as c_us_visits,v1.ca_visits as c_ca_visits,
              p_date,v2.visits as p_visits,v2.us_visits as p_us_visits,v2.ca_visits as p_ca_visits
          from periods p
          left join visits v1 on p.c_date = v1.visit_date
          left join visits v2 on p.p_date = v2.visit_date
          order by c_date

      ), traffic as (
          select visit_date,
          sum(case when code = 1 then values else 0 end) as campaign,
          sum(case when code = 12 then values else 0 end) as campaignppc,
          sum(case when code = 4 then values else 0 end) as organic,
          sum(case when code = 2 then values else 0 end) as direct,
          sum(case when code = 3 then values else 0 end) as referral
          from view_visits_detail_facts
          where ((visit_date between '#{dates[:date_from_prev]}' and '#{dates[:date_to_prev]}') or (visit_date between '#{dates[:date_from]}' and '#{dates[:date_to]}'))
          and code in (1,2,3,4,12)
          group by visit_date

      ), traffic_result as (
          select c_date,t1.campaign as c_campaign,t1.campaignppc as c_campaignppc,t1.organic as c_organic,t1.direct as c_direct,t1.referral as c_referral,
              p_date,t2.campaign as p_campaign,t2.campaignppc as p_campaignppc,t2.organic as p_organic,t2.direct as p_direct,t2.referral as p_referral
          from periods p
          left join traffic t1 on p.c_date = t1.visit_date
          left join traffic t2 on p.p_date = t2.visit_date
          order by c_date
      )
      #{select_sql};
  SQL

  results = ActiveRecord::Base.connection.execute(sql).to_a.map { |r| r.symbolize_keys }
end

.website_visits_totals(data) ⇒ Object



1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
# File 'app/services/report/lead_report/lead_report.rb', line 1083

def self.website_visits_totals(data)
  num_days = data.map { |i| i[:c_date].to_i }.count
  ttlc_visits = data.map { |i| i[:c_visits].to_i }.sum
  ttlc_us_visits = data.map { |i| i[:c_us_visits].to_i }.sum
  ttlc_ca_visits = data.map { |i| i[:c_ca_visits].to_i }.sum
  ttlp_visits = data.map { |i| i[:p_visits].to_i }.sum
  ttlp_us_visits = data.map { |i| i[:p_us_visits].to_i }.sum
  ttlp_ca_visits = data.map { |i| i[:p_ca_visits].to_i }.sum

  var_visits = ttlp_visits.zero? ? 0.0 : (((ttlc_visits.to_f - ttlp_visits.to_f) / ttlp_visits.to_f) * 100)
  var_us_visits = ttlp_us_visits.zero? ? 0.0 : (((ttlc_us_visits.to_f - ttlp_us_visits.to_f) / ttlp_us_visits.to_f) * 100)
  var_ca_visits = ttlp_ca_visits.zero? ? 0.0 : (((ttlc_ca_visits.to_f - ttlp_ca_visits.to_f) / ttlp_ca_visits.to_f) * 100)
  { ttlc_visits: ttlc_visits, ttlc_us_visits: ttlc_us_visits, ttlc_ca_visits: ttlc_ca_visits,
                            ttlp_visits: ttlp_visits, ttlp_us_visits: ttlp_us_visits, ttlp_ca_visits: ttlp_ca_visits,
                            var_visits: var_visits, var_us_visits: var_us_visits, var_ca_visits: var_ca_visits }
end