diff --git a/changelog.d/fl-ssp.added.md b/changelog.d/fl-ssp.added.md new file mode 100644 index 00000000000..8ab36fb7451 --- /dev/null +++ b/changelog.d/fl-ssp.added.md @@ -0,0 +1 @@ +Add Florida Optional State Supplementation (OSS). diff --git a/policyengine_us/parameters/gov/household/household_state_benefits.yaml b/policyengine_us/parameters/gov/household/household_state_benefits.yaml index eb8c9cd5676..1be6dabae36 100644 --- a/policyengine_us/parameters/gov/household/household_state_benefits.yaml +++ b/policyengine_us/parameters/gov/household/household_state_benefits.yaml @@ -24,6 +24,8 @@ values: - al_ssp # Alaska benefits - ak_ssp + # Florida benefits + - fl_oss # Nebraska benefits - ne_child_care_subsidies # Massachusetts benefits @@ -53,6 +55,8 @@ values: - al_ssp # Alaska benefits - ak_ssp + # Florida benefits + - fl_oss # Nebraska benefits - ne_child_care_subsidies # North Carolina benefits diff --git a/policyengine_us/parameters/gov/states/fl/dcf/oss/couple_provider_rate_reduction.yaml b/policyengine_us/parameters/gov/states/fl/dcf/oss/couple_provider_rate_reduction.yaml new file mode 100644 index 00000000000..3f1925e613f --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/dcf/oss/couple_provider_rate_reduction.yaml @@ -0,0 +1,15 @@ +description: Florida deducts this amount from the couple provider rate under the Optional State Supplementation program. +values: + 2011-01-01: 0 + 2024-07-01: 73 + 2025-01-01: 97 + +metadata: + unit: currency-USD + period: month + label: Florida OSS couple provider rate reduction + reference: + - title: SSA State Assistance Programs for SSI Recipients, January 2011 - Florida, Table 1 + href: https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/2011/fl.html + - title: FL DCF Appendix A-12, Optional State Supplementation Payment Standards + href: https://www.myflfamilies.com/sites/default/files/2025-05/Appendix%20A-12%20-%20State%20Funded%20Programs%20Eligibility%20Standards.pdf diff --git a/policyengine_us/parameters/gov/states/fl/dcf/oss/medicaid_facility/supplement/couple.yaml b/policyengine_us/parameters/gov/states/fl/dcf/oss/medicaid_facility/supplement/couple.yaml new file mode 100644 index 00000000000..0f014b9df16 --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/dcf/oss/medicaid_facility/supplement/couple.yaml @@ -0,0 +1,11 @@ +description: Florida provides this amount as the couple state supplement for Medicaid facility residents under the Optional State Supplementation program. +values: + 2011-01-01: 10 + +metadata: + unit: currency-USD + period: month + label: Florida OSS Medicaid facility couple supplement + reference: + - title: SSA State Assistance Programs for SSI Recipients, January 2011 - Florida, Table 1 + href: https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/2011/fl.html diff --git a/policyengine_us/parameters/gov/states/fl/dcf/oss/medicaid_facility/supplement/individual.yaml b/policyengine_us/parameters/gov/states/fl/dcf/oss/medicaid_facility/supplement/individual.yaml new file mode 100644 index 00000000000..91fed03cc80 --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/dcf/oss/medicaid_facility/supplement/individual.yaml @@ -0,0 +1,11 @@ +description: Florida provides this amount as the individual state supplement for Medicaid facility residents under the Optional State Supplementation program. +values: + 2011-01-01: 5 + +metadata: + unit: currency-USD + period: month + label: Florida OSS Medicaid facility individual supplement + reference: + - title: SSA State Assistance Programs for SSI Recipients, January 2011 - Florida, Table 1 + href: https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/2011/fl.html diff --git a/policyengine_us/parameters/gov/states/fl/dcf/oss/pna.yaml b/policyengine_us/parameters/gov/states/fl/dcf/oss/pna.yaml new file mode 100644 index 00000000000..05bd869a401 --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/dcf/oss/pna.yaml @@ -0,0 +1,16 @@ +description: Florida provides this amount as the Personal Needs Allowance per person under the Optional State Supplementation program. +values: + 2011-01-01: 54 + 2024-07-01: 160 + +metadata: + unit: currency-USD + period: month + label: Florida OSS Personal Needs Allowance + reference: + - title: SSA State Assistance Programs for SSI Recipients, January 2011 - Florida, Table 1 + href: https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/2011/fl.html + - title: FL DCF Appendix A-12, Optional State Supplementation Payment Standards + href: https://www.myflfamilies.com/sites/default/files/2025-05/Appendix%20A-12%20-%20State%20Funded%20Programs%20Eligibility%20Standards.pdf + - title: Florida HB 5001, 2024-25 General Appropriations Act + href: https://www.flsenate.gov/Session/Bill/2024/5001 diff --git a/policyengine_us/parameters/gov/states/fl/dcf/oss/protected/in_effect.yaml b/policyengine_us/parameters/gov/states/fl/dcf/oss/protected/in_effect.yaml new file mode 100644 index 00000000000..364800ebef4 --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/dcf/oss/protected/in_effect.yaml @@ -0,0 +1,12 @@ +description: Florida uses this indicator to determine whether the Protected program track applies under the Optional State Supplementation program. +values: + 2011-01-01: false + 2024-07-01: true + +metadata: + unit: bool + period: month + label: Florida OSS Protected track in effect + reference: + - title: FL DCF Appendix A-12, Optional State Supplementation Payment Standards + href: https://www.myflfamilies.com/sites/default/files/2025-05/Appendix%20A-12%20-%20State%20Funded%20Programs%20Eligibility%20Standards.pdf diff --git a/policyengine_us/parameters/gov/states/fl/dcf/oss/protected/max_oss/couple.yaml b/policyengine_us/parameters/gov/states/fl/dcf/oss/protected/max_oss/couple.yaml new file mode 100644 index 00000000000..6f35b45dc58 --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/dcf/oss/protected/max_oss/couple.yaml @@ -0,0 +1,11 @@ +description: Florida limits the couple Protected payment to this amount under the Optional State Supplementation program. +values: + 2024-07-01: 690 + +metadata: + unit: currency-USD + period: month + label: Florida OSS Protected maximum couple payment + reference: + - title: FL DCF Appendix A-12, Optional State Supplementation Payment Standards + href: https://www.myflfamilies.com/sites/default/files/2025-05/Appendix%20A-12%20-%20State%20Funded%20Programs%20Eligibility%20Standards.pdf diff --git a/policyengine_us/parameters/gov/states/fl/dcf/oss/protected/max_oss/individual.yaml b/policyengine_us/parameters/gov/states/fl/dcf/oss/protected/max_oss/individual.yaml new file mode 100644 index 00000000000..3d6446b0886 --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/dcf/oss/protected/max_oss/individual.yaml @@ -0,0 +1,11 @@ +description: Florida limits the individual Protected payment to this amount under the Optional State Supplementation program. +values: + 2024-07-01: 345 + +metadata: + unit: currency-USD + period: month + label: Florida OSS Protected maximum individual payment + reference: + - title: FL DCF Appendix A-12, Optional State Supplementation Payment Standards + href: https://www.myflfamilies.com/sites/default/files/2025-05/Appendix%20A-12%20-%20State%20Funded%20Programs%20Eligibility%20Standards.pdf diff --git a/policyengine_us/parameters/gov/states/fl/dcf/oss/protected/provider_rate_offset.yaml b/policyengine_us/parameters/gov/states/fl/dcf/oss/protected/provider_rate_offset.yaml new file mode 100644 index 00000000000..63bed6cf289 --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/dcf/oss/protected/provider_rate_offset.yaml @@ -0,0 +1,11 @@ +description: Florida sets this amount as the offset added to the federal SSI benefit rate to determine the Protected provider rate under the Optional State Supplementation program. +values: + 2024-07-01: 185 + +metadata: + unit: currency-USD + period: month + label: Florida OSS Protected provider rate offset + reference: + - title: FL DCF Appendix A-12, Optional State Supplementation Payment Standards + href: https://www.myflfamilies.com/sites/default/files/2025-05/Appendix%20A-12%20-%20State%20Funded%20Programs%20Eligibility%20Standards.pdf diff --git a/policyengine_us/parameters/gov/states/fl/dcf/oss/redesign/income_standard_pna_offset.yaml b/policyengine_us/parameters/gov/states/fl/dcf/oss/redesign/income_standard_pna_offset.yaml new file mode 100644 index 00000000000..008093f7aed --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/dcf/oss/redesign/income_standard_pna_offset.yaml @@ -0,0 +1,13 @@ +description: Florida sets this amount as the offset added to the provider rate to determine the Redesign income standard under the Optional State Supplementation program. +values: + 2011-01-01: 54 + +metadata: + unit: currency-USD + period: month + label: Florida OSS Redesign income standard personal needs allowance offset + reference: + - title: SSA State Assistance Programs for SSI Recipients, January 2011 - Florida, Table 1 + href: https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/2011/fl.html + - title: FL DCF Appendix A-12, Optional State Supplementation Payment Standards + href: https://www.myflfamilies.com/sites/default/files/2025-05/Appendix%20A-12%20-%20State%20Funded%20Programs%20Eligibility%20Standards.pdf diff --git a/policyengine_us/parameters/gov/states/fl/dcf/oss/redesign/max_oss/couple.yaml b/policyengine_us/parameters/gov/states/fl/dcf/oss/redesign/max_oss/couple.yaml new file mode 100644 index 00000000000..8eceec6bfeb --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/dcf/oss/redesign/max_oss/couple.yaml @@ -0,0 +1,14 @@ +description: Florida limits the couple Redesign payment to this amount under the Optional State Supplementation program. +values: + 2011-01-01: 156.8 + 2024-07-01: 386.8 + +metadata: + unit: currency-USD + period: month + label: Florida OSS Redesign maximum couple payment + reference: + - title: SSA State Assistance Programs for SSI Recipients, January 2011 - Florida, Table 1 + href: https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/2011/fl.html + - title: FL DCF Appendix A-12, Optional State Supplementation Payment Standards + href: https://www.myflfamilies.com/sites/default/files/2025-05/Appendix%20A-12%20-%20State%20Funded%20Programs%20Eligibility%20Standards.pdf diff --git a/policyengine_us/parameters/gov/states/fl/dcf/oss/redesign/max_oss/individual.yaml b/policyengine_us/parameters/gov/states/fl/dcf/oss/redesign/max_oss/individual.yaml new file mode 100644 index 00000000000..5124b88bd3c --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/dcf/oss/redesign/max_oss/individual.yaml @@ -0,0 +1,14 @@ +description: Florida limits the individual Redesign payment to this amount under the Optional State Supplementation program. +values: + 2011-01-01: 78.4 + 2024-07-01: 184.4 + +metadata: + unit: currency-USD + period: month + label: Florida OSS Redesign maximum individual payment + reference: + - title: SSA State Assistance Programs for SSI Recipients, January 2011 - Florida, Table 1 + href: https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/2011/fl.html + - title: FL DCF Appendix A-12, Optional State Supplementation Payment Standards + href: https://www.myflfamilies.com/sites/default/files/2025-05/Appendix%20A-12%20-%20State%20Funded%20Programs%20Eligibility%20Standards.pdf diff --git a/policyengine_us/parameters/gov/states/fl/dcf/oss/redesign/provider_rate_offset.yaml b/policyengine_us/parameters/gov/states/fl/dcf/oss/redesign/provider_rate_offset.yaml new file mode 100644 index 00000000000..fbbf10e3ea1 --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/dcf/oss/redesign/provider_rate_offset.yaml @@ -0,0 +1,13 @@ +description: Florida sets this amount as the offset added to the federal SSI benefit rate to determine the Redesign provider rate under the Optional State Supplementation program. +values: + 2011-01-01: 24.4 + +metadata: + unit: currency-USD + period: month + label: Florida OSS Redesign provider rate offset + reference: + - title: SSA State Assistance Programs for SSI Recipients, January 2011 - Florida, Table 1 + href: https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/2011/fl.html + - title: FL DCF Appendix A-12, Optional State Supplementation Payment Standards + href: https://www.myflfamilies.com/sites/default/files/2025-05/Appendix%20A-12%20-%20State%20Funded%20Programs%20Eligibility%20Standards.pdf diff --git a/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/edge_cases.yaml b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/edge_cases.yaml new file mode 100644 index 00000000000..fba44c75fb3 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/edge_cases.yaml @@ -0,0 +1,812 @@ +# Edge case tests for Florida OSS (Optional State Supplementation). +# All FL OSS variables are MONTH-defined (Person entity). +# ssi_countable_income and uncapped_ssi are YEAR-defined: +# in MONTH tests, provide ANNUAL input, formula reads monthly = annual / 12. + +# ────────────────────────────────────────────────────────────── +# Income threshold boundary tests (Redesign, individual, 2025) +# Income standard = $1,045.40/month = $12,544.80/year. +# ────────────────────────────────────────────────────────────── + +- name: Case 1, income exactly at income standard boundary, Group 2 eligible. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + # Not an SSI recipient, but income exactly at income standard. + uncapped_ssi: -940 + # $1,045.40/month * 12 = $12,544.80/year. + # Formula: countable_income ($1,045.40) <= income_standard ($1,045.40) → true. + ssi_countable_income: 12_544.80 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_eligible: [true] + # Total needs = $1,151.40/month. + # OSS = min(max(0, $1,151.40 - $1,045.40), $184.40) = min($106, $184.40) = $106. + fl_oss: [106] + +- name: Case 2, income one cent above income standard, Group 2 ineligible. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + uncapped_ssi: -950 + # ($1,045.40 + $0.01)/month * 12 = $12,544.92/year. + # Formula: countable_income ($1,045.41) > income_standard ($1,045.40) → false. + # Also uncapped_ssi < 0 → not SSI recipient. Both groups fail → ineligible. + ssi_countable_income: 12_544.92 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_eligible: [false] + fl_oss: [0] + +- name: Case 3, income one cent below income standard, Group 2 eligible. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + uncapped_ssi: -930 + # ($1,045.40 - $0.01)/month * 12 = $12,544.68/year. + # Formula: countable_income ($1,045.39) <= income_standard ($1,045.40) → true. + ssi_countable_income: 12_544.68 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_eligible: [true] + # OSS = min(max(0, $1,151.40 - $1,045.39), $184.40) = min($106.01, $184.40) = $106.01. + fl_oss: [106.01] + +# ────────────────────────────────────────────────────────────── +# Income = total_needs exactly → $0 benefit +# Total needs (Redesign, I) = $1,151.40/month = $13,816.80/year. +# ────────────────────────────────────────────────────────────── + +- name: Case 4, income equals total needs exactly, zero benefit. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + # SSI recipient (positive uncapped_ssi) to ensure eligibility via Group 1. + uncapped_ssi: 12 + # $1,151.40/month * 12 = $13,816.80/year. + # Formula: max(0, $1,151.40 - $1,151.40) = $0. + ssi_countable_income: 13_816.80 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_eligible: [true] + fl_oss: [0] + +# ────────────────────────────────────────────────────────────── +# Income = total_needs - max_oss exactly → benefit = max_oss +# Redesign I: total_needs - max_oss = $1,151.40 - $184.40 = $967/month. +# $967/month * 12 = $11,604/year. +# ────────────────────────────────────────────────────────────── + +- name: Case 5, income at total needs minus max OSS, benefit exactly equals max OSS. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + uncapped_ssi: 12 + # $967/month * 12 = $11,604/year. + # Formula: min(max(0, $1,151.40 - $967), $184.40) = min($184.40, $184.40) = $184.40. + ssi_countable_income: 11_604 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_eligible: [true] + fl_oss: [184.40] + +- name: Case 6, income one cent above transition point, benefit just below max OSS. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + uncapped_ssi: 12 + # ($967 + $0.01)/month * 12 = $11,604.12/year. + # Formula: min(max(0, $1,151.40 - $967.01), $184.40) = min($184.39, $184.40) = $184.39. + ssi_countable_income: 11_604.12 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_eligible: [true] + fl_oss: [184.39] + +# ────────────────────────────────────────────────────────────── +# Zero income → capped at max OSS +# ────────────────────────────────────────────────────────────── + +- name: Case 7, zero income Protected individual, capped at max OSS. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: MHRTF + fl_oss_program_track: PROTECTED + age: 45 + is_ssi_eligible: true + ssi_claim_is_joint: false + uncapped_ssi: 11_604 + ssi_countable_income: 0 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_eligible: [true] + # Total needs (Protected, I) = $1,312/month. Income = $0. + # Calculated = $1,312. Max = $345. Capped at $345. + fl_oss: [345] + +- name: Case 8, zero income Redesign couple, capped at max OSS per person. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: AFCH + fl_oss_program_track: REDESIGN + age: 72 + is_ssi_eligible: true + ssi_claim_is_joint: true + uncapped_ssi: 10_000 + ssi_countable_income: 0 + person2: + fl_oss_community_care_type: AFCH + fl_oss_program_track: REDESIGN + age: 68 + is_ssi_eligible: true + ssi_claim_is_joint: true + uncapped_ssi: 10_000 + ssi_countable_income: 0 + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: FL + output: + fl_oss_eligible: [true, true] + # Per person total needs = $1,102.90. Income = $0. + # Calculated per person = $1,102.90. Max per person = $193.40. + # Capped at $193.40 each. + fl_oss: [193.40, 193.40] + +# ────────────────────────────────────────────────────────────── +# Very high income → $0 benefit (well above income standard) +# ────────────────────────────────────────────────────────────── + +- name: Case 9, very high income SSI recipient, income well above total needs. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + # Still an SSI recipient (Group 1) but income very high. + uncapped_ssi: 12 + # $5,000/month * 12 = $60,000/year. + ssi_countable_income: 60_000 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_eligible: [true] + # Total needs = $1,151.40. Income = $5,000. max(0, $1,151.40 - $5,000) = $0. + fl_oss: [0] + +# ────────────────────────────────────────────────────────────── +# PNA transition boundary: 2024-01 (PNA=$54) vs 2025-01 (PNA=$160) +# The PNA changed 2024-07-01 from $54 to $160. +# Jan 2024 test: PNA=$54. Jan 2025 test: PNA=$160. +# ────────────────────────────────────────────────────────────── + +- name: Case 10, PNA at old rate (2024-01), Redesign individual. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + uncapped_ssi: 2_916 + ssi_countable_income: 8_400 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_eligible: [true] + # SSI FBR (I) 2024 = $943. Redesign offset = $24.40. + # Provider rate = $943 + $24.40 = $967.40/month. + fl_oss_provider_rate: [967.40] + # PNA = $54. Total needs = $967.40 + $54 = $1,021.40/month. + # Max OSS (Redesign, I, pre-Jul-2024) = $78.40. + # Income = $700/month. OSS = min(max(0, $1,021.40 - $700), $78.40) + # = min($321.40, $78.40) = $78.40. + fl_oss: [78.40] + +- name: Case 11, PNA at new rate (2025-01), same income scenario for comparison. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + uncapped_ssi: 2_004 + ssi_countable_income: 8_400 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_eligible: [true] + # SSI FBR (I) 2025 = $967. Redesign offset = $24.40. + # Provider rate = $967 + $24.40 = $991.40/month. + fl_oss_provider_rate: [991.40] + # PNA = $160. Total needs = $991.40 + $160 = $1,151.40/month. + # Max OSS (Redesign, I) = $184.40. + # Income = $700/month. OSS = min(max(0, $1,151.40 - $700), $184.40) + # = min($451.40, $184.40) = $184.40. + fl_oss: [184.40] + +# ────────────────────────────────────────────────────────────── +# Protected track: params are 0 before 2024-07-01 +# Provider rate offset = $0, max OSS individual = $0, couple = $0. +# This means Protected track effectively didn't exist before Jul 2024. +# ────────────────────────────────────────────────────────────── + +- name: Case 12, Protected track before Jul 2024, ineligible (track not in effect). + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: MHRTF + fl_oss_program_track: PROTECTED + age: 45 + is_ssi_eligible: true + ssi_claim_is_joint: false + uncapped_ssi: 2_916 + ssi_countable_income: 8_400 + households: + household: + members: [person1] + state_code: FL + output: + # Protected track not in effect before Jul 2024. + fl_oss_eligible: [false] + fl_oss: [0] + +- name: Case 13, Protected couple before Jul 2024, ineligible (track not in effect). + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: MHRTF + fl_oss_program_track: PROTECTED + age: 45 + is_ssi_eligible: true + ssi_claim_is_joint: true + uncapped_ssi: 2_000 + ssi_countable_income: 7_200 + person2: + fl_oss_community_care_type: MHRTF + fl_oss_program_track: PROTECTED + age: 42 + is_ssi_eligible: true + ssi_claim_is_joint: true + uncapped_ssi: 2_000 + ssi_countable_income: 7_200 + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: FL + output: + # Protected track not in effect before Jul 2024. + fl_oss_eligible: [false, false] + fl_oss: [0, 0] + +# ────────────────────────────────────────────────────────────── +# Protected track post Jul 2024 → nonzero max OSS +# ────────────────────────────────────────────────────────────── + +- name: Case 14, Protected individual after Jul 2024, full benefit. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: MHRTF + fl_oss_program_track: PROTECTED + age: 45 + is_ssi_eligible: true + ssi_claim_is_joint: false + uncapped_ssi: 11_604 + ssi_countable_income: 0 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_eligible: [true] + # Provider rate = $967 + $185 = $1,152/month. + fl_oss_provider_rate: [1_152] + # Max OSS (Protected, I) = $345/month. + fl_oss_max_oss: [345] + # Total needs = $1,152 + $160 = $1,312. Income = $0. + # OSS = min($1,312, $345) = $345. + fl_oss: [345] + +# ────────────────────────────────────────────────────────────── +# Protected track income standard boundary +# Protected income standard = provider rate = $1,152/month = $13,824/year. +# ────────────────────────────────────────────────────────────── + +- name: Case 15, Protected income exactly at income standard, Group 2 eligible. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: MHRTF + fl_oss_program_track: PROTECTED + age: 45 + is_ssi_eligible: true + ssi_claim_is_joint: false + uncapped_ssi: -200 + # $1,152/month * 12 = $13,824/year. + # countable_income ($1,152) <= income_standard ($1,152) → Group 2 eligible. + ssi_countable_income: 13_824 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_eligible: [true] + fl_oss_income_standard: [1_152] + # Total needs = $1,312. Income = $1,152. + # OSS = min(max(0, $1,312 - $1,152), $345) = min($160, $345) = $160. + fl_oss: [160] + +- name: Case 16, Protected income one cent above income standard, ineligible. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: MHRTF + fl_oss_program_track: PROTECTED + age: 45 + is_ssi_eligible: true + ssi_claim_is_joint: false + uncapped_ssi: -210 + # ($1,152 + $0.01)/month * 12 = $13,824.12/year. + # countable_income ($1,152.01) > income_standard ($1,152) → Group 2 fails. + # Also uncapped_ssi < 0 → not Group 1. Ineligible. + ssi_countable_income: 13_824.12 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_eligible: [false] + fl_oss: [0] + +# ────────────────────────────────────────────────────────────── +# All three facility types +# ────────────────────────────────────────────────────────────── + +- name: Case 17, AFCH facility type, Redesign individual. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: AFCH + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + uncapped_ssi: 11_604 + ssi_countable_income: 0 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_eligible: [true] + fl_oss: [184.40] + +- name: Case 18, MHRTF facility type, Redesign individual. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: MHRTF + fl_oss_program_track: REDESIGN + age: 45 + is_ssi_eligible: true + ssi_claim_is_joint: false + uncapped_ssi: 11_604 + ssi_countable_income: 0 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_eligible: [true] + fl_oss: [184.40] + +# ────────────────────────────────────────────────────────────── +# Couple with Protected track, both eligible, post Jul 2024 +# ────────────────────────────────────────────────────────────── + +- name: Case 19, Protected couple, zero income, max benefit. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: MHRTF + fl_oss_program_track: PROTECTED + age: 72 + is_ssi_eligible: true + ssi_claim_is_joint: true + uncapped_ssi: 10_000 + ssi_countable_income: 0 + person2: + fl_oss_community_care_type: MHRTF + fl_oss_program_track: PROTECTED + age: 68 + is_ssi_eligible: true + ssi_claim_is_joint: true + uncapped_ssi: 10_000 + ssi_countable_income: 0 + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: FL + output: + fl_oss_eligible: [true, true] + # Protected couple provider rate = 2 * $1,152 - $97 = $2,207/month. + # Per person = $2,207 / 2 = $1,103.50/month. + fl_oss_provider_rate: [1_103.50, 1_103.50] + # Max OSS (Protected, C) = $690. Per person = $345. + fl_oss_max_oss: [345, 345] + # Total needs per person = $1,103.50 + $160 = $1,263.50. Income = $0. + # OSS per person = min($1,263.50, $345) = $345. + fl_oss: [345, 345] + +# ────────────────────────────────────────────────────────────── +# Couple: income at total_needs - max_oss boundary (Redesign) +# Per person: total_needs = $1,102.90, max_oss = $193.40. +# Boundary income = $1,102.90 - $193.40 = $909.50/month per person. +# Annual per person = $909.50 * 12 = $10,914. +# ────────────────────────────────────────────────────────────── + +- name: Case 20, couple income at total needs minus max OSS, benefit exactly equals max. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: AFCH + fl_oss_program_track: REDESIGN + age: 72 + is_ssi_eligible: true + ssi_claim_is_joint: true + uncapped_ssi: 12 + # $909.50/month * 12 = $10,914/year. + ssi_countable_income: 10_914 + person2: + fl_oss_community_care_type: AFCH + fl_oss_program_track: REDESIGN + age: 68 + is_ssi_eligible: true + ssi_claim_is_joint: true + uncapped_ssi: 12 + ssi_countable_income: 10_914 + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: FL + output: + fl_oss_eligible: [true, true] + # Per person: min(max(0, $1,102.90 - $909.50), $193.40) = min($193.40, $193.40) = $193.40. + fl_oss: [193.40, 193.40] + +# ────────────────────────────────────────────────────────────── +# Couple income standard boundary (Redesign) +# Per person income standard = $996.90/month = $11,962.80/year. +# ────────────────────────────────────────────────────────────── + +- name: Case 21, couple income exactly at income standard, Group 2 eligible. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: AFCH + fl_oss_program_track: REDESIGN + age: 72 + is_ssi_eligible: true + ssi_claim_is_joint: true + uncapped_ssi: -100 + # $996.90/month * 12 = $11,962.80/year. + ssi_countable_income: 11_962.80 + person2: + fl_oss_community_care_type: AFCH + fl_oss_program_track: REDESIGN + age: 68 + is_ssi_eligible: true + ssi_claim_is_joint: true + uncapped_ssi: -100 + ssi_countable_income: 11_962.80 + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: FL + output: + # Income ($996.90) <= income standard ($996.90) → Group 2 eligible. + fl_oss_eligible: [true, true] + fl_oss_income_standard: [996.90, 996.90] + # Per person: min(max(0, $1,102.90 - $996.90), $193.40) = min($106, $193.40) = $106. + fl_oss: [106, 106] + +# ────────────────────────────────────────────────────────────── +# 2011 historical Protected track (offset=0, max=0 before Jul 2024) +# ────────────────────────────────────────────────────────────── + +- name: Case 22, 2011 Protected track, ineligible (track not in effect). + period: 2011-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: MHRTF + fl_oss_program_track: PROTECTED + age: 45 + is_ssi_eligible: true + ssi_claim_is_joint: false + uncapped_ssi: 2_088 + ssi_countable_income: 6_000 + households: + household: + members: [person1] + state_code: FL + output: + # Protected track not in effect before Jul 2024. + fl_oss_eligible: [false] + fl_oss: [0] + +# ────────────────────────────────────────────────────────────── +# Partial benefit: income between (total_needs - max_oss) and total_needs +# Redesign I: total_needs = $1,151.40, max_oss = $184.40. +# Transition at $967/month. Test $1,050/month → partial benefit. +# ────────────────────────────────────────────────────────────── + +- name: Case 23, partial benefit between threshold and total needs. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + uncapped_ssi: 12 + # $1,050/month * 12 = $12,600/year. + # Income standard = $1,045.40, but Group 1 (SSI recipient) so still eligible. + ssi_countable_income: 12_600 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_eligible: [true] + # Total needs = $1,151.40. Income = $1,050. + # OSS = min(max(0, $1,151.40 - $1,050), $184.40) = min($101.40, $184.40) = $101.40. + fl_oss: [101.40] + +# ────────────────────────────────────────────────────────────── +# Group 1 SSI recipient with income above Group 2 income standard +# SSI recipients (Group 1) can still receive OSS even if income > income standard, +# because the eligibility formula is: receives_ssi | income_within_standard. +# ────────────────────────────────────────────────────────────── + +- name: Case 24, SSI recipient with income above income standard but below total needs. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + # Income = $1,050/month > income standard $1,045.40 (would fail Group 2). + # But uncapped_ssi > 0 → SSI recipient → Group 1 eligible. + uncapped_ssi: 12 + ssi_countable_income: 12_600 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_eligible: [true] + # Income ($1,050) > income standard ($1,045.40) but Group 1 applies. + fl_oss_income_standard: [1_045.40] + # Total needs = $1,151.40. OSS = min(max(0, $1,151.40 - $1,050), $184.40) + # = min($101.40, $184.40) = $101.40. + fl_oss: [101.40] + +# ────────────────────────────────────────────────────────────── +# Not SSI eligible (fails categorically_eligible) +# ────────────────────────────────────────────────────────────── + +- name: Case 25, not SSI eligible even with low income, ineligible. + period: 2025-01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 40 + # Not aged/blind/disabled → is_ssi_eligible = false. + is_ssi_eligible: false + ssi_claim_is_joint: false + uncapped_ssi: 0 + ssi_countable_income: 0 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_eligible: [false] + fl_oss: [0] + +# ────────────────────────────────────────────────────────────── +# Facility type set but track is NONE → has_track fails +# ────────────────────────────────────────────────────────────── + +- name: Case 26, facility type set but program track NONE, ineligible. + period: 2025-01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: NONE + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + uncapped_ssi: 2_004 + ssi_countable_income: 9_600 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_eligible: [false] + fl_oss: [0] + +# ────────────────────────────────────────────────────────────── +# Track set but facility type NONE → in_facility fails +# ────────────────────────────────────────────────────────────── + +- name: Case 27, program track set but facility type NONE, ineligible. + period: 2025-01 + input: + people: + person1: + fl_oss_community_care_type: NONE + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + uncapped_ssi: 2_004 + ssi_countable_income: 9_600 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_eligible: [false] + fl_oss: [0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/fl_oss.yaml b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/fl_oss.yaml new file mode 100644 index 00000000000..41ae5ff7357 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/fl_oss.yaml @@ -0,0 +1,188 @@ +# Tests for fl_oss variable (final OSS payment). +# Formula: fl_oss = min(max(0, total_needs - countable_income), max_oss) + +- name: Case 1, SSI recipient Redesign individual with typical income. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + # uncapped_ssi > 0 means person receives SSI (Group 1). + # $967/month FBR - $800/month income = $167/month uncapped. + # Annual: $167 * 12 = $2,004. + uncapped_ssi: 2_004 + # Annual countable income = $800 * 12 = $9,600. + ssi_countable_income: 9_600 + households: + household: + members: [person1] + state_code: FL + output: + # Total needs (I, Redesign) = $991.40 + $160 = $1,151.40/month = $13,816.80/year. + # Countable income = $9,600/year. + # Calculated OSS = $13,816.80 - $9,600 = $4,216.80/year. + # Max OSS (Redesign, I) = $184.40/month = $2,212.80/year. + # OSS = min($4,216.80, $2,212.80) = $2,212.80/year. + # Monthly output = $2,212.80 / 12 = $184.40. + fl_oss: [184.40] + +- name: Case 2, SSI recipient Protected individual with typical income. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: MHRTF + fl_oss_program_track: PROTECTED + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + uncapped_ssi: 2_004 + ssi_countable_income: 9_600 + households: + household: + members: [person1] + state_code: FL + output: + # Total needs (I, Protected) = $1,152 + $160 = $1,312/month = $15,744/year. + # Countable income = $9,600/year. + # Calculated OSS = $15,744 - $9,600 = $6,144/year. + # Max OSS (Protected, I) = $345/month = $4,140/year. + # OSS = min($6,144, $4,140) = $4,140/year. + # Monthly output = $4,140 / 12 = $345. + fl_oss: [345] + +- name: Case 3, income exceeds total needs, zero benefit. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + # Income exceeds total needs, so max(0, total_needs - income) = 0. + uncapped_ssi: -2_000 + # $1,200/month countable income = $14,400/year. + # Total needs Redesign (I) = $13,816.80/year. + # $14,400 > $13,816.80, so benefit = 0. + ssi_countable_income: 14_400 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss: [0] + +- name: Case 4, zero countable income, capped at max OSS. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + uncapped_ssi: 11_604 + ssi_countable_income: 0 + households: + household: + members: [person1] + state_code: FL + output: + # Total needs (I, Redesign) = $13,816.80/year. + # Countable income = $0. + # Calculated OSS = $13,816.80/year. + # Max OSS (Redesign, I) = $2,212.80/year. + # OSS = min($13,816.80, $2,212.80) = $2,212.80/year. + # Monthly output = $2,212.80 / 12 = $184.40. + fl_oss: [184.40] + +- name: Case 5, income just below total needs, partial benefit under max. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + uncapped_ssi: -500 + # $1,100/month = $13,200/year. + # Total needs Redesign (I) = $13,816.80/year. + # Calculated = $13,816.80 - $13,200 = $616.80/year. + # But income standard (I, Redesign) = $1,045.40/month = $12,544.80/year. + # $13,200 > $12,544.80 so Group 2 check fails. + # Also uncapped_ssi < 0 so not Group 1. + # Person is INELIGIBLE (income above income standard for Group 2). + ssi_countable_income: 13_200 + households: + household: + members: [person1] + state_code: FL + output: + # Ineligible: uncapped_ssi <= 0 AND income > income standard. + fl_oss: [0] + +- name: Case 6, Group 2 eligible with income below income standard, small benefit. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + # Not an SSI recipient (income too high for SSI), but within OSS income standard. + uncapped_ssi: -100 + # $1,000/month = $12,000/year. + # Income standard (Redesign, I) = $1,045.40/month = $12,544.80/year. + # $12,000 < $12,544.80 → Group 2 eligible. + ssi_countable_income: 12_000 + households: + household: + members: [person1] + state_code: FL + output: + # Total needs (Redesign, I) = $13,816.80/year. + # Countable income = $12,000/year. + # Calculated = $13,816.80 - $12,000 = $1,816.80/year. + # Max OSS (Redesign, I) = $2,212.80/year. + # OSS = min($1,816.80, $2,212.80) = $1,816.80/year. + # Monthly output = $1,816.80 / 12 = $151.40. + fl_oss: [151.40] + +- name: Case 7, negative countable income does not inflate benefit beyond max. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + uncapped_ssi: 60_000_000 + ssi_countable_income: -60_000_000 + households: + household: + members: [person1] + state_code: FL + output: + # Even with hugely negative income, OSS is capped at max. + # Max OSS (Redesign, I) = $184.40/month. + fl_oss: [184.40] diff --git a/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/fl_oss_couple_rate_applies.yaml b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/fl_oss_couple_rate_applies.yaml new file mode 100644 index 00000000000..3a60a241f7e --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/fl_oss_couple_rate_applies.yaml @@ -0,0 +1,160 @@ +# Tests for fl_oss_couple_rate_applies variable. +# Couple rate requires: ssi_claim_is_joint AND both spouses is_ssi_eligible +# AND both spouses in a qualifying facility (living_arrangement != NONE). + +- name: Case 1, both spouses eligible and in facility, couple rate applies. + period: 2025-01 + input: + people: + person1: + fl_oss_community_care_type: ALF + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: true + person2: + fl_oss_community_care_type: ALF + age: 68 + is_ssi_eligible: true + ssi_claim_is_joint: true + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: FL + output: + fl_oss_couple_rate_applies: [true, true] + +- name: Case 2, one spouse not SSI eligible, couple rate does not apply. + period: 2025-01 + input: + people: + person1: + fl_oss_community_care_type: ALF + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + person2: + fl_oss_community_care_type: ALF + age: 40 + is_ssi_eligible: false + ssi_claim_is_joint: false + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: FL + output: + fl_oss_couple_rate_applies: [false, false] + +- name: Case 3, one spouse not in facility, couple rate does not apply. + period: 2025-01 + input: + people: + person1: + fl_oss_community_care_type: ALF + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: true + person2: + age: 68 + is_ssi_eligible: true + ssi_claim_is_joint: true + # No facility type → living arrangement = NONE + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: FL + output: + fl_oss_couple_rate_applies: [false, false] + +- name: Case 4, single person, couple rate does not apply. + period: 2025-01 + input: + people: + person1: + fl_oss_community_care_type: ALF + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_couple_rate_applies: [false] + +- name: Case 5, both in Medicaid facility, couple rate applies. + period: 2025-01 + input: + people: + person1: + age: 72 + is_ssi_eligible: true + ssi_claim_is_joint: true + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + person2: + age: 68 + is_ssi_eligible: true + ssi_claim_is_joint: true + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: FL + output: + fl_oss_couple_rate_applies: [true, true] + +- name: Case 6, mixed arrangement, one ALF one Medicaid facility, no couple rate. + period: 2025-01 + input: + people: + person1: + fl_oss_community_care_type: ALF + age: 70 + is_ssi_eligible: true + # Per 20 CFR 416.1149 (see #8003), SSI stops treating the + # couple as married when one enters a Title XIX institution. + ssi_claim_is_joint: false + person2: + age: 68 + is_ssi_eligible: true + ssi_claim_is_joint: false + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: FL + output: + # ssi_claim_is_joint = false → couple rate does not apply. + fl_oss_couple_rate_applies: [false, false] diff --git a/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/fl_oss_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/fl_oss_eligible.yaml new file mode 100644 index 00000000000..4642a157b07 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/fl_oss_eligible.yaml @@ -0,0 +1,115 @@ +# Tests for fl_oss_eligible variable. +# Eligibility requires: is_ssi_eligible AND facility type != NONE AND +# (uncapped_ssi > 0 [Group 1 SSI recipient] OR income <= income_standard [Group 2]) + +- name: Case 1, SSI recipient in ALF (Redesign) is eligible. + period: 2025-01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + # uncapped_ssi is YEAR-defined; $967 annual = $80.58/month output. + # >0 means person receives SSI (Group 1). + uncapped_ssi: 967 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_eligible: [true] + +- name: Case 2, person not SSI eligible is ineligible. + period: 2025-01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 40 + is_ssi_eligible: false + uncapped_ssi: 0 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_eligible: [false] + +- name: Case 3, wrong state is ineligible. + period: 2025-01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + uncapped_ssi: 967 + households: + household: + members: [person1] + state_code: CA + output: + fl_oss_eligible: [false] + +- name: Case 4, no facility placement (NONE) is ineligible. + period: 2025-01 + input: + people: + person1: + fl_oss_community_care_type: NONE + fl_oss_program_track: NONE + age: 70 + is_ssi_eligible: true + uncapped_ssi: 967 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_eligible: [false] + +- name: Case 5, Group 2 non-SSI recipient with income below income standard is eligible. + period: 2025-01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + # uncapped_ssi <= 0 means not an SSI recipient (income too high for SSI). + # But if income <= OSS income standard, Group 2 applies. + uncapped_ssi: -100 + # ssi_countable_income is YEAR-defined. + # Redesign income standard (I) 2025 = $991.40 + $54 = $1,045.40/month + # = $12,544.80/year. Set income below that. + ssi_countable_income: 12_000 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_eligible: [true] + +- name: Case 6, Group 2 non-SSI recipient with income above income standard is ineligible. + period: 2025-01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + uncapped_ssi: -500 + # Income well above income standard of $12,544.80/year. + ssi_countable_income: 15_000 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_eligible: [false] diff --git a/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/fl_oss_income_standard.yaml b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/fl_oss_income_standard.yaml new file mode 100644 index 00000000000..076e4db6b5a --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/fl_oss_income_standard.yaml @@ -0,0 +1,80 @@ +# Tests for fl_oss_income_standard variable. +# Redesign income standard = provider rate + $54 (frozen old PNA offset). +# Protected income standard = provider rate (same value). + +- name: Case 1, Redesign individual income standard Jan 2025. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + households: + household: + members: [person1] + state_code: FL + output: + # Redesign provider rate (I) = $991.40/month. + # Income standard PNA offset = $54/month. + # Income standard = $991.40 + $54 = $1,045.40/month. + # Annual = $1,045.40 * 12 = $12,544.80. + # Monthly output = $12,544.80 / 12 = $1,045.40. + fl_oss_income_standard: [1_045.40] + +- name: Case 2, Protected individual income standard Jan 2025. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_program_track: PROTECTED + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + households: + household: + members: [person1] + state_code: FL + output: + # Protected income standard = provider rate = $1,152/month. + # Annual = $1,152 * 12 = $13,824. + # Monthly output = $13,824 / 12 = $1,152. + fl_oss_income_standard: [1_152] + +- name: Case 3, Redesign couple income standard Jan 2025. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: true + person2: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 68 + is_ssi_eligible: true + ssi_claim_is_joint: true + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: FL + output: + # Couple provider rate (Redesign) = $1,885.80/month. + # Couple income standard = couple provider rate + 2 * $54 = $1,885.80 + $108 = $1,993.80/month. + # Per person = $1,993.80 / 2 = $996.90/month. + # Annual per person = $996.90 * 12 = $11,962.80. + # Monthly output = $11,962.80 / 12 = $996.90. + fl_oss_income_standard: [996.90, 996.90] diff --git a/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/fl_oss_living_arrangement.yaml b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/fl_oss_living_arrangement.yaml new file mode 100644 index 00000000000..77ceb01fa3d --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/fl_oss_living_arrangement.yaml @@ -0,0 +1,108 @@ +# Tests for fl_oss_living_arrangement variable. +# Formula derives from federal ssi_federal_living_arrangement (Medicaid facility) +# and state fl_oss_community_care_type (ALF, AFCH, MHRTF). + +- name: Case 1, ALF community care type maps to ALF. + period: 2025-01 + input: + people: + person1: + fl_oss_community_care_type: ALF + age: 70 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_living_arrangement: ALF + +- name: Case 2, AFCH community care type maps to AFCH. + period: 2025-01 + input: + people: + person1: + fl_oss_community_care_type: AFCH + age: 70 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_living_arrangement: AFCH + +- name: Case 3, MHRTF community care type maps to MHRTF. + period: 2025-01 + input: + people: + person1: + fl_oss_community_care_type: MHRTF + age: 45 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_living_arrangement: MHRTF + +- name: Case 4, no facility defaults to NONE. + period: 2025-01 + input: + people: + person1: + age: 70 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_living_arrangement: NONE + +- name: Case 5, federal Code D derives MEDICAID_FACILITY. + period: 2025-01 + input: + people: + person1: + age: 70 + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_living_arrangement: MEDICAID_FACILITY + +- name: Case 6, federal Code D takes priority over community care type. + period: 2025-01 + input: + people: + person1: + age: 70 + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + fl_oss_community_care_type: ALF + households: + household: + members: [person1] + state_code: FL + output: + # Federal Medicaid facility detection overrides state community care input. + fl_oss_living_arrangement: MEDICAID_FACILITY + +- name: Case 7, medical facility without Medicaid paying majority is not Code D. + period: 2025-01 + input: + people: + person1: + age: 70 + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: false + households: + household: + members: [person1] + state_code: FL + output: + # Without Medicaid paying majority of care, federal living arrangement + # is not MEDICAL_TREATMENT_FACILITY, so falls through to community care + # type (default NONE). + fl_oss_living_arrangement: NONE diff --git a/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/fl_oss_max_oss.yaml b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/fl_oss_max_oss.yaml new file mode 100644 index 00000000000..6710fc92381 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/fl_oss_max_oss.yaml @@ -0,0 +1,110 @@ +# Tests for fl_oss_max_oss variable. +# Max OSS caps by track and individual/couple status. + +- name: Case 1, Redesign individual max OSS Jan 2025. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + households: + household: + members: [person1] + state_code: FL + output: + # Max OSS (Redesign, I) = $184.40/month (frozen). + # Annual = $184.40 * 12 = $2,212.80. + # Monthly output = $2,212.80 / 12 = $184.40. + fl_oss_max_oss: [184.40] + +- name: Case 2, Protected individual max OSS Jan 2025. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_program_track: PROTECTED + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + households: + household: + members: [person1] + state_code: FL + output: + # Max OSS (Protected, I) = $345/month (frozen). + # Annual = $345 * 12 = $4,140. + # Monthly output = $4,140 / 12 = $345. + fl_oss_max_oss: [345] + +- name: Case 3, Redesign couple max OSS Jan 2025. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: true + person2: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 68 + is_ssi_eligible: true + ssi_claim_is_joint: true + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: FL + output: + # Max OSS (Redesign, C) = $386.80/month (frozen). + # Per person = $386.80 / 2 = $193.40/month. + # Annual per person = $193.40 * 12 = $2,320.80. + # Monthly output = $2,320.80 / 12 = $193.40. + fl_oss_max_oss: [193.40, 193.40] + +- name: Case 4, Protected couple max OSS Jan 2025. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: MHRTF + fl_oss_program_track: PROTECTED + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: true + person2: + fl_oss_community_care_type: MHRTF + fl_oss_program_track: PROTECTED + age: 68 + is_ssi_eligible: true + ssi_claim_is_joint: true + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: FL + output: + # Max OSS (Protected, C) = $690/month (frozen). + # Per person = $690 / 2 = $345/month. + # Annual per person = $345 * 12 = $4,140. + # Monthly output = $4,140 / 12 = $345. + fl_oss_max_oss: [345, 345] diff --git a/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/fl_oss_program_track.yaml b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/fl_oss_program_track.yaml new file mode 100644 index 00000000000..53168e9e187 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/fl_oss_program_track.yaml @@ -0,0 +1,50 @@ +# Tests for fl_oss_program_track variable. +# Input enum: REDESIGN, PROTECTED, NONE. +# REDESIGN = ALF, AFCH, RTF enrolled for ACS. +# PROTECTED = RTF not enrolled for ACS + 2001 "Gap" Group. +# NONE = no facility / not in program. + +- name: Case 1, Redesign track (ALF). + period: 2025-01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 70 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_program_track: REDESIGN + +- name: Case 2, Protected track (RTF not enrolled for ACS). + period: 2025-01 + input: + people: + person1: + fl_oss_community_care_type: MHRTF + fl_oss_program_track: PROTECTED + age: 70 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_program_track: PROTECTED + +- name: Case 3, NONE (no facility). + period: 2025-01 + input: + people: + person1: + fl_oss_community_care_type: NONE + fl_oss_program_track: NONE + age: 70 + households: + household: + members: [person1] + state_code: FL + output: + fl_oss_program_track: NONE diff --git a/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/fl_oss_provider_rate.yaml b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/fl_oss_provider_rate.yaml new file mode 100644 index 00000000000..1f2b4fcccf4 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/fl_oss_provider_rate.yaml @@ -0,0 +1,134 @@ +# Tests for fl_oss_provider_rate variable. +# Redesign (I) = SSI FBR (individual) + offset. +# Protected (I) = SSI FBR (individual) + offset. +# Couple = 2 * individual rate - $97 couple reduction. + +- name: Case 1, individual Redesign provider rate Jan 2025. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + households: + household: + members: [person1] + state_code: FL + output: + # SSI FBR (I) 2025 = $967/month = $11,604/year. + # Redesign offset = $24.40/month = $292.80/year. + # Provider rate = $11,604 + $292.80 = $11,896.80/year. + # Monthly output = $11,896.80 / 12 = $991.40. + fl_oss_provider_rate: [991.40] + +- name: Case 2, individual Protected provider rate Jan 2025. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_program_track: PROTECTED + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + households: + household: + members: [person1] + state_code: FL + output: + # SSI FBR (I) 2025 = $967/month = $11,604/year. + # Protected offset = $185/month = $2,220/year. + # Provider rate = $11,604 + $2,220 = $13,824/year. + # Monthly output = $13,824 / 12 = $1,152. + fl_oss_provider_rate: [1_152] + +- name: Case 3, couple Redesign provider rate Jan 2025. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: true + person2: + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + age: 68 + is_ssi_eligible: true + ssi_claim_is_joint: true + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: FL + output: + # Individual rate = $991.40/month. + # Couple rate = 2 * $991.40 - $97 = $1,885.80/month. + # Per person = $1,885.80 / 2 = $942.90/month. + # Annual per person = $942.90 * 12 = $11,314.80. + # Monthly output = $11,314.80 / 12 = $942.90. + fl_oss_provider_rate: [942.90, 942.90] + +- name: Case 4, couple Protected provider rate Jan 2025. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_community_care_type: MHRTF + fl_oss_program_track: PROTECTED + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: true + person2: + fl_oss_community_care_type: MHRTF + fl_oss_program_track: PROTECTED + age: 68 + is_ssi_eligible: true + ssi_claim_is_joint: true + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: FL + output: + # Individual Protected rate = $1,152/month. + # Couple rate = 2 * $1,152 - $97 = $2,207/month. + # Per person = $2,207 / 2 = $1,103.50/month. + fl_oss_provider_rate: [1_103.50, 1_103.50] + +- name: Case 5, individual Redesign provider rate 2024-01 (pre-restructuring era). + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + fl_oss_program_track: REDESIGN + age: 70 + is_ssi_eligible: true + ssi_claim_is_joint: false + households: + household: + members: [person1] + state_code: FL + output: + # SSI FBR (I) 2024 = $943/month. + # Redesign offset = $24.40/month. + # Provider rate = $943 + $24.40 = $967.40/month. + fl_oss_provider_rate: [967.40] diff --git a/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/integration.yaml new file mode 100644 index 00000000000..565724a26a4 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/fl/dcf/oss/integration.yaml @@ -0,0 +1,397 @@ +# Integration tests for Florida OSS (Optional State Supplementation). +# Uses real income sources and verifies the full federal SSI → state OSS chain. + +- name: Case 1, SSI recipient in ALF (Redesign), $800/month Social Security. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security: 9_600 + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + households: + household: + members: [person1] + state_code: FL + output: + # Federal SSI: $800 - $20 general exclusion = $780 countable. + # SSI = $967 FBR - $780 = $187/month. + is_ssi_eligible: [true] + ssi_countable_income: [780] + ssi: [187] + # State OSS: provider rate $991.40 + PNA $160 = $1,151.40 total needs. + # OSS = min(max($1,151.40 - $780, 0), $184.40) = min($371.40, $184.40) = $184.40. + fl_oss_eligible: [true] + fl_oss_provider_rate: [991.40] + fl_oss_income_standard: [1_045.40] + fl_oss_max_oss: [184.40] + fl_oss: [184.40] + +- name: Case 2, couple in AFCH (Redesign), $600/month Social Security each. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + social_security: 7_200 + fl_oss_community_care_type: AFCH + fl_oss_program_track: REDESIGN + person2: + age: 68 + social_security: 7_200 + fl_oss_community_care_type: AFCH + fl_oss_program_track: REDESIGN + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: FL + output: + # Federal SSI (couple): each $600 - $10 exclusion = $590 countable. + # SSI per person = $725 (half couple FBR $1,450) - $590 = $135/month. + is_ssi_eligible: [true, true] + ssi_countable_income: [590, 590] + ssi: [135, 135] + # State OSS: couple provider rate = 2 * $991.40 - $97 = $1,885.80. + # Per person = $942.90. Total needs = $942.90 + $160 = $1,102.90. + # OSS per person = min(max($1,102.90 - $590, 0), $193.40) = $193.40. + fl_oss_eligible: [true, true] + fl_oss_couple_rate_applies: [true, true] + fl_oss_provider_rate: [942.90, 942.90] + fl_oss_max_oss: [193.40, 193.40] + fl_oss: [193.40, 193.40] + +- name: Case 3, Group 2 non-SSI recipient, $1,000/month Social Security. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security: 12_000 + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + households: + household: + members: [person1] + state_code: FL + output: + # Federal SSI: $1,000 - $20 = $980 countable > $967 FBR → SSI = $0. + # But $980 < income standard $1,045.40 → Group 2 eligible. + is_ssi_eligible: [true] + ssi_countable_income: [980] + ssi: [0] + fl_oss_eligible: [true] + fl_oss_income_standard: [1_045.40] + # OSS = min(max($1,151.40 - $980, 0), $184.40) = min($171.40, $184.40) = $171.40. + fl_oss: [171.40] + +- name: Case 4, income above income standard, ineligible. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security: 13_200 + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + households: + household: + members: [person1] + state_code: FL + output: + # $1,100 - $20 = $1,080 countable > $1,045.40 standard → ineligible. + # SSI = $0 (income > FBR). Not Group 1 or Group 2. + is_ssi_eligible: [true] + ssi_countable_income: [1_080] + ssi: [0] + fl_oss_eligible: [false] + fl_oss: [0] + +- name: Case 5, disabled person in MHRTF (Protected), $700/month Social Security. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + is_disabled: true + social_security: 8_400 + fl_oss_community_care_type: MHRTF + fl_oss_program_track: PROTECTED + households: + household: + members: [person1] + state_code: FL + output: + # Federal SSI: $700 - $20 = $680 countable. + # SSI = $967 - $680 = $287/month. + is_ssi_eligible: [true] + ssi_countable_income: [680] + ssi: [287] + # State OSS (Protected): provider rate $1,152 + PNA $160 = $1,312. + # OSS = min(max($1,312 - $680, 0), $345) = min($632, $345) = $345. + fl_oss_eligible: [true] + fl_oss_provider_rate: [1_152] + fl_oss_max_oss: [345] + fl_oss: [345] + +- name: Case 6, SSI-eligible but no facility, not OSS eligible. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security: 9_600 + households: + household: + members: [person1] + state_code: FL + output: + is_ssi_eligible: [true] + ssi: [187] + fl_oss_eligible: [false] + fl_oss: [0] + +- name: Case 7, asymmetric couple, one eligible one not, individual rates. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security: 9_600 + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + person2: + age: 40 + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: FL + output: + # Person2 is not aged/blind/disabled → not SSI eligible. + # fl_oss_couple_rate_applies = false (both must be is_ssi_eligible). + # Person1 gets individual rates. + is_ssi_eligible: [true, false] + fl_oss_couple_rate_applies: [false, false] + fl_oss_eligible: [true, false] + fl_oss_provider_rate: [991.40, 991.40] + fl_oss: [184.40, 0] + +- name: Case 8, 2024-01, before PNA change, $700/month Social Security. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security: 8_400 + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + households: + household: + members: [person1] + state_code: FL + output: + # Federal SSI 2024: FBR $943. $700 - $20 = $680 countable. + # SSI = $943 - $680 = $263/month. + is_ssi_eligible: [true] + ssi_countable_income: [680] + ssi: [263] + # Pre-Jul 2024: PNA = $54, max OSS = $78.40. + # Provider rate = $943 + $24.40 = $967.40. + fl_oss_provider_rate: [967.40] + fl_oss_income_standard: [1_021.40] + fl_oss_max_oss: [78.40] + # OSS = min(max($1,021.40 - $680, 0), $78.40) = $78.40. + fl_oss: [78.40] + +- name: Case 9, 2011 historical, $500/month Social Security. + period: 2011-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security: 6_000 + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + households: + household: + members: [person1] + state_code: FL + output: + # Federal SSI 2011: FBR $674. $500 - $20 = $480 countable. + # SSI = $674 - $480 = $194/month. + is_ssi_eligible: [true] + ssi_countable_income: [480] + ssi: [194] + # 2011: offset $24.40, PNA $54, max OSS $78.40. + fl_oss_provider_rate: [698.40] + fl_oss_income_standard: [752.40] + fl_oss_max_oss: [78.40] + # OSS = min(max($752.40 - $480, 0), $78.40) = $78.40. + fl_oss: [78.40] + +- name: Case 10, Medicaid facility individual, 2011, federal-state connection. + period: 2011-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + households: + household: + members: [person1] + state_code: FL + output: + # Federal SSI: $30/month medical facility rate (no other income). + ssi: 30 + fl_oss_eligible: [true] + # State supplement: $5/month flat (SSA 2011 Table 1). + # Combined: $30 + $5 = $35/month. + fl_oss: [5] + +- name: Case 11, Medicaid facility couple, 2011, federal-state connection. + period: 2011-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + is_ssi_eligible: true + ssi_claim_is_joint: true + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + person2: + age: 68 + is_ssi_eligible: true + ssi_claim_is_joint: true + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: FL + output: + # Federal SSI: $30/month each. + ssi: [30, 30] + fl_oss_eligible: [true, true] + # State supplement: $10/month couple = $5/month each. + fl_oss: [5, 5] + +- name: Case 12, Medicaid facility with high income, no SSI, ineligible. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security: 12_000 + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + households: + household: + members: [person1] + state_code: FL + output: + # SSI medical facility rate = $30. Countable = $980 > $30 → SSI = $0. + # Medicaid facility requires Group 1 (ssi > 0) — no Group 2 path + # because FAC 65A-2.036 defines no income standard for Medicaid facility. + ssi: [0] + fl_oss_eligible: [false] + fl_oss: [0] + +- name: Case 13, couple with high combined income, SSI equal split. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security: 9_600 + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + person2: + age: 68 + social_security: 13_200 + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: FL + output: + # SSI couple: combined $1,900 - $20 exclusion = $1,880 countable. + # Per person = $940 (equal split). Couple FBR per person = $725. + # SSI = max($725 - $940, 0) = $0 each. Both fail Group 1. + is_ssi_eligible: [true, true] + ssi_countable_income: [940, 940] + ssi: [0, 0] + # Group 2: $940 < $996.90 (couple income standard) → both eligible. + # SSI equal-split ensures symmetric eligibility. + fl_oss_couple_rate_applies: [true, true] + fl_oss_eligible: [true, true] + fl_oss_provider_rate: [942.90, 942.90] + fl_oss_income_standard: [996.90, 996.90] + fl_oss_max_oss: [193.40, 193.40] + # OSS per person = min(max($1,102.90 - $940, 0), $193.40) = min($162.90, $193.40) = $162.90. + fl_oss: [162.90, 162.90] + +- name: Case 14, earnings with SSI earned income exclusions. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + employment_income: 6_000 + fl_oss_community_care_type: ALF + fl_oss_program_track: REDESIGN + households: + household: + members: [person1] + state_code: FL + output: + # Earned: $500/month. SSI exclusions: $500 - $20 - $65 = $415. + # 50% of $415 = $207.50 countable. + # SSI = $967 - $207.50 = $759.50/month. + is_ssi_eligible: [true] + ssi_countable_income: [207.50] + ssi: [759.50] + fl_oss_eligible: [true] + # OSS = min(max($1,151.40 - $207.50, 0), $184.40) = $184.40. + fl_oss: [184.40] diff --git a/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss.py b/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss.py new file mode 100644 index 00000000000..862ff0343b8 --- /dev/null +++ b/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss.py @@ -0,0 +1,34 @@ +from policyengine_us.model_api import * + + +class fl_oss(Variable): + value_type = float + entity = Person + label = "Florida Optional State Supplementation" + unit = USD + definition_period = MONTH + defined_for = "fl_oss_eligible" + reference = ( + "https://www.flrules.org/gateway/RuleNo.asp?title=PUBLIC%20ASSISTANCE&ID=65A-2.036", + "https://www.myflfamilies.com/sites/default/files/2024-10/Appendix%20A-12%20OSS%20Payment%20Standards.pdf", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.states.fl.dcf.oss + living_arrangement = person("fl_oss_living_arrangement", period) + LA = living_arrangement.possible_values + in_medicaid_facility = living_arrangement == LA.MEDICAID_FACILITY + # Medicaid facility: flat state supplement + couple_rate_applies = person("fl_oss_couple_rate_applies", period) + medicaid_supplement = where( + couple_rate_applies, + p.medicaid_facility.supplement.couple / 2, + p.medicaid_facility.supplement.individual, + ) + # Community care: provider rate + PNA - income, capped at max OSS + provider_rate = person("fl_oss_provider_rate", period) + total_needs = provider_rate + p.pna + countable_income = person("ssi_countable_income", period) + max_oss = person("fl_oss_max_oss", period) + community_benefit = min_(max_(total_needs - countable_income, 0), max_oss) + return where(in_medicaid_facility, medicaid_supplement, community_benefit) diff --git a/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss_community_care_type.py b/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss_community_care_type.py new file mode 100644 index 00000000000..4389602c79f --- /dev/null +++ b/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss_community_care_type.py @@ -0,0 +1,22 @@ +from policyengine_us.model_api import * + + +class FLOSSCommunityCareType(Enum): + ALF = "Assisted Living Facility" + AFCH = "Adult Family Care Home" + MHRTF = "Mental Health Residential Treatment Facility" + NONE = "None" + + +class fl_oss_community_care_type(Variable): + value_type = Enum + entity = Person + label = "Florida OSS community care facility type" + definition_period = MONTH + defined_for = StateCode.FL + possible_values = FLOSSCommunityCareType + default_value = FLOSSCommunityCareType.NONE + reference = ( + "https://www.flrules.org/gateway/RuleNo.asp?title=PUBLIC%20ASSISTANCE&ID=65A-2.032", + "https://www.myflfamilies.com/sites/default/files/2024-10/Appendix%20A-12%20OSS%20Payment%20Standards.pdf", + ) diff --git a/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss_couple_rate_applies.py b/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss_couple_rate_applies.py new file mode 100644 index 00000000000..bff8a750a81 --- /dev/null +++ b/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss_couple_rate_applies.py @@ -0,0 +1,28 @@ +from policyengine_us.model_api import * + + +class fl_oss_couple_rate_applies(Variable): + value_type = bool + entity = Person + label = "Florida OSS couple rate applies" + definition_period = MONTH + defined_for = StateCode.FL + reference = "https://www.myflfamilies.com/sites/default/files/2025-05/Appendix%20A-12%20-%20State%20Funded%20Programs%20Eligibility%20Standards.pdf" + + def formula(person, period, parameters): + # Requires: both spouses are an SSI eligible couple + # (ssi_claim_is_joint handles Title XIX separation per + # 20 CFR 416.1149 — see #8003), both pass SSI categorical + # eligibility (resources + immigration), and both reside + # in a qualifying OSS facility. + joint_claim = person("ssi_claim_is_joint", period) + both_ssi_eligible = ( + person.marital_unit.sum(person("is_ssi_eligible", period)) + == person.marital_unit.nb_persons() + ) + living_arrangement = person("fl_oss_living_arrangement", period) + in_facility = living_arrangement != living_arrangement.possible_values.NONE + both_in_facility = ( + person.marital_unit.sum(in_facility) == person.marital_unit.nb_persons() + ) + return joint_claim & both_ssi_eligible & both_in_facility diff --git a/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss_eligible.py b/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss_eligible.py new file mode 100644 index 00000000000..a3767224fb2 --- /dev/null +++ b/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss_eligible.py @@ -0,0 +1,42 @@ +from policyengine_us.model_api import * + + +class fl_oss_eligible(Variable): + value_type = bool + entity = Person + label = "Florida OSS eligible" + definition_period = MONTH + defined_for = StateCode.FL + reference = ( + "https://www.flrules.org/gateway/RuleNo.asp?title=PUBLIC%20ASSISTANCE&ID=65A-2.032", + "https://www.flrules.org/gateway/RuleNo.asp?title=PUBLIC%20ASSISTANCE&ID=65A-2.033", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.states.fl.dcf.oss + categorically_eligible = person("is_ssi_eligible", period) + living_arrangement = person("fl_oss_living_arrangement", period) + LA = living_arrangement.possible_values + in_facility = living_arrangement != LA.NONE + in_medicaid_facility = living_arrangement == LA.MEDICAID_FACILITY + # FAC 65A-2.033(1): "receiving SSI checks" + receives_ssi = person("ssi", period) > 0 + # Medicaid facility: Group 1 only (no income standard defined + # in FAC 65A-2.036 for Medicaid facility; the $30 medical + # facility SSI rate is the only payment path). + # Community care: Group 1 OR Group 2 (income ≤ income standard), + # plus requires a valid program track. + program_track = person("fl_oss_program_track", period) + has_track = program_track != program_track.possible_values.NONE + is_protected = program_track == program_track.possible_values.PROTECTED + track_valid = where(is_protected, p.protected.in_effect, has_track) + # FAC 65A-2.033(2): income ≤ OSS income standard + income_standard = person("fl_oss_income_standard", period) + countable_income = person("ssi_countable_income", period) + income_within_standard = countable_income <= income_standard + community_eligible = track_valid & (receives_ssi | income_within_standard) + return ( + categorically_eligible + & in_facility + & where(in_medicaid_facility, receives_ssi, community_eligible) + ) diff --git a/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss_income_standard.py b/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss_income_standard.py new file mode 100644 index 00000000000..0ad1d6a30a5 --- /dev/null +++ b/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss_income_standard.py @@ -0,0 +1,25 @@ +from policyengine_us.model_api import * + + +class fl_oss_income_standard(Variable): + value_type = float + entity = Person + label = "Florida OSS income standard" + unit = USD + definition_period = MONTH + defined_for = StateCode.FL + reference = "https://www.myflfamilies.com/sites/default/files/2025-05/Appendix%20A-12%20-%20State%20Funded%20Programs%20Eligibility%20Standards.pdf" + + def formula(person, period, parameters): + p = parameters(period).gov.states.fl.dcf.oss + track = person("fl_oss_program_track", period) + is_redesign = track == track.possible_values.REDESIGN + provider_rate = person("fl_oss_provider_rate", period) + # Redesign: income standard = provider rate + PNA offset + # Protected: income standard = provider rate + pna_offset = where( + is_redesign, + p.redesign.income_standard_pna_offset, + 0, + ) + return provider_rate + pna_offset diff --git a/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss_living_arrangement.py b/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss_living_arrangement.py new file mode 100644 index 00000000000..a1eea325eb1 --- /dev/null +++ b/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss_living_arrangement.py @@ -0,0 +1,47 @@ +from policyengine_us.model_api import * + + +class FLOSSLivingArrangement(Enum): + ALF = "Assisted Living Facility" + AFCH = "Adult Family Care Home" + MHRTF = "Mental Health Residential Treatment Facility" + MEDICAID_FACILITY = "Medicaid facility" + NONE = "None" + + +class fl_oss_living_arrangement(Variable): + value_type = Enum + entity = Person + label = "Florida OSS living arrangement" + definition_period = MONTH + defined_for = StateCode.FL + possible_values = FLOSSLivingArrangement + default_value = FLOSSLivingArrangement.NONE + reference = ( + "https://www.flrules.org/gateway/RuleNo.asp?title=PUBLIC%20ASSISTANCE&ID=65A-2.032", + "https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/2011/fl.html", + ) + + def formula(person, period): + federal_la = person("ssi_federal_living_arrangement", period) + in_medical_facility = ( + federal_la == federal_la.possible_values.MEDICAL_TREATMENT_FACILITY + ) + community_care = person("fl_oss_community_care_type", period) + CC = community_care.possible_values + LA = FLOSSLivingArrangement + return select( + [ + in_medical_facility, + community_care == CC.ALF, + community_care == CC.AFCH, + community_care == CC.MHRTF, + ], + [ + LA.MEDICAID_FACILITY, + LA.ALF, + LA.AFCH, + LA.MHRTF, + ], + default=LA.NONE, + ) diff --git a/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss_max_oss.py b/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss_max_oss.py new file mode 100644 index 00000000000..888363d0281 --- /dev/null +++ b/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss_max_oss.py @@ -0,0 +1,32 @@ +from policyengine_us.model_api import * + + +class fl_oss_max_oss(Variable): + value_type = float + entity = Person + label = "Florida OSS maximum payment" + unit = USD + definition_period = MONTH + defined_for = StateCode.FL + reference = "https://www.myflfamilies.com/sites/default/files/2025-05/Appendix%20A-12%20-%20State%20Funded%20Programs%20Eligibility%20Standards.pdf" + + def formula(person, period, parameters): + p = parameters(period).gov.states.fl.dcf.oss + track = person("fl_oss_program_track", period) + is_redesign = track == track.possible_values.REDESIGN + couple_rate_applies = person("fl_oss_couple_rate_applies", period) + if p.protected.in_effect: + individual_cap = where( + is_redesign, + p.redesign.max_oss.individual, + p.protected.max_oss.individual, + ) + couple_cap = where( + is_redesign, + p.redesign.max_oss.couple, + p.protected.max_oss.couple, + ) + else: + individual_cap = p.redesign.max_oss.individual + couple_cap = p.redesign.max_oss.couple + return where(couple_rate_applies, couple_cap / 2, individual_cap) diff --git a/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss_program_track.py b/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss_program_track.py new file mode 100644 index 00000000000..2db27d1a7b2 --- /dev/null +++ b/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss_program_track.py @@ -0,0 +1,18 @@ +from policyengine_us.model_api import * + + +class FLOSSProgramTrack(Enum): + REDESIGN = "Redesign" + PROTECTED = "Protected" + NONE = "None" + + +class fl_oss_program_track(Variable): + value_type = Enum + entity = Person + label = "Florida OSS program track" + definition_period = MONTH + defined_for = StateCode.FL + possible_values = FLOSSProgramTrack + default_value = FLOSSProgramTrack.NONE + reference = "https://www.myflfamilies.com/sites/default/files/2024-10/Appendix%20A-12%20OSS%20Payment%20Standards.pdf" diff --git a/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss_provider_rate.py b/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss_provider_rate.py new file mode 100644 index 00000000000..080a3c13263 --- /dev/null +++ b/policyengine_us/variables/gov/states/fl/dcf/oss/fl_oss_provider_rate.py @@ -0,0 +1,29 @@ +from policyengine_us.model_api import * + + +class fl_oss_provider_rate(Variable): + value_type = float + entity = Person + label = "Florida OSS provider rate" + unit = USD + definition_period = MONTH + defined_for = StateCode.FL + reference = "https://www.myflfamilies.com/sites/default/files/2025-05/Appendix%20A-12%20-%20State%20Funded%20Programs%20Eligibility%20Standards.pdf" + + def formula(person, period, parameters): + p = parameters(period).gov.states.fl.dcf.oss + track = person("fl_oss_program_track", period) + is_redesign = track == track.possible_values.REDESIGN + fbr_individual = parameters(period).gov.ssa.ssi.amount.individual + if p.protected.in_effect: + offset = where( + is_redesign, + p.redesign.provider_rate_offset, + p.protected.provider_rate_offset, + ) + else: + offset = p.redesign.provider_rate_offset + individual_rate = fbr_individual + offset + couple_rate_applies = person("fl_oss_couple_rate_applies", period) + couple_rate = 2 * individual_rate - p.couple_provider_rate_reduction + return where(couple_rate_applies, couple_rate / 2, individual_rate) diff --git a/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py b/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py index a81e0b8bbd0..25643c0d833 100644 --- a/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py +++ b/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py @@ -15,6 +15,7 @@ def formula(spm_unit, period, parameters): "al_ssp", "ak_ssp", "de_ssp", # Delaware benefits + "fl_oss", "ma_state_supplement", # Massachusetts benefits # California programs. "ca_cvrp", # California Clean Vehicle Rebate Project.