diff --git a/app/lib/submission_builder/state1099_r.rb b/app/lib/submission_builder/state1099_r.rb new file mode 100644 index 0000000000..f36cd33ec4 --- /dev/null +++ b/app/lib/submission_builder/state1099_r.rb @@ -0,0 +1,53 @@ +module SubmissionBuilder + class State1099R < SubmissionBuilder::Document + include SubmissionBuilder::FormattingMethods + + def document + form1099r = @kwargs[:form1099r] + state_abbreviation = form1099r.intake.state_code.upcase + + build_xml_doc("IRS1099R", documentId: "IRS1099R-#{form1099r.id}") do |xml| + xml.PayerNameControlTxt form1099r.payer_name_control + if form1099r.payer_name.present? + xml.PayerName do + xml.BusinessNameLine1Txt sanitize_for_xml(form1099r.payer_name.tr('-', ' '), 75) + end + xml.PayerUSAddress do + xml.AddressLine1Txt sanitize_for_xml(form1099r.payer_address_line1, 35) if form1099r.payer_address_line1.present? + xml.AddressLine2Txt sanitize_for_xml(form1099r.payer_address_line2, 35) if form1099r.payer_address_line2.present? + xml.CityNm sanitize_for_xml(form1099r.payer_city_name, 22) if form1099r.payer_city_name.present? + xml.StateAbbreviationCd form1099r.payer_state_code if form1099r.payer_state_code.present? + xml.ZIPCd form1099r.payer_zip if form1099r.payer_zip.present? + end + xml.PayerEIN form1099r.payer_identification_number + xml.RecipientSSN sanitize_for_xml(form1099r.recipient_ssn) if form1099r.recipient_ssn.present? + xml.RecipientNm sanitize_for_xml(form1099r.recipient_name) if form1099r.recipient_name.present? + xml.GrossDistributionAmt form1099r.gross_distribution_amount&.round + xml.TaxableAmt form1099r.taxable_amount&.round + if form1099r.taxable_amount_not_determined? + xml.TxblAmountNotDeterminedInd 'X' + end + if form1099r.total_distribution? + xml.TotalDistributionInd 'X' + end + xml.FederalIncomeTaxWithheldAmt form1099r.federal_income_tax_withheld_amount&.round + xml.F1099RDistributionCd form1099r.distribution_code + xml.DesignatedROTHAcctFirstYr form1099r.designated_roth_account_first_year if form1099r.designated_roth_account_first_year.present? + xml.F1099RStateLocalTaxGrp do + xml.F1099RStateTaxGrp do + xml.StateTaxWithheldAmt form1099r.state_tax_withheld_amount&.round + xml.StateAbbreviationCd form1099r.state_code if form1099r.state_code.present? + xml.PayerStateIdNum form1099r.payer_state_identification_number if form1099r.payer_state_identification_number.present? + xml.StateDistributionAmt form1099r.state_distribution_amount&.round + end + end + if form1099r.standard? + xml.StandardOrNonStandardCd 'S' + else + xml.StandardOrNonStandardCd 'N' + end + end + end + end + end +end diff --git a/app/lib/submission_builder/state_return.rb b/app/lib/submission_builder/state_return.rb index c432a7a77f..6465d92e5d 100644 --- a/app/lib/submission_builder/state_return.rb +++ b/app/lib/submission_builder/state_return.rb @@ -90,6 +90,21 @@ def form1099g_builder SubmissionBuilder::State1099G end + def form1099rs + @submission.data_source.state_file1099_rs.map do |form1099r| + { + xml: form1099r_builder, + pdf: nil, + include: true, + kwargs: { form1099r: form1099r } + } + end + end + + def form1099r_builder + SubmissionBuilder::State1099R + end + # default to nil def w2_pdf; end diff --git a/app/lib/submission_builder/ty2022/states/az/az_return_xml.rb b/app/lib/submission_builder/ty2022/states/az/az_return_xml.rb index 6f45573037..a3ece75876 100644 --- a/app/lib/submission_builder/ty2022/states/az/az_return_xml.rb +++ b/app/lib/submission_builder/ty2022/states/az/az_return_xml.rb @@ -214,6 +214,7 @@ def supported_documents ] supported_docs += combined_w2s + supported_docs += form1099rs supported_docs += form1099gs supported_docs end diff --git a/app/lib/submission_builder/ty2024/states/id/id_return_xml.rb b/app/lib/submission_builder/ty2024/states/id/id_return_xml.rb index a140688a45..791278d530 100644 --- a/app/lib/submission_builder/ty2024/states/id/id_return_xml.rb +++ b/app/lib/submission_builder/ty2024/states/id/id_return_xml.rb @@ -52,6 +52,7 @@ def supported_documents } end + supported_docs += form1099rs supported_docs += form1099gs supported_docs end diff --git a/app/lib/submission_builder/ty2024/states/md/md_return_xml.rb b/app/lib/submission_builder/ty2024/states/md/md_return_xml.rb index ec58ce5ce1..fbcc78cb7d 100644 --- a/app/lib/submission_builder/ty2024/states/md/md_return_xml.rb +++ b/app/lib/submission_builder/ty2024/states/md/md_return_xml.rb @@ -51,6 +51,7 @@ def supported_documents ] supported_docs += combined_w2s + supported_docs += form1099rs supported_docs += form1099gs supported_docs end diff --git a/app/views/state_file/questions/federal_info/_df_1099r.html.erb b/app/views/state_file/questions/federal_info/_df_1099r.html.erb index 5c2b191e22..7bf45ca243 100644 --- a/app/views/state_file/questions/federal_info/_df_1099r.html.erb +++ b/app/views/state_file/questions/federal_info/_df_1099r.html.erb @@ -3,6 +3,7 @@
<%= render 'node_xml_reveal', xml: f.object.to_pretty_s %> +

For payer_name_control, only use A-Z, 0-9, hyphen and ampersand. Only up to 4 characters are allowed. Spaces and symbols are not allowed.

<%= f.state_file_nested_xml_field :payer_name_control %> <%= f.state_file_nested_xml_field :payer_name %> diff --git a/spec/factories/state_file1099_rs.rb b/spec/factories/state_file1099_rs.rb index d03f86fd27..61a98d1039 100644 --- a/spec/factories/state_file1099_rs.rb +++ b/spec/factories/state_file1099_rs.rb @@ -41,6 +41,26 @@ # FactoryBot.define do factory :state_file1099_r do - + payer_name { "Dorothy Red" } + payer_name_control { "DORO" } + payer_address_line1 { "123 Sesame ST" } + payer_address_line2 { "Apt 202" } + payer_city_name { "Long Island" } + payer_zip { "12345"} + payer_identification_number { "22345"} + recipient_ssn { "123456789"} + recipient_name { "Dorothy Jane Red"} + gross_distribution_amount { 100.25 } + taxable_amount { 50.5 } + taxable_amount_not_determined { true } + total_distribution { true } + federal_income_tax_withheld_amount { 10.55 } + distribution_code { '7' } + designated_roth_account_first_year { 1993 } + state_tax_withheld_amount { 100.5 } + state_code { 'AZ' } + payer_state_identification_number { "222222222" } + state_distribution_amount { 155.15 } + standard { false } end end diff --git a/spec/fixtures/state_file/fed_return_xmls/2023/az/alexis_hoh_w2_and_1099.xml b/spec/fixtures/state_file/fed_return_xmls/2023/az/alexis_hoh_w2_and_1099.xml index 3c6c11e38a..47d955ac46 100644 --- a/spec/fixtures/state_file/fed_return_xmls/2023/az/alexis_hoh_w2_and_1099.xml +++ b/spec/fixtures/state_file/fed_return_xmls/2023/az/alexis_hoh_w2_and_1099.xml @@ -198,7 +198,7 @@ S - ALEXISPAYER + ALEX Payer Name diff --git a/spec/fixtures/state_file/fed_return_xmls/2023/az/df_complete_sample.xml b/spec/fixtures/state_file/fed_return_xmls/2023/az/df_complete_sample.xml index a4ae6fc70d..772ad751f4 100644 --- a/spec/fixtures/state_file/fed_return_xmls/2023/az/df_complete_sample.xml +++ b/spec/fixtures/state_file/fed_return_xmls/2023/az/df_complete_sample.xml @@ -209,7 +209,7 @@ S - ALEXISPAYER + ALEX Payer Name diff --git a/spec/fixtures/state_file/fed_return_xmls/2023/az/richard_retirement_1099r.xml b/spec/fixtures/state_file/fed_return_xmls/2023/az/richard_retirement_1099r.xml index acacf3591f..d7e7239445 100644 --- a/spec/fixtures/state_file/fed_return_xmls/2023/az/richard_retirement_1099r.xml +++ b/spec/fixtures/state_file/fed_return_xmls/2023/az/richard_retirement_1099r.xml @@ -101,7 +101,7 @@ 2030 Pecan Street Monroe - MA + AZ 05502 000000001 @@ -113,7 +113,7 @@ 11 - NC + AZ 111111111 111 @@ -121,14 +121,14 @@ S - PAYE DEUX + SECO Second Payer Name 2031 Pecan Street Nonroe - NA + AZ 05503 000000002 @@ -140,7 +140,7 @@ 22 - NC + AZ 222222222 222 diff --git a/spec/lib/submission_builder/state1099_r_spec.rb b/spec/lib/submission_builder/state1099_r_spec.rb new file mode 100644 index 0000000000..9455b6ef92 --- /dev/null +++ b/spec/lib/submission_builder/state1099_r_spec.rb @@ -0,0 +1,46 @@ +require 'rails_helper' + +describe SubmissionBuilder::State1099R do + StateFile::StateInformationService.active_state_codes.each do |state_code| + describe ".document" do + let(:submission) { create(:efile_submission, data_source: intake) } + let!(:form1099r) do + create( + :state_file1099_r, + intake: intake, + state_code: state_code.upcase, + payer_state_code: state_code.upcase + ) + end + let(:intake) do + create("state_file_#{state_code}_intake".to_sym) + end + let(:doc) { described_class.new(submission, kwargs: { form1099r: form1099r }).document } + + it "generates xml with the right values" do + expect(doc.at("PayerNameControlTxt").text).to eq "DORO" + expect(doc.at("PayerName BusinessNameLine1Txt").text).to eq "Dorothy Red" + expect(doc.at("PayerUSAddress AddressLine1Txt").text).to eq "123 Sesame ST" + expect(doc.at("PayerUSAddress AddressLine2Txt").text).to eq "Apt 202" + expect(doc.at("PayerUSAddress CityNm").text).to eq "Long Island" + expect(doc.at("PayerUSAddress StateAbbreviationCd").text).to eq "#{state_code.upcase}" + expect(doc.at("PayerUSAddress ZIPCd").text).to eq "12345" + expect(doc.at("PayerEIN").text).to eq "22345" + expect(doc.at("RecipientSSN").text).to eq "123456789" + expect(doc.at("RecipientNm").text).to eq "Dorothy Jane Red" + expect(doc.at("GrossDistributionAmt").text).to eq "100" + expect(doc.at("TaxableAmt").text).to eq "51" + expect(doc.at("TxblAmountNotDeterminedInd").text).to eq "X" + expect(doc.at("TotalDistributionInd").text).to eq "X" + expect(doc.at("FederalIncomeTaxWithheldAmt").text).to eq "11" + expect(doc.at("F1099RDistributionCd").text).to eq "7" + expect(doc.at("DesignatedROTHAcctFirstYr").text).to eq "1993" + expect(doc.at("F1099RStateTaxGrp StateTaxWithheldAmt").text).to eq "101" + expect(doc.at("F1099RStateTaxGrp StateAbbreviationCd").text).to eq "#{state_code.upcase}" + expect(doc.at("F1099RStateTaxGrp PayerStateIdNum").text).to eq "222222222" + expect(doc.at("F1099RStateTaxGrp StateDistributionAmt").text).to eq "155" + expect(doc.at("StandardOrNonStandardCd").text).to eq "N" + end + end + end +end diff --git a/spec/lib/submission_builder/state_return_spec.rb b/spec/lib/submission_builder/state_return_spec.rb index 1686e2a852..9145998446 100644 --- a/spec/lib/submission_builder/state_return_spec.rb +++ b/spec/lib/submission_builder/state_return_spec.rb @@ -20,8 +20,6 @@ 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(:submission) { create(:efile_submission, data_source: intake) } - let!(:initial_efile_device_info) { create :state_file_efile_device_info, :initial_creation, :filled, intake: intake } - let!(:submission_efile_device_info) { create :state_file_efile_device_info, :submission, :filled, intake: intake } let(:vars) { spec_vars[state_code.to_sym] || spec_vars[:default] } context "#{state_code}: when there are w2s present" do @@ -118,8 +116,6 @@ let(:builder_class) { StateFile::StateInformationService.submission_builder_class(state_code) } let(:intake) { create("state_file_#{state_code}_intake".to_sym) } let(:submission) { create(:efile_submission, data_source: intake) } - let!(:initial_efile_device_info) { create :state_file_efile_device_info, :initial_creation, :filled, intake: intake } - let!(:submission_efile_device_info) { create :state_file_efile_device_info, :submission, :filled, intake: intake } let!(:form1099g_1) { create(:state_file1099_g, intake: intake, state_income_tax_withheld_amount: 100) } let!(:form1099g_2) { create(:state_file1099_g, intake: intake, state_income_tax_withheld_amount: 200) } @@ -131,4 +127,23 @@ end end end + + states_requiring_1099rs = StateFile::StateInformationService.active_state_codes.excluding(["nc", "nj", "ny"]) + states_requiring_1099rs.each do |state_code| + describe "#form1099rs", required_schema: state_code do + context "#{state_code}: when there are 1099rs present" do + let(:builder_class) { StateFile::StateInformationService.submission_builder_class(state_code) } + let(:intake) { create("state_file_#{state_code}_intake".to_sym) } + let(:submission) { create(:efile_submission, data_source: intake) } + let!(:form1099r_1) { create(:state_file1099_r, intake: intake, state_tax_withheld_amount: 100) } + let!(:form1099r_2) { create(:state_file1099_r, intake: intake, state_tax_withheld_amount: 200) } + + it "builds all 1099gs from intake" do + xml = Nokogiri::XML::Document.parse(builder_class.build(submission).document.to_xml) + + expect(xml.css("IRS1099R").count).to eq 2 + end + end + end + end end