Skip to content
Merged
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
102 changes: 102 additions & 0 deletions app/jobs/reports/irs_verification_demographics_report.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# frozen_string_literal: true

require 'csv'
require 'reporting/irs_verification_demographics_report'

module Reports
class IrsVerificationDemographicsReport < BaseReport
REPORT_NAME = 'irs-verification-demographics-report'

attr_reader :report_date

def initialize(report_date = nil, *args, **rest)
@report_date = report_date
super(*args, **rest)
end

def perform(date = Time.zone.yesterday.end_of_day)
@report_date = date

email_addresses = emails.select(&:present?)
if email_addresses.empty?
Rails.logger.warn 'No email addresses - IRS Verification Demographics Report NOT SENT'
return false
end

reports.each do |report|
upload_to_s3(report.table, report_name: report.filename)
end

ReportMailer.tables_report(
email: email_addresses,
subject: "IRS Verification Demographics Metrics Report - #{report_date.to_date}",
reports: reports,
message: preamble,
attachment_format: :csv,
).deliver_now
end

# Explanatory text to go before the report in the email
# @return [String]
def preamble(env: Identity::Hostdata.env || 'local')
ERB.new(<<~ERB).result(binding).html_safe # rubocop:disable Rails/OutputSafety
<% if env != 'prod' %>
<div class="usa-alert usa-alert--info usa-alert--email">
<div class="usa-alert__body">
<%#
NOTE: our AlertComponent doesn't support heading content like this uses,
so for a one-off outside the Rails pipeline it was easier to inline the HTML here.
%>
<h2 class="usa-alert__heading">
Non-Production Report
</h2>
<p class="usa-alert__text">
This was generated in the <strong><%= env %></strong> environment.
</p>
</div>
</div>
<% end %>
ERB
end

def reports
@reports ||= irs_verification_demographics_report.as_emailable_reports
end

def irs_verification_demographics_report
@irs_verification_demographics_report ||= Reporting::IrsVerificationDemographicsReport.new(
issuers: issuers,
time_range: report_date.all_quarter,
)
end

def issuers
[*IdentityConfig.store.irs_verification_report_issuers]
end

def emails
[*IdentityConfig.store.irs_verification_report_config]
end

def upload_to_s3(report_body, report_name: nil)
_latest, path = generate_s3_paths(REPORT_NAME, 'csv', subname: report_name, now: report_date)

if bucket_name.present?
upload_file_to_s3_bucket(
path: path,
body: csv_file(report_body),
content_type: 'text/csv',
bucket: bucket_name,
)
end
end

def csv_file(report_array)
CSV.generate do |csv|
report_array.each do |row|
csv << row
end
end
end
end
end
7 changes: 7 additions & 0 deletions config/initializers/job_configurations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
cron_every_monday_1am = 'every Monday at 1:00 UTC' # equivalent to '0 1 * * 1'
cron_every_monday_2am = 'every Monday at 2:00 UTC' # equivalent to '0 2 * * 1'
cron_monthly = '30 0 1 * *' # monthly, 0:30 UTC to not overlap with jobs running at 0000
cron_quarterly = '0 0 1 1,4,7,10 *' # quarterly
s3_cron_24h = '0 6 * * *' # 6am UTC is 1am EST/2am EDT

if defined?(Rails::Console)
Expand Down Expand Up @@ -291,6 +292,12 @@
cron: cron_monthly,
args: -> { [Time.zone.yesterday.end_of_day] },
},
# Send irs quarterly metrics to Team Data
irs_verification_demographics_report: {
class: 'Reports::IrsVerificationDemographicsReport',
cron: cron_quarterly,
args: -> { [Time.zone.yesterday.end_of_day] },
},
# Download and store Socure reason codes
socure_reason_code_download: {
class: 'SocureReasonCodeDownloadJob',
Expand Down
30 changes: 15 additions & 15 deletions docs/attempts-api/schemas/events/IdentityProofingEvents.yml
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
properties:
idv-address-submitted:
$ref: "./identity-proofing/IdvAddressSubmitted.yml"
$ref: './identity-proofing/IdvAddressSubmitted.yml'
idv-document-uploaded:
$ref: "./identity-proofing/IdvDocumentUploaded.yml"
$ref: './identity-proofing/IdvDocumentUploaded.yml'
idv-document-upload-submitted:
$ref: "./identity-proofing/IdvDocumentUploadSubmitted.yml"
$ref: './identity-proofing/IdvDocumentUploadSubmitted.yml'
idv-enrollment-complete:
$ref: "./identity-proofing/IdvEnrollmentComplete.yml"
$ref: './identity-proofing/IdvEnrollmentComplete.yml'
idv-ipp-ready-to-verify-visit:
$ref: "./identity-proofing/IdvIppReadyToVerifyVisit.yml"
$ref: './identity-proofing/IdvIppReadyToVerifyVisit.yml'
idv-phone-otp-sent:
$ref: "./identity-proofing/IdvPhoneOtpSent.yml"
$ref: './identity-proofing/IdvPhoneOtpSent.yml'
idv-phone-otp-submitted:
$ref: "./identity-proofing/IdvPhoneOtpSubmitted.yml"
$ref: './identity-proofing/IdvPhoneOtpSubmitted.yml'
idv-phone-submitted:
$ref: "./identity-proofing/IdvPhoneSubmitted.yml"
$ref: './identity-proofing/IdvPhoneSubmitted.yml'
idv-rate-limited:
$ref: "./identity-proofing/IdvRateLimited.yml"
$ref: './identity-proofing/IdvRateLimited.yml'
idv-reproof:
$ref: "./identity-proofing/IdvReproof.yml"
$ref: './identity-proofing/IdvReproof.yml'
idv-ssn-submitted:
$ref: "./identity-proofing/IdvSsnSubmitted.yml"
$ref: './identity-proofing/IdvSsnSubmitted.yml'
idv-device-risk-assessment:
$ref: "./identity-proofing/IdvDeviceRiskAssessment.yml"
$ref: './identity-proofing/IdvDeviceRiskAssessment.yml'
idv-verification-submitted:
$ref: "./identity-proofing/IdvVerificationSubmitted.yml"
$ref: './identity-proofing/IdvVerificationSubmitted.yml'
idv-verify-by-mail-letter-requested:
$ref: "./identity-proofing/IdvVerifyByMailLetterRequested.yml"
$ref: './identity-proofing/IdvVerifyByMailLetterRequested.yml'
idv-verify-by-mail-enter-code-submitted:
$ref: "./identity-proofing/IdvVerifyByMailEnterCodeSubmitted.yml"
$ref: './identity-proofing/IdvVerifyByMailEnterCodeSubmitted.yml'
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
description: |
This event captures the result of the Device Risk Assessment during Identity Verification.
allOf:
- $ref: "../shared/EventProperties.yml"
- $ref: '../shared/EventProperties.yml'
- type: object
properties:
failure_reason:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ description: |
Therefore, document upload failed.
These image file names and encryption keys are invalid, and are not saved in the document escrow.
allOf:
- $ref: "../shared/EventProperties.yml"
- $ref: '../shared/EventProperties.yml'
- type: object
properties:
document_front_image_file_id:
type: string
description: If this image existed, the ID generated for storage
description: If this image existed, the ID generated for storage
document_back_image_file_id:
type: string
description: If this image existed, the ID generated for storage
description: If this image existed, the ID generated for storage
document_selfie_image_file_id:
type: string
description: If this image existed, the ID generated for storage
description: If this image existed, the ID generated for storage
document_front_image_encryption_key:
type: string
description: Randomly generated Base64-encoded key generated to encrypt the front image file if it exists.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
description: |
When the user verifies their information when identity proofing.
allOf:
- $ref: "../shared/EventProperties.yml"
- $ref: '../shared/EventProperties.yml'
- type: object
properties:
document_state:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ properties:
format: float64
description: The time when the event occurred.
subject:
$ref: "./Subject.yml"
$ref: './Subject.yml'
useragent_string:
type: string
description: The end user's browser's useragent string, which identifies the type of browser, device and operating system being used as well as the version of the browser.
Expand Down
Loading