Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NJ 140 - fix XML errors and add schema validation to all XML tests #4925

Merged
merged 5 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/lib/efile/nj/nj1040_calculator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ def calculate_line_15

sum = 0
@intake.state_file_w2s.each do |w2|
state_wage = w2.state_wages_amount
state_wage = w2.state_wages_amount.to_i
sum += state_wage
end
sum
Expand Down
6 changes: 2 additions & 4 deletions spec/factories/state_file_nj_intakes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
raw_direct_file_intake_data { StateFile::DirectFileApiResponseSampleService.new.read_json('nj_zeus_one_dep') }

after(:build) do |intake, evaluator|
intake.municipality_code = "0101"
numeric_status = {
single: 1,
married_filing_jointly: 2,
Expand All @@ -133,16 +134,13 @@
end
intake.update(overrides)

intake.synchronize_df_w2s_to_database
aloverso marked this conversation as resolved.
Show resolved Hide resolved
intake.synchronize_df_dependents_to_database
intake.dependents.each_with_index do |dependent, i|
dependent.update(dob: i.years.ago)
end
end

trait :with_w2s_synced do
after(:create, &:synchronize_df_w2s_to_database)
end

trait :df_data_2_w2s do
raw_direct_file_data { StateFile::DirectFileApiResponseSampleService.new.read_xml('nj_zeus_two_w2s') }
raw_direct_file_intake_data { StateFile::DirectFileApiResponseSampleService.new.read_json('nj_zeus_two_w2s') }
Expand Down
8 changes: 3 additions & 5 deletions spec/lib/efile/nj/nj1040_calculator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -366,25 +366,23 @@ def over_65_birth_year
let(:intake) { create(:state_file_nj_intake) }

context 'when no state file w2s' do
let(:intake) { create(:state_file_nj_intake, :df_data_minimal) }
it 'sets line 15 to -1 to indicate the sum does not exist' do
expect(instance.lines[:NJ1040_LINE_15].value).to eq(-1)
end
end

context 'when 2 state file w2s' do
let(:intake) { create(:state_file_nj_intake, :df_data_2_w2s) }
it 'sets line 15 to the sum of all state wage amounts' do
create(:state_file_w2, state_file_intake: intake, state_wages_amount: 12345)
create(:state_file_w2, state_file_intake: intake, state_wages_amount: 50000)
instance.calculate
expected_sum = 12345 + 50000
expect(instance.lines[:NJ1040_LINE_15].value).to eq(expected_sum)
end
end

context 'when many state file w2s' do
let(:intake) { create(:state_file_nj_intake, :df_data_many_w2s) }
it 'sets line 15 to the sum of all state wage amounts' do
4.times { create(:state_file_w2, state_file_intake: intake, state_wages_amount: 50000) }
instance.calculate
expected_sum = 50000 + 50000 + 50000 + 50000
expect(instance.lines[:NJ1040_LINE_15].value).to eq(expected_sum)
end
Expand Down
26 changes: 8 additions & 18 deletions spec/lib/pdf_filler/nj1040_pdf_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -638,8 +638,7 @@
let(:submission) {
create :efile_submission, tax_return: nil, data_source: create(
:state_file_nj_intake,
:df_data_many_w2s,
:with_w2s_synced
:df_data_many_w2s
)
}

Expand All @@ -665,8 +664,7 @@
let(:submission) {
create :efile_submission, tax_return: nil, data_source: create(
:state_file_nj_intake,
:df_data_2_w2s,
:with_w2s_synced
:df_data_2_w2s
)
}

Expand Down Expand Up @@ -800,8 +798,7 @@
let(:submission) {
create :efile_submission, tax_return: nil, data_source: create(
:state_file_nj_intake,
:df_data_many_w2s,
:with_w2s_synced
:df_data_many_w2s
)
}
it "fills in the total income boxes in the PDF on line 27 with the rounded value" do
Expand Down Expand Up @@ -855,8 +852,7 @@
let(:submission) {
create :efile_submission, tax_return: nil, data_source: create(
:state_file_nj_intake,
:df_data_many_w2s,
:with_w2s_synced
:df_data_many_w2s
)
}
it "fills in the gross income boxes in the PDF on line 29 with the rounded value" do
Expand Down Expand Up @@ -911,7 +907,6 @@
create :efile_submission, tax_return: nil, data_source: create(
:state_file_nj_intake,
:df_data_many_w2s,
:with_w2s_synced,
medical_expenses: 567_890
)
}
Expand All @@ -935,7 +930,6 @@
create :efile_submission, tax_return: nil, data_source: create(
:state_file_nj_intake,
:df_data_many_w2s,
:with_w2s_synced,
medical_expenses: 4000
)
}
Expand Down Expand Up @@ -981,7 +975,7 @@
describe "line 39 taxable income" do
let(:submission) {
create :efile_submission, tax_return: nil, data_source: create(
:state_file_nj_intake, :df_data_many_w2s, :with_w2s_synced
:state_file_nj_intake, :df_data_many_w2s
)
}
it "writes taxable income $199,000 (200,000-1000) to fill boxes on line 39" do
Expand Down Expand Up @@ -1038,7 +1032,6 @@
let(:submission) {
create :efile_submission, tax_return: nil, data_source: create(
:state_file_nj_intake,
:with_w2s_synced,
household_rent_own: 'own',
property_tax_paid: 12345678
)
Expand Down Expand Up @@ -1096,7 +1089,6 @@
create :efile_submission, tax_return: nil, data_source: create(
:state_file_nj_intake,
:df_data_many_w2s,
:with_w2s_synced,
household_rent_own: 'own',
property_tax_paid: 15_000,
)
Expand Down Expand Up @@ -1144,7 +1136,7 @@
describe "line 42 new jersey taxable income" do
let(:submission) {
create :efile_submission, tax_return: nil, data_source: create(
:state_file_nj_intake, :df_data_many_w2s, :with_w2s_synced
:state_file_nj_intake, :df_data_many_w2s
)
}
it "writes new jersey taxable income $199,000 (200,000-1000) to fill boxes on line 39" do
Expand All @@ -1171,7 +1163,6 @@
create :efile_submission, tax_return: nil, data_source: create(
:state_file_nj_intake,
:df_data_many_w2s,
:with_w2s_synced,
:married_filing_jointly,
household_rent_own: 'own',
property_tax_paid: 15_000,
Expand Down Expand Up @@ -1240,7 +1231,7 @@

describe "line 64 child and dependent care credit" do
let(:intake) {
create(:state_file_nj_intake, :df_data_one_dep, :with_w2s_synced, :fed_credit_for_child_and_dependent_care)
create(:state_file_nj_intake, :df_data_one_dep, :fed_credit_for_child_and_dependent_care)
}
let(:submission) {
create :efile_submission, tax_return: nil, data_source: intake
Expand Down Expand Up @@ -1268,8 +1259,7 @@
let(:intake) {
create(
:state_file_nj_intake,
:df_data_one_dep,
:with_w2s_synced
:df_data_one_dep
)
}
let(:submission) {
Expand Down
86 changes: 13 additions & 73 deletions spec/lib/submission_builder/state_return_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,89 +18,29 @@
states_requiring_w2s.each do |state_code|
describe "#combined_w2s", required_schema: state_code do
let(:builder_class) { StateFile::StateInformationService.submission_builder_class(state_code) }
let(:intake) { create("state_file_#{state_code}_intake".to_sym, filing_status: filing_status) }
let(:intake) { create("state_file_#{state_code}_intake".to_sym) }
let(:submission) { create(:efile_submission, data_source: intake) }
let(:vars) { spec_vars[state_code.to_sym] || spec_vars[:default] }
before do
intake.synchronize_df_w2s_to_database
end

context "#{state_code}: when there are w2s present" do
let(:filing_status) { 'single' }

context "when the intake does not have any state_file_w2s" do
it "copies all w2s from the direct file xml field" do
xml = Nokogiri::XML::Document.parse(builder_class.build(submission).document.to_xml)
expect(xml.css(vars[:w2_node_name]).count).to eq intake.direct_file_data.w2s.length
end
end

context "when the intake has state_file_w2s" do
context "create, update, delete nodes" do
let(:intake) { create "state_file_#{state_code}_intake".to_sym, :df_data_2_w2s }
let!(:state_file_w2) {
create(
:state_file_w2,
state_file_intake: intake,
w2_index: 1,
employer_state_id_num: "00123",
local_income_tax_amount: "0",
local_wages_and_tips_amount: "2000",
locality_nm: intake.direct_file_data.w2s[0].LocalityNm,
state_income_tax_amount: "700",
state_wages_amount: "2000",
)
}
before do
xml = Nokogiri::XML(intake.raw_direct_file_data)
xml.search(vars[:w2_node_name]).each_with_index do |w2, i|
if i == 1
w2.at("StateWagesAmt").remove
end
end
intake.update(raw_direct_file_data: xml.to_xml)
end

it "prioritises state_file_w2s over w2s from the direct file xml, correctly updates & creates & deletes nodes" do
it "copies the state and local tags from the state_file_w2s table into the state return xml" do
xml = Nokogiri::XML::Document.parse(builder_class.build(submission).document.to_xml)

# w2 at index 0 remains the same
w2_from_xml = xml.css(vars[:w2_node_name])[0]
expect(w2_from_xml.at(vars[:employer_state_id_num_name]).text).to eq intake.direct_file_data.w2s[0].node.at("W2StateLocalTaxGrp EmployerStateIdNum").text
expect(w2_from_xml.at("LocalIncomeTaxAmt").text).to eq intake.direct_file_data.w2s[0].node.at("W2StateLocalTaxGrp LocalIncomeTaxAmt").text
expect(w2_from_xml.at("LocalWagesAndTipsAmt").text).to eq intake.direct_file_data.w2s[0].node.at("W2StateLocalTaxGrp LocalWagesAndTipsAmt").text
expect(w2_from_xml.at(vars[:locality_name]).text).to eq intake.direct_file_data.w2s[0].node.at("W2StateLocalTaxGrp LocalityNm").text.upcase
expect(w2_from_xml.at("StateIncomeTaxAmt").text).to eq intake.direct_file_data.w2s[0].node.at("W2StateLocalTaxGrp StateIncomeTaxAmt").text
expect(w2_from_xml.at("StateWagesAmt").text).to eq intake.direct_file_data.w2s[0].node.at("W2StateLocalTaxGrp StateWagesAmt").text

# w2 at index 1 is filled in with info from client
w2_from_db = xml.css(vars[:w2_node_name])[1]
expect(w2_from_db.at(vars[:employer_state_id_num_name]).text).to eq state_file_w2.employer_state_id_num
expect(w2_from_db.at("LocalIncomeTaxAmt").text).to eq state_file_w2.local_income_tax_amount.round.to_s
expect(w2_from_db.at("LocalWagesAndTipsAmt").text).to eq state_file_w2.local_wages_and_tips_amount.round.to_s
expect(w2_from_db.at(vars[:locality_name]).text).to eq state_file_w2.locality_nm
expect(w2_from_db.at("StateIncomeTaxAmt").text).to eq state_file_w2.state_income_tax_amount.round.to_s
expect(w2_from_db.at("StateWagesAmt").text).to eq state_file_w2.state_wages_amount.round.to_s
end
end

context "updating multiple w2s" do
let(:intake) { create "state_file_#{state_code}_intake".to_sym, :df_data_many_w2s }
let!(:original_w2_count) { intake.direct_file_data.w2s.length }
let!(:w2_1) { create(:state_file_w2, state_file_intake: intake, w2_index: 0) }
let!(:w2_2) { create(:state_file_w2, state_file_intake: intake, w2_index: 1) }
let!(:w2_3) { create(:state_file_w2, state_file_intake: intake, w2_index: 2) }
let!(:w2_4) { create(:state_file_w2, state_file_intake: intake, w2_index: 3) }

it "updates the correct tags" do
w2 = vars[:w2_node_name]
generated_document = Nokogiri::XML::Document.parse(builder_class.build(submission).document.to_xml, &:noblanks)

expect(generated_document.css(w2).count).to eq original_w2_count
(0..3).each do |i|
expect(generated_document.css(w2)[i].at(vars[:employer_state_id_num_name]).text).to eq send("w2_#{i+1}").employer_state_id_num
expect(generated_document.css(w2)[i].at("LocalIncomeTaxAmt").text).to eq send("w2_#{i+1}").local_income_tax_amount.round.to_s
expect(generated_document.css(w2)[i].at("LocalWagesAndTipsAmt").text).to eq send("w2_#{i+1}").local_wages_and_tips_amount.round.to_s
expect(generated_document.css(w2)[i].at(vars[:locality_name]).text).to eq send("w2_#{i+1}").locality_nm
expect(generated_document.css(w2)[i].at("StateIncomeTaxAmt").text).to eq send("w2_#{i+1}").state_income_tax_amount.round.to_s
expect(generated_document.css(w2)[i].at("StateWagesAmt").text).to eq send("w2_#{i+1}").state_wages_amount.round.to_s
intake.state_file_w2s.each_with_index do |state_file_w2, index|
w2_xml = xml.css(vars[:w2_node_name])[index]
expect(w2_xml.at(vars[:employer_state_id_num_name]).text).to eq state_file_w2.employer_state_id_num
expect(w2_xml.at("LocalIncomeTaxAmt").text).to eq state_file_w2.local_income_tax_amount.round.to_s
expect(w2_xml.at("LocalWagesAndTipsAmt").text).to eq state_file_w2.local_wages_and_tips_amount.round.to_s
expect(w2_xml.at(vars[:locality_name]).text).to eq state_file_w2.locality_nm if state_file_w2.locality_nm.present?
expect(w2_xml.at("StateIncomeTaxAmt").text).to eq state_file_w2.state_income_tax_amount.round.to_s
expect(w2_xml.at("StateWagesAmt").text).to eq state_file_w2.state_wages_amount.round.to_s
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,22 @@

describe SubmissionBuilder::Ty2024::States::Nj::Documents::Nj1040, required_schema: "nj" do
describe ".document" do
let(:intake) { create(:state_file_nj_intake, filing_status: "single", municipality_code: "0101") }
let(:intake) { create(:state_file_nj_intake, filing_status: "single") }
let(:submission) { create(:efile_submission, data_source: intake) }
let(:build_response) { described_class.build(submission, validate: false) }
let(:build_response) { described_class.build(submission, validate: true) }
let(:xml) { Nokogiri::XML::Document.parse(build_response.document.to_xml) }

it "includes municipality code with a prepending 0" do
xml = described_class.build(submission).document
expect(xml.document.at("CountyCode").to_s).to include("00101")
after(:each) do
expect(build_response.errors).not_to be_present
aloverso marked this conversation as resolved.
Show resolved Hide resolved
end

context "with municipality code" do
let(:intake) { create(:state_file_nj_intake, municipality_code: "0304") }

it "includes municipality code with a prepending 0" do
xml = described_class.build(submission).document
expect(xml.document.at("CountyCode").to_s).to include("00304")
end
end

context "when filer has no spouse" do
Expand Down Expand Up @@ -333,7 +341,7 @@

describe "line 31 medical expenses" do
context "with an income of 200k" do
let(:intake) { create(:state_file_nj_intake, :df_data_many_w2s, :with_w2s_synced, medical_expenses: 10_000) }
let(:intake) { create(:state_file_nj_intake, :df_data_many_w2s, medical_expenses: 10_000) }
it "fills MedicalExpenses with medical expenses exceeding two percent gross income" do
expected_line_15_w2_wages = 200_000
two_percent_gross = expected_line_15_w2_wages * 0.02
Expand Down Expand Up @@ -425,7 +433,8 @@
describe "property tax deduction - line 41" do
context 'when taking property tax deduction' do
it "fills PropertyTaxDeduction with property tax deduction amount" do
allow_any_instance_of(Efile::Nj::Nj1040Calculator).to receive(:calculate_line_41).and_return 15000
allow_any_instance_of(Efile::Nj::Nj1040Calculator).to receive(:calculate_property_tax_deduction).and_return 15000
allow_any_instance_of(Efile::Nj::Nj1040Calculator).to receive(:should_use_property_tax_deduction).and_return true
aloverso marked this conversation as resolved.
Show resolved Hide resolved
expect(xml.at("PropertyTaxDeduction").text).to eq(15000.to_s)
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@
end

context "with one dep" do
let(:intake) { create(:state_file_nj_intake, :df_data_one_dep, municipality_code: "0101") }
let(:intake) { create(:state_file_nj_intake, :df_data_one_dep) }
it "does not error" do
builder_response = described_class.build(submission)
expect(builder_response.errors).not_to be_present
expect(builder_response.document.at("WagesSalariesTips").text).not_to eq(nil)
expect(builder_response.document.at("NewJerseyTaxableIncome").text).not_to eq(nil)
aloverso marked this conversation as resolved.
Show resolved Hide resolved
end

it "fills details from json" do
Expand All @@ -41,15 +43,15 @@
end

context "with two deps" do
let(:intake) { create(:state_file_nj_intake, :df_data_two_deps, municipality_code: "0101") }
let(:intake) { create(:state_file_nj_intake, :df_data_two_deps) }
it "does not error" do
builder_response = described_class.build(submission)
expect(builder_response.errors).not_to be_present
end
end

context "with many deps all under 5 yrs old" do
let(:intake) { create(:state_file_nj_intake, :df_data_many_deps, municipality_code: "0101") }
let(:intake) { create(:state_file_nj_intake, :df_data_many_deps) }

before do
five_years = Date.new(MultiTenantService.new(:statefile).current_tax_year - 5, 1, 1)
Expand All @@ -65,15 +67,15 @@
end

context "with many w2s" do
let(:intake) { create(:state_file_nj_intake, municipality_code: "0101", raw_direct_file_data: StateFile::DirectFileApiResponseSampleService.new.read_xml('nj_zeus_many_w2s')) }
let(:intake) { create(:state_file_nj_intake, :df_data_many_w2s) }
it "does not error" do
builder_response = described_class.build(submission)
expect(builder_response.errors).not_to be_present
end
end

context "with two w2s" do
let(:intake) { create(:state_file_nj_intake, municipality_code: "0101", raw_direct_file_data: StateFile::DirectFileApiResponseSampleService.new.read_xml('nj_zeus_two_w2s')) }
let(:intake) { create(:state_file_nj_intake, :df_data_2_w2s) }
it "does not error" do
builder_response = described_class.build(submission)
expect(builder_response.errors).not_to be_present
Expand Down
Loading