diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index e61d481607d..a7a1200636e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -175,6 +175,7 @@ app/controllers/v1/post911_gi_bill_statuses_controller.rb @department-of-veteran app/controllers/v2/higher_level_reviews_controller.rb @department-of-veterans-affairs/benefits-decision-reviews-be @department-of-veterans-affairs/backend-review-group app/mailers/application_mailer.rb @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group app/mailers/ch31_submissions_report_mailer.rb @department-of-veterans-affairs/benefits-non-disability @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group +app/mailers/create_excel_files_mailer.rb @department-of-veterans-affairs/govcio-vfep-codereviewers @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group app/mailers/create_daily_spool_files_mailer.rb @department-of-veterans-affairs/my-education-benefits @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group app/mailers/create_staging_spool_files_mailer.rb @department-of-veterans-affairs/my-education-benefits @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group app/mailers/dependents_application_failure_mailer.rb @department-of-veterans-affairs/benefits-dependents-management @department-of-veterans-affairs/vfs-authenticated-experience-backend @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group @@ -242,6 +243,7 @@ app/models/eligible_data_class.rb @department-of-veterans-affairs/vfs-vaos @depa app/models/evss_claim_document.rb @department-of-veterans-affairs/benefits-management-tools-be @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group app/models/evss_claim.rb @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group app/models/evss_claims_sync_status_tracker.rb @department-of-veterans-affairs/benefits-management-tools-be @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group +app/models/excel_file_event.rb @department-of-veterans-affairs/govcio-vfep-codereviewers @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group app/models/expiry_scanner.rb @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group app/models/external_services_redis/status.rb @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group app/models/feature_toggle_event.rb @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group @@ -305,6 +307,7 @@ app/models/rate_limited_search.rb @department-of-veterans-affairs/va-api-enginee app/models/saml_request_tracker.rb @department-of-veterans-affairs/octo-identity app/models/saved_claim.rb @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group app/models/saved_claim/education_benefits/va_10203.rb @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group +app/models/saved_claim/education_benefits/va_10282.rb @department-of-veterans-affairs/govcio-vfep-codereviewers @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group app/models/saved_claim/disability_compensation.rb @department-of-veterans-affairs/Disability-Experience @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group app/models/saved_claim/dependency_claim.rb @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group app/models/session.rb @department-of-veterans-affairs/octo-identity @@ -1201,6 +1204,7 @@ spec/factories/education_career_counseling_claim_no_vet_information.rb @departme spec/factories/education_career_counseling_claim.rb @department-of-veterans-affairs/my-education-benefits @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group spec/factories/education_stem_automated_decisions.rb @department-of-veterans-affairs/my-education-benefits @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group spec/factories/eligible_data_classes.rb @department-of-veterans-affairs/vfs-vaos @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group +spec/factories/excel_file_events.rb @department-of-veterans-affairs/govcio-vfep-codereviewers @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group spec/factories/extract_statuses.rb @department-of-veterans-affairs/vfs-vaos @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group spec/factories/evss_claims.rb @department-of-veterans-affairs/vfs-authenticated-experience-backend @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group spec/factories/evss_intent_to_files.rb @department-of-veterans-affairs/Disability-Experience @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group @@ -1273,6 +1277,7 @@ spec/factories/user_verifications.rb @department-of-veterans-affairs/octo-identi spec/factories/va0993.rb @department-of-veterans-affairs/govcio-vfep-codereviewers @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group spec/factories/va0994.rb @department-of-veterans-affairs/govcio-vfep-codereviewers @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group spec/factories/va10203.rb @department-of-veterans-affairs/govcio-vfep-codereviewers @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group +spec/factories/va10282.rb @department-of-veterans-affairs/govcio-vfep-codereviewers @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group spec/factories/va1990e.rb @department-of-veterans-affairs/govcio-vfep-codereviewers @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group spec/factories/va1990n.rb @department-of-veterans-affairs/govcio-vfep-codereviewers @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group spec/factories/va1990.rb @department-of-veterans-affairs/govcio-vfep-codereviewers @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group @@ -1592,6 +1597,7 @@ spec/models/education_benefits_claim_spec.rb @department-of-veterans-affairs/my- spec/models/education_benefits_submission_spec.rb @department-of-veterans-affairs/my-education-benefits @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group spec/models/education_stem_automated_decision_spec.rb @department-of-veterans-affairs/my-education-benefits @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group spec/models/evss_claims_sync_status_tracker_spec.rb @department-of-veterans-affairs/vfs-authenticated-experience-backend @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group +spec/models/excel_file_event_spec.rb @department-of-veterans-affairs/govcio-vfep-codereviewers @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group spec/models/external_services_redis @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group spec/models/folder_spec.rb @department-of-veterans-affairs/vfs-vaos @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group spec/models/form1010cg @department-of-veterans-affairs/vfs-10-10 @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group @@ -1852,6 +1858,7 @@ spec/support/database_cleaner.rb @department-of-veterans-affairs/va-api-engineer spec/support/default_configuration_helper.rb @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group spec/support/disability_compensation_form @department-of-veterans-affairs/Disability-Experience @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group spec/support/error_details.rb @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group +spec/support/excel_helpers.rb @department-of-veterans-affairs/govcio-vfep-codereviewers @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group spec/support/factory_bot.rb @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group spec/support/fake_api_key_for_lighthouse.txt @department-of-veterans-affairs/backend-review-group spec/support/financial_status_report_helpers.rb @department-of-veterans-affairs/vsa-debt-resolution @department-of-veterans-affairs/backend-review-group diff --git a/Gemfile.lock b/Gemfile.lock index a1b5bbad79f..7b0bfd1b77a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -611,8 +611,8 @@ GEM jar-dependencies (0.5.1) jmespath (1.6.2) jruby-openssl (0.15.1-java) - json (2.9.0) - json (2.9.0-java) + json (2.9.1) + json (2.9.1-java) json-schema (5.1.0) addressable (~> 2.8) json_schema (0.21.0) diff --git a/app/mailers/create_excel_files_mailer.rb b/app/mailers/create_excel_files_mailer.rb new file mode 100644 index 00000000000..675a6f2d30d --- /dev/null +++ b/app/mailers/create_excel_files_mailer.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +class CreateExcelFilesMailer < ApplicationMailer + def build(filename) + date = Time.zone.now.strftime('%m/%d/%Y') + file_contents = File.read("tmp/#{filename}") + headers['Content-Disposition'] = "attachment; filename=#{filename}" + + # rubocop:disable Layout/LineLength + recipients = Settings.vsp_environment.eql?('production') ? Settings.edu.production_excel_contents.emails : Settings.edu.staging_excel_contents.emails + subject = Settings.vsp_environment.eql?('production') ? "22-10282 Form CSV file for #{date}" : "Staging CSV file for #{date}" + # rubocop:enable Layout/LineLength + + mail( + to: recipients, + subject: subject, + content_type: 'text/csv', + body: file_contents + ) + end +end diff --git a/app/models/education_benefits_claim.rb b/app/models/education_benefits_claim.rb index 2fd99f8ea2c..0c7f43a97b6 100644 --- a/app/models/education_benefits_claim.rb +++ b/app/models/education_benefits_claim.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class EducationBenefitsClaim < ApplicationRecord - FORM_TYPES = %w[1990 1995 1990e 5490 5495 1990n 0993 0994 10203 1990s].freeze + FORM_TYPES = %w[1990 1995 1990e 5490 5495 1990n 0993 0994 10203 1990s 10282].freeze APPLICATION_TYPES = %w[ chapter33 diff --git a/app/models/excel_file_event.rb b/app/models/excel_file_event.rb new file mode 100644 index 00000000000..695a9d90f55 --- /dev/null +++ b/app/models/excel_file_event.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +class ExcelFileEvent < ApplicationRecord + validates :filename, uniqueness: true + + # Look for an existing row with same filename + # and increase retry attempt if wasn't successful from previous attempt + # Otherwise create a new event + def self.build_event(filename) + filename_date = filename.match(/(.+)_/)[1] + event = find_by('filename like ?', "#{filename_date}%") + + if event.present? + event.update(retry_attempt: event.retry_attempt + 1) if event.successful_at.nil? + return event + end + + create(filename: filename) + end +end diff --git a/app/models/form_profiles/va_10282.rb b/app/models/form_profiles/va_10282.rb new file mode 100644 index 00000000000..a8dd26e55cc --- /dev/null +++ b/app/models/form_profiles/va_10282.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class FormProfiles::VA10282 < FormProfile + def metadata + { + version: 0, + prefill: true, + returnUrl: '/applicant/information' + } + end +end diff --git a/app/models/saved_claim/education_benefits/va_10282.rb b/app/models/saved_claim/education_benefits/va_10282.rb new file mode 100644 index 00000000000..ac108796e24 --- /dev/null +++ b/app/models/saved_claim/education_benefits/va_10282.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +class SavedClaim::EducationBenefits::VA10282 < SavedClaim::EducationBenefits + add_form_and_validation('22-10282') + + def after_submit(_user) + return unless Flipper.enabled?(:form22_10282_confirmation_email) + + parsed_form_data = JSON.parse(form) + email = parsed_form_data['email'] + return if email.blank? + + send_confirmation_email(parsed_form_data, email) + end + + private + + def send_confirmation_email(parsed_form_data, email) + VANotify::EmailJob.perform_async( + email, + Settings.vanotify.services.va_gov.template_id.form22_10282_confirmation_email, + { + 'first_name' => parsed_form_data.dig('veteranFullName', 'first')&.upcase.presence, + 'date_submitted' => Time.zone.today.strftime('%B %d, %Y'), + 'confirmation_number' => education_benefits_claim.confirmation_number + } + ) + end +end diff --git a/app/sidekiq/education_form/create_daily_excel_files.rb b/app/sidekiq/education_form/create_daily_excel_files.rb new file mode 100644 index 00000000000..39e8d668da2 --- /dev/null +++ b/app/sidekiq/education_form/create_daily_excel_files.rb @@ -0,0 +1,194 @@ +# frozen_string_literal: true + +require 'sentry_logging' +require 'sftp_writer/factory' + +module EducationForm + class DailyExcelFileError < StandardError + end + + class CreateDailyExcelFiles + MAX_RETRIES = 5 + STATSD_KEY = 'worker.education_benefits_claim' + STATSD_FAILURE_METRIC = "#{STATSD_KEY}.failed_excel_file".freeze + LIVE_FORM_TYPES = ['22-10282'].freeze + AUTOMATED_DECISIONS_STATES = [nil, 'denied', 'processed'].freeze + EXCEL_FIELDS = %w[ + name + first_name + last_name + military_affiliation + phone_number + email_address + country + state + race_ethnicity + gender + education_level + employment_status + salary + technology_industry + ].freeze + HEADERS = ['Name', 'First Name', 'Last Name', 'Select Military Affiliation', + 'Phone Number', 'Email Address', 'Country', 'State', 'Race/Ethnicity', + 'Gender of Applicant', 'What is your highest level of education?', + 'Are you currently employed?', 'What is your current salary?', + 'Are you currently working in the technology industry? (If so, please select one)'].freeze + include Sidekiq::Job + include SentryLogging + sidekiq_options queue: 'default', + unique_for: 30.minutes, + retry: 5 + + # rubocop:disable Metrics/MethodLength + def perform + retry_count = 0 + filename = "22-10282_#{Time.zone.now.strftime('%m%d%Y_%H%M%S')}.csv" + excel_file_event = ExcelFileEvent.build_event(filename) + begin + records = EducationBenefitsClaim + .unprocessed + .joins(:saved_claim) + .where( + saved_claims: { + form_id: LIVE_FORM_TYPES + } + ) + return false if federal_holiday? + + if records.count.zero? + log_info('No records to process.') + return true + elsif retry_count.zero? + log_info("Processing #{records.count} application(s)") + end + + # Format the records and write to CSV file + formatted_records = format_records(records) + write_csv_file(formatted_records, filename) + + email_excel_files(filename) + + # Make records processed and add excel file event for rake job + records.each { |r| r.update(processed_at: Time.zone.now) } + excel_file_event.update(number_of_submissions: records.count, successful_at: Time.zone.now) + rescue => e + StatsD.increment("#{STATSD_FAILURE_METRIC}.general") + if retry_count < MAX_RETRIES + log_exception(DailyExcelFileError.new("Error creating excel files.\n\n#{e} + Retry count: #{retry_count}. Retrying..... ")) + retry_count += 1 + sleep(10 * retry_count) # exponential backoff for retries + retry + else + log_exception(DailyExcelFileError.new("Error creating excel files. + Job failed after #{MAX_RETRIES} retries \n\n#{e}")) + end + end + true + end + + def write_csv_file(records, filename) + retry_count = 0 + + begin + # Generate CSV string content instead of writing to file + csv_contents = CSV.generate do |csv| + # Add headers + csv << HEADERS + + # Add data rows + records.each_with_index do |record, index| + log_info("Processing record #{index + 1}: #{record.inspect}") + + begin + row_data = EXCEL_FIELDS.map do |field| + value = record.public_send(field) + value.is_a?(Hash) ? value.to_s : value + end + + csv << row_data + rescue => e + log_exception(DailyExcelFileError.new("Failed to add row #{index + 1}:\n")) + log_exception(DailyExcelFileError.new("#{e.message}\nRecord: #{record.inspect}")) + next + end + end + end + + # Write to file for backup/audit purposes + File.write("tmp/#{filename}", csv_contents) + log_info('Successfully created CSV file') + + # Return the CSV contents + csv_contents + rescue => e + StatsD.increment("#{STATSD_FAILURE_METRIC}.general") + log_exception(DailyExcelFileError.new('Error creating CSV files.')) + + if retry_count < MAX_RETRIES + log_exception(DailyExcelFileError.new("Retry count: #{retry_count}. Retrying..... ")) + retry_count += 1 + sleep(5) + retry + else + log_exception(DailyExcelFileError.new("Job failed after #{MAX_RETRIES} retries \n\n#{e}")) + end + end + end + # rubocop:enable Metrics/MethodLength + + def format_records(records) + records.map do |record| + format_application(record) + end.compact + end + + def format_application(data) + form = EducationForm::Forms::Base.build(data) + track_form_type("22-#{data.form_type}") + form + rescue => e + inform_on_error(data, e) + nil + end + + def inform_on_error(claim, error = nil) + StatsD.increment("#{STATSD_KEY}.failed_formatting.22-#{claim.form_type}") + exception = if error.present? + FormattingError.new("Could not format #{claim.confirmation_number}.\n\n#{error}") + else + FormattingError.new("Could not format #{claim.confirmation_number}") + end + log_exception(exception) + end + + private + + def federal_holiday? + holiday = Holidays.on(Time.zone.today, :us, :observed) + if holiday.empty? + false + else + log_info("Skipping on a Holiday: #{holiday.first[:name]}") + true + end + end + + def track_form_type(type) + StatsD.gauge("#{STATSD_KEY}.transmissions.#{type}", 1) + end + + def log_exception(exception) + log_exception_to_sentry(exception) + end + + def log_info(message) + logger.info(message) + end + + def email_excel_files(contents) + CreateExcelFilesMailer.build(contents).deliver_now + end + end +end diff --git a/app/sidekiq/education_form/forms/va_10282.rb b/app/sidekiq/education_form/forms/va_10282.rb new file mode 100644 index 00000000000..ff8be795ac6 --- /dev/null +++ b/app/sidekiq/education_form/forms/va_10282.rb @@ -0,0 +1,141 @@ +# frozen_string_literal: true + +module EducationForm::Forms + class VA10282 < Base + SALARY_TYPES = { + moreThanSeventyFive: 'More than $75,000', + thirtyFiveToFifty: '$35,000 - $50,000', + fiftyToSeventyFive: '$50,000 - $75,000', + twentyToThirtyFive: '$20,000 - $35,000', + lessThanTwenty: 'Less than $20,000' + }.freeze + + TECH_AREAS = { + CP: 'Computer Programming', + DP: 'Data Processing', + CS: 'Cyber Security', + IS: 'Information Security', + MA: 'Mobile Applications', + NA: 'Not Applicable' + }.freeze + + GENDER_TYPES = { + 'M' => 'Male', + 'W' => 'Female', + 'TW' => 'Transgender Woman', + 'TM' => 'Transgender Man', + 'NB' => 'Non-Binary', + '0' => 'Other', + 'NA' => 'Prefer Not to Answer' + }.freeze + + EDUCATION_LEVELS = { + 'HS' => 'High School', + 'AD' => 'Associate Degree', + 'BD' => "Bachelor's Degree", + 'MD' => "Master's Degree", + 'DD' => 'Doctorate Degree', + 'NA' => 'Prefer Not to Answer' + }.freeze + + MILITARY_TYPES = { + 'veteran' => 'Veteran', + 'veteransSpouse' => "Veteran's Spouse", + 'veteransChild' => "Veteran's Child", + 'veteransCaregiver' => "Veteran's Caregiver", + 'activeduty' => 'Active Duty', + 'nationalGuard' => 'National Guard', + 'reservist' => 'Reservist', + 'individualReadyReserve' => 'Individual Ready Reserve' + }.freeze + + ETHNICITY_TYPES = { + 'HL' => 'Hispanic or Latino', + 'NHL' => 'Not Hispanic or Latino', + 'NA' => 'Prefer Not to Answer' + }.freeze + + # rubocop:disable Lint/MissingSuper + def initialize(education_benefits_claim) + @education_benefits_claim = education_benefits_claim + @applicant = education_benefits_claim.parsed_form + end + # rubocop:enable Lint/MissingSuper + + def name + "#{first_name} #{last_name}" + end + + def first_name + @applicant['veteranFullName']['first'] + end + + def last_name + @applicant['veteranFullName']['last'] + end + + def military_affiliation + MILITARY_TYPES[@applicant['veteranDesc']] || 'Not specified' + end + + def phone_number + @applicant.dig('contactInfo', 'mobilePhone') || + @applicant.dig('contactInfo', 'homePhone') || + 'Not provided' + end + + def email_address + @applicant['contactInfo']['email'] + end + + def country + @applicant['country'] + end + + def state + @applicant['state'] + end + + def race_ethnicity + races = [] + origin_race = @applicant['originRace'] + + races << 'American Indian or Alaska Native' if origin_race['isAmericanIndianOrAlaskanNative'] + races << 'Asian' if origin_race['isAsian'] + races << 'Black or African American' if origin_race['isBlackOrAfricanAmerican'] + races << 'Native Hawaiian or Other Pacific Islander' if origin_race['isNativeHawaiianOrOtherPacificIslander'] + races << 'White' if origin_race['isWhite'] + races << 'Prefer Not to Answer' if origin_race['noAnswer'] + + return 'Not specified' if races.empty? + + races.join(', ') + end + + def gender + GENDER_TYPES[@applicant['gender']] || 'Not specified' + end + + def education_level + EDUCATION_LEVELS[@applicant['highestLevelOfEducation']['level']] || 'Not specified' + end + + def employment_status + @applicant['currentlyEmployed'] ? 'Yes' : 'No' + end + + def salary + SALARY_TYPES[@applicant['currentAnnualSalary']&.to_sym] || 'Not specified' + end + + def technology_industry + return 'No' unless @applicant['isWorkingInTechIndustry'] + + TECH_AREAS[@applicant['techIndustryFocusArea']&.to_sym] || 'Not specified' + end + + def header_form_type + 'V10282' + end + end +end diff --git a/app/sidekiq/education_form/templates/1995.erb b/app/sidekiq/education_form/templates/1995.erb index 3ea59e2d7ef..98b3b80e739 100644 --- a/app/sidekiq/education_form/templates/1995.erb +++ b/app/sidekiq/education_form/templates/1995.erb @@ -57,6 +57,8 @@ VA File Number: <%= value_or_na(@applicant.vaFileNumber) %> Benefit Most Recently Received: <%= form_benefit %> +Do you wish to request a 'Rudisill' review?: <%= @applicant.rudisillReview %> + Select Another Benefit: <%= @applicant.changeAnotherBenefit %> Benefit Being Applied For: <%= @applicant.benefitAppliedFor&.titleize %> diff --git a/config/features.yml b/config/features.yml index 0cada8cac3e..200781e9609 100644 --- a/config/features.yml +++ b/config/features.yml @@ -788,6 +788,9 @@ features: form21_4142_confirmation_email: actor_type: user description: Enables form 21-4142 email submission confirmation (VaNotify) + form22_10282_confirmation_email: + actor_type: user + description: Enables form 22-10282 email submission confirmation (VaNotify) enable_in_development: true form26_4555_confirmation_email: actor_type: user diff --git a/config/settings.yml b/config/settings.yml index 37d42d125ae..0ceb04f07b2 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -230,6 +230,17 @@ edu: - marelby.hernandez@va.gov - nawar.hussein@va.gov - engin.akman@va.gov + staging_excel_contents: + emails: + - alex.chan1@va.gov + - gregg.puhala@va.gov + - noah.stern@va.gov + - marelby.hernandez@va.gov + - nawar.hussein@va.gov + - engin.akman@va.gov + production_excel_contents: + emails: + - patricia.terry1@va.gov dependents: prefill: true diff --git a/lib/periodic_jobs.rb b/lib/periodic_jobs.rb index af456cd24fc..ac82f6b8d9e 100644 --- a/lib/periodic_jobs.rb +++ b/lib/periodic_jobs.rb @@ -115,6 +115,7 @@ # TODO: Document this job mgr.register('0 3 * * MON-FRI', 'EducationForm::CreateDailySpoolFiles') + mgr.register('0 3 * * MON-FRI', 'EducationForm::CreateDailyExcelFiles') # Deletes old, completed AsyncTransaction records mgr.register('0 3 * * *', 'DeleteOldTransactionsJob') diff --git a/rakelib/jobs.rake b/rakelib/jobs.rake index ed23b9a18c5..5cb11b290cb 100644 --- a/rakelib/jobs.rake +++ b/rakelib/jobs.rake @@ -22,4 +22,16 @@ namespace :jobs do SpoolFileEvent.where('DATE(successful_at) = ?', Date.current).delete_all end + + desc 'Create daily excel files' + task create_daily_excel_files: :environment do + EducationForm::CreateDailyExcelFiles.perform_async + end + + desc 'Remove ExcelFileEvent rows for today so the create_daily_excel_files rake task can rerun' + task reset_daily_excel_files_for_today: :environment do + raise Common::Exceptions::Unauthorized if Settings.vsp_environment.eql?('production') # only allowed for test envs + + ExcelFileEvent.where('DATE(successful_at) = ?', Date.current).delete_all + end end diff --git a/spec/factories/excel_file_events.rb b/spec/factories/excel_file_events.rb new file mode 100644 index 00000000000..6d965f40529 --- /dev/null +++ b/spec/factories/excel_file_events.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :excel_file_event do + sequence(:filename) { |n| "22-10282_#{Time.zone.now.strftime('%Y%m%d')}_#{n}.csv" } + retry_attempt { 0 } + + trait :successful do + successful_at { Time.zone.now } + end + end +end diff --git a/spec/factories/va10282.rb b/spec/factories/va10282.rb new file mode 100644 index 00000000000..04b503ae7b4 --- /dev/null +++ b/spec/factories/va10282.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :va10282, class: 'SavedClaim::EducationBenefits::VA10282', parent: :education_benefits do + form { Rails.root.join('spec', 'fixtures', 'education_benefits_claims', '10282', 'minimal.json').read } + end +end diff --git a/spec/fixtures/education_benefits_claims/10282/minimal.csv b/spec/fixtures/education_benefits_claims/10282/minimal.csv new file mode 100644 index 00000000000..aa0e3ab5dd1 --- /dev/null +++ b/spec/fixtures/education_benefits_claims/10282/minimal.csv @@ -0,0 +1,2 @@ +Name,First Name,Last Name,Select Military Affiliation,Phone Number,Email Address,Country,State,Race/Ethnicity,Gender of Applicant,What is your highest level of education?,Are you currently employed?,What is your current salary?,"Are you currently working in the technology industry? (If so, please select one)" +Mark Olson,Mark,Olson,Veteran,1234567890,test@sample.com,United States,FL,Black or African American,Male,Master's Degree,Yes,"More than $75,000",Computer Programming diff --git a/spec/fixtures/education_benefits_claims/10282/minimal.json b/spec/fixtures/education_benefits_claims/10282/minimal.json new file mode 100644 index 00000000000..cd5ecee2618 --- /dev/null +++ b/spec/fixtures/education_benefits_claims/10282/minimal.json @@ -0,0 +1,24 @@ +{ + "veteranFullName": { + "first": "Mark", + "last": "Olson" + }, + "veteranDesc": "veteran", + "contactInfo": { + "mobilePhone": "1234567890", + "email": "test@sample.com" + }, + "country": "United States", + "state": "FL", + "originRace": { + "isBlackOrAfricanAmerican": true + }, + "gender": "M", + "highestLevelOfEducation": { + "level": "MD" + }, + "currentlyEmployed": true, + "currentAnnualSalary": "moreThanSeventyFive", + "isWorkingInTechIndustry": true, + "techIndustryFocusArea": "CP" + } \ No newline at end of file diff --git a/spec/fixtures/education_benefits_claims/1995/ch1606.json b/spec/fixtures/education_benefits_claims/1995/ch1606.json index a9f439f3425..652452ddac9 100644 --- a/spec/fixtures/education_benefits_claims/1995/ch1606.json +++ b/spec/fixtures/education_benefits_claims/1995/ch1606.json @@ -17,6 +17,7 @@ "email": "test@test.com", "benefit": "chapter1606", "benefitUpdate": "chapter1606", + "rudisillReview": "Yes", "changeAnotherBenefit": "Yes", "benefitAppliedFor": "chapter30", "remarks": "remarks", diff --git a/spec/fixtures/education_benefits_claims/1995/ch1606.spl b/spec/fixtures/education_benefits_claims/1995/ch1606.spl index 849d7b488c5..14e8fd41973 100644 --- a/spec/fixtures/education_benefits_claims/1995/ch1606.spl +++ b/spec/fixtures/education_benefits_claims/1995/ch1606.spl @@ -45,6 +45,8 @@ Routing/Transit #: Account #: Benefit Most Recently Received: Chapter1606 +Do you wish to request a 'Rudisill' review?: Yes + Select Another Benefit: Yes Benefit Being Applied For: Chapter30 diff --git a/spec/fixtures/education_benefits_claims/1995/ch30.json b/spec/fixtures/education_benefits_claims/1995/ch30.json index 8b9a9cc6294..ea95af9f446 100644 --- a/spec/fixtures/education_benefits_claims/1995/ch30.json +++ b/spec/fixtures/education_benefits_claims/1995/ch30.json @@ -18,6 +18,7 @@ "email": "test@test.com", "benefit": "chapter30", "benefitUpdate": "chapter30", + "rudisillReview": "Yes", "changeAnotherBenefit": "Yes", "benefitAppliedFor": "chapter1606", "remarks": "remarks", diff --git a/spec/fixtures/education_benefits_claims/1995/ch30.spl b/spec/fixtures/education_benefits_claims/1995/ch30.spl index 1f34df6f4d1..412158e6df7 100644 --- a/spec/fixtures/education_benefits_claims/1995/ch30.spl +++ b/spec/fixtures/education_benefits_claims/1995/ch30.spl @@ -45,6 +45,8 @@ Routing/Transit #: Account #: Benefit Most Recently Received: Chapter30 +Do you wish to request a 'Rudisill' review?: Yes + Select Another Benefit: Yes Benefit Being Applied For: Chapter1606 diff --git a/spec/fixtures/education_benefits_claims/1995/ch30_guardian_graduated.json b/spec/fixtures/education_benefits_claims/1995/ch30_guardian_graduated.json index fa8e95826e0..6b8d1de1ca1 100644 --- a/spec/fixtures/education_benefits_claims/1995/ch30_guardian_graduated.json +++ b/spec/fixtures/education_benefits_claims/1995/ch30_guardian_graduated.json @@ -18,6 +18,7 @@ "email": "test@test.com", "benefit": "chapter30", "benefitUpdate": "chapter30", + "rudisillReview": "Yes", "changeAnotherBenefit": "Yes", "benefitAppliedFor": "chapter1606", "remarks": "remarks", diff --git a/spec/fixtures/education_benefits_claims/1995/ch30_guardian_graduated.spl b/spec/fixtures/education_benefits_claims/1995/ch30_guardian_graduated.spl index 6bff32f2501..7fec6777af9 100644 --- a/spec/fixtures/education_benefits_claims/1995/ch30_guardian_graduated.spl +++ b/spec/fixtures/education_benefits_claims/1995/ch30_guardian_graduated.spl @@ -49,6 +49,8 @@ Routing/Transit #: Account #: Benefit Most Recently Received: Chapter30 +Do you wish to request a 'Rudisill' review?: Yes + Select Another Benefit: Yes Benefit Being Applied For: Chapter1606 diff --git a/spec/fixtures/education_benefits_claims/1995/ch30_guardian_graduated_sponsor.json b/spec/fixtures/education_benefits_claims/1995/ch30_guardian_graduated_sponsor.json index b682ac22c96..9ed0d6f70cc 100644 --- a/spec/fixtures/education_benefits_claims/1995/ch30_guardian_graduated_sponsor.json +++ b/spec/fixtures/education_benefits_claims/1995/ch30_guardian_graduated_sponsor.json @@ -22,6 +22,7 @@ "email": "test@test.com", "benefit": "chapter30", "benefitUpdate": "chapter30", + "rudisillReview": "Yes", "changeAnotherBenefit": "Yes", "benefitAppliedFor": "chapter35", "remarks": "remarks", diff --git a/spec/fixtures/education_benefits_claims/1995/ch30_guardian_graduated_sponsor.spl b/spec/fixtures/education_benefits_claims/1995/ch30_guardian_graduated_sponsor.spl index 707429fad14..2aaca3866b1 100644 --- a/spec/fixtures/education_benefits_claims/1995/ch30_guardian_graduated_sponsor.spl +++ b/spec/fixtures/education_benefits_claims/1995/ch30_guardian_graduated_sponsor.spl @@ -58,6 +58,8 @@ VA File Number: c12345679 Benefit Most Recently Received: Chapter30 +Do you wish to request a 'Rudisill' review?: Yes + Select Another Benefit: Yes Benefit Being Applied For: Chapter35 diff --git a/spec/fixtures/education_benefits_claims/1995/ch30_guardian_not_graduated.json b/spec/fixtures/education_benefits_claims/1995/ch30_guardian_not_graduated.json index 63c30368b33..d8bab235036 100644 --- a/spec/fixtures/education_benefits_claims/1995/ch30_guardian_not_graduated.json +++ b/spec/fixtures/education_benefits_claims/1995/ch30_guardian_not_graduated.json @@ -17,6 +17,7 @@ "email": "test@test.com", "benefit": "chapter30", "benefitUpdate": "chapter30", + "rudisillReview": "Yes", "changeAnotherBenefit": "Yes", "remarks": "remarks", "programName": "program name", diff --git a/spec/fixtures/education_benefits_claims/1995/ch30_guardian_not_graduated.spl b/spec/fixtures/education_benefits_claims/1995/ch30_guardian_not_graduated.spl index 3e27864ed3c..5720b066bbe 100644 --- a/spec/fixtures/education_benefits_claims/1995/ch30_guardian_not_graduated.spl +++ b/spec/fixtures/education_benefits_claims/1995/ch30_guardian_not_graduated.spl @@ -49,6 +49,8 @@ Routing/Transit #: Account #: Benefit Most Recently Received: Chapter30 +Do you wish to request a 'Rudisill' review?: Yes + Select Another Benefit: Yes Benefit Being Applied For: diff --git a/spec/fixtures/education_benefits_claims/1995/ch33_fry.json b/spec/fixtures/education_benefits_claims/1995/ch33_fry.json index 305b67de740..b8fcbd174fa 100644 --- a/spec/fixtures/education_benefits_claims/1995/ch33_fry.json +++ b/spec/fixtures/education_benefits_claims/1995/ch33_fry.json @@ -45,6 +45,7 @@ "email": "test@sample.com", "benefit": "chapter33FryScholarship", "benefitUpdate": "chapter33FryScholarship", + "rudisillReview": "Yes", "changeAnotherBenefit": "Yes", "benefitAppliedFor": "chapter1606", "educationType": "tuitionTopUp", diff --git a/spec/fixtures/education_benefits_claims/1995/ch33_fry.spl b/spec/fixtures/education_benefits_claims/1995/ch33_fry.spl index 4f325396db2..b937daa9769 100644 --- a/spec/fixtures/education_benefits_claims/1995/ch33_fry.spl +++ b/spec/fixtures/education_benefits_claims/1995/ch33_fry.spl @@ -46,6 +46,8 @@ Routing/Transit #: 123456789 Account #: 88888888888 Benefit Most Recently Received: Chapter33 Fry Scholarship +Do you wish to request a 'Rudisill' review?: Yes + Select Another Benefit: Yes Benefit Being Applied For: Chapter1606 diff --git a/spec/fixtures/education_benefits_claims/1995/ch33_fry_noncollege.json b/spec/fixtures/education_benefits_claims/1995/ch33_fry_noncollege.json index aa87389d9f1..8a4fcc8a7c4 100644 --- a/spec/fixtures/education_benefits_claims/1995/ch33_fry_noncollege.json +++ b/spec/fixtures/education_benefits_claims/1995/ch33_fry_noncollege.json @@ -45,6 +45,7 @@ "email": "test@sample.com", "benefit": "chapter33FryScholarship", "benefitUpdate": "chapter33FryScholarship", + "rudisillReview": "Yes", "changeAnotherBenefit": "Yes", "benefitAppliedFor": "chapter1606", "educationType": "tuitionTopUp", diff --git a/spec/fixtures/education_benefits_claims/1995/ch33_fry_noncollege.spl b/spec/fixtures/education_benefits_claims/1995/ch33_fry_noncollege.spl index 24d762dd328..d88202bf266 100644 --- a/spec/fixtures/education_benefits_claims/1995/ch33_fry_noncollege.spl +++ b/spec/fixtures/education_benefits_claims/1995/ch33_fry_noncollege.spl @@ -46,6 +46,8 @@ Routing/Transit #: 123456789 Account #: 88888888888 Benefit Most Recently Received: Chapter33 Fry Scholarship +Do you wish to request a 'Rudisill' review?: Yes + Select Another Benefit: Yes Benefit Being Applied For: Chapter1606 diff --git a/spec/fixtures/education_benefits_claims/1995/ch33_post911.json b/spec/fixtures/education_benefits_claims/1995/ch33_post911.json index 3dc720a896f..65d882af135 100644 --- a/spec/fixtures/education_benefits_claims/1995/ch33_post911.json +++ b/spec/fixtures/education_benefits_claims/1995/ch33_post911.json @@ -45,6 +45,7 @@ "email": "test@sample.com", "benefit": "chapter33Post911", "benefitUpdate": "chapter33Post911", + "rudisillReview": "Yes", "changeAnotherBenefit": "Yes", "benefitAppliedFor": "chapter1606", "educationType": "tuitionTopUp", diff --git a/spec/fixtures/education_benefits_claims/1995/ch33_post911.spl b/spec/fixtures/education_benefits_claims/1995/ch33_post911.spl index f2a55c3be74..14f8f32efbc 100644 --- a/spec/fixtures/education_benefits_claims/1995/ch33_post911.spl +++ b/spec/fixtures/education_benefits_claims/1995/ch33_post911.spl @@ -46,6 +46,8 @@ Routing/Transit #: 123456789 Account #: 88888888888 Benefit Most Recently Received: Chapter33 Post911 +Do you wish to request a 'Rudisill' review?: Yes + Select Another Benefit: Yes Benefit Being Applied For: Chapter1606 diff --git a/spec/fixtures/education_benefits_claims/1995/kitchen_sink.json b/spec/fixtures/education_benefits_claims/1995/kitchen_sink.json index d862a09f4fa..8e1a867c9a5 100644 --- a/spec/fixtures/education_benefits_claims/1995/kitchen_sink.json +++ b/spec/fixtures/education_benefits_claims/1995/kitchen_sink.json @@ -45,6 +45,7 @@ "email": "test@sample.com", "benefit": "transferOfEntitlement", "benefitUpdate": "transferOfEntitlement", + "rudisillReview": "No", "changeAnotherBenefit": "Yes", "benefitAppliedFor": "chapter30", "educationType": "tuitionTopUp", diff --git a/spec/fixtures/education_benefits_claims/1995/kitchen_sink.spl b/spec/fixtures/education_benefits_claims/1995/kitchen_sink.spl index 3afecfc0be6..5a8ac5f1ab5 100644 --- a/spec/fixtures/education_benefits_claims/1995/kitchen_sink.spl +++ b/spec/fixtures/education_benefits_claims/1995/kitchen_sink.spl @@ -46,6 +46,8 @@ Routing/Transit #: 123456789 Account #: 88888888888 Benefit Most Recently Received: Transfer Of Entitlement +Do you wish to request a 'Rudisill' review?: No + Select Another Benefit: Yes Benefit Being Applied For: Chapter30 diff --git a/spec/fixtures/education_benefits_claims/1995/minimal.json b/spec/fixtures/education_benefits_claims/1995/minimal.json index c8004120133..3e2ec471ca3 100644 --- a/spec/fixtures/education_benefits_claims/1995/minimal.json +++ b/spec/fixtures/education_benefits_claims/1995/minimal.json @@ -19,6 +19,8 @@ "applicantGender": "F", "dateOfBirth": "1970-01-01", "changeAnotherBenefit": "Yes", - "benefitUpdate": "chapter35", + "benefitUpdate": "chapter30", + "benefitAppliedFor": "chapter35", + "rudisillReview": "No", "email": "test@sample.com", "bankAccount": {}} diff --git a/spec/fixtures/education_benefits_claims/1995/minimal.spl b/spec/fixtures/education_benefits_claims/1995/minimal.spl index 1428119039e..56f278277a0 100644 --- a/spec/fixtures/education_benefits_claims/1995/minimal.spl +++ b/spec/fixtures/education_benefits_claims/1995/minimal.spl @@ -52,11 +52,13 @@ VA File Number: 12345678 TYPE AND PROGRAM OF EDUCATION OR TRAINING ----------------------------------------- -Benefit Most Recently Received: Chapter35 +Benefit Most Recently Received: Chapter30 + +Do you wish to request a 'Rudisill' review?: No Select Another Benefit: Yes -Benefit Being Applied For: +Benefit Being Applied For: Chapter35 Type of Education or Training: Education or Career Goal: diff --git a/spec/fixtures/education_form/create_csv_array.json b/spec/fixtures/education_form/create_csv_array.json index 6c3e4462059..14413f0d6db 100644 --- a/spec/fixtures/education_form/create_csv_array.json +++ b/spec/fixtures/education_form/create_csv_array.json @@ -39,6 +39,9 @@ "", "22-1990s", "", + "", + "22-10282", + "", "" ], [ @@ -70,7 +73,10 @@ "2017-01-03 00:00:00 UTC..2017-01-03 23:59:59 UTC", "2017-01-01..2017-01-03 23:59:59 UTC", "", - "2017-01-03 00:00:00 UTC..2017-01-03 23:59:59 UTC" , + "2017-01-03 00:00:00 UTC..2017-01-03 23:59:59 UTC", + "2017-01-01..2017-01-03 23:59:59 UTC", + "", + "2017-01-03 00:00:00 UTC..2017-01-03 23:59:59 UTC", "2017-01-01..2017-01-03 23:59:59 UTC", "", "2017-01-03 00:00:00 UTC..2017-01-03 23:59:59 UTC" @@ -107,6 +113,9 @@ "Sent to Spool File", "", "Submitted", + "Sent to Spool File", + "", + "Submitted", "Sent to Spool File" ], [ @@ -141,6 +150,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -175,6 +187,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -209,6 +224,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -243,6 +261,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -277,6 +298,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -311,6 +335,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -345,6 +372,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -379,6 +409,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -413,6 +446,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -447,6 +483,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -481,6 +520,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -515,6 +557,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -549,6 +594,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -583,6 +631,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -617,6 +668,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -651,6 +705,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -685,6 +742,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -719,6 +779,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -753,6 +816,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -787,6 +853,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -821,6 +890,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -855,6 +927,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -889,6 +964,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -923,6 +1001,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -957,6 +1038,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -991,6 +1075,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1025,6 +1112,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1059,6 +1149,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1093,6 +1186,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1127,6 +1223,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1161,6 +1260,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1195,6 +1297,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1229,6 +1334,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1263,6 +1371,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1297,6 +1408,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1331,6 +1445,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1365,6 +1482,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1399,6 +1519,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1433,6 +1556,9 @@ 0, 0, 1, + 0, + 0, + 0, 0 ], [ @@ -1467,6 +1593,9 @@ 0, 0, 1, + 0, + 0, + 0, 0 ], [ @@ -1501,6 +1630,9 @@ 0, 0, 1, + 0, + 0, + 0, 0 ], [ @@ -1535,6 +1667,9 @@ "", "22-1990s", "", + "", + "22-10282", + "", "" ] ] \ No newline at end of file diff --git a/spec/fixtures/education_form/fiscal_year_create_csv_array.json b/spec/fixtures/education_form/fiscal_year_create_csv_array.json index 7999ea8f5aa..46c4922d558 100644 --- a/spec/fixtures/education_form/fiscal_year_create_csv_array.json +++ b/spec/fixtures/education_form/fiscal_year_create_csv_array.json @@ -39,6 +39,9 @@ "", "22-1990s", "", + "", + "22-10282", + "", "" ], [ @@ -73,6 +76,9 @@ "2017-01-09 00:00:00 UTC..2017-01-09 23:59:59 UTC", "2016-10-01..2017-01-09 23:59:59 UTC", "", + "2017-01-09 00:00:00 UTC..2017-01-09 23:59:59 UTC", + "2016-10-01..2017-01-09 23:59:59 UTC", + "", "2017-01-09 00:00:00 UTC..2017-01-09 23:59:59 UTC" ], [ @@ -107,6 +113,9 @@ "Sent to Spool File", "", "Submitted", + "Sent to Spool File", + "", + "Submitted", "Sent to Spool File" ], [ @@ -141,6 +150,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -175,6 +187,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -209,6 +224,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -243,6 +261,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -277,6 +298,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -311,6 +335,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -345,6 +372,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -379,6 +409,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -413,6 +446,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -447,6 +483,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -481,6 +520,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -515,6 +557,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -549,6 +594,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -583,6 +631,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -617,6 +668,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -651,6 +705,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -685,6 +742,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -719,6 +779,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -753,6 +816,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -787,6 +853,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -821,6 +890,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -855,6 +927,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -889,6 +964,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -923,6 +1001,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -957,6 +1038,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -991,6 +1075,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1025,6 +1112,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1059,6 +1149,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1093,6 +1186,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1127,6 +1223,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1161,6 +1260,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1195,6 +1297,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1229,6 +1334,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1263,6 +1371,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1297,6 +1408,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1331,6 +1445,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1365,6 +1482,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1399,6 +1519,9 @@ 0, 0, 0, + 0, + 0, + 0, 0 ], [ @@ -1433,6 +1556,9 @@ 0, 0, 1, + 0, + 0, + 0, 0 ], [ @@ -1467,6 +1593,9 @@ 0, 0, 1, + 0, + 0, + 0, 0 ], [ @@ -1501,6 +1630,9 @@ 0, 0, 1, + 0, + 0, + 0, 0 ], [ @@ -1535,6 +1667,9 @@ "", "22-1990s", "", + "", + "22-10282", + "", "" ] ] \ No newline at end of file diff --git a/spec/fixtures/education_form/minimal.csv b/spec/fixtures/education_form/minimal.csv new file mode 100644 index 00000000000..aa0e3ab5dd1 --- /dev/null +++ b/spec/fixtures/education_form/minimal.csv @@ -0,0 +1,2 @@ +Name,First Name,Last Name,Select Military Affiliation,Phone Number,Email Address,Country,State,Race/Ethnicity,Gender of Applicant,What is your highest level of education?,Are you currently employed?,What is your current salary?,"Are you currently working in the technology industry? (If so, please select one)" +Mark Olson,Mark,Olson,Veteran,1234567890,test@sample.com,United States,FL,Black or African American,Male,Master's Degree,Yes,"More than $75,000",Computer Programming diff --git a/spec/fixtures/education_form/ytd_day_processed.json b/spec/fixtures/education_form/ytd_day_processed.json index b05b9ba519b..b09a826138c 100644 --- a/spec/fixtures/education_form/ytd_day_processed.json +++ b/spec/fixtures/education_form/ytd_day_processed.json @@ -394,5 +394,51 @@ "vettec": 0, "vrrap": 0 } + }, + "10282": { + "eastern": { + "chapter33": 0, + "chapter1607": 0, + "chapter1606": 0, + "chapter32": 0, + "chapter35": 0, + "transfer_of_entitlement": 0, + "vettec": 0, + "chapter30": 0, + "vrrap": 0 + }, + "southern": { + "chapter33": 0, + "chapter1607": 0, + "chapter1606": 0, + "chapter32": 0, + "chapter35": 0, + "transfer_of_entitlement": 0, + "vettec": 0, + "chapter30": 0, + "vrrap": 0 + }, + "central": { + "chapter33": 0, + "chapter1607": 0, + "chapter1606": 0, + "chapter32": 0, + "chapter35": 0, + "transfer_of_entitlement": 0, + "vettec": 0, + "chapter30": 0, + "vrrap": 0 + }, + "western": { + "chapter33": 0, + "chapter1607": 0, + "chapter1606": 0, + "chapter32": 0, + "chapter35": 0, + "transfer_of_entitlement": 0, + "vettec": 0, + "chapter30": 0, + "vrrap": 0 + } } } diff --git a/spec/fixtures/education_form/ytd_day_submitted.json b/spec/fixtures/education_form/ytd_day_submitted.json index bd2753e17cd..0df56d4745f 100644 --- a/spec/fixtures/education_form/ytd_day_submitted.json +++ b/spec/fixtures/education_form/ytd_day_submitted.json @@ -440,5 +440,51 @@ "vettec": 0, "vrrap": 1 } + }, + "10282": { + "eastern": { + "chapter33": 0, + "chapter1607": 0, + "chapter1606": 0, + "chapter32": 0, + "chapter35": 0, + "transfer_of_entitlement": 0, + "vettec": 0, + "chapter30": 0, + "vrrap": 0 + }, + "southern": { + "chapter33": 0, + "chapter1607": 0, + "chapter1606": 0, + "chapter32": 0, + "chapter35": 0, + "transfer_of_entitlement": 0, + "vettec": 0, + "chapter30": 0, + "vrrap": 0 + }, + "central": { + "chapter33": 0, + "chapter1607": 0, + "chapter1606": 0, + "chapter32": 0, + "chapter35": 0, + "transfer_of_entitlement": 0, + "vettec": 0, + "chapter30": 0, + "vrrap": 0 + }, + "western": { + "chapter33": 0, + "chapter1607": 0, + "chapter1606": 0, + "chapter32": 0, + "chapter35": 0, + "transfer_of_entitlement": 0, + "vettec": 0, + "chapter30": 0, + "vrrap": 0 + } } } diff --git a/spec/fixtures/education_form/ytd_year_processed.json b/spec/fixtures/education_form/ytd_year_processed.json index 86831f5c792..91c209aff8a 100644 --- a/spec/fixtures/education_form/ytd_year_processed.json +++ b/spec/fixtures/education_form/ytd_year_processed.json @@ -394,5 +394,51 @@ "vettec": 0, "vrrap": 0 } + }, + "10282": { + "eastern": { + "chapter33": 0, + "chapter1607": 0, + "chapter1606": 0, + "chapter32": 0, + "chapter35": 0, + "transfer_of_entitlement": 0, + "vettec": 0, + "chapter30": 0, + "vrrap": 0 + }, + "southern": { + "chapter33": 0, + "chapter1607": 0, + "chapter1606": 0, + "chapter32": 0, + "chapter35": 0, + "transfer_of_entitlement": 0, + "vettec": 0, + "chapter30": 0, + "vrrap": 0 + }, + "central": { + "chapter33": 0, + "chapter1607": 0, + "chapter1606": 0, + "chapter32": 0, + "chapter35": 0, + "transfer_of_entitlement": 0, + "vettec": 0, + "chapter30": 0, + "vrrap": 0 + }, + "western": { + "chapter33": 0, + "chapter1607": 0, + "chapter1606": 0, + "chapter32": 0, + "chapter35": 0, + "transfer_of_entitlement": 0, + "vettec": 0, + "chapter30": 0, + "vrrap": 0 + } } } diff --git a/spec/fixtures/education_form/ytd_year_submitted.json b/spec/fixtures/education_form/ytd_year_submitted.json index 3f67c9f6e17..9fc794c34e9 100644 --- a/spec/fixtures/education_form/ytd_year_submitted.json +++ b/spec/fixtures/education_form/ytd_year_submitted.json @@ -394,5 +394,51 @@ "vettec": 0, "vrrap": 1 } + }, + "10282": { + "eastern": { + "chapter33": 0, + "chapter1607": 0, + "chapter1606": 0, + "chapter32": 0, + "chapter35": 0, + "transfer_of_entitlement": 0, + "vettec": 0, + "chapter30": 0, + "vrrap": 0 + }, + "southern": { + "chapter33": 0, + "chapter1607": 0, + "chapter1606": 0, + "chapter32": 0, + "chapter35": 0, + "transfer_of_entitlement": 0, + "vettec": 0, + "chapter30": 0, + "vrrap": 0 + }, + "central": { + "chapter33": 0, + "chapter1607": 0, + "chapter1606": 0, + "chapter32": 0, + "chapter35": 0, + "transfer_of_entitlement": 0, + "vettec": 0, + "chapter30": 0, + "vrrap": 0 + }, + "western": { + "chapter33": 0, + "chapter1607": 0, + "chapter1606": 0, + "chapter32": 0, + "chapter35": 0, + "transfer_of_entitlement": 0, + "vettec": 0, + "chapter30": 0, + "vrrap": 0 + } } } diff --git a/spec/models/education_benefits_claim_spec.rb b/spec/models/education_benefits_claim_spec.rb index 9e784341034..22481d1d742 100644 --- a/spec/models/education_benefits_claim_spec.rb +++ b/spec/models/education_benefits_claim_spec.rb @@ -7,7 +7,7 @@ create(:va1990).education_benefits_claim end - %w[1990 1995 1990e 5490 5495 1990n 0993 0994 10203 1990s].each do |form_type| + %w[1990 1995 1990e 5490 5495 1990n 0993 0994 10203 1990s 10282].each do |form_type| method = "is_#{form_type}?" describe "##{method}" do @@ -240,6 +240,22 @@ def associated_submission end end + context 'with a form type of 10282' do + subject do + create(:va10282) + end + + it 'creates a submission' do + subject + + expect(associated_submission).to eq( + submission_attributes.merge( + 'form_type' => '10282' + ) + ) + end + end + it 'does not create a submission after save if it was already submitted' do subject.education_benefits_claim.update!(processed_at: Time.zone.now) expect(EducationBenefitsSubmission.count).to eq(1) diff --git a/spec/models/saved_claim/education_benefits/va10282_spec.rb b/spec/models/saved_claim/education_benefits/va10282_spec.rb new file mode 100644 index 00000000000..558d6da6771 --- /dev/null +++ b/spec/models/saved_claim/education_benefits/va10282_spec.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +require 'rails_helper' +require 'lib/saved_claims_spec_helper' + +RSpec.describe SavedClaim::EducationBenefits::VA10282 do + let(:instance) { FactoryBot.build(:va10282) } + + it_behaves_like 'saved_claim' + + validate_inclusion(:form_id, '22-10282') +end diff --git a/spec/sidekiq/education_form/forms/va10282_spec.rb b/spec/sidekiq/education_form/forms/va10282_spec.rb new file mode 100644 index 00000000000..040aeef03cf --- /dev/null +++ b/spec/sidekiq/education_form/forms/va10282_spec.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe EducationForm::Forms::VA10282 do + %w[minimal].each do |test_application| + test_excel_file('10282', test_application) + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index a780d2c3059..90ae4bdc8f6 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -4,6 +4,7 @@ require 'support/spec_builders' require 'support/matchers' require 'support/spool_helpers' +require 'support/excel_helpers' require 'support/fixture_helpers' require 'support/silence_stream' require 'sidekiq-pro' if Gem.loaded_specs.key?('sidekiq-pro') @@ -166,6 +167,7 @@ config.include SpecBuilders config.include SpoolHelpers + config.include ExcelHelpers config.include FixtureHelpers config.around(:example, :run_at) do |example| diff --git a/spec/support/excel_helpers.rb b/spec/support/excel_helpers.rb new file mode 100644 index 00000000000..01709d918c9 --- /dev/null +++ b/spec/support/excel_helpers.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +module ExcelHelpers + extend ActiveSupport::Concern + + module ClassMethods + # rubocop:disable Metrics/MethodLength + def test_excel_file(form_type, test_name, disabled_features = []) + describe "#{form_type} #{test_name} excel test" do + subject do + described_class.new(education_benefits_claim) + end + + let(:file_prefix) { "spec/fixtures/education_benefits_claims/#{form_type}/#{test_name}." } + let(:form_class) { "SavedClaim::EducationBenefits::VA#{form_type}".constantize } + let(:education_benefits_claim) do + form_class.create!( + form: File.read("#{file_prefix}json") + ).education_benefits_claim + end + + before do + allow(education_benefits_claim).to receive(:id).and_return(1) + education_benefits_claim.instance_variable_set(:@application, nil) + end + + it 'generates the excel data correctly', run_at: '2017-01-17 03:00:00 -0500' do + disabled_features.each do |feature| + allow(Flipper).to receive(:enabled?).with(feature).and_return(false) + end + + expected_data = CSV.read("#{file_prefix}csv", headers: true) + + # Format the application data using the form object + form = subject + row_data = EducationForm::CreateDailyExcelFiles::EXCEL_FIELDS.map do |field| + form.public_send(field) + end + + # Create CSV data for comparison + generated_csv = CSV.generate do |csv| + csv << EducationForm::CreateDailyExcelFiles::HEADERS + csv << row_data + end + generated_data = CSV.parse(generated_csv, headers: true) + + # Compare headers + expect(generated_data.headers).to eq(EducationForm::CreateDailyExcelFiles::HEADERS) + + # Compare data row by row + expected_data.each_with_index do |expected_row, index| + generated_row = generated_data[index] + + EducationForm::CreateDailyExcelFiles::EXCEL_FIELDS.each_with_index do |field, field_index| + expect(generated_row[field_index]).to eq(expected_row[field_index]), + "Mismatch in #{field} for row #{index + 1}. " \ + "Expected: #{expected_row[field_index]}, " \ + "Got: #{generated_row[field_index]}" + end + end + end + end + end + # rubocop:enable Metrics/MethodLength + end +end