diff --git a/changelog.d/fix-9982-fl-tca-recipient-disregard.fixed.md b/changelog.d/fix-9982-fl-tca-recipient-disregard.fixed.md new file mode 100644 index 00000000000..6afe6cbabcc --- /dev/null +++ b/changelog.d/fix-9982-fl-tca-recipient-disregard.fixed.md @@ -0,0 +1 @@ +Apply the Florida TCA $200 and 1/2 earned income disregard to current participants (is_tanf_enrolled) whatever their income after the $90 disregard, per Fla. Stat. 414.095(11)(a) and ESS manual 2420.0315, and count the $90 standard disregard as part of the first $200 instead of on top of it. diff --git a/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/tanf/fl_tca_200_and_half_disregard_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/tanf/fl_tca_200_and_half_disregard_eligible.yaml new file mode 100644 index 00000000000..24ae73cd4b6 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/tanf/fl_tca_200_and_half_disregard_eligible.yaml @@ -0,0 +1,109 @@ +# Tests eligibility for the Florida TCA $200 and 1/2 earned income disregard. +# Florida Statutes 414.095(11)(a): the individual must be "1. A current +# participant in the program; or 2. Eligible for participation in the program +# without the earnings disregard." +# DCF ESS Program Policy Manual 2420.0315: the member must +# 1. have been eligible for and received TCA in one of the past four months +# (is_tanf_enrolled); or +# 2. have gross countable income, less the $90 standard earned income +# disregard, which is less than the applicable payment standard. +# All cases: three people, shelter obligation over $50, so the payment standard +# is $303. + +- name: Case 1, current participant with income after $90 above the payment standard. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 6_000 # $500/month + pre_subsidy_rent: 9_600 + person2: + age: 8 + person3: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3] + is_tanf_enrolled: true + households: + household: + members: [person1, person2, person3] + state_code: FL + output: + fl_tca_payment_standard: 303 + # Income after $90 = $500 - $90 = $410 >= $303, so condition 2 fails, but + # the unit is a current participant (condition 1). + fl_tca_200_and_half_disregard_eligible: true + +- name: Case 2, applicant with the same income is not eligible for the disregard. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 6_000 # $500/month + pre_subsidy_rent: 9_600 + person2: + age: 8 + person3: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3] + is_tanf_enrolled: false + households: + household: + members: [person1, person2, person3] + state_code: FL + output: + # Not a current participant, and $410 >= $303. + fl_tca_200_and_half_disregard_eligible: false + +- name: Case 3, applicant with income after $90 below the payment standard. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 3_600 # $300/month + pre_subsidy_rent: 9_600 + person2: + age: 8 + person3: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3] + is_tanf_enrolled: false + households: + household: + members: [person1, person2, person3] + state_code: FL + output: + # Income after $90 = $300 - $90 = $210 < $303 (condition 2). + fl_tca_200_and_half_disregard_eligible: true + +- name: Case 4, applicant with income after $90 equal to the payment standard. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 4_716 # $393/month + pre_subsidy_rent: 9_600 + person2: + age: 8 + person3: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3] + is_tanf_enrolled: false + households: + household: + members: [person1, person2, person3] + state_code: FL + output: + # Income after $90 = $393 - $90 = $303, which is not less than $303. + fl_tca_200_and_half_disregard_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/tanf/fl_tca_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/tanf/fl_tca_countable_earned_income.yaml index 9144ea27742..354a20d5c7f 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/tanf/fl_tca_countable_earned_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/tanf/fl_tca_countable_earned_income.yaml @@ -2,9 +2,13 @@ # Per DCF ESS Program Policy Manual 2620.0111.01: # Step 2 - subtract the $90 standard disregard (always). # Step 3 - subtract the remainder of the "$200 and 1/2" disregard "if eligible". -# The $200 and 1/2 disregard is granted (2420.0314-.0315) when income after the -# $90 disregard is below the payment standard for the size of the SFU; otherwise -# only the $90 is deducted. +# Per 2420.0315, "the $90 standard earned income disregard is included in the +# first $200 earned income disregard": an eligible member has $90 and then +# another $110 deducted, "for a total of $200", and then half of the rest. +# The $200 and 1/2 disregard is granted (2420.0314-.0315) to a member who +# received TCA in one of the past four months (is_tanf_enrolled) or when income +# after the $90 disregard is below the payment standard for the size of the SFU; +# otherwise only the $90 is deducted. # # The disregard-formula cases below use a large filing unit with high shelter so # the payment standard ($610 for size 8) is high enough that the $200 and 1/2 @@ -43,7 +47,7 @@ fl_tca_countable_earned_income: 0 # $0 earned -> $0 countable. -- name: Case 2, earned income $290 (exactly at $90 + $200 threshold). +- name: Case 2, earned income $290. period: 2024-01 input: people: @@ -66,10 +70,11 @@ members: [person1, person2, person3, person4, person5, person6, person7, person8] state_code: FL output: - fl_tca_countable_earned_income: 0 - # After $90 = $200 (< $610, disregard applies); after $200 = $0; * 0.5 = $0. + fl_tca_countable_earned_income: 45 + # After $90 = $200 (< $610, disregard applies); after the remaining $110 = + # $90; * 0.5 = $45. ($290 - $200 total disregard) / 2 = $45. -- name: Case 3, earned income $291 (one dollar above $90 + $200 threshold). +- name: Case 3, earned income $291. period: 2024-01 input: people: @@ -92,8 +97,8 @@ members: [person1, person2, person3, person4, person5, person6, person7, person8] state_code: FL output: - fl_tca_countable_earned_income: 0.5 - # After $90 = $201 (< $610); after $200 = $1; * 0.5 = $0.50. + fl_tca_countable_earned_income: 45.5 + # After $90 = $201 (< $610); after the remaining $110 = $91; * 0.5 = $45.50. - name: Case 4, earned income $300. period: 2024-01 @@ -118,8 +123,8 @@ members: [person1, person2, person3, person4, person5, person6, person7, person8] state_code: FL output: - fl_tca_countable_earned_income: 5 - # After $90 = $210 (< $610); after $200 = $10; * 0.5 = $5. + fl_tca_countable_earned_income: 50 + # After $90 = $210 (< $610); after the remaining $110 = $100; * 0.5 = $50. - name: Case 5, earned income $400. period: 2024-01 @@ -144,8 +149,8 @@ members: [person1, person2, person3, person4, person5, person6, person7, person8] state_code: FL output: - fl_tca_countable_earned_income: 55 - # After $90 = $310 (< $610); after $200 = $110; * 0.5 = $55. + fl_tca_countable_earned_income: 100 + # After $90 = $310 (< $610); after the remaining $110 = $200; * 0.5 = $100. - name: Case 6, earned income $500. period: 2024-01 @@ -170,10 +175,10 @@ members: [person1, person2, person3, person4, person5, person6, person7, person8] state_code: FL output: - fl_tca_countable_earned_income: 105 - # After $90 = $410 (< $610); after $200 = $210; * 0.5 = $105. + fl_tca_countable_earned_income: 150 + # After $90 = $410 (< $610); after the remaining $110 = $300; * 0.5 = $150. -- name: Case 7, earned income $91 (one dollar above $90 disregard, below $290). +- name: Case 7, earned income $91 (one dollar above $90 disregard, below $200). period: 2024-01 input: people: @@ -197,7 +202,7 @@ state_code: FL output: fl_tca_countable_earned_income: 0 - # After $90 = $1 (< $610); after $200 = $0; * 0.5 = $0. + # After $90 = $1 (< $610); after the remaining $110 = $0; * 0.5 = $0. # ============================================================ # $200 and 1/2 disregard does NOT apply: income after the $90 standard diff --git a/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/tanf/fl_tca_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/tanf/fl_tca_eligible.yaml index ddc04887b02..c8f64a44dc1 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/tanf/fl_tca_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/tanf/fl_tca_eligible.yaml @@ -43,7 +43,8 @@ output: fl_tca_eligible: false # Gross test: $1,000 < 185% FPL ($3,151) -> Pass - # Net test: max(max(1000-90,0)-200,0)*0.5 = 355 > $241 -> Fail + # Net test: income after $90 = $910 >= $241, so the $200 and 1/2 + # disregard is denied; countable $910 > $241 -> Fail # Must pass BOTH tests - name: Case 3, fails gross income test. @@ -167,7 +168,7 @@ fl_tca_eligible: true # Size 8, >$50 shelter payment standard: $610. # Income after $90 = $210 < $610, so the $200 and 1/2 disregard applies: - # countable = max(max(300-90,0)-200,0)*0.5 = $5 < $610 -> net test passes. + # countable = max(300-90-110,0)*0.5 = $50 < $610 -> net test passes. - name: Case 7, adult-only household ineligible. period: 2024-01 diff --git a/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/tanf/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/tanf/integration.yaml index d67fc8be65e..784e827b8f4 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/tanf/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/tanf/integration.yaml @@ -283,18 +283,18 @@ members: [person1, person2, person3, person4] state_code: FL output: - fl_tca_countable_earned_income: 5 - # After $90: 210, after $200: 10, * 0.5 = 5 - fl_tca_countable_income: 5 + fl_tca_countable_earned_income: 50 + # After $90: 210, after the remaining $110 of the $200: 100, * 0.5 = 50 + fl_tca_countable_income: 50 fl_tca_gross_income_eligible: true # Gross: $300 < 185% FPL for 4 ($4,810) -> Pass fl_tca_net_income_eligible: true - # 5 < $364 -> Pass + # 50 < $364 -> Pass fl_tca_eligible: true fl_tca_payment_standard: 364 # Size 4, >$50 shelter - fl_tca: 359 - # 364 - 5 = $359 + fl_tca: 314 + # 364 - 50 = $314 - name: Case 10, mixed income sources. period: 2024-01 @@ -368,7 +368,7 @@ # Edge Case Integration Tests # ============================================================ -- name: Case 12, earned income $200 below $290 threshold. +- name: Case 12, earned income $200, fully absorbed by the $200 disregard. period: 2024-01 input: people: @@ -387,7 +387,7 @@ state_code: FL output: fl_tca_countable_earned_income: 0 - # After $90: 110, after $200: 0, * 0.5 = 0 + # After $90: 110, after the remaining $110 of the $200: 0, * 0.5 = 0 fl_tca_countable_income: 0 fl_tca_gross_income_eligible: true # Gross: $200 < $3,151 -> Pass @@ -396,7 +396,7 @@ fl_tca_eligible: true fl_tca_payment_standard: 241 fl_tca: 241 - # Full benefit when earned income below $290 threshold + # Full benefit when earned income is at or below the $200 disregard - name: Case 13, shelter cost exactly at $50 boundary. period: 2024-01 @@ -557,17 +557,17 @@ members: [person1, person2] state_code: FL output: - fl_tca_countable_earned_income: 5 - # After $90: 210, after $200: 10, * 0.5 = 5 - fl_tca_countable_income: 5 + fl_tca_countable_earned_income: 50 + # After $90: 210, after the remaining $110 of the $200: 100, * 0.5 = 50 + fl_tca_countable_income: 50 fl_tca_resources_eligible: true # 2,000 <= 2,000 -> Pass fl_tca_gross_income_eligible: true fl_tca_net_income_eligible: true fl_tca_eligible: true fl_tca_payment_standard: 241 - fl_tca: 236 - # 241 - 5 = $236 + fl_tca: 191 + # 241 - 50 = $191 - name: Case 19, assets over limit ineligible. period: 2024-01 @@ -595,3 +595,101 @@ fl_tca_eligible: false # Failed resource test fl_tca: 0 + +- name: Case 20, current participant keeps the $200 and 1/2 disregard above the payment standard. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 6_000 # $500/month + pre_subsidy_rent: 9_600 + person2: + age: 8 + person3: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3] + is_tanf_enrolled: true + households: + household: + members: [person1, person2, person3] + state_code: FL + output: + fl_tca_payment_standard: 303 + # Size 3, >$50 shelter. + fl_tca_200_and_half_disregard_eligible: true + # Income after $90 = $410 >= $303, but a current participant is eligible + # for the disregard (414.095(11)(a)1; 2420.0315 condition 1). + fl_tca_countable_earned_income: 150 + # ($500 - $90 - $110) * 0.5 = $150, that is ($500 - $200) / 2. + fl_tca_net_income_eligible: true + # 150 <= 303 -> Pass + fl_tca_eligible: true + fl_tca: 153 + # 303 - 150 = $153 + +- name: Case 21, applicant with the same earnings gets only the $90 disregard. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 6_000 # $500/month + pre_subsidy_rent: 9_600 + person2: + age: 8 + person3: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3] + is_tanf_enrolled: false + households: + household: + members: [person1, person2, person3] + state_code: FL + output: + fl_tca_200_and_half_disregard_eligible: false + # Not a current participant, and income after $90 = $410 >= $303. + fl_tca_countable_earned_income: 410 + # $500 - $90 = $410 + fl_tca_net_income_eligible: false + # 410 > 303 -> Fail + fl_tca: 0 + +- name: Case 22, current participant with unearned income above the payment standard keeps the disregard but fails the net test. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 1_200 # $100/month + social_security: 4_800 # $400/month + pre_subsidy_rent: 9_600 + person2: + age: 8 + person3: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3] + is_tanf_enrolled: true + households: + household: + members: [person1, person2, person3] + state_code: FL + output: + fl_tca_payment_standard: 303 + # Size 3, >$50 shelter. + fl_tca_200_and_half_disregard_eligible: true + # A current participant keeps the disregard (2420.0315 condition 1). + fl_tca_countable_earned_income: 0 + # 2620.0111.01 steps 2-3: max($100 - $90, 0) = $10, less the $110 + # remainder, floored at 0. + fl_tca_countable_income: 400 + # Step 4: 0 earned + $400 unearned. + fl_tca_net_income_eligible: false + # 400 > 303 -> Fail + fl_tca: 0 diff --git a/policyengine_us/variables/gov/states/fl/dcf/tanf/income/fl_tca_200_and_half_disregard_eligible.py b/policyengine_us/variables/gov/states/fl/dcf/tanf/income/fl_tca_200_and_half_disregard_eligible.py index 47ed5f55ec3..f4fb856cc79 100644 --- a/policyengine_us/variables/gov/states/fl/dcf/tanf/income/fl_tca_200_and_half_disregard_eligible.py +++ b/policyengine_us/variables/gov/states/fl/dcf/tanf/income/fl_tca_200_and_half_disregard_eligible.py @@ -6,33 +6,42 @@ class fl_tca_200_and_half_disregard_eligible(Variable): entity = SPMUnit label = "Florida TCA eligible for the $200 and 1/2 earned income disregard" definition_period = MONTH - reference = "https://ffic.myflfamilies.com/manual/2400.pdf" + reference = ( + "https://www.leg.state.fl.us/statutes/index.cfm?App_mode=Display_Statute&URL=0400-0499/0414/Sections/0414.095.html", + "https://ffic.myflfamilies.com/manual/2400.pdf#page=28", + ) defined_for = StateCode.FL documentation = """ Whether the assistance group may receive the remainder of the "$200 and 1/2" - earned income disregard under DCF ESS Program Policy Manual 2420.0314-.0315. + earned income disregard under Florida Statutes 414.095(11)(a) and DCF ESS + Program Policy Manual 2420.0314-.0315. Per 2420.0315, a member receives the $200 and 1/2 disregard if the individual: (1) has been eligible for and received TCA in one of the past four months; OR (2) has gross countable income (earned + unearned), less the $90 standard earned income disregard, that is less than the applicable payment standard. + Florida Statutes 414.095(11)(a) requires the individual to be a current + participant in the program, or eligible for participation without the + earnings disregard. The statute does not mention the $90 standard + disregard; the manual supplies the $90 and the test of income after it in + condition (2). - PolicyEngine cannot observe prior-month TCA receipt from a static snapshot, so - condition (1) is not represented. This variable encodes the computable - condition (2): (gross earned + unearned - $90 standard disregard) < payment - standard. Because condition (1) can only expand eligibility, applying condition - (2) alone is the conservative, manual-aligned choice for new applicants; it - understates eligibility only for continuing recipients whose income has risen - above the payment standard after the $90 disregard. + Condition (1) uses is_tanf_enrolled, which defaults to reported TANF + receipt, to stand for receipt of TCA in one of the past four months. + Condition (2) compares (gross earned + unearned - $90 standard disregard) to + the payment standard. """ def formula(spm_unit, period, parameters): p = parameters(period).gov.states.fl.dcf.tanf.income.disregard + # 2420.0315(1): eligible for and received TCA in one of the past four + # months (414.095(11)(a)1: a current participant in the program). + current_participant = spm_unit("is_tanf_enrolled", period) gross_earned = add(spm_unit, period, ["tanf_gross_earned_income"]) unearned = add(spm_unit, period, ["tanf_gross_unearned_income"]) payment_standard = spm_unit("fl_tca_payment_standard", period) # 2420.0315(2): gross countable income less the $90 standard earned income # disregard, compared to the payment standard. income_after_standard = max_(gross_earned - p.standard_disregard, 0) + unearned - return income_after_standard < payment_standard + return current_participant | (income_after_standard < payment_standard) diff --git a/policyengine_us/variables/gov/states/fl/dcf/tanf/income/fl_tca_countable_earned_income.py b/policyengine_us/variables/gov/states/fl/dcf/tanf/income/fl_tca_countable_earned_income.py index 5342b212c0e..addf1185708 100644 --- a/policyengine_us/variables/gov/states/fl/dcf/tanf/income/fl_tca_countable_earned_income.py +++ b/policyengine_us/variables/gov/states/fl/dcf/tanf/income/fl_tca_countable_earned_income.py @@ -9,7 +9,8 @@ class fl_tca_countable_earned_income(Variable): definition_period = MONTH reference = ( "https://www.leg.state.fl.us/statutes/index.cfm?App_mode=Display_Statute&URL=0400-0499/0414/Sections/0414.095.html", - "https://ffic.myflfamilies.com/manual/2400.pdf", + "https://ffic.myflfamilies.com/manual/2400.pdf#page=28", + "https://ffic.myflfamilies.com/manual/2600.pdf#page=21", ) defined_for = StateCode.FL @@ -25,9 +26,14 @@ def formula(spm_unit, period, parameters): # Step 3: The remainder of the $200 and 1/2 disregard is subtracted only # "if eligible" (2620.0111.01 Step 3). Per 2420.0314-.0315 the $200 and - # 1/2 disregard is granted when income after the $90 disregard is below - # the payment standard (condition 2); otherwise only the $90 applies. + # 1/2 disregard is granted to a recent recipient or when income after + # the $90 disregard is below the payment standard; otherwise only the + # $90 applies. eligible = spm_unit("fl_tca_200_and_half_disregard_eligible", period) - remaining_after_first = max_(after_standard - p.first_amount, 0) + # Per 2420.0315, the $90 standard disregard "is included in the first + # $200 earned income disregard", so only the remaining $110 is + # subtracted here, "for a total of $200". + remainder_of_first_amount = p.first_amount - p.standard_disregard + remaining_after_first = max_(after_standard - remainder_of_first_amount, 0) countable_with_full_disregard = remaining_after_first * (1 - p.remaining_rate) return where(eligible, countable_with_full_disregard, after_standard)