From 03038b8ef28c7f8cc85ebd538078cd34a4bd1dce Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 25 Mar 2026 13:18:02 -0400 Subject: [PATCH 1/3] Fix CA CalWORKs per-person applicant earned income disregard Per WIC 11450.12, the applicant $450 disregard must be applied "for each employed person," not as a single flat amount per AU. This creates person-level earned income variables and updates the applicant countable income formula to sum post-disregard amounts across members. Also fixes broken San Diego County reference links (#5488) and a typo in ca_tanf_eligible (financial_eligibile -> financial_eligible). Closes #770, Closes #5488 Co-Authored-By: Claude Opus 4.6 (1M context) --- ...ks-per-person-applicant-disregard.fixed.md | 1 + .../income/monthly_limit/max_au_size.yaml | 4 +- .../cash/monthly_payment/max_au_size.yaml | 4 +- .../cash/monthly_payment/region1/exempt.yaml | 2 - .../monthly_payment/region1/non_exempt.yaml | 2 - .../cash/monthly_payment/region2/exempt.yaml | 2 - .../monthly_payment/region2/non_exempt.yaml | 2 - .../ca_tanf_countable_income_applicant.yaml | 219 +++++++++++++----- ..._earned_income_after_disregard_person.yaml | 73 ++++++ .../states/ca/cdss/tanf/cash/integration.yaml | 52 +++++ .../tanf/cash/eligibility/ca_tanf_eligible.py | 4 +- .../eligibility/ca_tanf_maximum_payment.py | 2 +- .../ca_tanf_countable_income_applicant.py | 13 +- .../ca_tanf_countable_income_recipient.py | 2 +- .../tanf/cash/income/ca_tanf_earned_income.py | 2 +- ...nf_earned_income_after_disregard_person.py | 16 ++ .../income/ca_tanf_earned_income_person.py | 13 ++ 17 files changed, 328 insertions(+), 85 deletions(-) create mode 100644 changelog.d/fix-ca-calworks-per-person-applicant-disregard.fixed.md create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ca/cdss/tanf/cash/income/ca_tanf_earned_income_after_disregard_person.yaml create mode 100644 policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_earned_income_after_disregard_person.py create mode 100644 policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_earned_income_person.py diff --git a/changelog.d/fix-ca-calworks-per-person-applicant-disregard.fixed.md b/changelog.d/fix-ca-calworks-per-person-applicant-disregard.fixed.md new file mode 100644 index 00000000000..a287a9b671c --- /dev/null +++ b/changelog.d/fix-ca-calworks-per-person-applicant-disregard.fixed.md @@ -0,0 +1 @@ +Fix CA CalWORKs per-person applicant earned income disregard and update broken references. diff --git a/policyengine_us/parameters/gov/states/ca/cdss/tanf/cash/income/monthly_limit/max_au_size.yaml b/policyengine_us/parameters/gov/states/ca/cdss/tanf/cash/income/monthly_limit/max_au_size.yaml index 211692d6b22..f56074d226a 100644 --- a/policyengine_us/parameters/gov/states/ca/cdss/tanf/cash/income/monthly_limit/max_au_size.yaml +++ b/policyengine_us/parameters/gov/states/ca/cdss/tanf/cash/income/monthly_limit/max_au_size.yaml @@ -5,8 +5,8 @@ metadata: period: month label: California CalWORKs maximum assistance unit size for MBSAC reference: - - title: County of San Diego CalWORKS Program Guide | CalWORKs Payment Standards Chart - href: https://hhsaprogramguides.sandiegocounty.gov/CalWORKS/44-300/CalWORKs_Payment_Standards/G_CalWORKs_Payment_Standards.pdf + - title: California Department of Social Services, Executive Summary, All County Letter No. 24-55, CalWORKs Payment Standards Chart Effective October 1, 2024 + href: https://cdss.ca.gov/Portals/9/Additional-Resources/Letters-and-Notices/ACLs/2024/24-55.pdf#page=7 values: 2015-07-01: 10 diff --git a/policyengine_us/parameters/gov/states/ca/cdss/tanf/cash/monthly_payment/max_au_size.yaml b/policyengine_us/parameters/gov/states/ca/cdss/tanf/cash/monthly_payment/max_au_size.yaml index af556b925c8..af8bea884d0 100644 --- a/policyengine_us/parameters/gov/states/ca/cdss/tanf/cash/monthly_payment/max_au_size.yaml +++ b/policyengine_us/parameters/gov/states/ca/cdss/tanf/cash/monthly_payment/max_au_size.yaml @@ -5,8 +5,8 @@ metadata: period: month label: California CalWORKs maximum assistance unit size for payment standards reference: - - title: County of San Diego CalWORKS Program Guide | CalWORKs Payment Standards Chart - href: https://hhsaprogramguides.sandiegocounty.gov/CalWORKS/44-300/CalWORKs_Payment_Standards/G_CalWORKs_Payment_Standards.pdf + - title: California Department of Social Services, Executive Summary, All County Letter No. 24-55, CalWORKs Payment Standards Chart Effective October 1, 2024 + href: https://cdss.ca.gov/Portals/9/Additional-Resources/Letters-and-Notices/ACLs/2024/24-55.pdf#page=7 - title: California Welfare & Institutions Code Section 11450 href: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=WIC§ionNum=11450. diff --git a/policyengine_us/parameters/gov/states/ca/cdss/tanf/cash/monthly_payment/region1/exempt.yaml b/policyengine_us/parameters/gov/states/ca/cdss/tanf/cash/monthly_payment/region1/exempt.yaml index 9ce385739eb..b190d8440e9 100644 --- a/policyengine_us/parameters/gov/states/ca/cdss/tanf/cash/monthly_payment/region1/exempt.yaml +++ b/policyengine_us/parameters/gov/states/ca/cdss/tanf/cash/monthly_payment/region1/exempt.yaml @@ -9,8 +9,6 @@ metadata: - Household size label: California CalWORKs monthly payment level - exempt map region 1 reference: - - title: County of San Diego CalWORKS Program Guide | CalWORKs Payment Standards Chart - href: https://hhsaprogramguides.sandiegocounty.gov/CalWORKS/44-300/CalWORKs_Payment_Standards/G_CalWORKs_Payment_Standards.pdf - title: California Department of Social Services, Executive Summary, All County Letter No. 24-55, CalWORKs Payment Standards Chart Effective October 1, 2024 href: https://cdss.ca.gov/Portals/9/Additional-Resources/Letters-and-Notices/ACLs/2024/24-55.pdf?ver=2024-08-19-162608-673#page=7 - title: CDSS Historical MAP and MBSAC Since 1971 (Region 1, page 9 of 10) diff --git a/policyengine_us/parameters/gov/states/ca/cdss/tanf/cash/monthly_payment/region1/non_exempt.yaml b/policyengine_us/parameters/gov/states/ca/cdss/tanf/cash/monthly_payment/region1/non_exempt.yaml index ceff29878d0..ff433ab2814 100644 --- a/policyengine_us/parameters/gov/states/ca/cdss/tanf/cash/monthly_payment/region1/non_exempt.yaml +++ b/policyengine_us/parameters/gov/states/ca/cdss/tanf/cash/monthly_payment/region1/non_exempt.yaml @@ -9,8 +9,6 @@ metadata: - Household size label: California CalWORKs monthly payment level - non-exempt map region 1 reference: - - title: County of San Diego CalWORKS Program Guide | CalWORKs Payment Standards Chart - href: https://hhsaprogramguides.sandiegocounty.gov/CalWORKS/44-300/CalWORKs_Payment_Standards/G_CalWORKs_Payment_Standards.pdf - title: California Department of Social Services, Executive Summary, All County Letter No. 24-55, CalWORKs Payment Standards Chart Effective October 1, 2024 href: https://cdss.ca.gov/Portals/9/Additional-Resources/Letters-and-Notices/ACLs/2024/24-55.pdf?ver=2024-08-19-162608-673#page=7 - title: CDSS Historical MAP and MBSAC Since 1971 (Region 1, page 9 of 10) diff --git a/policyengine_us/parameters/gov/states/ca/cdss/tanf/cash/monthly_payment/region2/exempt.yaml b/policyengine_us/parameters/gov/states/ca/cdss/tanf/cash/monthly_payment/region2/exempt.yaml index 03d2c1b9e92..0e382433453 100644 --- a/policyengine_us/parameters/gov/states/ca/cdss/tanf/cash/monthly_payment/region2/exempt.yaml +++ b/policyengine_us/parameters/gov/states/ca/cdss/tanf/cash/monthly_payment/region2/exempt.yaml @@ -9,8 +9,6 @@ metadata: - Household size label: California CalWORKs monthly payment level - exempt map region 2 reference: - - title: County of San Diego CalWORKS Program Guide | CalWORKs Payment Standards Chart - href: https://hhsaprogramguides.sandiegocounty.gov/CalWORKS/44-300/CalWORKs_Payment_Standards/G_CalWORKs_Payment_Standards.pdf - title: California Department of Social Services, Executive Summary, All County Letter No. 24-55, CalWORKs Payment Standards Chart Effective October 1, 2024 href: https://cdss.ca.gov/Portals/9/Additional-Resources/Letters-and-Notices/ACLs/2024/24-55.pdf?ver=2024-08-19-162608-673#page=7 - title: CDSS Historical MAP and MBSAC Since 1971 (Region 2, page 10 of 10) diff --git a/policyengine_us/parameters/gov/states/ca/cdss/tanf/cash/monthly_payment/region2/non_exempt.yaml b/policyengine_us/parameters/gov/states/ca/cdss/tanf/cash/monthly_payment/region2/non_exempt.yaml index e6456f6e626..76631c44f6c 100644 --- a/policyengine_us/parameters/gov/states/ca/cdss/tanf/cash/monthly_payment/region2/non_exempt.yaml +++ b/policyengine_us/parameters/gov/states/ca/cdss/tanf/cash/monthly_payment/region2/non_exempt.yaml @@ -9,8 +9,6 @@ metadata: - Household size label: California CalWORKs monthly payment level - non-exempt map region 2 reference: - - title: County of San Diego CalWORKS Program Guide | CalWORKs Payment Standards Chart - href: https://hhsaprogramguides.sandiegocounty.gov/CalWORKS/44-300/CalWORKs_Payment_Standards/G_CalWORKs_Payment_Standards.pdf - title: California Department of Social Services, Executive Summary, All County Letter No. 24-55, CalWORKs Payment Standards Chart Effective October 1, 2024 href: https://cdss.ca.gov/Portals/9/Additional-Resources/Letters-and-Notices/ACLs/2024/24-55.pdf?ver=2024-08-19-162608-673#page=7 - title: CDSS Historical MAP and MBSAC Since 1971 (Region 2, page 10 of 10) diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/tanf/cash/income/ca_tanf_countable_income_applicant.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/tanf/cash/income/ca_tanf_countable_income_applicant.yaml index bfccb2802bd..bf6c95137f3 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/tanf/cash/income/ca_tanf_countable_income_applicant.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/tanf/cash/income/ca_tanf_countable_income_applicant.yaml @@ -1,100 +1,199 @@ -- name: $1,000 earned, $1,000 disabli disability-based unearned, and $1,000 other unearned. +- name: Case 1, single earner above $450 disregard with unearned income. period: 2023 + absolute_error_margin: 0.01 input: - state_code: CA - ca_tanf_earned_income: 5_412 # 451 monthly - ca_tanf_db_unearned_income: 1_000 - ca_tanf_other_unearned_income: 2_000 + people: + person1: + employment_income: 5_412 + spm_units: + spm_unit: + members: [person1] + ca_tanf_db_unearned_income: 1_000 + ca_tanf_other_unearned_income: 2_000 + households: + household: + members: [person1] + state_code: CA output: + # earned monthly: 451; after disregard: 451 - 450 = 1; yearly: 12 + # total: 12 + 1000 + 2000 = 3012 ca_tanf_countable_income_applicant: 3_012 -- name: Test that the flat $450 disregard is only subtracted (with floor $0) from earned income as opposed to from the total sum. +- name: Case 2, single earner one dollar below $450 disregard with unearned income. period: 2023 + absolute_error_margin: 0.01 input: - state_code: CA - ca_tanf_earned_income: 5_388 # 449 monthly - ca_tanf_db_unearned_income: 1_000 - ca_tanf_other_unearned_income: 2_000 + people: + person1: + employment_income: 5_388 + spm_units: + spm_unit: + members: [person1] + ca_tanf_db_unearned_income: 1_000 + ca_tanf_other_unearned_income: 2_000 + households: + household: + members: [person1] + state_code: CA output: + # earned monthly: 449; after disregard: max(449 - 450, 0) = 0; yearly: 0 + # total: 0 + 1000 + 2000 = 3000 ca_tanf_countable_income_applicant: 3_000 -- name: Test that the flat $450 disregard is only subtracted (with floor $0) from earned income. +- name: Case 3, single earner below disregard with no unearned income. period: 2023 + absolute_error_margin: 0.01 input: - state_code: CA - ca_tanf_earned_income: 5_388 # 449 monthly - ca_tanf_db_unearned_income: 0 - ca_tanf_other_unearned_income: 0 + people: + person1: + employment_income: 5_388 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: CA output: ca_tanf_countable_income_applicant: 0 -- name: Historical 2019 applicant EID is $90 per employed person. +- name: Case 4, historical 2019 applicant EID is $90 per person. period: 2019 + absolute_error_margin: 0.01 input: - state_code: CA - ca_tanf_earned_income: 6_000 - ca_tanf_db_unearned_income: 0 - ca_tanf_other_unearned_income: 0 + people: + person1: + employment_income: 6_000 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: CA output: - # yearly: 6000 - (90 * 12) = 6000 - 1080 = 4920 + # monthly: 500 - 90 = 410; yearly: 4920 ca_tanf_countable_income_applicant: 4_920 -- name: Case 1, earned income exactly at $450/mo disregard. +- name: Case 5, earned income exactly at $450/mo disregard. period: 2025 - absolute_error_margin: 0.1 + absolute_error_margin: 0.01 input: - state_code: CA - ca_tanf_earned_income: 5_400 - ca_tanf_db_unearned_income: 0 - ca_tanf_other_unearned_income: 0 + people: + person1: + employment_income: 5_400 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: CA output: - # yearly: max(5400 - 5400, 0) = 0 + # monthly: max(450 - 450, 0) = 0; yearly: 0 ca_tanf_countable_income_applicant: 0 -- name: Case 2, earned income one dollar above $450/mo disregard. +- name: Case 6, zero income yields zero countable. period: 2025 - absolute_error_margin: 0.1 + absolute_error_margin: 0.01 input: - state_code: CA - ca_tanf_earned_income: 5_412 - ca_tanf_db_unearned_income: 0 - ca_tanf_other_unearned_income: 0 + people: + person1: + employment_income: 0 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: CA output: - # yearly: max(5412 - 5400, 0) = 12 - ca_tanf_countable_income_applicant: 12 + ca_tanf_countable_income_applicant: 0 -- name: Case 3, zero income yields zero countable. +- name: Case 7, only unearned income no disregard applied. period: 2025 - absolute_error_margin: 0.1 + absolute_error_margin: 0.01 input: - state_code: CA - ca_tanf_earned_income: 0 - ca_tanf_db_unearned_income: 0 - ca_tanf_other_unearned_income: 0 + people: + person1: + employment_income: 0 + spm_units: + spm_unit: + members: [person1] + ca_tanf_db_unearned_income: 6_000 + ca_tanf_other_unearned_income: 3_000 + households: + household: + members: [person1] + state_code: CA output: - ca_tanf_countable_income_applicant: 0 + ca_tanf_countable_income_applicant: 9_000 -- name: Case 4, only unearned income no disregard applied. +- name: Case 8, two earners each get $450 disregard per WIC 11450.12. period: 2025 - absolute_error_margin: 0.1 + absolute_error_margin: 0.01 input: - state_code: CA - ca_tanf_earned_income: 0 - ca_tanf_db_unearned_income: 6_000 - ca_tanf_other_unearned_income: 3_000 + people: + person1: + employment_income: 12_000 + person2: + employment_income: 12_000 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA output: - # disregard only applies to earned income - ca_tanf_countable_income_applicant: 9_000 + # person1 monthly: 1000 - 450 = 550; yearly: 6600 + # person2 monthly: 1000 - 450 = 550; yearly: 6600 + # total: 6600 + 6600 = 13200 + ca_tanf_countable_income_applicant: 13_200 + +- name: Case 9, two earners one below disregard. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + employment_income: 12_000 + person2: + employment_income: 2_400 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + output: + # person1 monthly: 1000 - 450 = 550; yearly: 6600 + # person2 monthly: max(200 - 450, 0) = 0; yearly: 0 + # total: 6600 + 0 = 6600 + ca_tanf_countable_income_applicant: 6_600 -- name: Case 5, earned below disregard with unearned income. +- name: Case 10, two earners with unearned income. period: 2025 - absolute_error_margin: 0.1 + absolute_error_margin: 0.01 input: - state_code: CA - ca_tanf_earned_income: 2_400 - ca_tanf_db_unearned_income: 1_200 - ca_tanf_other_unearned_income: 600 + people: + person1: + employment_income: 12_000 + person2: + employment_income: 7_200 + spm_units: + spm_unit: + members: [person1, person2] + ca_tanf_db_unearned_income: 2_400 + ca_tanf_other_unearned_income: 1_200 + households: + household: + members: [person1, person2] + state_code: CA output: - # earned: max(2400 - 5400, 0) = 0 - # total: 0 + 1200 + 600 = 1800 - ca_tanf_countable_income_applicant: 1_800 + # person1 monthly: 1000 - 450 = 550; yearly: 6600 + # person2 monthly: 600 - 450 = 150; yearly: 1800 + # earned total: 6600 + 1800 = 8400 + # total: 8400 + 2400 + 1200 = 12000 + ca_tanf_countable_income_applicant: 12_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/tanf/cash/income/ca_tanf_earned_income_after_disregard_person.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/tanf/cash/income/ca_tanf_earned_income_after_disregard_person.yaml new file mode 100644 index 00000000000..396d640a245 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/tanf/cash/income/ca_tanf_earned_income_after_disregard_person.yaml @@ -0,0 +1,73 @@ +- name: Case 1, earned income above $450 disregard. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + employment_income: 12_000 + households: + household: + members: [person1] + state_code: CA + output: + # monthly: 1000 - 450 = 550 + ca_tanf_earned_income_after_disregard_person: [550] + +- name: Case 2, earned income exactly at $450 disregard. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + employment_income: 5_400 + households: + household: + members: [person1] + state_code: CA + output: + # monthly: 450 - 450 = 0 + ca_tanf_earned_income_after_disregard_person: [0] + +- name: Case 3, earned income below $450 disregard floors at zero. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + employment_income: 2_400 + households: + household: + members: [person1] + state_code: CA + output: + # monthly: max(200 - 450, 0) = 0 + ca_tanf_earned_income_after_disregard_person: [0] + +- name: Case 4, zero earned income. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + employment_income: 0 + households: + household: + members: [person1] + state_code: CA + output: + ca_tanf_earned_income_after_disregard_person: [0] + +- name: Case 5, historical 2019 applicant EID is $90 per person. + period: 2019-01 + absolute_error_margin: 0.01 + input: + people: + person1: + employment_income: 6_000 + households: + household: + members: [person1] + state_code: CA + output: + # monthly: 500 - 90 = 410 + ca_tanf_earned_income_after_disregard_person: [410] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/tanf/cash/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/tanf/cash/integration.yaml index 2401864d246..cc08402ae40 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/tanf/cash/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/tanf/cash/integration.yaml @@ -210,3 +210,55 @@ ca_tanf_recipient_financial_test: true # Benefit: max(8568 - 1650, 0) = 6918 ca_tanf: 6_918 + +- name: Case 6, 2025 R1 non-exempt applicant two-earner family of 4. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 35 + employment_income: 18_000 + immigration_status: CITIZEN + person2: + age: 33 + employment_income: 12_000 + immigration_status: CITIZEN + person3: + age: 10 + immigration_status: CITIZEN + person4: + age: 6 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + is_tanf_enrolled: false + households: + household: + members: [person1, person2, person3, person4] + state_code: CA + ca_tanf_region1: true + tax_units: + tax_unit: + members: [person1, person2, person3, person4] + output: + # Person-level earned income (monthly): + # person1: 18000/12 = 1500; person2: 12000/12 = 1000 + # Per-person applicant disregard ($450 each per WIC 11450.12): + # person1: max(1500 - 450, 0) = 1050; person2: max(1000 - 450, 0) = 550 + # Applicant countable earned (yearly): (1050 + 550) * 12 = 19200 + ca_tanf_countable_income_applicant: 19_200 + # MBSAC: R1 size 4 + ca_tanf_applicant_financial_test: true + # Recipient EID: $600 flat + 50% + # total monthly earned: 1500 + 1000 = 2500 + # max(2500 - 600, 0) * 0.5 = 950; yearly: 11400 + ca_tanf_countable_income_recipient: 11_400 + ca_tanf_recipient_financial_test: true + ca_tanf_financial_eligible: true + ca_tanf_eligible: true + # MAP: R1 non-exempt size 4 = $1416/mo -> 16992/yr + ca_tanf_maximum_payment: 16_992 + # Benefit: max(16992 - 11400, 0) = 5592, all citizens so proration = 1.0 + ca_tanf: 5_592 diff --git a/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/eligibility/ca_tanf_eligible.py b/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/eligibility/ca_tanf_eligible.py index e8b67f53ce2..ed02ac6b07c 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/eligibility/ca_tanf_eligible.py +++ b/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/eligibility/ca_tanf_eligible.py @@ -10,13 +10,13 @@ class ca_tanf_eligible(Variable): def formula(spm_unit, period, parameters): demographic_eligible = spm_unit("is_demographic_tanf_eligible", period) - financial_eligibile = spm_unit("ca_tanf_financial_eligible", period) + financial_eligible = spm_unit("ca_tanf_financial_eligible", period) resources_eligible = spm_unit("ca_tanf_resources_eligible", period) vehicle_value_eligible = spm_unit("ca_tanf_vehicle_value_eligible", period) return ( demographic_eligible - & financial_eligibile + & financial_eligible & resources_eligible & vehicle_value_eligible ) diff --git a/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/eligibility/ca_tanf_maximum_payment.py b/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/eligibility/ca_tanf_maximum_payment.py index a7907f13a16..eb2e7ba234b 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/eligibility/ca_tanf_maximum_payment.py +++ b/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/eligibility/ca_tanf_maximum_payment.py @@ -8,7 +8,7 @@ class ca_tanf_maximum_payment(Variable): unit = USD definition_period = YEAR defined_for = StateCode.CA - reference = "https://hhsaprogramguides.sandiegocounty.gov/CalWORKS/44-300/CalWORKs_Payment_Standards/G_CalWORKs_Payment_Standards.pdf" + reference = "https://cdss.ca.gov/Portals/9/Additional-Resources/Letters-and-Notices/ACLs/2024/24-55.pdf#page=7" def formula(spm_unit, period, parameters): p = parameters(period).gov.states.ca.cdss.tanf.cash.monthly_payment diff --git a/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_countable_income_applicant.py b/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_countable_income_applicant.py index b99d18597c6..2941392cc90 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_countable_income_applicant.py +++ b/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_countable_income_applicant.py @@ -10,14 +10,11 @@ class ca_tanf_countable_income_applicant(Variable): defined_for = StateCode.CA reference = "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=WIC§ionNum=11450.12." - def formula(spm_unit, period, parameters): - # Known simplification: per WIC 11450.12, the $450 disregard - # should be applied per employed person, not as a flat total. - # Current implementation subtracts a single flat amount. - p = parameters(period).gov.states.ca.cdss.tanf.cash.income.disregards.applicant - yearly_disregard = p.flat * MONTHS_IN_YEAR - countable_earned = max_( - spm_unit("ca_tanf_earned_income", period) - yearly_disregard, 0 + def formula(spm_unit, period): + countable_earned = add( + spm_unit, + period, + ["ca_tanf_earned_income_after_disregard_person"], ) db_unearned = spm_unit("ca_tanf_db_unearned_income", period) other_unearned = spm_unit("ca_tanf_other_unearned_income", period) diff --git a/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_countable_income_recipient.py b/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_countable_income_recipient.py index 4bb8968aea9..37d400387f2 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_countable_income_recipient.py +++ b/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_countable_income_recipient.py @@ -18,7 +18,7 @@ def formula(spm_unit, period, parameters): spm_unit("ca_tanf_other_unearned_income", period) ) / MONTHS_IN_YEAR - # Flat exlusion only applies to disability-based unearned income and earned income. + # Flat exclusion only applies to disability-based unearned income and earned income. countable_db_unearned = max_(db_unearned - p.flat, 0) remaining_flat_exclusion = max_(p.flat - db_unearned, 0) countable_earned = max_(earned - remaining_flat_exclusion, 0) * ( diff --git a/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_earned_income.py b/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_earned_income.py index e1d2582658b..0a782516c04 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_earned_income.py +++ b/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_earned_income.py @@ -10,4 +10,4 @@ class ca_tanf_earned_income(Variable): defined_for = StateCode.CA reference = "http://epolicy.dpss.lacounty.gov/epolicy/epolicy/server/general/projects_responsive/ePolicyMaster/index.htm?&area=general&type=responsivehelp&ctxid=&project=ePolicyMaster#t=mergedProjects%2FCalWORKs%2FCalWORKs%2F44-101_Income_Definitions%2F44-101_Income_Definitions.htm%23Definitionsbc-4&rhtocid=_3_1_6_0_3" - adds = "gov.states.ca.cdss.tanf.cash.income.sources.earned" + adds = ["ca_tanf_earned_income_person"] diff --git a/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_earned_income_after_disregard_person.py b/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_earned_income_after_disregard_person.py new file mode 100644 index 00000000000..568fafd913a --- /dev/null +++ b/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_earned_income_after_disregard_person.py @@ -0,0 +1,16 @@ +from policyengine_us.model_api import * + + +class ca_tanf_earned_income_after_disregard_person(Variable): + value_type = float + entity = Person + definition_period = MONTH + label = "California CalWORKs earned income after applicant disregard per person" + unit = USD + defined_for = StateCode.CA + reference = "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=WIC§ionNum=11450.12." + + def formula(person, period, parameters): + p = parameters(period).gov.states.ca.cdss.tanf.cash.income.disregards.applicant + earned = person("ca_tanf_earned_income_person", period) + return max_(earned - p.flat, 0) diff --git a/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_earned_income_person.py b/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_earned_income_person.py new file mode 100644 index 00000000000..68f063c91df --- /dev/null +++ b/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_earned_income_person.py @@ -0,0 +1,13 @@ +from policyengine_us.model_api import * + + +class ca_tanf_earned_income_person(Variable): + value_type = float + entity = Person + definition_period = MONTH + label = "California CalWORKs gross earned income per person" + unit = USD + defined_for = StateCode.CA + reference = "http://epolicy.dpss.lacounty.gov/epolicy/epolicy/server/general/projects_responsive/ePolicyMaster/index.htm?&area=general&type=responsivehelp&ctxid=&project=ePolicyMaster#t=mergedProjects%2FCalWORKs%2FCalWORKs%2F44-101_Income_Definitions%2F44-101_Income_Definitions.htm%23Definitionsbc-4&rhtocid=_3_1_6_0_3" + + adds = "gov.states.ca.cdss.tanf.cash.income.sources.earned" From 577b0a7d54fee1555123ccb5026c4f17199af0c5 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Thu, 26 Mar 2026 22:10:38 -0400 Subject: [PATCH 2/3] Preserve CA TANF aggregate income fallback --- .../ca_tanf_countable_income_applicant.yaml | 23 +++++++++++++++++ .../ca_tanf_countable_income_applicant.py | 25 +++++++++++++++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/tanf/cash/income/ca_tanf_countable_income_applicant.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/tanf/cash/income/ca_tanf_countable_income_applicant.yaml index bf6c95137f3..c5269d45e0e 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/tanf/cash/income/ca_tanf_countable_income_applicant.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/tanf/cash/income/ca_tanf_countable_income_applicant.yaml @@ -197,3 +197,26 @@ # earned total: 6600 + 1800 = 8400 # total: 8400 + 2400 + 1200 = 12000 ca_tanf_countable_income_applicant: 12_000 + +- name: Case 11, direct earned-income input still counts for 2025 debugging scenarios. + period: 2025 + absolute_error_margin: 0.01 + input: + state_code: CA + ca_tanf_earned_income: 12_000 + ca_tanf_db_unearned_income: 2_400 + ca_tanf_other_unearned_income: 1_200 + output: + # legacy aggregate fallback: monthly earned 1000 - 450 = 550; yearly = 6600 + # total: 6600 + 2400 + 1200 = 10200 + ca_tanf_countable_income_applicant: 10_200 + +- name: Case 12, direct earned-income input uses the historical 2020 applicant disregard. + period: 2020 + absolute_error_margin: 0.01 + input: + state_code: CA + ca_tanf_earned_income: 12_000 + output: + # legacy aggregate fallback: monthly earned 1000 - 90 = 910; yearly = 10920 + ca_tanf_countable_income_applicant: 10_920 diff --git a/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_countable_income_applicant.py b/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_countable_income_applicant.py index 2941392cc90..2f7e3d48f6c 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_countable_income_applicant.py +++ b/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_countable_income_applicant.py @@ -10,12 +10,33 @@ class ca_tanf_countable_income_applicant(Variable): defined_for = StateCode.CA reference = "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=WIC§ionNum=11450.12." - def formula(spm_unit, period): - countable_earned = add( + def formula(spm_unit, period, parameters): + countable_earned_from_people = add( spm_unit, period, ["ca_tanf_earned_income_after_disregard_person"], ) + gross_earned = spm_unit("ca_tanf_earned_income", period) + gross_earned_from_people = add( + spm_unit, period, ["ca_tanf_earned_income_person"] + ) + monthly_gross_earned = gross_earned / period.size_in_months + legacy_countable_earned = sum( + max_( + monthly_gross_earned + - parameters(subperiod).gov.states.ca.cdss.tanf.cash.income.disregards.applicant.flat, + 0, + ) + for subperiod in period.get_subperiods(MONTH) + ) + # Preserve per-person disregards for modeled earnings, but keep direct + # aggregate overrides usable in tests/debugging when person inputs are absent + # or intentionally out of sync. + countable_earned = where( + gross_earned != gross_earned_from_people, + legacy_countable_earned, + countable_earned_from_people, + ) db_unearned = spm_unit("ca_tanf_db_unearned_income", period) other_unearned = spm_unit("ca_tanf_other_unearned_income", period) From 5bf4e37a60b844e51a0b275499440376bc1a3512 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Thu, 26 Mar 2026 22:13:35 -0400 Subject: [PATCH 3/3] Format CA TANF review fix --- .../tanf/cash/income/ca_tanf_countable_income_applicant.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_countable_income_applicant.py b/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_countable_income_applicant.py index 2f7e3d48f6c..23ab8ff4b08 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_countable_income_applicant.py +++ b/policyengine_us/variables/gov/states/ca/cdss/tanf/cash/income/ca_tanf_countable_income_applicant.py @@ -24,7 +24,9 @@ def formula(spm_unit, period, parameters): legacy_countable_earned = sum( max_( monthly_gross_earned - - parameters(subperiod).gov.states.ca.cdss.tanf.cash.income.disregards.applicant.flat, + - parameters( + subperiod + ).gov.states.ca.cdss.tanf.cash.income.disregards.applicant.flat, 0, ) for subperiod in period.get_subperiods(MONTH)