diff --git a/changelog.d/mt-newborn-credit.added.md b/changelog.d/mt-newborn-credit.added.md new file mode 100644 index 00000000000..bf110b0ea02 --- /dev/null +++ b/changelog.d/mt-newborn-credit.added.md @@ -0,0 +1 @@ +Add Montana newborn credit reform. diff --git a/policyengine_us/parameters/gov/contrib/states/mt/newborn_credit/age_limit.yaml b/policyengine_us/parameters/gov/contrib/states/mt/newborn_credit/age_limit.yaml new file mode 100644 index 00000000000..002d50df283 --- /dev/null +++ b/policyengine_us/parameters/gov/contrib/states/mt/newborn_credit/age_limit.yaml @@ -0,0 +1,9 @@ +description: Montana limits child age to this threshold under the newborn credit program. + +values: + 2027-01-01: 1 + +metadata: + unit: year + period: year + label: Montana newborn credit child age limit diff --git a/policyengine_us/parameters/gov/contrib/states/mt/newborn_credit/amount.yaml b/policyengine_us/parameters/gov/contrib/states/mt/newborn_credit/amount.yaml new file mode 100644 index 00000000000..2d25d308ea8 --- /dev/null +++ b/policyengine_us/parameters/gov/contrib/states/mt/newborn_credit/amount.yaml @@ -0,0 +1,9 @@ +description: Montana provides this amount per qualifying child under the newborn credit program. + +values: + 2027-01-01: 1_000 + +metadata: + unit: currency-USD + period: year + label: Montana newborn credit amount diff --git a/policyengine_us/parameters/gov/contrib/states/mt/newborn_credit/in_effect.yaml b/policyengine_us/parameters/gov/contrib/states/mt/newborn_credit/in_effect.yaml new file mode 100644 index 00000000000..a81b8445078 --- /dev/null +++ b/policyengine_us/parameters/gov/contrib/states/mt/newborn_credit/in_effect.yaml @@ -0,0 +1,9 @@ +description: Montana uses this indicator to determine whether the newborn credit reform is in effect. + +values: + 0000-01-01: false + +metadata: + unit: bool + period: year + label: Montana newborn credit in effect diff --git a/policyengine_us/parameters/gov/contrib/states/mt/newborn_credit/reduction/amount.yaml b/policyengine_us/parameters/gov/contrib/states/mt/newborn_credit/reduction/amount.yaml new file mode 100644 index 00000000000..c1e45f001ae --- /dev/null +++ b/policyengine_us/parameters/gov/contrib/states/mt/newborn_credit/reduction/amount.yaml @@ -0,0 +1,9 @@ +description: Montana sets this amount as the phase-out reduction per income increment under the newborn credit program. + +values: + 2027-01-01: 50 + +metadata: + unit: currency-USD + period: year + label: Montana newborn credit reduction amount diff --git a/policyengine_us/parameters/gov/contrib/states/mt/newborn_credit/reduction/increment.yaml b/policyengine_us/parameters/gov/contrib/states/mt/newborn_credit/reduction/increment.yaml new file mode 100644 index 00000000000..4a4e2530957 --- /dev/null +++ b/policyengine_us/parameters/gov/contrib/states/mt/newborn_credit/reduction/increment.yaml @@ -0,0 +1,9 @@ +description: Montana sets this amount as the income increment for phase-out calculations under the newborn credit program. + +values: + 2027-01-01: 1_000 + +metadata: + unit: currency-USD + period: year + label: Montana newborn credit reduction increment diff --git a/policyengine_us/parameters/gov/contrib/states/mt/newborn_credit/reduction/threshold.yaml b/policyengine_us/parameters/gov/contrib/states/mt/newborn_credit/reduction/threshold.yaml new file mode 100644 index 00000000000..3b3c9c14ca1 --- /dev/null +++ b/policyengine_us/parameters/gov/contrib/states/mt/newborn_credit/reduction/threshold.yaml @@ -0,0 +1,28 @@ +description: Montana limits the newborn credit to taxpayers with AGI at or below this amount. + +SINGLE: + values: + 2027-01-01: 60_000 + +HEAD_OF_HOUSEHOLD: + values: + 2027-01-01: 60_000 + +JOINT: + values: + 2027-01-01: 120_000 + +SEPARATE: + values: + 2027-01-01: 60_000 + +SURVIVING_SPOUSE: + values: + 2027-01-01: 120_000 + +metadata: + unit: currency-USD + period: year + label: Montana newborn credit phase-out threshold + breakdown: + - filing_status diff --git a/policyengine_us/reforms/reforms.py b/policyengine_us/reforms/reforms.py index 323ac631597..e4f6a2ffbc5 100644 --- a/policyengine_us/reforms/reforms.py +++ b/policyengine_us/reforms/reforms.py @@ -88,6 +88,9 @@ from .states.mt.ctc import ( create_mt_ctc_reform, ) +from .states.mt.newborn_credit import ( + create_mt_newborn_credit_reform, +) from .congress.golden import ( create_fisc_act_reform, ) @@ -281,6 +284,7 @@ def create_structural_reforms_from_parameters(parameters, period): create_nyc_school_tax_credit_with_phase_out_reform(parameters, period) ) mt_ctc = create_mt_ctc_reform(parameters, period) + mt_newborn_credit = create_mt_newborn_credit_reform(parameters, period) fisc_act = create_fisc_act_reform(parameters, period) tax_employer_social_security_tax = ( create_tax_employer_social_security_tax_reform(parameters, period) @@ -409,6 +413,7 @@ def create_structural_reforms_from_parameters(parameters, period): limit_salt_deduction_to_property_taxes, nyc_school_tax_credit_with_phase_out, mt_ctc, + mt_newborn_credit, fisc_act, tax_employer_social_security_tax, tax_employer_medicare_tax, diff --git a/policyengine_us/reforms/states/mt/newborn_credit/__init__.py b/policyengine_us/reforms/states/mt/newborn_credit/__init__.py new file mode 100644 index 00000000000..edc2dbecbea --- /dev/null +++ b/policyengine_us/reforms/states/mt/newborn_credit/__init__.py @@ -0,0 +1 @@ +from .mt_newborn_credit import create_mt_newborn_credit_reform diff --git a/policyengine_us/reforms/states/mt/newborn_credit/mt_newborn_credit.py b/policyengine_us/reforms/states/mt/newborn_credit/mt_newborn_credit.py new file mode 100644 index 00000000000..8bd9edc26dc --- /dev/null +++ b/policyengine_us/reforms/states/mt/newborn_credit/mt_newborn_credit.py @@ -0,0 +1,122 @@ +from policyengine_us.model_api import * +from policyengine_core.periods import period as period_ +from policyengine_core.periods import instant + + +def create_mt_newborn_credit() -> Reform: + """Montana newborn credit reform. + + Provides a $1,000 refundable credit per qualifying child under + age 1 with phase-out based on AGI. This is a PolicyEngine-designed + contrib reform; no enacted legislation exists. + """ + + class mt_newborn_credit_eligible_child(Variable): + value_type = bool + entity = Person + label = "Montana newborn credit eligible child" + definition_period = YEAR + defined_for = StateCode.MT + + def formula(person, period, parameters): + p = parameters(period).gov.contrib.states.mt.newborn_credit + age = person("age", period) + is_dependent = person("is_tax_unit_dependent", period) + has_ssn = person("meets_eitc_identification_requirements", period) + return (age < p.age_limit) & is_dependent & has_ssn + + class mt_newborn_credit_eligible(Variable): + value_type = bool + entity = TaxUnit + label = "Eligible for the Montana newborn credit" + definition_period = YEAR + defined_for = StateCode.MT + + def formula(tax_unit, period, parameters): + has_earned_income = tax_unit("tax_unit_earned_income", period) > 0 + has_qualifying_children = ( + add( + tax_unit, + period, + ["mt_newborn_credit_eligible_child"], + ) + > 0 + ) + person = tax_unit.members + head_or_spouse = person("is_tax_unit_head_or_spouse", period) + has_ssn = person("meets_eitc_identification_requirements", period) + # Uses any() not all(): at least one filer needs SSN, + # unlike EITC which requires all filers to have SSN. + filer_has_ssn = tax_unit.any(head_or_spouse & has_ssn) + return has_earned_income & has_qualifying_children & filer_has_ssn + + class mt_newborn_credit(Variable): + value_type = float + entity = TaxUnit + label = "Montana newborn credit" + definition_period = YEAR + unit = USD + defined_for = "mt_newborn_credit_eligible" + + def formula(tax_unit, period, parameters): + p = parameters(period).gov.contrib.states.mt.newborn_credit + qualifying_children = add( + tax_unit, period, ["mt_newborn_credit_eligible_child"] + ) + base_credit = p.amount * qualifying_children + filing_status = tax_unit("filing_status", period) + agi = tax_unit("adjusted_gross_income", period) + threshold = p.reduction.threshold[filing_status] + excess = max_(agi - threshold, 0) + # Ceiling: any fraction of an increment triggers reduction + increments = np.ceil(excess / p.reduction.increment) + reduction = p.reduction.amount * increments + return max_(base_credit - reduction, 0) + + def modify_parameters(parameters): + # NOTE: MT CTC reform hard-codes the refundable credits list, + # so this reform must run after MT CTC in reforms.py to + # correctly append mt_newborn_credit via read-then-append. + refundable = parameters.gov.states.mt.tax.income.credits.refundable + current_refundable = refundable(instant("2027-01-01")) + if "mt_newborn_credit" not in current_refundable: + new_refundable = list(current_refundable) + ["mt_newborn_credit"] + refundable.update( + start=instant("2027-01-01"), + stop=instant("2100-12-31"), + value=new_refundable, + ) + return parameters + + class reform(Reform): + def apply(self): + self.update_variable(mt_newborn_credit_eligible_child) + self.update_variable(mt_newborn_credit_eligible) + self.update_variable(mt_newborn_credit) + self.modify_parameters(modify_parameters) + + return reform + + +def create_mt_newborn_credit_reform(parameters, period, bypass: bool = False): + if bypass: + return create_mt_newborn_credit() + + p = parameters.gov.contrib.states.mt.newborn_credit + + reform_active = False + current_period = period_(period) + + for _ in range(5): + if p(current_period).in_effect: + reform_active = True + break + current_period = current_period.offset(1, "year") + + if reform_active: + return create_mt_newborn_credit() + else: + return None + + +mt_newborn_credit = create_mt_newborn_credit_reform(None, None, bypass=True) diff --git a/policyengine_us/tests/policy/contrib/states/mt/newborn_credit/mt_newborn_credit.yaml b/policyengine_us/tests/policy/contrib/states/mt/newborn_credit/mt_newborn_credit.yaml new file mode 100644 index 00000000000..fdd0bb63c46 --- /dev/null +++ b/policyengine_us/tests/policy/contrib/states/mt/newborn_credit/mt_newborn_credit.yaml @@ -0,0 +1,1061 @@ +# Montana Newborn Credit Tests + +# Basic Eligibility Tests + +- name: Case 1, single filer with newborn under income threshold. + period: 2027 + absolute_error_margin: 1 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + employment_income: 40_000 + ssn_card_type: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SINGLE + households: + household: + members: [person1, person2] + state_code: MT + output: + mt_newborn_credit: 1_000 + # Refundable credit exceeds tax liability, producing a negative mt_income_tax + mt_income_tax: -1_304 + +- name: Case 2, MFJ with newborn under income threshold. + period: 2027 + absolute_error_margin: 1 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 35 + is_tax_unit_head: true + employment_income: 60_000 + ssn_card_type: CITIZEN + person2: + age: 33 + is_tax_unit_spouse: true + employment_income: 40_000 + ssn_card_type: CITIZEN + person3: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2, person3] + filing_status: JOINT + households: + household: + members: [person1, person2, person3] + state_code: MT + output: + # AGI $100k < $120k threshold for MFJ + mt_newborn_credit: 1_000 + # Baseline mt_income_tax ~$3,147 minus $1,000 refundable credit + mt_income_tax: 147 + +- name: Case 3, two newborns double credit. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + employment_income: 50_000 + ssn_card_type: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + person3: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2, person3] + filing_status: SINGLE + households: + household: + members: [person1, person2, person3] + state_code: MT + output: + mt_newborn_credit: 2_000 + +# Age Eligibility Tests + +- name: Case 4, child age 1 not eligible must be under 1. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + employment_income: 40_000 + ssn_card_type: CITIZEN + person2: + age: 1 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SINGLE + households: + household: + members: [person1, person2] + state_code: MT + output: + mt_newborn_credit: 0 + +- name: Case 5, one newborn eligible one older child not. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 35 + is_tax_unit_head: true + employment_income: 50_000 + ssn_card_type: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + person3: + age: 3 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2, person3] + filing_status: SINGLE + households: + household: + members: [person1, person2, person3] + state_code: MT + output: + mt_newborn_credit: 1_000 + +- name: Case 6, child not claimed as dependent not eligible. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + employment_income: 40_000 + ssn_card_type: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: false + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SINGLE + households: + household: + members: [person1, person2] + state_code: MT + output: + mt_newborn_credit: 0 + +# SSN Requirement Tests - Child + +- name: Case 7, child with SSN NON_CITIZEN_VALID_EAD qualifies. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + employment_income: 40_000 + ssn_card_type: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: NON_CITIZEN_VALID_EAD + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SINGLE + households: + household: + members: [person1, person2] + state_code: MT + output: + mt_newborn_credit: 1_000 + +- name: Case 8, child with ITIN only OTHER_NON_CITIZEN not eligible. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + employment_income: 40_000 + ssn_card_type: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: OTHER_NON_CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SINGLE + households: + household: + members: [person1, person2] + state_code: MT + output: + mt_newborn_credit: 0 + +# SSN Requirement Tests - Filer + +- name: Case 9, filer with SSN NON_CITIZEN_VALID_EAD qualifies. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + employment_income: 40_000 + ssn_card_type: NON_CITIZEN_VALID_EAD + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SINGLE + households: + household: + members: [person1, person2] + state_code: MT + output: + mt_newborn_credit: 1_000 + +- name: Case 10, filer with ITIN only OTHER_NON_CITIZEN not eligible. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + employment_income: 40_000 + ssn_card_type: OTHER_NON_CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SINGLE + households: + household: + members: [person1, person2] + state_code: MT + output: + mt_newborn_credit: 0 + +- name: Case 11, MFJ one spouse has SSN qualifies. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 35 + is_tax_unit_head: true + employment_income: 60_000 + ssn_card_type: CITIZEN + person2: + age: 33 + is_tax_unit_spouse: true + ssn_card_type: OTHER_NON_CITIZEN + person3: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2, person3] + filing_status: JOINT + households: + household: + members: [person1, person2, person3] + state_code: MT + output: + mt_newborn_credit: 1_000 + +- name: Case 12, MFJ neither spouse has SSN not eligible. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 35 + is_tax_unit_head: true + employment_income: 60_000 + ssn_card_type: OTHER_NON_CITIZEN + person2: + age: 33 + is_tax_unit_spouse: true + ssn_card_type: OTHER_NON_CITIZEN + person3: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2, person3] + filing_status: JOINT + households: + household: + members: [person1, person2, person3] + state_code: MT + output: + mt_newborn_credit: 0 + +# Earned Income Requirement Tests + +- name: Case 13, no earned income not eligible. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + employment_income: 0 + ssn_card_type: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SINGLE + households: + household: + members: [person1, person2] + state_code: MT + output: + mt_newborn_credit: 0 + +- name: Case 14, exactly $1 earned income qualifies. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + employment_income: 1 + ssn_card_type: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SINGLE + households: + household: + members: [person1, person2] + state_code: MT + output: + mt_newborn_credit: 1_000 + +# Phase-out Tests + +- name: Case 15, single at exactly threshold full credit. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + employment_income: 60_000 + ssn_card_type: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SINGLE + households: + household: + members: [person1, person2] + state_code: MT + output: + # AGI $60k = threshold, no reduction + mt_newborn_credit: 1_000 + +- name: Case 16, single $1 above threshold one increment reduction. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + employment_income: 60_001 + ssn_card_type: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SINGLE + households: + household: + members: [person1, person2] + state_code: MT + output: + # ceil($1 / $1,000) = 1 increment, reduction = $50 + mt_newborn_credit: 950 + +- name: Case 17, single $1001 above threshold two increments. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + employment_income: 61_001 + ssn_card_type: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SINGLE + households: + household: + members: [person1, person2] + state_code: MT + output: + # ceil($1,001 / $1,000) = 2 increments, reduction = $100 + mt_newborn_credit: 900 + +- name: Case 18, single last $50 of credit before full phase-out. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + employment_income: 79_000 + ssn_card_type: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SINGLE + households: + household: + members: [person1, person2] + state_code: MT + output: + # excess = $19,000, ceil($19,000/$1,000) = 19, reduction = $950 + mt_newborn_credit: 50 + +- name: Case 19, single exactly at full phase-out boundary. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + employment_income: 80_000 + ssn_card_type: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SINGLE + households: + household: + members: [person1, person2] + state_code: MT + output: + # excess = $20,000, ceil($20,000/$1,000) = 20, reduction = $1,000 + mt_newborn_credit: 0 + +- name: Case 20, MFJ at exactly threshold full credit. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 35 + is_tax_unit_head: true + employment_income: 70_000 + ssn_card_type: CITIZEN + person2: + age: 33 + is_tax_unit_spouse: true + employment_income: 50_000 + ssn_card_type: CITIZEN + person3: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2, person3] + filing_status: JOINT + households: + household: + members: [person1, person2, person3] + state_code: MT + output: + # AGI $120k = threshold for MFJ, no reduction + mt_newborn_credit: 1_000 + +- name: Case 21, MFJ $1 above threshold partial phase-out. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 35 + is_tax_unit_head: true + employment_income: 70_001 + ssn_card_type: CITIZEN + person2: + age: 33 + is_tax_unit_spouse: true + employment_income: 50_000 + ssn_card_type: CITIZEN + person3: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2, person3] + filing_status: JOINT + households: + household: + members: [person1, person2, person3] + state_code: MT + output: + # AGI $120,001, excess = $1, ceil($1/$1,000) = 1, reduction = $50 + mt_newborn_credit: 950 + +- name: Case 22, MFJ above threshold partial phase-out. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 35 + is_tax_unit_head: true + employment_income: 70_000 + ssn_card_type: CITIZEN + person2: + age: 33 + is_tax_unit_spouse: true + employment_income: 55_000 + ssn_card_type: CITIZEN + person3: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2, person3] + filing_status: JOINT + households: + household: + members: [person1, person2, person3] + state_code: MT + output: + # AGI $125,000, excess = $5,000, 5 increments, reduction = $250 + mt_newborn_credit: 750 + +# Filing Status Threshold Tests + +- name: Case 23, HOH phase-out uses $60k threshold. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + employment_income: 65_000 + ssn_card_type: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [person1, person2] + state_code: MT + output: + # excess = $5,000, 5 increments, reduction = $250 + mt_newborn_credit: 750 + +- name: Case 24, MFS phase-out uses $60k threshold. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + employment_income: 63_000 + ssn_card_type: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SEPARATE + households: + household: + members: [person1, person2] + state_code: MT + output: + # excess = $3,000, 3 increments, reduction = $150 + mt_newborn_credit: 850 + +- name: Case 25, surviving spouse phase-out uses $120k threshold. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 35 + is_tax_unit_head: true + employment_income: 125_000 + ssn_card_type: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SURVIVING_SPOUSE + households: + household: + members: [person1, person2] + state_code: MT + output: + # excess = $5,000, 5 increments, reduction = $250 + mt_newborn_credit: 750 + +# Phase-out with Multiple Children + +- name: Case 26, two newborns with partial phase-out. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + employment_income: 65_000 + ssn_card_type: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + person3: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2, person3] + filing_status: SINGLE + households: + household: + members: [person1, person2, person3] + state_code: MT + output: + # base = $2,000, excess = $5,000, 5 increments, reduction = $250 + # credit = max($2,000 - $250, 0) = $1,750 + mt_newborn_credit: 1_750 + +# Non-MT Resident Test + +- name: Case 27, non-MT resident gets zero. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + employment_income: 40_000 + ssn_card_type: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SINGLE + households: + household: + members: [person1, person2] + state_code: NY + output: + mt_newborn_credit: 0 + +# Additional Edge Case Tests + +- name: Case 28, self-employment income satisfies earned income requirement. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + self_employment_income: 40_000 + ssn_card_type: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SINGLE + households: + household: + members: [person1, person2] + state_code: MT + output: + mt_newborn_credit: 1_000 + +- name: Case 29, unearned income only does not satisfy earned income requirement. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 65 + is_tax_unit_head: true + social_security: 40_000 + ssn_card_type: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SINGLE + households: + household: + members: [person1, person2] + state_code: MT + output: + mt_newborn_credit: 0 + +- name: Case 30, adult-only tax unit gets zero credit. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + employment_income: 40_000 + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: MT + output: + mt_newborn_credit: 0 + +- name: Case 31, MFJ full phase-out boundary at $140k. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 35 + is_tax_unit_head: true + employment_income: 80_000 + ssn_card_type: CITIZEN + person2: + age: 33 + is_tax_unit_spouse: true + employment_income: 60_000 + ssn_card_type: CITIZEN + person3: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2, person3] + filing_status: JOINT + households: + household: + members: [person1, person2, person3] + state_code: MT + output: + # AGI $140k, excess = $20k, ceil($20k/$1k) = 20, reduction = $1,000 + mt_newborn_credit: 0 + +- name: Case 32, two newborns full phase-out requires $40k above threshold. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + employment_income: 100_000 + ssn_card_type: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + person3: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2, person3] + filing_status: SINGLE + households: + household: + members: [person1, person2, person3] + state_code: MT + output: + # base = $2,000, excess = $40k, ceil($40k/$1k) = 40, reduction = $2,000 + mt_newborn_credit: 0 + +- name: Case 33, negative SE income with zero employment income not eligible. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + self_employment_income: -10_000 + ssn_card_type: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SINGLE + households: + household: + members: [person1, person2] + state_code: MT + output: + mt_newborn_credit: 0 + +- name: Case 34, child with SSN card type NONE not eligible. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + employment_income: 40_000 + ssn_card_type: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: NONE + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SINGLE + households: + household: + members: [person1, person2] + state_code: MT + output: + mt_newborn_credit: 0 + +- name: Case 35, negative AGI with earned income still eligible. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + employment_income: 20_000 + short_term_capital_gains: -100_000 + ssn_card_type: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SINGLE + households: + household: + members: [person1, person2] + state_code: MT + output: + # AGI is negative due to capital losses, no phase-out applies + mt_newborn_credit: 1_000 + +- name: Case 36, single exactly $1000 above threshold one increment. + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.mt.newborn_credit.mt_newborn_credit.mt_newborn_credit + input: + gov.contrib.states.mt.newborn_credit.in_effect: true + people: + person1: + age: 30 + is_tax_unit_head: true + employment_income: 61_000 + ssn_card_type: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SINGLE + households: + household: + members: [person1, person2] + state_code: MT + output: + # ceil($1,000 / $1,000) = 1 increment, reduction = $50 + mt_newborn_credit: 950