app/services/reporting/active_users_count_report.rb
# frozen_string_literal: true
module Reporting
class ActiveUsersCountReport
attr_reader :report_date
def initialize(report_date = Time.zone.today)
@report_date = report_date
end
def active_users_count_emailable_report
EmailableReport.new(
title: 'Active Users',
table: generate_report,
filename: 'active_users_count',
)
end
def active_users_count_apg_emailable_report
EmailableReport.new(
title: 'Active Users (APG)',
table: generate_apg_report,
filename: 'active_users_count_apg',
)
end
class ReportRow
# hash comes from Db::Identity::SpActiveUserCounts.overall
def self.from_hash_time_range(hash:, time_range:)
new(
ial1: hash['total_ial1_active'],
idv: hash['total_ial2_active'],
time_range:,
)
end
attr_reader :ial1, :idv, :time_range
def initialize(ial1:, idv:, time_range:)
@ial1 = ial1
@idv = idv
@time_range = time_range
end
def as_csv(title:)
[
title,
ial1,
idv,
ial1 + idv,
time_range.begin.to_date,
time_range.end.to_date,
]
end
end
private
def generate_report
q1, q2, q3, q4 = fiscal_year_active_users_per_quarter_cumulative
[
['Active Users', 'IAL1', 'IDV', 'Total', 'Range start', 'Range end'],
monthly_active_users.as_csv(title: 'Current month'),
q1.as_csv(title: 'Fiscal year Q1'),
q2.as_csv(title: 'Fiscal year Q2 cumulative'),
q3.as_csv(title: 'Fiscal year Q3 cumulative'),
q4.as_csv(title: 'Fiscal year Q4 cumulative'),
]
end
def generate_apg_report
q1, q2, q3, q4 = apg_fiscal_year_active_users_per_quarter_cumulative
[
['Active Users (APG)', 'IAL1', 'IDV', 'Total', 'Range start', 'Range end'],
monthly_active_users_apg.as_csv(title: 'Current month'),
q1.as_csv(title: 'Fiscal year Q1'),
q2.as_csv(title: 'Fiscal year Q2 cumulative'),
q3.as_csv(title: 'Fiscal year Q3 cumulative'),
q4.as_csv(title: 'Fiscal year Q4 cumulative'),
]
end
# @return [ReportRow]
def monthly_active_users
@monthly_active_users ||= Reports::BaseReport.transaction_with_timeout do
ReportRow.from_hash_time_range(
time_range: monthly_range,
hash: Db::Identity::SpActiveUserCounts.overall(
monthly_range.begin,
monthly_range.end,
).first,
)
end
end
# @return [ReportRow]
def monthly_active_users_apg
@monthly_active_users_apg ||= Reports::BaseReport.transaction_with_timeout do
ReportRow.from_hash_time_range(
time_range: monthly_range,
hash: Db::Identity::SpActiveUserCounts.overall_apg(
monthly_range.begin,
monthly_range.end,
).first,
)
end
end
# @return [Array<ReportRow>]
def fiscal_year_active_users_per_quarter_cumulative
@fiscal_year_active_users_per_quarter_cumulative ||= begin
data_by_quarter = {}
cumulative_quarter_ranges.
map do |quarter_range|
data_by_quarter[quarter_range] ||= Reports::BaseReport.transaction_with_timeout do
ReportRow.from_hash_time_range(
time_range: quarter_range,
hash: Db::Identity::SpActiveUserCounts.overall(
quarter_range.begin,
quarter_range.end,
).first,
)
end
end
end
end
# @return [Array<ReportRow>]
def apg_fiscal_year_active_users_per_quarter_cumulative
@apg_fiscal_year_active_users_per_quarter_cumulative ||= begin
data_by_quarter = {}
cumulative_quarter_ranges.
map do |quarter_range|
data_by_quarter[quarter_range] ||= Reports::BaseReport.transaction_with_timeout do
ReportRow.from_hash_time_range(
time_range: quarter_range,
hash: Db::Identity::SpActiveUserCounts.overall_apg(
quarter_range.begin,
quarter_range.end,
).first,
)
end
end
end
end
# rubocop:disable Layout/LineLength
# @return [Array<Range<Time>>]
def cumulative_quarter_ranges
[
CalendarService.fiscal_start_date(report_date)..CalendarService.fiscal_q2_start(report_date),
CalendarService.fiscal_start_date(report_date)..CalendarService.fiscal_q3_start(report_date),
CalendarService.fiscal_start_date(report_date)..CalendarService.fiscal_q4_start(report_date),
CalendarService.fiscal_start_date(report_date)..CalendarService.fiscal_end_date(report_date).next_day(1),
].map do |range|
range.begin.in_time_zone('UTC').beginning_of_day..([range.end.prev_day(1).in_time_zone('UTC').end_of_day, report_date.in_time_zone('UTC')].min)
end
end
# rubocop:enable Layout/LineLength
def monthly_range
report_date.all_month
end
def fiscal_start_date
CalendarService.fiscal_start_date(report_date)
end
def fiscal_end_date
CalendarService.fiscal_end_date(report_date)
end
end
end