diff --git a/changelog.d/ia-ssp.added.md b/changelog.d/ia-ssp.added.md new file mode 100644 index 00000000000..a58a93e66bd --- /dev/null +++ b/changelog.d/ia-ssp.added.md @@ -0,0 +1 @@ +Added Iowa State Supplementary Assistance (SSA), covering the Blind, Dependent Person, Family-Life Home, In-Home Health-Related Care, Residential Care Facility, and Supplement for Medicare and Medicaid Eligibles supplements. diff --git a/policyengine_us/parameters/gov/household/household_state_benefits.yaml b/policyengine_us/parameters/gov/household/household_state_benefits.yaml index ed6f13b2d2d..445cecc4cbb 100644 --- a/policyengine_us/parameters/gov/household/household_state_benefits.yaml +++ b/policyengine_us/parameters/gov/household/household_state_benefits.yaml @@ -36,6 +36,8 @@ values: - ak_ssp # Florida benefits - fl_oss + # Iowa benefits + - ia_ssa # Idaho benefits - id_aabd # Kentucky benefits @@ -102,6 +104,8 @@ values: - ak_ssp # Florida benefits - fl_oss + # Iowa benefits + - ia_ssa # Idaho benefits - id_aabd # Kentucky benefits diff --git a/policyengine_us/parameters/gov/states/ia/hhs/ssa/blind.yaml b/policyengine_us/parameters/gov/states/ia/hhs/ssa/blind.yaml new file mode 100644 index 00000000000..56e9f101d1e --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/hhs/ssa/blind.yaml @@ -0,0 +1,18 @@ +description: Iowa provides this amount as the blind supplement under the State Supplementary Assistance program. + +values: + 2011-01-01: 22 + +metadata: + unit: currency-USD + period: month + label: Iowa SSA blind supplement amount + reference: + - title: Iowa Administrative Code 441—52.1(4) + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.52.pdf#page=2 + - title: SSA State Assistance Programs for SSI Recipients — Iowa (January 2011), Table 1 + href: https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/2011/ia.pdf#page=2 + - title: Iowa Administrative Code 441—52.1(4), January 4, 2017 supplement + href: https://www.legis.iowa.gov/docs/aco/supplement/01-04-2017.pdf#page=120 + - title: Iowa Administrative Code 441—52.1, March 28, 2018 rule update + href: https://www.legis.iowa.gov/docs/iac/rule/03-28-2018.441.52.1.pdf#page=2 diff --git a/policyengine_us/parameters/gov/states/ia/hhs/ssa/dp/assistance_standard.yaml b/policyengine_us/parameters/gov/states/ia/hhs/ssa/dp/assistance_standard.yaml new file mode 100644 index 00000000000..ec397918787 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/hhs/ssa/dp/assistance_standard.yaml @@ -0,0 +1,64 @@ +description: Iowa provides this monthly assistance standard for dependent person configurations under the State Supplementary Assistance program. + +metadata: + unit: currency-USD + period: month + label: Iowa SSA dependent person assistance standard + breakdown: + - ia_ssa_dp_configuration + reference: + - title: Iowa Administrative Code 441—52.1(2) + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.52.pdf#page=1 + - title: SSA State Assistance Programs for SSI Recipients — Iowa (January 2011), Table 1 OS code C totals + href: https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/2011/ia.pdf#page=2 + - title: Iowa Administrative Code 441—52.1(2), January 4, 2017 supplement + href: https://www.legis.iowa.gov/docs/aco/supplement/01-04-2017.pdf#page=119 + - title: Iowa Administrative Code 441—52.1, March 28, 2018 rule update + href: https://www.legis.iowa.gov/docs/iac/rule/03-28-2018.441.52.1.pdf#page=1 + - title: Iowa HHS General Letter 6-B-46 (effective January 1, 2025) + href: https://hhs.iowa.gov/media/15607/download + - title: Iowa HHS State Supplementary Assistance Standards (current) + href: https://hhs.iowa.gov/assistance-programs/state-supplementary-assistance + +AGED_OR_DISABLED_WITH_DEPENDENT: + 2011-01-01: 1_018 + 2017-01-01: 1_114 + 2018-01-01: 1_137 + 2025-01-01: 1_470 + 2026-01-01: 1_512 +AGED_OR_DISABLED_WITH_SPOUSE_AND_DEPENDENT: + 2011-01-01: 1_355 + 2017-01-01: 1_482 + 2018-01-01: 1_512 + 2025-01-01: 1_953 + 2026-01-01: 2_009 +BLIND_WITH_DEPENDENT: + 2011-01-01: 1_040 + 2017-01-01: 1_136 + 2018-01-01: 1_159 + 2025-01-01: 1_492 + 2026-01-01: 1_534 +BLIND_WITH_AGED_OR_DISABLED_SPOUSE_AND_DEPENDENT: + # 2011 Iowa HHS total; SSA 2011 Table 1 shows both-blind couple total $1,399; + # footnote a reduces the total by $22 when only one spouse is blind, giving $1,377. + 2011-01-01: 1_377 + 2017-01-01: 1_504 + 2018-01-01: 1_534 + 2025-01-01: 1_975 + # Iowa HHS's 2026 page publishes this configuration at $3,031 — a +53.5% jump + # vs 2025 ($1,975), out of step with the ~2.85% COLA applied to every other + # DP configuration and in conflict with the "-$22 when only one spouse is blind" + # footnote rule that holds for 2011/2017/2018/2025. The $3,031 value appears + # to be an Iowa HHS publication error (likely a transposed digit from an + # intended $2,031). Encoded as the COLA-consistent total $2,031, which + # preserves the 14-year footnote pattern; revisit if Iowa HHS corrects the + # page or issues a General Letter confirming the higher figure. + 2026-01-01: 2_031 +BLIND_WITH_BLIND_SPOUSE_AND_DEPENDENT: + 2011-01-01: 1_399 + 2017-01-01: 1_526 + 2018-01-01: 1_556 + 2025-01-01: 1_997 + 2026-01-01: 2_053 +NONE: + 2011-01-01: 0 diff --git a/policyengine_us/parameters/gov/states/ia/hhs/ssa/dp/dependent_income_limit.yaml b/policyengine_us/parameters/gov/states/ia/hhs/ssa/dp/dependent_income_limit.yaml new file mode 100644 index 00000000000..959b5dedbae --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/hhs/ssa/dp/dependent_income_limit.yaml @@ -0,0 +1,26 @@ +description: Iowa limits a dependent relative's countable income to this amount for dependent person eligibility under the State Supplementary Assistance program. + +values: + # IAC 441—51.4(1): the dependent income limit equals the state portion of + # the AGED_OR_DISABLED_WITH_DEPENDENT assistance standard (total minus + # individual FBR). 2011 SSA report Table 1 (Code C aged/disabled) confirms + # state portion $344 ($1,018 total - $674 individual FBR). + 2011-01-01: 344 + 2017-01-01: 379 + 2018-01-01: 387 + 2025-01-01: 503 + 2026-01-01: 518 + +metadata: + unit: currency-USD + period: month + label: Iowa SSA dependent person dependent income limit + reference: + - title: Iowa Administrative Code 441—51.5(1) (dependent relative income test) + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.51.pdf#page=2 + - title: Iowa Administrative Code 441—51.4(1), January 4, 2017 supplement + href: https://www.legis.iowa.gov/docs/aco/supplement/01-04-2017.pdf#page=113 + - title: Iowa HHS Employees' Manual Title 6 Chapter B, Income (DP), p.15 + href: https://hhs.iowa.gov/media/15607/download#page=21 + - title: Iowa HHS State Supplementary Assistance Standards (current) + href: https://hhs.iowa.gov/assistance-programs/state-supplementary-assistance diff --git a/policyengine_us/parameters/gov/states/ia/hhs/ssa/flh/max_supplement.yaml b/policyengine_us/parameters/gov/states/ia/hhs/ssa/flh/max_supplement.yaml new file mode 100644 index 00000000000..323f3aab0f6 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/hhs/ssa/flh/max_supplement.yaml @@ -0,0 +1,16 @@ +description: Iowa limits the family-life home supplement to this amount under the State Supplementary Assistance program. + +values: + 2011-01-01: 142 + +metadata: + unit: currency-USD + period: month + label: Iowa SSA family-life home maximum supplement + reference: + - title: Iowa HHS Employees' Manual Title 6 Chapter B, Making the Family-Life Home Payment, p.31 + href: https://hhs.iowa.gov/media/15607/download#page=37 + - title: Iowa Administrative Code 441—52.1(1) + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.52.pdf#page=1 + - title: SSA State Assistance Programs for SSI Recipients — Iowa (January 2011), Table 1 OS code D aged + href: https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/2011/ia.pdf#page=2 diff --git a/policyengine_us/parameters/gov/states/ia/hhs/ssa/flh/state_supplement.yaml b/policyengine_us/parameters/gov/states/ia/hhs/ssa/flh/state_supplement.yaml new file mode 100644 index 00000000000..1388446f2ea --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/hhs/ssa/flh/state_supplement.yaml @@ -0,0 +1,26 @@ +description: Iowa provides this state supplement amount above the federal SSI benefit rate (FBR) for family-life home residents under the State Supplementary Assistance program. + +values: + 2011-01-01: 142 + 2017-01-01: 162 + 2018-01-01: 162 + 2025-01-01: 162 + 2026-01-01: 162 + +metadata: + unit: currency-USD + period: month + label: Iowa SSA family-life home state supplement + reference: + - title: Iowa Administrative Code 441—52.1(1) + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.52.pdf#page=1 + - title: SSA State Assistance Programs for SSI Recipients — Iowa (January 2011), Table 1 footnote a + href: https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/2011/ia.pdf#page=2 + - title: Iowa Administrative Code 441—52.1(1), January 4, 2017 supplement + href: https://www.legis.iowa.gov/docs/aco/supplement/01-04-2017.pdf#page=119 + - title: Iowa Administrative Code 441—52.1, March 28, 2018 rule update + href: https://www.legis.iowa.gov/docs/iac/rule/03-28-2018.441.52.1.pdf#page=1 + - title: Iowa HHS General Letter 6-B-46 (effective January 1, 2025) + href: https://hhs.iowa.gov/media/15607/download + - title: Iowa HHS State Supplementary Assistance Standards (current) + href: https://hhs.iowa.gov/assistance-programs/state-supplementary-assistance diff --git a/policyengine_us/parameters/gov/states/ia/hhs/ssa/ihhrc/max_cost_couple.yaml b/policyengine_us/parameters/gov/states/ia/hhs/ssa/ihhrc/max_cost_couple.yaml new file mode 100644 index 00000000000..925eb82eebd --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/hhs/ssa/ihhrc/max_cost_couple.yaml @@ -0,0 +1,14 @@ +description: Iowa limits combined couple countable income to this amount when both spouses need in-home health-related care under the State Supplementary Assistance program. + +values: + 2011-01-01: 961.10 + +metadata: + unit: currency-USD + period: month + label: Iowa SSA in-home health-related care combined couple income cap + reference: + - title: Iowa Administrative Code 441—177.4(1)(f) + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.177.pdf#page=2 + - title: SSA State Assistance Programs for SSI Recipients — Iowa (January 2011), Table 1 in-home health care couple + href: https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/2011/ia.pdf#page=2 diff --git a/policyengine_us/parameters/gov/states/ia/hhs/ssa/ihhrc/max_cost_single.yaml b/policyengine_us/parameters/gov/states/ia/hhs/ssa/ihhrc/max_cost_single.yaml new file mode 100644 index 00000000000..a126eb7b2d0 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/hhs/ssa/ihhrc/max_cost_single.yaml @@ -0,0 +1,16 @@ +description: Iowa limits the in-home health-related care supplement and countable income to this amount per person under the State Supplementary Assistance program. + +values: + 2011-01-01: 480.55 + +metadata: + unit: currency-USD + period: month + label: Iowa SSA in-home health-related care maximum cost single + reference: + - title: Iowa Administrative Code 441—177.4(1)(f) + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.177.pdf#page=2 + - title: Iowa Administrative Code 441—177.10(3) + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.177.pdf#page=5 + - title: SSA State Assistance Programs for SSI Recipients — Iowa (January 2011), Table 1 in-home health care + href: https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/2011/ia.pdf#page=2 diff --git a/policyengine_us/parameters/gov/states/ia/hhs/ssa/rcf/days_multiplier.yaml b/policyengine_us/parameters/gov/states/ia/hhs/ssa/rcf/days_multiplier.yaml new file mode 100644 index 00000000000..ef41744f615 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/hhs/ssa/rcf/days_multiplier.yaml @@ -0,0 +1,16 @@ +description: Iowa uses this number of days per month to convert the maximum per diem to a monthly residential care income limit under the State Supplementary Assistance program. + +values: + 2011-01-01: 31 + +metadata: + unit: /1 + period: eternity + label: Iowa SSA residential care facility days-per-month multiplier + reference: + - title: Iowa Administrative Code 441—51.4(3) + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.51.pdf#page=2 + - title: Iowa Administrative Code 441—52.1(3) + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.52.pdf#page=1 + - title: Iowa Administrative Code 441—51.4(3), January 4, 2017 supplement + href: https://www.legis.iowa.gov/docs/aco/supplement/01-04-2017.pdf#page=113 diff --git a/policyengine_us/parameters/gov/states/ia/hhs/ssa/rcf/max_per_diem.yaml b/policyengine_us/parameters/gov/states/ia/hhs/ssa/rcf/max_per_diem.yaml new file mode 100644 index 00000000000..5475be42ee6 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/hhs/ssa/rcf/max_per_diem.yaml @@ -0,0 +1,26 @@ +description: Iowa provides this amount as the maximum cost-related per diem for residential care facility residents under the State Supplementary Assistance program. + +values: + 2011-01-01: 28.14 + 2017-01-01: 30.11 + 2018-01-01: 30.60 + 2025-01-01: 37.60 + 2026-01-01: 38.47 + +metadata: + unit: currency-USD + period: day + label: Iowa SSA residential care facility maximum cost-related per diem + reference: + - title: Iowa Administrative Code 441—52.1(3) + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.52.pdf#page=1 + - title: SSA State Assistance Programs for SSI Recipients — Iowa (January 2011), Table 1 footnote b + href: https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/2011/ia.pdf#page=2 + - title: Iowa Administrative Code 441—52.1(3), January 4, 2017 supplement + href: https://www.legis.iowa.gov/docs/aco/supplement/01-04-2017.pdf#page=119 + - title: Iowa Administrative Code 441—52.1, March 28, 2018 rule update + href: https://www.legis.iowa.gov/docs/iac/rule/03-28-2018.441.52.1.pdf#page=1 + - title: Iowa HHS General Letter 6-B-46 (effective January 1, 2025) + href: https://hhs.iowa.gov/media/15607/download + - title: Iowa HHS State Supplementary Assistance Standards (current) + href: https://hhs.iowa.gov/assistance-programs/state-supplementary-assistance diff --git a/policyengine_us/parameters/gov/states/ia/hhs/ssa/rcf/personal_needs_allowance.yaml b/policyengine_us/parameters/gov/states/ia/hhs/ssa/rcf/personal_needs_allowance.yaml new file mode 100644 index 00000000000..5e3af7c9ced --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/hhs/ssa/rcf/personal_needs_allowance.yaml @@ -0,0 +1,28 @@ +description: Iowa provides this amount as the residential care facility personal needs allowance under the State Supplementary Assistance program. + +values: + 2011-01-01: 93 + 2017-01-01: 100 + 2018-01-01: 99 + 2025-01-01: 126 + 2026-01-01: 130 + +metadata: + unit: currency-USD + period: month + label: Iowa SSA residential care facility personal needs allowance + reference: + - title: Iowa Administrative Code 441—52.1(3) + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.52.pdf#page=1 + - title: Iowa Code Section 249.9A + href: https://www.legis.iowa.gov/docs/code/249.9A.pdf + - title: SSA State Assistance Programs for SSI Recipients — Iowa (January 2011), Table 1 footnote b + href: https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/2011/ia.pdf#page=2 + - title: Iowa Administrative Code 441—52.1(3), January 4, 2017 supplement + href: https://www.legis.iowa.gov/docs/aco/supplement/01-04-2017.pdf#page=119 + - title: Iowa Administrative Code 441—52.1, March 28, 2018 rule update + href: https://www.legis.iowa.gov/docs/iac/rule/03-28-2018.441.52.1.pdf#page=1 + - title: Iowa HHS General Letter 6-B-46 (effective January 1, 2025) + href: https://hhs.iowa.gov/media/15607/download + - title: Iowa HHS State Supplementary Assistance Standards (current) + href: https://hhs.iowa.gov/assistance-programs/state-supplementary-assistance diff --git a/policyengine_us/parameters/gov/states/ia/hhs/ssa/smme/amount.yaml b/policyengine_us/parameters/gov/states/ia/hhs/ssa/smme/amount.yaml new file mode 100644 index 00000000000..9912d4d4ef7 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/hhs/ssa/smme/amount.yaml @@ -0,0 +1,21 @@ +description: Iowa provides this amount as the supplement for Medicare and Medicaid eligibles under the State Supplementary Assistance program. + +values: + # SMME was added by 2004 Iowa Acts ch. 1085 (§4) at Iowa Code 249.3(4) as a + # technical token payment whose purpose is to bring Medicare premium + # payments under federal financial participation. The $1 token amount has + # been published since at least 2017; carried back to the program's + # earliest in-model date. + 2011-01-01: 1 + +metadata: + unit: currency-USD + period: month + label: Iowa SSA Medicare and Medicaid eligibles supplement amount + reference: + - title: Iowa Administrative Code 441—52.1(7) + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.52.pdf#page=2 + - title: Iowa Administrative Code 441—52.1(7), January 4, 2017 supplement + href: https://www.legis.iowa.gov/docs/aco/supplement/01-04-2017.pdf#page=120 + - title: Iowa Administrative Code 441—52.1, March 28, 2018 rule update + href: https://www.legis.iowa.gov/docs/iac/rule/03-28-2018.441.52.1.pdf#page=3 diff --git a/policyengine_us/parameters/gov/states/ia/hhs/ssa/smme/minimum_income_fpl_multiplier.yaml b/policyengine_us/parameters/gov/states/ia/hhs/ssa/smme/minimum_income_fpl_multiplier.yaml new file mode 100644 index 00000000000..0aaf21ce96a --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/hhs/ssa/smme/minimum_income_fpl_multiplier.yaml @@ -0,0 +1,19 @@ +description: Iowa uses this share of the federal poverty level as the minimum income threshold for supplement for Medicare and Medicaid eligibles under the State Supplementary Assistance program. + +values: + # Iowa Code 249.3(4)(g): "income of at least one hundred twenty percent of + # the federal poverty level". This 120% FPL test has been in statute since + # 2004 Iowa Acts ch. 1085 (§4) when SMME was created. + 2011-01-01: 1.2 + +metadata: + unit: /1 + period: year + label: Iowa SSA SMME minimum income FPL multiplier + reference: + - title: Iowa Administrative Code 441—51.7(6) + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.51.pdf#page=2 + - title: Iowa Administrative Code 441—51.6(6), January 4, 2017 supplement + href: https://www.legis.iowa.gov/docs/aco/supplement/01-04-2017.pdf#page=114 + - title: Iowa Code 249.3(4)(g) + href: https://www.legis.iowa.gov/docs/code/249.3.pdf diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index bc2bc4bbd73..4e1bd162d90 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -633,9 +633,11 @@ programs: name: Hawaii OSS full_name: Hawaii Optional State Supplementation - state: IA - status: in_progress - name: Iowa SSP - full_name: Iowa State Supplemental Payment + status: complete + name: Iowa SSA + full_name: Iowa State Supplementary Assistance + variable: ia_ssa + parameter_prefix: gov.states.ia.hhs.ssa - state: ID status: complete name: Idaho AABD diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/hhs/ssa/ia_ssa.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/hhs/ssa/ia_ssa.yaml new file mode 100644 index 00000000000..3660c3cc100 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/hhs/ssa/ia_ssa.yaml @@ -0,0 +1,2036 @@ +# Iowa SSA consolidated payment tests. +# +# ia_ssa is computed by selecting over ia_ssa_living_arrangement and applying +# the category-specific payment formula. Tests here exercise each arrangement's +# math (Blind, DP, FLH, RCF, IHHRC, SMME) plus multi-category integrations. +# Routing priority (RCF > IHHRC > FLH > DP > BLIND > SMME > NONE) is verified +# separately in ia_ssa_living_arrangement.yaml. + +# ============================================================================ +# BLIND supplement tests (IAC 441—52.1(4): flat $22, frozen since 2011). +# ============================================================================ +- name: Case 1, blind aged Iowan receives flat 22 dollar supplement plus federal SSI. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_blind: true + employment_income: 0 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + is_ssi_eligible: [true] + ssi: [967] + ia_ssa_eligible: [true] + ia_ssa_living_arrangement: [BLIND] + ia_ssa: [22] + +- name: Case 2, non-blind aged Iowan receives no blind supplement. + period: 2025-01 + input: + people: + person1: + age: 70 + is_blind: false + employment_income: 0 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + ia_ssa: [0] + +- name: Case 3, blind person with excess resources receives no supplement. + period: 2025-01 + input: + people: + person1: + age: 40 + is_blind: true + employment_income: 0 + ssi_countable_resources: 5_000 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Resources $5,000 > single limit $2,000 -> ia_ssa_resources_eligible false + ia_ssa_resources_eligible: [false] + ia_ssa_eligible: [false] + ia_ssa: [0] + +- name: Case 4, blind RCF resident routed to RCF (IAC 441-52.1(4) exclusivity). + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + is_blind: true + employment_income: 0 + ia_ssa_living_arrangement_input: RESIDENTIAL_CARE_FACILITY + ia_ssa_rcf_cost_per_diem: 37.60 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Per IAC 441-52.1(4) blind is not paid concurrently with another SSA + # arrangement. RCF outranks BLIND in the priority cascade, so the person + # is paid as RCF: 31 * $37.60 - ($967 SSI - $126 PNA) = $324.60. + ia_ssa_living_arrangement: [RCF] + ia_ssa: [324.60] + +- name: Case 5, blind Iowan with earnings still gets blind supplement. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_blind: true + # Earned income: $500/mo; after blind/disabled working student? + # The blind supplement has no income test at the category level + # beyond SSI categorical eligibility (which ignores income). + employment_income: 6_000 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Still ssi_eligible (passes ABD + resources + immigration). + is_ssi_eligible: [true] + ia_ssa_eligible: [true] + ia_ssa_living_arrangement: [BLIND] + ia_ssa: [22] + +- name: Case 6, blind person at 2026 still receives frozen 22 dollar supplement. + period: 2026-01 + input: + people: + person1: + age: 40 + is_blind: true + employment_income: 0 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Blind supplement frozen at $22 since 2017. + ia_ssa: [22] + +- name: Case 7, blind person with income above FBR plus state standard gets zero supplement. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + is_blind: true + social_security_retirement: 14_400 # $1,200/mo gross + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # $1,200/mo SS gross -> $1,180/mo countable (after $20 disregard). + # FBR $967, blind state standard $22, total $989. Countable $1,180 + # exceeds $989 -> blind income gate in ia_ssa_living_arrangement excludes, + # so category drops to NONE and supplement is $0. + ia_ssa_living_arrangement: [NONE] + ia_ssa: [0] + +- name: Case 8, blind person with income just above FBR gets partial supplement. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + is_blind: true + social_security_retirement: 12_000 # $1,000/mo gross + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # $1,000/mo SS gross -> $980/mo countable (after $20 disregard). + # FBR $967, blind state standard $22, total $989. + # Federally-administered formula: max(0, 989 - max(980, 967)) = 9. + ia_ssa_living_arrangement: [BLIND] + ia_ssa: [9] + +# ============================================================================ +# DP (Dependent Person) supplement tests (IAC 441—52.1(2): 5 configurations). +# ============================================================================ +# IAC 441—52.1(2): DP is federally-administered per POMS SI 01415.050.F. +# Iowa GL 6-B-46 p. 22 publishes a per-configuration assistance standard. +# Per the manual ("Only the income of the eligible person or eligible couple +# is subtracted from the applicable assistance standard"), the supplement is: +# supplement = max(0, assistance_standard - max(countable, applicable_FBR)) +# where applicable_FBR is the couple FBR for configurations that include an +# eligible spouse, and the individual FBR otherwise. +# Also requires dependent's countable income < dependent_income_limit +# (enforced in ia_ssa_living_arrangement). + +- name: Case 1, person with no DP configuration gets zero supplement. + period: 2025-01 + input: + people: + person1: + age: 70 + employment_income: 0 + ia_ssa_dp_configuration: NONE + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + ia_ssa: [0] + +- name: Case 2, person with excess resources gets zero DP supplement. + period: 2025-01 + input: + people: + person1: + age: 70 + employment_income: 0 + ssi_countable_resources: 5_000 + ia_ssa_dp_configuration: AGED_OR_DISABLED_WITH_DEPENDENT + ia_ssa_dp_has_eligible_dependent: true + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Resources $5,000 > single limit $2,000 -> ia_ssa_resources_eligible false + ia_ssa_eligible: [false] + ia_ssa: [0] + +- name: Case 3, blind client with aged spouse and dependent child receives DP at couple-FBR-based standard. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + is_blind: true + employment_income: 0 + ia_ssa_dp_configuration: BLIND_WITH_AGED_OR_DISABLED_SPOUSE_AND_DEPENDENT + ia_ssa_dp_has_eligible_dependent: true + ia_ssa_dp_dependent_countable_income: 0 + person2: + age: 68 + is_blind: false + employment_income: 0 + ia_ssa_dp_configuration: NONE + person3: + age: 10 + employment_income: 0 + marital_units: + first_marital_unit: + members: [person1, person2] + second_marital_unit: + members: [person3] + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: IA + output: + # person1: DP standard $1,975 minus couple FBR $1,450 = $525. + # person2: aged spouse with no DP/BLIND/SMME qualification -> NONE. + # person3: child -> NONE. + ia_ssa_living_arrangement: [DP, NONE, NONE] + ia_ssa: [525, 0, 0] + +- name: Case 4, blind client with aged spouse and dependent child at 2026 rates. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + is_blind: true + employment_income: 0 + ia_ssa_dp_configuration: BLIND_WITH_AGED_OR_DISABLED_SPOUSE_AND_DEPENDENT + ia_ssa_dp_has_eligible_dependent: true + ia_ssa_dp_dependent_countable_income: 0 + person2: + age: 68 + is_blind: false + employment_income: 0 + ia_ssa_dp_configuration: NONE + person3: + age: 10 + employment_income: 0 + marital_units: + first_marital_unit: + members: [person1, person2] + second_marital_unit: + members: [person3] + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: IA + output: + # 2026 DP standard $2,031 minus 2026 couple FBR $1,491 = $540. + ia_ssa_living_arrangement: [DP, NONE, NONE] + ia_ssa: [540, 0, 0] + +- name: Case 5, aged client with aged spouse and dependent child integration. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + employment_income: 0 + ia_ssa_dp_configuration: AGED_OR_DISABLED_WITH_SPOUSE_AND_DEPENDENT + ia_ssa_dp_has_eligible_dependent: true + ia_ssa_dp_dependent_countable_income: 0 + person2: + age: 68 + employment_income: 0 + ia_ssa_dp_configuration: NONE + person3: + age: 10 + employment_income: 0 + marital_units: + first_marital_unit: + members: [person1, person2] + second_marital_unit: + members: [person3] + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: IA + output: + # person1: aged + aged-spouse + dependent. Standard $1,953, couple FBR + # $1,450: max(0, 1953 - max(0, 1450)) = $503. + # person2: aged with no DP configuration; for SMME income must exceed + # 120% FPL for one person ($1,565/mo with the new 1-person/2-person + # FPG sizing); income is $0, so not SMME-eligible -> NONE. + # person3: child -> NONE. + ia_ssa_living_arrangement: [DP, NONE, NONE] + ia_ssa: [503, 0, 0] + +- name: Case 6, dependent income above limit disqualifies DP supplement. + period: 2025-01 + input: + people: + person1: + age: 70 + employment_income: 0 + ia_ssa_dp_configuration: AGED_OR_DISABLED_WITH_DEPENDENT + ia_ssa_dp_has_eligible_dependent: true + ia_ssa_dp_dependent_countable_income: 600 # > $503 limit + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Dependent income exceeds the limit -> DP category gate fails. Person + # is 70 with no other qualifying category -> NONE -> supplement 0. + ia_ssa_living_arrangement: [NONE] + ia_ssa: [0] + +- name: Case 7, 2017 DP aged-or-disabled-with-dependent uses 1114 dollar standard and 379 dollar cap. + period: 2017-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + employment_income: 0 + ia_ssa_dp_configuration: AGED_OR_DISABLED_WITH_DEPENDENT + ia_ssa_dp_has_eligible_dependent: true + ia_ssa_dp_dependent_countable_income: 0 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # 2017 AGED_OR_DISABLED_WITH_DEPENDENT standard $1,114; individual FBR $735. + # Single eligible person -> applicable FBR is individual. + # max(0, 1114 - max(0, 735)) = $379. + ia_ssa_living_arrangement: [DP] + ia_ssa: [379] + +- name: Case 8, DP supplement phases down when single client's countable income exceeds FBR. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security_retirement: 15_600 # $1,300/mo + ia_ssa_dp_configuration: AGED_OR_DISABLED_WITH_DEPENDENT + ia_ssa_dp_has_eligible_dependent: true + ia_ssa_dp_dependent_countable_income: 0 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # $1,300/mo SS gross -> $1,280/mo countable (after SSI $20 disregard, + # which DP retains because DP is federally administered). Standard + # $1,470, individual FBR $967 (single eligible client): + # max(0, 1470 - max(1280, 967)) = $190. + ia_ssa: [190] + +- name: Case 9, blind client with dependent uses single-client BLIND_WITH_DEPENDENT standard. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 50 + is_blind: true + employment_income: 0 + ia_ssa_dp_configuration: BLIND_WITH_DEPENDENT + ia_ssa_dp_has_eligible_dependent: true + ia_ssa_dp_dependent_countable_income: 0 + person2: + age: 10 + employment_income: 0 + marital_units: + first_marital_unit: + members: [person1] + second_marital_unit: + members: [person2] + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # BLIND_WITH_DEPENDENT 2025 standard $1,492 - individual FBR $967 = $525. + ia_ssa_living_arrangement: [DP, NONE] + ia_ssa: [525, 0] + +- name: Case 10, blind client with blind spouse and dependent uses BLIND_WITH_BLIND_SPOUSE_AND_DEPENDENT standard. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + is_blind: true + employment_income: 0 + ia_ssa_dp_configuration: BLIND_WITH_BLIND_SPOUSE_AND_DEPENDENT + ia_ssa_dp_has_eligible_dependent: true + ia_ssa_dp_dependent_countable_income: 0 + person2: + age: 68 + is_blind: true + employment_income: 0 + ia_ssa_dp_configuration: NONE + person3: + age: 10 + employment_income: 0 + marital_units: + first_marital_unit: + members: [person1, person2] + second_marital_unit: + members: [person3] + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: IA + output: + # person1: BLIND_WITH_BLIND_SPOUSE_AND_DEPENDENT 2025 standard $1,997 - + # couple FBR $1,450 = $547 DP supplement. Only person1 sets the + # couple-FBR config (repo convention), marital-unit guard divides by 1. + # person2 has no DP/RCF/IHHRC/FLH but is_blind=true with $0 income, so + # the SELECT cascade routes her to BLIND ($22 federally-administered). + # person3: child, no SSP category. + ia_ssa_living_arrangement: [DP, BLIND, NONE] + ia_ssa: [547, 22, 0] + +- name: Case 11, both spouses set the same couple-FBR DP config — marital-unit guard prevents double-attribution. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + employment_income: 0 + ia_ssa_dp_configuration: AGED_OR_DISABLED_WITH_SPOUSE_AND_DEPENDENT + ia_ssa_dp_has_eligible_dependent: true + ia_ssa_dp_dependent_countable_income: 0 + person2: + age: 68 + employment_income: 0 + ia_ssa_dp_configuration: AGED_OR_DISABLED_WITH_SPOUSE_AND_DEPENDENT + ia_ssa_dp_has_eligible_dependent: true + ia_ssa_dp_dependent_countable_income: 0 + person3: + age: 10 + employment_income: 0 + marital_units: + first_marital_unit: + members: [person1, person2] + second_marital_unit: + members: [person3] + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: IA + output: + # AGED_OR_DISABLED_WITH_SPOUSE_AND_DEPENDENT 2025 standard $1,953 - + # couple FBR $1,450 = $503. Both spouses claim the couple config; the + # marital-unit guard splits the supplement so the SPM-unit total stays + # at $503 (each spouse gets $251.50), not $1,006. + ia_ssa: [251.5, 251.5, 0] + +- name: Case 12, joint-claim couple DP phases to zero when combined income exceeds couple FBR. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security_retirement: 14_400 # $1,200/mo each + ia_ssa_dp_configuration: AGED_OR_DISABLED_WITH_SPOUSE_AND_DEPENDENT + ia_ssa_dp_has_eligible_dependent: true + ia_ssa_dp_dependent_countable_income: 0 + is_ssi_aged_blind_disabled: true + ssi_claim_is_joint: true + person2: + age: 68 + social_security_retirement: 14_400 + ia_ssa_dp_configuration: NONE + is_ssi_aged_blind_disabled: true + ssi_claim_is_joint: true + person3: + age: 10 + employment_income: 0 + marital_units: + first_marital_unit: + members: [person1, person2] + second_marital_unit: + members: [person3] + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: IA + output: + # Combined SS $28,800/yr - $240 disregard = $28,560/yr countable couple. + # Combined monthly = $2,380 > couple FBR $1,450, so the supplement + # phases out: max(0, $1,953 standard - max($2,380, $1,450)) = $0. + # Without the marital-unit aggregation, the formula would compare the + # per-spouse half ($1,190) against the couple-level threshold and + # incorrectly pay the full $503. + ia_ssa: [0, 0, 0] + +- name: Case 13, 2011 aged-or-disabled-with-dependent — state portion matches SSA Table 1 ($344). + period: 2011-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + employment_income: 0 + ia_ssa_dp_configuration: AGED_OR_DISABLED_WITH_DEPENDENT + ia_ssa_dp_has_eligible_dependent: true + ia_ssa_dp_dependent_countable_income: 0 + person2: + # Dependent relative present in the household (per IAC 441—51.5(1)). + age: 10 + employment_income: 0 + marital_units: + first_marital_unit: + members: [person1] + second_marital_unit: + members: [person2] + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Iowa 2011 combined standard $1,018 - 2011 individual FBR $674 = $344 + # state portion (matches SSA 2011 Iowa report Table 1, Code C aged). + ia_ssa_living_arrangement: [DP, NONE] + ia_ssa: [344, 0] + +- name: Case 14, 2011 blind-with-dependent — state portion matches SSA Table 1 ($366). + period: 2011-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 50 + is_blind: true + employment_income: 0 + ia_ssa_dp_configuration: BLIND_WITH_DEPENDENT + ia_ssa_dp_has_eligible_dependent: true + ia_ssa_dp_dependent_countable_income: 0 + person2: + # Dependent relative present in the household (per IAC 441—51.5(1)). + age: 10 + employment_income: 0 + marital_units: + first_marital_unit: + members: [person1] + second_marital_unit: + members: [person2] + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Iowa 2011 combined standard $1,040 - 2011 individual FBR $674 = $366 + # state portion (matches SSA 2011 Iowa report Table 1, Code C blind). + ia_ssa_living_arrangement: [DP, NONE] + ia_ssa: [366, 0] + +# ============================================================================ +# FLH (Family-Life Home) supplement tests (IAC 441—52.1(1)). +# ============================================================================ +# IAC 441—52.1(1): FLH is federally-administered per POMS SI 01415.050.F. +# Federally-administered SSP formula: +# base = min(max(0, (FBR + state_supplement) - max(countable, FBR)), +# max_supplement) +# extra = max(0, state_supplement - max_supplement) if countable == 0 +# supplement = base + extra +# $142 cap on the federally-administered portion; the Department pays the +# extra directly when SSA's $20 general-income disregard goes unused on an +# SSI-only recipient. + +- name: Case 1, aged FLH resident with zero income receives capped supplement plus Department top-up. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + employment_income: 0 + ia_ssa_living_arrangement_input: FAMILY_LIFE_HOME + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Federal SSI fills to FBR $967; state supplement $162, capped at $142. + # With no other income the SSI $20 general-income disregard goes unused, + # so Iowa HHS pays the remaining $20 as a Department top-up, totaling + # $162 — bringing federal + state payments to the full $1,129 standard. + is_ssi_eligible: [true] + ssi: [967] + ia_ssa_eligible: [true] + ia_ssa_living_arrangement: [FLH] + ia_ssa: [162] + +- name: Case 2, person not in FLH receives zero FLH supplement. + period: 2025-01 + input: + people: + person1: + age: 70 + employment_income: 0 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + ia_ssa: [0] + +- name: Case 3, FLH resident with excess resources receives zero. + period: 2025-01 + input: + people: + person1: + age: 70 + employment_income: 0 + ssi_countable_resources: 5_000 + ia_ssa_living_arrangement_input: FAMILY_LIFE_HOME + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Resources $5,000 > single limit $2,000 -> ia_ssa_resources_eligible false + ia_ssa_eligible: [false] + ia_ssa: [0] + +- name: Case 4, FLH resident 2026 zero income receives 162 dollars (capped 142 plus 20 dollar top-up). + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + employment_income: 0 + ia_ssa_living_arrangement_input: FAMILY_LIFE_HOME + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Cap frozen at $142; 2026 state supplement $162, so Department top-up + # of $20 applies to SSI-only recipient. Total Iowa payment $162. + ia_ssa: [162] + +- name: Case 5, FLH supplement phases down when countable income exceeds FBR. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security_retirement: 12_840 # $1,070/mo gross + ia_ssa_living_arrangement_input: FAMILY_LIFE_HOME + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # $1,070/mo SS gross -> $1,050/mo countable (after $20 disregard). + # Assistance standard $1,129; FBR $967. + # max(0, 1129 - max(1050, 967)) = $79 (under the $142 cap). + ia_ssa: [79] + +- name: Case 6, FLH supplement is zero when countable income equals or exceeds standard. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security_retirement: 14_400 # $1,200/mo gross + ia_ssa_living_arrangement_input: FAMILY_LIFE_HOME + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Countable $1,180/mo; standard $1,129; raw = max(0, 1129 - 1180) = 0. + ia_ssa: [0] + +- name: Case 7, blind FLH resident gets FLH benefit only without 22 dollar add-on. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_blind: true + employment_income: 0 + ia_ssa_living_arrangement_input: FAMILY_LIFE_HOME + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # IAC 441-52.1(4): the $22 blind standard is for a blind recipient "not + # receiving another type of state supplementary assistance" — mutually + # exclusive with FLH, so the add-on does NOT stack. SSI-only recipient + # still gets the $20 Department top-up: max_supplement $142 + $20 gap = $162. + ia_ssa_living_arrangement: [FLH] + ia_ssa: [162] + +# ============================================================================ +# IHHRC (In-Home Health-Related Care) supplement tests (IAC 441—177). +# ============================================================================ +# IAC 441—177.10(2)(a): payment = max(0, min(cost, per-person cap) - +# client participation), where client participation is marital-unit +# countable income minus the basic SSI standard disregard (the applicable +# FBR for a single or joint claim), split evenly across the marital unit. +# IAC 441—177.10(3): IHHRC max benefit payable is $480.55 per person, inclusive +# of all services for all providers. The $961.10 in 441—177.4(1)(f) is the +# combined couple income cap, NOT a per-person payment cap. +# IAC 441—177.4(1)(c): recipient must live in own home (not in RCF or FLH). +# IAC 441—177.4(1)(f): income cap on countable income after the basic SSI +# standard disregard — individual <= $480.55, or combined couple <= $961.10 +# when both spouses need care. + +- name: Case 1, individual IHHRC cost below max pays actual cost. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + employment_income: 0 + ia_ssa_living_arrangement_input: IN_HOME_HEALTH_RELATED_CARE + ia_ssa_ihhrc_cost_of_care: 450 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Cost $450 below max $480.55 -> pays actual $450 + ia_ssa: [450] + +- name: Case 2, individual IHHRC cost above max is capped at 480.55 dollars. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + employment_income: 0 + ia_ssa_living_arrangement_input: IN_HOME_HEALTH_RELATED_CARE + ia_ssa_ihhrc_cost_of_care: 600 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Cost $600 > max $480.55 -> capped + ia_ssa: [480.55] + +- name: Case 3, person not needing IHHRC receives zero supplement. + period: 2025-01 + input: + people: + person1: + age: 70 + employment_income: 0 + ia_ssa_ihhrc_cost_of_care: 400 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + ia_ssa: [0] + +- name: Case 4, person needing IHHRC with excess resources receives zero. + period: 2025-01 + input: + people: + person1: + age: 70 + employment_income: 0 + ssi_countable_resources: 5_000 + ia_ssa_living_arrangement_input: IN_HOME_HEALTH_RELATED_CARE + ia_ssa_ihhrc_cost_of_care: 400 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Resources $5,000 > single limit $2,000 -> ia_ssa_resources_eligible false + ia_ssa_eligible: [false] + ia_ssa: [0] + +- name: Case 5, couple both needing IHHRC use couple cap. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + employment_income: 0 + ia_ssa_living_arrangement_input: IN_HOME_HEALTH_RELATED_CARE + ia_ssa_ihhrc_cost_of_care: 900 + person2: + age: 68 + employment_income: 0 + ia_ssa_living_arrangement_input: IN_HOME_HEALTH_RELATED_CARE + ia_ssa_ihhrc_cost_of_care: 900 + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Both need care -> combined income cap $961.10 (combined countable = 0). + # Payment max is $480.55 per person (441—177.10(3)). + # Each cost $900 > per-person max $480.55 -> capped at $480.55 each. + ia_ssa_ihhrc_both_need_care: [true, true] + ia_ssa: [480.55, 480.55] + +- name: Case 6, couple both needing IHHRC with high cost capped at 480.55 dollars per person. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + employment_income: 0 + ia_ssa_living_arrangement_input: IN_HOME_HEALTH_RELATED_CARE + ia_ssa_ihhrc_cost_of_care: 1_500 + person2: + age: 68 + employment_income: 0 + ia_ssa_living_arrangement_input: IN_HOME_HEALTH_RELATED_CARE + ia_ssa_ihhrc_cost_of_care: 1_500 + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Both need care -> combined income cap $961.10 (combined countable = 0). + # Payment max is $480.55 per person (441—177.10(3)). + # Each cost $1,500 > per-person max $480.55 -> capped at $480.55 each. + ia_ssa: [480.55, 480.55] + +- name: Case 7, couple with only one spouse needing IHHRC uses single cap. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + employment_income: 0 + ia_ssa_living_arrangement_input: IN_HOME_HEALTH_RELATED_CARE + ia_ssa_ihhrc_cost_of_care: 800 + person2: + age: 68 + employment_income: 0 + ia_ssa_ihhrc_cost_of_care: 0 + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Only person1 needs care -> both_need_care false -> single cap $480.55 + ia_ssa_ihhrc_both_need_care: [false, false] + ia_ssa: [480.55, 0] + +- name: Case 8, person with countable income above single cap is ineligible. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security_retirement: 20_000 # $1,667/mo gross + ia_ssa_living_arrangement_input: IN_HOME_HEALTH_RELATED_CARE + ia_ssa_ihhrc_cost_of_care: 400 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Countable for IHHRC (no SSI $20 disregard) $1,667/mo minus individual + # FBR disregard $967 = $700, which exceeds the single cap $480.55 -> not + # in IHHRC category -> no supplement. + ia_ssa: [0] + +- name: Case 9, single person with countable income below FBR gets full supplement. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security_retirement: 9_600 # $800/mo gross + ia_ssa_living_arrangement_input: IN_HOME_HEALTH_RELATED_CARE + ia_ssa_ihhrc_cost_of_care: 400 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # $800/mo SS unearned. IHHRC countable (no $20 disregard) $800/mo. + # Individual FBR disregard $967 makes income after disregard 0 -> passes + # single cap. Client participation is 0 -> supplement equals cost $400. + ia_ssa: [400] + +- name: Case 10, couple both needing IHHRC with combined countable below couple FBR. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security_retirement: 7_200 # $600/mo gross + ia_ssa_living_arrangement_input: IN_HOME_HEALTH_RELATED_CARE + ia_ssa_ihhrc_cost_of_care: 400 + person2: + age: 68 + social_security_retirement: 7_200 # $600/mo gross + ia_ssa_living_arrangement_input: IN_HOME_HEALTH_RELATED_CARE + ia_ssa_ihhrc_cost_of_care: 400 + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Each spouse's IHHRC countable (no $20 disregard) is $600/mo, combined + # $1,200. Couple FBR disregard $1,450 leaves 0 after disregard -> passes + # couple cap $961.10. Client participation is 0 -> each person's + # supplement equals cost $400. + ia_ssa_ihhrc_both_need_care: [true, true] + ia_ssa: [400, 400] + +- name: Case 11, couple both needing IHHRC with combined countable above couple cap. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security_retirement: 15_840 # $1,320/mo gross + ia_ssa_living_arrangement_input: IN_HOME_HEALTH_RELATED_CARE + ia_ssa_ihhrc_cost_of_care: 400 + person2: + age: 68 + social_security_retirement: 15_840 # $1,320/mo gross + ia_ssa_living_arrangement_input: IN_HOME_HEALTH_RELATED_CARE + ia_ssa_ihhrc_cost_of_care: 400 + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Each spouse's IHHRC countable (no $20 disregard) is $1,320/mo; combined + # $2,640. After couple FBR disregard $1,450 -> $1,190 countable, which + # exceeds the couple cap $961.10 -> both ineligible. + ia_ssa_ihhrc_both_need_care: [true, true] + ia_ssa: [0, 0] + +- name: Case 12, couple with only one recipient charges all participation to that recipient. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + # $800/mo unearned per spouse; couple-combined ~$1,580 countable + # after the $20 disregard, exceeding the couple FBR $1,450 by $130. + social_security_retirement: 9_600 + ia_ssa_living_arrangement_input: IN_HOME_HEALTH_RELATED_CARE + ia_ssa_ihhrc_cost_of_care: 400 + person2: + age: 68 + social_security_retirement: 9_600 + ia_ssa_ihhrc_cost_of_care: 0 + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # person1 is the sole IHHRC recipient. Each spouse has $800/mo IHHRC + # countable (no $20 disregard); combined $1,600 minus couple FBR $1,450 + # = $150. Per IAC 441-177.10(2)(a) all of that participation is charged + # to the one recipient. Supplement = min($400, $480.55) − $150 = $250. + # person2 is not in the IHHRC category and receives $0. + ia_ssa_ihhrc_both_need_care: [false, false] + ia_ssa: [250, 0] + +# ============================================================================ +# RCF (Residential Care Facility) supplement tests (IAC 441—52.1(3)). +# ============================================================================ +# IAC 441—52.1(3): payment in RCF = (31 * max_per_diem) - client_participation +# where client_participation = total_monthly_income - personal_needs_allowance. +# Total income = SSI-countable income + federal SSI payment. +# RCF income eligibility: client_participation < 31 * max_per_diem. + +- name: Case 1, aged RCF resident with no income (SSI fills to FBR). + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + employment_income: 0 + ia_ssa_living_arrangement_input: RESIDENTIAL_CARE_FACILITY + ia_ssa_rcf_cost_per_diem: 37.60 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Federal SSI fills to 2025 FBR $967; RCF supplement = + # 31 * $37.60 - ($967 - $126) = $1,165.60 - $841 = $324.60 + is_ssi_eligible: [true] + ssi: [967] + ia_ssa_eligible: [true] + ia_ssa_living_arrangement: [RCF] + ia_ssa: [324.60] + +- name: Case 2, RCF per diem above max is capped at 37.60 dollars per day. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + employment_income: 0 + ia_ssa_living_arrangement_input: RESIDENTIAL_CARE_FACILITY + ia_ssa_rcf_cost_per_diem: 50 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Capped cost = 31 * $37.60 = $1,165.60; CP $841; supplement $324.60 + ia_ssa: [324.60] + +- name: Case 3, person not in RCF receives zero supplement. + period: 2025-01 + input: + people: + person1: + age: 70 + employment_income: 0 + ia_ssa_rcf_cost_per_diem: 30 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + ia_ssa: [0] + +- name: Case 4, aged RCF resident in 2026 uses higher 38.47 dollar per diem. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + employment_income: 0 + ia_ssa_living_arrangement_input: RESIDENTIAL_CARE_FACILITY + ia_ssa_rcf_cost_per_diem: 38.47 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Federal SSI fills to 2026 FBR $994; RCF supplement = + # 31 * $38.47 - ($994 - $130) = $1,192.57 - $864 = $328.57 + is_ssi_eligible: [true] + ssi: [994] + ia_ssa_living_arrangement: [RCF] + ia_ssa: [328.57] + +- name: Case 5, RCF resident with zero reported per diem receives zero. + period: 2025-01 + input: + people: + person1: + age: 70 + employment_income: 0 + ia_ssa_living_arrangement_input: RESIDENTIAL_CARE_FACILITY + ia_ssa_rcf_cost_per_diem: 0 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # cost_of_care = 0; max(0, 0 - client_participation) = 0 + ia_ssa: [0] + +- name: Case 6, RCF resident with 12000 dollar Social Security has higher client participation. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security_retirement: 12_000 # $1,000/mo + ia_ssa_living_arrangement_input: RESIDENTIAL_CARE_FACILITY + ia_ssa_rcf_cost_per_diem: 37.60 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # $1,000/mo SS unearned. RCF does not allow the SSI $20 disregard + # (GL 6-B-46 p. 54), so countable for RCF is $1,000 (not $980). No SSI + # (SSI's calc treats countable as $980 > FBR $967 -> $0). Total monthly + # income $1,000; client participation $1,000 - $126 = $874; supplement + # = $1,165.60 - $874 = $291.60. + ia_ssa: [291.60] + +- name: Case 7, RCF resident with income above 31 times max per diem is ineligible. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security_retirement: 30_000 + ia_ssa_living_arrangement_input: RESIDENTIAL_CARE_FACILITY + ia_ssa_rcf_cost_per_diem: 37.60 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # SS $2,500/mo exceeds SSI FBR; client participation > + # 31 * $37.60 income limit -> not in RCF category -> no supplement + ia_ssa: [0] + +- name: Case 8, 2018 RCF resident uses the 99 dollar PNA effective March 2018. + period: 2018-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + employment_income: 0 + ia_ssa_living_arrangement_input: RESIDENTIAL_CARE_FACILITY + ia_ssa_rcf_cost_per_diem: 30.60 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Federal SSI fills to 2018 FBR $750. 2018 RCF: max_per_diem $30.60, + # PNA $99 (per March 28, 2018 IAC rule update). CP $750 - $99 = $651. + # Cost of care 31 * $30.60 = $948.60. Supplement $948.60 - $651 = $297.60. + ssi: [750] + ia_ssa_living_arrangement: [RCF] + ia_ssa: [297.60] + +- name: Case 9, RCF resident with excess resources receives zero supplement. + period: 2025-01 + input: + people: + person1: + age: 70 + employment_income: 0 + ssi_countable_resources: 5_000 + ia_ssa_living_arrangement_input: RESIDENTIAL_CARE_FACILITY + ia_ssa_rcf_cost_per_diem: 37.60 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Resources $5,000 > $2,000 limit -> ia_ssa_eligible false + ia_ssa_eligible: [false] + ia_ssa: [0] + +# ============================================================================ +# SMME (Supplement for Medicare and Medicaid Eligibles) tests (IAC 441—52.1(7)). +# ============================================================================ +# SMME is a $1/month technical SSP pathway for people who meet all SSI +# categorical eligibility (aged/blind/disabled, resources, immigration) but +# whose income exceeds the federal SSI benefit rate. Per IAC 441—51.7(6), +# income must exceed 120% of the federal poverty level. 2025 FPL (1 person, +# contiguous US) = $15,650; 120% = $18,780/year or $1,565/month. + +- name: Case 1, aged Iowan with income above 120% FPL, full Medicaid and Part B. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security_retirement: 24_000 # $2,000/month + ia_ssa_has_full_medicaid: true + ia_ssa_has_medicare_part_b: true + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Income $2,000/mo; countable $1,980 after $20 exclusion; + # 120% FPL for 1 person (2025, contiguous) = $1,565/mo; exceeds threshold. + # No SSI (countable > FBR $967). SMME pays $1. + is_ssi_eligible: [true] + ssi: [0] + ia_ssa_eligible: [true] + ia_ssa_living_arrangement: [SMME] + ia_ssa: [1] + +- name: Case 2, aged Iowan with low income (below 120% FPL) is not SMME-eligible. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security_retirement: 12_000 # $1,000/month + ia_ssa_has_full_medicaid: true + ia_ssa_has_medicare_part_b: true + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Income $1,000/mo; countable $980 after $20 exclusion; below 120% FPL + # $1,565/mo. SMME-ineligible; person gets regular SSI instead + # (FBR $967 - countable $980 < 0, so no federal SSI either). + ia_ssa_living_arrangement: [NONE] + ia_ssa: [0] + +- name: Case 3, aged Iowan without full Medicaid gets no SMME. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security_retirement: 24_000 + ia_ssa_has_full_medicaid: false + ia_ssa_has_medicare_part_b: true + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + ia_ssa_living_arrangement: [NONE] + ia_ssa: [0] + +- name: Case 4, aged Iowan without Medicare Part B gets no SMME. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security_retirement: 24_000 + ia_ssa_has_full_medicaid: true + ia_ssa_has_medicare_part_b: false + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + ia_ssa_living_arrangement: [NONE] + ia_ssa: [0] + +- name: Case 5, person with excess resources receives zero SMME. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security_retirement: 24_000 + ssi_countable_resources: 5_000 + ia_ssa_has_full_medicaid: true + ia_ssa_has_medicare_part_b: true + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Resources $5,000 > single limit $2,000 -> ia_ssa_resources_eligible false + ia_ssa_eligible: [false] + ia_ssa: [0] + +- name: Case 6, income exactly at 120% FPL boundary is not SMME-eligible. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + # $18,780/year gross = $1,565/month; countable = $1,545 after $20 + # exclusion, which is below the $1,565 threshold. Boundary check. + social_security_retirement: 18_780 + ia_ssa_has_full_medicaid: true + ia_ssa_has_medicare_part_b: true + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Statute requires income to EXCEED 120% FPL (>, not >=). + ia_ssa_living_arrangement: [NONE] + ia_ssa: [0] + +- name: Case 7, aged Iowan at 2026 rates with income above 120% FPL. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + # 2026 FPL (1 person, contiguous) = $15,960; 120% = $19,152/year. + social_security_retirement: 30_000 # $2,500/month, well above threshold + ia_ssa_has_full_medicaid: true + ia_ssa_has_medicare_part_b: true + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + ia_ssa_living_arrangement: [SMME] + ia_ssa: [1] + +- name: Case 8, aged married couple with joint SSI claim — SMME uses 2-person 120% FPL threshold. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security_retirement: 14_400 # $1,200/mo each + ia_ssa_has_full_medicaid: true + ia_ssa_has_medicare_part_b: true + is_ssi_aged_blind_disabled: true + ssi_claim_is_joint: true + person2: + age: 68 + social_security_retirement: 14_400 + ia_ssa_has_full_medicaid: true + ia_ssa_has_medicare_part_b: true + is_ssi_aged_blind_disabled: true + ssi_claim_is_joint: true + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # 2025 2-person FPL (contiguous) = $20,440/yr; 120% = $24,528/yr = + # $2,044/mo. Combined SS $28,800/yr - $20/mo couple disregard = ~$2,380/mo + # countable per spouse (joint claim). Above the 2-person 120% FPL gate. + # No federal SSI (countable > couple FBR $1,450). Each spouse gets $1 + # SMME so the SPM-unit total ia_ssa = $2. + ia_ssa_living_arrangement: [SMME, SMME] + ia_ssa: [1, 1] + +# ============================================================================ +# Pre-2017 historical and earned-income SSI-disregard regression tests. +# ============================================================================ + +- name: Case 8 historical, 2011 RCF resident with no other income. + period: 2011-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + employment_income: 0 + ia_ssa_living_arrangement_input: RESIDENTIAL_CARE_FACILITY + ia_ssa_rcf_cost_per_diem: 20.00 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # 2011 individual FBR $674, RCF max_per_diem $28.14, PNA $93. SSI fills + # to FBR -> total_rcf_income $674; client participation $674 - $93 = + # $581. Cost-of-care 31 * min($20, $28.14) = $620. Supplement $620 - + # $581 = $39. Verifies 2011 lookups succeed (dependent_income_limit and + # SMME parameters now have 2011 historical values to prevent + # ParameterNotFoundError). + ssi: [674] + ia_ssa_living_arrangement: [RCF] + ia_ssa: [39] + +- name: Case 13 RCF earned-income, no-disregard add-back applies the leftover-20 dollars to earnings at half rate. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + employment_income: 6_000 # $500/mo earned, no unearned + ia_ssa_living_arrangement_input: RESIDENTIAL_CARE_FACILITY + ia_ssa_rcf_cost_per_diem: 37.60 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # $500/mo earned, $0 unearned. SSI exclusions: $20 general falls into + # the earned flat ($65 + $20 = $85), then 50% of remainder. SSI + # countable_earned = ($500 - $85) * 0.5 = $207.50. SSI fills to + # $967 - $207.50 = $759.50. For RCF (no $20 disregard): add back + # $20 * 0.5 = $10 (the leftover applied to earned, halved by the 50% + # earned-share rule). Iowa countable = $217.50 (matches GL 6-B-46 p. + # 55: "an SSI recipient ... with earned income of more than $85 per + # month will commonly have countable income ... equal to the SSI + # payment standard plus $10 ($977)"). Total RCF income $977; client + # participation $977 - $126 = $851. Cost-of-care 31 * $37.60 = + # $1,165.60. Supplement = $1,165.60 - $851 = $314.60. + ia_ssa: [314.60] + +- name: Case 15 BLIND one-blind joint couple uses couple-FBR basis (regression for one-blind joint bug). + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + is_blind: true + is_ssi_aged_blind_disabled: true + social_security_retirement: 8_940 # $745/mo each, $1,490/mo combined + ssi_claim_is_joint: true + person2: + age: 70 + is_blind: false + is_ssi_aged_blind_disabled: true + social_security_retirement: 8_940 + ssi_claim_is_joint: true + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # 2025: individual FBR $967, couple FBR $1,450. Combined gross unearned + # $1,490/mo. After SSI $20 GIE, combined countable = $1,470/mo + # ($735/mo per spouse via joint-claim attribution). + # Pre-fix bug: per-spouse comparison $735 < $967 + $22 → person1 receives + # full $22 even though combined > couple FBR. + # Post-fix: marital comparison $1,470 vs $1,450 + 1×$22 = $1,472. + # supplement = $1,472 - max($1,470, $1,450) = $2 → person1 ia_ssa = $2. + # person2 (not blind, no other category) routes to NONE. + ia_ssa_living_arrangement: [BLIND, NONE] + ia_ssa: [2, 0] + +- name: Case 16 Iowa $3,000 marital resource limit reachable for non-joint married claimant (regression for federal $2,000 over-gating). + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + is_blind: true + is_ssi_aged_blind_disabled: true + ssi_countable_resources: 2_500 + ssi_claim_is_joint: false + person2: + age: 50 + is_ssi_aged_blind_disabled: false + ssi_countable_resources: 0 + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # IAC 441—51.5(2): Iowa allows $3,000 marital-unit resources when the + # claimant lives with a (potentially ineligible) spouse. Federal SSI + # applies $2,000 individual when not in a joint claim; person1's $2,500 + # alone fails federal resource test (ssi = 0) but Iowa's $3,000 limit + # is satisfied ($2,500 ≤ $3,000), so ia_ssa_eligible holds and the + # blind branch pays the $22 state supplement. + # Pre-fix bug: ia_ssa_eligible AND'd with is_ssi_eligible (federal + # individual $2,000 test) → False → no Iowa SSP. + # Post-fix: ABD + immigration + Iowa resource test → True. + ia_ssa_eligible: [true, false] + ia_ssa_living_arrangement: [BLIND, NONE] + ia_ssa: [22, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/hhs/ssa/ia_ssa_dp_configuration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/hhs/ssa/ia_ssa_dp_configuration.yaml new file mode 100644 index 00000000000..7e33831e5a1 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/hhs/ssa/ia_ssa_dp_configuration.yaml @@ -0,0 +1,77 @@ +- name: Case 1, aged or disabled client with dependent. + period: 2025-01 + input: + people: + person1: + ia_ssa_dp_configuration: AGED_OR_DISABLED_WITH_DEPENDENT + households: + household: + members: [person1] + state_code: IA + output: + ia_ssa_dp_configuration: [AGED_OR_DISABLED_WITH_DEPENDENT] + +- name: Case 2, aged or disabled client with spouse and dependent. + period: 2025-01 + input: + people: + person1: + ia_ssa_dp_configuration: AGED_OR_DISABLED_WITH_SPOUSE_AND_DEPENDENT + households: + household: + members: [person1] + state_code: IA + output: + ia_ssa_dp_configuration: [AGED_OR_DISABLED_WITH_SPOUSE_AND_DEPENDENT] + +- name: Case 3, blind client with dependent. + period: 2025-01 + input: + people: + person1: + ia_ssa_dp_configuration: BLIND_WITH_DEPENDENT + households: + household: + members: [person1] + state_code: IA + output: + ia_ssa_dp_configuration: [BLIND_WITH_DEPENDENT] + +- name: Case 4, blind client with aged or disabled spouse and dependent. + period: 2025-01 + input: + people: + person1: + ia_ssa_dp_configuration: BLIND_WITH_AGED_OR_DISABLED_SPOUSE_AND_DEPENDENT + households: + household: + members: [person1] + state_code: IA + output: + ia_ssa_dp_configuration: [BLIND_WITH_AGED_OR_DISABLED_SPOUSE_AND_DEPENDENT] + +- name: Case 5, blind client with blind spouse and dependent. + period: 2025-01 + input: + people: + person1: + ia_ssa_dp_configuration: BLIND_WITH_BLIND_SPOUSE_AND_DEPENDENT + households: + household: + members: [person1] + state_code: IA + output: + ia_ssa_dp_configuration: [BLIND_WITH_BLIND_SPOUSE_AND_DEPENDENT] + +- name: Case 6, person with no dependent relative. + period: 2025-01 + input: + people: + person1: + ia_ssa_dp_configuration: NONE + households: + household: + members: [person1] + state_code: IA + output: + ia_ssa_dp_configuration: [NONE] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/hhs/ssa/ia_ssa_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/hhs/ssa/ia_ssa_eligible.yaml new file mode 100644 index 00000000000..8a751e6e91d --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/hhs/ssa/ia_ssa_eligible.yaml @@ -0,0 +1,123 @@ +- name: Case 1, aged Iowan meets SSI categorical eligibility. + period: 2025-01 + input: + people: + person1: + age: 70 + employment_income: 0 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + is_ssi_eligible: [true] + ia_ssa_eligible: [true] + +- name: Case 2, young non-disabled person is not SSA-eligible (not aged/blind/disabled). + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 0 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + is_ssi_eligible: [false] + ia_ssa_eligible: [false] + +- name: Case 3, aged Iowan with excess resources is ineligible. + period: 2025-01 + input: + people: + person1: + age: 70 + employment_income: 0 + ssi_countable_resources: 5_000 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Resources $5,000 > $2,000 individual limit -> fails resources test + ia_ssa_resources_eligible: [false] + ia_ssa_eligible: [false] + +- name: Case 4, non-Iowa resident is ineligible (defined_for filter). + period: 2025-01 + input: + people: + person1: + age: 70 + employment_income: 0 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: NY + output: + ia_ssa_eligible: [false] + +- name: Case 5, aged Iowan with high income still SSA-eligible (no state income test for eligibility itself). + period: 2025-01 + input: + people: + person1: + age: 70 + social_security_retirement: 24_000 # $2,000/mo -> no federal SSI + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # ia_ssa_eligible = is_ssi_eligible & resources_eligible. + # is_ssi_eligible does NOT include an income test -> true even with high income. + # Per IAC 441—51.2, applicants need only "apply for or receive" SSI. + is_ssi_eligible: [true] + ia_ssa_eligible: [true] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/hhs/ssa/ia_ssa_living_arrangement.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/hhs/ssa/ia_ssa_living_arrangement.yaml new file mode 100644 index 00000000000..2b03369d7dd --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/hhs/ssa/ia_ssa_living_arrangement.yaml @@ -0,0 +1,326 @@ +# Verifies ia_ssa_living_arrangement priority ordering: +# RCF > IHHRC > FLH > DP > BLIND > SMME > NONE +# +# Note: SMME requires income > 120% FPL (IAC 441—51.7(6)). 2025 FPL 1-person +# (contiguous US) = $15,650; 120% = $18,780/year or $1,565/month. + +- name: Case 1, RCF resident who is also blind gets RCF category not BLIND. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + is_blind: true + employment_income: 0 + ia_ssa_living_arrangement_input: RESIDENTIAL_CARE_FACILITY + ia_ssa_rcf_cost_per_diem: 37.60 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # RCF outranks BLIND + ia_ssa_living_arrangement: [RCF] + +- name: Case 2, FLH resident who is also blind gets FLH category not BLIND. + period: 2025-01 + input: + people: + person1: + age: 40 + is_blind: true + employment_income: 0 + ia_ssa_living_arrangement_input: FAMILY_LIFE_HOME + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # FLH outranks BLIND + ia_ssa_living_arrangement: [FLH] + +- name: Case 3, aged person above 120% FPL with Medicaid and Part B gets SMME. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security_retirement: 24_000 # $2,000/mo, above 120% FPL + ia_ssa_has_full_medicaid: true + ia_ssa_has_medicare_part_b: true + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # No other category applies; income above 120% FPL -> SMME + ia_ssa_living_arrangement: [SMME] + +- name: Case 4, person in no qualifying category gets NONE. + period: 2025-01 + input: + people: + person1: + age: 70 + employment_income: 0 + # Override federal medicare/medicaid defaults to exclude from SMME + ia_ssa_has_medicare_part_b: false + ia_ssa_has_full_medicaid: false + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + ia_ssa_living_arrangement: [NONE] + +- name: Case 6, person needing IHHRC who is also blind gets IHHRC not BLIND. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_blind: true + employment_income: 0 + ia_ssa_living_arrangement_input: IN_HOME_HEALTH_RELATED_CARE + ia_ssa_ihhrc_cost_of_care: 400 + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # IHHRC outranks BLIND + ia_ssa_living_arrangement: [IHHRC] + +- name: Case 7, person needing IHHRC with DP configuration gets IHHRC not DP. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + employment_income: 0 + ia_ssa_living_arrangement_input: IN_HOME_HEALTH_RELATED_CARE + ia_ssa_ihhrc_cost_of_care: 400 + ia_ssa_dp_configuration: AGED_OR_DISABLED_WITH_DEPENDENT + ia_ssa_dp_has_eligible_dependent: true + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # IHHRC outranks DP + ia_ssa_living_arrangement: [IHHRC] + +- name: Case 8, person with DP configuration who is also blind gets DP not BLIND. + period: 2025-01 + input: + people: + person1: + age: 40 + is_blind: true + employment_income: 0 + ia_ssa_dp_configuration: BLIND_WITH_DEPENDENT + ia_ssa_dp_has_eligible_dependent: true + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # DP outranks BLIND + ia_ssa_living_arrangement: [DP] + +- name: Case 9, blind person with SMME-range income falls to SMME not BLIND. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + is_blind: true + social_security_retirement: 24_000 # $2,000/mo -> countable $1,980 + ia_ssa_has_full_medicaid: true + ia_ssa_has_medicare_part_b: true + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Blind income gate (FBR $967 + $22 = $989). Countable $1,980 > $989 -> + # BLIND branch skipped. SMME income floor is 120% FPL ($1,565); $1,980 > + # $1,565 -> SMME applies. BLIND and SMME income ranges are disjoint, so + # priority ordering between them is academic. + ia_ssa_living_arrangement: [SMME] + +- name: Case 10, DP-configured person with over-DP-standard income falls through to SMME. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security_retirement: 24_000 # $2,000/mo -> countable $1,980 + ia_ssa_dp_configuration: AGED_OR_DISABLED_WITH_DEPENDENT + ia_ssa_dp_has_eligible_dependent: true + ia_ssa_has_full_medicaid: true + ia_ssa_has_medicare_part_b: true + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # The 2025 AGED_OR_DISABLED_WITH_DEPENDENT DP standard is $1,470. Countable + # $1,980 > $1,470, so the DP recipient-income gate fails and the person + # falls through to SMME (income > 120% FPL of $1,565). DP and SMME income + # ranges are disjoint by construction — the priority cascade between them + # is academic. + ia_ssa_living_arrangement: [SMME] + +- name: Case 11, IHHRC person with SMME-eligible income gets IHHRC not SMME. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + # Note: IHHRC income cap is $480.55/mo countable, so this needs to + # be low enough to qualify for IHHRC. But we also want Medicaid + + # Part B to test that IHHRC still wins over SMME. Use zero income + # so IHHRC wins even though SMME condition could apply. + employment_income: 0 + ia_ssa_living_arrangement_input: IN_HOME_HEALTH_RELATED_CARE + ia_ssa_ihhrc_cost_of_care: 400 + ia_ssa_has_full_medicaid: true + ia_ssa_has_medicare_part_b: true + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # IHHRC outranks SMME (SMME not active here — income $0 below 120% FPL — + # but the priority order still applies even if SMME were active). + ia_ssa_living_arrangement: [IHHRC] + +- name: Case 12, blind person with DP configuration and over-income dependent falls to BLIND. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_blind: true + employment_income: 0 + ia_ssa_dp_configuration: BLIND_WITH_DEPENDENT + ia_ssa_dp_has_eligible_dependent: true + ia_ssa_dp_dependent_countable_income: 600 # > $503 2025 limit + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Dependent income $600 exceeds the $503 2025 dependent income limit, so + # the DP living-arrangement gate fails. Person is blind with $0 countable (< FBR + + # blind standard) -> falls through to BLIND category. + ia_ssa_living_arrangement: [BLIND] + ia_ssa: [22] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/hhs/ssa/ia_ssa_resources_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/hhs/ssa/ia_ssa_resources_eligible.yaml new file mode 100644 index 00000000000..9f519b4b85d --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/hhs/ssa/ia_ssa_resources_eligible.yaml @@ -0,0 +1,120 @@ +- name: Case 1, single person with resources at 2,000 limit is eligible. + period: 2025-01 + input: + people: + person1: + age: 70 + ssi_countable_resources: 2_000 + ssi_claim_is_joint: false + households: + household: + members: [person1] + state_code: IA + output: + ia_ssa_resources_eligible: [true] + +- name: Case 2, single person with resources 1 dollar above 2,000 limit is ineligible. + period: 2025-01 + input: + people: + person1: + age: 70 + ssi_countable_resources: 2_001 + ssi_claim_is_joint: false + households: + household: + members: [person1] + state_code: IA + output: + ia_ssa_resources_eligible: [false] + +- name: Case 3, single person with resources 1,500 dollars is eligible. + period: 2025-01 + input: + people: + person1: + age: 70 + ssi_countable_resources: 1_500 + ssi_claim_is_joint: false + households: + household: + members: [person1] + state_code: IA + output: + ia_ssa_resources_eligible: [true] + +- name: Case 4, joint SSI couple at combined 3,000 dollar limit is eligible. + period: 2025-01 + input: + people: + person1: + age: 70 + ssi_countable_resources: 1_500 + ssi_claim_is_joint: true + person2: + age: 68 + ssi_countable_resources: 1_500 + ssi_claim_is_joint: true + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Federal SSI counts couple resources against the couple limit. Combined + # $3,000 equals the limit -> both eligible. + ia_ssa_resources_eligible: [true, true] + +- name: Case 5, joint SSI couple with 2,000 dollars each (combined 4,000 dollars) is ineligible. + period: 2025-01 + input: + people: + person1: + age: 70 + ssi_countable_resources: 2_000 + ssi_claim_is_joint: true + person2: + age: 68 + ssi_countable_resources: 2_000 + ssi_claim_is_joint: true + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Combined $4,000 exceeds the couple limit $3,000 -> both ineligible, even + # though each individual is below the single limit. + ia_ssa_resources_eligible: [false, false] + +- name: Case 6, aged recipient with non-disabled co-resident spouse uses couple limit. + period: 2025-01 + input: + people: + person1: + age: 70 + is_disabled: false + ssi_countable_resources: 1_500 + person2: + age: 50 + is_disabled: false + ssi_countable_resources: 1_500 + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Spouse is not categorically SSI-eligible (under 65, not disabled), so + # ssi_claim_is_joint is false. Per IAC 441—51.5(2) Iowa still applies the + # $3,000 couple limit when there is a dependent spouse (51.5(4) covers + # ineligible-but-financially-dependent spouses). Combined $3,000 -> both + # eligible. Without this fix the recipient would be tested individually + # at $2,000 and lose eligibility despite Iowa's rule. + ia_ssa_resources_eligible: [true, true] diff --git a/policyengine_us/variables/gov/states/ia/hhs/ssa/dp/ia_ssa_dp_configuration.py b/policyengine_us/variables/gov/states/ia/hhs/ssa/dp/ia_ssa_dp_configuration.py new file mode 100644 index 00000000000..964df6fc003 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/hhs/ssa/dp/ia_ssa_dp_configuration.py @@ -0,0 +1,30 @@ +from policyengine_us.model_api import * + + +class IASSADPConfiguration(Enum): + AGED_OR_DISABLED_WITH_DEPENDENT = "Aged/disabled client with dependent relative" + AGED_OR_DISABLED_WITH_SPOUSE_AND_DEPENDENT = ( + "Aged/disabled client with aged/disabled spouse and dependent relative" + ) + BLIND_WITH_DEPENDENT = "Blind client with dependent relative" + BLIND_WITH_AGED_OR_DISABLED_SPOUSE_AND_DEPENDENT = ( + "Blind client with aged/disabled spouse and dependent relative" + ) + BLIND_WITH_BLIND_SPOUSE_AND_DEPENDENT = ( + "Blind client with blind spouse and dependent relative" + ) + NONE = "Not in a dependent person configuration" + + +class ia_ssa_dp_configuration(Variable): + value_type = Enum + entity = Person + definition_period = MONTH + label = "Iowa SSA dependent person configuration" + possible_values = IASSADPConfiguration + default_value = IASSADPConfiguration.NONE + defined_for = StateCode.IA + reference = ( + "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.52.pdf#page=1", + "https://hhs.iowa.gov/assistance-programs/state-supplementary-assistance", + ) diff --git a/policyengine_us/variables/gov/states/ia/hhs/ssa/dp/ia_ssa_dp_dependent_countable_income.py b/policyengine_us/variables/gov/states/ia/hhs/ssa/dp/ia_ssa_dp_dependent_countable_income.py new file mode 100644 index 00000000000..264f178c6e5 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/hhs/ssa/dp/ia_ssa_dp_dependent_countable_income.py @@ -0,0 +1,13 @@ +from policyengine_us.model_api import * + + +class ia_ssa_dp_dependent_countable_income(Variable): + value_type = float + entity = Person + definition_period = MONTH + label = "Iowa SSA dependent person countable income" + unit = USD + defined_for = StateCode.IA + reference = ( + "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.51.pdf#page=2" + ) diff --git a/policyengine_us/variables/gov/states/ia/hhs/ssa/dp/ia_ssa_dp_has_eligible_dependent.py b/policyengine_us/variables/gov/states/ia/hhs/ssa/dp/ia_ssa_dp_has_eligible_dependent.py new file mode 100644 index 00000000000..9714555264f --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/hhs/ssa/dp/ia_ssa_dp_has_eligible_dependent.py @@ -0,0 +1,12 @@ +from policyengine_us.model_api import * + + +class ia_ssa_dp_has_eligible_dependent(Variable): + value_type = bool + entity = Person + definition_period = MONTH + label = "Iowa SSA has financially dependent relative" + defined_for = StateCode.IA + reference = ( + "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.52.pdf#page=1" + ) diff --git a/policyengine_us/variables/gov/states/ia/hhs/ssa/ia_ssa.py b/policyengine_us/variables/gov/states/ia/hhs/ssa/ia_ssa.py new file mode 100644 index 00000000000..ad5c7e2567c --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/hhs/ssa/ia_ssa.py @@ -0,0 +1,177 @@ +from policyengine_us.model_api import * + + +class ia_ssa(Variable): + value_type = float + entity = Person + definition_period = MONTH + label = "Iowa State Supplementary Assistance" + unit = USD + defined_for = StateCode.IA + reference = ( + "https://www.legis.iowa.gov/docs/code/249.3.pdf", + "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.52.pdf", + "https://hhs.iowa.gov/media/15607/download", + "https://hhs.iowa.gov/assistance-programs/state-supplementary-assistance", + ) + + def formula(person, period, parameters): + arrangement = person("ia_ssa_living_arrangement", period) + arr_values = arrangement.possible_values + p = parameters(period).gov.states.ia.hhs.ssa + # YEAR-defined FLOW variables auto-divide to monthly when requested + # at a MONTH period (policyengine-core simulation.calculate_divide). + countable_monthly = person("ssi_countable_income", period) + ssi_monthly = person("ssi", period) + # Iowa RCF, FLH-eligibility, and IHHRC do not allow the SSI $20 general + # income disregard (GL 6-B-46 pp. 30, 36–38, 54–58). RCF and IHHRC are + # state-administered, so this helper restores the $20 the SSI exclusion + # already removed. + countable_no_disregard = person("ia_ssa_countable_income_no_disregard", period) + p_ssi = parameters(period).gov.ssa.ssi.amount + individual_fbr = p_ssi.individual + couple_fbr = p_ssi.couple + joint_claim = person("ssi_claim_is_joint", period.this_year) + is_blind = person("is_blind", period.this_year) + marital_countable = person.marital_unit.sum(countable_monthly) + # BLIND — IAC 441—52.1(4): flat $22 state supplement (frozen since 2011) + # per blind person. Federally administered, so SSA's $20 disregard + # applies via ssi_countable_income. For any joint SSI claim + # ssi_countable_income returns combined / 2 per spouse and the + # federal piece is paid against couple_fbr, so aggregate marital + # countable and compare against (couple_fbr + N × $22) where N is + # the number of blind people in the unit. Split the supplement only + # when both spouses are blind (both route to BLIND); when only one + # spouse is blind, the non-blind spouse routes elsewhere and the + # blind spouse keeps the full per-blind allowance. + blind_count_in_unit = person.marital_unit.sum(is_blind) + blind_applicable_fbr = where(joint_claim, couple_fbr, individual_fbr) + blind_supplement_total = where( + joint_claim, blind_count_in_unit * p.blind, p.blind + ) + blind_compare_income = where(joint_claim, marital_countable, countable_monthly) + blind_amt_full = max_( + 0, + (blind_applicable_fbr + blind_supplement_total) + - max_(blind_compare_income, blind_applicable_fbr), + ) + joint_blind_couple = joint_claim & (blind_count_in_unit == 2) + blind_amt = blind_amt_full / where(joint_blind_couple, 2, 1) + # DP — IAC 441—52.1(2): per-configuration assistance standard. Pick the + # applicable Federal Benefit Rate (couple FBR for configurations that + # include an eligible spouse, individual FBR otherwise) so the + # supplement equals (standard − max(countable, applicable_fbr)). + dp_config = person("ia_ssa_dp_configuration", period) + dp_config_values = dp_config.possible_values + dp_assistance_standard = p.dp.assistance_standard[dp_config] + dp_has_spouse = ( + (dp_config == dp_config_values.AGED_OR_DISABLED_WITH_SPOUSE_AND_DEPENDENT) + | ( + dp_config + == dp_config_values.BLIND_WITH_AGED_OR_DISABLED_SPOUSE_AND_DEPENDENT + ) + | (dp_config == dp_config_values.BLIND_WITH_BLIND_SPOUSE_AND_DEPENDENT) + ) + dp_applicable_fbr = where(dp_has_spouse, couple_fbr, individual_fbr) + # Couple-config DP compares income against couple_fbr, which is a + # marital-unit-level threshold. countable_monthly is per-spouse + # (combined / 2 for joint SSI claims), so aggregate across the + # marital unit when the comparison threshold is couple-level. + dp_compare_income = where(dp_has_spouse, marital_countable, countable_monthly) + dp_amt_full = max_( + 0, + dp_assistance_standard - max_(dp_compare_income, dp_applicable_fbr), + ) + # Per-marital-unit guard: couple-FBR DP configurations describe the + # whole marital unit, not each spouse. Split the supplement equally + # among spouses in the marital unit who claim a couple-FBR config so + # the SPM-unit aggregation does not double-count when both spouses + # set the same couple configuration. + dp_couple_count = person.marital_unit.sum(dp_has_spouse) + dp_divisor = where(dp_has_spouse, max_(dp_couple_count, 1), 1) + dp_amt = dp_amt_full / dp_divisor + # FLH — IAC 441—52.1(1): SSA-administered, so the V-shape uses + # ssi_countable_income (with the $20 disregard SSA actually applies). + # The $142 SSA cap caps the federally-administered piece; the + # Department fills the gap from total income to the FLH standard + # (GL 6-B-46 p.30) — so an SSI-only recipient gets the full + # (state_supplement − cap) top-up, while a recipient with $10/mo of + # other unearned income needs only a $10 top-up to reach the + # standard. 441—52.1(4) excludes the $22 blind allowance for + # recipients of any other SSP, so blind FLH recipients receive the + # FLH benefit only. + flh_v_shape = max_( + 0, + (individual_fbr + p.flh.state_supplement) + - max_(countable_monthly, individual_fbr), + ) + flh_base = min_(flh_v_shape, p.flh.max_supplement) + # non_ssi_income proxies gross other income via post-SSI-exclusion + # countable; pre-exclusion gross would be more accurate for cases + # with earned income (where the $65 + 50% earned exclusions hide + # gross from countable_no_disregard) — flag for follow-up. + non_ssi_income = max_(0, countable_no_disregard) + flh_total_income_after_base = ssi_monthly + non_ssi_income + flh_base + flh_standard = individual_fbr + p.flh.state_supplement + # Defensive cap at the published gap so artificially low ssi_monthly + # (non-takeup, mid-month transitions) cannot explode the supplement. + flh_extra = min_( + max_(0, flh_standard - flh_total_income_after_base), + max_(0, p.flh.state_supplement - p.flh.max_supplement), + ) + flh_amt = flh_base + flh_extra + # RCF — IAC 441—52.1(3): cost-of-care minus client participation. + # Client participation = total monthly income (countable + SSI) minus + # the personal needs allowance. Iowa GL 6-B-46 p. 54 omits the SSI $20 + # disregard, so use countable_no_disregard. Other regulatory deductions + # (impairment-related work expenses, dependent diversions, unmet + # medical needs, first-month expenses) are not modeled. + rcf_per_diem = person("ia_ssa_rcf_cost_per_diem", period) + rcf_capped_per_diem = min_(rcf_per_diem, p.rcf.max_per_diem) + rcf_cost_of_care = rcf_capped_per_diem * p.rcf.days_multiplier + rcf_total_income = countable_no_disregard + ssi_monthly + rcf_client_participation = max_( + 0, rcf_total_income - p.rcf.personal_needs_allowance + ) + rcf_amt = max_(0, rcf_cost_of_care - rcf_client_participation) + # IHHRC — IAC 441—177.10(2)(a) and 177.10(3): + # payment = max(0, min(cost, per-person cap) − client participation). + # Client participation = combined marital-unit countable income + # (without the SSI $20 disregard, per GL 6-B-46 p. 36) minus the + # applicable FBR. When both spouses need care, split evenly across the + # marital unit so SPM-unit aggregation does not double-count. + # Home-maintenance, dependent-diversion, and medical-need deductions + # are not modeled. + ihhrc_cost = person("ia_ssa_ihhrc_cost_of_care", period) + both_need_care = person("ia_ssa_ihhrc_both_need_care", period) + # IAC 441—177.4(1)(f)(1) and Iowa HHS GL 6-B-46: deduct the basic SSI + # standard "for an individual or a couple, as applicable." The couple + # allowance applies whenever a spouse lives in the home, not only + # when both spouses are SSI-categorically eligible. + has_spouse_in_home = person.marital_unit.nb_persons() > 1 + ihhrc_basic_ssi_disregard = where( + has_spouse_in_home, couple_fbr, individual_fbr + ) + combined_countable = person.marital_unit.sum(countable_no_disregard) + combined_participation = max_(0, combined_countable - ihhrc_basic_ssi_disregard) + ihhrc_client_participation = where( + both_need_care, + combined_participation / person.marital_unit.nb_persons(), + combined_participation, + ) + ihhrc_eligible_cost = min_(ihhrc_cost, p.ihhrc.max_cost_single) + ihhrc_amt = max_(0, ihhrc_eligible_cost - ihhrc_client_participation) + # SMME — IAC 441—52.1(7): flat amount ($1 since 2017). + smme_amt = p.smme.amount + return select( + [ + arrangement == arr_values.RCF, + arrangement == arr_values.IHHRC, + arrangement == arr_values.FLH, + arrangement == arr_values.DP, + arrangement == arr_values.BLIND, + arrangement == arr_values.SMME, + ], + [rcf_amt, ihhrc_amt, flh_amt, dp_amt, blind_amt, smme_amt], + default=0, + ) diff --git a/policyengine_us/variables/gov/states/ia/hhs/ssa/ia_ssa_countable_income_no_disregard.py b/policyengine_us/variables/gov/states/ia/hhs/ssa/ia_ssa_countable_income_no_disregard.py new file mode 100644 index 00000000000..42ba67d8553 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/hhs/ssa/ia_ssa_countable_income_no_disregard.py @@ -0,0 +1,47 @@ +from policyengine_us.model_api import * + + +class ia_ssa_countable_income_no_disregard(Variable): + value_type = float + entity = Person + definition_period = MONTH + label = "Iowa SSA monthly countable income, without the SSI $20 general income disregard" + unit = USD + defined_for = StateCode.IA + reference = ( + "https://hhs.iowa.gov/media/15607/download", + "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.52.pdf#page=2", + "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.177.pdf#page=2", + "https://www.law.cornell.edu/cfr/text/20/416.1112", + ) + + def formula(person, period, parameters): + # Iowa RCF and IHHRC do not allow the SSI $20 general income disregard + # (GL 6-B-46 pp. 36, 54-58). Reverse what _apply_ssi_exclusions + # actually applied. The exclusion bases must mirror + # ssi_countable_income exactly: unearned = marital unearned + parent + # deemed + ISM; earned = marital earned − blind/disabled working + # student exclusion (clamped at 0). The $20 falls first on the + # unearned base; any leftover applies inside the earned flat exclusion + # ($65 + leftover) before the 50% earned-share rule, so the + # earned-side add-back is reduced by (1 − earned_share). Couple + # computation halves countable per person; mirror that by dividing + # the add-back by marital-unit size when it applies. + p = parameters(period).gov.ssa.ssi.income.exclusions + countable_monthly = person("ssi_countable_income", period) + marital_unearned = person("ssi_marital_unearned_income", period) + parent_deemed = person( + "ssi_unearned_income_deemed_from_ineligible_parent", period + ) + ism = person("ssi_in_kind_support_and_maintenance", period) + unearned_basis = marital_unearned + parent_deemed + ism + marital_earned = person("ssi_marital_earned_income", period) + student_excl = person("ssi_blind_or_disabled_working_student_exclusion", period) + earned_basis = max_(marital_earned - student_excl, 0) + applied_to_unearned = min_(p.general, unearned_basis) + leftover = p.general - applied_to_unearned + applied_to_earned = min_(leftover, max_(earned_basis - p.earned, 0)) + addback = applied_to_unearned + applied_to_earned * (1 - p.earned_share) + couple = person("ssi_couple_computation_applies", period.this_year) + nb_in_unit = person.marital_unit.nb_persons() + return countable_monthly + where(couple, addback / nb_in_unit, addback) diff --git a/policyengine_us/variables/gov/states/ia/hhs/ssa/ia_ssa_eligible.py b/policyengine_us/variables/gov/states/ia/hhs/ssa/ia_ssa_eligible.py new file mode 100644 index 00000000000..99af99fc569 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/hhs/ssa/ia_ssa_eligible.py @@ -0,0 +1,33 @@ +from policyengine_us.model_api import * + + +class ia_ssa_eligible(Variable): + value_type = bool + entity = Person + definition_period = MONTH + label = "Iowa SSA eligible" + defined_for = StateCode.IA + reference = ( + "https://www.legis.iowa.gov/docs/code/249.3.pdf", + "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.51.pdf", + ) + + def formula(person, period, parameters): + # Use SSI's categorical eligibility (aged/blind/disabled + + # immigration) but apply Iowa's own resource test (IAC 441—51.5) + # rather than the federal SSI resource test. Federal applies the + # $2,000 individual limit when the spouse is not part of a joint + # SSI claim, which would block Iowa's $3,000 marital-unit limit + # for cases like a claimant with a non-ABD spouse and $2,500 in + # combined resources. IAC 441—51.1 lets Iowa SSA pay recipients + # who would qualify for SSI except for excess income, so the + # federal resource test should not gate Iowa eligibility. + abd = person("is_ssi_aged_blind_disabled", period.this_year) + is_qualified_noncitizen = person( + "is_ssi_qualified_noncitizen", period.this_year + ) + immigration_status = person("immigration_status", period.this_year) + is_citizen = immigration_status == immigration_status.possible_values.CITIZEN + meets_immigration = is_qualified_noncitizen | is_citizen + resources_eligible = person("ia_ssa_resources_eligible", period) + return abd & meets_immigration & resources_eligible diff --git a/policyengine_us/variables/gov/states/ia/hhs/ssa/ia_ssa_living_arrangement.py b/policyengine_us/variables/gov/states/ia/hhs/ssa/ia_ssa_living_arrangement.py new file mode 100644 index 00000000000..3fe5c6d7493 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/hhs/ssa/ia_ssa_living_arrangement.py @@ -0,0 +1,155 @@ +from policyengine_us.model_api import * + + +class IASSALivingArrangement(Enum): + RCF = "Residential care facility" + IHHRC = "In-home health-related care" + FLH = "Family-life home" + DP = "Dependent person" + BLIND = "Blind" + SMME = "Supplement for Medicare and Medicaid eligibles" + NONE = "Not in an Iowa SSA category" + + +class ia_ssa_living_arrangement(Variable): + value_type = Enum + entity = Person + definition_period = MONTH + label = "Iowa SSA living arrangement" + possible_values = IASSALivingArrangement + default_value = IASSALivingArrangement.NONE + defined_for = StateCode.IA + reference = "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.52.pdf" + + def formula(person, period, parameters): + eligible = person("ia_ssa_eligible", period) + p = parameters(period).gov.states.ia.hhs.ssa + # YEAR-defined FLOW variables auto-divide to monthly at MONTH period. + countable_monthly = person("ssi_countable_income", period) + ssi_monthly = person("ssi", period) + countable_no_disregard = person("ia_ssa_countable_income_no_disregard", period) + p_ssi = parameters(period).gov.ssa.ssi.amount + individual_fbr = p_ssi.individual + couple_fbr = p_ssi.couple + joint_claim = person("ssi_claim_is_joint", period.this_year) + marital_countable = person.marital_unit.sum(countable_monthly) + # IAC 441—177.4(1)(f)(1) and Iowa HHS GL 6-B-46: the IHHRC home + # maintenance allowance deducts the basic SSI standard "for an + # individual or a couple, as applicable." The couple allowance applies + # whenever a spouse lives in the home, not only when both spouses are + # SSI-categorically eligible. + has_spouse_in_home = person.marital_unit.nb_persons() > 1 + ihhrc_basic_ssi_disregard = where( + has_spouse_in_home, couple_fbr, individual_fbr + ) + # IAC 441—51.4(3) cross-refs 52.1(3)"a": RCF income eligibility compares + # client participation (total monthly income minus the personal needs + # allowance) against 31 × the maximum per diem. GL 6-B-46 p. 54 omits + # the SSI $20 disregard, so use countable_no_disregard. + rcf_total_income = countable_no_disregard + ssi_monthly + rcf_client_participation = max_( + 0, rcf_total_income - p.rcf.personal_needs_allowance + ) + arrangement_input = person("ia_ssa_living_arrangement_input", period) + arr_input_values = arrangement_input.possible_values + in_rcf = arrangement_input == arr_input_values.RESIDENTIAL_CARE_FACILITY + rcf_income_threshold = p.rcf.days_multiplier * p.rcf.max_per_diem + rcf_income_eligible = rcf_client_participation < rcf_income_threshold + needs_ihhrc = arrangement_input == arr_input_values.IN_HOME_HEALTH_RELATED_CARE + both_need_care = person("ia_ssa_ihhrc_both_need_care", period) + # IAC 441—177.4(1)(f) caps combined marital-unit countable income at + # $480.55 (one spouse needs care) or $961.10 (both need care) after + # the basic SSI standard disregard. GL 6-B-46 p. 36 omits the $20 + # disregard, so use countable_no_disregard. + combined_countable = person.marital_unit.sum(countable_no_disregard) + ihhrc_countable_after_disregard = max_( + 0, combined_countable - ihhrc_basic_ssi_disregard + ) + ihhrc_cap = where( + both_need_care, p.ihhrc.max_cost_couple, p.ihhrc.max_cost_single + ) + ihhrc_income_eligible = ihhrc_countable_after_disregard <= ihhrc_cap + in_flh = arrangement_input == arr_input_values.FAMILY_LIFE_HOME + # IAC 441—50.2(1) and 52.1(1): the FLH supplement phases to zero when + # countable income reaches the FLH standard (FBR + state supplement). + # Gate at the living-arrangement level so FLH-living recipients with + # excess income fall through rather than blocking the SMME fallback. + flh_income_eligible = countable_monthly < ( + individual_fbr + p.flh.state_supplement + ) + # IAC 441—177.4(1)(c): IHHRC recipients must live in their own home, + # so exclude those residing in an RCF or family-life home. + in_own_home = ~in_rcf & ~in_flh + has_dependent = person("ia_ssa_dp_has_eligible_dependent", period) + dp_configuration = person("ia_ssa_dp_configuration", period) + dp_config_values = dp_configuration.possible_values + in_dp = dp_configuration != dp_config_values.NONE + # IAC 441—52.1(2): DP requires the dependent's countable income below + # the dependent income limit (per IAC 441—51.5(1)). Gate at the + # living-arrangement level so people who qualify for DP but fail the + # dependent-income test fall through to Blind / SMME rather than + # receiving a zero DP supplement. + dependent_income = person("ia_ssa_dp_dependent_countable_income", period) + dependent_income_eligible = dependent_income < p.dp.dependent_income_limit + # IAC 441—50.2(1) and 52.1(2): the DP supplement phases to zero when + # the recipient/marital countable income reaches the configuration's + # assistance standard. Couple configurations describe the whole + # marital unit, so use marital countable income to match the + # marital-unit-level standard. + dp_assistance_standard = p.dp.assistance_standard[dp_configuration] + dp_has_spouse = ( + ( + dp_configuration + == dp_config_values.AGED_OR_DISABLED_WITH_SPOUSE_AND_DEPENDENT + ) + | ( + dp_configuration + == dp_config_values.BLIND_WITH_AGED_OR_DISABLED_SPOUSE_AND_DEPENDENT + ) + | ( + dp_configuration + == dp_config_values.BLIND_WITH_BLIND_SPOUSE_AND_DEPENDENT + ) + ) + dp_compare_income = where(dp_has_spouse, marital_countable, countable_monthly) + dp_recipient_income_eligible = dp_compare_income < dp_assistance_standard + is_blind = person("is_blind", period.this_year) + # IAC 441—52.1(4) blind standard is a federally-administered SSP; + # supplement phases to zero when countable income reaches FBR + state + # standard. Mirror that ceiling in the category gate so blind + # recipients with excess income fall through to the next category. + # Any joint SSI claim uses couple-FBR basis: ssi_countable_income + # returns combined / 2 per spouse, so aggregate marital countable + # and compare against (couple_fbr + N × $22) where N is the number + # of blind people in the marital unit. + blind_count_in_unit = person.marital_unit.sum(is_blind) + blind_applicable_fbr = where(joint_claim, couple_fbr, individual_fbr) + blind_supplement = where(joint_claim, blind_count_in_unit * p.blind, p.blind) + blind_compare_income = where(joint_claim, marital_countable, countable_monthly) + blind_income_eligible = ( + blind_compare_income < blind_applicable_fbr + blind_supplement + ) + smme_eligible = person("ia_ssa_smme_eligible", period) + return select( + [ + eligible & in_rcf & rcf_income_eligible, + eligible & needs_ihhrc & in_own_home & ihhrc_income_eligible, + eligible & in_flh & flh_income_eligible, + eligible + & has_dependent + & in_dp + & dependent_income_eligible + & dp_recipient_income_eligible, + eligible & is_blind & blind_income_eligible, + eligible & smme_eligible, + ], + [ + IASSALivingArrangement.RCF, + IASSALivingArrangement.IHHRC, + IASSALivingArrangement.FLH, + IASSALivingArrangement.DP, + IASSALivingArrangement.BLIND, + IASSALivingArrangement.SMME, + ], + default=IASSALivingArrangement.NONE, + ) diff --git a/policyengine_us/variables/gov/states/ia/hhs/ssa/ia_ssa_living_arrangement_input.py b/policyengine_us/variables/gov/states/ia/hhs/ssa/ia_ssa_living_arrangement_input.py new file mode 100644 index 00000000000..6e323e7266b --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/hhs/ssa/ia_ssa_living_arrangement_input.py @@ -0,0 +1,23 @@ +from policyengine_us.model_api import * + + +class IASSALivingArrangementInput(Enum): + NONE = "Not in a qualifying arrangement" + FAMILY_LIFE_HOME = "Resides in certified family-life home" + RESIDENTIAL_CARE_FACILITY = "Resides in licensed residential care facility" + IN_HOME_HEALTH_RELATED_CARE = "Receives in-home health-related care" + + +class ia_ssa_living_arrangement_input(Variable): + value_type = Enum + entity = Person + definition_period = MONTH + label = "Iowa SSA living-arrangement input" + possible_values = IASSALivingArrangementInput + default_value = IASSALivingArrangementInput.NONE + defined_for = StateCode.IA + reference = ( + "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.52.pdf#page=1", + "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.177.pdf#page=2", + "https://www.legis.iowa.gov/docs/code/135C.1.pdf", + ) diff --git a/policyengine_us/variables/gov/states/ia/hhs/ssa/ia_ssa_resources_eligible.py b/policyengine_us/variables/gov/states/ia/hhs/ssa/ia_ssa_resources_eligible.py new file mode 100644 index 00000000000..742db277ad9 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/hhs/ssa/ia_ssa_resources_eligible.py @@ -0,0 +1,37 @@ +from policyengine_us.model_api import * + + +class ia_ssa_resources_eligible(Variable): + value_type = bool + entity = Person + definition_period = MONTH + label = "Iowa SSA resources eligible" + defined_for = StateCode.IA + reference = ( + "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.50.pdf", + "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.51.pdf#page=2", + "https://secure.ssa.gov/poms.nsf/lnx/0501110003", + "https://secure.ssa.gov/poms.nsf/lnx/0501110530", + "https://www.ecfr.gov/current/title-20/chapter-III/part-416/subpart-K#p-416.1202(a)", + ) + + def formula(person, period, parameters): + # IA SSA adopts the federal SSI $2,000 / $3,000 resource schedule + # under the umbrella authority of IAC 441—50.2 (resource policy + # follows SSI rules unless explicitly modified). Federal SSI applies + # the $3,000 limit to "an individual with a spouse" whether the + # spouse is eligible or ineligible, when they live in the same + # household: SSA POMS SI 01110.003 (limits) and SI 01110.530 (deeming + # of ineligible spouse resources), 20 CFR §416.1202(a). IAC + # 441—51.5(2) carries the same $2k/$3k schedule for the dependent- + # relative configuration. Apply the couple limit whenever the + # recipient lives with any spouse — using `ssi_claim_is_joint` is too + # narrow because it requires both spouses to be SSI-categorically + # eligible. + individual_resources = person("ssi_countable_resources", period.this_year) + marital_resources = person.marital_unit.sum(individual_resources) + has_spouse = person.marital_unit.nb_persons() > 1 + resources_to_check = where(has_spouse, marital_resources, individual_resources) + p = parameters(period).gov.ssa.ssi.eligibility.resources.limit + limit = where(has_spouse, p.couple, p.individual) + return resources_to_check <= limit diff --git a/policyengine_us/variables/gov/states/ia/hhs/ssa/ihhrc/ia_ssa_ihhrc_both_need_care.py b/policyengine_us/variables/gov/states/ia/hhs/ssa/ihhrc/ia_ssa_ihhrc_both_need_care.py new file mode 100644 index 00000000000..c7f0d502696 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/hhs/ssa/ihhrc/ia_ssa_ihhrc_both_need_care.py @@ -0,0 +1,20 @@ +from policyengine_us.model_api import * + + +class ia_ssa_ihhrc_both_need_care(Variable): + value_type = bool + entity = Person + definition_period = MONTH + label = "Iowa SSA IHHRC both spouses need in-home health-related care" + defined_for = StateCode.IA + reference = ( + "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.177.pdf#page=2" + ) + + def formula(person, period, parameters): + arrangement_input = person("ia_ssa_living_arrangement_input", period) + needs_care = ( + arrangement_input + == arrangement_input.possible_values.IN_HOME_HEALTH_RELATED_CARE + ) + return person.marital_unit.sum(needs_care) == 2 diff --git a/policyengine_us/variables/gov/states/ia/hhs/ssa/ihhrc/ia_ssa_ihhrc_cost_of_care.py b/policyengine_us/variables/gov/states/ia/hhs/ssa/ihhrc/ia_ssa_ihhrc_cost_of_care.py new file mode 100644 index 00000000000..1ad27fc1074 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/hhs/ssa/ihhrc/ia_ssa_ihhrc_cost_of_care.py @@ -0,0 +1,25 @@ +from policyengine_us.model_api import * + + +class ia_ssa_ihhrc_cost_of_care(Variable): + value_type = float + entity = Person + definition_period = MONTH + label = "Iowa SSA in-home health-related care monthly cost" + unit = USD + defined_for = StateCode.IA + reference = ( + "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.177.pdf#page=2" + ) + + def formula(person, period, parameters): + # Iowa pays the eligible service cost above client participation, up + # to the per-person max payment of $480.55 (IAC 441—177.10(3); Iowa + # HHS 2026 standards). Actual care cost is a per-recipient input we + # do not track at the moment. When arrangement is known to be IHHRC + # but cost is unavailable, impute the cap so the supplement is not + # falsely zeroed; users can override with actual care-cost data. + p = parameters(period).gov.states.ia.hhs.ssa.ihhrc + arrangement = person("ia_ssa_living_arrangement", period) + in_ihhrc = arrangement == arrangement.possible_values.IHHRC + return where(in_ihhrc, p.max_cost_single, 0) diff --git a/policyengine_us/variables/gov/states/ia/hhs/ssa/rcf/ia_ssa_rcf_cost_per_diem.py b/policyengine_us/variables/gov/states/ia/hhs/ssa/rcf/ia_ssa_rcf_cost_per_diem.py new file mode 100644 index 00000000000..ff95cb37af2 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/hhs/ssa/rcf/ia_ssa_rcf_cost_per_diem.py @@ -0,0 +1,13 @@ +from policyengine_us.model_api import * + + +class ia_ssa_rcf_cost_per_diem(Variable): + value_type = float + entity = Person + definition_period = MONTH + label = "Iowa SSA residential care facility actual per diem cost" + unit = USD + defined_for = StateCode.IA + reference = ( + "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.52.pdf#page=1" + ) diff --git a/policyengine_us/variables/gov/states/ia/hhs/ssa/smme/ia_ssa_has_full_medicaid.py b/policyengine_us/variables/gov/states/ia/hhs/ssa/smme/ia_ssa_has_full_medicaid.py new file mode 100644 index 00000000000..a6c18749075 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/hhs/ssa/smme/ia_ssa_has_full_medicaid.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class ia_ssa_has_full_medicaid(Variable): + value_type = bool + entity = Person + definition_period = MONTH + label = "Iowa SSA receives full Medicaid" + defined_for = StateCode.IA + default_value = False + reference = ( + "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.51.pdf#page=2" + ) + # IAC 441—51.6(1) requires SMME recipients to be enrolled in "full + # Medicaid", which excludes medically-needy/spenddown and MEPD-premium + # pathways. PolicyEngine's generic `medicaid_enrolled` flag includes + # those narrower populations, so Iowa SSA takes an explicit input for + # this flag — users opt in when a household is known to be enrolled in + # full Medicaid. diff --git a/policyengine_us/variables/gov/states/ia/hhs/ssa/smme/ia_ssa_has_medicare_part_b.py b/policyengine_us/variables/gov/states/ia/hhs/ssa/smme/ia_ssa_has_medicare_part_b.py new file mode 100644 index 00000000000..de2d24cb551 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/hhs/ssa/smme/ia_ssa_has_medicare_part_b.py @@ -0,0 +1,13 @@ +from policyengine_us.model_api import * + + +class ia_ssa_has_medicare_part_b(Variable): + value_type = bool + entity = Person + definition_period = MONTH + label = "Iowa SSA eligible for Medicare Part B" + defined_for = StateCode.IA + default_value = False + reference = ( + "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.51.pdf#page=2" + ) diff --git a/policyengine_us/variables/gov/states/ia/hhs/ssa/smme/ia_ssa_smme_eligible.py b/policyengine_us/variables/gov/states/ia/hhs/ssa/smme/ia_ssa_smme_eligible.py new file mode 100644 index 00000000000..b731ff02b1a --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/hhs/ssa/smme/ia_ssa_smme_eligible.py @@ -0,0 +1,43 @@ +from policyengine_us.model_api import * + + +class ia_ssa_smme_eligible(Variable): + value_type = bool + entity = Person + definition_period = MONTH + label = "Iowa SSA SMME eligible" + defined_for = StateCode.IA + reference = ( + "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.51.pdf#page=2", + "https://www.legis.iowa.gov/docs/code/249.3.pdf", + ) + + def formula(person, period, parameters): + # IAC 441—51.7(6): "Income of a recipient" must exceed 120% of the + # federal poverty level. The test is on the SSI claimant's own (or + # joint-claim couple's) combined income, not on a larger SPM unit, + # so size the FPL by the SSI claim — 1 person for an individual, + # 2 for a joint claim — rather than by SPM unit size. For joint + # claims, ssi_countable_income returns the per-spouse half of the + # combined marital countable, so aggregate across the marital unit + # before comparing to the 2-person FPL. + aged_or_disabled = person("is_ssi_aged_blind_disabled", period.this_year) + has_medicaid = person("ia_ssa_has_full_medicaid", period) + has_medicare = person("ia_ssa_has_medicare_part_b", period) + p = parameters(period).gov.states.ia.hhs.ssa + p_fpg = parameters(period).gov.hhs.fpg + joint_claim = person("ssi_claim_is_joint", period.this_year) + # YEAR-defined FLOW vars auto-divide to monthly at MONTH period. + own_monthly = person("ssi_countable_income", period) + marital_monthly = person.marital_unit.sum(own_monthly) + countable_monthly = where(joint_claim, marital_monthly, own_monthly) + state_group = person.household("state_group_str", period.this_year) + first_person = p_fpg.first_person[state_group] + additional_person = p_fpg.additional_person[state_group] + annual_fpg = first_person + where(joint_claim, additional_person, 0) + # FPG parameters are annual values (no auto-divide for parameters). + fpg_monthly = annual_fpg / MONTHS_IN_YEAR + income_above_fpl_floor = ( + countable_monthly > p.smme.minimum_income_fpl_multiplier * fpg_monthly + ) + return aged_or_disabled & has_medicaid & has_medicare & income_above_fpl_floor 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 9ec28688a31..809dc14ab8a 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 @@ -17,6 +17,7 @@ def formula(spm_unit, period, parameters): "ga_ssp", "al_ssp", "ak_ssp", + "ia_ssa", # Iowa benefits "dc_ossp", # DC benefits "id_aabd", # Idaho benefits "ky_ssp", # Kentucky benefits