Skip to content

Commit

Permalink
Merge pull request #19270 from department-of-veterans-affairs/feature…
Browse files Browse the repository at this point in the history
…/APPEALS-15378

Feature/appeals 15378 add EIN field to unrecognized claimant
  • Loading branch information
craigrva authored Sep 29, 2023
2 parents a499aa6 + bc04109 commit 1ed29e3
Show file tree
Hide file tree
Showing 14 changed files with 94 additions and 13 deletions.
2 changes: 1 addition & 1 deletion app/controllers/unrecognized_appellants_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def unrecognized_appellant_params
def unrecognized_party_details
[
:party_type, :name, :middle_name, :last_name, :suffix, :address_line_1, :address_line_2, :date_of_birth,
:address_line_3, :city, :state, :zip, :country, :phone_number, :email_address
:address_line_3, :city, :state, :zip, :country, :phone_number, :email_address, :ein, :ssn
]
end
end
2 changes: 1 addition & 1 deletion app/models/concerns/has_unrecognized_party_detail.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module HasUnrecognizedPartyDetail
extend ActiveSupport::Concern

included do
delegate :name, :first_name, :middle_name, :last_name, :suffix, :ssn,
delegate :name, :first_name, :middle_name, :last_name, :suffix, :ein, :ssn,
:address, :address_line_1, :address_line_2, :address_line_3,
:city, :state, :zip, :country, :date_of_birth,
:phone_number, :email_address, :party_type,
Expand Down
2 changes: 1 addition & 1 deletion app/models/other_claimant.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# Currently used for attorney fee cases when the attorney isn't found in the BGS attorney database.

class OtherClaimant < Claimant
delegate :name, :first_name, :middle_name, :last_name, :suffix, :ssn,
delegate :name, :first_name, :middle_name, :last_name, :suffix, :ein, :ssn,
:address, :address_line_1, :address_line_2, :address_line_3,
:city, :state, :zip, :country, :date_of_birth,
:email_address, :phone_number,
Expand Down
4 changes: 3 additions & 1 deletion client/COPY.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"AGE_MAX_ERR": "Appellant cannot be older than 118 years of age."
},
"SSN_INVALID_ERR": "Please enter a valid social security number that follows the format: 123-45-6789 or 123456789",
"EIN_INVALID_ERR": "Please enter a valid employer identification number that follows the format: 12-3456789 or 123456789",
"NULL_FILTER_LABEL": "<<blank>>",
"OTHER_REVIEWS_TABLE_TITLE": "Higher Level Reviews & Supplemental Claims",
"OTHER_REVIEWS_TABLE_EP_CODE_COLUMN_TITLE": "EP Codes",
Expand Down Expand Up @@ -1394,5 +1395,6 @@
"NO_DATE_ENTERED": "No date entered",
"REFRESH_POA": "Refresh POA",
"POA_SUCCESSFULLY_REFRESH_MESSAGE": "Successfully refreshed. No power of attorney information was found at this time.",
"POA_UPDATED_SUCCESSFULLY": "POA Updated Successfully"
"POA_UPDATED_SUCCESSFULLY": "POA Updated Successfully",
"EMPLOYER_IDENTIFICATION_NUMBER": "Employer Identification Number"
}
15 changes: 14 additions & 1 deletion client/app/intake/addClaimant/ClaimantForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import styled from 'styled-components';

import * as Constants from '../constants';
import { fetchAttorneys, formatAddress } from './utils';
import { ADD_CLAIMANT_PAGE_DESCRIPTION, ERROR_EMAIL_INVALID_FORMAT } from 'app/../COPY';
import { ADD_CLAIMANT_PAGE_DESCRIPTION, ERROR_EMAIL_INVALID_FORMAT, EMPLOYER_IDENTIFICATION_NUMBER } from 'app/../COPY';

import Address from 'app/queue/components/Address';
import AddressForm from 'app/components/AddressForm';
Expand Down Expand Up @@ -61,6 +61,7 @@ export const ClaimantForm = ({
const emailValidationError = errors?.emailAddress && ERROR_EMAIL_INVALID_FORMAT;
const dobValidationError = errors?.dateOfBirth && errors.dateOfBirth.message;
const ssnValidationError = errors?.ssn && errors.ssn.message;
const einValidationError = errors?.ein && errors.ein.message;

const watchRelationship = watch('relationship');
const dependentRelationship = ['spouse', 'child'].includes(watchRelationship);
Expand Down Expand Up @@ -253,6 +254,18 @@ export const ClaimantForm = ({
/>
</FieldDiv>
)}
{isOrgPartyType && isHLROrSCForm && (
<FieldDiv>
<TextField
validationError={einValidationError}
name="ein"
label={EMPLOYER_IDENTIFICATION_NUMBER}
inputRef={register}
strongLabel
optional
/>
</FieldDiv>
)}
{partyType && (
<>
<AddressForm
Expand Down
12 changes: 11 additions & 1 deletion client/app/intake/addClaimant/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { camelCase, reduce, startCase } from 'lodash';
import { FORM_TYPES } from '../constants';

import ApiUtil from 'app/util/ApiUtil';
import { DOB_INVALID_ERRS, SSN_INVALID_ERR } from 'app/../COPY';
import { DOB_INVALID_ERRS, SSN_INVALID_ERR, EIN_INVALID_ERR } from 'app/../COPY';

const { AGE_MIN_ERR, AGE_MAX_ERR } = DOB_INVALID_ERRS;

Expand All @@ -21,6 +21,7 @@ const yearsFromToday = (years) => {
};

const ssnRegex = /^(?!000|666)[0-9]{3}([ -]?)(?!00)[0-9]{2}\1(?!0000)[0-9]{4}$/gm;
const einRegex = /^(?!00)[0-9]{2}([ -]?)(?!0000000)[0-9]{7}$/gm;

const sharedValidation = {
relationship: yup.string().when(['$hideListedAttorney'], {
Expand Down Expand Up @@ -117,6 +118,14 @@ export const schemaHLR = yup.object().shape({
message: SSN_INVALID_ERR,
excludeEmptyString: true
}
),
ein: yup.string().
matches(
einRegex,
{
message: EIN_INVALID_ERR,
excludeEmptyString: true
}
),
...sharedValidation,
});
Expand All @@ -125,6 +134,7 @@ export const defaultFormValues = {
relationship: null,
partyType: null,
name: '',
ein: '',
firstName: '',
middleName: '',
lastName: '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,20 @@ describe('HlrScClaimantForm', () => {
});
};

const validatePresenceOfEin = async (optionNum) => {
await selectRelationship(optionNum);

await userEvent.click(
screen.getByRole('radio', { name: /organization/i })
);

await waitFor(() => {
expect(
screen.getByRole('textbox', { name: /Employer Identification Number/i })
).toBeInTheDocument();
});
}

it('renders default state correctly', () => {
const { container } = setup();

Expand Down Expand Up @@ -201,6 +215,7 @@ describe('HlrScClaimantForm', () => {
screen.getByRole('radio', { name: /organization/i })
);

screen.debug(undefined, Infinity);
expect(container).toMatchSnapshot();

// Set type to individual
Expand Down Expand Up @@ -232,4 +247,10 @@ describe('HlrScClaimantForm', () => {
expect(container).toMatchSnapshot();
});

it('validate the presence of Employer Identification number for Organizations', async () => {
setup();
validatePresenceOfEin(relationshipOptsHlrSc.map((r) => r.value).indexOf('healthcare_provider'));
validatePresenceOfEin(relationshipOptsHlrSc.map((r) => r.value).indexOf('other'));
}, 15000);

});
9 changes: 8 additions & 1 deletion client/test/app/intake/components/addClaimants/testUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,21 @@ const street1 = '1000 Monticello';
const city = 'Washington';
const zip = '20000';
const country = 'USA';
const ein = '123456789'

export const fillForm = async () => {
export const fillForm = async (isHLROrSCForm = false) => {
// Enter organization
await userEvent.type(
screen.getByRole('textbox', { name: /Organization name/i }),
organization
);

if (isHLROrSCForm) {
await userEvent.type(
screen.getByRole('textbox', { name: /employer identification number/i }),
ein
);
}
// Enter Street1
await userEvent.type(
screen.getByRole('textbox', { name: /Street address 1/i }),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ exports[`EditPOAInformation renders default state correctly 1`] = `
"city": "",
"country": "",
"dateOfBirth": null,
"ein": "",
"emailAddress": "",
"firstName": "",
"lastName": "",
Expand Down Expand Up @@ -198,6 +199,7 @@ exports[`EditPOAInformation renders default state correctly 1`] = `
"city": "",
"country": "",
"dateOfBirth": null,
"ein": "",
"emailAddress": "",
"firstName": "",
"lastName": "",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddEinToUnrecognizedPartyDetails < Caseflow::Migration
def change
add_column :unrecognized_party_details, :ein, :string, comment: "PII. Employer Identification Number"
end
end
3 changes: 2 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 2023_08_01_195310) do
ActiveRecord::Schema.define(version: 2023_08_14_133820) do

# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
Expand Down Expand Up @@ -1790,6 +1790,7 @@
t.string "country", null: false
t.datetime "created_at", null: false
t.date "date_of_birth", comment: "PII"
t.string "ein", comment: "PII. Employer Identification Number"
t.string "email_address", comment: "PII"
t.string "last_name", comment: "PII"
t.string "middle_name", comment: "PII"
Expand Down
5 changes: 4 additions & 1 deletion spec/controllers/unrecognized_appellant_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
let(:updated_relationship) { "updated" }
let(:updated_address_1) { "updated_address_1" }
let(:updated_address_2) { "updated_address_2" }
let(:ein) { "1234567" }
let(:params) do
{
relationship: updated_relationship,
unrecognized_party_detail: {
address_line_1: updated_address_1,
address_line_2: updated_address_2
address_line_2: updated_address_2,
ein: ein
}
}
end
Expand Down Expand Up @@ -43,6 +45,7 @@
expect(response_body["relationship"]).to eq updated_relationship
expect(response_body["unrecognized_party_detail"]["address_line_1"]).to eq updated_address_1
expect(response_body["unrecognized_party_detail"]["address_line_2"]).to eq updated_address_2
expect(response_body["unrecognized_party_detail"]["ein"]).to eq ein

expect(ua.current_version.relationship).to eq updated_relationship
expect(ua.first_version.relationship).to eq original_relationship
Expand Down
23 changes: 19 additions & 4 deletions spec/feature/intake/hlr_sc_non_veteran_claimants_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@
state: "CA",
zip: "94123",
country: "United States",
email: "claimant@example.com"
email: "claimant@example.com",
ein: "11-0999001"
}
end

Expand Down Expand Up @@ -89,7 +90,8 @@
full_state: "New York",
zip: "10001",
country: "United States",
email: "attorney@example.com"
email: "attorney@example.com",
ein: "123456789"
}
end

Expand Down Expand Up @@ -142,6 +144,7 @@ def add_new_individual_claimant

def add_new_organization_claimant
fill_in "Organization name", with: new_organization_claimant[:organization_name]
fill_in "Employer Identification Number", with: new_organization_claimant[:ein]
fill_in "Street address 1", with: new_organization_claimant[:address1]
fill_in "City", with: new_organization_claimant[:city]
fill_in("State", with: new_organization_claimant[:state]).send_keys :enter
Expand All @@ -150,14 +153,15 @@ def add_new_organization_claimant
fill_in "Claimant email", with: new_organization_claimant[:email]
end

def add_new_organization_attorney
def add_new_organization_attorney(poa = false)
fill_in "Organization name", with: new_organization_attorney[:organization_name]
fill_in "Street address 1", with: new_organization_attorney[:address1]
fill_in "City", with: new_organization_attorney[:city]
fill_in("State", with: new_organization_attorney[:state]).send_keys :enter
fill_in("Zip", with: new_organization_attorney[:zip]).send_keys :enter
fill_in("Country", with: new_organization_attorney[:country]).send_keys :enter
fill_in "Representative email", with: new_organization_attorney[:email]
fill_in "Employer Identification Number", with: new_organization_claimant[:ein] unless poa == true
end

def add_new_individual_attorney
Expand Down Expand Up @@ -281,7 +285,10 @@ def verify_individual_claimant_on_add_issues
end

def verify_organization_claimant_on_add_issues
expect(page).to have_current_path("/intake/add_issues")
expect(page).to have_content("Add / Remove Issues")
expect(page).to have_text("Ed Merica (123412345)")
expect(page).to have_text("Education")
# Fix the attorney string for the test
claimant_type_string = (claimant_type == "Attorney (previously or currently)") ? "Attorney" : claimant_type
claimant_string = "#{new_organization_claimant[:organization_name]}, #{claimant_type_string}"
Expand All @@ -308,6 +315,11 @@ def add_existing_attorney_on_poa_page(attorney)
find("div", class: "cf-select__option", text: attorney.name).click
end

def validate_ein_error_message
fill_in "Employer Identification Number", with: "exsdasd"
expect(page).to have_content(COPY::EIN_INVALID_ERR)
end

shared_examples "HLR/SC intake unlisted claimant" do
scenario "creating a HLR/SC intake with an unlisted claimant - verify dropdown relationship options" do
start_intake
Expand Down Expand Up @@ -355,6 +367,7 @@ def add_existing_attorney_on_poa_page(attorney)
fill_in("Claimant's name", with: "Name not listed")
find("div", class: "cf-select__option", text: "Name not listed").click
select_organization_party_type
validate_ein_error_message
add_new_organization_claimant
click_button "Continue to next step"
expect(page).to have_content("Review and confirm claimant information")
Expand Down Expand Up @@ -410,6 +423,7 @@ def add_existing_attorney_on_poa_page(attorney)
advance_to_add_unlisted_claimant_page

select_organization_party_type
validate_ein_error_message
add_new_organization_claimant
click_does_not_have_va_form
click_button "Continue to next step"
Expand Down Expand Up @@ -445,6 +459,7 @@ def add_existing_attorney_on_poa_page(attorney)
"healthcare provider with type organization" do
advance_to_add_unlisted_claimant_page
select_organization_party_type
validate_ein_error_message
add_new_organization_claimant
click_does_not_have_va_form
click_button "Continue to next step"
Expand Down Expand Up @@ -601,7 +616,7 @@ def add_existing_attorney_on_poa_page(attorney)
fill_in("Representative's name", with: "Name not listed")
find("div", class: "cf-select__option", text: "Name not listed").click
select_attorney_organization_party_type
add_new_organization_attorney
add_new_organization_attorney(true)
click_button "Continue to next step"
verify_add_claimant_modal_information_with_new_attorney(claimant_is_individual: true)
click_button "Confirm"
Expand Down
2 changes: 2 additions & 0 deletions spec/feature/intake/non_veteran_claimants_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@
within_fieldset("Is the claimant an organization or individual?") do
find("label", text: "Organization", match: :prefer_exact).click
end

expect(page).to have_no_content(COPY::EMPLOYER_IDENTIFICATION_NUMBER)
fill_in "Organization name", with: "Attorney's Law Firm"
fill_in "Street address 1", with: "1234 Justice St."
fill_in "City", with: "Anytown"
Expand Down

0 comments on commit 1ed29e3

Please sign in to comment.