Class: AccountDailyActivityReport
- Inherits:
-
Object
- Object
- AccountDailyActivityReport
- Defined in:
- app/services/account_daily_activity_report.rb
Overview
Reporting window for the sysadmin email:
- Production default: previous calendar day in America/Chicago.
- Optional local/test: set ACCOUNT_ACTIVITY_REPORT_LOOKBACK_HOURS=48 for a rolling window
ending at “now” in Chicago (e.g. dev DB snapshot testing).
Constant Summary collapse
- TZ =
rubocop:disable Metrics/ClassLength
'America/Chicago'- ENV_LOOKBACK_HOURS =
'ACCOUNT_ACTIVITY_REPORT_LOOKBACK_HOURS'
Instance Attribute Summary collapse
-
#date ⇒ Object
readonly
Returns the value of attribute date.
-
#rolling_hours ⇒ Object
readonly
Returns the value of attribute rolling_hours.
-
#window_end ⇒ Object
readonly
Returns the value of attribute window_end.
-
#window_start ⇒ Object
readonly
Returns the value of attribute window_start.
Class Method Summary collapse
- .calendar_yesterday ⇒ Object
- .for_scheduled_run ⇒ Object
- .lookback_hours_from_env ⇒ Object
- .rolling_hours(hours) ⇒ Object
Instance Method Summary collapse
- #accounts_created ⇒ Object
-
#accounts_created_by_group ⇒ Object
Split: WWW = customer site (Customer party), CRM = employee app (Employee party).
-
#initialize(date: nil, range: nil, rolling_hours: nil) ⇒ AccountDailyActivityReport
constructor
A new instance of AccountDailyActivityReport.
-
#login_events ⇒ Object
Per-event sign-in attempts (success + failure) recorded by AuthTrail in
login_activities. -
#login_events_by_group ⇒ Object
Bucket every LoginActivity row in the window by audience and outcome:.
Constructor Details
#initialize(date: nil, range: nil, rolling_hours: nil) ⇒ AccountDailyActivityReport
Returns a new instance of AccountDailyActivityReport.
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'app/services/account_daily_activity_report.rb', line 13 def initialize(date: nil, range: nil, rolling_hours: nil) tz = ActiveSupport::TimeZone[TZ] if range @window_start = range.begin.in_time_zone(tz) @window_end = range.end.in_time_zone(tz) @date = @window_start.to_date @rolling_hours = rolling_hours elsif date @date = date @window_start = tz.local(date.year, date.month, date.day).beginning_of_day @window_end = @window_start.end_of_day @rolling_hours = nil else raise ArgumentError, 'Provide date: or range:' end end |
Instance Attribute Details
#date ⇒ Object (readonly)
Returns the value of attribute date.
11 12 13 |
# File 'app/services/account_daily_activity_report.rb', line 11 def date @date end |
#rolling_hours ⇒ Object (readonly)
Returns the value of attribute rolling_hours.
11 12 13 |
# File 'app/services/account_daily_activity_report.rb', line 11 def rolling_hours @rolling_hours end |
#window_end ⇒ Object (readonly)
Returns the value of attribute window_end.
11 12 13 |
# File 'app/services/account_daily_activity_report.rb', line 11 def window_end @window_end end |
#window_start ⇒ Object (readonly)
Returns the value of attribute window_start.
11 12 13 |
# File 'app/services/account_daily_activity_report.rb', line 11 def window_start @window_start end |
Class Method Details
.calendar_yesterday ⇒ Object
45 46 47 48 |
# File 'app/services/account_daily_activity_report.rb', line 45 def self.calendar_yesterday tz = ActiveSupport::TimeZone[TZ] new(date: tz.now.to_date - 1) end |
.for_scheduled_run ⇒ Object
30 31 32 33 34 35 36 37 |
# File 'app/services/account_daily_activity_report.rb', line 30 def self.for_scheduled_run hours = lookback_hours_from_env if hours&.positive? rolling_hours(hours) else calendar_yesterday end end |
.lookback_hours_from_env ⇒ Object
50 51 52 53 54 55 56 57 |
# File 'app/services/account_daily_activity_report.rb', line 50 def self.lookback_hours_from_env v = ENV[ENV_LOOKBACK_HOURS].to_s.strip return nil if v.blank? Integer(v) rescue ArgumentError, TypeError nil end |
.rolling_hours(hours) ⇒ Object
39 40 41 42 43 |
# File 'app/services/account_daily_activity_report.rb', line 39 def self.rolling_hours(hours) tz = ActiveSupport::TimeZone[TZ] now = tz.now new(range: (now - hours.hours)..now, rolling_hours: hours) end |
Instance Method Details
#accounts_created ⇒ Object
59 60 61 |
# File 'app/services/account_daily_activity_report.rb', line 59 def accounts_created Account.includes(:party).where(created_at: window_start..window_end).order(:id) end |
#accounts_created_by_group ⇒ Object
Split: WWW = customer site (Customer party), CRM = employee app (Employee party).
71 72 73 |
# File 'app/services/account_daily_activity_report.rb', line 71 def accounts_created_by_group split_by_www_crm(accounts_created) end |
#login_events ⇒ Object
Per-event sign-in attempts (success + failure) recorded by AuthTrail
in login_activities. Replaces the previous Devise current_sign_in_at
snapshot, which collapsed multi-login days into a single row per account.
66 67 68 |
# File 'app/services/account_daily_activity_report.rb', line 66 def login_events LoginActivity.where(created_at: window_start..window_end).order(:created_at) end |
#login_events_by_group ⇒ Object
Bucket every LoginActivity row in the window by audience and outcome:
{
www: { success: [...], failure: [...] },
crm: { success: [...], failure: [...] },
other: { success: [...], failure: [...] }, # Account exists but party is neither Customer nor Employee
unmatched: { success: [...], failure: [...] }, # No Account row matched (typical for failed attempts)
}
Each event also carries a memoised :account (or nil) and :party
(or nil) on the row's instance_variable_get(:@report_*) shims so the
mailer view can render them without re-querying.
87 88 89 90 91 |
# File 'app/services/account_daily_activity_report.rb', line 87 def login_events_by_group events = login_events.to_a grouped = bucket_events(events, preload_accounts(events)) ensure_all_buckets(grouped) end |