Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 178 additions & 0 deletions lib/tasks/hbx_reports/active_sep_report.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# frozen_string_literal: true

require 'csv'
# RAILS_ENV=production bundle exec rake reports:active_sep_report start_date="2026-01-01" end_date="2026-03-18"
namespace :reports do
desc "Person Details report for people with active IVL SEPs"
task :active_sep_report => :environment do

start_date_str = ENV['start_date'].to_s.strip
end_date_str = ENV['end_date'].to_s.strip
start_date = Date.strptime(start_date_str, '%Y-%m-%d') if start_date_str.present?
end_date = Date.strptime(end_date_str, '%Y-%m-%d') if end_date_str.present?

if start_date.blank? || end_date.blank?
puts "Please provide start_date and end_date in YYYY-MM-DD format."
puts 'Example: bundle exec rake reports:active_sep_report start_date="2026-01-01" end_date="2026-03-18"'
exit
end

file_name = "#{Rails.root}/active_sep_report_#{start_date.strftime('%Y%m%d')}_#{end_date.strftime('%Y%m%d')}.csv"
puts "Generating Active SEP Report: #{file_name}" unless Rails.env.test?

ivl_qle_ids = QualifyingLifeEventKind.individual_market_events.map(&:id) +
QualifyingLifeEventKind.individual_market_non_self_attested_events.map(&:id)

families = Family.where(
:special_enrollment_periods => {
'$elemMatch' => {
:start_on.lte => end_date,
:end_on.gte => start_date,
:qualifying_life_event_kind_id.in => ivl_qle_ids
}
}
).order_by(:_id.asc)

total_count = families.count
count = 0
batch_size = 500
offset = 0

CSV.open(file_name, "w") do |csv|
csv << [
"Family HBX ID",
"Primary HBX ID",
"Consumer HBX ID",
"Consumer Name",
"Email Address",
"AI/AN Indicator",
"Tribe State",
"Tribe Name",
"Phone Number",
"Home Address",
"Mailing Address",
"Contact Method",
"Household Size",
"Name of SEP Used",
"SEP Start Date",
"SEP End Date",
"Plan Type",
"Carrier",
"Plan Title",
"Net Annual Income",
"Is Broker Assisted",
"Broker Name"
]

while offset < total_count
families.no_timeout.offset(offset).limit(batch_size).each do |family|

person = family.primary_person
next unless person.present?

active_seps = family.special_enrollment_periods.select do |sep|
sep.start_on.present? &&
sep.end_on.present? &&
sep.start_on <= end_date &&
sep.end_on >= start_date &&
ivl_qle_ids.include?(sep.qualifying_life_event_kind_id)
end

next if active_seps.blank?

primary_hbx_id = person.hbx_id
family_hbx_id = family.hbx_assigned_id
household_size = family.active_family_members.count

# Enrollment info (latest active IVL enrollment for the family)
latest_enrollment = family.hbx_enrollments
.individual_market
.where(:aasm_state.in => HbxEnrollment::ENROLLED_AND_RENEWAL_STATUSES)
.order_by(created_at: :desc)
.first

plan_type = latest_enrollment&.product&.kind&.to_s
carrier = latest_enrollment&.product&.issuer_profile&.legal_name
plan_title = latest_enrollment&.product&.title

# Net annual income from latest determined FA application
net_annual_income = nil
if ::EnrollRegistry.feature_enabled?(:financial_assistance)
latest_app = ::FinancialAssistance::Application.where(
family_id: family.id,
aasm_state: 'determined'
).order_by(submitted_at: :desc).first

if latest_app.present?
primary_applicant = latest_app.primary_applicant
net_annual_income = primary_applicant&.net_annual_income&.to_f
end
end

# Broker info
broker_account = family.active_broker_agency_account
is_broker_assisted = broker_account.present? ? "Yes" : "No"
broker_name = broker_account&.writing_agent&.person&.full_name

family.active_family_members.each do |family_member|
consumer = family_member.person
next unless consumer.present?

# Consumer level details
consumer_hbx_id = consumer.hbx_id
consumer_name = consumer.full_name
email = consumer.home_email&.address || consumer.emails&.first&.address
ai_an = consumer.indian_tribe_member ? "Yes" : "No"
tribe_state = consumer.tribal_state
tribe_name = consumer.tribal_name
phone = consumer.work_phone_or_best

home_addr = consumer.home_address
home_address_str = ([home_addr.address_1, home_addr.address_2, home_addr.city, home_addr.state, home_addr.zip].compact.reject(&:blank?).join(', ') if home_addr)

mail_addr = consumer.has_mailing_address? ? consumer.addresses.detect { |a| a.kind == "mailing" } : nil
mailing_address_str = ([mail_addr.address_1, mail_addr.address_2, mail_addr.city, mail_addr.state, mail_addr.zip].compact.reject(&:blank?).join(', ') if mail_addr)

contact_method = consumer.consumer_role&.contact_method

active_seps.each do |sep|
csv << [
family_hbx_id,
primary_hbx_id,
consumer_hbx_id,
consumer_name,
email,
ai_an,
tribe_state,
tribe_name,
phone,
home_address_str,
mailing_address_str,
contact_method,
household_size,
sep.title,
sep.start_on&.strftime("%m/%d/%Y"),
sep.end_on&.strftime("%m/%d/%Y"),
plan_type,
carrier,
plan_title,
net_annual_income,
is_broker_assisted,
broker_name
]
end
end

count += 1
puts "#{count}/#{total_count} families processed at #{Time.now}" if count % 1000 == 0
rescue StandardError => e
puts "Error processing family #{family.hbx_id}: #{e.message}"

end
offset += batch_size
end
end

puts "***** Successfully generated report: #{file_name} ******" unless Rails.env.test?
end
end
Loading
Loading