Skip to content

Commit 59ae757

Browse files
authored
FYST-661 Implement Form 502 xml pdf other contributions balance (#4997)
1 parent 73328b2 commit 59ae757

File tree

9 files changed

+379
-8
lines changed

9 files changed

+379
-8
lines changed

app/lib/efile/line_data.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,8 +712,24 @@ MD502_LINE_33:
712712
label: '33. Local tax after credits: local tax amount minus total local tax credits (line 28 - line 32)'
713713
MD502_LINE_34:
714714
label: '34. Total Maryland and local tax amount (line 27 + line 33 if deduction standard)'
715+
MD502_LINE_39:
716+
label: "39. Total Maryland income tax, local income tax and contributions"
715717
MD502_LINE_40:
716718
label: "40 Total Maryland and local tax withheld"
719+
MD502_LINE_42:
720+
label: "42. Refundable earned income credit"
721+
MD502_LINE_43:
722+
label: "43. Refundable income tax credits from Part CC, line 10 of Form 502CR"
723+
MD502_LINE_44:
724+
label: "44. Total payments and credits (Add lines 40 through 43.)"
725+
MD502_LINE_45:
726+
label: "45. Balance due (If line 39 is more than line 44, subtract line 44 from line 39"
727+
MD502_LINE_46:
728+
label: "46. Overpayment (If line 39 is less than line 44, subtract line 39 from line 44.)"
729+
MD502_LINE_48:
730+
label: "48. Amount of overpayment TO BE REFUNDED TO YOU"
731+
MD502_LINE_50:
732+
label: "50. TOTAL AMOUNT DUE (Add lines 45 and 49.)"
717733
MD502_AUTHORIZE_DIRECT_DEPOSIT:
718734
label: "Client authorizes the State of Maryland to issue refund by direct deposit (tax refund controller)."
719735
MD502_LINE_51D:

app/lib/efile/md/md502_calculator.rb

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ module Efile
22
module Md
33
class Md502Calculator < ::Efile::TaxCalculator
44
attr_reader :lines
5+
set_refund_owed_lines refund: :MD502_LINE_48, owed: :MD502_LINE_50
56

67
def initialize(year:, intake:, include_source: false)
78
super
@@ -99,10 +100,16 @@ def calculate
99100
set_line(:MD502_LINE_32, :calculate_line_32)
100101
set_line(:MD502_LINE_33, :calculate_line_33)
101102
set_line(:MD502_LINE_34, :calculate_line_34)
102-
103+
set_line(:MD502_LINE_39, :calculate_line_39)
103104
set_line(:MD502_LINE_40, :calculate_line_40)
105+
set_line(:MD502_LINE_42, :calculate_line_42)
106+
set_line(:MD502_LINE_43, :calculate_line_43)
107+
set_line(:MD502_LINE_44, :calculate_line_44)
108+
set_line(:MD502_LINE_45, :calculate_line_45)
109+
set_line(:MD502_LINE_46, :calculate_line_46)
110+
set_line(:MD502_LINE_48, :calculate_line_48)
111+
set_line(:MD502_LINE_50, :calculate_line_50)
104112
set_line(:MD502_AUTHORIZE_DIRECT_DEPOSIT, @intake, :bank_authorization_confirmed_yes?)
105-
106113
@md502cr.calculate
107114
@lines.transform_values(&:value)
108115
end
@@ -560,13 +567,54 @@ def calculate_line_34
560567
end
561568
end
562569

570+
def calculate_line_39
571+
(34..38).sum do |line_num|
572+
line_or_zero("MD502_LINE_#{line_num}")
573+
end
574+
end
575+
563576
def calculate_line_40
564577
@intake.state_file_w2s.sum { |item| item.state_income_tax_amount.round } +
565578
@intake.state_file_w2s.sum { |item| item.local_income_tax_amount.round } +
566579
@intake.state_file1099_gs.sum { |item| item.state_income_tax_withheld_amount.round } +
567580
@intake.state_file1099_rs.sum { |item| item.state_tax_withheld_amount.round }
568581
end
569582

583+
def calculate_line_42
584+
# Earned Income Credit (EIC)
585+
if filing_status_mfj? || filing_status_mfs? || @direct_file_data.fed_eic_qc_claimed
586+
[(@direct_file_data.fed_eic * 0.45).round - line_or_zero(:MD502_LINE_21), 0].max
587+
elsif filing_status_single? || filing_status_hoh? || filing_status_qw?
588+
[@direct_file_data.fed_eic - line_or_zero(:MD502_LINE_21), 0].max
589+
end
590+
end
591+
592+
def calculate_line_43; end
593+
594+
def calculate_line_44
595+
[40, 42, 43].sum { |number| line_or_zero("MD502_LINE_#{number}") }
596+
end
597+
598+
def calculate_line_45
599+
if line_or_zero(:MD502_LINE_39) > line_or_zero(:MD502_LINE_44)
600+
line_or_zero(:MD502_LINE_39) - line_or_zero(:MD502_LINE_44)
601+
end
602+
end
603+
604+
def calculate_line_46
605+
if line_or_zero(:MD502_LINE_39) < line_or_zero(:MD502_LINE_44)
606+
line_or_zero(:MD502_LINE_44) - line_or_zero(:MD502_LINE_39)
607+
end
608+
end
609+
610+
def calculate_line_48
611+
line_or_zero(:MD502_LINE_46) - line_or_zero(:MD502_LINE_47)
612+
end
613+
614+
def calculate_line_50
615+
line_or_zero(:MD502_LINE_45) + line_or_zero(:MD502_LINE_49)
616+
end
617+
570618
def filing_status_dependent?
571619
@filing_status == :dependent
572620
end

app/lib/pdf_filler/md502_pdf.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ def hash_for_pdf
7676
'Enter 13': @xml_document.at('Form502 Subtractions Other')&.text,
7777
'Enter 14': @xml_document.at('Form502 Subtractions TwoIncome')&.text,
7878
'Text Box 68': @xml_document.at('Form502 TaxWithheld')&.text,
79+
'Text Box 69': @xml_document.at('Form502 TaxWithheld')&.text.present? ? "00" : nil,
7980
'Text Box 34': @xml_document.at('Form502 StateTaxComputation EarnedIncomeCredit')&.text,
8081
'Check Box 37': checkbox_value(@xml_document.at('Form502 StateTaxComputation MDEICWithQualChildInd')&.text),
8182
'Text Box 96': @xml_document.at('ReturnHeaderState Filer Primary USPhone')&.text,
@@ -93,6 +94,20 @@ def hash_for_pdf
9394
'Text Box 36': @xml_document.at('Form502 StateTaxComputation PovertyLevelCredit')&.text,
9495
'Text Box 40': @xml_document.at('Form502 StateTaxComputation TotalCredits')&.text,
9596
'Text Box 42': @xml_document.at('Form502 StateTaxComputation StateTaxAfterCredits')&.text,
97+
'Text Box 66': calculated_fields.fetch(:MD502_LINE_39),
98+
'Text Box 67': "00",
99+
'Text Box 72': calculated_fields.fetch(:MD502_LINE_42),
100+
'Text Box 73': "00",
101+
'Text Box 76': calculated_fields.fetch(:MD502_LINE_44),
102+
'Text Box 77': "00",
103+
'Text Box 78': calculated_fields.fetch(:MD502_LINE_45),
104+
'Text Box 79': calculated_fields.fetch(:MD502_LINE_45).present? ? "00" : nil,
105+
'Text Box 80': calculated_fields.fetch(:MD502_LINE_46),
106+
'Text Box 81': calculated_fields.fetch(:MD502_LINE_46).present? ? "00" : nil,
107+
'Text Box 84': calculated_fields.fetch(:MD502_LINE_48),
108+
'Text Box 85': "00",
109+
'Text Box 91': calculated_fields.fetch(:MD502_LINE_50),
110+
'Text Box 92': "00",
96111
'Enter local tax rate': @xml_document.at('Form502 LocalTaxComputation LocalTaxRate')&.text&.split('0.0')&.last,
97112
'Text Box 44': @xml_document.at('Form502 LocalTaxComputation LocalIncomeTax')&.text,
98113
'Text Box 46': @xml_document.at('Form502 LocalTaxComputation EarnedIncomeCredit')&.text,

app/lib/pdf_filler/md_el101_pdf.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,19 @@ def hash_for_pdf
3333
'ERO firm name 2': @submission.data_source.spouse_esigned_yes? ? 'FileYourStateTaxes' : "",
3434
'Primary Signature Pin': @xml_document.at('Primary TaxpayerPIN')&.text,
3535
'Spouse Esigned': checkbox_value(@submission.data_source.spouse_esigned_yes?),
36-
'Secondary Signature Pin': @xml_document.at('Secondary TaxpayerPIN')&.text
36+
'Secondary Signature Pin': @xml_document.at('Secondary TaxpayerPIN')&.text,
37+
'2 Amount of overpayment to be refunded to you 2': calculated_fields.fetch(:MD502_LINE_48),
38+
'3': calculated_fields.fetch(:MD502_LINE_50),
3739
}
3840
end
3941

4042
def checkbox_value(condition)
4143
condition ? 'On' : 'Off'
4244
end
45+
46+
def calculated_fields
47+
@calculated_fields ||= @submission.data_source.tax_calculator.calculate
48+
end
4349
end
4450
end
4551

app/lib/submission_builder/ty2024/states/md/documents/md502.rb

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,11 +145,22 @@ def document
145145
add_element_if_present(xml, "LocalIncomeTax", :MD502_LINE_28_LOCAL_TAX_AMOUNT)
146146
add_element_if_present(xml, "EarnedIncomeCredit", :MD502_LINE_29)
147147
add_element_if_present(xml, "PovertyLevelCredit", :MD502_LINE_30)
148-
add_element_if_present(xml,"TotalCredits", :MD502_LINE_32)
149-
add_element_if_present(xml,"LocalTaxAfterCredits", :MD502_LINE_33)
148+
add_element_if_present(xml, "TotalCredits", :MD502_LINE_32)
149+
add_element_if_present(xml, "LocalTaxAfterCredits", :MD502_LINE_33)
150150
end
151151
add_element_if_present(xml, "TotalStateAndLocalTax", :MD502_LINE_34)
152+
add_non_zero_value(xml, :TotalTaxAndContributions, :MD502_LINE_39)
152153
xml.TaxWithheld calculated_fields.fetch(:MD502_LINE_40)
154+
add_non_zero_value(xml, :RefundableEIC, :MD502_LINE_42)
155+
add_non_zero_value(xml, :TotalPaymentsAndCredits, :MD502_LINE_44)
156+
add_non_zero_value(xml, :BalanceDue, :MD502_LINE_45)
157+
add_non_zero_value(xml, :Overpayment, :MD502_LINE_46)
158+
if calculated_fields.fetch(:MD502_LINE_48).positive?
159+
xml.AmountOverpayment do
160+
xml.ToBeRefunded calculated_fields.fetch(:MD502_LINE_48)
161+
end
162+
end
163+
add_non_zero_value(xml, :TotalAmountDue, :MD502_LINE_50)
153164
xml.AuthToDirectDepositInd "X" if calculated_fields.fetch(:MD502_AUTHORIZE_DIRECT_DEPOSIT)
154165
if @intake.payment_or_deposit_type.to_sym == :direct_deposit
155166
xml.NameOnBankAccount do

spec/lib/efile/md/md502_calculator_spec.rb

Lines changed: 163 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,6 +1124,27 @@
11241124
end
11251125
end
11261126

1127+
describe "#calculate_line_39" do
1128+
context "when there is a value for line 34" do
1129+
before do
1130+
allow_any_instance_of(described_class).to receive(:calculate_line_34).and_return 500
1131+
end
1132+
1133+
it "returns line 34" do
1134+
instance.calculate
1135+
expect(instance.lines[:MD502_LINE_39].value).to eq 500
1136+
end
1137+
end
1138+
1139+
context "when line 34 is nil" do
1140+
it "returns 0" do
1141+
allow_any_instance_of(described_class).to receive(:calculate_line_34).and_return nil
1142+
instance.calculate
1143+
expect(instance.lines[:MD502_LINE_39].value).to eq 0
1144+
end
1145+
end
1146+
end
1147+
11271148
describe "#calculate_line_28_local_tax_rate" do
11281149
let(:taxable_net_income) { 10_000 }
11291150
before do
@@ -1198,6 +1219,82 @@
11981219
end
11991220
end
12001221

1222+
describe "#calculate_line_42" do
1223+
let(:filing_status) { "head_of_household" }
1224+
let(:df_xml_key) { "md_laney_qss" }
1225+
let!(:intake) {
1226+
create(
1227+
:state_file_md_intake,
1228+
filing_status: filing_status,
1229+
raw_direct_file_data: StateFile::DirectFileApiResponseSampleService.new.read_xml(df_xml_key)
1230+
)
1231+
}
1232+
let(:federal_eic) { 1200 }
1233+
1234+
before do
1235+
intake.direct_file_data.fed_eic = federal_eic
1236+
allow_any_instance_of(described_class).to receive(:calculate_line_21).and_return 500
1237+
instance.calculate
1238+
end
1239+
1240+
context "when there is least one qualifying child" do
1241+
context "when federal EIC * .45 is equal to or greater than Maryland tax (line 21)" do
1242+
it 'refundable EIC equals (federal EIC * .45) - Maryland tax (line 21)' do
1243+
expect(instance.lines[:MD502_LINE_42].value).to eq 40 # .45 of 1200 is 540. 540 - 500
1244+
end
1245+
end
1246+
1247+
context "when federal EIC * .45 is less than than Maryland tax (line 21)" do
1248+
before do
1249+
intake.direct_file_data.fed_eic = federal_eic
1250+
allow_any_instance_of(described_class).to receive(:calculate_line_21).and_return 600
1251+
instance.calculate
1252+
end
1253+
it 'refundable EIC is 0' do
1254+
expect(instance.lines[:MD502_LINE_42].value).to eq 0
1255+
end
1256+
end
1257+
end
1258+
1259+
context "when mfj and no qualifying children" do
1260+
let(:filing_status) { "married_filing_jointly" }
1261+
let(:df_xml_key) { "md_zeus_two_w2s" }
1262+
it 'refundable EIC equals (federal EIC * .45) - Maryland tax (line 21)' do
1263+
expect(instance.lines[:MD502_LINE_42].value).to eq 40
1264+
end
1265+
end
1266+
1267+
context "when single and no qualifying children" do
1268+
let(:filing_status) { "single" }
1269+
let(:df_xml_key) { "md_zeus_two_w2s" }
1270+
1271+
context "when federal EIC is equal to or greater than Maryland tax (line 21)" do
1272+
it "refundable EIC equals - Maryland tax (line 21)" do
1273+
expect(instance.lines[:MD502_LINE_42].value).to eq 700
1274+
end
1275+
end
1276+
1277+
context "when federal EIC is less than than Maryland tax (line 21)" do
1278+
before do
1279+
intake.direct_file_data.fed_eic = federal_eic
1280+
allow_any_instance_of(described_class).to receive(:calculate_line_21).and_return 1500
1281+
instance.calculate
1282+
end
1283+
it 'refundable EIC is 0' do
1284+
expect(instance.lines[:MD502_LINE_42].value).to eq 0
1285+
end
1286+
end
1287+
end
1288+
1289+
context "when filing as a dependent and no qualifying children" do
1290+
let(:filing_status) { "dependent" }
1291+
let(:df_xml_key) { "md_zeus_two_w2s" }
1292+
it 'refundable EIC is nil' do
1293+
expect(instance.lines[:MD502_LINE_42].value).to eq nil
1294+
end
1295+
end
1296+
end
1297+
12011298
describe "#calculate_line_28_local_tax_amount" do
12021299
before do
12031300
allow_any_instance_of(described_class).to receive(:calculate_line_20).and_return 300_000
@@ -1258,6 +1355,68 @@
12581355
end
12591356
end
12601357

1358+
describe "#calculate_line_44" do
1359+
before do
1360+
allow_any_instance_of(described_class).to receive(:calculate_line_40).and_return 250
1361+
allow_any_instance_of(described_class).to receive(:calculate_line_42).and_return 200
1362+
allow_any_instance_of(described_class).to receive(:calculate_line_43).and_return 150
1363+
end
1364+
it "sums lines 40 to 44" do
1365+
instance.calculate
1366+
expect(instance.lines[:MD502_LINE_44].value).to eq(600)
1367+
end
1368+
end
1369+
1370+
describe "#calculate_line_45" do
1371+
context "line 39 is less than 44" do
1372+
before do
1373+
allow_any_instance_of(described_class).to receive(:calculate_line_39).and_return 50
1374+
allow_any_instance_of(described_class).to receive(:calculate_line_44).and_return 150
1375+
end
1376+
it "returns nil" do
1377+
instance.calculate
1378+
expect(instance.lines[:MD502_LINE_45].value).to eq(nil)
1379+
end
1380+
end
1381+
1382+
context "line 39 is more than 44" do
1383+
before do
1384+
allow_any_instance_of(described_class).to receive(:calculate_line_39).and_return 1_000
1385+
allow_any_instance_of(described_class).to receive(:calculate_line_44).and_return 900
1386+
end
1387+
it "subtracts line 39 from line 44" do
1388+
instance.calculate
1389+
expect(instance.lines[:MD502_LINE_45].value).to eq(100)
1390+
expect(instance.lines[:MD502_LINE_50].value).to eq(100)
1391+
end
1392+
end
1393+
end
1394+
1395+
describe "#calculate_line_46" do
1396+
context "line 39 is less than 44" do
1397+
before do
1398+
allow_any_instance_of(described_class).to receive(:calculate_line_39).and_return 900
1399+
allow_any_instance_of(described_class).to receive(:calculate_line_44).and_return 1_000
1400+
end
1401+
it "subtracts line 39 from line 44" do
1402+
instance.calculate
1403+
expect(instance.lines[:MD502_LINE_46].value).to eq(100)
1404+
expect(instance.lines[:MD502_LINE_48].value).to eq(100)
1405+
end
1406+
end
1407+
1408+
context "line 39 is more than 44" do
1409+
before do
1410+
allow_any_instance_of(described_class).to receive(:calculate_line_39).and_return 150
1411+
allow_any_instance_of(described_class).to receive(:calculate_line_44).and_return 50
1412+
end
1413+
it "returns nil" do
1414+
instance.calculate
1415+
expect(instance.lines[:MD502_LINE_46].value).to eq(nil)
1416+
end
1417+
end
1418+
end
1419+
12611420
describe "#calculate_line_30" do
12621421
context "deduction method is standard and they qualify for state poverty level credit" do
12631422
before do
@@ -1383,8 +1542,10 @@
13831542

13841543
describe "refund_or_owed_amount" do
13851544
it "subtracts owed amount from refund amount" do
1386-
# TEMP: stub calculator lines and test outcome of method once implemented
1387-
expect(instance.refund_or_owed_amount).to eq(0)
1545+
allow(instance).to receive(:calculate_line_48).and_return 0
1546+
allow(instance).to receive(:calculate_line_50).and_return -30
1547+
instance.calculate
1548+
expect(instance.refund_or_owed_amount).to eq(30)
13881549
end
13891550
end
13901551

0 commit comments

Comments
 (0)