diff --git a/app/controllers/v0/burial_claims_controller.rb b/app/controllers/v0/burial_claims_controller.rb index 56b202efb03..77d398fb6b5 100644 --- a/app/controllers/v0/burial_claims_controller.rb +++ b/app/controllers/v0/burial_claims_controller.rb @@ -8,18 +8,24 @@ class BurialClaimsController < ClaimsBaseController def create PensionBurial::TagSentry.tag_sentry - claim = claim_class.new(form: filtered_params[:form]) + + claim = if Flipper.enabled?(:va_burial_v2) + # cannot parse a nil form, to pass unit tests do a check for form presence + form = filtered_params[:form] + claim_class.new(form:, formV2: form.present? ? JSON.parse(form)['formV2'] : nil) + else + claim_class.new(form: filtered_params[:form]) + end unless claim.save StatsD.increment("#{stats_key}.failure") Sentry.set_tags(team: 'benefits-memorial-1') # tag sentry logs with team name raise Common::Exceptions::ValidationErrors, claim end - # this method also calls claim.process_attachments! claim.submit_to_structured_data_services! - Rails.logger.info "ClaimID=#{claim.confirmation_number} Form=#{claim.class::FORM}" + Rails.logger.info "ClaimID=#{claim.confirmation_number} Form=#{claim.form_id}" clear_saved_form(claim.form_id) render(json: claim) end diff --git a/app/controllers/v0/claim_documents_controller.rb b/app/controllers/v0/claim_documents_controller.rb index 1bcaba7a14c..95c471e4e66 100644 --- a/app/controllers/v0/claim_documents_controller.rb +++ b/app/controllers/v0/claim_documents_controller.rb @@ -31,7 +31,7 @@ def create def klass case form_id - when '21P-527EZ', '21P-530' + when '21P-527EZ', '21P-530', '21P-530V2' PensionBurial::TagSentry.tag_sentry PersistentAttachments::PensionBurial when '21-686C', '686C-674' diff --git a/app/models/form_profile.rb b/app/models/form_profile.rb index 6cc8209e578..bfd47678896 100644 --- a/app/models/form_profile.rb +++ b/app/models/form_profile.rb @@ -92,7 +92,7 @@ class FormProfile 22-5495 22-0993 22-0994 FEEDBACK-TOOL 22-10203 22-1990S 22-1990EZ], evss: ['21-526EZ'], hca: %w[1010ez 10-10EZR], - pension_burial: %w[21P-530 21P-527EZ], + pension_burial: %w[21P-530 21P-527EZ 21P-530V2], dependents: ['686C-674'], decision_review: %w[20-0995 20-0996 10182], mdot: ['MDOT'], @@ -121,6 +121,7 @@ class FormProfile '22-5490E' => ::FormProfiles::VA5490e, '22-5495' => ::FormProfiles::VA5495, '21P-530' => ::FormProfiles::VA21p530, + '21P-530V2' => ::FormProfiles::VA21p530v2, '21-686C' => ::FormProfiles::VA21686c, '686C-674' => ::FormProfiles::VA686c674, '40-10007' => ::FormProfiles::VA4010007, diff --git a/app/models/form_profiles/va_21p530v2.rb b/app/models/form_profiles/va_21p530v2.rb new file mode 100644 index 00000000000..4cdbdfe237e --- /dev/null +++ b/app/models/form_profiles/va_21p530v2.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require 'iso_country_codes' + +class FormProfiles::VA21p530v2 < FormProfile + def metadata + { + version: 0, + prefill: true, + returnUrl: '/claimant-information' + } + end + + def prefill + @identity_information = initialize_identity_information + @contact_information = initialize_contact_information + if @contact_information&.address&.country.present? + @contact_information.address.country = convert_to_iso2(@contact_information.address.country) + end + mappings = self.class.mappings_for_form(form_id) + + form_data = generate_prefill(mappings) if FormProfile.prefill_enabled_forms.include?(form_id) + + { form_data:, metadata: } + end + + private + + def convert_to_iso2(country_code) + code = IsoCountryCodes.find(country_code) + code.alpha2 + end +end diff --git a/app/models/saved_claim.rb b/app/models/saved_claim.rb index 83c812e08cf..1d73e4da0c2 100644 --- a/app/models/saved_claim.rb +++ b/app/models/saved_claim.rb @@ -31,7 +31,7 @@ class SavedClaim < ApplicationRecord # create a uuid for this second (used in the confirmation number) and store # the form type based on the constant found in the subclass. after_initialize do - self.form_id = self.class::FORM.upcase + self.form_id = self.class::FORM.upcase unless instance_of?(SavedClaim::Burial) end def self.add_form_and_validation(form_id) @@ -51,7 +51,7 @@ def process_attachments! def submit_to_structured_data_services! # Only 21P-530 burial forms are supported at this time - if form_id != '21P-530' + unless %w[21P-530 21P-530V2].include?(form_id) err_message = "Unsupported form id: #{form_id}" raise Common::Exceptions::UnprocessableEntity.new(detail: err_message), err_message end diff --git a/app/models/saved_claim/burial.rb b/app/models/saved_claim/burial.rb index 02bddbc08aa..465821ab084 100644 --- a/app/models/saved_claim/burial.rb +++ b/app/models/saved_claim/burial.rb @@ -5,6 +5,17 @@ class SavedClaim::Burial < CentralMailClaim FORM = '21P-530' + # attribute name is passed from the FE as a flag, maintaining camel case + attr_accessor :formV2 # rubocop:disable Naming/MethodName + + after_initialize do + self.form_id = if Flipper.enabled?(:va_burial_v2) + formV2 || form_id == '21P-530V2' ? '21P-530V2' : self.class::FORM.upcase + else + self.class::FORM.upcase + end + end + def process_attachments! refs = attachment_keys.map { |key| Array(open_struct_form.send(key)) }.flatten files = PersistentAttachment.where(guid: refs.map(&:confirmationCode)) @@ -25,6 +36,14 @@ def email parsed_form['claimantEmail'] end + def form_matches_schema + return unless form_is_string + + JSON::Validator.fully_validate(VetsJsonSchema::SCHEMAS[form_id], parsed_form).each do |v| + errors.add(:form, v.to_s) + end + end + def business_line 'NCA' end diff --git a/app/sidekiq/structured_data/process_data_job.rb b/app/sidekiq/structured_data/process_data_job.rb index b10191b15b9..c6f2400bf05 100644 --- a/app/sidekiq/structured_data/process_data_job.rb +++ b/app/sidekiq/structured_data/process_data_job.rb @@ -25,8 +25,7 @@ def perform(saved_claim_id) ensure @claim.process_attachments! # upload claim and attachments to Central Mail - send_confirmation_email if @claim.form_id == '21P-530' - + send_confirmation_email if %w[21P-530 21P-530V2].include?(@claim.form_id) # veteran lookup for hit/miss metrics in support of Automation work StatsD.increment("#{stats_key}.success", tags: %W[relationship:#{relationship_type} veteranInMVI:#{veteran&.participant_id}]) diff --git a/config/features.yml b/config/features.yml index ae260e16ecd..28bfd610610 100644 --- a/config/features.yml +++ b/config/features.yml @@ -1139,6 +1139,9 @@ features: va_view_dependents_access: actor_type: user description: Allows us to gate the View/ Modify dependents content in a progressive rollout + va_burial_v2: + actor_type: user + description: Allows us to toggle between 21-P530 and 21-P530V2 show_edu_benefits_1990EZ_Wizard: actor_type: user description: Navigates user to 1990EZ or 1990 depending on form questions. diff --git a/lib/bip_claims/service.rb b/lib/bip_claims/service.rb index f1d8b5eec13..204809fb1e1 100644 --- a/lib/bip_claims/service.rb +++ b/lib/bip_claims/service.rb @@ -14,7 +14,7 @@ class Service < Common::Client::Base def veteran_attributes(claim) case claim.form_id - when '21P-530' + when '21P-530', '21P-530V2' ssn, full_name, bday = claim.parsed_form.values_at( 'veteranSocialSecurityNumber', 'veteranFullName', diff --git a/lib/evss/disability_compensation_form/form4142_processor.rb b/lib/evss/disability_compensation_form/form4142_processor.rb index 07cef2a5465..446f5d55349 100644 --- a/lib/evss/disability_compensation_form/form4142_processor.rb +++ b/lib/evss/disability_compensation_form/form4142_processor.rb @@ -2,6 +2,7 @@ require 'pdf_fill/forms/va21p527ez' require 'pdf_fill/forms/va21p530' +require 'pdf_fill/forms/va21p530v2' require 'pdf_fill/forms/va214142' require 'pdf_fill/forms/va210781a' require 'pdf_fill/forms/va210781' diff --git a/lib/pdf_fill/filler.rb b/lib/pdf_fill/filler.rb index 69122f4c6cc..2ce6719beca 100644 --- a/lib/pdf_fill/filler.rb +++ b/lib/pdf_fill/filler.rb @@ -2,6 +2,7 @@ require 'pdf_fill/forms/va21p527ez' require 'pdf_fill/forms/va21p530' +require 'pdf_fill/forms/va21p530v2' require 'pdf_fill/forms/va214142' require 'pdf_fill/forms/va210781a' require 'pdf_fill/forms/va210781' @@ -25,6 +26,7 @@ module Filler FORM_CLASSES = { '21P-527EZ' => PdfFill::Forms::Va21p527ez, '21P-530' => PdfFill::Forms::Va21p530, + '21P-530V2' => PdfFill::Forms::Va21p530v2, '21-4142' => PdfFill::Forms::Va214142, '21-0781a' => PdfFill::Forms::Va210781a, '21-0781' => PdfFill::Forms::Va210781, diff --git a/lib/pdf_fill/forms/pdfs/21P-530V2.pdf b/lib/pdf_fill/forms/pdfs/21P-530V2.pdf new file mode 100644 index 00000000000..87650f0b3d5 Binary files /dev/null and b/lib/pdf_fill/forms/pdfs/21P-530V2.pdf differ diff --git a/lib/pdf_fill/forms/va21p530v2.rb b/lib/pdf_fill/forms/va21p530v2.rb new file mode 100644 index 00000000000..b850d80a404 --- /dev/null +++ b/lib/pdf_fill/forms/va21p530v2.rb @@ -0,0 +1,732 @@ +# frozen_string_literal: true + +require 'pdf_fill/hash_converter' +require 'pdf_fill/forms/form_base' +require 'pdf_fill/forms/form_helper' +require 'string_helpers' + +# rubocop:disable Metrics/ClassLength +module PdfFill + module Forms + class Va21p530v2 < FormBase + include FormHelper + + ITERATOR = PdfFill::HashConverter::ITERATOR + + PLACE_OF_DEATH_KEY = { + 'vaMedicalCenter' => 'VA MEDICAL CENTER', + 'stateVeteransHome' => 'STATE VETERANS HOME', + 'nursingHome' => 'NURSING HOME UNDER VA CONTRACT' + }.freeze + + # rubocop:disable Layout/LineLength + KEY = { + 'veteranFullName' => { # start veteran information + 'first' => { + key: 'form1[0].#subform[82].VeteransFirstName[0]', + limit: 12, + question_num: 1, + question_text: "DECEASED VETERAN'S FIRST NAME" + }, + 'middle' => { + key: 'form1[0].#subform[82].VeteransMiddleInitial1[0]', + question_num: 1, + limit: 1, + question_text: "DECEASED VETERAN'S MIDDLE INITIAL" + }, + 'last' => { + key: 'form1[0].#subform[82].VeteransLastName[0]', + limit: 18, + question_num: 1, + question_text: "DECEASED VETERAN'S LAST NAME" + }, + 'suffix' => { + key: 'form1[0].#subform[82].Suffix[0]', + question_num: 1, + limit: 0, + question_text: "DECEASED VETERAN'S SUFFIX" + } + }, + 'veteranSocialSecurityNumber' => { + 'first' => { + key: 'form1[0].#subform[82].VeteransSocialSecurityNumber_FirstThreeNumbers[0]' + }, + 'second' => { + key: 'form1[0].#subform[82].VeteransSocialSecurityNumber_SecondTwoNumbers[0]' + }, + 'third' => { + key: 'form1[0].#subform[82].VeteransSocialSecurityNumber_LastFourNumbers[0]' + } + }, + 'vaFileNumber' => { + key: 'form1[0].#subform[82].VAFileNumber[0]', + question_num: 3 + }, + 'veteranDateOfBirth' => { + 'month' => { + key: 'form1[0].#subform[82].Veterans_DOBmonth[0]', + limit: 2, + question_num: 4, + question_suffix: 'A', + question_text: 'VETERAN/CLAIMANT\'S IDENTIFICATION INFORMATION > VETERAN\'S DATE OF BIRTH (MM-DD-YYYY)' + }, + 'day' => { + key: 'form1[0].#subform[82].Veterans_DOBday[0]', + limit: 2, + question_num: 4, + question_suffix: 'B', + question_text: 'VETERAN/CLAIMANT\'S IDENTIFICATION INFORMATION > VETERAN\'S DATE OF BIRTH (MM-DD-YYYY)' + }, + 'year' => { + key: 'form1[0].#subform[82].Veterans_DOByear[0]', + limit: 4, + question_num: 4, + question_suffix: 'C', + question_text: 'VETERAN/CLAIMANT\'S IDENTIFICATION INFORMATION > VETERAN\'S DATE OF BIRTH (MM-DD-YYYY)' + } + }, + 'deathDate' => { + 'month' => { + key: 'form1[0].#subform[82].Veterans_DateOfDeathmonth[0]', + limit: 2, + question_num: 5, + question_suffix: 'A', + question_text: 'VETERAN/CLAIMANT\'S IDENTIFICATION INFORMATION > VETERAN\'S DATE OF DEATH (MM-DD-YYYY)' + }, + 'day' => { + key: 'form1[0].#subform[82].Veterans_DateofDeathday[0]', + limit: 2, + question_num: 5, + question_suffix: 'B', + question_text: 'VETERAN/CLAIMANT\'S IDENTIFICATION INFORMATION > VETERAN\'S DATE OF DEATH (MM-DD-YYYY)' + }, + 'year' => { + key: 'form1[0].#subform[82].Veterans_DateofDeathyear[0]', + limit: 4, + question_num: 5, + question_suffix: 'C', + question_text: 'VETERAN/CLAIMANT\'S IDENTIFICATION INFORMATION > VETERAN\'S DATE OF DEATH (MM-DD-YYYY)' + } + }, + 'burialDate' => { + 'month' => { + key: 'form1[0].#subform[82].Veterans_Date_of_Burial_Month[0]', + limit: 2, + question_num: 6, + question_suffix: 'A', + question_text: 'VETERAN/CLAIMANT\'S IDENTIFICATION INFORMATION > VETERAN\'S DATE OF BURIAL (MM-DD-YYYY)' + }, + 'day' => { + key: 'form1[0].#subform[82].Veterans_Date_of_Burial_Day[0]', + limit: 2, + question_num: 6, + question_suffix: 'B', + question_text: 'VETERAN/CLAIMANT\'S IDENTIFICATION INFORMATION > VETERAN\'S DATE OF BURIAL (MM-DD-YYYY)' + }, + 'year' => { + key: 'form1[0].#subform[82].Veterans_Date_of_Burial_Year[0]', + limit: 4, + question_num: 6, + question_suffix: 'C', + question_text: 'VETERAN/CLAIMANT\'S IDENTIFICATION INFORMATION > VETERAN\'S DATE OF BURIAL (MM-DD-YYYY)' + } + }, # end veteran information + 'claimantFullName' => { # start claimant information + 'first' => { + key: 'form1[0].#subform[82].ClaimantsFirstName[0]', + limit: 12, + question_num: 7, + question_text: "CLAIMANT'S FIRST NAME" + }, + 'middle' => { + key: 'form1[0].#subform[82].ClaimantsMiddleInitial1[0]' + }, + 'last' => { + key: 'form1[0].#subform[82].ClaimantsLastName[0]', + limit: 18, + question_num: 7, + question_text: "CLAIMANT'S LAST NAME" + }, + 'suffix' => { + key: 'form1[0].#subform[82].ClaimantSuffix[0]', + question_num: 7, + limit: 0, + question_text: "CLAIMANT'S SUFFIX" + } + }, + 'claimantSocialSecurityNumber' => { + 'first' => { + key: 'form1[0].#subform[82].Claimants_SocialSecurityNumber_FirstThreeNumbers[0]' + }, + 'second' => { + key: 'form1[0].#subform[82].Claimants_SocialSecurityNumber_SecondTwoNumbers[0]' + }, + 'third' => { + key: 'form1[0].#subform[82].Claimants_SocialSecurityNumber_LastFourNumbers[0]' + } + }, + 'claimantDateOfBirth' => { + 'month' => { + key: 'form1[0].#subform[82].Claimants_DOBmonth[0]', + limit: 2, + question_num: 9, + question_suffix: 'A', + question_text: 'VETERAN/CLAIMANT\'S IDENTIFICATION INFORMATION > CLAIMANT\'S DATE OF BIRTH (MM-DD-YYYY)' + }, + 'day' => { + key: 'form1[0].#subform[82].Claimants_DOBday[0]', + limit: 2, + question_num: 9, + question_suffix: 'B', + question_text: 'VETERAN/CLAIMANT\'S IDENTIFICATION INFORMATION > CLAIMANT\'S DATE OF BIRTH (MM-DD-YYYY)' + }, + 'year' => { + key: 'form1[0].#subform[82].Claimants_DOByear[0]', + limit: 4, + question_num: 9, + question_suffix: 'C', + question_text: 'VETERAN/CLAIMANT\'S IDENTIFICATION INFORMATION > CLAIMANT\'S DATE OF BIRTH (MM-DD-YYYY)' + } + }, + 'claimantAddress' => { + 'street' => { + key: 'form1[0].#subform[82].CurrentMailingAddress_NumberAndStreet[0]', + limit: 30, + question_num: 10, + question_text: "CLAIMANT'S ADDRESS - STREET" + }, + 'street2' => { + key: 'form1[0].#subform[82].CurrentMailingAddress_ApartmentOrUnitNumber[0]', + limit: 5, + question_num: 10, + question_text: "CLAIMANT'S ADDRESS - APT/UNIT NO." + }, + 'city' => { + key: 'form1[0].#subform[82].CurrentMailingAddress_City[0]', + limit: 18, + question_num: 10, + question_text: "CLAIMANT'S ADDRESS - CITY" + }, + 'state' => { + key: 'form1[0].#subform[82].CurrentMailingAddress_StateOrProvince[0]', + limit: 2, + question_num: 10, + question_text: "CLAIMANT'S ADDRESS - STATE" + }, + 'country' => { + key: 'form1[0].#subform[82].CurrentMailingAddress_Country[0]', + limit: 2, + question_num: 10, + question_text: "CLAIMANT'S ADDRESS - COUNTRY" + }, + 'postalCode' => { + 'firstFive' => { + key: 'form1[0].#subform[82].CurrentMailingAddress_ZIPOrPostalCode_FirstFiveNumbers[0]', + limit: 5, + question_num: 10, + question_text: "CLAIMANT'S ADDRESS - POSTAL CODE - FIRST FIVE" + }, + 'lastFour' => { + key: 'form1[0].#subform[82].CurrentMailingAddress_ZIPOrPostalCode_LastFourNumbers[0]', + limit: 4, + question: 10, + question_text: "CLAIMANT's ADDRESS - POSTAL CODE - LAST FOUR" + } + } + }, + 'claimantPhone' => { + 'first' => { + key: 'form1[0].#subform[82].TelephoneNumber_AreaCode[0]' + }, + 'second' => { + key: 'form1[0].#subform[82].TelephoneNumber_FirstThreeNumbers[0]' + }, + 'third' => { + key: 'form1[0].#subform[82].TelephoneNumber_LastFourNumbers[0]' + } + }, + 'claimantIntPhone' => { + key: 'form1[0].#subform[82].IntTelephoneNumber[0]', + question_num: 11, + question_text: "CLAIMANT'S INTERNATIONAL PHONE NUMBER", + limit: 0 # this will force this value that is not on the pdf to appear in the overflow + }, + 'claimantEmail' => { + key: 'form1[0].#subform[82].E-Mail_Address[0]', + limit: 31, + question_num: 12, + question_text: 'E-MAIL ADDRESS' + }, + 'relationshipToVeteran' => { + 'spouse' => { + key: 'form1[0].#subform[82].CheckboxSpouse[0]' + }, + 'child' => { + key: 'form1[0].#subform[82].CheckboxChild[0]' + }, + 'parent' => { + key: 'form1[0].#subform[82].CheckboxParent[0]' + }, + 'executor' => { + key: 'form1[0].#subform[82].CheckboxExecutor[0]' + }, + 'funeralHome' => { + key: 'form1[0].#subform[82].CheckboxFuneralHome[0]' + }, + 'other' => { + key: 'form1[0].#subform[82].CheckboxOther[0]' + } + }, + 'toursOfDuty' => { + limit: 3, + first_key: 'rank', + 'dateRangeStart' => { + key: "form1[0].#subform[82].DATE_ENTERED_SERVICE[#{ITERATOR}]", + question_num: 14, + question_suffix: 'A', + question_text: 'ENTERED SERVICE (date)', + format: 'date' + }, + 'placeOfEntry' => { + key: "form1[0].#subform[82].PLACE[#{ITERATOR}]", + limit: 14, + question_num: 14, + question_suffix: 'A', + question_text: 'ENTERED SERVICE (place)' + }, + 'militaryServiceNumber' => { + key: "form1[0].#subform[82].SERVICE_NUMBER[#{ITERATOR}]", + limit: 12, + question_num: 14, + question_suffix: 'B', + question_text: 'SERVICE NUMBER' + }, + 'dateRangeEnd' => { + key: "form1[0].#subform[82].DATE_SEPARATED_SERVICE[#{ITERATOR}]", + question_num: 14, + question_suffix: 'C', + question_text: 'SEPARATED FROM SERVICE (date)', + format: 'date' + }, + 'placeOfSeparation' => { + key: "form1[0].#subform[82].PLACE_SEPARATED[#{ITERATOR}]", + question_num: 14, + question_suffix: 'C', + question_text: 'SEPARATED FROM SERVICE (place)', + limit: 15 + }, + 'rank' => { + key: "form1[0].#subform[82].GRADE_RANK_OR_RATING[#{ITERATOR}]", + question_num: 11, + question_suffix: 'D', + question_text: 'GRADE, RANK OR RATING, ORGANIZATION AND BRANCH OF SERVICE', + limit: 31 + } + }, + 'previousNames' => { + key: 'form1[0].#subform[82].OTHER_NAME_VETERAN_SERVED_UNDER[0]', + question_num: 15, + question_text: 'IF VETERAN SERVED UNDER NAME OTHER THAN THAT SHOWN IN ITEM 1, GIVE FULL NAME AND SERVICE RENDERED UNDER THAT NAME', + limit: 180 + }, + 'veteranSocialSecurityNumber2' => { + 'first' => { + key: 'form1[0].#subform[83].#subform[84].VeteransSocialSecurityNumber_FirstThreeNumbers[1]' + }, + 'second' => { + key: 'form1[0].#subform[83].#subform[84].VeteransSocialSecurityNumber_SecondTwoNumbers[1]' + }, + 'third' => { + key: 'form1[0].#subform[83].#subform[84].VeteransSocialSecurityNumber_LastFourNumbers[1]' + } + }, + 'finalRestingPlace' => { # break into yes/nos + 'location' => { + 'cemetery' => { + key: 'form1[0].#subform[83].#subform[84].RestingPlaceCemetery[5]' + }, + 'privateResidence' => { + key: 'form1[0].#subform[83].#subform[84].RestingPlacePrivateResidence[5]' + }, + 'mausoleum' => { + key: 'form1[0].#subform[83].#subform[84].RestingPlaceMausoleum[5]' + }, + 'other' => { + key: 'form1[0].#subform[83].#subform[84].RestingPlaceOther[5]' + } + }, + 'other' => { + limit: 58, + question_num: 16, + question_text: "PLACE OF BURIAL PLOT, INTERMENT SITE, OR FINAL RESTING PLACE OF DECEASED VETERAN'S REMAINS", + key: 'form1[0].#subform[83].#subform[84].PLACE_OF_DEATH[0]' + } + }, + 'hasNationalOrFederal' => { + key: 'form1[0].#subform[37].FederalCemeteryYES[0]' + }, + 'noNationalOrFederal' => { + key: 'form1[0].#subform[37].FederalCemeteryNo[0]' + }, + 'name' => { + key: 'form1[0].#subform[37].FederalCemeteryName[0]', + limit: 50 + }, + 'cemetaryLocationQuestionCemetery' => { + key: 'form1[0].#subform[37].HasStateCemetery[2]' + }, + 'cemetaryLocationQuestionTribal' => { + key: 'form1[0].#subform[37].HasTribalTrust[2]' + }, + 'cemetaryLocationQuestionNone' => { + key: 'form1[0].#subform[37].NoStateCemetery[2]' + }, + 'stateCemeteryOrTribalTrustName' => { + key: 'form1[0].#subform[37].StateCemeteryOrTribalTrustName[2]', + limit: 33 + }, + 'stateCemeteryOrTribalTrustZip' => { + key: 'form1[0].#subform[37].StateCemeteryOrTribalTrustZip[2]' + }, + 'hasGovtContributions' => { + key: 'form1[0].#subform[37].GovContributionYES[0]' + }, + 'noGovtContributions' => { + key: 'form1[0].#subform[37].GovContributionNo[0]' + }, + 'amountGovtContribution' => { + key: 'form1[0].#subform[37].AmountGovtContribution[0]', + question_num: 19, + question_suffix: 'B', + dollar: true, + question_text: 'AMOUNT OF GOVERNMENT OR EMPLOYER CONTRIBUTION', + limit: 5 + }, + 'burialAllowanceRequested' => { + 'checkbox' => { + 'nonService' => { + key: 'form1[0].#subform[83].Non-Service-Connected[0]' + }, + 'service' => { + key: 'form1[0].#subform[83].Service-Connected[0]' + }, + 'unclaimed' => { + key: 'form1[0].#subform[83].UnclaimedRemains[0]' + } + } + }, + 'locationOfDeath' => { + 'checkbox' => { + 'nursingHomeUnpaid' => { + key: 'form1[0].#subform[83].NursingHomeOrResidenceNotPaid[1]' + }, + 'nursingHomePaid' => { + key: 'form1[0].#subform[83].NursingHomeOrResidencePaid[1]' + }, + 'vaMedicalCenter' => { + key: 'form1[0].#subform[83].VaMedicalCenter[1]' + }, + 'stateVeteransHome' => { + key: 'form1[0].#subform[83].StateVeteransHome[1]' + }, + 'other' => { + key: 'form1[0].#subform[83].DeathOccurredOther[1]' + } + }, + 'other' => { + key: 'form1[0].#subform[37].DeathOccurredOtherSpecify[1]', + question_num: 20, + question_suffix: 'B', + question_text: "WHERE DID THE VETERAN'S DEATH OCCUR?", + limit: 32 + } + }, + 'hasPreviouslyReceivedAllowance' => { + key: 'form1[0].#subform[83].PreviousAllowanceYes[0]' + }, + 'noPreviouslyReceivedAllowance' => { + key: 'form1[0].#subform[83].PreviousAllowanceNo[0]' + }, + 'hasBurialExpenseResponsibility' => { + key: 'form1[0].#subform[83].ResponsibleForBurialCostYes[0]' + }, + 'noBurialExpenseResponsibility' => { + key: 'form1[0].#subform[83].ResponsibleForBurialCostNo[0]' + }, + 'hasConfirmation' => { + key: 'form1[0].#subform[83].certifyUnclaimedYes[0]' + }, + 'noConfirmation' => { + key: 'form1[0].#subform[83].certifyUnclaimedNo[0]' + }, + 'hasPlotExpenseResponsibility' => { + key: 'form1[0].#subform[83].ResponsibleForPlotIntermentCostYes[0]' + }, + 'noPlotExpenseResponsibility' => { + key: 'form1[0].#subform[83].ResponsibleForPlotIntermentCostNo[0]' + }, + 'hasTransportation' => { + key: 'form1[0].#subform[83].ResponsibleForTransportationYes[0]' + }, + 'noTransportation' => { + key: 'form1[0].#subform[83].ResponsibleForTransportationNo[0]' + }, + 'hasProcessOption' => { + key: 'form1[0].#subform[83].WantClaimFDCProcessedYes[0]' + }, + 'noProcessOption' => { + key: 'form1[0].#subform[83].WantClaimFDCProcessedNo[0]' + }, + 'signature' => { + key: 'form1[0].#subform[83].CLAIMANT_SIGNATURE[0]', + limit: 45, + question_num: 25, + question_text: 'SIGNATURE OF CLAIMANT', + question_suffix: 'A' + }, + 'claimantPrintedName' => { + key: 'form1[0].#subform[83].ClaimantPrintedName[0]', + limit: 45, + question_num: 25, + question_text: 'Printed Name of Claimant', + question_suffix: 'B' + }, + 'firmNameAndAddr' => { + key: 'form1[0].#subform[83].FirmNameAndAddress[0]', + limit: 90, + question_num: 26, + question_suffix: 'B', + question_text: 'FULL NAME AND ADDRESS OF THE FIRM, CORPORATION, OR STATE AGENCY FILING AS CLAIMANT' + }, + 'officialPosition' => { + key: 'form1[0].#subform[83].OfficialPosition[0]', + limit: 90, + question_num: 26, + question_suffix: 'B', + question_text: 'OFFICIAL POSITION OF PERSON SIGNING ON BEHALF OF FIRM, CORPORATION OR STATE AGENCY' + }, + 'veteranSocialSecurityNumber3' => { + 'first' => { + key: 'form1[0].#subform[83].#subform[84].VeteransSocialSecurityNumber_FirstThreeNumbers[2]' + }, + 'second' => { + key: 'form1[0].#subform[83].#subform[84].VeteransSocialSecurityNumber_SecondTwoNumbers[2]' + }, + 'third' => { + key: 'form1[0].#subform[83].#subform[84].VeteransSocialSecurityNumber_LastFourNumbers[2]' + } + } + }.freeze + # rubocop:enable Layout/LineLength + + def split_phone(hash, key) + phone = hash[key] + return if phone.blank? + + hash[key] = { + 'first' => phone[0..2], + 'second' => phone[3..5], + 'third' => phone[6..9] + } + end + + def split_postal_code(hash) + postal_code = hash['claimantAddress']['postalCode'] + return if postal_code.blank? + + hash['claimantAddress']['postalCode'] = { + 'firstFive' => postal_code[0..4], + 'lastFour' => postal_code[6..10] + } + end + + # override for how this pdf works, it needs the strings of yes/no + def expand_checkbox(value, key) + { + "has#{key}" => value == true ? 'YES' : nil, + "no#{key}" => value == false ? 'NO' : nil + } + end + + def expand_checkbox_in_place(hash, key) + hash.merge!(expand_checkbox(hash[key], StringHelpers.capitalize_only(key))) + end + + def expand_relationship(hash, key) + expand_checkbox_as_hash(hash[key], 'type') + end + + def expand_tours_of_duty(tours_of_duty) + return if tours_of_duty.blank? + + tours_of_duty.each do |tour_of_duty| + expand_date_range(tour_of_duty, 'dateRange') + tour_of_duty['rank'] = combine_hash(tour_of_duty, %w[serviceBranch rank], ', ') + tour_of_duty['militaryServiceNumber'] = @form_data['militaryServiceNumber'] + end + end + + def convert_location_of_death + location_of_death = @form_data['locationOfDeath'] + return if location_of_death.blank? + + location_of_death['location'] = 'nursingHomeUnpaid' if location_of_death['location'] == 'atHome' + expand_checkbox_as_hash(@form_data['locationOfDeath'], 'location') + end + + def expand_burial_allowance + burial_allowance = @form_data['burialAllowanceRequested'] + return if burial_allowance.blank? + + burial_allowance.each do |key, value| + burial_allowance[key] = value.present? ? 'On' : nil + end + + @form_data['burialAllowanceRequested'] = { + 'checkbox' => burial_allowance + } + end + + def expand_cemetery_location + cemetery_location = @form_data['cemeteryLocation'] + return if cemetery_location.blank? + + @form_data['stateCemeteryOrTribalTrustName'] = cemetery_location['name'] if cemetery_location['name'].present? + @form_data['stateCemeteryOrTribalTrustZip'] = cemetery_location['zip'] if cemetery_location['zip'].present? + end + + # VA file number can be up to 10 digits long; An optional leading 'c' or 'C' followed by + # 7-9 digits. The file number field on the 4142 form has space for 9 characters so trim the + # potential leading 'c' to ensure the file number will fit into the form without overflow. + def extract_va_file_number(va_file_number) + return va_file_number if va_file_number.blank? || va_file_number.length < 10 + + va_file_number.sub(/^[Cc]/, '') + end + + # override for on/off vs 1/off + def select_checkbox(value) + value ? 'On' : 'Off' + end + + # override + def expand_checkbox_as_hash(hash, key) + value = hash.try(:[], key) + return if value.blank? + + hash['checkbox'] = { + value => 'On' + } + end + + def expand_confirmation_question + if @form_data['confirmation'].present? + confirmation = @form_data['confirmation'] + @form_data['confirmation'] = confirmation['checkBox'] + expand_checkbox_in_place(@form_data, 'confirmation') + end + end + + def expand_location_question + cemetery_location = @form_data['cemetaryLocationQuestion'] + @form_data['cemetaryLocationQuestionCemetery'] = select_checkbox(cemetery_location == 'cemetery') + @form_data['cemetaryLocationQuestionTribal'] = select_checkbox(cemetery_location == 'tribal') + @form_data['cemetaryLocationQuestionNone'] = select_checkbox(cemetery_location == 'none') + end + + def combine_previous_names_and_service(previous_names) + return if previous_names.blank? + + previous_names.map do |previous_name| + "#{combine_full_name(previous_name)} (#{previous_name['serviceBranch']})" + end.join('; ') + end + + # rubocop:disable Metrics/MethodLength + def merge_fields(_options = {}) + expand_signature(@form_data['claimantFullName']) + + %w[veteranFullName claimantFullName].each do |attr| + extract_middle_i(@form_data, attr) + end + + %w[veteranDateOfBirth deathDate burialDate claimantDateOfBirth].each do |attr| + @form_data[attr] = split_date(@form_data[attr]) + end + + ssn = @form_data['veteranSocialSecurityNumber'] + ['', '2', '3'].each do |suffix| + @form_data["veteranSocialSecurityNumber#{suffix}"] = split_ssn(ssn) + end + + @form_data['claimantSocialSecurityNumber'] = split_ssn(@form_data['claimantSocialSecurityNumber']) + + relationship_to_veteran = @form_data['relationshipToVeteran'] + @form_data['relationshipToVeteran'] = { + 'spouse' => select_checkbox(relationship_to_veteran == 'spouse'), + 'child' => select_checkbox(relationship_to_veteran == 'child'), + 'executor' => select_checkbox(relationship_to_veteran == 'executor'), + 'parent' => select_checkbox(relationship_to_veteran == 'parent'), + 'funeralHome' => select_checkbox(relationship_to_veteran == 'funeralHome'), + 'other' => select_checkbox(relationship_to_veteran == 'other') + } + + final_resting_place = @form_data.dig('finalRestingPlace', 'location') + @form_data['finalRestingPlace']['location'] = { + 'cemetery' => select_checkbox(final_resting_place == 'cemetery'), + 'privateResidence' => select_checkbox(final_resting_place == 'privateResidence'), + 'mausoleum' => select_checkbox(final_resting_place == 'mausoleum'), + 'other' => select_checkbox(final_resting_place == 'other') + } + + expand_cemetery_location + + # special case: these fields were built as checkboxes instead of radios, so usual radio logic can't be used. + burial_expense_responsibility = @form_data['burialExpenseResponsibility'] + @form_data['hasBurialExpenseResponsibility'] = burial_expense_responsibility ? 'On' : nil + @form_data['noBurialExpenseResponsibility'] = burial_expense_responsibility ? nil : 'On' + + # special case: these fields were built as checkboxes instead of radios, so usual radio logic can't be used. + plot_expense_responsibility = @form_data['plotExpenseResponsibility'] + @form_data['hasPlotExpenseResponsibility'] = plot_expense_responsibility ? 'On' : nil + @form_data['noPlotExpenseResponsibility'] = plot_expense_responsibility ? nil : 'On' + + # special case: these fields were built as checkboxes instead of radios, so usual radio logic can't be used. + process_option = @form_data['processOption'] + @form_data['hasProcessOption'] = process_option ? 'On' : nil + @form_data['noProcessOption'] = process_option ? nil : 'On' + + expand_confirmation_question + expand_location_question + + split_phone(@form_data, 'claimantPhone') + + split_postal_code(@form_data) + + expand_tours_of_duty(@form_data['toursOfDuty']) + + @form_data['previousNames'] = combine_previous_names_and_service(@form_data['previousNames']) + + @form_data['vaFileNumber'] = extract_va_file_number(@form_data['vaFileNumber']) + + expand_burial_allowance + + convert_location_of_death + + %w[ + nationalOrFederal + govtContributions + previouslyReceivedAllowance + allowanceStatementOfTruth + transportation + ].each do |attr| + expand_checkbox_in_place(@form_data, attr) + end + + @form_data + end + # rubocop:enable Metrics/MethodLength + end + end +end +# rubocop:enable Metrics/ClassLength diff --git a/lib/statsd_middleware.rb b/lib/statsd_middleware.rb index 9b1f97c3be0..7d54281a381 100644 --- a/lib/statsd_middleware.rb +++ b/lib/statsd_middleware.rb @@ -61,6 +61,7 @@ class StatsdMiddleware avs burial-poc-v6 burials + burials-v2 check-in claims-status coe diff --git a/spec/factories/burial_claim.rb b/spec/factories/burial_claim.rb index 8d8705b75aa..23c7189318d 100644 --- a/spec/factories/burial_claim.rb +++ b/spec/factories/burial_claim.rb @@ -33,6 +33,39 @@ end end + factory :burial_claim_v2, class: 'SavedClaim::Burial' do + form_id { '21P-530V2' } + form do + { + privacyAgreementAccepted: true, + veteranFullName: { + first: 'WESLEY', + last: 'FORD' + }, + claimantEmail: 'foo@foo.com', + deathDate: '1989-12-13', + veteranDateOfBirth: '1986-05-06', + veteranSocialSecurityNumber: '796043735', + claimantAddress: { + country: 'USA', + state: 'CA', + postalCode: '90210', + street: '123 Main St', + city: 'Anytown' + }, + claimantFullName: { + first: 'Derrick', + middle: 'A', + last: 'Stewart' + }, + burialAllowance: true, + plotAllowance: true, + transportation: true, + formV2: true + }.to_json + end + end + # Bad names that fail the EMMS API regex factory :burial_claim_bad_names, class: 'SavedClaim::Burial' do form_id { '21P-530' } diff --git a/spec/fixtures/pdf_fill/21P-530V2/kitchen_sink.json b/spec/fixtures/pdf_fill/21P-530V2/kitchen_sink.json new file mode 100644 index 00000000000..f4bc77bd629 --- /dev/null +++ b/spec/fixtures/pdf_fill/21P-530V2/kitchen_sink.json @@ -0,0 +1,56 @@ +{ + "transportationExpenses":true, + "plotExpenseResponsibility":true, + "govtContributions":true, + "amountGovtContribution":"50000", + "cemeteryLocation":{"name":"state cemetery", "zip":"04102"}, + "cemetaryLocationQuestion":"cemetery", + "nationalOrFederal":true, + "name":"name of cemetery", + "finalRestingPlace":{"location":"other", "other":"other"}, + "previouslyReceivedAllowance":true, + "burialExpenseResponsibility":true, + "confirmation":{"checkBox":true}, + "burialAllowanceRequested":{"service":true, "nonService":true, "unclaimed":true}, + "burialAllowance":true, + "plotAllowance":true, + "processOption":false, + "transportation":true, + "previousNames":[{"first":"previous", "middle":"other", "last":"name", "suffix":"Jr.", "serviceBranch":"navy"}], + "militaryServiceNumber":"123123", + "toursOfDuty": + [{"serviceBranch":"Air Force", + "dateRange":{"from":"1970-01-01", "to":"1974-01-01"}, + "placeOfEntry":"placeofentry12", + "placeOfSeparation":"placeofentry12", + "rank":"gradeofentry12", + "unit":"unit"}, + {"serviceBranch":"Army", + "dateRange":{"from":"1976-01-01", "to":"1978-01-02"}, + "placeOfEntry":"placeofentry34", + "placeOfSeparation":"placeofentry34", + "rank":"gradeofentry13", + "unit":"unit"}, + {"serviceBranch":"Navy", + "dateRange":{"from":"1980-01-01", "to":"1984-01-01"}, + "placeOfEntry":"placeofentry56", + "placeOfSeparation":"placeofentry56", + "rank":"gradeofentry56", + "unit":"unit"}], + "locationOfDeath":{"location":"other", "other":"other place"}, + "deathDate":"2024-01-01", + "burialDate":"2024-01-02", + "veteranFullName":{"first":"veteran", "middle":"middle", "last":"lastname", "suffix":"Jr."}, + "veteranSocialSecurityNumber":"987654322", + "vaFileNumber":"987654322", + "veteranDateOfBirth":"1950-01-01", + "claimantEmail":"test@test.com", + "claimantPhone":"5555555555", + "claimantIntPhone":"5555555556", + "claimantAddress":{"country":"US", "street":"123 fake street", "street2":"street address line 2", "city":"portland", "state":"ME", "postalCode":"04102"}, + "claimantFullName":{"first":"test", "middle":"middle", "last":"spouse", "suffix":"Jr."}, + "claimantSocialSecurityNumber":"987654321", + "claimantDateOfBirth":"1960-01-01", + "formV2":true, + "relationshipToVeteran":"spouse", + "privacyAgreementAccepted":true} \ No newline at end of file diff --git a/spec/fixtures/pdf_fill/21P-530V2/merge_fields.json b/spec/fixtures/pdf_fill/21P-530V2/merge_fields.json new file mode 100644 index 00000000000..108b49025f0 --- /dev/null +++ b/spec/fixtures/pdf_fill/21P-530V2/merge_fields.json @@ -0,0 +1,102 @@ +{ + "transportationExpenses":true, + "plotExpenseResponsibility":true, + "govtContributions":true, + "amountGovtContribution":"50000", + "cemeteryLocation":{"name":"state cemetery", "zip":"04102"}, + "cemetaryLocationQuestion":"cemetery", + "nationalOrFederal":true, + "name":"name of cemetery", + "finalRestingPlace":{"location":{"cemetery":"Off", "privateResidence":"Off", "mausoleum":"Off", "other":"On"}, "other":"other"}, + "previouslyReceivedAllowance":true, + "burialExpenseResponsibility":true, + "confirmation":true, + "burialAllowanceRequested":{"checkbox":{"service":"On", "nonService":"On", "unclaimed":"On"}}, + "burialAllowance":true, + "plotAllowance":true, + "processOption":false, + "transportation":true, + "previousNames":"previous other name Jr. (navy)", + "militaryServiceNumber":"123123", + "toursOfDuty":[ + { + "serviceBranch":"Air Force", + "placeOfEntry":"placeofentry12", + "placeOfSeparation":"placeofentry12", + "rank":"Air Force, gradeofentry12", + "unit":"unit", + "dateRangeStart":"1970-01-01", + "dateRangeEnd":"1974-01-01", + "militaryServiceNumber":"123123" + }, + { + "serviceBranch":"Army", + "placeOfEntry":"placeofentry34", + "placeOfSeparation":"placeofentry34", + "rank":"Army, gradeofentry13", + "unit":"unit", + "dateRangeStart":"1976-01-01", + "dateRangeEnd":"1978-01-02", + "militaryServiceNumber":"123123" + }, + { + "serviceBranch":"Navy", + "placeOfEntry":"placeofentry56", + "placeOfSeparation":"placeofentry56", + "rank":"Navy, gradeofentry56", + "unit":"unit", + "dateRangeStart":"1980-01-01", + "dateRangeEnd":"1984-01-01", + "militaryServiceNumber":"123123" + } + ], + "locationOfDeath": + { + "location":"other", + "other":"other place", + "checkbox":{"other":"On"} + }, + "deathDate":{"month":"01", "day":"01", "year":"2024"}, + "burialDate":{"month":"01", "day":"02", "year":"2024"}, + "veteranFullName":{"first":"veteran", "middle":"middle", "last":"lastname", "suffix":"Jr.", "middleInitial":"m"}, + "veteranSocialSecurityNumber":{"first":"987", "second":"65", "third":"4322"}, + "vaFileNumber":"987654322", + "veteranDateOfBirth":{"month":"01", "day":"01", "year":"1950"}, + "claimantEmail":"test@test.com", + "claimantPhone":{"first":"555", "second":"555", "third":"5555"}, + "claimantIntPhone":"5555555556", + "claimantAddress":{"country":"US", "street":"123 fake street", "street2":"street address line 2", "city":"portland", "state":"ME", "postalCode":{"firstFive":"04102", "lastFour":null}}, + "claimantFullName":{"first":"test", "middle":"middle", "last":"spouse", "suffix":"Jr.", "middleInitial":"m"}, + "claimantSocialSecurityNumber":{"first":"987", "second":"65", "third":"4321"}, + "claimantDateOfBirth":{"month":"01", "day":"01", "year":"1960"}, + "formV2":true, + "relationshipToVeteran":{"spouse":"On", "child":"Off", "executor":"Off", "parent":"Off", "funeralHome":"Off", "other":"Off"}, + "privacyAgreementAccepted":true, + "signature":"test spouse", + "signatureDate":"2024-03-21", + "veteranSocialSecurityNumber2":{"first":"987", "second":"65", "third":"4322"}, + "veteranSocialSecurityNumber3":{"first":"987", "second":"65", "third":"4322"}, + "stateCemeteryOrTribalTrustName":"state cemetery", + "stateCemeteryOrTribalTrustZip":"04102", + "hasBurialExpenseResponsibility":"On", + "noBurialExpenseResponsibility":null, + "hasPlotExpenseResponsibility":"On", + "noPlotExpenseResponsibility":null, + "hasProcessOption":null, + "noProcessOption":"On", + "hasConfirmation":"YES", + "noConfirmation":null, + "cemetaryLocationQuestionCemetery":"On", + "cemetaryLocationQuestionTribal":"Off", + "cemetaryLocationQuestionNone":"Off", + "hasNationalOrFederal":"YES", + "noNationalOrFederal":null, + "hasGovtContributions":"YES", + "noGovtContributions":null, + "hasPreviouslyReceivedAllowance":"YES", + "noPreviouslyReceivedAllowance":null, + "hasAllowanceStatementOfTruth":null, + "noAllowanceStatementOfTruth":null, + "hasTransportation":"YES", + "noTransportation":null +} \ No newline at end of file diff --git a/spec/lib/pdf_fill/forms/va21p530v2_spec.rb b/spec/lib/pdf_fill/forms/va21p530v2_spec.rb new file mode 100644 index 00000000000..36b6947982a --- /dev/null +++ b/spec/lib/pdf_fill/forms/va21p530v2_spec.rb @@ -0,0 +1,115 @@ +# frozen_string_literal: true + +require 'rails_helper' +require 'pdf_fill/forms/va21p530v2' + +def basic_class + PdfFill::Forms::Va21p530v2.new({}) +end + +describe PdfFill::Forms::Va21p530v2 do + let(:form_data) do + {} + end + + let(:new_form_class) do + described_class.new(form_data) + end + + def class_form_data + new_form_class.instance_variable_get(:@form_data) + end + + test_method( + basic_class, + 'expand_checkbox', + [ + [ + [ + true, 'GovtContribution' + ], + { 'hasGovtContribution' => 'YES', 'noGovtContribution' => nil } + ], + [ + [ + false, 'GovtContribution' + ], + { 'hasGovtContribution' => nil, 'noGovtContribution' => 'NO' } + ], + [ + [ + nil, 'GovtContribution' + ], + { 'hasGovtContribution' => nil, 'noGovtContribution' => nil } + ] + ] + ) + + test_method( + basic_class, + 'split_phone', + [ + [ + [{}, nil], + nil + ], + [ + [ + { phone: '1112223333' }, + :phone + ], + { 'first' => '111', 'second' => '222', 'third' => '3333' } + ] + ] + ) + + describe '#convert_location_of_death' do + subject do + new_form_class.convert_location_of_death + end + + context 'with no location of death' do + it 'returns nil' do + expect(subject).to eq(nil) + end + end + + context 'with a regular location of death' do + let(:form_data) do + { + 'locationOfDeath' => { + 'location' => 'nursingHomeUnpaid' + } + } + end + + it 'returns the directly mapped location' do + subject + expect(class_form_data['locationOfDeath']['checkbox']).to eq({ 'nursingHomeUnpaid' => 'On' }) + end + end + + context 'with a location needed for translation' do + let(:form_data) do + { + 'locationOfDeath' => { + 'location' => 'atHome' + } + } + end + + it 'returns the directly mapped location' do + subject + expect(class_form_data['locationOfDeath']['checkbox']).to eq({ 'nursingHomeUnpaid' => 'On' }) + end + end + end + + describe '#merge_fields' do + it 'merges the right fields', run_at: '2024-03-21 00:00:00 EDT' do + expect(described_class.new(get_fixture('pdf_fill/21P-530V2/kitchen_sink')).merge_fields.to_json).to eq( + get_fixture('pdf_fill/21P-530V2/merge_fields').to_json + ) + end + end +end diff --git a/spec/models/saved_claim/burial_spec.rb b/spec/models/saved_claim/burial_spec.rb index a606364789a..026298c434e 100644 --- a/spec/models/saved_claim/burial_spec.rb +++ b/spec/models/saved_claim/burial_spec.rb @@ -6,6 +6,7 @@ subject { described_class.new } let(:instance) { FactoryBot.build(:burial_claim) } + let(:instance_v2) { FactoryBot.build(:burial_claim_v2) } it 'responds to #confirmation_number' do expect(subject.confirmation_number).to eq(subject.guid) @@ -27,7 +28,11 @@ end end - context 'a record' do + context 'a record is processed through v1' do + before do + Flipper.disable(:va_burial_v2) + end + it 'inherits init callsbacks from saved_claim' do expect(subject.form_id).to eq(described_class::FORM) expect(subject.guid).not_to be_nil @@ -53,6 +58,38 @@ end end + context 'a record is processed through v2' do + before do + Flipper.enable(:va_burial_v2) + end + + let(:subject_v2) { described_class.new(formV2: true) } + + it 'inherits init callsbacks from saved_claim' do + expect(subject_v2.form_id).to eq('21P-530V2') + expect(subject_v2.guid).not_to be_nil + expect(subject_v2.type).to eq(described_class.to_s) + end + + context 'validates against the form schema' do + before do + expect(instance_v2.valid?).to be(true) + expect(JSON::Validator).to receive(:fully_validate).once.and_call_original + end + + # NOTE: We assume all forms have the privacyAgreementAccepted element. Obviously. + it 'rejects forms with missing elements' do + bad_form = instance_v2.parsed_form.deep_dup + bad_form.delete('privacyAgreementAccepted') + instance_v2.form = bad_form.to_json + instance_v2.remove_instance_variable(:@parsed_form) + expect(instance_v2.valid?).to be(false) + expect(instance_v2.errors.full_messages.size).to eq(1) + expect(instance_v2.errors.full_messages).to include(/privacyAgreementAccepted/) + end + end + end + describe '#email' do it 'returns the users email' do expect(instance.email).to eq('foo@foo.com')