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 =
Tz.
'America/Chicago'- ENV_LOOKBACK_HOURS =
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 ⇒ AccountDailyActivityReport
Report over the previous calendar day in America/Chicago.
-
.for_scheduled_run ⇒ AccountDailyActivityReport
Report for the scheduled daily run: a rolling window when
ACCOUNT_ACTIVITY_REPORT_LOOKBACK_HOURSis set, otherwise calendar yesterday. -
.lookback_hours_from_env ⇒ Integer?
Lookback window from the
ACCOUNT_ACTIVITY_REPORT_LOOKBACK_HOURSenv var. -
.rolling_hours(hours) ⇒ AccountDailyActivityReport
Report over a rolling window of the last
hourshours ending now.
Instance Method Summary collapse
-
#accounts_created ⇒ ActiveRecord::Relation<Account>
Accounts created inside the reporting window, oldest first.
-
#accounts_created_by_group ⇒ Hash{Symbol => Array<Account>}
Split: WWW = customer site (Customer party), CRM = employee app (Employee party).
-
#initialize(date: nil, range: nil, rolling_hours: nil) ⇒ void
constructor
Builds a report for either a single calendar date or an explicit range.
-
#login_events ⇒ ActiveRecord::Relation<LoginActivity>
Per-event sign-in attempts (success + failure) recorded by AuthTrail in
login_activities. -
#login_events_by_group ⇒ Hash{Symbol => Hash{Symbol => Array<LoginActivity>}}
Bucket every LoginActivity row in the window by audience and outcome:.
Constructor Details
#initialize(date: nil, range: nil, rolling_hours: nil) ⇒ void
Builds a report for either a single calendar date or an explicit range.
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'app/services/account_daily_activity_report.rb', line 21 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.
13 14 15 |
# File 'app/services/account_daily_activity_report.rb', line 13 def date @date end |
#rolling_hours ⇒ Object (readonly)
Returns the value of attribute rolling_hours.
13 14 15 |
# File 'app/services/account_daily_activity_report.rb', line 13 def rolling_hours @rolling_hours end |
#window_end ⇒ Object (readonly)
Returns the value of attribute window_end.
13 14 15 |
# File 'app/services/account_daily_activity_report.rb', line 13 def window_end @window_end end |
#window_start ⇒ Object (readonly)
Returns the value of attribute window_start.
13 14 15 |
# File 'app/services/account_daily_activity_report.rb', line 13 def window_start @window_start end |
Class Method Details
.calendar_yesterday ⇒ AccountDailyActivityReport
Report over the previous calendar day in America/Chicago.
61 62 63 64 |
# File 'app/services/account_daily_activity_report.rb', line 61 def self.calendar_yesterday tz = ActiveSupport::TimeZone[TZ] new(date: tz.now.to_date - 1) end |
.for_scheduled_run ⇒ AccountDailyActivityReport
Report for the scheduled daily run: a rolling window when
ACCOUNT_ACTIVITY_REPORT_LOOKBACK_HOURS is set, otherwise calendar yesterday.
41 42 43 44 45 46 47 48 |
# File 'app/services/account_daily_activity_report.rb', line 41 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 ⇒ Integer?
Lookback window from the ACCOUNT_ACTIVITY_REPORT_LOOKBACK_HOURS env var.
68 69 70 71 72 73 74 75 |
# File 'app/services/account_daily_activity_report.rb', line 68 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) ⇒ AccountDailyActivityReport
Report over a rolling window of the last hours hours ending now.
53 54 55 56 57 |
# File 'app/services/account_daily_activity_report.rb', line 53 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 ⇒ ActiveRecord::Relation<Account>
Accounts created inside the reporting window, oldest first.
79 80 81 |
# File 'app/services/account_daily_activity_report.rb', line 79 def accounts_created Account.includes(:party).where(created_at: window_start..window_end).order(:id) end |
#accounts_created_by_group ⇒ Hash{Symbol => Array<Account>}
Split: WWW = customer site (Customer party), CRM = employee app (Employee party).
93 94 95 |
# File 'app/services/account_daily_activity_report.rb', line 93 def accounts_created_by_group split_by_www_crm(accounts_created) end |
#login_events ⇒ ActiveRecord::Relation<LoginActivity>
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.
87 88 89 |
# File 'app/services/account_daily_activity_report.rb', line 87 def login_events LoginActivity.where(created_at: window_start..window_end).order(:created_at) end |
#login_events_by_group ⇒ Hash{Symbol => Hash{Symbol => Array<LoginActivity>}}
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.
110 111 112 113 114 |
# File 'app/services/account_daily_activity_report.rb', line 110 def login_events_by_group events = login_events.to_a grouped = bucket_events(events, preload_accounts(events)) ensure_all_buckets(grouped) end |