From 97736b7f5ad4e6d1e57288752bd9edbeb898b0fd Mon Sep 17 00:00:00 2001 From: Ziming Date: Mon, 1 Jun 2026 11:58:01 -0400 Subject: [PATCH 1/3] Add Orange County General Relief partial screen --- changelog.d/8556.added.md | 1 + .../eligibility/adult_age_threshold.yaml | 11 ++ .../qualified_immigration_status.yaml | 18 +++ .../income/earned_income_deduction_rate.yaml | 11 ++ .../general_relief/income/sources/earned.yaml | 14 ++ .../income/sources/unearned.yaml | 28 ++++ .../resources/home_equity_limit.yaml | 11 ++ .../resources/liquid_resource_disregard.yaml | 11 ++ .../resources/property_limit.yaml | 11 ++ .../resources/vehicle_exclusion.yaml | 11 ++ policyengine_us/programs.yaml | 11 ++ ...al_relief_immigration_status_eligible.yaml | 23 +++ .../gov/local/ca/oc/general_relief/in_oc.yaml | 13 ++ ...eneral_relief_countable_income_person.yaml | 29 ++++ .../ca/oc/general_relief/integration.yaml | 142 ++++++++++++++++++ ...eneral_relief_countable_vehicle_value.yaml | 15 ++ ...eneral_relief_excess_liquid_resources.yaml | 15 ++ ..._oc_general_relief_resources_eligible.yaml | 26 ++++ .../ca_oc_general_relief_eligible.py | 31 ++++ ...ca_oc_general_relief_aided_person_count.py | 10 ++ ..._oc_general_relief_demographic_eligible.py | 15 ++ .../ca_oc_general_relief_eligible_person.py | 25 +++ ...eral_relief_immigration_status_eligible.py | 15 ++ ...l_relief_receives_other_cash_assistance.py | 15 ++ ..._general_relief_countable_earned_income.py | 19 +++ .../ca_oc_general_relief_countable_income.py | 11 ++ ..._general_relief_countable_income_person.py | 41 +++++ ...a_oc_general_relief_gross_earned_income.py | 11 ++ ...oc_general_relief_gross_unearned_income.py | 11 ++ ...eral_relief_countable_personal_property.py | 17 +++ ...ca_oc_general_relief_countable_property.py | 16 ++ ..._general_relief_countable_vehicle_value.py | 21 +++ ..._general_relief_excess_liquid_resources.py | 22 +++ .../ca_oc_general_relief_home_equity.py | 12 ++ ...general_relief_other_real_estate_equity.py | 19 +++ ...ca_oc_general_relief_resources_eligible.py | 21 +++ .../variables/gov/local/ca/oc/in_oc.py | 12 ++ sources/working_references.md | 70 +++++++++ 38 files changed, 815 insertions(+) create mode 100644 changelog.d/8556.added.md create mode 100644 policyengine_us/parameters/gov/local/ca/oc/general_relief/eligibility/adult_age_threshold.yaml create mode 100644 policyengine_us/parameters/gov/local/ca/oc/general_relief/eligibility/qualified_immigration_status.yaml create mode 100644 policyengine_us/parameters/gov/local/ca/oc/general_relief/income/earned_income_deduction_rate.yaml create mode 100644 policyengine_us/parameters/gov/local/ca/oc/general_relief/income/sources/earned.yaml create mode 100644 policyengine_us/parameters/gov/local/ca/oc/general_relief/income/sources/unearned.yaml create mode 100644 policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/home_equity_limit.yaml create mode 100644 policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/liquid_resource_disregard.yaml create mode 100644 policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/property_limit.yaml create mode 100644 policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/vehicle_exclusion.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_immigration_status_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/in_oc.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_countable_income_person.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/integration.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_countable_vehicle_value.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_excess_liquid_resources.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_resources_eligible.yaml create mode 100644 policyengine_us/variables/gov/local/ca/oc/general_relief/ca_oc_general_relief_eligible.py create mode 100644 policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_aided_person_count.py create mode 100644 policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_demographic_eligible.py create mode 100644 policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_eligible_person.py create mode 100644 policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_immigration_status_eligible.py create mode 100644 policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_receives_other_cash_assistance.py create mode 100644 policyengine_us/variables/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_countable_earned_income.py create mode 100644 policyengine_us/variables/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_countable_income.py create mode 100644 policyengine_us/variables/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_countable_income_person.py create mode 100644 policyengine_us/variables/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_gross_earned_income.py create mode 100644 policyengine_us/variables/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_gross_unearned_income.py create mode 100644 policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_countable_personal_property.py create mode 100644 policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_countable_property.py create mode 100644 policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_countable_vehicle_value.py create mode 100644 policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_excess_liquid_resources.py create mode 100644 policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_home_equity.py create mode 100644 policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_other_real_estate_equity.py create mode 100644 policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_resources_eligible.py create mode 100644 policyengine_us/variables/gov/local/ca/oc/in_oc.py create mode 100644 sources/working_references.md diff --git a/changelog.d/8556.added.md b/changelog.d/8556.added.md new file mode 100644 index 00000000000..d8e1458c42d --- /dev/null +++ b/changelog.d/8556.added.md @@ -0,0 +1 @@ +Added a partial Orange County, California General Relief eligibility, income, and resource screen. diff --git a/policyengine_us/parameters/gov/local/ca/oc/general_relief/eligibility/adult_age_threshold.yaml b/policyengine_us/parameters/gov/local/ca/oc/general_relief/eligibility/adult_age_threshold.yaml new file mode 100644 index 00000000000..44d4f8afdda --- /dev/null +++ b/policyengine_us/parameters/gov/local/ca/oc/general_relief/eligibility/adult_age_threshold.yaml @@ -0,0 +1,11 @@ +description: Orange County General Relief limits aid to adults without minor children. +values: + 2022-02-01: 18 + +metadata: + unit: year + period: year + label: Orange County General Relief adult age threshold + reference: + - title: Orange County General Relief regulations, section 10.6.v + href: https://www.ssa.ocgov.com/sites/ssa/files/2026-01/GR%20Reg%20SECTION%2010%20-%20Approved%20-%20January%202026.pdf#page=08 diff --git a/policyengine_us/parameters/gov/local/ca/oc/general_relief/eligibility/qualified_immigration_status.yaml b/policyengine_us/parameters/gov/local/ca/oc/general_relief/eligibility/qualified_immigration_status.yaml new file mode 100644 index 00000000000..7497607aeb4 --- /dev/null +++ b/policyengine_us/parameters/gov/local/ca/oc/general_relief/eligibility/qualified_immigration_status.yaml @@ -0,0 +1,18 @@ +description: Orange County General Relief treats these PolicyEngine immigration statuses as qualified lawful statuses. +values: + 2026-01-01: + - CITIZEN + - LEGAL_PERMANENT_RESIDENT + - REFUGEE + - ASYLEE + - DEPORTATION_WITHHELD + - CUBAN_HAITIAN_ENTRANT + - CONDITIONAL_ENTRANT + +metadata: + unit: list + period: year + label: Orange County General Relief qualified immigration statuses + reference: + - title: Orange County General Relief regulations, section 40.1 + href: https://www.ssa.ocgov.com/sites/ssa/files/2026-01/GR%20Reg%20SECTION%2040%20-%20Approved%20-%20January%202026.pdf#page=01 diff --git a/policyengine_us/parameters/gov/local/ca/oc/general_relief/income/earned_income_deduction_rate.yaml b/policyengine_us/parameters/gov/local/ca/oc/general_relief/income/earned_income_deduction_rate.yaml new file mode 100644 index 00000000000..12b26886b39 --- /dev/null +++ b/policyengine_us/parameters/gov/local/ca/oc/general_relief/income/earned_income_deduction_rate.yaml @@ -0,0 +1,11 @@ +description: Orange County General Relief deducts this share of gross earned income. +values: + 2022-02-01: 0.2 + +metadata: + unit: /1 + period: year + label: Orange County General Relief earned income deduction rate + reference: + - title: Orange County General Relief regulations, section 70.2.o + href: https://www.ssa.ocgov.com/sites/ssa/files/2025-03/Income.pdf#page=04 diff --git a/policyengine_us/parameters/gov/local/ca/oc/general_relief/income/sources/earned.yaml b/policyengine_us/parameters/gov/local/ca/oc/general_relief/income/sources/earned.yaml new file mode 100644 index 00000000000..b2250471e05 --- /dev/null +++ b/policyengine_us/parameters/gov/local/ca/oc/general_relief/income/sources/earned.yaml @@ -0,0 +1,14 @@ +description: Orange County General Relief counts these available earned income sources. +values: + 2024-11-01: + - employment_income + - self_employment_income + - sstb_self_employment_income + +metadata: + unit: list + period: year + label: Orange County General Relief earned income sources + reference: + - title: Orange County General Relief regulations, section 70.2 + href: https://www.ssa.ocgov.com/sites/ssa/files/2025-03/Income.pdf#page=02 diff --git a/policyengine_us/parameters/gov/local/ca/oc/general_relief/income/sources/unearned.yaml b/policyengine_us/parameters/gov/local/ca/oc/general_relief/income/sources/unearned.yaml new file mode 100644 index 00000000000..22453193165 --- /dev/null +++ b/policyengine_us/parameters/gov/local/ca/oc/general_relief/income/sources/unearned.yaml @@ -0,0 +1,28 @@ +description: Orange County General Relief counts these available unearned income sources. +values: + 2024-11-01: + - rental_income + - interest_income + - dividend_income + - social_security + - unemployment_compensation + - ca_state_disability_insurance + - veterans_benefits + - pension_income + - retirement_distributions + - financial_assistance + - educational_assistance + - life_insurance_benefits + - disability_benefits + +metadata: + unit: list + period: year + label: Orange County General Relief unearned income sources + reference: + - title: Orange County General Relief regulations, section 70.2 + href: https://www.ssa.ocgov.com/sites/ssa/files/2025-03/Income.pdf#page=01 + - title: Orange County General Relief regulations, section 70.2.c + href: https://www.ssa.ocgov.com/sites/ssa/files/2025-03/Income.pdf#page=02 + - title: Orange County General Relief regulations, sections 70.2.f through 70.2.l + href: https://www.ssa.ocgov.com/sites/ssa/files/2025-03/Income.pdf#page=03 diff --git a/policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/home_equity_limit.yaml b/policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/home_equity_limit.yaml new file mode 100644 index 00000000000..e13e9da93c4 --- /dev/null +++ b/policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/home_equity_limit.yaml @@ -0,0 +1,11 @@ +description: Orange County General Relief limits the net value of a primary residence to this amount. +values: + 2022-02-01: 5_000 + +metadata: + unit: currency-USD + period: year + label: Orange County General Relief home equity limit + reference: + - title: Orange County General Relief regulations, section 50.2.a + href: https://www.ssa.ocgov.com/sites/ssa/files/2023-04/GR%20Reg%20SECTION%2050%20-%20Approved%20-%20March%202023_0.pdf#page=01 diff --git a/policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/liquid_resource_disregard.yaml b/policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/liquid_resource_disregard.yaml new file mode 100644 index 00000000000..e4d828636d3 --- /dev/null +++ b/policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/liquid_resource_disregard.yaml @@ -0,0 +1,11 @@ +description: Orange County General Relief disregards liquid resources up to this amount when reducing the initial-month grant. +values: + 2012-11-01: 50 + +metadata: + unit: currency-USD + period: year + label: Orange County General Relief liquid resource disregard + reference: + - title: Orange County General Relief regulations, section 60.2.a + href: https://www.ssa.ocgov.com/sites/ssa/files/2023-04/GR%20Reg%20SECTION%2060%20-%20Approved%20-%20March%202023_0.pdf#page=01 diff --git a/policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/property_limit.yaml b/policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/property_limit.yaml new file mode 100644 index 00000000000..58d1b8e6d94 --- /dev/null +++ b/policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/property_limit.yaml @@ -0,0 +1,11 @@ +description: Orange County General Relief limits combined countable secondary real and personal property to this amount. +values: + 2022-02-01: 1_000 + +metadata: + unit: currency-USD + period: year + label: Orange County General Relief countable property limit + reference: + - title: Orange County General Relief regulations, section 50.2.b + href: https://www.ssa.ocgov.com/sites/ssa/files/2023-04/GR%20Reg%20SECTION%2050%20-%20Approved%20-%20March%202023_0.pdf#page=01 diff --git a/policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/vehicle_exclusion.yaml b/policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/vehicle_exclusion.yaml new file mode 100644 index 00000000000..0f219f59d84 --- /dev/null +++ b/policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/vehicle_exclusion.yaml @@ -0,0 +1,11 @@ +description: Orange County General Relief excludes one vehicle per economic unit when its net value does not exceed this amount. +values: + 2012-11-01: 4_650 + +metadata: + unit: currency-USD + period: year + label: Orange County General Relief vehicle exclusion threshold + reference: + - title: Orange County General Relief regulations, section 60.4.b + href: https://www.ssa.ocgov.com/sites/ssa/files/2023-04/GR%20Reg%20SECTION%2060%20-%20Approved%20-%20March%202023_0.pdf#page=02 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index d66185d7f72..47f6eab75e9 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -1285,6 +1285,17 @@ programs: variable: la_general_relief parameter_prefix: gov.local.ca.la.general_relief + - id: ca_oc_general_relief + name: Orange County General Relief + full_name: Orange County General Relief + category: Benefits + agency: Local + status: partial + coverage: Orange County + variable: ca_oc_general_relief_eligible + parameter_prefix: gov.local.ca.oc.general_relief + notes: Eligibility, income, and resource screens only; monthly payment schedule and administrative-history rules are not modeled + - id: ca_riv_general_relief name: Riverside County General Relief full_name: Riverside County General Relief diff --git a/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_immigration_status_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_immigration_status_eligible.yaml new file mode 100644 index 00000000000..57657354b8b --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_immigration_status_eligible.yaml @@ -0,0 +1,23 @@ +- name: A citizen meets the modeled immigration-status rule. + period: 2026-01 + input: + immigration_status: CITIZEN + in_oc: true + output: + ca_oc_general_relief_immigration_status_eligible: true + +- name: An undocumented person does not meet the modeled immigration-status rule. + period: 2026-01 + input: + immigration_status: UNDOCUMENTED + in_oc: true + output: + ca_oc_general_relief_immigration_status_eligible: false + +- name: A person paroled for one year does not meet the manual's indefinite-stay standard. + period: 2026-01 + input: + immigration_status: PAROLED_ONE_YEAR + in_oc: true + output: + ca_oc_general_relief_immigration_status_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/in_oc.yaml b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/in_oc.yaml new file mode 100644 index 00000000000..b3e22784143 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/in_oc.yaml @@ -0,0 +1,13 @@ +- name: Orange County is identified from the county string. + period: 2026 + input: + county_str: ORANGE_COUNTY_CA + output: + in_oc: true + +- name: A different California county is not Orange County. + period: 2026 + input: + county_str: RIVERSIDE_COUNTY_CA + output: + in_oc: false diff --git a/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_countable_income_person.yaml b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_countable_income_person.yaml new file mode 100644 index 00000000000..f2d7679eb8c --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_countable_income_person.yaml @@ -0,0 +1,29 @@ +- name: Countable earned income applies the twenty percent deduction. + period: 2026-01 + input: + employment_income: 1_000 * 12 + in_oc: true + output: + ca_oc_general_relief_gross_earned_income: 1_000 + ca_oc_general_relief_countable_earned_income: 800 + ca_oc_general_relief_countable_income_person: 800 + +- name: Health premiums and court-ordered child support reduce countable income once. + period: 2026-01 + input: + employment_income: 1_000 * 12 + rental_income: 200 * 12 + health_insurance_premiums: 100 * 12 + child_support_expense: 50 * 12 + in_oc: true + output: + ca_oc_general_relief_countable_income_person: 850 + +- name: Income from a person receiving SSI is excluded. + period: 2026-01 + input: + employment_income: 1_000 * 12 + ssi: 100 + in_oc: true + output: + ca_oc_general_relief_countable_income_person: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/integration.yaml b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/integration.yaml new file mode 100644 index 00000000000..9c344fbc5a3 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/integration.yaml @@ -0,0 +1,142 @@ +- name: A single adult citizen with resources below the limits passes the partial screen. + period: 2026-01 + input: + people: + person: + age: 30 + immigration_status: CITIZEN + ssi: 0 + households: + household: + members: [person] + in_oc: true + spm_units: + spm_unit: + members: [person] + ca_tanf: 0 + output: + ca_oc_general_relief_aided_person_count: 1 + ca_oc_general_relief_resources_eligible: true + ca_oc_general_relief_eligible: true + +- name: An undocumented adult does not pass the partial screen. + period: 2026-01 + input: + people: + person: + age: 30 + immigration_status: UNDOCUMENTED + ssi: 0 + households: + household: + members: [person] + in_oc: true + spm_units: + spm_unit: + members: [person] + ca_tanf: 0 + output: + ca_oc_general_relief_aided_person_count: 0 + ca_oc_general_relief_eligible: false + +- name: A unit with a minor child does not pass the partial screen. + period: 2026-01 + input: + people: + adult: + age: 30 + ssi: 0 + child: + age: 10 + ssi: 0 + households: + household: + members: [adult, child] + in_oc: true + spm_units: + spm_unit: + members: [adult, child] + ca_tanf: 0 + output: + ca_oc_general_relief_demographic_eligible: false + ca_oc_general_relief_eligible: false + +- name: A person receiving SSI does not pass the partial screen. + period: 2026-01 + input: + people: + person: + age: 30 + ssi: 100 + households: + household: + members: [person] + in_oc: true + spm_units: + spm_unit: + members: [person] + ca_tanf: 0 + output: + ca_oc_general_relief_receives_other_cash_assistance: true + ca_oc_general_relief_aided_person_count: 0 + ca_oc_general_relief_eligible: false + +- name: A CalWORKs unit does not pass the partial screen. + period: 2026-01 + input: + people: + person: + age: 30 + ssi: 0 + households: + household: + members: [person] + in_oc: true + spm_units: + spm_unit: + members: [person] + ca_tanf: 100 * 12 + output: + ca_oc_general_relief_receives_other_cash_assistance: true + ca_oc_general_relief_aided_person_count: 0 + ca_oc_general_relief_eligible: false + +- name: Property above the limit does not pass the partial screen. + period: 2026-01 + input: + people: + person: + age: 30 + ssi: 0 + personal_property: 1_001 + households: + household: + members: [person] + in_oc: true + spm_units: + spm_unit: + members: [person] + ca_tanf: 0 + output: + ca_oc_general_relief_resources_eligible: false + ca_oc_general_relief_eligible: false + +- name: Income is exposed without changing the partial screen because the MAP schedule is unavailable. + period: 2026-01 + input: + people: + person: + age: 30 + employment_income: 1_000 * 12 + ssi: 0 + households: + household: + members: [person] + in_oc: true + spm_units: + spm_unit: + members: [person] + ca_tanf: 0 + output: + ca_oc_general_relief_countable_income: 800 + ca_oc_general_relief_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_countable_vehicle_value.yaml b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_countable_vehicle_value.yaml new file mode 100644 index 00000000000..2b2ac83dee3 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_countable_vehicle_value.yaml @@ -0,0 +1,15 @@ +- name: Vehicle equity below the exclusion has no countable value. + period: 2026 + input: + household_vehicles_equity: 4_650 + in_oc: true + output: + ca_oc_general_relief_countable_vehicle_value: 0 + +- name: Vehicle equity above the exclusion has countable value. + period: 2026 + input: + household_vehicles_equity: 4_800 + in_oc: true + output: + ca_oc_general_relief_countable_vehicle_value: 4_800 diff --git a/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_excess_liquid_resources.yaml b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_excess_liquid_resources.yaml new file mode 100644 index 00000000000..e04c4fd7b53 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_excess_liquid_resources.yaml @@ -0,0 +1,15 @@ +- name: Liquid resources at the disregard do not reduce an initial-month grant. + period: 2026 + input: + spm_unit_cash_assets: 50 + in_oc: true + output: + ca_oc_general_relief_excess_liquid_resources: 0 + +- name: Liquid resources above the disregard expose the amount available to reduce an initial-month grant. + period: 2026 + input: + spm_unit_cash_assets: 75 + in_oc: true + output: + ca_oc_general_relief_excess_liquid_resources: 25 diff --git a/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_resources_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_resources_eligible.yaml new file mode 100644 index 00000000000..2aac0769cf7 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_resources_eligible.yaml @@ -0,0 +1,26 @@ +- name: Resources at both limits meet the resource screen. + period: 2026-01 + input: + home_equity: 5_000 + personal_property: 1_000 + in_oc: true + output: + ca_oc_general_relief_resources_eligible: true + +- name: Home equity above the primary-residence limit fails the resource screen. + period: 2026-01 + input: + home_equity: 5_001 + in_oc: true + output: + ca_oc_general_relief_resources_eligible: false + +- name: Combined countable property above the property limit fails the resource screen. + period: 2026-01 + input: + personal_property: 500 + household_other_real_estate_equity: 501 + in_oc: true + output: + ca_oc_general_relief_countable_property: 1_001 + ca_oc_general_relief_resources_eligible: false diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/ca_oc_general_relief_eligible.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/ca_oc_general_relief_eligible.py new file mode 100644 index 00000000000..b6e7f6ba24a --- /dev/null +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/ca_oc_general_relief_eligible.py @@ -0,0 +1,31 @@ +from policyengine_us.model_api import * + + +class ca_oc_general_relief_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Partial eligibility screen for Orange County General Relief" + documentation = ( + "Models available demographic, immigration, public assistance, and " + "resource rules. It does not model the income limit, payment amount, " + "or administrative eligibility rules because required Orange County " + "schedules and history inputs are unavailable." + ) + definition_period = MONTH + defined_for = "in_oc" + reference = "https://www.ssa.ocgov.com/page/general-relief-regulations" + + def formula(spm_unit, period, parameters): + demographic_eligible = spm_unit( + "ca_oc_general_relief_demographic_eligible", + period, + ) + resources_eligible = spm_unit( + "ca_oc_general_relief_resources_eligible", + period, + ) + aided_person_count = spm_unit( + "ca_oc_general_relief_aided_person_count", + period, + ) + return demographic_eligible & resources_eligible & (aided_person_count > 0) diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_aided_person_count.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_aided_person_count.py new file mode 100644 index 00000000000..3cad3ba81f1 --- /dev/null +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_aided_person_count.py @@ -0,0 +1,10 @@ +from policyengine_us.model_api import * + + +class ca_oc_general_relief_aided_person_count(Variable): + value_type = int + entity = SPMUnit + label = "Orange County General Relief aided person count" + definition_period = MONTH + defined_for = "in_oc" + adds = ["ca_oc_general_relief_eligible_person"] diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_demographic_eligible.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_demographic_eligible.py new file mode 100644 index 00000000000..051e3054ac6 --- /dev/null +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_demographic_eligible.py @@ -0,0 +1,15 @@ +from policyengine_us.model_api import * + + +class ca_oc_general_relief_demographic_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Meets Orange County General Relief demographic requirements" + definition_period = MONTH + defined_for = "in_oc" + reference = "https://www.ssa.ocgov.com/cash-calfresh/faqs/general-relief" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.local.ca.oc.general_relief.eligibility + age = spm_unit.members("monthly_age", period) + return spm_unit.all(age >= p.adult_age_threshold) diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_eligible_person.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_eligible_person.py new file mode 100644 index 00000000000..a11391cdd3a --- /dev/null +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_eligible_person.py @@ -0,0 +1,25 @@ +from policyengine_us.model_api import * + + +class ca_oc_general_relief_eligible_person(Variable): + value_type = bool + entity = Person + label = "Eligible person for Orange County General Relief" + definition_period = MONTH + defined_for = "in_oc" + reference = "https://www.ssa.ocgov.com/sites/ssa/files/2026-01/GR%20Reg%20SECTION%2020%20-%20Approved%20-%20January%202026.pdf#page=03" + + def formula(person, period, parameters): + p = parameters(period).gov.local.ca.oc.general_relief.eligibility + age_eligible = person("monthly_age", period) >= p.adult_age_threshold + immigration_status_eligible = person( + "ca_oc_general_relief_immigration_status_eligible", + period, + ) + receives_other_cash_assistance = person( + "ca_oc_general_relief_receives_other_cash_assistance", + period, + ) + return ( + age_eligible & immigration_status_eligible & ~receives_other_cash_assistance + ) diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_immigration_status_eligible.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_immigration_status_eligible.py new file mode 100644 index 00000000000..a6635711395 --- /dev/null +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_immigration_status_eligible.py @@ -0,0 +1,15 @@ +from policyengine_us.model_api import * + + +class ca_oc_general_relief_immigration_status_eligible(Variable): + value_type = bool + entity = Person + label = "Eligible for Orange County General Relief due to immigration status" + definition_period = MONTH + defined_for = "in_oc" + reference = "https://www.ssa.ocgov.com/sites/ssa/files/2026-01/GR%20Reg%20SECTION%2040%20-%20Approved%20-%20January%202026.pdf#page=01" + + def formula(person, period, parameters): + p = parameters(period).gov.local.ca.oc.general_relief.eligibility + status = person("immigration_status", period.this_year).decode_to_str() + return np.isin(status, p.qualified_immigration_status) diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_receives_other_cash_assistance.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_receives_other_cash_assistance.py new file mode 100644 index 00000000000..f02c77217c2 --- /dev/null +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_receives_other_cash_assistance.py @@ -0,0 +1,15 @@ +from policyengine_us.model_api import * + + +class ca_oc_general_relief_receives_other_cash_assistance(Variable): + value_type = bool + entity = Person + label = "Receives other cash assistance that excludes Orange County General Relief" + definition_period = MONTH + defined_for = "in_oc" + reference = "https://www.ssa.ocgov.com/sites/ssa/files/2026-01/GR%20Reg%20SECTION%2020%20-%20Approved%20-%20January%202026.pdf#page=03" + + def formula(person, period, parameters): + receives_ssi = person("ssi", period) > 0 + receives_calworks = person.spm_unit("ca_tanf", period) > 0 + return receives_ssi | receives_calworks diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_countable_earned_income.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_countable_earned_income.py new file mode 100644 index 00000000000..c8e1707a455 --- /dev/null +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_countable_earned_income.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class ca_oc_general_relief_countable_earned_income(Variable): + value_type = float + entity = Person + label = "Orange County General Relief countable earned income" + unit = USD + definition_period = MONTH + defined_for = "in_oc" + reference = "https://www.ssa.ocgov.com/sites/ssa/files/2025-03/Income.pdf#page=04" + + def formula(person, period, parameters): + p = parameters(period).gov.local.ca.oc.general_relief.income + gross_earned_income = person( + "ca_oc_general_relief_gross_earned_income", + period, + ) + return max_(gross_earned_income * (1 - p.earned_income_deduction_rate), 0) diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_countable_income.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_countable_income.py new file mode 100644 index 00000000000..06c4c4d3ea9 --- /dev/null +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_countable_income.py @@ -0,0 +1,11 @@ +from policyengine_us.model_api import * + + +class ca_oc_general_relief_countable_income(Variable): + value_type = float + entity = SPMUnit + label = "Orange County General Relief countable income" + unit = USD + definition_period = MONTH + defined_for = "in_oc" + adds = ["ca_oc_general_relief_countable_income_person"] diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_countable_income_person.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_countable_income_person.py new file mode 100644 index 00000000000..83eb7f814fc --- /dev/null +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_countable_income_person.py @@ -0,0 +1,41 @@ +from policyengine_us.model_api import * + + +class ca_oc_general_relief_countable_income_person(Variable): + value_type = float + entity = Person + label = "Orange County General Relief countable income per person" + unit = USD + definition_period = MONTH + defined_for = "in_oc" + reference = ( + "https://www.ssa.ocgov.com/sites/ssa/files/2025-03/Income.pdf#page=04", + "https://www.ssa.ocgov.com/sites/ssa/files/2025-03/Income.pdf#page=05", + ) + + def formula(person, period, parameters): + countable_income = add( + person, + period, + [ + "ca_oc_general_relief_countable_earned_income", + "ca_oc_general_relief_gross_unearned_income", + ], + ) + deductions = add( + person, + period, + [ + "health_insurance_premiums", + "child_support_expense", + ], + ) + receives_other_cash_assistance = person( + "ca_oc_general_relief_receives_other_cash_assistance", + period, + ) + return where( + receives_other_cash_assistance, + 0, + max_(countable_income - deductions, 0), + ) diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_gross_earned_income.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_gross_earned_income.py new file mode 100644 index 00000000000..750ab7efd0c --- /dev/null +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_gross_earned_income.py @@ -0,0 +1,11 @@ +from policyengine_us.model_api import * + + +class ca_oc_general_relief_gross_earned_income(Variable): + value_type = float + entity = Person + label = "Orange County General Relief gross earned income" + unit = USD + definition_period = MONTH + defined_for = "in_oc" + adds = "gov.local.ca.oc.general_relief.income.sources.earned" diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_gross_unearned_income.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_gross_unearned_income.py new file mode 100644 index 00000000000..11c5acd3d90 --- /dev/null +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_gross_unearned_income.py @@ -0,0 +1,11 @@ +from policyengine_us.model_api import * + + +class ca_oc_general_relief_gross_unearned_income(Variable): + value_type = float + entity = Person + label = "Orange County General Relief gross unearned income" + unit = USD + definition_period = MONTH + defined_for = "in_oc" + adds = "gov.local.ca.oc.general_relief.income.sources.unearned" diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_countable_personal_property.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_countable_personal_property.py new file mode 100644 index 00000000000..670fbf87a43 --- /dev/null +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_countable_personal_property.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class ca_oc_general_relief_countable_personal_property(Variable): + value_type = float + entity = SPMUnit + label = "Orange County General Relief countable personal property" + documentation = ( + "Uses available personal-property inputs. PolicyEngine does not " + "separate all Orange County regulatory exclusions, including " + "household effects and burial reserves." + ) + unit = USD + quantity_type = STOCK + definition_period = YEAR + defined_for = "in_oc" + adds = ["personal_property"] diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_countable_property.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_countable_property.py new file mode 100644 index 00000000000..b5c59c452c4 --- /dev/null +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_countable_property.py @@ -0,0 +1,16 @@ +from policyengine_us.model_api import * + + +class ca_oc_general_relief_countable_property(Variable): + value_type = float + entity = SPMUnit + label = "Orange County General Relief countable property" + unit = USD + quantity_type = STOCK + definition_period = YEAR + defined_for = "in_oc" + adds = [ + "ca_oc_general_relief_countable_personal_property", + "ca_oc_general_relief_other_real_estate_equity", + "ca_oc_general_relief_countable_vehicle_value", + ] diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_countable_vehicle_value.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_countable_vehicle_value.py new file mode 100644 index 00000000000..5926b281627 --- /dev/null +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_countable_vehicle_value.py @@ -0,0 +1,21 @@ +from policyengine_us.model_api import * + + +class ca_oc_general_relief_countable_vehicle_value(Variable): + value_type = float + entity = SPMUnit + label = "Orange County General Relief countable vehicle value" + documentation = ( + "Uses total household vehicle equity as a proxy for the net value of one " + "vehicle per Orange County General Relief economic unit." + ) + unit = USD + quantity_type = STOCK + definition_period = YEAR + defined_for = "in_oc" + reference = "https://www.ssa.ocgov.com/sites/ssa/files/2023-04/GR%20Reg%20SECTION%2060%20-%20Approved%20-%20March%202023_0.pdf#page=02" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.local.ca.oc.general_relief.resources + vehicle_equity = spm_unit.household("household_vehicles_equity", period) + return where(vehicle_equity <= p.vehicle_exclusion, 0, vehicle_equity) diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_excess_liquid_resources.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_excess_liquid_resources.py new file mode 100644 index 00000000000..5686a979d1a --- /dev/null +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_excess_liquid_resources.py @@ -0,0 +1,22 @@ +from policyengine_us.model_api import * + + +class ca_oc_general_relief_excess_liquid_resources(Variable): + value_type = float + entity = SPMUnit + label = "Orange County General Relief excess liquid resources" + documentation = ( + "Amount available to reduce an initial-month grant. The ordinary " + "monthly payment is not modeled because Orange County's MAP schedule " + "is not publicly available." + ) + unit = USD + quantity_type = STOCK + definition_period = YEAR + defined_for = "in_oc" + reference = "https://www.ssa.ocgov.com/sites/ssa/files/2023-04/GR%20Reg%20SECTION%2060%20-%20Approved%20-%20March%202023_0.pdf#page=01" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.local.ca.oc.general_relief.resources + liquid_resources = spm_unit("spm_unit_cash_assets", period) + return max_(liquid_resources - p.liquid_resource_disregard, 0) diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_home_equity.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_home_equity.py new file mode 100644 index 00000000000..12aa9dd1bfd --- /dev/null +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_home_equity.py @@ -0,0 +1,12 @@ +from policyengine_us.model_api import * + + +class ca_oc_general_relief_home_equity(Variable): + value_type = float + entity = SPMUnit + label = "Orange County General Relief home equity" + unit = USD + quantity_type = STOCK + definition_period = YEAR + defined_for = "in_oc" + adds = ["home_equity"] diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_other_real_estate_equity.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_other_real_estate_equity.py new file mode 100644 index 00000000000..1d1af8cded9 --- /dev/null +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_other_real_estate_equity.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class ca_oc_general_relief_other_real_estate_equity(Variable): + value_type = float + entity = SPMUnit + label = "Orange County General Relief other real estate equity" + documentation = ( + "Uses available household other-real-estate equity. PolicyEngine does " + "not identify secondary real property that the unit is making a good " + "faith effort to sell." + ) + unit = USD + quantity_type = STOCK + definition_period = YEAR + defined_for = "in_oc" + + def formula(spm_unit, period, parameters): + return spm_unit.household("household_other_real_estate_equity", period) diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_resources_eligible.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_resources_eligible.py new file mode 100644 index 00000000000..306cec47b39 --- /dev/null +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_resources_eligible.py @@ -0,0 +1,21 @@ +from policyengine_us.model_api import * + + +class ca_oc_general_relief_resources_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Meets Orange County General Relief resource requirements" + definition_period = MONTH + defined_for = "in_oc" + reference = "https://www.ssa.ocgov.com/sites/ssa/files/2023-04/GR%20Reg%20SECTION%2050%20-%20Approved%20-%20March%202023_0.pdf#page=01" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.local.ca.oc.general_relief.resources + home_equity = spm_unit("ca_oc_general_relief_home_equity", period.this_year) + property_value = spm_unit( + "ca_oc_general_relief_countable_property", + period.this_year, + ) + return (home_equity <= p.home_equity_limit) & ( + property_value <= p.property_limit + ) diff --git a/policyengine_us/variables/gov/local/ca/oc/in_oc.py b/policyengine_us/variables/gov/local/ca/oc/in_oc.py new file mode 100644 index 00000000000..fee554c8258 --- /dev/null +++ b/policyengine_us/variables/gov/local/ca/oc/in_oc.py @@ -0,0 +1,12 @@ +from policyengine_us.model_api import * + + +class in_oc(Variable): + value_type = bool + entity = Household + definition_period = YEAR + label = "Is in Orange County" + + def formula(household, period, parameters): + county = household("county_str", period) + return county == "ORANGE_COUNTY_CA" diff --git a/sources/working_references.md b/sources/working_references.md new file mode 100644 index 00000000000..bdcde704a38 --- /dev/null +++ b/sources/working_references.md @@ -0,0 +1,70 @@ +# Orange County General Relief working references + +## Program + +- Program: Orange County, California General Relief (GR). +- Variable prefix: `ca_oc_general_relief`. +- Parameter prefix: `gov.local.ca.oc.general_relief`. +- Registry status: `partial`. +- Official regulations index: https://www.ssa.ocgov.com/page/general-relief-regulations +- Official FAQ: https://www.ssa.ocgov.com/cash-calfresh/faqs/general-relief +- User-provided consolidated manual: `/Users/ziminghua/Downloads/GR Regulation Manual.pdf` +- Consolidated manual SHA-256: `2a9f4e5be086106b73f6b22abb55127461bdec873164b0671e81fc42b8bb47d7` +- Consolidated manual metadata: Orange County Social Services Agency, created March 19, 2026, 58 PDF pages. +- Extraction: `/tmp/ca-oc-general-relief-docs/manual-text/gr-regulation-manual.txt` +- Rendered pages: `/tmp/ca-oc-general-relief-docs/manual-rendered/page-01.png` through `page-58.png` + +## Official PDF references + +- Section 10, Introduction: + https://www.ssa.ocgov.com/sites/ssa/files/2026-01/GR%20Reg%20SECTION%2010%20-%20Approved%20-%20January%202026.pdf#page=01 +- Section 20, Eligibility Determination: + https://www.ssa.ocgov.com/sites/ssa/files/2026-01/GR%20Reg%20SECTION%2020%20-%20Approved%20-%20January%202026.pdf#page=01 +- Section 30, Program Requirements and Penalties: + https://www.ssa.ocgov.com/sites/ssa/files/2026-01/GR%20Reg%20SECTION%2030%20-%20Approved%20-%20January%202026.pdf#page=01 +- Section 40, Residence: + https://www.ssa.ocgov.com/sites/ssa/files/2026-01/GR%20Reg%20SECTION%2040%20-%20Approved%20-%20January%202026.pdf#page=01 +- Section 50, Real Property: + https://www.ssa.ocgov.com/sites/ssa/files/2023-04/GR%20Reg%20SECTION%2050%20-%20Approved%20-%20March%202023_0.pdf#page=01 +- Section 60, Personal Property: + https://www.ssa.ocgov.com/sites/ssa/files/2023-04/GR%20Reg%20SECTION%2060%20-%20Approved%20-%20March%202023_0.pdf#page=01 +- Section 70, Income: + https://www.ssa.ocgov.com/sites/ssa/files/2025-03/Income.pdf#page=01 +- Section 80, Benefits and Services: + https://www.ssa.ocgov.com/sites/ssa/files/2025-03/Benefits_Services.pdf#page=01 +- Section 90, Responsible Relatives: + https://www.ssa.ocgov.com/sites/ssa/files/2023-04/GR%20Reg%20SECTION%2090%20-%20Approved%20-%20March%202023_0.pdf#page=01 + +## Verified simulatable rules + +- GR is a residual relief program for people ineligible for federal or state cash aid programs. Section 10.3, PDF page 01. +- A GR economic unit (GR-EU) includes people living together who are legally and/or economically dependent. Section 10.6.j, PDF page 05. +- The FAQ describes the target population as eligible indigent adult lawful residents without custody of minor children. +- Recipients of SSI/SSP, CalWORKs, and Refugee Cash Assistance are excluded members of the GR-EU. Section 20.4.b, PDF page 03. +- County residence requires 15 consecutive calendar days immediately before application. Section 40.2, PDF page 01. +- Eligible immigration pathways include U.S. citizens, permanent legal residents, people granted an indefinite stay from deportation, and qualifying victims of trafficking, domestic violence, and other serious crimes. Temporary visa holders and undocumented non-citizens are ineligible. Section 40.1, PDF page 01. +- Primary-residence real property is limited to $5,000 net value. Combined countable secondary real and personal property is limited to $1,000. Section 50.2, PDF page 01. +- Cash or liquid resources over $50 reduce the initial-month grant. Section 60.2.a, PDF page 01. +- Personal-property exclusions include household furniture and personal effects up to $500, one vehicle per EU with net value up to $4,650, and qualifying burial reserves up to $1,000. Section 60.4, PDF page 02. +- Current income includes earned income, countable grants or gifts, certain loans, rental income, lump sums, retirement withdrawals, and 10% of roomer or boarder payments. Energy assistance and qualifying reimbursements are excluded. Section 70.2, PDF pages 01-03. +- Net earned income deducts 20% of gross earnings, medical insurance payments, and verified court-ordered support actually paid. Section 70.2.o, PDF page 04. +- Net unearned income deducts medical insurance payments, verified court-ordered support actually paid, and mandatory federal or state income tax deductions. Section 70.2.p, PDF page 04. +- Financial eligibility subtracts current net income from the maximum aid payment (MAP). Section 80.2.d, PDF page 02. +- MAP excludes children and other excluded members. Section 80.2.d, PDF page 02. +- CalWORKs or RCA recipient members use a difference-of-MAP method; other excluded members use the MAP for eligible GR-EU members. Section 80.3.a, PDF page 04. +- Shared housing reduces MAP by 15% for one unrelated person, 20% for two unrelated people, and 25% for three or more unrelated people. Section 80.3.a.3, PDF page 04. +- Housing and utility expenses are allowed up to the housing and utility component value. Homeless people receive the full housing and utility component value. Section 80.3.b.1, PDF page 05. +- Food, transportation, and clothing component values are deducted only when the entire component is provided at no cost. CalFresh receipt does not reduce the food component value. Section 80.3.b.1, PDF page 05. +- Employable participants are limited to 90 days of GR benefits in any 12-month period. Section 30.7.c, PDF page 05. + +## Important missing source + +The official regulations define the regular monthly benefit formula but do not publish: + +- the regular MAP table by eligible GR-EU size; +- the housing and utility component values; +- the food component values; +- the transportation component values; +- the clothing component values. + +These values are required to calculate the ordinary monthly GR benefit. Request an official Orange County companion schedule, procedure, or current eligibility handbook before implementing the full payment calculation. From 37370babb14abfe9702f744315bb3e03f7a79eb2 Mon Sep 17 00:00:00 2001 From: Ziming Date: Mon, 1 Jun 2026 15:24:19 -0400 Subject: [PATCH 2/3] Refine Orange County General Relief partial screen - Restore the no-minor-child eligibility restriction with its regulatory basis (Sec 20 must-apply-for-available-aid -> ineligibility, Sec 80.2.d CalWORKs time-limit MAP exclusion, Sec 20.4.b excluded members); families with minor children are routed to CalWORKs, so the parent cannot also receive GR. - Exclude CAPI recipients from General Relief (Sec 20.4.b 'another type of public assistance'); catches recently-arrived aged/disabled permanent residents who receive CAPI instead of SSI. - Trim qualified immigration statuses to those enumerated in Sec 40.1 (citizen, permanent resident, deportation-withheld). - Fix three resource-parameter subsection citations (60.4.b->60.4.c, 50.2.a and 50.2.b -> 50.2). - Document RCA and unearned-income tax deductions as not tracked; replace deprecated documentation fields with inline comments. - Drive program receipt (SSI/CalWORKs/CAPI) from real family inputs in tests instead of program values; add eligibility-map integration cases. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../qualified_immigration_status.yaml | 4 -- .../resources/home_equity_limit.yaml | 2 +- .../resources/property_limit.yaml | 2 +- .../resources/vehicle_exclusion.yaml | 2 +- ...c_general_relief_demographic_eligible.yaml | 35 ++++++++++ .../ca_oc_general_relief_eligible_person.yaml | 51 ++++++++++++++ ...al_relief_immigration_status_eligible.yaml | 24 +++++++ ...relief_receives_other_cash_assistance.yaml | 45 +++++++++++++ ...eneral_relief_countable_earned_income.yaml | 24 +++++++ .../ca/oc/general_relief/integration.yaml | 67 +++++++++++++++++-- ...neral_relief_other_real_estate_equity.yaml | 7 ++ .../ca_oc_general_relief_eligible.py | 10 ++- ..._oc_general_relief_demographic_eligible.py | 14 +++- ...eral_relief_immigration_status_eligible.py | 4 ++ ...l_relief_receives_other_cash_assistance.py | 14 +++- ..._general_relief_countable_income_person.py | 4 ++ ...eral_relief_countable_personal_property.py | 8 +-- ..._general_relief_countable_vehicle_value.py | 6 +- ..._general_relief_excess_liquid_resources.py | 8 +-- ...general_relief_other_real_estate_equity.py | 7 +- 20 files changed, 297 insertions(+), 41 deletions(-) create mode 100644 policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_demographic_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_eligible_person.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_receives_other_cash_assistance.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_countable_earned_income.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_other_real_estate_equity.yaml diff --git a/policyengine_us/parameters/gov/local/ca/oc/general_relief/eligibility/qualified_immigration_status.yaml b/policyengine_us/parameters/gov/local/ca/oc/general_relief/eligibility/qualified_immigration_status.yaml index 7497607aeb4..e1093132902 100644 --- a/policyengine_us/parameters/gov/local/ca/oc/general_relief/eligibility/qualified_immigration_status.yaml +++ b/policyengine_us/parameters/gov/local/ca/oc/general_relief/eligibility/qualified_immigration_status.yaml @@ -3,11 +3,7 @@ values: 2026-01-01: - CITIZEN - LEGAL_PERMANENT_RESIDENT - - REFUGEE - - ASYLEE - DEPORTATION_WITHHELD - - CUBAN_HAITIAN_ENTRANT - - CONDITIONAL_ENTRANT metadata: unit: list diff --git a/policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/home_equity_limit.yaml b/policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/home_equity_limit.yaml index e13e9da93c4..9fa351a7efa 100644 --- a/policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/home_equity_limit.yaml +++ b/policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/home_equity_limit.yaml @@ -7,5 +7,5 @@ metadata: period: year label: Orange County General Relief home equity limit reference: - - title: Orange County General Relief regulations, section 50.2.a + - title: Orange County General Relief regulations, section 50.2 href: https://www.ssa.ocgov.com/sites/ssa/files/2023-04/GR%20Reg%20SECTION%2050%20-%20Approved%20-%20March%202023_0.pdf#page=01 diff --git a/policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/property_limit.yaml b/policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/property_limit.yaml index 58d1b8e6d94..727dea4feb5 100644 --- a/policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/property_limit.yaml +++ b/policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/property_limit.yaml @@ -7,5 +7,5 @@ metadata: period: year label: Orange County General Relief countable property limit reference: - - title: Orange County General Relief regulations, section 50.2.b + - title: Orange County General Relief regulations, section 50.2 href: https://www.ssa.ocgov.com/sites/ssa/files/2023-04/GR%20Reg%20SECTION%2050%20-%20Approved%20-%20March%202023_0.pdf#page=01 diff --git a/policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/vehicle_exclusion.yaml b/policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/vehicle_exclusion.yaml index 0f219f59d84..528237aa16c 100644 --- a/policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/vehicle_exclusion.yaml +++ b/policyengine_us/parameters/gov/local/ca/oc/general_relief/resources/vehicle_exclusion.yaml @@ -7,5 +7,5 @@ metadata: period: year label: Orange County General Relief vehicle exclusion threshold reference: - - title: Orange County General Relief regulations, section 60.4.b + - title: Orange County General Relief regulations, section 60.4.c href: https://www.ssa.ocgov.com/sites/ssa/files/2023-04/GR%20Reg%20SECTION%2060%20-%20Approved%20-%20March%202023_0.pdf#page=02 diff --git a/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_demographic_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_demographic_eligible.yaml new file mode 100644 index 00000000000..a03abe3b29c --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_demographic_eligible.yaml @@ -0,0 +1,35 @@ +- name: A unit of only adults meets the demographic requirement. + period: 2026-01 + input: + people: + adult1: + age: 30 + adult2: + age: 45 + households: + household: + members: [adult1, adult2] + in_oc: true + spm_units: + spm_unit: + members: [adult1, adult2] + output: + ca_oc_general_relief_demographic_eligible: true + +- name: A unit containing a minor child does not meet the demographic requirement. + period: 2026-01 + input: + people: + adult: + age: 30 + child: + age: 10 + households: + household: + members: [adult, child] + in_oc: true + spm_units: + spm_unit: + members: [adult, child] + output: + ca_oc_general_relief_demographic_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_eligible_person.yaml b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_eligible_person.yaml new file mode 100644 index 00000000000..1893888817d --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_eligible_person.yaml @@ -0,0 +1,51 @@ +- name: An adult citizen not on other assistance is an eligible person. + period: 2026-01 + input: + age: 30 + immigration_status: CITIZEN + county_str: ORANGE_COUNTY_CA + state_code: CA + output: + ca_oc_general_relief_eligible_person: true + +- name: A person below the adult age threshold is not an eligible person. + period: 2026-01 + input: + age: 17 + immigration_status: CITIZEN + county_str: ORANGE_COUNTY_CA + state_code: CA + output: + ca_oc_general_relief_eligible_person: false + +- name: A person at the adult age threshold is an eligible person. + period: 2026-01 + input: + age: 18 + immigration_status: CITIZEN + county_str: ORANGE_COUNTY_CA + state_code: CA + output: + ca_oc_general_relief_eligible_person: true + +- name: An undocumented adult is not an eligible person. + period: 2026-01 + input: + age: 30 + immigration_status: UNDOCUMENTED + county_str: ORANGE_COUNTY_CA + state_code: CA + output: + ca_oc_general_relief_eligible_person: false + +- name: A disabled adult who receives SSI is not an eligible person. + period: 2026-01 + input: + age: 30 + immigration_status: CITIZEN + is_disabled: true + meets_ssi_disability_criteria: true + county_str: ORANGE_COUNTY_CA + state_code: CA + output: + ca_oc_general_relief_eligible_person: false diff --git a/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_immigration_status_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_immigration_status_eligible.yaml index 57657354b8b..92d59271154 100644 --- a/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_immigration_status_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_immigration_status_eligible.yaml @@ -21,3 +21,27 @@ in_oc: true output: ca_oc_general_relief_immigration_status_eligible: false + +- name: A permanent legal resident meets the modeled immigration-status rule. + period: 2026-01 + input: + immigration_status: LEGAL_PERMANENT_RESIDENT + in_oc: true + output: + ca_oc_general_relief_immigration_status_eligible: true + +- name: A person granted an indefinite stay from deportation meets the modeled rule. + period: 2026-01 + input: + immigration_status: DEPORTATION_WITHHELD + in_oc: true + output: + ca_oc_general_relief_immigration_status_eligible: true + +- name: A refugee is not in the regulation's enumerated eligible list. + period: 2026-01 + input: + immigration_status: REFUGEE + in_oc: true + output: + ca_oc_general_relief_immigration_status_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_receives_other_cash_assistance.yaml b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_receives_other_cash_assistance.yaml new file mode 100644 index 00000000000..020358bf597 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_receives_other_cash_assistance.yaml @@ -0,0 +1,45 @@ +# Inputs describe the family (age, disability, immigration, work history); +# the model computes whether they receive SSI / CalWORKs / CAPI. +- name: An able-bodied adult with modest earnings receives no other cash assistance. + period: 2026-01 + input: + age: 30 + immigration_status: CITIZEN + employment_income: 6_000 + county_str: ORANGE_COUNTY_CA + state_code: CA + output: + ca_oc_general_relief_receives_other_cash_assistance: false + +- name: A disabled adult with no income receives SSI. + period: 2026-01 + input: + age: 30 + immigration_status: CITIZEN + is_disabled: true + meets_ssi_disability_criteria: true + county_str: ORANGE_COUNTY_CA + state_code: CA + output: + ca_oc_general_relief_receives_other_cash_assistance: true + +- name: An aged adult with no income receives SSI. + period: 2026-01 + input: + age: 70 + immigration_status: CITIZEN + county_str: ORANGE_COUNTY_CA + state_code: CA + output: + ca_oc_general_relief_receives_other_cash_assistance: true + +- name: A recently arrived aged permanent resident without work history receives CAPI. + period: 2026-01 + input: + age: 70 + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 0 + county_str: ORANGE_COUNTY_CA + state_code: CA + output: + ca_oc_general_relief_receives_other_cash_assistance: true diff --git a/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_countable_earned_income.yaml new file mode 100644 index 00000000000..64d54645c6e --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_countable_earned_income.yaml @@ -0,0 +1,24 @@ +- name: Countable earned income applies the twenty percent deduction. + period: 2026-01 + input: + employment_income: 1_000 * 12 + in_oc: true + output: + ca_oc_general_relief_gross_earned_income: 1_000 + ca_oc_general_relief_countable_earned_income: 800 + +- name: Zero earned income produces zero countable earned income. + period: 2026-01 + input: + in_oc: true + output: + ca_oc_general_relief_countable_earned_income: 0 + +- name: Negative self-employment income does not reduce countable earned income below zero. + period: 2026-01 + input: + self_employment_income: -1_000 * 12 + in_oc: true + output: + ca_oc_general_relief_gross_earned_income: -1_000 + ca_oc_general_relief_countable_earned_income: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/integration.yaml b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/integration.yaml index 9c344fbc5a3..2776334a791 100644 --- a/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/integration.yaml @@ -45,19 +45,17 @@ people: adult: age: 30 - ssi: 0 child: age: 10 - ssi: 0 households: household: members: [adult, child] - in_oc: true - spm_units: - spm_unit: - members: [adult, child] - ca_tanf: 0 + county_str: ORANGE_COUNTY_CA + state_code: CA output: + # General Relief aids adults without minor children; a family with a child + # is routed to CalWORKs (Sec 20 must-apply, Sec 20.4.b, Sec 80.2.d), so the + # parent cannot also receive GR. ca_oc_general_relief_demographic_eligible: false ca_oc_general_relief_eligible: false @@ -140,3 +138,58 @@ output: ca_oc_general_relief_countable_income: 800 ca_oc_general_relief_eligible: true + +# Mapping the eligible population from real family inputs: only able-bodied, +# childless, qualified-immigration adults with low assets pass the screen. +- name: An able-bodied childless citizen adult with low assets passes the partial screen. + period: 2026-01 + input: + people: + person: + age: 30 + immigration_status: CITIZEN + households: + household: + members: [person] + county_str: ORANGE_COUNTY_CA + state_code: CA + output: + ca_oc_general_relief_receives_other_cash_assistance: false + ca_oc_general_relief_eligible: true + +- name: A disabled adult receives SSI and so does not pass the partial screen. + period: 2026-01 + input: + people: + person: + age: 30 + immigration_status: CITIZEN + is_disabled: true + meets_ssi_disability_criteria: true + households: + household: + members: [person] + county_str: ORANGE_COUNTY_CA + state_code: CA + output: + ca_oc_general_relief_receives_other_cash_assistance: true + ca_oc_general_relief_eligible: false + +- name: A recently arrived aged permanent resident receives CAPI and so does not pass the partial screen. + period: 2026-01 + input: + people: + person: + age: 70 + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 0 + households: + household: + members: [person] + county_str: ORANGE_COUNTY_CA + state_code: CA + output: + # No SSI (not an SSI-qualified noncitizen), but receives CAPI, which is an + # excluded "other type of public assistance" under Sec 20.4.b. + ca_oc_general_relief_receives_other_cash_assistance: true + ca_oc_general_relief_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_other_real_estate_equity.yaml b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_other_real_estate_equity.yaml new file mode 100644 index 00000000000..c61557a8cb9 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_other_real_estate_equity.yaml @@ -0,0 +1,7 @@ +- name: Other real estate equity uses the household value. + period: 2026 + input: + household_other_real_estate_equity: 700 + in_oc: true + output: + ca_oc_general_relief_other_real_estate_equity: 700 diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/ca_oc_general_relief_eligible.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/ca_oc_general_relief_eligible.py index b6e7f6ba24a..13706f5ede8 100644 --- a/policyengine_us/variables/gov/local/ca/oc/general_relief/ca_oc_general_relief_eligible.py +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/ca_oc_general_relief_eligible.py @@ -5,17 +5,15 @@ class ca_oc_general_relief_eligible(Variable): value_type = bool entity = SPMUnit label = "Partial eligibility screen for Orange County General Relief" - documentation = ( - "Models available demographic, immigration, public assistance, and " - "resource rules. It does not model the income limit, payment amount, " - "or administrative eligibility rules because required Orange County " - "schedules and history inputs are unavailable." - ) definition_period = MONTH defined_for = "in_oc" reference = "https://www.ssa.ocgov.com/page/general-relief-regulations" def formula(spm_unit, period, parameters): + # Partial screen: models demographic (adults without minor children), + # immigration, public-assistance, and resource rules. The income limit + # and MAP payment amount are not modeled because Orange County does not + # publish the MAP schedule. demographic_eligible = spm_unit( "ca_oc_general_relief_demographic_eligible", period, diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_demographic_eligible.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_demographic_eligible.py index 051e3054ac6..add5f10f9be 100644 --- a/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_demographic_eligible.py +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_demographic_eligible.py @@ -7,9 +7,21 @@ class ca_oc_general_relief_demographic_eligible(Variable): label = "Meets Orange County General Relief demographic requirements" definition_period = MONTH defined_for = "in_oc" - reference = "https://www.ssa.ocgov.com/cash-calfresh/faqs/general-relief" + reference = ( + "https://www.ssa.ocgov.com/cash-calfresh/faqs/general-relief", + "https://www.ssa.ocgov.com/sites/ssa/files/2025-03/Benefits_Services.pdf#page=02", + ) def formula(spm_unit, period, parameters): + # General Relief aids adults without minor children. A unit with a minor + # child is effectively routed to CalWORKs, and the parent cannot also + # receive GR: the unit must apply for any aid it appears eligible for or + # be ineligible (Sec 20, "Failure ... to apply for any aid ... results + # in ineligibility"); a parent receiving CalWORKs is an excluded member + # (Sec 20.4.b); and a parent who has exhausted the CalWORKs time limit + # is excluded from the GR MAP until all children turn 18 (Sec 80.2.d). + # So no realistic family has a child on CalWORKs and that child's parent + # on GR. The rare non-parent-caretaker case is not modeled. p = parameters(period).gov.local.ca.oc.general_relief.eligibility age = spm_unit.members("monthly_age", period) return spm_unit.all(age >= p.adult_age_threshold) diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_immigration_status_eligible.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_immigration_status_eligible.py index a6635711395..be10de1de66 100644 --- a/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_immigration_status_eligible.py +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_immigration_status_eligible.py @@ -10,6 +10,10 @@ class ca_oc_general_relief_immigration_status_eligible(Variable): reference = "https://www.ssa.ocgov.com/sites/ssa/files/2026-01/GR%20Reg%20SECTION%2040%20-%20Approved%20-%20January%202026.pdf#page=01" def formula(person, period, parameters): + # NOTE: Section 40.1 also makes victims of trafficking, domestic + # violence, and other serious crimes (T/U-visa, VAWA) eligible, but + # PolicyEngine's ImmigrationStatus enum has no value for that pathway, + # so we don't track it at the moment. p = parameters(period).gov.local.ca.oc.general_relief.eligibility status = person("immigration_status", period.this_year).decode_to_str() return np.isin(status, p.qualified_immigration_status) diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_receives_other_cash_assistance.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_receives_other_cash_assistance.py index f02c77217c2..d2633162b3c 100644 --- a/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_receives_other_cash_assistance.py +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/eligibility/ca_oc_general_relief_receives_other_cash_assistance.py @@ -10,6 +10,18 @@ class ca_oc_general_relief_receives_other_cash_assistance(Variable): reference = "https://www.ssa.ocgov.com/sites/ssa/files/2026-01/GR%20Reg%20SECTION%2020%20-%20Approved%20-%20January%202026.pdf#page=03" def formula(person, period, parameters): + # Section 20.4.b excludes recipients of "another type of public + # assistance (SSI/SSP, CalWORKs, Refugee Cash Assistance (RCA))"; the + # list is non-exhaustive ("include but are not limited to"), so CAPI -- + # California's SSI-equivalent cash aid for immigrants -- is also an + # excluding program. CAPI recipients do NOT have ssi > 0, so ca_capi is + # checked separately. + # CalWORKs and CAPI receipt are only available at the SPM-unit level, so + # any unit receiving them excludes its members; this does not + # distinguish child-only cases. Refugee Cash Assistance has no + # California variable in PolicyEngine, so we don't track RCA at the + # moment. receives_ssi = person("ssi", period) > 0 receives_calworks = person.spm_unit("ca_tanf", period) > 0 - return receives_ssi | receives_calworks + receives_capi = person.spm_unit("ca_capi", period) > 0 + return receives_ssi | receives_calworks | receives_capi diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_countable_income_person.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_countable_income_person.py index 83eb7f814fc..db9e040a25c 100644 --- a/policyengine_us/variables/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_countable_income_person.py +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/income/ca_oc_general_relief_countable_income_person.py @@ -14,6 +14,10 @@ class ca_oc_general_relief_countable_income_person(Variable): ) def formula(person, period, parameters): + # NOTE: Section 70.2.p also allows mandatory federal/state income tax + # withheld from unearned income as a deduction; we don't track that at + # the moment (negligible for the very-low-income General Relief + # population). countable_income = add( person, period, diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_countable_personal_property.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_countable_personal_property.py index 670fbf87a43..35f8059169c 100644 --- a/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_countable_personal_property.py +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_countable_personal_property.py @@ -5,13 +5,11 @@ class ca_oc_general_relief_countable_personal_property(Variable): value_type = float entity = SPMUnit label = "Orange County General Relief countable personal property" - documentation = ( - "Uses available personal-property inputs. PolicyEngine does not " - "separate all Orange County regulatory exclusions, including " - "household effects and burial reserves." - ) unit = USD quantity_type = STOCK definition_period = YEAR defined_for = "in_oc" + # NOTE: uses available personal-property inputs; we don't separate all + # Orange County exclusions (household effects up to $500, burial reserves + # up to $1,000) at the moment. adds = ["personal_property"] diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_countable_vehicle_value.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_countable_vehicle_value.py index 5926b281627..84d7a2b368f 100644 --- a/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_countable_vehicle_value.py +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_countable_vehicle_value.py @@ -5,10 +5,6 @@ class ca_oc_general_relief_countable_vehicle_value(Variable): value_type = float entity = SPMUnit label = "Orange County General Relief countable vehicle value" - documentation = ( - "Uses total household vehicle equity as a proxy for the net value of one " - "vehicle per Orange County General Relief economic unit." - ) unit = USD quantity_type = STOCK definition_period = YEAR @@ -16,6 +12,8 @@ class ca_oc_general_relief_countable_vehicle_value(Variable): reference = "https://www.ssa.ocgov.com/sites/ssa/files/2023-04/GR%20Reg%20SECTION%2060%20-%20Approved%20-%20March%202023_0.pdf#page=02" def formula(spm_unit, period, parameters): + # NOTE: uses total household vehicle equity as a proxy for the net value + # of one vehicle per economic unit. p = parameters(period).gov.local.ca.oc.general_relief.resources vehicle_equity = spm_unit.household("household_vehicles_equity", period) return where(vehicle_equity <= p.vehicle_exclusion, 0, vehicle_equity) diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_excess_liquid_resources.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_excess_liquid_resources.py index 5686a979d1a..c57f80c42b9 100644 --- a/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_excess_liquid_resources.py +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_excess_liquid_resources.py @@ -5,11 +5,6 @@ class ca_oc_general_relief_excess_liquid_resources(Variable): value_type = float entity = SPMUnit label = "Orange County General Relief excess liquid resources" - documentation = ( - "Amount available to reduce an initial-month grant. The ordinary " - "monthly payment is not modeled because Orange County's MAP schedule " - "is not publicly available." - ) unit = USD quantity_type = STOCK definition_period = YEAR @@ -17,6 +12,9 @@ class ca_oc_general_relief_excess_liquid_resources(Variable): reference = "https://www.ssa.ocgov.com/sites/ssa/files/2023-04/GR%20Reg%20SECTION%2060%20-%20Approved%20-%20March%202023_0.pdf#page=01" def formula(spm_unit, period, parameters): + # NOTE: amount available to reduce an initial-month grant; the ordinary + # monthly payment is not modeled because Orange County's MAP schedule + # is not publicly available. p = parameters(period).gov.local.ca.oc.general_relief.resources liquid_resources = spm_unit("spm_unit_cash_assets", period) return max_(liquid_resources - p.liquid_resource_disregard, 0) diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_other_real_estate_equity.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_other_real_estate_equity.py index 1d1af8cded9..0015899b1af 100644 --- a/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_other_real_estate_equity.py +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/resources/ca_oc_general_relief_other_real_estate_equity.py @@ -5,15 +5,12 @@ class ca_oc_general_relief_other_real_estate_equity(Variable): value_type = float entity = SPMUnit label = "Orange County General Relief other real estate equity" - documentation = ( - "Uses available household other-real-estate equity. PolicyEngine does " - "not identify secondary real property that the unit is making a good " - "faith effort to sell." - ) unit = USD quantity_type = STOCK definition_period = YEAR defined_for = "in_oc" def formula(spm_unit, period, parameters): + # NOTE: uses household other-real-estate equity; we don't track whether + # secondary real property is under a good-faith effort to sell. return spm_unit.household("household_other_real_estate_equity", period) From 3d85cc2c2a1fd4dbfb4ec0a4a5407c9b6ac3dd39 Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 2 Jun 2026 13:28:34 -0400 Subject: [PATCH 3/3] Add Orange County General Relief benefit amount Implement the OC General Relief monthly maximum aid payment (MAP) and the grant calculation, replacing the prior partial (eligibility-only) screen. - MAP by economic unit size (1-10) from the County of Orange MAP table effective April 1, 2015, with the size-1 increase to $355 effective October 1, 2016. - Shared-housing reductions of 15% / 20% / 25% for sharing with 1 / 2 / 3+ other people (GR manual Sec 80.3.a(3)). - Grant = max_(MAP - countable income, 0) (Sec 80.2.d, Sec 80.3.c-e). - Point programs.yaml at ca_oc_general_relief and mark status complete. Component-value deductions for in-kind aid (Sec 80.3.b) are not modeled because Orange County does not publish the component-value amounts; MAP values are the 2015/2016 schedule pending a current published table. Co-Authored-By: Claude Opus 4.8 (1M context) --- changelog.d/8556.added.md | 2 +- .../payment/max_aid_payment.yaml | 35 ++++ .../payment/shared_housing_reduction.yaml | 27 +++ policyengine_us/programs.yaml | 6 +- .../general_relief/ca_oc_general_relief.yaml | 87 ++++++++++ .../ca/oc/general_relief/integration.yaml | 38 ++++- .../ca_oc_general_relief_max_aid_payment.yaml | 158 ++++++++++++++++++ .../oc/general_relief/ca_oc_general_relief.py | 21 +++ .../ca_oc_general_relief_eligible.py | 11 +- .../ca_oc_general_relief_max_aid_payment.py | 33 ++++ 10 files changed, 407 insertions(+), 11 deletions(-) create mode 100644 policyengine_us/parameters/gov/local/ca/oc/general_relief/payment/max_aid_payment.yaml create mode 100644 policyengine_us/parameters/gov/local/ca/oc/general_relief/payment/shared_housing_reduction.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/ca_oc_general_relief.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/payment/ca_oc_general_relief_max_aid_payment.yaml create mode 100644 policyengine_us/variables/gov/local/ca/oc/general_relief/ca_oc_general_relief.py create mode 100644 policyengine_us/variables/gov/local/ca/oc/general_relief/payment/ca_oc_general_relief_max_aid_payment.py diff --git a/changelog.d/8556.added.md b/changelog.d/8556.added.md index d8e1458c42d..c7c1bbb4b03 100644 --- a/changelog.d/8556.added.md +++ b/changelog.d/8556.added.md @@ -1 +1 @@ -Added a partial Orange County, California General Relief eligibility, income, and resource screen. +Added the Orange County, California General Relief benefit, paying the maximum aid payment by economic unit size and shared-housing situation net of countable income. diff --git a/policyengine_us/parameters/gov/local/ca/oc/general_relief/payment/max_aid_payment.yaml b/policyengine_us/parameters/gov/local/ca/oc/general_relief/payment/max_aid_payment.yaml new file mode 100644 index 00000000000..cb3080fcc60 --- /dev/null +++ b/policyengine_us/parameters/gov/local/ca/oc/general_relief/payment/max_aid_payment.yaml @@ -0,0 +1,35 @@ +description: Orange County provides this maximum aid payment based on economic unit size under the General Relief program. +metadata: + unit: currency-USD + breakdown: + - range(1, 11) + breakdown_labels: + - Economic unit size + period: month + label: Orange County General Relief maximum aid payment + reference: + - title: County of Orange General Relief Program Monthly Maximum Aid Payment (MAP) Table, effective April 1, 2015 + href: https://www.ochealthinfo.com/sites/hca/files/2021-07/DUI%20Program%20Standards%20%28FINAL%29%207.2021.pdf#page=32 + - title: 2017 Orange County Continuum of Care Application, Social Service Agency Benefits (single homeless individual maximum, effective October 1, 2016) + href: https://ochealthinfo.com/sites/hca/files/import/data/files/73607.pdf#page=21 +1: + 2015-04-01: 350 + 2016-10-01: 355 +2: + 2015-04-01: 569 +3: + 2015-04-01: 704 +4: + 2015-04-01: 840 +5: + 2015-04-01: 954 +6: + 2015-04-01: 1_072 +7: + 2015-04-01: 1_178 +8: + 2015-04-01: 1_283 +9: + 2015-04-01: 1_387 +10: + 2015-04-01: 1_490 diff --git a/policyengine_us/parameters/gov/local/ca/oc/general_relief/payment/shared_housing_reduction.yaml b/policyengine_us/parameters/gov/local/ca/oc/general_relief/payment/shared_housing_reduction.yaml new file mode 100644 index 00000000000..d94e4db3c48 --- /dev/null +++ b/policyengine_us/parameters/gov/local/ca/oc/general_relief/payment/shared_housing_reduction.yaml @@ -0,0 +1,27 @@ +description: Orange County reduces the maximum aid payment by this share when the economic unit shares housing with this number of other people under the General Relief program. +metadata: + type: single_amount + threshold_unit: person + amount_unit: /1 + period: year + label: Orange County General Relief shared housing reduction + reference: + - title: Orange County General Relief regulations, section 80.3.a(3) + href: https://www.ssa.ocgov.com/sites/ssa/files/2025-03/Benefits_Services.pdf#page=04 +brackets: + - threshold: + 2015-04-01: 0 + amount: + 2015-04-01: 0 + - threshold: + 2015-04-01: 1 + amount: + 2015-04-01: 0.15 + - threshold: + 2015-04-01: 2 + amount: + 2015-04-01: 0.2 + - threshold: + 2015-04-01: 3 + amount: + 2015-04-01: 0.25 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 47f6eab75e9..5b62055ca21 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -1290,11 +1290,11 @@ programs: full_name: Orange County General Relief category: Benefits agency: Local - status: partial + status: complete coverage: Orange County - variable: ca_oc_general_relief_eligible + variable: ca_oc_general_relief parameter_prefix: gov.local.ca.oc.general_relief - notes: Eligibility, income, and resource screens only; monthly payment schedule and administrative-history rules are not modeled + notes: Monthly maximum aid payment by economic unit size and shared-housing situation (April 2015 / October 2016 schedule) net of countable income; component-value deductions for in-kind aid and administrative-history rules are not modeled - id: ca_riv_general_relief name: Riverside County General Relief diff --git a/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/ca_oc_general_relief.yaml b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/ca_oc_general_relief.yaml new file mode 100644 index 00000000000..6c864d04b42 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/ca_oc_general_relief.yaml @@ -0,0 +1,87 @@ +- name: Single eligible adult with no income receives the full maximum aid payment. + period: 2017-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + ssi: 0 + households: + household: + members: [person1] + in_oc: true + spm_units: + spm_unit: + members: [person1] + ca_tanf: 0 + output: + # MAP 355, no countable income: grant = 355. + ca_oc_general_relief: 355 + +- name: Earnings below the maximum aid payment reduce the grant. + period: 2017-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + ssi: 0 + employment_income: 300 * 12 + households: + household: + members: [person1] + in_oc: true + spm_units: + spm_unit: + members: [person1] + ca_tanf: 0 + output: + # Gross earned 300/month; countable earned = 300 x (1 - 0.2) = 240. + # Grant = max(355 - 240, 0) = 115. + ca_oc_general_relief: 115 + +- name: Earnings above the maximum aid payment yield a zero grant. + period: 2017-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + ssi: 0 + employment_income: 600 * 12 + households: + household: + members: [person1] + in_oc: true + spm_units: + spm_unit: + members: [person1] + ca_tanf: 0 + output: + # Gross earned 600/month; countable earned = 480 > MAP 355. + # Grant = max(355 - 480, 0) = 0. + ca_oc_general_relief: 0 + +- name: Two-person economic unit with no income receives the size-2 maximum aid payment. + period: 2017-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + ssi: 0 + person2: + age: 35 + immigration_status: CITIZEN + ssi: 0 + households: + household: + members: [person1, person2] + in_oc: true + spm_units: + spm_unit: + members: [person1, person2] + ca_tanf: 0 + output: + # MAP size 2 = 569, no countable income. + ca_oc_general_relief: 569 diff --git a/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/integration.yaml b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/integration.yaml index 2776334a791..8b311cfc217 100644 --- a/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/integration.yaml @@ -1,4 +1,4 @@ -- name: A single adult citizen with resources below the limits passes the partial screen. +- name: A single adult citizen with resources below the limits receives the maximum aid payment. period: 2026-01 input: people: @@ -18,6 +18,9 @@ ca_oc_general_relief_aided_person_count: 1 ca_oc_general_relief_resources_eligible: true ca_oc_general_relief_eligible: true + # EU size 1, no shared housing, no countable income. + ca_oc_general_relief_max_aid_payment: 355 + ca_oc_general_relief: 355 - name: An undocumented adult does not pass the partial screen. period: 2026-01 @@ -119,7 +122,7 @@ ca_oc_general_relief_resources_eligible: false ca_oc_general_relief_eligible: false -- name: Income is exposed without changing the partial screen because the MAP schedule is unavailable. +- name: Income above the maximum aid payment yields a zero grant. period: 2026-01 input: people: @@ -136,8 +139,11 @@ members: [person] ca_tanf: 0 output: + # Countable income 800 exceeds the size-1 MAP (355), so the grant is 0, + # though the unit still passes the categorical screen. ca_oc_general_relief_countable_income: 800 ca_oc_general_relief_eligible: true + ca_oc_general_relief: 0 # Mapping the eligible population from real family inputs: only able-bodied, # childless, qualified-immigration adults with low assets pass the screen. @@ -193,3 +199,31 @@ # excluded "other type of public assistance" under Sec 20.4.b. ca_oc_general_relief_receives_other_cash_assistance: true ca_oc_general_relief_eligible: false + +- name: A single adult sharing a home with one roommate has the grant reduced for shared housing. + period: 2026-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + ssi: 0 + person2: + age: 45 + immigration_status: CITIZEN + ssi: 0 + households: + household: + members: [person1, person2] + in_oc: true + spm_units: + spm_unit1: + members: [person1] + ca_tanf: 0 + spm_unit2: + members: [person2] + ca_tanf: 0 + output: + # Each one-person economic unit shares with 1 other person, so the size-1 + # MAP (355) is reduced 15%: 355 x 0.85 = 301.75. + ca_oc_general_relief: [301.75, 301.75] diff --git a/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/payment/ca_oc_general_relief_max_aid_payment.yaml b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/payment/ca_oc_general_relief_max_aid_payment.yaml new file mode 100644 index 00000000000..16efc520322 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/local/ca/oc/general_relief/payment/ca_oc_general_relief_max_aid_payment.yaml @@ -0,0 +1,158 @@ +- name: Single economic unit, no shared housing, April 2015 schedule. + period: 2016-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + ssi: 0 + households: + household: + members: [person1] + in_oc: true + spm_units: + spm_unit: + members: [person1] + ca_tanf: 0 + output: + # EU size 1, no shared housing, effective April 1, 2015. + ca_oc_general_relief_max_aid_payment: 350 + +- name: Single economic unit, no shared housing, October 2016 schedule. + period: 2017-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + ssi: 0 + households: + household: + members: [person1] + in_oc: true + spm_units: + spm_unit: + members: [person1] + ca_tanf: 0 + output: + # EU size 1 increased from 350 to 355 effective October 1, 2016. + ca_oc_general_relief_max_aid_payment: 355 + +- name: Two-person economic unit, no shared housing. + period: 2017-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + ssi: 0 + person2: + age: 35 + immigration_status: CITIZEN + ssi: 0 + households: + household: + members: [person1, person2] + in_oc: true + spm_units: + spm_unit: + members: [person1, person2] + ca_tanf: 0 + output: + # EU size 2, no shared housing (both members in one economic unit). + ca_oc_general_relief_max_aid_payment: 569 + +- name: Four-person economic unit, no shared housing. + period: 2017-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + ssi: 0 + person2: + age: 35 + immigration_status: CITIZEN + ssi: 0 + person3: + age: 40 + immigration_status: CITIZEN + ssi: 0 + person4: + age: 45 + immigration_status: CITIZEN + ssi: 0 + households: + household: + members: [person1, person2, person3, person4] + in_oc: true + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + ca_tanf: 0 + output: + # EU size 4, no shared housing. + ca_oc_general_relief_max_aid_payment: 840 + +- name: Two single-person economic units sharing one home (one other person each). + period: 2017-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + ssi: 0 + person2: + age: 40 + immigration_status: CITIZEN + ssi: 0 + households: + household: + members: [person1, person2] + in_oc: true + spm_units: + spm_unit1: + members: [person1] + ca_tanf: 0 + spm_unit2: + members: [person2] + ca_tanf: 0 + output: + # Each EU shares with 1 other person: 355 x (1 - 0.15) = 301.75. + ca_oc_general_relief_max_aid_payment: [301.75, 301.75] + +- name: Single economic unit sharing a home with three other people. + period: 2017-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + ssi: 0 + person2: + age: 40 + immigration_status: CITIZEN + ssi: 0 + person3: + age: 41 + immigration_status: CITIZEN + ssi: 0 + person4: + age: 42 + immigration_status: CITIZEN + ssi: 0 + households: + household: + members: [person1, person2, person3, person4] + in_oc: true + spm_units: + spm_unit1: + members: [person1] + ca_tanf: 0 + spm_unit2: + members: [person2, person3, person4] + ca_tanf: 0 + output: + # spm_unit1: EU size 1 sharing with 3 others: 355 x (1 - 0.25) = 266.25. + # spm_unit2: EU size 3 sharing with 1 other: 704 x (1 - 0.15) = 598.4. + ca_oc_general_relief_max_aid_payment: [266.25, 598.4] diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/ca_oc_general_relief.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/ca_oc_general_relief.py new file mode 100644 index 00000000000..c3826893997 --- /dev/null +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/ca_oc_general_relief.py @@ -0,0 +1,21 @@ +from policyengine_us.model_api import * + + +class ca_oc_general_relief(Variable): + value_type = float + entity = SPMUnit + unit = USD + label = "Orange County General Relief" + definition_period = MONTH + defined_for = "ca_oc_general_relief_eligible" + reference = "https://www.ssa.ocgov.com/sites/ssa/files/2025-03/Benefits_Services.pdf#page=01" + + def formula(spm_unit, period, parameters): + # The GR benefit is the maximum aid payment less all net countable + # income (Sec 80.2.d, Sec 80.3.c-e). The grant cannot be negative. + # We don't model the component-value deductions for in-kind aid met at + # no cost (Sec 80.3.b) at the moment, because Orange County does not + # publish the component-value dollar amounts. + max_aid_payment = spm_unit("ca_oc_general_relief_max_aid_payment", period) + countable_income = spm_unit("ca_oc_general_relief_countable_income", period) + return max_(max_aid_payment - countable_income, 0) diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/ca_oc_general_relief_eligible.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/ca_oc_general_relief_eligible.py index 13706f5ede8..349abbc92da 100644 --- a/policyengine_us/variables/gov/local/ca/oc/general_relief/ca_oc_general_relief_eligible.py +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/ca_oc_general_relief_eligible.py @@ -4,16 +4,17 @@ class ca_oc_general_relief_eligible(Variable): value_type = bool entity = SPMUnit - label = "Partial eligibility screen for Orange County General Relief" + label = "Eligible for Orange County General Relief" definition_period = MONTH defined_for = "in_oc" reference = "https://www.ssa.ocgov.com/page/general-relief-regulations" def formula(spm_unit, period, parameters): - # Partial screen: models demographic (adults without minor children), - # immigration, public-assistance, and resource rules. The income limit - # and MAP payment amount are not modeled because Orange County does not - # publish the MAP schedule. + # Categorical screen: demographic (adults without minor children), + # immigration, public-assistance, and resource rules. Financial + # eligibility (income below the maximum aid payment) is applied in the + # benefit variable ca_oc_general_relief, which nets countable income + # against the MAP. demographic_eligible = spm_unit( "ca_oc_general_relief_demographic_eligible", period, diff --git a/policyengine_us/variables/gov/local/ca/oc/general_relief/payment/ca_oc_general_relief_max_aid_payment.py b/policyengine_us/variables/gov/local/ca/oc/general_relief/payment/ca_oc_general_relief_max_aid_payment.py new file mode 100644 index 00000000000..8b80340a1c6 --- /dev/null +++ b/policyengine_us/variables/gov/local/ca/oc/general_relief/payment/ca_oc_general_relief_max_aid_payment.py @@ -0,0 +1,33 @@ +from policyengine_us.model_api import * + + +class ca_oc_general_relief_max_aid_payment(Variable): + value_type = float + entity = SPMUnit + unit = USD + label = "Orange County General Relief maximum aid payment" + definition_period = MONTH + defined_for = "in_oc" + reference = ( + "https://www.ochealthinfo.com/sites/hca/files/2021-07/DUI%20Program%20Standards%20%28FINAL%29%207.2021.pdf#page=32", + "https://www.ssa.ocgov.com/sites/ssa/files/2025-03/Benefits_Services.pdf#page=04", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.local.ca.oc.general_relief.payment + # The MAP is based on the size of the GR Economic Unit and its housing + # arrangement (Sec 80.2.d). It covers only the aided persons: children + # and members excluded for SSI/other cash assistance or immigration + # status are not included in the MAP. + size = spm_unit("ca_oc_general_relief_aided_person_count", period) + capped_size = clip(size, 1, 10) + base = p.max_aid_payment[capped_size] + # The MAP is reduced when the Economic Unit shares housing with one or + # more people who are not part of the unit (Sec 80.3.a(3)). We proxy the + # number of other people sharing the home as the household members + # outside the Economic Unit (the SPM unit). + household_size = spm_unit.household("household_size", period.this_year) + unit_size = spm_unit("spm_unit_size", period.this_year) + other_people = max_(household_size - unit_size, 0) + reduction = p.shared_housing_reduction.calc(other_people) + return base * (1 - reduction)