diff --git a/changelog_entry.yaml b/changelog_entry.yaml index e69de29bb2d..2f7166cd419 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -0,0 +1,6 @@ +- bump: minor + changes: + added: + - California CalWORKs Stage 2 (C2AP) child care subsidy for former CalWORKs recipients within 24 months of leaving cash aid. + - California CalWORKs Stage 3 (C3AP) child care subsidy for former CalWORKs recipients who exhausted Stage 2 eligibility. + - California Alternative Payment Program (CAPP) child care subsidy for income-eligible families who never received CalWORKs. diff --git a/policyengine_us/parameters/gov/states/ca/cdss/child_care/family_fees/exemption_threshold.yaml b/policyengine_us/parameters/gov/states/ca/cdss/child_care/family_fees/exemption_threshold.yaml new file mode 100644 index 00000000000..a65a480f89c --- /dev/null +++ b/policyengine_us/parameters/gov/states/ca/cdss/child_care/family_fees/exemption_threshold.yaml @@ -0,0 +1,11 @@ +description: California exempts families below this share of State Median Income from child care family fees. +values: + 2023-10-01: 0.75 + +metadata: + unit: /1 + period: year + label: California child care family fee exemption threshold + reference: + - title: California Welfare and Institutions Code Section 10290(e)(2) + href: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=10290.&lawCode=WIC diff --git a/policyengine_us/parameters/gov/states/ca/cdss/child_care/family_fees/fee_cap.yaml b/policyengine_us/parameters/gov/states/ca/cdss/child_care/family_fees/fee_cap.yaml new file mode 100644 index 00000000000..12c8f0bf2e7 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ca/cdss/child_care/family_fees/fee_cap.yaml @@ -0,0 +1,11 @@ +description: California caps child care family fees at this share of adjusted monthly income. +values: + 2023-10-01: 0.01 + +metadata: + unit: /1 + period: month + label: California child care family fee cap + reference: + - title: California Welfare and Institutions Code Section 10290(e)(2) + href: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=10290.&lawCode=WIC diff --git a/policyengine_us/parameters/gov/states/ca/cdss/child_care/income/income_limit.yaml b/policyengine_us/parameters/gov/states/ca/cdss/child_care/income/income_limit.yaml new file mode 100644 index 00000000000..31349064fea --- /dev/null +++ b/policyengine_us/parameters/gov/states/ca/cdss/child_care/income/income_limit.yaml @@ -0,0 +1,16 @@ +description: California limits child care subsidy eligibility to this share of State Median Income for CalWORKs Stage 2, Stage 3, and CAPP programs. +values: + 2011-07-01: 0.7 + 2017-10-01: 0.85 + +metadata: + unit: /1 + period: year + label: California child care income limit as share of SMI + reference: + - title: SB 70 (2011) Section 8263.1 - Lowered income limit from 75% to 70% SMI + href: https://leginfo.legislature.ca.gov/faces/billNavClient.xhtml?bill_id=201120120SB70 + - title: AB 99 (2017) Section 8263.1 - Raised income limit from 70% to 85% SMI + href: https://leginfo.legislature.ca.gov/faces/billTextClient.xhtml?bill_id=201720180AB99 + - title: California Welfare and Institutions Code Section 10271.5 + href: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=10271.5.&lawCode=WIC diff --git a/policyengine_us/parameters/gov/states/ca/cdss/child_care/income/sources.yaml b/policyengine_us/parameters/gov/states/ca/cdss/child_care/income/sources.yaml new file mode 100644 index 00000000000..6ae15ea404e --- /dev/null +++ b/policyengine_us/parameters/gov/states/ca/cdss/child_care/income/sources.yaml @@ -0,0 +1,34 @@ +description: California counts these income sources for child care subsidy eligibility. + +values: + 2000-01-01: + # Earned income + - employment_income + - self_employment_income + # Public assistance + - ca_tanf + # Unemployment and disability + - unemployment_compensation + - workers_compensation + - ca_state_disability_insurance + # Social Security (excluding SSI) + - social_security + # Support payments + - child_support_received + - alimony_income + # Retirement and veterans + - pension_income + - veterans_benefits + # Investment income + - interest_income + - dividend_income + - capital_gains + - rental_income + +metadata: + unit: list + period: year + label: California child care countable income sources + reference: + - title: California Code of Regulations Title 5 Section 18078(w) + href: https://www.law.cornell.edu/regulations/california/5-CCR-18078 diff --git a/policyengine_us/parameters/gov/states/ca/cdss/child_care/stage_2/time_limit_months.yaml b/policyengine_us/parameters/gov/states/ca/cdss/child_care/stage_2/time_limit_months.yaml new file mode 100644 index 00000000000..954d4e74981 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ca/cdss/child_care/stage_2/time_limit_months.yaml @@ -0,0 +1,11 @@ +description: California limits CalWORKs Stage 2 child care eligibility to this number of months after leaving cash aid. +values: + 1998-01-01: 24 + +metadata: + unit: month + period: year + label: California CalWORKs Stage 2 time limit + reference: + - title: California Welfare and Institutions Code Section 10372 + href: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=10372.&nodeTreePath=16.4.19&lawCode=WIC diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/capp/ca_capp_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/capp/ca_capp_eligible.yaml new file mode 100644 index 00000000000..de4b0a5525c --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/capp/ca_capp_eligible.yaml @@ -0,0 +1,135 @@ +- name: Case 1, never received CalWORKs, income eligible, CAPP eligible. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 48_000 + person2: + age: 5 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: false + households: + household: + members: [person1, person2] + state_code: CA + output: + # Never received CalWORKs + income eligible = CAPP eligible + ca_capp_eligible: true + +- name: Case 2, formerly received CalWORKs, not eligible for CAPP. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 48_000 + person2: + age: 5 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: true + months_since_calworks_exit: 12 + households: + household: + members: [person1, person2] + state_code: CA + output: + # Ever received CalWORKs = not eligible for CAPP (use Stage 2 or 3) + ca_capp_eligible: false + +- name: Case 3, income above 85 percent SMI, not eligible for CAPP. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 120_000 + person2: + age: 5 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: false + households: + household: + members: [person1, person2] + state_code: CA + output: + # Income too high + ca_capp_eligible: false + +- name: Case 4, no age-eligible children, not eligible for CAPP. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 48_000 + person2: + age: 16 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: false + households: + household: + members: [person1, person2] + state_code: CA + output: + # No age-eligible children (child is 16, threshold is typically 13) + ca_capp_eligible: false + +- name: Case 5, adult only household, not eligible for CAPP. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 48_000 + spm_units: + spm_unit: + members: [person1] + was_calworks_recipient: false + households: + household: + members: [person1] + state_code: CA + output: + # No children at all = not eligible + ca_capp_eligible: false + +- name: Case 6, zero income fails work requirement, not CAPP eligible. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 0 + person2: + age: 5 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: false + households: + household: + members: [person1, person2] + state_code: CA + output: + # Zero income fails work requirement (earned_income > 0) + ca_capp_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/capp/ca_capp_payment.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/capp/ca_capp_payment.yaml new file mode 100644 index 00000000000..2d5b4bf3961 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/capp/ca_capp_payment.yaml @@ -0,0 +1,34 @@ +- name: Case 1, CAPP payment uses RMR structure. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 48_000 + ca_calworks_child_care_provider_category: CHILD_CARE_CENTER + ca_calworks_child_care_time_category: MONTHLY + ca_calworks_child_care_full_time: true + pre_subsidy_childcare_expenses: 24_000 + person2: + age: 3 + immigration_status: CITIZEN + ca_calworks_child_care_provider_category: CHILD_CARE_CENTER + ca_calworks_child_care_time_category: MONTHLY + ca_calworks_child_care_full_time: true + pre_subsidy_childcare_expenses: 24_000 + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: false + households: + household: + members: [person1, person2] + state_code: CA + output: + # Child (person2) receives payment based on RMR ceiling + # RMR for 3-year-old at child care center, full-time monthly: ~1,253 + # pre_subsidy_childcare_expenses: 24,000 annual / 12 = 2,000/month + # Payment = min(1,253, 2,000) = 1,253 + # Adult (person1) does not receive child care payment + ca_capp_payment: [0, 1_253.26] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/common/ca_child_care_family_fee.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/common/ca_child_care_family_fee.yaml new file mode 100644 index 00000000000..3034b3c2009 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/common/ca_child_care_family_fee.yaml @@ -0,0 +1,121 @@ +- name: Case 1, income below 75 percent SMI, exempt from fees. + period: 2025-01 + input: + people: + person1: + age: 35 + employment_income: 48_000 + person2: + age: 33 + person3: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: CA + output: + # Monthly SMI for family of 3: 7,761.53 + # 75% SMI: 5,821.15 + # Monthly income: 48,000 / 12 = 4,000 + # 4,000 < 5,821.15 = exempt + ca_child_care_family_fee: 0 + +- name: Case 2, income above 75 percent SMI, fee is 1 percent of income. + period: 2025-01 + input: + people: + person1: + age: 35 + employment_income: 72_000 + person2: + age: 33 + person3: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: CA + output: + # Monthly SMI for family of 3: 7,761.53 + # 75% SMI: 5,821.15 + # Monthly income: 72,000 / 12 = 6,000 + # 6,000 >= 5,821.15 = not exempt + # Fee: 6,000 * 0.01 = 60 + ca_child_care_family_fee: 60 + +- name: Case 3, zero income, exempt from fees. + period: 2025-01 + input: + people: + person1: + age: 35 + employment_income: 0 + person2: + age: 33 + person3: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: CA + output: + # Zero income < 75% SMI = exempt + ca_child_care_family_fee: 0 + +- name: Case 4, income exactly at 75 percent SMI, fee applies. + period: 2025-01 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 35 + # 3-person SMI: 7,761.53/month, 75% = 5,821.15/month + # Annual: 5,821.15 * 12 = 69,854 + employment_income: 69_854 + person2: + age: 33 + person3: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: CA + output: + # Income exactly at 75% SMI: uses < for exempt, so fee applies + # Fee: 5,821.17 * 0.01 = 58.21 + ca_child_care_family_fee: 58.21 + +- name: Case 5, income one dollar below 75 percent SMI, exempt. + period: 2025-01 + input: + people: + person1: + age: 35 + # 75% SMI = 69,854 annual, so 69,840 is below + employment_income: 69_840 + person2: + age: 33 + person3: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: CA + output: + # Income just below 75% SMI = exempt + ca_child_care_family_fee: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/common/ca_child_care_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/common/ca_child_care_income_eligible.yaml new file mode 100644 index 00000000000..ce169c52846 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/common/ca_child_care_income_eligible.yaml @@ -0,0 +1,113 @@ +- name: Case 1, income below 85 percent SMI. + period: 2025-01 + input: + people: + person1: + age: 35 + employment_income: 60_000 + person2: + age: 33 + person3: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: CA + output: + # Monthly SMI for family of 3: 7,761.53 + # 85% SMI: 6,597.30 + # Monthly income: 60,000 / 12 = 5,000 + # 5,000 <= 6,597.30 = true + ca_child_care_income_eligible: true + +- name: Case 2, income above 85 percent SMI. + period: 2025-01 + input: + people: + person1: + age: 35 + employment_income: 100_000 + person2: + age: 33 + person3: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: CA + output: + # Monthly SMI for family of 3: 7,761.53 + # 85% SMI: 6,597.30 + # Monthly income: 100,000 / 12 = 8,333.33 + # 8,333.33 <= 6,597.30 = false + ca_child_care_income_eligible: false + +- name: Case 3, zero income, eligible. + period: 2025-01 + input: + people: + person1: + age: 35 + employment_income: 0 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + output: + # Zero income <= any SMI threshold + ca_child_care_income_eligible: true + +- name: Case 4, income exactly at 85 percent SMI, eligible. + period: 2025-01 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 35 + # 2-person SMI: 6,283.14/month, 85% = 5,340.67/month + # Annual: 5,340.67 * 12 = 64,088 + employment_income: 64_088 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + output: + # Income exactly at 85% SMI: uses <=, so eligible + ca_child_care_income_eligible: true + +- name: Case 5, income one dollar above 85 percent SMI, not eligible. + period: 2025-01 + input: + people: + person1: + age: 35 + # 85% SMI = 64,088, so 64,089 is $1 over + employment_income: 64_100 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + output: + # Income just above 85% SMI = not eligible + ca_child_care_income_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/common/ca_child_care_smi.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/common/ca_child_care_smi.yaml new file mode 100644 index 00000000000..6f14bc55c12 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/common/ca_child_care_smi.yaml @@ -0,0 +1,133 @@ +- name: Case 1, family of 3 in California. + period: 2025-01 + input: + people: + person1: + age: 35 + person2: + age: 33 + person3: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: CA + output: + # 4-person SMI for CA at 2023-10-01: 110,879 + # Size adjustment for 3: 0.52 + 0.16 * 2 = 0.84 + # Annual: 110,879 * 0.84 = 93,138.36 + # Monthly: 93,138.36 / 12 = 7,761.53 + ca_child_care_smi: 7_761.53 + +- name: Case 2, family of 4 in California. + period: 2025-01 + input: + people: + person1: + age: 35 + person2: + age: 33 + person3: + age: 8 + person4: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: CA + output: + # 4-person SMI for CA at 2023-10-01: 110,879 + # Size adjustment for 4: 0.52 + 0.16 * 3 = 1.00 + # Annual: 110,879 * 1.00 = 110,879 + # Monthly: 110,879 / 12 = 9,239.92 + ca_child_care_smi: 9_239.917 + +- name: Case 3, family of 2 in California. + period: 2025-01 + input: + people: + person1: + age: 35 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + output: + # 4-person SMI for CA: 110,879 + # Size adjustment for 2: 0.52 + 0.16 * 1 = 0.68 + # Annual: 110,879 * 0.68 = 75,397.72 + # Monthly: 75,397.72 / 12 = 6,283.14 + ca_child_care_smi: 6_283.1436 + +- name: Case 4, family of 6 in California, max second to sixth adjustment. + period: 2025-01 + input: + people: + person1: + age: 40 + person2: + age: 38 + person3: + age: 15 + person4: + age: 12 + person5: + age: 8 + person6: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6] + households: + household: + members: [person1, person2, person3, person4, person5, person6] + state_code: CA + output: + # 4-person SMI for CA: 110,879 + # Size adjustment for 6: 0.52 + 0.16 * 5 = 1.32 + # Annual: 110,879 * 1.32 = 146,360.28 + # Monthly: 146,360.28 / 12 = 12,196.69 + ca_child_care_smi: 12_196.69 + +- name: Case 5, family of 7 in California, uses additional person adjustment. + period: 2025-01 + input: + people: + person1: + age: 42 + person2: + age: 40 + person3: + age: 16 + person4: + age: 14 + person5: + age: 11 + person6: + age: 8 + person7: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6, person7] + households: + household: + members: [person1, person2, person3, person4, person5, person6, person7] + state_code: CA + output: + # 4-person SMI for CA: 110,879 + # Size adjustment for 7: 0.52 + 0.16 * 5 + 0.03 * 1 = 1.35 + # Annual: 110,879 * 1.35 = 149,686.65 + # Monthly: 149,686.65 / 12 = 12,473.89 + ca_child_care_smi: 12_473.888 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/integration.yaml new file mode 100644 index 00000000000..f007fc62695 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/integration.yaml @@ -0,0 +1,417 @@ +- name: Case 1, Stage 1 family currently on CalWORKs. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 24_000 + ca_calworks_child_care_provider_category: CHILD_CARE_CENTER + ca_calworks_child_care_time_category: MONTHLY + ca_calworks_child_care_full_time: true + pre_subsidy_childcare_expenses: 24_000 + person2: + age: 3 + immigration_status: CITIZEN + ca_calworks_child_care_provider_category: CHILD_CARE_CENTER + ca_calworks_child_care_time_category: MONTHLY + ca_calworks_child_care_full_time: true + pre_subsidy_childcare_expenses: 24_000 + spm_units: + spm_unit: + members: [person1, person2] + ca_tanf: 500 + was_calworks_recipient: true + households: + household: + members: [person1, person2] + state_code: CA + output: + # Currently receiving TANF = Stage 1 eligible + ca_calworks_child_care_eligible: true + # Stage 2/3/CAPP not eligible (currently on TANF or ever_received) + ca_calworks_stage_2_eligible: false + ca_calworks_stage_3_eligible: false + ca_capp_eligible: false + # Stage 1 payment (child only): RMR ceiling ~1,253 + ca_calworks_child_care_payment: [0, 1_253.26] + # Total subsidies: Stage 1 only = 1,253.26 + ca_child_care_subsidies: 1_253.26 + +- name: Case 2, Stage 2 former CalWORKs within 24 months. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 48_000 + ca_calworks_child_care_provider_category: CHILD_CARE_CENTER + ca_calworks_child_care_time_category: MONTHLY + ca_calworks_child_care_full_time: true + pre_subsidy_childcare_expenses: 24_000 + person2: + age: 3 + immigration_status: CITIZEN + ca_calworks_child_care_provider_category: CHILD_CARE_CENTER + ca_calworks_child_care_time_category: MONTHLY + ca_calworks_child_care_full_time: true + pre_subsidy_childcare_expenses: 24_000 + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: true + months_since_calworks_exit: 12 + households: + household: + members: [person1, person2] + state_code: CA + output: + # Former TANF within 24 months = Stage 2 eligible + ca_calworks_child_care_eligible: false + ca_calworks_stage_2_eligible: true + ca_calworks_stage_3_eligible: false + ca_capp_eligible: false + # Stage 2 payment (child only): RMR ceiling ~1,253 + ca_calworks_stage_2_payment: [0, 1_253.26] + # Family fee: income 4,000/month, below 75% SMI = exempt + ca_child_care_family_fee: 0 + # Final Stage 2: 1,253 - 0 = 1,253 + ca_calworks_stage_2: 1_253.26 + # Total subsidies: Stage 2 only = 1,253.26 + ca_child_care_subsidies: 1_253.26 + +- name: Case 3, Stage 3 former CalWORKs beyond 24 months. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 48_000 + ca_calworks_child_care_provider_category: CHILD_CARE_CENTER + ca_calworks_child_care_time_category: MONTHLY + ca_calworks_child_care_full_time: true + pre_subsidy_childcare_expenses: 24_000 + person2: + age: 3 + immigration_status: CITIZEN + ca_calworks_child_care_provider_category: CHILD_CARE_CENTER + ca_calworks_child_care_time_category: MONTHLY + ca_calworks_child_care_full_time: true + pre_subsidy_childcare_expenses: 24_000 + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: true + months_since_calworks_exit: 30 + households: + household: + members: [person1, person2] + state_code: CA + output: + # Former TANF beyond 24 months = Stage 3 eligible + ca_calworks_child_care_eligible: false + ca_calworks_stage_2_eligible: false + ca_calworks_stage_3_eligible: true + ca_capp_eligible: false + # Stage 3 payment (child only): RMR ceiling ~1,253 + ca_calworks_stage_3_payment: [0, 1_253.26] + # Family fee: income 4,000/month, below 75% SMI (4,712) = exempt + ca_child_care_family_fee: 0 + # Final Stage 3: 1,253 - 0 = 1,253 + ca_calworks_stage_3: 1_253.26 + # Total subsidies: Stage 3 only = 1,253.26 + ca_child_care_subsidies: 1_253.26 + +- name: Case 4, CAPP never received CalWORKs. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 48_000 + ca_calworks_child_care_provider_category: CHILD_CARE_CENTER + ca_calworks_child_care_time_category: MONTHLY + ca_calworks_child_care_full_time: true + pre_subsidy_childcare_expenses: 24_000 + person2: + age: 3 + immigration_status: CITIZEN + ca_calworks_child_care_provider_category: CHILD_CARE_CENTER + ca_calworks_child_care_time_category: MONTHLY + ca_calworks_child_care_full_time: true + pre_subsidy_childcare_expenses: 24_000 + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: false + households: + household: + members: [person1, person2] + state_code: CA + output: + # Never received CalWORKs = CAPP eligible + ca_calworks_child_care_eligible: false + ca_calworks_stage_2_eligible: false + ca_calworks_stage_3_eligible: false + ca_capp_eligible: true + # CAPP payment (child only): RMR ceiling ~1,253 + ca_capp_payment: [0, 1_253.26] + # Family fee: income 4,000/month, below 75% SMI = exempt + ca_child_care_family_fee: 0 + # Final CAPP: 1,253 - 0 = 1,253 + ca_capp: 1_253.26 + # Total subsidies: CAPP only = 1,253.26 + ca_child_care_subsidies: 1_253.26 + +- name: Case 5, Stage 2 with family fee applied. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 60_000 + ca_calworks_child_care_provider_category: CHILD_CARE_CENTER + ca_calworks_child_care_time_category: MONTHLY + ca_calworks_child_care_full_time: true + pre_subsidy_childcare_expenses: 24_000 + person2: + age: 3 + immigration_status: CITIZEN + ca_calworks_child_care_provider_category: CHILD_CARE_CENTER + ca_calworks_child_care_time_category: MONTHLY + ca_calworks_child_care_full_time: true + pre_subsidy_childcare_expenses: 24_000 + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: true + months_since_calworks_exit: 12 + households: + household: + members: [person1, person2] + state_code: CA + output: + ca_calworks_stage_2_eligible: true + # Stage 2 payment (child only): RMR ceiling ~1,253 + ca_calworks_stage_2_payment: [0, 1_253.26] + # Family fee: income 5,000/month, above 75% SMI (4,712) + # Fee = 5,000 * 0.01 = 50 + ca_child_care_family_fee: 50 + # Final Stage 2: 1,253 - 50 = 1,203 + ca_calworks_stage_2: 1_203.26 + # Total subsidies: Stage 2 only = 1,203.26 + ca_child_care_subsidies: 1_203.26 + +- name: Case 6, income too high for any program. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 150_000 + ca_calworks_child_care_provider_category: CHILD_CARE_CENTER + ca_calworks_child_care_time_category: MONTHLY + ca_calworks_child_care_full_time: true + pre_subsidy_childcare_expenses: 24_000 + person2: + age: 3 + immigration_status: CITIZEN + ca_calworks_child_care_provider_category: CHILD_CARE_CENTER + ca_calworks_child_care_time_category: MONTHLY + ca_calworks_child_care_full_time: true + pre_subsidy_childcare_expenses: 24_000 + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: false + households: + household: + members: [person1, person2] + state_code: CA + output: + # Income above 85% SMI = not eligible for any program + ca_child_care_income_eligible: false + ca_calworks_stage_2_eligible: false + ca_calworks_stage_3_eligible: false + ca_capp_eligible: false + # Total subsidies: none eligible = 0 + ca_child_care_subsidies: 0 + +- name: Case 7, two children, Stage 2. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 60_000 + ca_calworks_child_care_provider_category: CHILD_CARE_CENTER + ca_calworks_child_care_time_category: MONTHLY + ca_calworks_child_care_full_time: true + pre_subsidy_childcare_expenses: 0 + person2: + age: 3 + immigration_status: CITIZEN + ca_calworks_child_care_provider_category: CHILD_CARE_CENTER + ca_calworks_child_care_time_category: MONTHLY + ca_calworks_child_care_full_time: true + pre_subsidy_childcare_expenses: 24_000 + person3: + age: 6 + immigration_status: CITIZEN + ca_calworks_child_care_provider_category: CHILD_CARE_CENTER + ca_calworks_child_care_time_category: MONTHLY + ca_calworks_child_care_full_time: true + pre_subsidy_childcare_expenses: 24_000 + spm_units: + spm_unit: + members: [person1, person2, person3] + was_calworks_recipient: true + months_since_calworks_exit: 18 + households: + household: + members: [person1, person2, person3] + state_code: CA + output: + ca_calworks_stage_2_eligible: true + # Payments for two children (RMR ceilings) + # person2 (3 yo, middle): 1,253.26, person3 (6 yo, older): 1,001.50 + ca_calworks_stage_2_payment: [0, 1_253.26, 1_001.5] + # Family fee: income 5,000/month for 3-person, below 75% SMI (5,821) = exempt + ca_child_care_family_fee: 0 + # Final Stage 2: 1,253.26 + 1,001.5 = 2,254.76 + ca_calworks_stage_2: 2_254.76 + # Total subsidies: Stage 2 only = 2,254.76 + ca_child_care_subsidies: 2_254.76 + +- name: Case 8, YEAR period test for Stage 2. + absolute_error_margin: 0.1 + period: 2025 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 48_000 + ca_calworks_child_care_provider_category: CHILD_CARE_CENTER + ca_calworks_child_care_time_category: MONTHLY + ca_calworks_child_care_full_time: true + pre_subsidy_childcare_expenses: 24_000 + person2: + age: 3 + immigration_status: CITIZEN + ca_calworks_child_care_provider_category: CHILD_CARE_CENTER + ca_calworks_child_care_time_category: MONTHLY + ca_calworks_child_care_full_time: true + pre_subsidy_childcare_expenses: 24_000 + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: true + months_since_calworks_exit: 12 + households: + household: + members: [person1, person2] + state_code: CA + output: + # Testing with YEAR period + ca_calworks_stage_2_eligible: true + # Annual Stage 2 payment (child only): 1,253.26 * 12 = 15,039.12 + ca_calworks_stage_2: 15_039.12 + # Total subsidies: Stage 2 only = 15,039.12 + ca_child_care_subsidies: 15_039.12 + +- name: Case 9, basic inputs with minimal child care variables. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 3_600 # $300/month + person2: + age: 3 + pre_subsidy_childcare_expenses: 24_000 + ca_calworks_child_care_time_category: MONTHLY + households: + household: + state_code: CA + output: + # Low income qualifies for TANF -> Stage 1 child care, not CAPP + ca_tanf_eligible: true + ca_calworks_child_care_eligible: true + ca_capp_eligible: false # Not CAPP because currently TANF eligible + # Part-time rate (childcare_hours_per_week defaults to 0 -> full_time = false) + ca_calworks_child_care_full_time: [false, false] + # Payment standard: part-time rate for middle age group at child care center + ca_calworks_child_care_payment_standard: [0, 793.85] + # Stage 1 payment + ca_calworks_child_care_payment: [0, 793.85] + # Total subsidies: Stage 1 only (no double counting) + ca_child_care_subsidies: 793.85 + +- name: Case 10, YEAR period test for Stage 3 (25 months since exit). + absolute_error_margin: 0.1 + period: 2025 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 48_000 + ca_calworks_child_care_provider_category: CHILD_CARE_CENTER + ca_calworks_child_care_time_category: MONTHLY + ca_calworks_child_care_full_time: true + pre_subsidy_childcare_expenses: 24_000 + person2: + age: 3 + immigration_status: CITIZEN + ca_calworks_child_care_provider_category: CHILD_CARE_CENTER + ca_calworks_child_care_time_category: MONTHLY + ca_calworks_child_care_full_time: true + pre_subsidy_childcare_expenses: 24_000 + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: true + months_since_calworks_exit: 25 + households: + household: + members: [person1, person2] + state_code: CA + output: + # Testing with YEAR period, 25 months since exit = Stage 3 + ca_calworks_stage_2_eligible: false + ca_calworks_stage_3_eligible: true + # Annual Stage 3 payment (child only): 1,253.26 * 12 = 15,039.12 + ca_calworks_stage_3: 15_039.12 + # Total subsidies: Stage 3 only = 15,039.12 + ca_child_care_subsidies: 15_039.12 + +- name: Case 11, YEAR period test with minimal child care variables. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 3_600 # $300/month + person2: + age: 3 + pre_subsidy_childcare_expenses: 24_000 + ca_calworks_child_care_time_category: MONTHLY + households: + household: + state_code: CA + output: + # Low income qualifies for TANF -> Stage 1 child care, not CAPP + ca_tanf_eligible: true + ca_calworks_child_care_eligible: true + ca_capp_eligible: false + # Annual Stage 1 payment: 793.85 * 12 = 9,526.2 + ca_calworks_child_care_payment: [0, 9_526.2] + # Total subsidies: Stage 1 only = 9,526.2 + ca_child_care_subsidies: 9_526.2 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/stage_2/ca_calworks_stage_2_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/stage_2/ca_calworks_stage_2_eligible.yaml new file mode 100644 index 00000000000..1a0a36eddab --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/stage_2/ca_calworks_stage_2_eligible.yaml @@ -0,0 +1,190 @@ +- name: Case 1, former CalWORKs recipient within 24 months, eligible. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 48_000 + person2: + age: 5 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: true + months_since_calworks_exit: 12 + households: + household: + members: [person1, person2] + state_code: CA + output: + ca_calworks_stage_2_eligible: true + +- name: Case 2, former CalWORKs recipient beyond 24 months, not eligible. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 48_000 + person2: + age: 5 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: true + months_since_calworks_exit: 30 + households: + household: + members: [person1, person2] + state_code: CA + output: + # Beyond 24 months = Stage 3, not Stage 2 + ca_calworks_stage_2_eligible: false + +- name: Case 3, never received CalWORKs, not eligible. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 48_000 + person2: + age: 5 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: false + months_since_calworks_exit: 0 + households: + household: + members: [person1, person2] + state_code: CA + output: + # Never received CalWORKs = not eligible for Stage 2 + ca_calworks_stage_2_eligible: false + +- name: Case 4, currently receiving CalWORKs, not eligible for Stage 2. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 24_000 + person2: + age: 5 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: true + months_since_calworks_exit: 0 + ca_tanf: 500 + households: + household: + members: [person1, person2] + state_code: CA + output: + # Currently receiving TANF = Stage 1, not Stage 2 + ca_calworks_stage_2_eligible: false + +- name: Case 5, income above 85 percent SMI, not eligible. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 120_000 + person2: + age: 5 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: true + months_since_calworks_exit: 12 + households: + household: + members: [person1, person2] + state_code: CA + output: + # Income too high + ca_calworks_stage_2_eligible: false + +- name: Case 6, exactly 24 months since exit, still Stage 2 eligible. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 48_000 + person2: + age: 5 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: true + months_since_calworks_exit: 24 + households: + household: + members: [person1, person2] + state_code: CA + output: + # Exactly 24 months: uses <= 24, so still Stage 2 + ca_calworks_stage_2_eligible: true + +- name: Case 7, zero months since exit with no current TANF, Stage 2 eligible. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 48_000 + person2: + age: 5 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: true + households: + household: + members: [person1, person2] + state_code: CA + output: + # Just left CalWORKs this month (0 months), no current TANF = Stage 2 + ca_calworks_stage_2_eligible: true + +- name: Case 8, TANF equals one cent, still Stage 1 not Stage 2. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 24_000 + person2: + age: 5 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: true + ca_tanf: 0.01 + households: + household: + members: [person1, person2] + state_code: CA + output: + # Any positive TANF (even $0.01) means currently receiving = Stage 1 + ca_calworks_stage_2_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/stage_2/ca_calworks_stage_2_payment.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/stage_2/ca_calworks_stage_2_payment.yaml new file mode 100644 index 00000000000..8785343b514 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/stage_2/ca_calworks_stage_2_payment.yaml @@ -0,0 +1,35 @@ +- name: Case 1, Stage 2 payment uses RMR structure. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 48_000 + ca_calworks_child_care_provider_category: CHILD_CARE_CENTER + ca_calworks_child_care_time_category: MONTHLY + ca_calworks_child_care_full_time: true + pre_subsidy_childcare_expenses: 24_000 + person2: + age: 3 + immigration_status: CITIZEN + ca_calworks_child_care_provider_category: CHILD_CARE_CENTER + ca_calworks_child_care_time_category: MONTHLY + ca_calworks_child_care_full_time: true + pre_subsidy_childcare_expenses: 24_000 + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: true + months_since_calworks_exit: 12 + households: + household: + members: [person1, person2] + state_code: CA + output: + # Child (person2) receives payment based on RMR ceiling + # RMR for 3-year-old at child care center, full-time monthly: ~1,253 + # pre_subsidy_childcare_expenses: 24,000 annual / 12 = 2,000/month + # Payment = min(1,253, 2,000) = 1,253 + # Adult (person1) does not receive child care payment + ca_calworks_stage_2_payment: [0, 1_253.26] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/stage_3/ca_calworks_stage_3_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/stage_3/ca_calworks_stage_3_eligible.yaml new file mode 100644 index 00000000000..4c491859b10 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/stage_3/ca_calworks_stage_3_eligible.yaml @@ -0,0 +1,143 @@ +- name: Case 1, former CalWORKs recipient beyond 24 months, eligible for Stage 3. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 48_000 + person2: + age: 5 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: true + months_since_calworks_exit: 30 + households: + household: + members: [person1, person2] + state_code: CA + output: + # Beyond 24 months = eligible for Stage 3 + ca_calworks_stage_3_eligible: true + +- name: Case 2, former CalWORKs recipient within 24 months, not eligible for Stage 3. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 48_000 + person2: + age: 5 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: true + months_since_calworks_exit: 12 + households: + household: + members: [person1, person2] + state_code: CA + output: + # Within 24 months = Stage 2, not Stage 3 + ca_calworks_stage_3_eligible: false + +- name: Case 3, never received CalWORKs, not eligible for Stage 3. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 48_000 + person2: + age: 5 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: false + months_since_calworks_exit: 0 + households: + household: + members: [person1, person2] + state_code: CA + output: + # Never received CalWORKs = not eligible for Stage 3 + ca_calworks_stage_3_eligible: false + +- name: Case 4, income above 85 percent SMI, not eligible. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 120_000 + person2: + age: 5 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: true + months_since_calworks_exit: 30 + households: + household: + members: [person1, person2] + state_code: CA + output: + # Income too high + ca_calworks_stage_3_eligible: false + +- name: Case 5, exactly 25 months since exit, first month of Stage 3. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 48_000 + person2: + age: 5 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: true + months_since_calworks_exit: 25 + households: + household: + members: [person1, person2] + state_code: CA + output: + # 25 months > 24 = first month of Stage 3 eligibility + ca_calworks_stage_3_eligible: true + +- name: Case 6, exactly 24 months since exit, not yet Stage 3. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 48_000 + person2: + age: 5 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: true + months_since_calworks_exit: 24 + households: + household: + members: [person1, person2] + state_code: CA + output: + # Exactly 24 months: uses > 24 for Stage 3, so not eligible yet + ca_calworks_stage_3_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/stage_3/ca_calworks_stage_3_payment.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/stage_3/ca_calworks_stage_3_payment.yaml new file mode 100644 index 00000000000..1d73a31f6a0 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/child_care/stage_3/ca_calworks_stage_3_payment.yaml @@ -0,0 +1,35 @@ +- name: Case 1, Stage 3 payment uses RMR structure. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income: 48_000 + ca_calworks_child_care_provider_category: CHILD_CARE_CENTER + ca_calworks_child_care_time_category: MONTHLY + ca_calworks_child_care_full_time: true + pre_subsidy_childcare_expenses: 24_000 + person2: + age: 3 + immigration_status: CITIZEN + ca_calworks_child_care_provider_category: CHILD_CARE_CENTER + ca_calworks_child_care_time_category: MONTHLY + ca_calworks_child_care_full_time: true + pre_subsidy_childcare_expenses: 24_000 + spm_units: + spm_unit: + members: [person1, person2] + was_calworks_recipient: true + months_since_calworks_exit: 30 + households: + household: + members: [person1, person2] + state_code: CA + output: + # Child (person2) receives payment based on RMR ceiling + # RMR for 3-year-old at child care center, full-time monthly: ~1,253 + # pre_subsidy_childcare_expenses: 24,000 annual / 12 = 2,000/month + # Payment = min(1,253, 2,000) = 1,253 + # Adult (person1) does not receive child care payment + ca_calworks_stage_3_payment: [0, 1_253.26] diff --git a/policyengine_us/variables/gov/states/ca/ca_child_care_subsidies.py b/policyengine_us/variables/gov/states/ca/ca_child_care_subsidies.py index caf58776cf9..4d6f09fe794 100644 --- a/policyengine_us/variables/gov/states/ca/ca_child_care_subsidies.py +++ b/policyengine_us/variables/gov/states/ca/ca_child_care_subsidies.py @@ -6,6 +6,12 @@ class ca_child_care_subsidies(Variable): entity = SPMUnit label = "California child care subsidies" unit = USD - definition_period = YEAR + definition_period = MONTH defined_for = StateCode.CA - adds = ["ca_calworks_child_care"] + reference = "https://leginfo.legislature.ca.gov/faces/codes_displayText.xhtml?lawCode=WIC&division=9.&title=&part=1.8.&chapter=2.&article=" + adds = [ + "ca_calworks_child_care", + "ca_calworks_stage_2", + "ca_calworks_stage_3", + "ca_capp", + ] diff --git a/policyengine_us/variables/gov/states/ca/cdss/child_care/capp/ca_capp.py b/policyengine_us/variables/gov/states/ca/cdss/child_care/capp/ca_capp.py new file mode 100644 index 00000000000..82a1f9d05cf --- /dev/null +++ b/policyengine_us/variables/gov/states/ca/cdss/child_care/capp/ca_capp.py @@ -0,0 +1,16 @@ +from policyengine_us.model_api import * + + +class ca_capp(Variable): + value_type = float + entity = SPMUnit + label = "California Alternative Payment Program subsidy" + unit = USD + definition_period = MONTH + defined_for = "ca_capp_eligible" + reference = "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=10271.&lawCode=WIC" + + def formula(spm_unit, period, parameters): + gross_payment = add(spm_unit, period, ["ca_capp_payment"]) + family_fee = spm_unit("ca_child_care_family_fee", period) + return max_(gross_payment - family_fee, 0) diff --git a/policyengine_us/variables/gov/states/ca/cdss/child_care/capp/ca_capp_eligible.py b/policyengine_us/variables/gov/states/ca/cdss/child_care/capp/ca_capp_eligible.py new file mode 100644 index 00000000000..a45247950a0 --- /dev/null +++ b/policyengine_us/variables/gov/states/ca/cdss/child_care/capp/ca_capp_eligible.py @@ -0,0 +1,39 @@ +from policyengine_us.model_api import * + + +class ca_capp_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for California Alternative Payment Program" + definition_period = MONTH + defined_for = StateCode.CA + reference = "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=10271.&lawCode=WIC" + + def formula(spm_unit, period, parameters): + # CAPP is for families who have NEVER received CalWORKs + ever_received = spm_unit("was_calworks_recipient", period.this_year) + + # Not currently receiving CalWORKs cash aid + currently_receiving = spm_unit("ca_tanf", period) > 0 + + not_calworks_recipient = ~ever_received & ~currently_receiving + + # Income must be at or below 85% SMI + income_eligible = spm_unit("ca_child_care_income_eligible", period) + + # Must have a need for child care (work requirement) + need_eligible = spm_unit( + "ca_calworks_child_care_meets_work_requirement", period.this_year + ) + + # Must have age-eligible children + age_eligible = spm_unit("ca_calworks_child_care_age_eligible", period) + + # NOTE: CAPP is subject to funding availability and waitlists, + # which cannot be modeled in PolicyEngine. We assume enrollment. + return ( + not_calworks_recipient + & income_eligible + & need_eligible + & age_eligible + ) diff --git a/policyengine_us/variables/gov/states/ca/cdss/child_care/capp/ca_capp_payment.py b/policyengine_us/variables/gov/states/ca/cdss/child_care/capp/ca_capp_payment.py new file mode 100644 index 00000000000..4120ae0a652 --- /dev/null +++ b/policyengine_us/variables/gov/states/ca/cdss/child_care/capp/ca_capp_payment.py @@ -0,0 +1,29 @@ +from policyengine_us.model_api import * + + +class ca_capp_payment(Variable): + value_type = float + entity = Person + label = "California Alternative Payment Program payment" + unit = USD + definition_period = MONTH + defined_for = "ca_capp_eligible" + reference = "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=10271.&lawCode=WIC" + + def formula(person, period, parameters): + # CAPP uses same RMR payment structure as CalWORKs child care + payment_standard = person( + "ca_calworks_child_care_payment_standard", period + ) + time_coefficient = person( + "ca_calworks_child_care_time_coefficient", period + ) + payment_factor = person( + "ca_calworks_child_care_payment_factor", period + ) + childcare_expenses = person("pre_subsidy_childcare_expenses", period) + + return min_( + payment_standard * time_coefficient * payment_factor, + childcare_expenses, + ) diff --git a/policyengine_us/variables/gov/states/ca/cdss/child_care/common/ca_child_care_countable_income.py b/policyengine_us/variables/gov/states/ca/cdss/child_care/common/ca_child_care_countable_income.py new file mode 100644 index 00000000000..0fabdaf69ed --- /dev/null +++ b/policyengine_us/variables/gov/states/ca/cdss/child_care/common/ca_child_care_countable_income.py @@ -0,0 +1,15 @@ +from policyengine_us.model_api import * + + +class ca_child_care_countable_income(Variable): + value_type = float + entity = SPMUnit + label = "California child care countable income" + unit = USD + definition_period = MONTH + defined_for = StateCode.CA + reference = ( + "https://www.law.cornell.edu/regulations/california/5-CCR-18078" + ) + + adds = "gov.states.ca.cdss.child_care.income.sources" diff --git a/policyengine_us/variables/gov/states/ca/cdss/child_care/common/ca_child_care_family_fee.py b/policyengine_us/variables/gov/states/ca/cdss/child_care/common/ca_child_care_family_fee.py new file mode 100644 index 00000000000..afb6f81f7f0 --- /dev/null +++ b/policyengine_us/variables/gov/states/ca/cdss/child_care/common/ca_child_care_family_fee.py @@ -0,0 +1,25 @@ +from policyengine_us.model_api import * + + +class ca_child_care_family_fee(Variable): + value_type = float + entity = SPMUnit + label = "California child care family fee" + unit = USD + definition_period = MONTH + defined_for = StateCode.CA + reference = "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=10290.&lawCode=WIC" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ca.cdss.child_care + smi = spm_unit("ca_child_care_smi", period) + income = spm_unit("ca_child_care_countable_income", period) + + # Families below 75% SMI are exempt from fees + fee_exemption_threshold = smi * p.family_fees.exemption_threshold + exempt = income < fee_exemption_threshold + + # Fee capped at 1% of adjusted monthly income for families at/above 75% SMI + fee_amount = income * p.family_fees.fee_cap + + return where(exempt, 0, fee_amount) diff --git a/policyengine_us/variables/gov/states/ca/cdss/child_care/common/ca_child_care_income_eligible.py b/policyengine_us/variables/gov/states/ca/cdss/child_care/common/ca_child_care_income_eligible.py new file mode 100644 index 00000000000..20b7f59e8e6 --- /dev/null +++ b/policyengine_us/variables/gov/states/ca/cdss/child_care/common/ca_child_care_income_eligible.py @@ -0,0 +1,16 @@ +from policyengine_us.model_api import * + + +class ca_child_care_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "California child care income eligible" + definition_period = MONTH + defined_for = StateCode.CA + reference = "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=10271.5.&lawCode=WIC" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ca.cdss.child_care.income + smi = spm_unit("ca_child_care_smi", period) + income = spm_unit("ca_child_care_countable_income", period) + return income <= smi * p.income_limit diff --git a/policyengine_us/variables/gov/states/ca/cdss/child_care/common/ca_child_care_smi.py b/policyengine_us/variables/gov/states/ca/cdss/child_care/common/ca_child_care_smi.py new file mode 100644 index 00000000000..f05eac59399 --- /dev/null +++ b/policyengine_us/variables/gov/states/ca/cdss/child_care/common/ca_child_care_smi.py @@ -0,0 +1,26 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.hhs.hhs_smi import smi + + +class ca_child_care_smi(Variable): + value_type = float + entity = SPMUnit + label = "California child care State Median Income" + unit = USD + definition_period = MONTH + defined_for = StateCode.CA + reference = "https://www.cde.ca.gov/sp/cd/ci/mb2505.asp" + + def formula(spm_unit, period, parameters): + # California uses July 1 fiscal year for SMI + year = period.start.year + month = period.start.month + if month >= 7: + instant_str = f"{year}-07-01" + else: + instant_str = f"{year - 1}-07-01" + + size = spm_unit("spm_unit_size", period.this_year) + state = spm_unit.household("state_code_str", period.this_year) + + return smi(size, state, instant_str, parameters) / MONTHS_IN_YEAR diff --git a/policyengine_us/variables/gov/states/ca/cdss/child_care/common/months_since_calworks_exit.py b/policyengine_us/variables/gov/states/ca/cdss/child_care/common/months_since_calworks_exit.py new file mode 100644 index 00000000000..802466a89db --- /dev/null +++ b/policyengine_us/variables/gov/states/ca/cdss/child_care/common/months_since_calworks_exit.py @@ -0,0 +1,10 @@ +from policyengine_us.model_api import * + + +class months_since_calworks_exit(Variable): + value_type = int + entity = SPMUnit + label = "Months since CalWORKs cash aid ended" + definition_period = MONTH + defined_for = StateCode.CA + reference = "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=10372.&nodeTreePath=16.4.19&lawCode=WIC" diff --git a/policyengine_us/variables/gov/states/ca/cdss/child_care/common/was_calworks_recipient.py b/policyengine_us/variables/gov/states/ca/cdss/child_care/common/was_calworks_recipient.py new file mode 100644 index 00000000000..e7570aaaf1f --- /dev/null +++ b/policyengine_us/variables/gov/states/ca/cdss/child_care/common/was_calworks_recipient.py @@ -0,0 +1,11 @@ +from policyengine_us.model_api import * + + +class was_calworks_recipient(Variable): + value_type = bool + entity = SPMUnit + label = "Was a CalWORKs cash aid recipient" + definition_period = YEAR + defined_for = StateCode.CA + default_value = False + reference = "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=10372.&nodeTreePath=16.4.19&lawCode=WIC" diff --git a/policyengine_us/variables/gov/states/ca/cdss/child_care/stage_2/ca_calworks_stage_2.py b/policyengine_us/variables/gov/states/ca/cdss/child_care/stage_2/ca_calworks_stage_2.py new file mode 100644 index 00000000000..1235155bb49 --- /dev/null +++ b/policyengine_us/variables/gov/states/ca/cdss/child_care/stage_2/ca_calworks_stage_2.py @@ -0,0 +1,16 @@ +from policyengine_us.model_api import * + + +class ca_calworks_stage_2(Variable): + value_type = float + entity = SPMUnit + label = "California CalWORKs Stage 2 child care subsidy" + unit = USD + definition_period = MONTH + defined_for = "ca_calworks_stage_2_eligible" + reference = "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=10372.&lawCode=WIC" + + def formula(spm_unit, period, parameters): + gross_payment = add(spm_unit, period, ["ca_calworks_stage_2_payment"]) + family_fee = spm_unit("ca_child_care_family_fee", period) + return max_(gross_payment - family_fee, 0) diff --git a/policyengine_us/variables/gov/states/ca/cdss/child_care/stage_2/ca_calworks_stage_2_eligible.py b/policyengine_us/variables/gov/states/ca/cdss/child_care/stage_2/ca_calworks_stage_2_eligible.py new file mode 100644 index 00000000000..4c20f994605 --- /dev/null +++ b/policyengine_us/variables/gov/states/ca/cdss/child_care/stage_2/ca_calworks_stage_2_eligible.py @@ -0,0 +1,43 @@ +from policyengine_us.model_api import * + + +class ca_calworks_stage_2_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for California CalWORKs Stage 2 child care" + definition_period = MONTH + defined_for = StateCode.CA + reference = "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=10372.&nodeTreePath=16.4.19&lawCode=WIC" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ca.cdss.child_care.stage_2 + + # Must have formerly received CalWORKs + ever_received = spm_unit("was_calworks_recipient", period.this_year) + + # Not currently receiving CalWORKs cash aid + currently_receiving = spm_unit("ca_tanf", period) > 0 + + # Must be within 24 months of leaving cash aid + months_since = spm_unit("months_since_calworks_exit", period) + within_time_limit = months_since <= p.time_limit_months + + # Must be off cash aid but within time limit + former_recipient = ( + ever_received & ~currently_receiving & within_time_limit + ) + + # Income must be at or below 85% SMI + income_eligible = spm_unit("ca_child_care_income_eligible", period) + + # Must have a need for child care (work requirement) + need_eligible = spm_unit( + "ca_calworks_child_care_meets_work_requirement", period.this_year + ) + + # Must have age-eligible children + age_eligible = spm_unit("ca_calworks_child_care_age_eligible", period) + + return ( + former_recipient & income_eligible & need_eligible & age_eligible + ) diff --git a/policyengine_us/variables/gov/states/ca/cdss/child_care/stage_2/ca_calworks_stage_2_payment.py b/policyengine_us/variables/gov/states/ca/cdss/child_care/stage_2/ca_calworks_stage_2_payment.py new file mode 100644 index 00000000000..94405a3822e --- /dev/null +++ b/policyengine_us/variables/gov/states/ca/cdss/child_care/stage_2/ca_calworks_stage_2_payment.py @@ -0,0 +1,29 @@ +from policyengine_us.model_api import * + + +class ca_calworks_stage_2_payment(Variable): + value_type = float + entity = Person + label = "California CalWORKs Stage 2 child care payment" + unit = USD + definition_period = MONTH + defined_for = "ca_calworks_stage_2_eligible" + reference = "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=10372.&lawCode=WIC" + + def formula(person, period, parameters): + # Uses same RMR payment structure as Stage 1 + payment_standard = person( + "ca_calworks_child_care_payment_standard", period + ) + time_coefficient = person( + "ca_calworks_child_care_time_coefficient", period + ) + payment_factor = person( + "ca_calworks_child_care_payment_factor", period + ) + childcare_expenses = person("pre_subsidy_childcare_expenses", period) + + return min_( + payment_standard * time_coefficient * payment_factor, + childcare_expenses, + ) diff --git a/policyengine_us/variables/gov/states/ca/cdss/child_care/stage_3/ca_calworks_stage_3.py b/policyengine_us/variables/gov/states/ca/cdss/child_care/stage_3/ca_calworks_stage_3.py new file mode 100644 index 00000000000..12929457ff1 --- /dev/null +++ b/policyengine_us/variables/gov/states/ca/cdss/child_care/stage_3/ca_calworks_stage_3.py @@ -0,0 +1,16 @@ +from policyengine_us.model_api import * + + +class ca_calworks_stage_3(Variable): + value_type = float + entity = SPMUnit + label = "California CalWORKs Stage 3 child care subsidy" + unit = USD + definition_period = MONTH + defined_for = "ca_calworks_stage_3_eligible" + reference = "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=10372.5.&lawCode=WIC" + + def formula(spm_unit, period, parameters): + gross_payment = add(spm_unit, period, ["ca_calworks_stage_3_payment"]) + family_fee = spm_unit("ca_child_care_family_fee", period) + return max_(gross_payment - family_fee, 0) diff --git a/policyengine_us/variables/gov/states/ca/cdss/child_care/stage_3/ca_calworks_stage_3_eligible.py b/policyengine_us/variables/gov/states/ca/cdss/child_care/stage_3/ca_calworks_stage_3_eligible.py new file mode 100644 index 00000000000..5fadf90125f --- /dev/null +++ b/policyengine_us/variables/gov/states/ca/cdss/child_care/stage_3/ca_calworks_stage_3_eligible.py @@ -0,0 +1,45 @@ +from policyengine_us.model_api import * + + +class ca_calworks_stage_3_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for California CalWORKs Stage 3 child care" + definition_period = MONTH + defined_for = StateCode.CA + reference = "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=10372.5.&nodeTreePath=16.4.19&lawCode=WIC" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ca.cdss.child_care.stage_2 + + # Must have formerly received CalWORKs + ever_received = spm_unit("was_calworks_recipient", period.this_year) + + # Not currently receiving CalWORKs cash aid + currently_receiving = spm_unit("ca_tanf", period) > 0 + + # Must have exhausted Stage 2 (more than 24 months since leaving cash aid) + months_since = spm_unit("months_since_calworks_exit", period) + exhausted_stage_2 = months_since > p.time_limit_months + + # Former recipient who exhausted Stage 2 + stage_3_recipient = ( + ever_received & ~currently_receiving & exhausted_stage_2 + ) + + # Income must be at or below 85% SMI + income_eligible = spm_unit("ca_child_care_income_eligible", period) + + # Must have a need for child care (work requirement) + need_eligible = spm_unit( + "ca_calworks_child_care_meets_work_requirement", period.this_year + ) + + # Must have age-eligible children + age_eligible = spm_unit("ca_calworks_child_care_age_eligible", period) + + # NOTE: Stage 3 is subject to funding availability, which cannot be + # modeled in PolicyEngine. We assume funding is available. + return ( + stage_3_recipient & income_eligible & need_eligible & age_eligible + ) diff --git a/policyengine_us/variables/gov/states/ca/cdss/child_care/stage_3/ca_calworks_stage_3_payment.py b/policyengine_us/variables/gov/states/ca/cdss/child_care/stage_3/ca_calworks_stage_3_payment.py new file mode 100644 index 00000000000..7fb1aeeb409 --- /dev/null +++ b/policyengine_us/variables/gov/states/ca/cdss/child_care/stage_3/ca_calworks_stage_3_payment.py @@ -0,0 +1,29 @@ +from policyengine_us.model_api import * + + +class ca_calworks_stage_3_payment(Variable): + value_type = float + entity = Person + label = "California CalWORKs Stage 3 child care payment" + unit = USD + definition_period = MONTH + defined_for = "ca_calworks_stage_3_eligible" + reference = "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=10372.5.&lawCode=WIC" + + def formula(person, period, parameters): + # Uses same RMR payment structure as Stage 1 and Stage 2 + payment_standard = person( + "ca_calworks_child_care_payment_standard", period + ) + time_coefficient = person( + "ca_calworks_child_care_time_coefficient", period + ) + payment_factor = person( + "ca_calworks_child_care_payment_factor", period + ) + childcare_expenses = person("pre_subsidy_childcare_expenses", period) + + return min_( + payment_standard * time_coefficient * payment_factor, + childcare_expenses, + )