diff --git a/modules/claims_api/app/controllers/claims_api/v2/veterans/disability_compensation_controller.rb b/modules/claims_api/app/controllers/claims_api/v2/veterans/disability_compensation_controller.rb index ef7d5ac7184..6427f500172 100644 --- a/modules/claims_api/app/controllers/claims_api/v2/veterans/disability_compensation_controller.rb +++ b/modules/claims_api/app/controllers/claims_api/v2/veterans/disability_compensation_controller.rb @@ -14,6 +14,7 @@ class DisabilityCompensationController < ClaimsApi::V2::Veterans::Base def submit validate_json_schema + validate_form_526_submission_values! auto_claim = ClaimsApi::AutoEstablishedClaim.create( status: ClaimsApi::AutoEstablishedClaim::PENDING, diff --git a/modules/claims_api/app/controllers/concerns/claims_api/v2/disability_compensation_validation.rb b/modules/claims_api/app/controllers/concerns/claims_api/v2/disability_compensation_validation.rb index 7a63bd21dd0..4fcd05885cc 100644 --- a/modules/claims_api/app/controllers/concerns/claims_api/v2/disability_compensation_validation.rb +++ b/modules/claims_api/app/controllers/concerns/claims_api/v2/disability_compensation_validation.rb @@ -12,7 +12,9 @@ def validate_form_526_submission_values! def validate_form_526_submission_claim_date! return if form_attributes['claimDate'].blank? - return if DateTime.parse(form_attributes['claimDate']) <= Time.zone.now + # EVSS runs in the Central US Time Zone. + # So 'claim_date' needs to be <= current day according to the Central US Time Zone. + return if Date.parse(form_attributes['claimDate']) <= Time.find_zone!('Central Time (US & Canada)').today raise ::Common::Exceptions::InvalidFieldValue.new('claimDate', form_attributes['claimDate']) end diff --git a/modules/claims_api/app/swagger/claims_api/v2/dev/swagger.json b/modules/claims_api/app/swagger/claims_api/v2/dev/swagger.json index 4abddce6105..831a98158a1 100644 --- a/modules/claims_api/app/swagger/claims_api/v2/dev/swagger.json +++ b/modules/claims_api/app/swagger/claims_api/v2/dev/swagger.json @@ -2588,7 +2588,7 @@ ], "properties": { "claimDate": { - "pattern": "^(\\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$", + "pattern": "^(?:[0-9]{4})-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])(?:T[0-1][0-9]:[0-5][0-9]:[0-5][0-9](?:[-+][0-9]{2}:[0-9]{2}|Z))*$", "type": "string", "example": "2018-06-04" }, @@ -4550,8 +4550,8 @@ "id": "1", "type": "intent_to_file", "attributes": { - "creationDate": "2023-05-03", - "expirationDate": "2024-05-03", + "creationDate": "2023-05-04", + "expirationDate": "2024-05-04", "type": "compensation", "status": "active" } diff --git a/modules/claims_api/config/schemas/v2/526.json b/modules/claims_api/config/schemas/v2/526.json index 15c99c91fc8..2ebda4b70df 100644 --- a/modules/claims_api/config/schemas/v2/526.json +++ b/modules/claims_api/config/schemas/v2/526.json @@ -12,7 +12,7 @@ ], "properties": { "claimDate": { - "pattern": "^(\\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$", + "pattern": "^(?:[0-9]{4})-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])(?:T[0-1][0-9]:[0-5][0-9]:[0-5][0-9](?:[-+][0-9]{2}:[0-9]{2}|Z))*$", "type": "string", "example": "2018-06-04" }, diff --git a/modules/claims_api/spec/requests/v2/veterans/disability_compensation_request_spec.rb b/modules/claims_api/spec/requests/v2/veterans/disability_compensation_request_spec.rb index f00929173f3..961fbd85636 100644 --- a/modules/claims_api/spec/requests/v2/veterans/disability_compensation_request_spec.rb +++ b/modules/claims_api/spec/requests/v2/veterans/disability_compensation_request_spec.rb @@ -46,16 +46,54 @@ end let(:add_response) { build(:add_person_response, parsed_codes:) } - before do - Timecop.freeze(Time.parse('2022-05-01 12:00:00 UTC')) - end + # real world example happened in API-15575 + describe "'claim_date' difference between Lighthouse (UTC) and EVSS (Central Time)" do + context 'when UTC is currently a day ahead of the US Central Time Zone' do + context "and 'claim_date' is same as the Central Time Zone day" do + let(:claim_date) { (Time.zone.today - 1.day).to_s } - after do - Timecop.return - end + it 'responds with a 200' do + with_okta_user(scopes) do |auth_header| + VCR.use_cassette('evss/claims/claims') do + VCR.use_cassette('evss/reference_data/countries') do + post path, params: data, headers: headers.merge(auth_header) + expect(response).to have_http_status(:ok) + end + end + end + end + end + + context "and 'claim_date' is earlier than the Central Time Zone day" do + let(:claim_date) { (Time.zone.today - 7.days).to_s } + + it 'responds with a 200' do + with_okta_user(scopes) do |auth_header| + VCR.use_cassette('evss/claims/claims') do + VCR.use_cassette('evss/reference_data/countries') do + post path, params: data, headers: headers.merge(auth_header) + expect(response).to have_http_status(:ok) + end + end + end + end + end + + context "and 'claim_date' is later than both the Central Time Zone day and UTC day" do + let(:claim_date) { (Time.zone.today + 7.days).to_s } + + it 'responds with a bad request' do + with_okta_user(scopes) do |auth_header| + VCR.use_cassette('evss/claims/claims') do + post path, params: data, headers: headers.merge(auth_header) + expect(response).to have_http_status(:bad_request) + end + end + end + end + end - describe "'claim_date'" do - context 'when it is the appropriate time range' do + context 'when UTC is same day as the US Central Time Zone day' do context "and 'claim_date' is the current day" do let(:claim_date) { Time.zone.today.to_s } @@ -85,9 +123,89 @@ end end end - end - context 'when it is formatted' do + context "and 'claim_date' is in the future" do + let(:claim_date) { (Time.zone.today + 7.days).to_s } + + it 'responds with bad request' do + with_okta_user(scopes) do |auth_header| + VCR.use_cassette('evss/claims/claims') do + post path, params: data, headers: headers.merge(auth_header) + expect(response).to have_http_status(:bad_request) + end + end + end + end + + context "and 'claim_date' has timezone (iso w/Z)" do + let(:claim_date) { 1.day.ago.iso8601 } + + it 'responds with a 200' do + with_okta_user(scopes) do |auth_header| + VCR.use_cassette('evss/claims/claims') do + VCR.use_cassette('evss/reference_data/countries') do + post path, params: data, headers: headers.merge(auth_header) + expect(response).to have_http_status(:ok) + end + end + end + end + end + + context "and 'claim_date' has timezone (iso wo/Z)" do + let(:claim_date) { 1.day.ago.iso8601.sub('Z', '-00:00') } + + it 'responds with a 200' do + with_okta_user(scopes) do |auth_header| + VCR.use_cassette('evss/claims/claims') do + VCR.use_cassette('evss/reference_data/countries') do + post path, params: data, headers: headers.merge(auth_header) + expect(response).to have_http_status(:ok) + end + end + end + end + end + + context "and 'claim_date' has timezone (iso w/out zone)" do + let(:claim_date) { 1.day.ago.iso8601.sub('Z', '') } + + it 'responds with a bad request' do + with_okta_user(scopes) do |auth_header| + VCR.use_cassette('evss/claims/claims') do + post path, params: data, headers: headers.merge(auth_header) + expect(response).to have_http_status(:unprocessable_entity) + end + end + end + end + + context "and 'claim_date' has timezone (TZ String)" do + let(:claim_date) { 1.day.ago.to_s } + + it 'responds with a 422' do + with_okta_user(scopes) do |auth_header| + VCR.use_cassette('evss/claims/claims') do + post path, params: data, headers: headers.merge(auth_header) + expect(response).to have_http_status(:unprocessable_entity) + end + end + end + end + + context "and 'claim_date' has timezone (w/out T)" do + let(:claim_date) { 1.day.ago.iso8601.sub('T', ' ') } + + it 'responds with a 422' do + with_okta_user(scopes) do |auth_header| + VCR.use_cassette('evss/claims/claims') do + post path, params: data, headers: headers.merge(auth_header) + expect(response).to have_http_status(:unprocessable_entity) + end + end + end + end + context "and 'claim_date' improperly formatted (hello world)" do let(:claim_date) { 'hello world' } @@ -115,6 +233,58 @@ end end end + + describe 'schema catches claimProcessType error' do + context 'when something other than an enum option is used' do + let(:claim_process_type) { 'claim_test' } + + it 'responds with bad request' do + with_okta_user(scopes) do |auth_header| + VCR.use_cassette('evss/claims/claims') do + json = JSON.parse(data) + json['data']['attributes']['claimProcessType'] = claim_process_type + data = json + post path, params: data, headers: headers.merge(auth_header) + expect(response).to have_http_status(:unprocessable_entity) + end + end + end + end + + context 'when an empty string is provided' do + let(:claim_process_type) { ' ' } + + it 'responds with bad request' do + with_okta_user(scopes) do |auth_header| + VCR.use_cassette('evss/claims/claims') do + json = JSON.parse(data) + json['data']['attributes']['claimProcessType'] = claim_process_type + data = json + post path, params: data, headers: headers.merge(auth_header) + expect(response).to have_http_status(:unprocessable_entity) + end + end + end + end + end + + describe 'validation of claimant certification' do + context 'when the cert is false' do + let(:claimant_certification) { false } + + it 'responds with a bad request' do + with_okta_user(scopes) do |auth_header| + VCR.use_cassette('evss/claims/claims') do + json = JSON.parse(data) + json['data']['attributes']['claimantCertification'] = claimant_certification + data = json + post path, params: data, headers: headers.merge(auth_header) + expect(response).to have_http_status(:unprocessable_entity) + end + end + end + end + end end context 'validate' do