diff --git a/changelog.d/nj-ccap.added.md b/changelog.d/nj-ccap.added.md new file mode 100644 index 00000000000..bc5e2f13340 --- /dev/null +++ b/changelog.d/nj-ccap.added.md @@ -0,0 +1 @@ +Add New Jersey Child Care Assistance Program (CCAP). diff --git a/policyengine_us/parameters/gov/hhs/ccdf/child_care_subsidy_programs.yaml b/policyengine_us/parameters/gov/hhs/ccdf/child_care_subsidy_programs.yaml index 4050e47c83e..45da5eb00b9 100644 --- a/policyengine_us/parameters/gov/hhs/ccdf/child_care_subsidy_programs.yaml +++ b/policyengine_us/parameters/gov/hhs/ccdf/child_care_subsidy_programs.yaml @@ -10,6 +10,7 @@ values: - vt_child_care_subsidies # Vermont Child Care Financial Assistance Program - nh_child_care_subsidies # New Hampshire Child Care Scholarship Program - pa_child_care_subsidies # Pennsylvania Child Care Works + - nj_child_care_subsidies # New Jersey Child Care Assistance Program - ri_child_care_subsidies # Rhode Island Child Care Assistance Program metadata: diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/ccap/activity_requirements/weekly_hours.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/activity_requirements/weekly_hours.yaml new file mode 100644 index 00000000000..83ba41407c1 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/activity_requirements/weekly_hours.yaml @@ -0,0 +1,11 @@ +description: New Jersey sets this amount as the minimum weekly hours of approved activity under the Child Care Assistance Program. +values: + 2024-01-01: 30 + +metadata: + unit: hour + period: year + label: New Jersey CCAP minimum weekly activity hours + reference: + - title: CCDF State Plan for NJ FFY 2025-2027, Section 2.2.2d + href: https://www.childcarenj.gov/ChildCareNJ/media/media_library/CCDF_State_Plan_for_New_Jersey_FFY25-27.pdf#page=21 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/ccap/activity_requirements/weekly_hours_redetermination.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/activity_requirements/weekly_hours_redetermination.yaml new file mode 100644 index 00000000000..733b7843c44 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/activity_requirements/weekly_hours_redetermination.yaml @@ -0,0 +1,12 @@ +description: New Jersey sets this amount as the minimum weekly hours of approved activity at redetermination under the Child Care Assistance Program. +values: + 2024-01-01: 20 + 2025-10-01: 25 + +metadata: + unit: hour + period: year + label: New Jersey CCAP minimum weekly activity hours at redetermination + reference: + - title: CCDF State Plan for NJ FFY 2025-2027, Section 2.2.2d + href: https://www.childcarenj.gov/ChildCareNJ/media/media_library/CCDF_State_Plan_for_New_Jersey_FFY25-27.pdf#page=21 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/ccap/age_group/months.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/age_group/months.yaml new file mode 100644 index 00000000000..93015298e06 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/age_group/months.yaml @@ -0,0 +1,28 @@ +description: New Jersey sets these age group boundaries in months under the Child Care Assistance Program. +metadata: + type: single_amount + threshold_unit: month + amount_unit: /1 + period: year + label: New Jersey CCAP age group by age in months + reference: + - title: CC-230 Maximum Child Care Payment Rates + href: https://www.childcarenj.gov/ChildCareNJ/media/media_library/Max_CC_Payment_Rates.pdf#page=1 + +brackets: + - threshold: + 2024-01-01: 0 + amount: + 2024-01-01: 0 + - threshold: + 2024-01-01: 18 + amount: + 2024-01-01: 1 + - threshold: + 2024-01-01: 30 + amount: + 2024-01-01: 2 + - threshold: + 2024-01-01: 60 + amount: + 2024-01-01: 3 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/ccap/age_threshold/child.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/age_threshold/child.yaml new file mode 100644 index 00000000000..b85801dcc7d --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/age_threshold/child.yaml @@ -0,0 +1,11 @@ +description: New Jersey limits the Child Care Assistance Program to children younger than this age. +values: + 2024-01-01: 13 + +metadata: + unit: year + period: year + label: New Jersey CCAP child age threshold + reference: + - title: CCDF State Plan for NJ FFY 2025-2027, Section 2.2.1 + href: https://www.childcarenj.gov/ChildCareNJ/media/media_library/CCDF_State_Plan_for_New_Jersey_FFY25-27.pdf#page=19 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/ccap/age_threshold/special_needs.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/age_threshold/special_needs.yaml new file mode 100644 index 00000000000..2a117863c4e --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/age_threshold/special_needs.yaml @@ -0,0 +1,11 @@ +description: New Jersey limits the Child Care Assistance Program to children with special needs younger than this age. +values: + 2024-01-01: 19 + +metadata: + unit: year + period: year + label: New Jersey CCAP special needs child age threshold + reference: + - title: CCDF State Plan for NJ FFY 2025-2027, Section 2.2.1b + href: https://www.childcarenj.gov/ChildCareNJ/media/media_library/CCDF_State_Plan_for_New_Jersey_FFY25-27.pdf#page=19 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/ccap/copay/first_child_ft_rate.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/copay/first_child_ft_rate.yaml new file mode 100644 index 00000000000..df690bd093f --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/copay/first_child_ft_rate.yaml @@ -0,0 +1,30 @@ +description: New Jersey sets this copayment percentage for the first child in full-time care under the Child Care Assistance Program. +metadata: + type: single_amount + threshold_unit: /1 + amount_unit: /1 + period: year + label: New Jersey CCAP first child full-time copayment rate by FPL ratio + reference: + - title: CC-236 Copayment Schedule + href: https://www.childcarenj.gov/ChildCareNJ/media/media_library/Copayment_Schedule.pdf#page=1 + - title: NJ DHS Important Information - Copayment + href: https://www.childcarenj.gov/Parents/CCAP/ImportantInfo + +brackets: + - threshold: + 2024-01-01: 0 + amount: + 2024-01-01: 0 + - threshold: + 2024-01-01: 1.0001 + amount: + 2024-01-01: 0 + 2024-08-01: 0.02 + 2026-03-01: 0.04 + - threshold: + 2024-01-01: 2.0001 + amount: + 2024-01-01: 0 + 2024-08-01: 0.03 + 2026-03-01: 0.05 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/ccap/copay/first_child_pt_rate.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/copay/first_child_pt_rate.yaml new file mode 100644 index 00000000000..5db6126fe26 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/copay/first_child_pt_rate.yaml @@ -0,0 +1,30 @@ +description: New Jersey sets this copayment percentage for the first child in part-time care under the Child Care Assistance Program. +metadata: + type: single_amount + threshold_unit: /1 + amount_unit: /1 + period: year + label: New Jersey CCAP first child part-time copayment rate by FPL ratio + reference: + - title: CC-236 Copayment Schedule + href: https://www.childcarenj.gov/ChildCareNJ/media/media_library/Copayment_Schedule.pdf#page=1 + - title: NJ DHS Important Information - Copayment + href: https://www.childcarenj.gov/Parents/CCAP/ImportantInfo + +brackets: + - threshold: + 2024-01-01: 0 + amount: + 2024-01-01: 0 + - threshold: + 2024-01-01: 1.0001 + amount: + 2024-01-01: 0 + 2024-08-01: 0.01 + 2026-03-01: 0.02 + - threshold: + 2024-01-01: 2.0001 + amount: + 2024-01-01: 0 + 2024-08-01: 0.015 + 2026-03-01: 0.025 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/ccap/copay/second_child_ft_rate.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/copay/second_child_ft_rate.yaml new file mode 100644 index 00000000000..e53fa121255 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/copay/second_child_ft_rate.yaml @@ -0,0 +1,29 @@ +description: New Jersey sets this additional copayment percentage for the second child in full-time care under the Child Care Assistance Program. +metadata: + type: single_amount + threshold_unit: /1 + amount_unit: /1 + period: year + label: New Jersey CCAP second child full-time copayment rate by FPL ratio + reference: + - title: CC-236 Copayment Schedule + href: https://www.childcarenj.gov/ChildCareNJ/media/media_library/Copayment_Schedule.pdf#page=1 + - title: NJ DHS Important Information - Copayment + href: https://www.childcarenj.gov/Parents/CCAP/ImportantInfo + +brackets: + - threshold: + 2024-01-01: 0 + amount: + 2024-01-01: 0 + - threshold: + 2024-01-01: 1.0001 + amount: + 2024-01-01: 0 + 2024-08-01: 0.01 + 2026-03-01: 0.02 + - threshold: + 2024-01-01: 2.0001 + amount: + 2024-01-01: 0 + 2024-08-01: 0.02 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/ccap/copay/second_child_pt_rate.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/copay/second_child_pt_rate.yaml new file mode 100644 index 00000000000..bceea0d344e --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/copay/second_child_pt_rate.yaml @@ -0,0 +1,29 @@ +description: New Jersey sets this additional copayment percentage for the second child in part-time care under the Child Care Assistance Program. +metadata: + type: single_amount + threshold_unit: /1 + amount_unit: /1 + period: year + label: New Jersey CCAP second child part-time copayment rate by FPL ratio + reference: + - title: CC-236 Copayment Schedule + href: https://www.childcarenj.gov/ChildCareNJ/media/media_library/Copayment_Schedule.pdf#page=1 + - title: NJ DHS Important Information - Copayment + href: https://www.childcarenj.gov/Parents/CCAP/ImportantInfo + +brackets: + - threshold: + 2024-01-01: 0 + amount: + 2024-01-01: 0 + - threshold: + 2024-01-01: 1.0001 + amount: + 2024-01-01: 0 + 2024-08-01: 0.005 + 2026-03-01: 0.01 + - threshold: + 2024-01-01: 2.0001 + amount: + 2024-01-01: 0 + 2024-08-01: 0.01 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/ccap/income/countable_income/sources.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/income/countable_income/sources.yaml new file mode 100644 index 00000000000..76a35a6809f --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/income/countable_income/sources.yaml @@ -0,0 +1,29 @@ +description: New Jersey counts these income sources under the Child Care Assistance Program. +values: + 2024-01-01: + - employment_income + - self_employment_income + - social_security_retirement + - social_security_disability + - social_security_survivors + - ssi + - dividend_income + - interest_income + - rental_income + - pension_income + - unemployment_compensation + - workers_compensation + - alimony_income + - child_support_received + # The following are counted per CCDF State Plan 2.2.4c but have no matching variables: + # - inheritance + # - any other source required for federal/state tax reporting + # Excluded: TANF cash benefits (WFNJ) + +metadata: + unit: list + period: year + label: New Jersey CCAP countable income sources + reference: + - title: CCDF State Plan for NJ FFY 2025-2027, Section 2.2.4c + href: https://www.childcarenj.gov/ChildCareNJ/media/media_library/CCDF_State_Plan_for_New_Jersey_FFY25-27.pdf#page=25 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/ccap/income/fpl_rate/continuing_eligibility.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/income/fpl_rate/continuing_eligibility.yaml new file mode 100644 index 00000000000..ce3cbefd1b5 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/income/fpl_rate/continuing_eligibility.yaml @@ -0,0 +1,13 @@ +description: New Jersey limits the Child Care Assistance Program to enrolled families with income at or below this share of the federal poverty level at redetermination. +values: + 2024-01-01: 2.5 + +metadata: + unit: /1 + period: year + label: New Jersey CCAP continuing eligibility FPL rate + reference: + - title: CC-229 Income Eligibility Schedule, Tier E (250% FPL) + href: https://www.childcarenj.gov/ChildCareNJ/media/media_library/Income_Eligibility_Schedule.pdf + - title: CCDF State Plan for NJ FFY 2025-2027, Section 2.5 + href: https://www.childcarenj.gov/ChildCareNJ/media/media_library/CCDF_State_Plan_for_New_Jersey_FFY25-27.pdf#page=34 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/ccap/income/fpl_rate/initial_eligibility.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/income/fpl_rate/initial_eligibility.yaml new file mode 100644 index 00000000000..d35250573f2 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/income/fpl_rate/initial_eligibility.yaml @@ -0,0 +1,13 @@ +description: New Jersey limits the Child Care Assistance Program to new applicants with income at or below this share of the federal poverty level. +values: + 2024-01-01: 2 + +metadata: + unit: /1 + period: year + label: New Jersey CCAP initial eligibility FPL rate + reference: + - title: CC-229 Income Eligibility Schedule, Tier D (200% FPL) + href: https://www.childcarenj.gov/ChildCareNJ/media/media_library/Income_Eligibility_Schedule.pdf + - title: CCDF State Plan for NJ FFY 2025-2027, Section 2.2.4 + href: https://www.childcarenj.gov/ChildCareNJ/media/media_library/CCDF_State_Plan_for_New_Jersey_FFY25-27.pdf#page=24 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/ccap/income/fpl_rate/smi_exit.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/income/fpl_rate/smi_exit.yaml new file mode 100644 index 00000000000..c9a7ea8e711 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/income/fpl_rate/smi_exit.yaml @@ -0,0 +1,13 @@ +description: New Jersey sets this share of State Median Income as the exit threshold under the Child Care Assistance Program. +values: + 2024-01-01: 0.85 + +metadata: + unit: /1 + period: year + label: New Jersey CCAP SMI exit threshold rate + reference: + - title: CC-229 Income Eligibility Schedule, 85% NJ SMI column + href: https://www.childcarenj.gov/ChildCareNJ/media/media_library/Income_Eligibility_Schedule.pdf + - title: CCDF State Plan for NJ FFY 2025-2027, Section 2.5 + href: https://www.childcarenj.gov/ChildCareNJ/media/media_library/CCDF_State_Plan_for_New_Jersey_FFY25-27.pdf#page=34 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/ccap/rates/aca_summer_camp.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/rates/aca_summer_camp.yaml new file mode 100644 index 00000000000..8b601db9de5 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/rates/aca_summer_camp.yaml @@ -0,0 +1,56 @@ +description: New Jersey provides these weekly reimbursement rates for ACA summer youth camps under the Child Care Assistance Program. +metadata: + period: week + unit: currency-USD + label: New Jersey CCAP ACA summer camp weekly rates + breakdown: + - nj_ccap_time_category + - nj_ccap_age_group + reference: + - title: CC-230 (02/25) Maximum Child Care Payment Rates, ACA Summer Youth Camps + href: https://www.childcarenj.gov/ChildCareNJ/media/media_library/Max_CC_Payment_Rates.pdf#page=4 + - title: CC-230 (02/24) Maximum Child Care Payment Rates, ACA Summer Youth Camps + href: http://www.bccap.org/wp-content/uploads/2024/03/Maximum-Child-Care-Payment-Rates-March-2024.pdf#page=4 + +# 2024-01-01 values are CC-230 (02/24) rates effective March 1, 2024, +# backdated to January 1 for microsimulation coverage. +# The prior (March 2023) rates could not be sourced. +FULL_TIME: + INFANT: + 2024-01-01: 0 + INFANT_SN: + 2024-01-01: 0 + TODDLER: + 2024-01-01: 0 + TODDLER_SN: + 2024-01-01: 0 + PRESCHOOL: + 2024-01-01: 0 + PRESCHOOL_SN: + 2024-01-01: 0 + SCHOOL_AGE: + 2024-01-01: 287.27 + 2025-03-01: 288.70 + SCHOOL_AGE_SN: + 2024-01-01: 364.83 + 2025-03-01: 366.65 + +PART_TIME: + INFANT: + 2024-01-01: 0 + INFANT_SN: + 2024-01-01: 0 + TODDLER: + 2024-01-01: 0 + TODDLER_SN: + 2024-01-01: 0 + PRESCHOOL: + 2024-01-01: 0 + PRESCHOOL_SN: + 2024-01-01: 0 + SCHOOL_AGE: + 2024-01-01: 143.63 + 2025-03-01: 144.35 + SCHOOL_AGE_SN: + 2024-01-01: 182.42 + 2025-03-01: 183.33 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/ccap/rates/approved_home.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/rates/approved_home.yaml new file mode 100644 index 00000000000..2412de4c27b --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/rates/approved_home.yaml @@ -0,0 +1,53 @@ +description: New Jersey provides these weekly reimbursement rates for approved home providers under the Child Care Assistance Program. +metadata: + period: week + unit: currency-USD + label: New Jersey CCAP approved home weekly rates + breakdown: + - nj_ccap_time_category + - nj_ccap_age_group + reference: + - title: CC-230 (02/25) Maximum Child Care Payment Rates, Approved Homes (FFN and In-Home) + href: https://www.childcarenj.gov/ChildCareNJ/media/media_library/Max_CC_Payment_Rates.pdf#page=3 + - title: CC-230 (02/24) Maximum Child Care Payment Rates, Approved Homes (FFN and In-Home) + href: http://www.bccap.org/wp-content/uploads/2024/03/Maximum-Child-Care-Payment-Rates-March-2024.pdf#page=3 + +# 2024-01-01 values are CC-230 (02/24) rates effective March 1, 2024, +# backdated to January 1 for microsimulation coverage. +# The prior (March 2023) rates could not be sourced. +# Rates unchanged between CC-230 (02/24) and CC-230 (02/25). +FULL_TIME: + INFANT: + 2024-01-01: 139.39 + INFANT_SN: + 2024-01-01: 158.79 + TODDLER: + 2024-01-01: 139.39 + TODDLER_SN: + 2024-01-01: 158.79 + PRESCHOOL: + 2024-01-01: 118.79 + PRESCHOOL_SN: + 2024-01-01: 139.39 + SCHOOL_AGE: + 2024-01-01: 118.79 + SCHOOL_AGE_SN: + 2024-01-01: 139.39 + +PART_TIME: + INFANT: + 2024-01-01: 69.70 + INFANT_SN: + 2024-01-01: 79.39 + TODDLER: + 2024-01-01: 69.70 + TODDLER_SN: + 2024-01-01: 79.39 + PRESCHOOL: + 2024-01-01: 59.39 + PRESCHOOL_SN: + 2024-01-01: 69.70 + SCHOOL_AGE: + 2024-01-01: 59.39 + SCHOOL_AGE_SN: + 2024-01-01: 69.70 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/ccap/rates/licensed_center.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/rates/licensed_center.yaml new file mode 100644 index 00000000000..cde19a8001a --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/rates/licensed_center.yaml @@ -0,0 +1,221 @@ +description: New Jersey provides these weekly reimbursement rates for licensed child care centers under the Child Care Assistance Program. +metadata: + period: week + unit: currency-USD + label: New Jersey CCAP licensed center weekly rates + breakdown: + - nj_ccap_time_category + - nj_ccap_grow_nj_kids_rating + - nj_ccap_age_group + reference: + - title: CC-230 (02/25) Maximum Child Care Payment Rates, Licensed Child Care Centers + href: https://www.childcarenj.gov/ChildCareNJ/media/media_library/Max_CC_Payment_Rates.pdf#page=1 + - title: CC-230 (02/24) Maximum Child Care Payment Rates, Licensed Child Care Centers + href: http://www.bccap.org/wp-content/uploads/2024/03/Maximum-Child-Care-Payment-Rates-March-2024.pdf#page=1 + +# 2024-01-01 values are CC-230 (02/24) rates effective March 1, 2024, +# backdated to January 1 for microsimulation coverage. +# The prior (March 2023) rates could not be sourced. +FULL_TIME: + NONE: + INFANT: + 2024-01-01: 363.04 + 2025-03-01: 366.67 + INFANT_SN: + 2024-01-01: 435.65 + 2025-03-01: 440.01 + TODDLER: + 2024-01-01: 321.55 + 2025-03-01: 326.56 + TODDLER_SN: + 2024-01-01: 385.86 + 2025-03-01: 391.87 + PRESCHOOL: + 2024-01-01: 287.27 + 2025-03-01: 291.57 + PRESCHOOL_SN: + 2024-01-01: 364.84 + 2025-03-01: 370.29 + SCHOOL_AGE: + 2024-01-01: 273.59 + 2025-03-01: 274.96 + SCHOOL_AGE_SN: + 2024-01-01: 347.46 + 2025-03-01: 349.20 + STAR_3: + INFANT: + 2024-01-01: 387.44 + 2025-03-01: 391.32 + INFANT_SN: + 2024-01-01: 464.93 + 2025-03-01: 469.58 + TODDLER: + 2024-01-01: 331.80 + 2025-03-01: 336.96 + TODDLER_SN: + 2024-01-01: 398.16 + 2025-03-01: 404.36 + PRESCHOOL: + 2024-01-01: 300.77 + 2025-03-01: 305.27 + PRESCHOOL_SN: + 2024-01-01: 381.98 + 2025-03-01: 387.70 + SCHOOL_AGE: + 2024-01-01: 273.59 + 2025-03-01: 274.96 + SCHOOL_AGE_SN: + 2024-01-01: 347.46 + 2025-03-01: 349.20 + STAR_4: + INFANT: + 2024-01-01: 398.29 + 2025-03-01: 402.27 + INFANT_SN: + 2024-01-01: 477.95 + 2025-03-01: 482.73 + TODDLER: + 2024-01-01: 340.39 + 2025-03-01: 345.68 + TODDLER_SN: + 2024-01-01: 408.46 + 2025-03-01: 414.82 + PRESCHOOL: + 2024-01-01: 308.10 + 2025-03-01: 312.71 + PRESCHOOL_SN: + 2024-01-01: 391.28 + 2025-03-01: 397.14 + SCHOOL_AGE: + 2024-01-01: 273.59 + 2025-03-01: 274.96 + SCHOOL_AGE_SN: + 2024-01-01: 347.46 + 2025-03-01: 349.20 + STAR_5: + INFANT: + 2024-01-01: 412.30 + 2025-03-01: 416.42 + INFANT_SN: + 2024-01-01: 494.76 + 2025-03-01: 499.70 + TODDLER: + 2024-01-01: 351.50 + 2025-03-01: 356.97 + TODDLER_SN: + 2024-01-01: 421.80 + 2025-03-01: 428.36 + PRESCHOOL: + 2024-01-01: 317.59 + 2025-03-01: 322.34 + PRESCHOOL_SN: + 2024-01-01: 403.34 + 2025-03-01: 409.37 + SCHOOL_AGE: + 2024-01-01: 273.59 + 2025-03-01: 274.96 + SCHOOL_AGE_SN: + 2024-01-01: 347.46 + 2025-03-01: 349.20 + +PART_TIME: + NONE: + INFANT: + 2024-01-01: 181.52 + 2025-03-01: 183.34 + INFANT_SN: + 2024-01-01: 217.83 + 2025-03-01: 220.00 + TODDLER: + 2024-01-01: 160.78 + 2025-03-01: 163.28 + TODDLER_SN: + 2024-01-01: 192.93 + 2025-03-01: 195.94 + PRESCHOOL: + 2024-01-01: 143.64 + 2025-03-01: 145.79 + PRESCHOOL_SN: + 2024-01-01: 182.42 + 2025-03-01: 185.15 + SCHOOL_AGE: + 2024-01-01: 136.79 + 2025-03-01: 137.48 + SCHOOL_AGE_SN: + 2024-01-01: 173.73 + 2025-03-01: 174.60 + STAR_3: + INFANT: + 2024-01-01: 193.72 + 2025-03-01: 195.66 + INFANT_SN: + 2024-01-01: 232.47 + 2025-03-01: 234.79 + TODDLER: + 2024-01-01: 165.90 + 2025-03-01: 168.48 + TODDLER_SN: + 2024-01-01: 199.08 + 2025-03-01: 202.18 + PRESCHOOL: + 2024-01-01: 150.39 + 2025-03-01: 152.64 + PRESCHOOL_SN: + 2024-01-01: 190.99 + 2025-03-01: 193.85 + SCHOOL_AGE: + 2024-01-01: 136.79 + 2025-03-01: 137.48 + SCHOOL_AGE_SN: + 2024-01-01: 173.73 + 2025-03-01: 174.60 + STAR_4: + INFANT: + 2024-01-01: 199.15 + 2025-03-01: 201.14 + INFANT_SN: + 2024-01-01: 238.97 + 2025-03-01: 241.36 + TODDLER: + 2024-01-01: 170.19 + 2025-03-01: 172.84 + TODDLER_SN: + 2024-01-01: 204.23 + 2025-03-01: 207.41 + PRESCHOOL: + 2024-01-01: 154.05 + 2025-03-01: 156.35 + PRESCHOOL_SN: + 2024-01-01: 195.64 + 2025-03-01: 198.57 + SCHOOL_AGE: + 2024-01-01: 136.79 + 2025-03-01: 137.48 + SCHOOL_AGE_SN: + 2024-01-01: 173.73 + 2025-03-01: 174.60 + STAR_5: + INFANT: + 2024-01-01: 206.15 + 2025-03-01: 208.21 + INFANT_SN: + 2024-01-01: 247.38 + 2025-03-01: 249.85 + TODDLER: + 2024-01-01: 175.75 + 2025-03-01: 178.48 + TODDLER_SN: + 2024-01-01: 210.90 + 2025-03-01: 214.18 + PRESCHOOL: + 2024-01-01: 158.80 + 2025-03-01: 161.17 + PRESCHOOL_SN: + 2024-01-01: 201.67 + 2025-03-01: 204.69 + SCHOOL_AGE: + 2024-01-01: 136.79 + 2025-03-01: 137.48 + SCHOOL_AGE_SN: + 2024-01-01: 173.73 + 2025-03-01: 174.60 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/ccap/rates/registered_family.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/rates/registered_family.yaml new file mode 100644 index 00000000000..e10bedee0ec --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/rates/registered_family.yaml @@ -0,0 +1,221 @@ +description: New Jersey provides these weekly reimbursement rates for registered family child care homes under the Child Care Assistance Program. +metadata: + period: week + unit: currency-USD + label: New Jersey CCAP registered family weekly rates + breakdown: + - nj_ccap_time_category + - nj_ccap_grow_nj_kids_rating + - nj_ccap_age_group + reference: + - title: CC-230 (02/25) Maximum Child Care Payment Rates, Registered Family Child Care Homes + href: https://www.childcarenj.gov/ChildCareNJ/media/media_library/Max_CC_Payment_Rates.pdf#page=2 + - title: CC-230 (02/24) Maximum Child Care Payment Rates, Registered Family Child Care Homes + href: http://www.bccap.org/wp-content/uploads/2024/03/Maximum-Child-Care-Payment-Rates-March-2024.pdf#page=2 + +# 2024-01-01 values are CC-230 (02/24) rates effective March 1, 2024, +# backdated to January 1 for microsimulation coverage. +# The prior (March 2023) rates could not be sourced. +FULL_TIME: + NONE: + INFANT: + 2024-01-01: 278.41 + 2025-03-01: 281.19 + INFANT_SN: + 2024-01-01: 312.78 + 2025-03-01: 315.91 + TODDLER: + 2024-01-01: 278.41 + 2025-03-01: 281.19 + TODDLER_SN: + 2024-01-01: 312.78 + 2025-03-01: 315.91 + PRESCHOOL: + 2024-01-01: 244.03 + 2025-03-01: 246.47 + PRESCHOOL_SN: + 2024-01-01: 278.41 + 2025-03-01: 281.19 + SCHOOL_AGE: + 2024-01-01: 244.03 + 2025-03-01: 245.25 + SCHOOL_AGE_SN: + 2024-01-01: 278.41 + 2025-03-01: 279.80 + STAR_3: + INFANT: + 2024-01-01: 320.18 + 2025-03-01: 323.38 + INFANT_SN: + 2024-01-01: 324.73 + 2025-03-01: 327.98 + TODDLER: + 2024-01-01: 302.32 + 2025-03-01: 305.34 + TODDLER_SN: + 2024-01-01: 314.27 + 2025-03-01: 317.42 + PRESCHOOL: + 2024-01-01: 290.36 + 2025-03-01: 293.27 + PRESCHOOL_SN: + 2024-01-01: 302.32 + 2025-03-01: 305.34 + SCHOOL_AGE: + 2024-01-01: 244.03 + 2025-03-01: 245.25 + SCHOOL_AGE_SN: + 2024-01-01: 278.41 + 2025-03-01: 279.80 + STAR_4: + INFANT: + 2024-01-01: 332.14 + 2025-03-01: 335.46 + INFANT_SN: + 2024-01-01: 336.69 + 2025-03-01: 340.06 + TODDLER: + 2024-01-01: 314.21 + 2025-03-01: 317.35 + TODDLER_SN: + 2024-01-01: 326.23 + 2025-03-01: 329.49 + PRESCHOOL: + 2024-01-01: 302.25 + 2025-03-01: 305.27 + PRESCHOOL_SN: + 2024-01-01: 314.21 + 2025-03-01: 317.35 + SCHOOL_AGE: + 2024-01-01: 244.03 + 2025-03-01: 245.25 + SCHOOL_AGE_SN: + 2024-01-01: 278.41 + 2025-03-01: 279.80 + STAR_5: + INFANT: + 2024-01-01: 346.24 + 2025-03-01: 349.71 + INFANT_SN: + 2024-01-01: 348.64 + 2025-03-01: 352.13 + TODDLER: + 2024-01-01: 328.31 + 2025-03-01: 331.59 + TODDLER_SN: + 2024-01-01: 340.33 + 2025-03-01: 343.74 + PRESCHOOL: + 2024-01-01: 316.36 + 2025-03-01: 319.52 + PRESCHOOL_SN: + 2024-01-01: 328.31 + 2025-03-01: 331.59 + SCHOOL_AGE: + 2024-01-01: 244.03 + 2025-03-01: 245.25 + SCHOOL_AGE_SN: + 2024-01-01: 278.41 + 2025-03-01: 279.80 + +PART_TIME: + NONE: + INFANT: + 2024-01-01: 139.20 + 2025-03-01: 140.60 + INFANT_SN: + 2024-01-01: 156.39 + 2025-03-01: 157.95 + TODDLER: + 2024-01-01: 139.20 + 2025-03-01: 140.60 + TODDLER_SN: + 2024-01-01: 156.39 + 2025-03-01: 157.95 + PRESCHOOL: + 2024-01-01: 122.02 + 2025-03-01: 123.24 + PRESCHOOL_SN: + 2024-01-01: 139.20 + 2025-03-01: 140.60 + SCHOOL_AGE: + 2024-01-01: 122.02 + 2025-03-01: 122.63 + SCHOOL_AGE_SN: + 2024-01-01: 139.20 + 2025-03-01: 139.90 + STAR_3: + INFANT: + 2024-01-01: 160.09 + 2025-03-01: 161.69 + INFANT_SN: + 2024-01-01: 162.37 + 2025-03-01: 163.99 + TODDLER: + 2024-01-01: 151.16 + 2025-03-01: 152.67 + TODDLER_SN: + 2024-01-01: 157.14 + 2025-03-01: 158.71 + PRESCHOOL: + 2024-01-01: 145.18 + 2025-03-01: 146.63 + PRESCHOOL_SN: + 2024-01-01: 151.16 + 2025-03-01: 152.67 + SCHOOL_AGE: + 2024-01-01: 122.02 + 2025-03-01: 122.63 + SCHOOL_AGE_SN: + 2024-01-01: 139.20 + 2025-03-01: 139.90 + STAR_4: + INFANT: + 2024-01-01: 166.07 + 2025-03-01: 167.73 + INFANT_SN: + 2024-01-01: 168.34 + 2025-03-01: 170.03 + TODDLER: + 2024-01-01: 157.10 + 2025-03-01: 158.67 + TODDLER_SN: + 2024-01-01: 163.11 + 2025-03-01: 164.74 + PRESCHOOL: + 2024-01-01: 151.12 + 2025-03-01: 152.64 + PRESCHOOL_SN: + 2024-01-01: 157.10 + 2025-03-01: 158.67 + SCHOOL_AGE: + 2024-01-01: 122.02 + 2025-03-01: 122.63 + SCHOOL_AGE_SN: + 2024-01-01: 139.20 + 2025-03-01: 139.90 + STAR_5: + INFANT: + 2024-01-01: 173.12 + 2025-03-01: 174.85 + INFANT_SN: + 2024-01-01: 174.32 + 2025-03-01: 176.07 + TODDLER: + 2024-01-01: 164.16 + 2025-03-01: 165.80 + TODDLER_SN: + 2024-01-01: 170.17 + 2025-03-01: 171.87 + PRESCHOOL: + 2024-01-01: 158.18 + 2025-03-01: 159.76 + PRESCHOOL_SN: + 2024-01-01: 164.16 + 2025-03-01: 165.80 + SCHOOL_AGE: + 2024-01-01: 122.02 + 2025-03-01: 122.63 + SCHOOL_AGE_SN: + 2024-01-01: 139.20 + 2025-03-01: 139.90 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/ccap/time_authorization/thresholds.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/time_authorization/thresholds.yaml new file mode 100644 index 00000000000..7300f40f291 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/ccap/time_authorization/thresholds.yaml @@ -0,0 +1,22 @@ +description: New Jersey sets these full-time and part-time care thresholds under the Child Care Assistance Program. +metadata: + type: single_amount + threshold_unit: hour + amount_unit: /1 + period: year + label: New Jersey CCAP time authorization thresholds + reference: + - title: CC-230 Maximum Child Care Payment Rates notes + href: https://www.childcarenj.gov/ChildCareNJ/media/media_library/Max_CC_Payment_Rates.pdf#page=1 + - title: CC-236 Copayment Schedule + href: https://www.childcarenj.gov/ChildCareNJ/media/media_library/Copayment_Schedule.pdf#page=1 + +brackets: + - threshold: + 2024-01-01: 0 + amount: + 2024-01-01: 1 + - threshold: + 2024-01-01: 30 + amount: + 2024-01-01: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/edge_cases.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/edge_cases.yaml new file mode 100644 index 00000000000..e877a27ac34 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/edge_cases.yaml @@ -0,0 +1,1047 @@ +# NJ CCAP Edge Case Tests +# Targets boundary conditions for eligibility, copay, age groups, provider rates, +# time categories, and assets. +# +# 2026 FPG (Contiguous US): first_person = 15_960, additional = 5_680 +# Family of 2: 21_640; 200% = 43_280; 250% = 54_100 +# Family of 3: 27_320; 200% = 54_640; 250% = 68_300 +# Family of 4: 33_000; 200% = 66_000; 250% = 82_500 +# Family of 8: 55_720; 200% = 111_440 +# CCDF asset limit: 1_000_000 + +# === Income threshold boundaries === + +- name: Case 1, income one dollar below 200% FPL for family of 2. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 43_279 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NJ + output: + # 43_279 < 43_280 (200% FPL) -> eligible + nj_ccap_income_eligible: true + +- name: Case 2, income one dollar above 200% FPL for family of 2. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 43_281 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NJ + output: + # 43_281 > 43_280 (200% FPL) -> ineligible for initial + nj_ccap_income_eligible: false + +- name: Case 3, enrolled family one dollar below 250% FPL. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 54_099 + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + nj_ccap_enrolled: true + households: + household: + members: [person1, person2] + state_code: NJ + output: + # 54_099 < 54_100 (250% FPL fam of 2) -> eligible + nj_ccap_income_eligible: true + +- name: Case 4, enrolled family above 250% FPL but below 85% SMI is eligible. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 54_101 + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + nj_ccap_enrolled: true + households: + household: + members: [person1, person2] + state_code: NJ + output: + # Enrolled -> uses 85% SMI (graduated phase-out) + # 85% SMI family of 2 = 88_516; 54_101 <= 88_516 -> eligible + nj_ccap_income_eligible: true + +# === Copay at FPL tier boundaries === + +- name: Case 5, copay at exactly 100% FPL is waived. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 21_640 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NJ + output: + # FPG fam of 2 = 21_640; FPL ratio = 21_640/21_640 = 1.0 + # 1.0 < 1.0001 -> still in 0% bracket -> copay waived + nj_ccap_copay: 0 + +- name: Case 6, copay just above 100% FPL enters 101-200% tier. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 21_700 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NJ + output: + # FPL ratio = 21_700/21_640 = 1.00277 + # 1.00277 >= 1.0001 -> 101-200% tier + # 1 child FT -> 2% + # monthly copay = 21_700 * 0.02 / 12 = 36.17 + nj_ccap_copay: 36.17 + +- name: Case 7, copay at exactly 200% FPL stays in 101-200% tier. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 43_280 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NJ + output: + # FPL ratio = 43_280/21_640 = 2.0 + # 2.0 < 2.0001 -> still in 101-200% tier + # 1 child FT -> 2% + # monthly copay = 43_280 * 0.02 / 12 = 72.13 + nj_ccap_copay: 72.13 + +- name: Case 8, copay just above 200% FPL enters 201%+ tier. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 43_340 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + nj_ccap_enrolled: true + households: + household: + members: [person1, person2] + state_code: NJ + output: + # FPL ratio = 43_340/21_640 = 2.00277 + # 2.00277 >= 2.0001 -> 201%+ tier + # 1 child FT -> 3% + # monthly copay = 43_340 * 0.03 / 12 = 108.35 + nj_ccap_copay: 108.35 + +# === Asset boundary === + +- name: Case 9, assets exactly at 1M limit is eligible. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 30_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000_000 + households: + household: + members: [person1, person2] + state_code: NJ + output: + # Assets 1_000_000 <= 1_000_000 -> asset eligible + is_ccdf_asset_eligible: true + nj_ccap_eligible: true + +- name: Case 10, assets one dollar over 1M limit is ineligible. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 30_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000_001 + households: + household: + members: [person1, person2] + state_code: NJ + output: + # Assets 1_000_001 > 1_000_000 -> asset ineligible + is_ccdf_asset_eligible: false + nj_ccap_eligible: false + +# === Age group month boundaries === +# age field is in years; age_in_months = age * 12 +# Boundary: 17 months (1.4167 yrs) = INFANT; 18 months (1.5 yrs) = TODDLER + +- name: Case 11, child at 17 months is infant. + period: 2026-01 + input: + people: + person1: + # 17 months = 17/12 = 1.4167 years + age: 1.4167 + households: + household: + members: [person1] + state_code: NJ + output: + # 1.4167 * 12 = 17.0 months < 18 -> INFANT + nj_ccap_age_group: INFANT + +- name: Case 12, child at 18 months is toddler. + period: 2026-01 + input: + people: + person1: + # 18 months = 1.5 years + age: 1.5 + households: + household: + members: [person1] + state_code: NJ + output: + # 1.5 * 12 = 18.0 months >= 18 -> TODDLER + nj_ccap_age_group: TODDLER + +- name: Case 13, child at 29 months is toddler. + period: 2026-01 + input: + people: + person1: + # 29 months = 29/12 = 2.4167 years + age: 2.4167 + households: + household: + members: [person1] + state_code: NJ + output: + # 2.4167 * 12 = 29.0 months < 30 -> TODDLER + nj_ccap_age_group: TODDLER + +- name: Case 14, child at 30 months is preschool. + period: 2026-01 + input: + people: + person1: + # 30 months = 2.5 years + age: 2.5 + households: + household: + members: [person1] + state_code: NJ + output: + # 2.5 * 12 = 30.0 months >= 30 -> PRESCHOOL + nj_ccap_age_group: PRESCHOOL + +- name: Case 15, child at 59 months is preschool. + period: 2026-01 + input: + people: + person1: + # 59 months = 59/12 = 4.9167 years + age: 4.9167 + households: + household: + members: [person1] + state_code: NJ + output: + # 4.9167 * 12 = 59.0 months < 60 -> PRESCHOOL + nj_ccap_age_group: PRESCHOOL + +- name: Case 16, child at 60 months is school age. + period: 2026-01 + input: + people: + person1: + # 60 months = 5.0 years + age: 5.0 + households: + household: + members: [person1] + state_code: NJ + output: + # 5.0 * 12 = 60.0 months >= 60 -> SCHOOL_AGE + nj_ccap_age_group: SCHOOL_AGE + +# === Time category boundary: 31 hours === + +- name: Case 17, childcare 31 hours is full time. + period: 2026-01 + input: + people: + person1: + childcare_hours_per_week: 31 + households: + household: + members: [person1] + state_code: NJ + output: + # 31 >= 30 -> FULL_TIME + nj_ccap_time_category: FULL_TIME + +# === Eligible child age boundaries === + +- name: Case 18, child exactly 13 years without disability is ineligible. + period: 2026-01 + input: + people: + person1: + age: 13 + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + # age 13 >= 13 -> not age eligible (not disabled) + nj_ccap_eligible_child: false + +- name: Case 19, child exactly 19 years with disability is ineligible. + period: 2026-01 + input: + people: + person1: + age: 19 + is_disabled: true + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + # age 19 >= 19 -> not age eligible even with disability + nj_ccap_eligible_child: false + +- name: Case 20, child exactly 18 years with disability is eligible. + period: 2026-01 + input: + people: + person1: + age: 18 + is_disabled: true + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + # age 18 < 19 -> age eligible with disability + nj_ccap_eligible_child: true + +# === Large family size === + +- name: Case 22, family of 8 at 200% FPL boundary. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 111_440 + immigration_status: CITIZEN + person2: + age: 38 + immigration_status: CITIZEN + person3: + age: 1 + is_tax_unit_dependent: true + immigration_status: CITIZEN + person4: + age: 3 + is_tax_unit_dependent: true + immigration_status: CITIZEN + person5: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + person6: + age: 8 + is_tax_unit_dependent: true + immigration_status: CITIZEN + person7: + age: 10 + is_tax_unit_dependent: true + immigration_status: CITIZEN + person8: + age: 12 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2, person3, person4, person5, person6, person7, person8] + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6, person7, person8] + households: + household: + members: [person1, person2, person3, person4, person5, person6, person7, person8] + state_code: NJ + output: + # FPG fam of 8: 15_960 + 7*5_680 = 55_720 + # 200% FPL = 111_440 + # 111_440 <= 111_440 -> eligible at boundary + nj_ccap_income_eligible: true + +# === All children ineligible === + +- name: Case 23, all children over 13 makes family ineligible. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + employment_income: 30_000 + immigration_status: CITIZEN + person2: + age: 14 + is_tax_unit_dependent: true + immigration_status: CITIZEN + person3: + age: 16 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_pre_subsidy_childcare_expenses: 10_000 + households: + household: + members: [person1, person2, person3] + state_code: NJ + output: + nj_ccap_eligible_child: [false, false, false] + nj_ccap_eligible: false + nj_ccap: 0 + +# === Single adult no children === + +- name: Case 24, single adult with no children is ineligible. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_pre_subsidy_childcare_expenses: 5_000 + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_eligible_child: [false] + nj_ccap_eligible: false + nj_ccap: 0 + +# === Provider rate lookups: registered family 5-star === + +- name: Case 25, registered family FT 5-star toddler rate. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 2 + childcare_hours_per_week: 35 + nj_ccap_provider_type: REGISTERED_FAMILY + nj_ccap_grow_nj_kids_rating: STAR_5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + # Registered family FT 5-star toddler = 331.59 + nj_ccap_maximum_weekly_benefit: 331.59 + +# === Provider rate: approved home special needs === + +- name: Case 26, approved home FT special needs preschool rate. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 4 + is_disabled: true + childcare_hours_per_week: 35 + nj_ccap_provider_type: APPROVED_HOME + nj_ccap_grow_nj_kids_rating: NONE + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + # Approved home FT PRESCHOOL_SN = 139.39 + nj_ccap_maximum_weekly_benefit: 139.39 + +# === ACA summer camp for non-school-age child gives $0 rate === + +- name: Case 27, ACA summer camp for preschool child gives zero rate. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 4 + childcare_hours_per_week: 35 + nj_ccap_provider_type: ACA_SUMMER_CAMP + nj_ccap_grow_nj_kids_rating: NONE + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + # ACA summer camp FT PRESCHOOL = 0 (camp is school-age only) + nj_ccap_maximum_weekly_benefit: 0 + +# === Third child confirms $0 additional copay (via full nj_ccap benefit) === + +- name: Case 28, three children FT confirms third child zero additional copay. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 50_000 + immigration_status: CITIZEN + person2: + age: 32 + immigration_status: CITIZEN + person3: + age: 1 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + person4: + age: 3 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + person5: + age: 7 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2, person3, person4, person5] + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + spm_unit_pre_subsidy_childcare_expenses: 30_000 + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: NJ + output: + # FPG fam of 5: 38_680; FPL ratio = 50_000/38_680 = 1.293 + # 3 children all FT at 101-200%: + # first child FT 2% + second child FT 1% + third child 0% = 3% + # copay = 50_000 * 0.03 / 12 = 125 + nj_ccap_copay: 125 + + # Rates: infant FT base = 366.67; preschool FT base = 291.57; school age FT base = 274.96 + nj_ccap_maximum_weekly_benefit: [0, 0, 366.67, 291.57, 274.96] + + # max annual = (366.67 + 291.57 + 274.96) * 52 = 933.20 * 52 = 48_526.40 + # annual copay = 50_000 * 0.03 = 1_500 + # uncapped = max(30_000 - 1_500, 0) = 28_500 + # annual benefit = min(28_500, 48_526.40) = 28_500 + # monthly = 28_500 / 12 = 2_375 + nj_ccap: 2_375 + +# === Activity requirement: hours exactly at boundary === + +- name: Case 29, parent at exactly 30 hours meets activity requirement. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 30_000 + immigration_status: CITIZEN + weekly_hours_worked: 30 + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NJ + output: + # 30 >= 30 -> meets activity requirement + nj_ccap_activity_eligible: true + +- name: Case 30, parent at 29 hours fails activity requirement. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 30_000 + immigration_status: CITIZEN + weekly_hours_worked: 29 + is_full_time_student: false + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NJ + output: + # 29 < 30 -> fails activity, not student -> ineligible + nj_ccap_activity_eligible: false + +# === Two-parent household where one fails activity === + +- name: Case 31, two parents one fails activity makes family ineligible. + period: 2026-01 + input: + people: + person1: + age: 35 + employment_income: 30_000 + immigration_status: CITIZEN + weekly_hours_worked: 40 + person2: + age: 32 + immigration_status: CITIZEN + weekly_hours_worked: 10 + is_full_time_student: false + person3: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: NJ + output: + # person1: 40 >= 30 -> meets work + # person2: 10 < 30 and not student -> fails + # Both heads/spouses must meet requirement + nj_ccap_activity_eligible: false + nj_ccap_eligible: false + +# === Zero income with zero deductions === + +- name: Case 32, zero income family gets full benefit up to rate cap. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 25 + immigration_status: CITIZEN + is_full_time_student: true + weekly_hours_worked: 0 + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 18_000 + households: + household: + members: [person1, person2] + state_code: NJ + output: + # Income = 0 -> income eligible, copay = 0 + nj_ccap_income_eligible: true + nj_ccap_copay: 0 + nj_ccap_countable_income: 0 + + # Toddler (24 mo) FT base center = 326.56 + nj_ccap_maximum_weekly_benefit: [0, 326.56] + + # max annual = 326.56 * 52 = 16_981.12 + # uncapped = max(18_000 - 0, 0) = 18_000 + # annual benefit = min(18_000, 16_981.12) = 16_981.12 + # monthly = 16_981.12 / 12 = 1_415.09 + nj_ccap: 1_415.09 + +# === Mixed copay: 1 FT + 1 PT at 201%+ with second child PT === + +- name: Case 33, mixed FT PT copay at 201%+ tier second child is PT. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 75_000 + immigration_status: CITIZEN + person2: + age: 32 + immigration_status: CITIZEN + person3: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + person4: + age: 7 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 20 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2, person3, person4] + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + nj_ccap_enrolled: true + households: + household: + members: [person1, person2, person3, person4] + state_code: NJ + output: + # FPG fam of 4: 33_000; FPL ratio = 75_000/33_000 = 2.273 + # 1 FT + 1 PT at 201%+: + # n_ft = 1 (person3 only); first child rate = FT 3% + # n_ft = 1 < 2; second child rate = PT 1% + # total rate = 3% + 1% = 4% + # copay = 75_000 * 0.04 / 12 = 250 + nj_ccap_copay: 250 + +# === Provider rate: registered family with star rating for school age = base === + +- name: Case 34, registered family 5-star school age gets base rate. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 8 + childcare_hours_per_week: 35 + nj_ccap_provider_type: REGISTERED_FAMILY + nj_ccap_grow_nj_kids_rating: STAR_5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + # Registered family FT 5-star school age = 245.25 (same as base) + nj_ccap_maximum_weekly_benefit: 245.25 + +# === Provider rate: ACA summer camp PT special needs school age === + +- name: Case 35, ACA summer camp PT special needs school age rate. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 10 + is_disabled: true + childcare_hours_per_week: 20 + nj_ccap_provider_type: ACA_SUMMER_CAMP + nj_ccap_grow_nj_kids_rating: NONE + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + # ACA summer camp PT SCHOOL_AGE_SN = 183.33 + nj_ccap_maximum_weekly_benefit: 183.33 + +# === Minimum family: 1 adult + 1 child, positive benefit === + +- name: Case 36, minimum family size with benefit. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 20 + employment_income: 18_000 + immigration_status: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 40 + nj_ccap_provider_type: APPROVED_HOME + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 8_000 + households: + household: + members: [person1, person2] + state_code: NJ + output: + # Parent (age 20 = 240 mo) -> SCHOOL_AGE; Newborn (0 mo) -> INFANT + nj_ccap_age_group: [SCHOOL_AGE, INFANT] + + # FPG fam of 2: 21_640; FPL ratio = 18_000/21_640 = 0.832 + # Below 100% FPL -> copay waived + nj_ccap_copay: 0 + + # Approved home FT infant = 139.39 + nj_ccap_maximum_weekly_benefit: [0, 139.39] + + # max annual = 139.39 * 52 = 7_248.28 + # uncapped = max(8_000 - 0, 0) = 8_000 + # annual benefit = min(8_000, 7_248.28) = 7_248.28 + # monthly = 7_248.28 / 12 = 604.02 + nj_ccap: 604.02 + +# === Redetermination activity threshold (20 hours) === + +- name: Case 37, enrolled parent at 25 hours meets redetermination activity requirement. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 30_000 + immigration_status: CITIZEN + weekly_hours_worked: 25 + is_full_time_student: false + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + nj_ccap_enrolled: true + households: + household: + members: [person1, person2] + state_code: NJ + output: + # Enrolled -> redetermination threshold = 20 hrs; 25 >= 20 -> eligible + nj_ccap_activity_eligible: true + +- name: Case 38, non-enrolled parent at 25 hours fails initial activity requirement. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 30_000 + immigration_status: CITIZEN + weekly_hours_worked: 25 + is_full_time_student: false + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NJ + output: + # Not enrolled -> initial threshold = 30 hrs; 25 < 30 -> ineligible + nj_ccap_activity_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/integration.yaml new file mode 100644 index 00000000000..6c8812b51e9 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/integration.yaml @@ -0,0 +1,418 @@ +# NJ CCAP Integration Tests +# 2026 FPG (Contiguous US): first_person = 15_960, additional = 5_680 +# Family of 2: 21_640; 200% = 43_280 +# Family of 3: 27_320; 200% = 54_640 +# Family of 4: 33_000; 200% = 66_000; 250% = 82_500 +# Family of 5: 38_680; 200% = 77_360 + +- name: Case 1, single parent one infant FT licensed center. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + employment_income: 31_000 + immigration_status: CITIZEN + person2: + age: 1 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 40 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 19_000 + households: + household: + members: [person1, person2] + state_code: NJ + output: + # === Eligibility === + # Child age 1 < 13 -> age eligible + # Citizen, dependent -> eligible child + nj_ccap_eligible_child: [false, true] + + # FPG family of 2: 21_640 + # 31_000 <= 43_280 (200% FPL) -> income eligible + nj_ccap_income_eligible: true + is_ccdf_asset_eligible: true + nj_ccap_eligible: true + + # === Copay === + # FPL ratio = 31_000 / 21_640 = 1.433 -> 101-200% FPL tier + # 1 child FT -> 2% of annual income + # annual copay = 31_000 * 0.02 = 620 + # monthly copay = 620 / 12 = 51.67 + nj_ccap_copay: 51.67 + + # === Provider rates === + # Parent (age 28 = 336 mo >= 60) -> SCHOOL_AGE; Child (age 1 = 12 mo < 18) -> INFANT + nj_ccap_age_group: [SCHOOL_AGE, INFANT] + # Parent: 0 hrs -> PART_TIME; Child: 40 hrs -> FULL_TIME + nj_ccap_time_category: [PART_TIME, FULL_TIME] + # Center FT Base Infant = $366.67/wk + nj_ccap_maximum_weekly_benefit: [0, 366.67] + + # === Benefit === + # max annual = 366.67 * 52 = 19_066.84 + # uncapped = max(19_000 - 620, 0) = 18_380 + # annual benefit = min(18_380, 19_066.84) = 18_380 + # monthly = 18_380 / 12 = 1_531.67 + nj_ccap: 1_531.67 + +- name: Case 2, single parent two children PT registered family low income. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 25 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 20 + nj_ccap_provider_type: REGISTERED_FAMILY + nj_ccap_grow_nj_kids_rating: NONE + person3: + age: 7 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 15 + nj_ccap_provider_type: REGISTERED_FAMILY + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_pre_subsidy_childcare_expenses: 12_000 + households: + household: + members: [person1, person2, person3] + state_code: NJ + output: + # === Eligibility === + nj_ccap_eligible_child: [false, true, true] + + # FPG family of 3: 27_320 + # 20_000 <= 54_640 (200% FPL) -> income eligible + nj_ccap_income_eligible: true + is_ccdf_asset_eligible: true + nj_ccap_eligible: true + + # === Copay === + # FPL ratio = 20_000 / 27_320 = 0.732 -> at or below 100% FPL -> waived + nj_ccap_copay: 0 + + # === Provider rates === + # Parent (age 25 = 300 mo >= 60) -> SCHOOL_AGE + # child1 (age 2 = 24 mo): >= 18, < 30 -> TODDLER + # child2 (age 7 = 84 mo): >= 60 -> SCHOOL_AGE + nj_ccap_age_group: [SCHOOL_AGE, TODDLER, SCHOOL_AGE] + # Parent: 0 hrs -> PT; child1: 20 hrs -> PT; child2: 15 hrs -> PT + nj_ccap_time_category: [PART_TIME, PART_TIME, PART_TIME] + # Registered family PT base toddler = $140.60; school age = $122.63 + nj_ccap_maximum_weekly_benefit: [0, 140.60, 122.63] + + # === Benefit === + # max annual = (140.60 + 122.63) * 52 = 263.23 * 52 = 13_687.96 + # uncapped = max(12_000 - 0, 0) = 12_000 + # annual benefit = min(12_000, 13_687.96) = 12_000 + # monthly = 12_000 / 12 = 1_000 + nj_ccap: 1_000 + +- name: Case 3, two parents one preschooler FT 5-star center enrolled at 220% FPL. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 70_000 + immigration_status: CITIZEN + person2: + age: 32 + immigration_status: CITIZEN + person3: + age: 3 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 40 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: STAR_5 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + nj_ccap_enrolled: true + spm_unit_pre_subsidy_childcare_expenses: 16_000 + households: + household: + members: [person1, person2, person3] + state_code: NJ + output: + # === Eligibility === + nj_ccap_eligible_child: [false, false, true] + + # FPG family of 3: 27_320 + # Enrolled -> uses 85% SMI (graduated phase-out) + # 85% SMI family of 3 = 113_577 / 12 = 9_464.75/mo + # Monthly income = 70_000 / 12 = 5_833.33 + # 5_833.33 <= 9_464.75 -> eligible + nj_ccap_income_eligible: true + nj_ccap_eligible: true + + # === Copay === + # FPL ratio = 70_000 / 27_320 = 2.562 (above 200% -> higher tier) + # 1 child FT at 201%+ FPL: 3% (CC-236 06/24 reinstatement rate) + # Monthly copay = 70_000 * 0.03 / 12 = 175 + nj_ccap_copay: 175 + + # === Rates === + # Preschool FT 5-star licensed center = $322.34/wk + nj_ccap_maximum_weekly_benefit: [0, 0, 322.34] + + # === Benefit === + # Expenses: 16_000 / 12 = 1_333.33/mo + # Uncapped: 1_333.33 - 175 = 1_158.33 + # Max reimbursement: 322.34 * 52 / 12 = 1_396.81 + # Benefit = min(1_158.33, 1_396.81) = 1_158.33 + nj_ccap: 1_158.33 + +- name: Case 4, family exactly at 200% FPL initial application. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 66_000 + immigration_status: CITIZEN + person2: + age: 32 + immigration_status: CITIZEN + person3: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: STAR_4 + person4: + age: 8 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 30 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: STAR_4 + tax_units: + tax_unit: + members: [person1, person2, person3, person4] + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2, person3, person4] + state_code: NJ + output: + # === Eligibility === + nj_ccap_eligible_child: [false, false, true, true] + + # FPG family of 4: 33_000; 200% = 66_000 + # 66_000 <= 66_000 -> exactly at limit -> eligible + nj_ccap_income_eligible: true + is_ccdf_asset_eligible: true + nj_ccap_eligible: true + + # === Copay === + # FPL ratio = 66_000 / 33_000 = 2.0 -> at 200% exactly + # Threshold for higher tier is 2.0001, so 2.0 < 2.0001 -> 101-200% tier + # 2 children both FT -> first child FT 2% + second child FT 1% = 3% (CC-236 06/24) + # copay = 66_000 * 0.03 / 12 = 165 + nj_ccap_copay: 165 + + # === Provider rates === + # Person1 (age 35 = 420 mo >= 60) -> SCHOOL_AGE; Person2 (age 32 = 384 mo >= 60) -> SCHOOL_AGE + # child1 (age 4 = 48 mo): PRESCHOOL; child2 (age 8 = 96 mo): SCHOOL_AGE + nj_ccap_age_group: [SCHOOL_AGE, SCHOOL_AGE, PRESCHOOL, SCHOOL_AGE] + nj_ccap_time_category: [PART_TIME, PART_TIME, FULL_TIME, FULL_TIME] + # Center FT Star 4 Preschool = 312.71; Center FT Star 4 School Age = 274.96 (base) + nj_ccap_maximum_weekly_benefit: [0, 0, 312.71, 274.96] + + # === Benefit === + # max annual = (312.71 + 274.96) * 52 = 587.67 * 52 = 30_558.84 + # annual copay = 66_000 * 0.03 = 1_980 + # uncapped = max(20_000 - 1_980, 0) = 18_020 + # annual benefit = min(18_020, 30_558.84) = 18_020 + # monthly = 18_020 / 12 = 1_501.67 + nj_ccap: 1_501.67 + +- name: Case 5, enrolled family at 240% FPL continuing eligible. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 79_200 + immigration_status: CITIZEN + person2: + age: 32 + immigration_status: CITIZEN + person3: + age: 1 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 40 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: STAR_3 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + nj_ccap_enrolled: true + spm_unit_pre_subsidy_childcare_expenses: 22_000 + households: + household: + members: [person1, person2, person3] + state_code: NJ + output: + # === Eligibility === + nj_ccap_eligible_child: [false, false, true] + + # FPG family of 3: 27_320 + # Enrolled -> uses 85% SMI (graduated phase-out) + # 85% SMI family of 3 = 113_577 / 12 = 9_464.75/mo + # Monthly income = 79_200 / 12 = 6_600 + # 6_600 <= 9_464.75 -> eligible + nj_ccap_income_eligible: true + nj_ccap_eligible: true + + # === Copay === + # FPL ratio = 79_200 / 27_320 = 2.899 (above 200% -> higher tier) + # 1 child FT at 201%+ FPL: 3% (CC-236 06/24 reinstatement rate) + # Monthly copay = 79_200 * 0.03 / 12 = 198 + nj_ccap_copay: 198 + + # === Rates === + # Infant FT 3-star licensed center = $391.32/wk + nj_ccap_maximum_weekly_benefit: [0, 0, 391.32] + + # === Benefit === + # Expenses: 22_000 / 12 = 1_833.33/mo + # Uncapped: 1_833.33 - 198 = 1_635.33 + # Max reimbursement: 391.32 * 52 / 12 = 1_695.72 + # Benefit = min(1_635.33, 1_695.72) = 1_635.33 + nj_ccap: 1_635.33 + +- name: Case 6, enrolled family at 230% FPL continuing eligible. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 62_836 + immigration_status: CITIZEN + person2: + age: 32 + immigration_status: CITIZEN + person3: + age: 1 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 40 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: STAR_3 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + nj_ccap_enrolled: true + spm_unit_pre_subsidy_childcare_expenses: 22_000 + households: + household: + members: [person1, person2, person3] + state_code: NJ + output: + # === Eligibility === + nj_ccap_eligible_child: [false, false, true] + + # FPG family of 3: 27_320; 250% = 68_300 + # Enrolled: 62_836 <= 68_300 -> eligible + nj_ccap_income_eligible: true + is_ccdf_asset_eligible: true + nj_ccap_eligible: true + + # === Copay === + # FPL ratio = 62_836 / 27_320 = 2.300 -> 201%+ tier + # 1 child FT -> 3% (CC-236 06/24 reinstatement rate) + # monthly copay = 62_836 * 0.03 / 12 = 157.09 + nj_ccap_copay: 157.09 + + # === Provider rates === + # Person1 (age 35 = 420 mo >= 60) -> SCHOOL_AGE; Person2 (age 32 = 384 mo >= 60) -> SCHOOL_AGE + # Child (age 1 = 12 mo < 18) -> INFANT + nj_ccap_age_group: [SCHOOL_AGE, SCHOOL_AGE, INFANT] + nj_ccap_time_category: [PART_TIME, PART_TIME, FULL_TIME] + # Center FT Star 3 Infant = $391.32 + nj_ccap_maximum_weekly_benefit: [0, 0, 391.32] + + # === Benefit === + # max annual = 391.32 * 52 = 20_348.64 + # annual copay = 62_836 * 0.03 = 1_885.08 + # uncapped = max(22_000 - 1_885.08, 0) = 20_114.92 + # annual benefit = min(20_114.92, 20_348.64) = 20_114.92 + # monthly = 20_114.92 / 12 = 1_676.24 + nj_ccap: 1_676.24 + +- name: Case 7, child exactly age 13 is ineligible unless special needs. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 30_000 + immigration_status: CITIZEN + person2: + age: 13 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 30 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 10_000 + households: + household: + members: [person1, person2] + state_code: NJ + output: + # Child age 13 >= 13 -> not eligible (not disabled) + nj_ccap_eligible_child: [false, false] + nj_ccap_eligible: false + nj_ccap: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap.yaml new file mode 100644 index 00000000000..c832dd9adb2 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap.yaml @@ -0,0 +1,211 @@ +# nj_ccap: SPMUnit, float, MONTH +# Per-child benefit = max(0, weekly_rate * 52/12 - copay_share) +# Total benefit = min(sum of per-child rates * 52/12, max(expenses - copay, 0)) +# Follows pattern: benefit = min(actual_expenses - copay, max_reimbursement) +# +# 2026 FPG: first_person = 15_960, additional = 5_680 +# Family of 2: 21_640; Family of 3: 27_320 + +- name: Case 1, basic eligible family positive benefit. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 30_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 14_000 + households: + household: + members: [person1, person2] + state_code: NJ + output: + # FPG family of 2: 21_640; FPL ratio = 30_000/21_640 = 1.386 + # 1 child FT at 101-200% -> copay = 30_000 * 0.02 / 12 = 50 (CC-236 06/24) + # annual copay = 600 + # max weekly = 291.57 (center FT base preschool); annual = 291.57 * 52 = 15_161.64 + # uncapped = max(14_000 - 600, 0) = 13_400 + # annual benefit = min(13_400, 15_161.64) = 13_400 + # monthly = 13_400 / 12 = 1_116.67 + nj_ccap: 1_116.67 + +- name: Case 2, ineligible family gets zero. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 14_000 + households: + household: + members: [person1, person2] + state_code: NJ + output: + # 50_000 > 43_280 (200% FPL for family of 2) -> ineligible + nj_ccap: 0 + +- name: Case 3, benefit capped at maximum rate. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 15_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 25_000 + households: + household: + members: [person1, person2] + state_code: NJ + output: + # FPL ratio = 15_000/21_640 = 0.693 -> copay waived ($0) + # max weekly = 291.57 (center FT base preschool); annual = 15_161.64 + # uncapped = max(25_000 - 0, 0) = 25_000 + # annual benefit = min(25_000, 15_161.64) = 15_161.64 + # monthly = 15_161.64 / 12 = 1_263.47 + nj_ccap: 1_263.47 + +- name: Case 4, zero expenses gives zero benefit. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 0 + households: + household: + members: [person1, person2] + state_code: NJ + output: + nj_ccap: 0 + +- name: Case 5, copay exceeds expenses gives zero benefit. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 42_000 + immigration_status: CITIZEN + person2: + age: 8 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 10 + nj_ccap_provider_type: APPROVED_HOME + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 1_200 + households: + household: + members: [person1, person2] + state_code: NJ + output: + # FPL ratio = 42_000/21_640 = 1.941; 1 child PT at 101-200% -> 1% (CC-236 06/24) + # annual copay = 42_000 * 0.01 = 420 + # uncapped = max(1_200 - 420, 0) = 780 + # max weekly = 59.39 (approved home PT school age); annual = 59.39 * 52 = 3_088.28 + # annual benefit = min(780, 3_088.28) = 780 + # monthly = 780 / 12 = 65 + nj_ccap: 65 + +- name: Case 6, negative countable income does not inflate benefit. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + self_employment_income: -60_000_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 15_000 + households: + household: + members: [person1, person2] + state_code: NJ + output: + # Negative income -> copay = 0 + # max weekly = 291.57; annual = 15_161.64 + # uncapped = max(15_000 - 0, 0) = 15_000 + # annual = min(15_000, 15_161.64) = 15_000 + # monthly = 15_000 / 12 = 1_250 + nj_ccap: 1_250 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_age_group.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_age_group.yaml new file mode 100644 index 00000000000..125bf3b94db --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_age_group.yaml @@ -0,0 +1,161 @@ +# nj_ccap_age_group: Person, Enum, MONTH +# Age group boundaries (from age_group/months.yaml bracket parameter): +# 0 months -> INFANT (index 0) +# 18 months -> TODDLER (index 1) +# 30 months -> PRESCHOOL (index 2) +# 60 months -> SCHOOL_AGE (index 3) +# Special needs variants derived from is_disabled flag. +# Enum values: INFANT, INFANT_SN, TODDLER, TODDLER_SN, PRESCHOOL, PRESCHOOL_SN, +# SCHOOL_AGE, SCHOOL_AGE_SN + +- name: Case 1, newborn is infant. + period: 2026-01 + input: + people: + person1: + age: 0 + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_age_group: INFANT + +- name: Case 2, child at 1 year is infant. + period: 2026-01 + input: + people: + person1: + age: 1 + households: + household: + members: [person1] + state_code: NJ + output: + # 1 year = 12 months < 18 months -> INFANT + nj_ccap_age_group: INFANT + +- name: Case 3, child at 2 years is toddler. + period: 2026-01 + input: + people: + person1: + age: 2 + households: + household: + members: [person1] + state_code: NJ + output: + # 2 years = 24 months >= 18, < 30 -> TODDLER + nj_ccap_age_group: TODDLER + +- name: Case 4, child at 3 years is preschool. + period: 2026-01 + input: + people: + person1: + age: 3 + households: + household: + members: [person1] + state_code: NJ + output: + # 3 years = 36 months >= 30, < 60 -> PRESCHOOL + nj_ccap_age_group: PRESCHOOL + +- name: Case 5, child at 4 years is preschool. + period: 2026-01 + input: + people: + person1: + age: 4 + households: + household: + members: [person1] + state_code: NJ + output: + # 4 years = 48 months >= 30, < 60 -> PRESCHOOL + nj_ccap_age_group: PRESCHOOL + +- name: Case 6, child at 5 years is school age. + period: 2026-01 + input: + people: + person1: + age: 5 + households: + household: + members: [person1] + state_code: NJ + output: + # 5 years = 60 months >= 60 -> SCHOOL_AGE + nj_ccap_age_group: SCHOOL_AGE + +- name: Case 7, child at 10 years is school age. + period: 2026-01 + input: + people: + person1: + age: 10 + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_age_group: SCHOOL_AGE + +- name: Case 8, disabled infant has special needs variant. + period: 2026-01 + input: + people: + person1: + age: 1 + is_disabled: true + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_age_group: INFANT_SN + +- name: Case 9, disabled toddler has special needs variant. + period: 2026-01 + input: + people: + person1: + age: 2 + is_disabled: true + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_age_group: TODDLER_SN + +- name: Case 10, disabled preschooler has special needs variant. + period: 2026-01 + input: + people: + person1: + age: 3 + is_disabled: true + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_age_group: PRESCHOOL_SN + +- name: Case 11, disabled school age child has special needs variant. + period: 2026-01 + input: + people: + person1: + age: 8 + is_disabled: true + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_age_group: SCHOOL_AGE_SN diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_copay.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_copay.yaml new file mode 100644 index 00000000000..c984dd03a56 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_copay.yaml @@ -0,0 +1,398 @@ +# nj_ccap_copay: SPMUnit, float, MONTH +# Copay = annual_income * copay_percentage / 12 +# Copay percentage depends on FPL tier, care type (FT/PT), and child count (1 or 2+). +# Third+ child = $0 additional. +# +# 2026 FPG family of 2: 21_640; family of 4: 33_000; family of 5: 38_680 +# Copay rates (CC-236 06/24, reinstatement era effective Aug 1, 2024): +# 0-1.0: 0% (waived) +# 1.0001-2.0: first child FT 2%, PT 1%; second child FT +1%, PT +0.5% +# 2.0001+: first child FT 3%, PT 1.5%; second child FT +2%, PT +1% +# +# CC-236 verification examples (reinstatement rates): +# Income $22,000, 1 child FT weekly: $22,000 * 2% / 52 = $8.46 +# Income $55,000, 2 children FT weekly: $55,000 * 3% / 52 = $31.73 +# Income $40,000, 1 child PT weekly: $40,000 * 1% / 52 = $7.69 +# Income $91,000, 2 children mixed weekly: $91,000 * 4% / 52 = $70.00 + +- name: Case 1, income at or below 100% FPL copay waived. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NJ + output: + # FPG family of 2: 21_640 + # FPL ratio = 20_000 / 21_640 = 0.924 -> below 100% -> $0 copay + nj_ccap_copay: 0 + +- name: Case 2, one child FT at 101-200% FPL. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 31_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NJ + output: + # FPG family of 2: 21_640; FPL ratio = 31_000/21_640 = 1.4326 + # 1 child FT at 101-200% FPL -> 2% + # monthly copay = 31_000 * 0.02 / 12 = 51.67 + nj_ccap_copay: 51.67 + +- name: Case 3, two children FT at 101-200% FPL. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 55_000 + immigration_status: CITIZEN + person2: + age: 32 + immigration_status: CITIZEN + person3: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 40 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + person4: + age: 7 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2, person3, person4] + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: NJ + output: + # FPG family of 4: 33_000; FPL ratio = 55_000/33_000 = 1.667 + # 2 children both FT at 101-200% -> first child 2% + second child 1% = 3% + # copay = 55_000 * 0.03 / 12 = 137.50 + nj_ccap_copay: 137.50 + +- name: Case 4, one child PT at 101-200% FPL. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 40_000 + immigration_status: CITIZEN + person2: + age: 32 + immigration_status: CITIZEN + person3: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 20 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: NJ + output: + # FPG family of 3: 27_320; FPL ratio = 40_000/27_320 = 1.464 + # 1 child PT at 101-200% -> 1% + # monthly copay = 40_000 * 0.01 / 12 = 33.33 + nj_ccap_copay: 33.33 + +- name: Case 5, one child FT at 201%+ FPL. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 70_000 + immigration_status: CITIZEN + person2: + age: 32 + immigration_status: CITIZEN + person3: + age: 3 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: STAR_5 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + nj_ccap_enrolled: true + households: + household: + members: [person1, person2, person3] + state_code: NJ + output: + # FPG family of 3: 27_320; FPL ratio = 70_000/27_320 = 2.562 + # 1 child FT at 201%+ -> 3% + # monthly copay = 70_000 * 0.03 / 12 = 175 + nj_ccap_copay: 175 + +- name: Case 6, two children FT at 201%+ FPL. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 80_000 + immigration_status: CITIZEN + person2: + age: 32 + immigration_status: CITIZEN + person3: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 40 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + person4: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2, person3, person4] + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + nj_ccap_enrolled: true + households: + household: + members: [person1, person2, person3, person4] + state_code: NJ + output: + # FPG family of 4: 33_000; FPL ratio = 80_000/33_000 = 2.424 + # 2 children both FT at 201%+ -> first child 3% + second child 2% = 5% + # copay = 80_000 * 0.05 / 12 = 333.33 + nj_ccap_copay: 333.33 + +- name: Case 7, mixed care one FT one PT at 101-200% FPL. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 61_000 + immigration_status: CITIZEN + person2: + age: 32 + immigration_status: CITIZEN + person3: + age: 1 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 20 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + person4: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2, person3, person4] + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: NJ + output: + # FPG family of 4: 33_000; FPL ratio = 61_000/33_000 = 1.848 + # 1 FT + 1 PT at 101-200% -> first child FT 2% + second child PT 0.5% = 2.5% + # monthly copay = 61_000 * 0.025 / 12 = 127.08 + nj_ccap_copay: 127.08 + +- name: Case 8, three children third child no additional copay. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 91_000 + immigration_status: CITIZEN + person2: + age: 32 + immigration_status: CITIZEN + person3: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + person4: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + person5: + age: 3 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2, person3, person4, person5] + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + nj_ccap_enrolled: true + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: NJ + output: + # FPG family of 5: 38_680; FPL ratio = 91_000/38_680 = 2.352 + # 3 children all FT at 201%+ -> first child 3% + second child 2% + third child 0% = 5% + # copay = 91_000 * 0.05 / 12 = 379.17 + nj_ccap_copay: 379.17 + +- name: Case 9, two children mixed care at 201% FPL. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 80_000 + immigration_status: CITIZEN + person2: + age: 32 + immigration_status: CITIZEN + person3: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 20 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + person4: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2, person3, person4] + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + nj_ccap_enrolled: true + households: + household: + members: [person1, person2, person3, person4] + state_code: NJ + output: + # FPG family of 4: 33_000; FPL ratio = 80_000/33_000 = 2.424 + # 1 FT + 1 PT at 201%+ -> first child FT 3% + second child PT 1% = 4% + # copay = 80_000 * 0.04 / 12 = 266.67 + nj_ccap_copay: 266.67 + +- name: Case 10, zero income gives zero copay. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NJ + output: + nj_ccap_copay: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_countable_income.yaml new file mode 100644 index 00000000000..07f4d7723df --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_countable_income.yaml @@ -0,0 +1,113 @@ +# nj_ccap_countable_income: SPMUnit, float, MONTH +# Sums income sources via adds parameter list. +# Excludes TANF cash benefits. +# Sources: employment_income, self_employment_income, social_security_retirement, +# social_security_disability, social_security_survivors, ssi, dividend_income, +# interest_income, rental_income, pension_income, unemployment_compensation, +# workers_compensation, alimony_income, child_support_received. +# All are YEAR-defined; in MONTH test, input annual, output monthly (annual/12). + +- name: Case 1, employment income only. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 36_000 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: NJ + output: + # 36_000 / 12 = 3_000/month + nj_ccap_countable_income: 3_000 + +- name: Case 2, multiple income sources. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 24_000 + child_support_received: 6_000 + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NJ + output: + # (24_000 + 6_000) / 12 = 2_500/month + nj_ccap_countable_income: 2_500 + +- name: Case 3, TANF excluded from countable income. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 12_000 + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + nj_wfnj: 4_800 + households: + household: + members: [person1, person2] + state_code: NJ + output: + # Only employment counts: 12_000 / 12 = 1_000/month + # TANF (nj_wfnj) not in sources list -> excluded + nj_ccap_countable_income: 1_000 + +- name: Case 4, zero income. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_countable_income: 0 + +- name: Case 5, two earners in household. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 30_000 + person2: + age: 32 + employment_income: 18_000 + person3: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: NJ + output: + # (30_000 + 18_000) / 12 = 4_000/month + nj_ccap_countable_income: 4_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_eligible.yaml new file mode 100644 index 00000000000..6e290913501 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_eligible.yaml @@ -0,0 +1,165 @@ +# nj_ccap_eligible: SPMUnit, bool, MONTH +# Combines: has_eligible_child & income_eligible & asset_eligible & activity_eligible +# +# 2026 FPG (Contiguous US): first_person = 15_960, additional = 5_680 +# Family of 2: 21_640; 200% = 43_280 + +- name: Case 1, basic eligible family. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 30_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NJ + output: + # Has eligible child (age 4, dependent, citizen) + # Income 30_000 <= 43_280 (200% FPL) -> income eligible + # Assets default 0 <= 1_000_000 -> asset eligible + # weekly_hours_worked defaults to 40 >= 30 -> activity eligible + nj_ccap_eligible: true + +- name: Case 2, no eligible child makes family ineligible. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 30_000 + immigration_status: CITIZEN + person2: + age: 15 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NJ + output: + # Child age 15 >= 13 -> not eligible child + nj_ccap_eligible: false + +- name: Case 3, income too high for initial applicant. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NJ + output: + # 50_000 > 43_280 (200% FPL for family of 2) -> income ineligible + nj_ccap_eligible: false + +- name: Case 4, activity ineligible parent. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 30_000 + immigration_status: CITIZEN + weekly_hours_worked: 20 + is_full_time_student: false + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NJ + output: + # Parent works 20 hrs < 30 hrs minimum, not student -> activity ineligible + nj_ccap_eligible: false + +- name: Case 5, full time student meets activity requirement. + period: 2026-01 + input: + people: + person1: + age: 22 + employment_income: 15_000 + immigration_status: CITIZEN + weekly_hours_worked: 0 + is_full_time_student: true + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NJ + output: + # Student exemption -> activity eligible + nj_ccap_eligible: true + +- name: Case 6, non-NJ family gets false. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 30_000 + person2: + age: 4 + is_tax_unit_dependent: true + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: PA + output: + nj_ccap_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_eligible_child.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_eligible_child.yaml new file mode 100644 index 00000000000..648e0819de3 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_eligible_child.yaml @@ -0,0 +1,156 @@ +# nj_ccap_eligible_child: Person, bool, MONTH +# Child must be: age < 13 (or < 19 if special needs), dependent, immigration eligible +# Age threshold params: child = 13, special_needs = 19 + +- name: Case 1, child age 4 is eligible. + period: 2026-01 + input: + people: + person1: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_eligible_child: true + +- name: Case 2, child age 12 is eligible. + period: 2026-01 + input: + people: + person1: + age: 12 + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_eligible_child: true + +- name: Case 3, child age 13 is ineligible. + period: 2026-01 + input: + people: + person1: + age: 13 + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_eligible_child: false + +- name: Case 4, child age 14 is ineligible. + period: 2026-01 + input: + people: + person1: + age: 14 + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_eligible_child: false + +- name: Case 5, disabled child age 13 is eligible. + period: 2026-01 + input: + people: + person1: + age: 13 + is_disabled: true + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_eligible_child: true + +- name: Case 6, disabled child age 18 is eligible. + period: 2026-01 + input: + people: + person1: + age: 18 + is_disabled: true + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_eligible_child: true + +- name: Case 7, disabled child age 19 is ineligible. + period: 2026-01 + input: + people: + person1: + age: 19 + is_disabled: true + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_eligible_child: false + +- name: Case 8, non-dependent child is ineligible. + period: 2026-01 + input: + people: + person1: + age: 5 + is_tax_unit_dependent: false + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_eligible_child: false + +- name: Case 9, undocumented child is ineligible. + period: 2026-01 + input: + people: + person1: + age: 5 + is_tax_unit_dependent: true + immigration_status: UNDOCUMENTED + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_eligible_child: false + +- name: Case 10, adult age 30 is ineligible. + period: 2026-01 + input: + people: + person1: + age: 30 + is_tax_unit_dependent: false + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_eligible_child: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_income_eligible.yaml new file mode 100644 index 00000000000..bcacefab5b9 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_income_eligible.yaml @@ -0,0 +1,192 @@ +# nj_ccap_income_eligible: SPMUnit, bool, MONTH +# Initial (not enrolled): income <= FPL * 2.0 (200% FPL) +# Continuing (enrolled): income <= FPL * 2.5 (250% FPL) +# Exit: income <= SMI * 0.85 +# +# 2026 FPG (Contiguous US): first_person = 15_960, additional = 5_680 +# Family of 2: 15_960 + 5_680 = 21_640 +# Family of 3: 15_960 + 2*5_680 = 27_320 +# Family of 4: 15_960 + 3*5_680 = 33_000 +# +# 200% FPL family of 2: 21_640 * 2 = 43_280 +# 250% FPL family of 2: 21_640 * 2.5 = 54_100 + +- name: Case 1, initial applicant at 150% FPL is eligible. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 32_460 + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NJ + output: + # 32_460 / 12 = 2_705/mo; FPG fam of 2 = 21_640 + # 200% FPL = 43_280; 32_460 <= 43_280 -> eligible + nj_ccap_income_eligible: true + +- name: Case 2, initial applicant exactly at 200% FPL is eligible. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 43_280 + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NJ + output: + # 43_280 = 200% FPL family of 2 -> exactly at limit -> eligible + nj_ccap_income_eligible: true + +- name: Case 3, initial applicant above 200% FPL is ineligible. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 43_281 + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NJ + output: + # 43_281 > 43_280 (200% FPL) -> ineligible for initial + nj_ccap_income_eligible: false + +- name: Case 4, enrolled family at 220% FPL is eligible. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 47_608 + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + nj_ccap_enrolled: true + households: + household: + members: [person1, person2] + state_code: NJ + output: + # 47_608 = ~220% FPL; enrolled -> limit is 250% = 54_100 + # 47_608 <= 54_100 -> eligible + nj_ccap_income_eligible: true + +- name: Case 5, enrolled family exactly at 250% FPL is eligible. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 54_100 + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + nj_ccap_enrolled: true + households: + household: + members: [person1, person2] + state_code: NJ + output: + # 54_100 = 250% FPL family of 2; enrolled -> limit is 54_100 + # 54_100 <= 54_100 -> eligible + nj_ccap_income_eligible: true + +- name: Case 6, enrolled family above 250% FPL but below 85% SMI is eligible. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 54_101 + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + nj_ccap_enrolled: true + households: + household: + members: [person1, person2] + state_code: NJ + output: + # 54_101 > 250% FPL (54_100) but enrolled families use 85% SMI + # 85% SMI family of 2 = 88_516; 54_101 <= 88_516 -> eligible + # (graduated phase-out, CCDF State Plan Section 2.5) + nj_ccap_income_eligible: true + +- name: Case 7, zero income is eligible. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NJ + output: + # $0 <= 43_280 (200% FPL) -> eligible + nj_ccap_income_eligible: true + +- name: Case 8, family of 4 at 200% FPL boundary. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 66_000 + person2: + age: 32 + person3: + age: 8 + person4: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: NJ + output: + # FPG family of 4 = 33_000; 200% = 66_000 + # 66_000 <= 66_000 -> eligible + nj_ccap_income_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_maximum_weekly_benefit.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_maximum_weekly_benefit.yaml new file mode 100644 index 00000000000..74d2429763b --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_maximum_weekly_benefit.yaml @@ -0,0 +1,275 @@ +# nj_ccap_maximum_weekly_benefit: Person, float, MONTH +# Looks up rate by provider_type x quality_rating x age_group x time_category. +# Rates effective 2025-03-01 (CC-230). +# Person-level variable: returns the max weekly reimbursement for each child. + +- name: Case 1, licensed center FT base infant. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 1 + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_maximum_weekly_benefit: 366.67 + +- name: Case 2, licensed center PT base infant. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 1 + childcare_hours_per_week: 20 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_maximum_weekly_benefit: 183.34 + +- name: Case 3, licensed center FT 3-star preschool. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 3 + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: STAR_3 + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_maximum_weekly_benefit: 305.27 + +- name: Case 4, licensed center FT 5-star toddler. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 2 + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: STAR_5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_maximum_weekly_benefit: 356.97 + +- name: Case 5, licensed center FT base school age. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 8 + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_maximum_weekly_benefit: 274.96 + +- name: Case 6, licensed center FT 5-star school age gets base rate. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 8 + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: STAR_5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + # School-age always gets base rate regardless of quality rating + nj_ccap_maximum_weekly_benefit: 274.96 + +- name: Case 7, registered family FT base infant. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 1 + childcare_hours_per_week: 35 + nj_ccap_provider_type: REGISTERED_FAMILY + nj_ccap_grow_nj_kids_rating: NONE + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_maximum_weekly_benefit: 281.19 + +- name: Case 8, registered family PT 4-star preschool. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 4 + childcare_hours_per_week: 20 + nj_ccap_provider_type: REGISTERED_FAMILY + nj_ccap_grow_nj_kids_rating: STAR_4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_maximum_weekly_benefit: 152.64 + +- name: Case 9, approved home FT infant. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 1 + childcare_hours_per_week: 35 + nj_ccap_provider_type: APPROVED_HOME + nj_ccap_grow_nj_kids_rating: NONE + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_maximum_weekly_benefit: 139.39 + +- name: Case 10, approved home PT school age. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 8 + childcare_hours_per_week: 20 + nj_ccap_provider_type: APPROVED_HOME + nj_ccap_grow_nj_kids_rating: NONE + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_maximum_weekly_benefit: 59.39 + +- name: Case 11, ACA summer camp FT school age. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 8 + childcare_hours_per_week: 35 + nj_ccap_provider_type: ACA_SUMMER_CAMP + nj_ccap_grow_nj_kids_rating: NONE + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_maximum_weekly_benefit: 288.70 + +- name: Case 12, ACA summer camp FT school age special needs. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 8 + is_disabled: true + childcare_hours_per_week: 35 + nj_ccap_provider_type: ACA_SUMMER_CAMP + nj_ccap_grow_nj_kids_rating: NONE + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_maximum_weekly_benefit: 366.65 + +- name: Case 13, licensed center FT base special needs infant. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 1 + is_disabled: true + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_maximum_weekly_benefit: 440.01 + +- name: Case 14, licensed center PT base special needs school age. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 10 + is_disabled: true + childcare_hours_per_week: 20 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + is_tax_unit_dependent: true + immigration_status: CITIZEN + households: + household: + members: [person1] + state_code: NJ + output: + # 5-18 yr Special Needs PT base: $174.60 + nj_ccap_maximum_weekly_benefit: 174.60 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_smi.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_smi.yaml new file mode 100644 index 00000000000..3689b029e0e --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_smi.yaml @@ -0,0 +1,101 @@ +# nj_ccap_smi: SPMUnit, float, MONTH +# 85% of NJ State Median Income, annualized / 12 for monthly comparison. +# Uses federal HHS SMI data with household size adjustments, accessed at +# Oct 1 fiscal-year instant. +# +# For 2026-01 (FY 2026): NJ 4-person base = 160_276 (2025-10-01 HHS data) +# Size adjustments: first_person=0.52, second_to_sixth=0.16 each +# Family of 2: 160_276 * (0.52 + 0.16) * 0.85 / 12 = 7_719.96 +# Family of 4: 160_276 * (0.52 + 0.16*3) * 0.85 / 12 = 11_352.88 + +- name: Case 1, basic SMI lookup for family of 4. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + person2: + age: 32 + person3: + age: 8 + person4: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: NJ + output: + # 160_276 * 1.00 * 0.85 / 12 = 11_352.88 + nj_ccap_smi: 11_352.88 + +- name: Case 2, SMI for family of 2 used for exit threshold. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NJ + output: + # 160_276 * 0.68 * 0.85 / 12 = 7_719.96 + nj_ccap_smi: 7_719.96 + +- name: Case 3, enrolled family above 250% FPL but below 85% SMI is eligible. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 60_000 + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + nj_ccap_enrolled: true + households: + household: + members: [person1, person2] + state_code: NJ + output: + # Family of 2: 85% SMI annual = 92_640 + # Enrolled -> uses 85% SMI only (graduated phase-out) + # 60_000 <= 92_640 -> eligible + nj_ccap_income_eligible: true + +- name: Case 4, income below 250% FPL but exceeds 85% SMI so SMI is binding. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 39_000 + person2: + age: 0 + spm_units: + spm_unit: + members: [person1, person2] + nj_ccap_enrolled: true + households: + household: + members: [person1, person2] + state_code: NJ + output: + # Family of 2: 250% FPL = 54_100; 85% SMI annual = 92_640 + # Income 39_000 < 54_100 (FPL passes) and 39_000 < 92_640 (SMI passes) + # Both pass -> eligible (SMI is not binding at this income) + nj_ccap_income_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_time_category.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_time_category.yaml new file mode 100644 index 00000000000..8c5031ed0a4 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_time_category.yaml @@ -0,0 +1,83 @@ +# nj_ccap_time_category: Person, Enum, MONTH +# NJ has binary FT/PT only (unlike RI which has 4 tiers). +# Time authorization thresholds (from time_authorization/thresholds.yaml): +# 0 hours -> PART_TIME (index 1) +# 30+ hours -> FULL_TIME (index 0) + +- name: Case 1, full time 35 hours per week. + period: 2026-01 + input: + people: + person1: + childcare_hours_per_week: 35 + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_time_category: FULL_TIME + +- name: Case 2, full time exactly 30 hours per week. + period: 2026-01 + input: + people: + person1: + childcare_hours_per_week: 30 + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_time_category: FULL_TIME + +- name: Case 3, part time 29 hours per week. + period: 2026-01 + input: + people: + person1: + childcare_hours_per_week: 29 + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_time_category: PART_TIME + +- name: Case 4, part time 15 hours per week. + period: 2026-01 + input: + people: + person1: + childcare_hours_per_week: 15 + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_time_category: PART_TIME + +- name: Case 5, part time zero hours per week. + period: 2026-01 + input: + people: + person1: + childcare_hours_per_week: 0 + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_time_category: PART_TIME + +- name: Case 6, full time 40 hours per week. + period: 2026-01 + input: + people: + person1: + childcare_hours_per_week: 40 + households: + household: + members: [person1] + state_code: NJ + output: + nj_ccap_time_category: FULL_TIME diff --git a/policyengine_us/variables/gov/states/nj/njdhs/ccap/copay/nj_ccap_copay.py b/policyengine_us/variables/gov/states/nj/njdhs/ccap/copay/nj_ccap_copay.py new file mode 100644 index 00000000000..e995ce0bd12 --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/ccap/copay/nj_ccap_copay.py @@ -0,0 +1,53 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.nj.njdhs.ccap.nj_ccap_time_category import ( + NJCCAPTimeCategory, +) + + +class nj_ccap_copay(Variable): + value_type = float + entity = SPMUnit + unit = USD + label = "New Jersey CCAP family co-payment" + definition_period = MONTH + defined_for = StateCode.NJ + reference = ( + "https://www.childcarenj.gov/ChildCareNJ/media/media_library/Copayment_Schedule.pdf#page=1", + "https://www.childcarenj.gov/ChildCareNJ/media/media_library/CCDF_State_Plan_for_New_Jersey_FFY25-27.pdf#page=40", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.nj.njdhs.ccap.copay + countable_income = spm_unit("nj_ccap_countable_income", period) + fpg = spm_unit("spm_unit_fpg", period) + fpl_ratio = where(fpg > 0, countable_income / fpg, 0) + + person = spm_unit.members + is_eligible_child = person("nj_ccap_eligible_child", period) + time_category = person("nj_ccap_time_category", period) + is_ft = time_category == NJCCAPTimeCategory.FULL_TIME + + n_eligible = spm_unit.sum(is_eligible_child) + n_ft = spm_unit.sum(is_eligible_child & is_ft) + has_second_child = n_eligible >= 2 + + # First child rate: use FT rate if any child is FT, else PT + first_child_rate = where( + n_ft > 0, + p.first_child_ft_rate.calc(fpl_ratio), + p.first_child_pt_rate.calc(fpl_ratio), + ) + + # Second child rate: FT only if 2+ FT children, otherwise PT + second_child_rate = where( + n_ft >= 2, + p.second_child_ft_rate.calc(fpl_ratio), + p.second_child_pt_rate.calc(fpl_ratio), + ) + + total_rate = first_child_rate + where(has_second_child, second_child_rate, 0) + # CPS children are copay-exempt (N.J.A.C. 10:15-9.1). + has_cps_child = spm_unit.any( + is_eligible_child & person("receives_or_needs_protective_services", period) + ) + return where(has_cps_child, 0, countable_income * total_rate) diff --git a/policyengine_us/variables/gov/states/nj/njdhs/ccap/eligibility/nj_ccap_activity_eligible.py b/policyengine_us/variables/gov/states/nj/njdhs/ccap/eligibility/nj_ccap_activity_eligible.py new file mode 100644 index 00000000000..5a52315ba7d --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/ccap/eligibility/nj_ccap_activity_eligible.py @@ -0,0 +1,31 @@ +from policyengine_us.model_api import * + + +class nj_ccap_activity_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for New Jersey CCAP based on activity requirements" + definition_period = MONTH + defined_for = StateCode.NJ + reference = ( + "https://www.childcarenj.gov/ChildCareNJ/media/media_library/CCDF_State_Plan_for_New_Jersey_FFY25-27.pdf#page=22", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.nj.njdhs.ccap.activity_requirements + enrolled = spm_unit("nj_ccap_enrolled", period) + min_hours = where(enrolled, p.weekly_hours_redetermination, p.weekly_hours) + person = spm_unit.members + is_head_or_spouse = person("is_tax_unit_head_or_spouse", period.this_year) + hours_worked = person("weekly_hours_worked", period.this_year) + meets_work_requirement = hours_worked >= spm_unit.project(min_hours) + is_student = person("is_full_time_student", period.this_year) + individually_eligible = meets_work_requirement | is_student + # Each parent must independently qualify (N.J.A.C. 10:15-5.2). + n_parents = spm_unit.sum(is_head_or_spouse) + n_qualifying = spm_unit.sum(is_head_or_spouse & individually_eligible) + all_parents_qualify = n_qualifying >= n_parents + # Fallback for non-derivable activities (TANF recipients, + # CP&P cases, job training combos). + fallback = spm_unit("meets_ccdf_activity_test", period.this_year) + return all_parents_qualify | fallback diff --git a/policyengine_us/variables/gov/states/nj/njdhs/ccap/eligibility/nj_ccap_eligible.py b/policyengine_us/variables/gov/states/nj/njdhs/ccap/eligibility/nj_ccap_eligible.py new file mode 100644 index 00000000000..3eee86c6e7f --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/ccap/eligibility/nj_ccap_eligible.py @@ -0,0 +1,20 @@ +from policyengine_us.model_api import * + + +class nj_ccap_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for New Jersey CCAP" + definition_period = MONTH + defined_for = StateCode.NJ + reference = ( + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-15-5-2", + "https://www.childcarenj.gov/ChildCareNJ/media/media_library/CCDF_State_Plan_for_New_Jersey_FFY25-27.pdf#page=14", + ) + + def formula(spm_unit, period, parameters): + has_eligible_child = add(spm_unit, period, ["nj_ccap_eligible_child"]) > 0 + income_eligible = spm_unit("nj_ccap_income_eligible", period) + asset_eligible = spm_unit("is_ccdf_asset_eligible", period.this_year) + activity_eligible = spm_unit("nj_ccap_activity_eligible", period) + return has_eligible_child & income_eligible & asset_eligible & activity_eligible diff --git a/policyengine_us/variables/gov/states/nj/njdhs/ccap/eligibility/nj_ccap_eligible_child.py b/policyengine_us/variables/gov/states/nj/njdhs/ccap/eligibility/nj_ccap_eligible_child.py new file mode 100644 index 00000000000..aa9e75353c2 --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/ccap/eligibility/nj_ccap_eligible_child.py @@ -0,0 +1,30 @@ +from policyengine_us.model_api import * + + +class nj_ccap_eligible_child(Variable): + value_type = bool + entity = Person + label = "Eligible child for New Jersey CCAP" + definition_period = MONTH + defined_for = StateCode.NJ + reference = ( + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-15-5-2", + "https://www.childcarenj.gov/ChildCareNJ/media/media_library/CCDF_State_Plan_for_New_Jersey_FFY25-27.pdf#page=14", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.states.nj.njdhs.ccap.age_threshold + age = person("age", period.this_year) + is_disabled = person("is_disabled", period.this_year) + age_eligible = where(is_disabled, age < p.special_needs, age < p.child) + is_dependent = person("is_tax_unit_dependent", period.this_year) + immigration_eligible = person( + "is_ccdf_immigration_eligible_child", period.this_year + ) + standard_eligible = age_eligible & is_dependent & immigration_eligible + # CP&P (Child Protective & Permanency) children are eligible + # regardless of dependency or immigration status. + protective = person("receives_or_needs_protective_services", period) + foster = person("is_in_foster_care", period) + categorical_eligible = age_eligible & (protective | foster) + return standard_eligible | categorical_eligible diff --git a/policyengine_us/variables/gov/states/nj/njdhs/ccap/eligibility/nj_ccap_income_eligible.py b/policyengine_us/variables/gov/states/nj/njdhs/ccap/eligibility/nj_ccap_income_eligible.py new file mode 100644 index 00000000000..232342196ac --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/ccap/eligibility/nj_ccap_income_eligible.py @@ -0,0 +1,26 @@ +from policyengine_us.model_api import * + + +class nj_ccap_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for New Jersey CCAP based on income" + definition_period = MONTH + defined_for = StateCode.NJ + reference = ( + "https://www.childcarenj.gov/ChildCareNJ/media/media_library/Income_Eligibility_Schedule.pdf", + "https://www.childcarenj.gov/ChildCareNJ/media/media_library/CCDF_State_Plan_for_New_Jersey_FFY25-27.pdf#page=23", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.nj.njdhs.ccap.income.fpl_rate + countable_income = spm_unit("nj_ccap_countable_income", period) + fpg = spm_unit("spm_unit_fpg", period) + enrolled = spm_unit("nj_ccap_enrolled", period) + smi = spm_unit("nj_ccap_smi", period) + initial_limit = fpg * p.initial_eligibility + # Enrolled families use 85% SMI between redeterminations. + # Families between 250% FPL and 85% SMI get a one-year + # graduated phase-out (CCDF State Plan Section 2.5). + income_limit = where(enrolled, smi, initial_limit) + return countable_income <= income_limit diff --git a/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap.py b/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap.py new file mode 100644 index 00000000000..dd2bcd08eed --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap.py @@ -0,0 +1,28 @@ +from policyengine_us.model_api import * + + +class nj_ccap(Variable): + value_type = float + entity = SPMUnit + unit = USD + label = "New Jersey CCAP benefit amount" + definition_period = MONTH + defined_for = "nj_ccap_eligible" + reference = ( + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-15-5-2", + "https://www.childcarenj.gov/ChildCareNJ/media/media_library/CCDF_State_Plan_for_New_Jersey_FFY25-27.pdf#page=14", + ) + + def formula(spm_unit, period, parameters): + copay = spm_unit("nj_ccap_copay", period) + maximum_weekly_benefit = add( + spm_unit, period, ["nj_ccap_maximum_weekly_benefit"] + ) + maximum_monthly_benefit = maximum_weekly_benefit * ( + WEEKS_IN_YEAR / MONTHS_IN_YEAR + ) + pre_subsidy_childcare_expenses = spm_unit( + "spm_unit_pre_subsidy_childcare_expenses", period + ) + uncapped = max_(pre_subsidy_childcare_expenses - copay, 0) + return min_(uncapped, maximum_monthly_benefit) diff --git a/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap_age_group.py b/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap_age_group.py new file mode 100644 index 00000000000..73d7444719e --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap_age_group.py @@ -0,0 +1,35 @@ +from policyengine_us.model_api import * + + +class NJCCAPAgeGroup(Enum): + INFANT = "Infant (Birth to 17 Months)" + INFANT_SN = "Infant with Special Needs" + TODDLER = "Toddler (18 to 29 Months)" + TODDLER_SN = "Toddler with Special Needs" + PRESCHOOL = "Preschool (30 Months to 5 Years)" + PRESCHOOL_SN = "Preschool with Special Needs" + SCHOOL_AGE = "School Age (5 to 13 Years)" + SCHOOL_AGE_SN = "School Age with Special Needs" + + +class nj_ccap_age_group(Variable): + value_type = Enum + entity = Person + possible_values = NJCCAPAgeGroup + default_value = NJCCAPAgeGroup.PRESCHOOL + definition_period = MONTH + label = "New Jersey CCAP age group" + defined_for = StateCode.NJ + reference = "https://www.childcarenj.gov/ChildCareNJ/media/media_library/Max_CC_Payment_Rates.pdf#page=1" + + def formula(person, period, parameters): + p = parameters(period).gov.states.nj.njdhs.ccap.age_group + age_in_months = person("age", period.this_year) * MONTHS_IN_YEAR + base_group = p.months.calc(age_in_months) + is_disabled = person("is_disabled", period.this_year) + # base_group: 0=INFANT, 1=TODDLER, 2=PRESCHOOL, 3=SCHOOL_AGE + # SN variants are at indices: 1=INFANT_SN, 3=TODDLER_SN, 5=PRESCHOOL_SN, 7=SCHOOL_AGE_SN + # Standard variants at: 0=INFANT, 2=TODDLER, 4=PRESCHOOL, 6=SCHOOL_AGE + standard_index = base_group * 2 + sn_index = standard_index + 1 + return where(is_disabled, sn_index, standard_index) diff --git a/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap_countable_income.py b/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap_countable_income.py new file mode 100644 index 00000000000..7580d533e2b --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap_countable_income.py @@ -0,0 +1,13 @@ +from policyengine_us.model_api import * + + +class nj_ccap_countable_income(Variable): + value_type = float + entity = SPMUnit + label = "New Jersey CCAP countable income" + definition_period = MONTH + unit = USD + defined_for = StateCode.NJ + reference = "https://www.childcarenj.gov/ChildCareNJ/media/media_library/CCDF_State_Plan_for_New_Jersey_FFY25-27.pdf#page=23" + + adds = "gov.states.nj.njdhs.ccap.income.countable_income.sources" diff --git a/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap_enrolled.py b/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap_enrolled.py new file mode 100644 index 00000000000..4ff163cbd9c --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap_enrolled.py @@ -0,0 +1,9 @@ +from policyengine_us.model_api import * + + +class nj_ccap_enrolled(Variable): + value_type = bool + entity = SPMUnit + definition_period = MONTH + label = "Whether the family is currently enrolled in New Jersey CCAP" + defined_for = StateCode.NJ diff --git a/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap_grow_nj_kids_rating.py b/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap_grow_nj_kids_rating.py new file mode 100644 index 00000000000..67165a26109 --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap_grow_nj_kids_rating.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class NJCCAPGrowNJKidsRating(Enum): + NONE = "No Rating" + STAR_3 = "3-Star" + STAR_4 = "4-Star" + STAR_5 = "5-Star" + + +class nj_ccap_grow_nj_kids_rating(Variable): + value_type = Enum + entity = Person + possible_values = NJCCAPGrowNJKidsRating + default_value = NJCCAPGrowNJKidsRating.NONE + definition_period = MONTH + label = "New Jersey CCAP Grow NJ Kids quality rating" + defined_for = StateCode.NJ + reference = "https://www.childcarenj.gov/ChildCareNJ/media/media_library/Max_CC_Payment_Rates.pdf#page=1" diff --git a/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap_maximum_weekly_benefit.py b/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap_maximum_weekly_benefit.py new file mode 100644 index 00000000000..b857d528e12 --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap_maximum_weekly_benefit.py @@ -0,0 +1,42 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.nj.njdhs.ccap.nj_ccap_provider_type import ( + NJCCAPProviderType, +) + + +class nj_ccap_maximum_weekly_benefit(Variable): + value_type = float + entity = Person + unit = USD + label = "New Jersey CCAP maximum weekly benefit per child" + definition_period = MONTH + defined_for = "nj_ccap_eligible_child" + reference = "https://www.childcarenj.gov/ChildCareNJ/media/media_library/Max_CC_Payment_Rates.pdf#page=1" + + def formula(person, period, parameters): + p = parameters(period).gov.states.nj.njdhs.ccap.rates + provider_type = person("nj_ccap_provider_type", period) + time_category = person("nj_ccap_time_category", period) + age_group = person("nj_ccap_age_group", period) + grow_nj_kids_rating = person("nj_ccap_grow_nj_kids_rating", period) + + center_rate = p.licensed_center[time_category][grow_nj_kids_rating][age_group] + family_rate = p.registered_family[time_category][grow_nj_kids_rating][age_group] + home_rate = p.approved_home[time_category][age_group] + camp_rate = p.aca_summer_camp[time_category][age_group] + + return select( + [ + provider_type == NJCCAPProviderType.LICENSED_CENTER, + provider_type == NJCCAPProviderType.REGISTERED_FAMILY, + provider_type == NJCCAPProviderType.APPROVED_HOME, + provider_type == NJCCAPProviderType.ACA_SUMMER_CAMP, + ], + [ + center_rate, + family_rate, + home_rate, + camp_rate, + ], + default=center_rate, + ) diff --git a/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap_provider_type.py b/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap_provider_type.py new file mode 100644 index 00000000000..e50efce90d5 --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap_provider_type.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class NJCCAPProviderType(Enum): + LICENSED_CENTER = "Licensed Center" + REGISTERED_FAMILY = "Registered Family" + APPROVED_HOME = "Approved Home" + ACA_SUMMER_CAMP = "ACA Summer Camp" + + +class nj_ccap_provider_type(Variable): + value_type = Enum + entity = Person + possible_values = NJCCAPProviderType + default_value = NJCCAPProviderType.LICENSED_CENTER + definition_period = MONTH + label = "New Jersey CCAP child care provider type" + defined_for = StateCode.NJ + reference = "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-15-5-2" diff --git a/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap_smi.py b/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap_smi.py new file mode 100644 index 00000000000..c060d22e26e --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap_smi.py @@ -0,0 +1,28 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.hhs.hhs_smi import smi + + +class nj_ccap_smi(Variable): + value_type = float + entity = SPMUnit + label = "New Jersey CCAP 85% State Median Income exit threshold" + unit = USD + definition_period = MONTH + defined_for = StateCode.NJ + reference = ( + "https://www.childcarenj.gov/ChildCareNJ/media/media_library/Income_Eligibility_Schedule.pdf", + "https://www.childcarenj.gov/ChildCareNJ/media/media_library/CCDF_State_Plan_for_New_Jersey_FFY25-27.pdf#page=34", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.nj.njdhs.ccap.income.fpl_rate + year = period.start.year + month = period.start.month + if month >= 10: + instant_str = f"{year}-10-01" + else: + instant_str = f"{year - 1}-10-01" + size = spm_unit("spm_unit_size", period.this_year) + state = spm_unit.household("state_code_str", period.this_year) + annual_smi = smi(size, state, instant_str, parameters) + return annual_smi * p.smi_exit / MONTHS_IN_YEAR diff --git a/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap_time_category.py b/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap_time_category.py new file mode 100644 index 00000000000..d0ea9afb112 --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/ccap/nj_ccap_time_category.py @@ -0,0 +1,22 @@ +from policyengine_us.model_api import * + + +class NJCCAPTimeCategory(Enum): + FULL_TIME = "Full Time" + PART_TIME = "Part Time" + + +class nj_ccap_time_category(Variable): + value_type = Enum + entity = Person + possible_values = NJCCAPTimeCategory + default_value = NJCCAPTimeCategory.FULL_TIME + definition_period = MONTH + label = "New Jersey CCAP time authorization category" + defined_for = StateCode.NJ + reference = "https://www.childcarenj.gov/ChildCareNJ/media/media_library/Max_CC_Payment_Rates.pdf#page=1" + + def formula(person, period, parameters): + hours = person("childcare_hours_per_week", period.this_year) + p = parameters(period).gov.states.nj.njdhs.ccap.time_authorization + return p.thresholds.calc(hours) diff --git a/policyengine_us/variables/gov/states/nj/njdhs/nj_child_care_subsidies.py b/policyengine_us/variables/gov/states/nj/njdhs/nj_child_care_subsidies.py new file mode 100644 index 00000000000..83803de6bfe --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/nj_child_care_subsidies.py @@ -0,0 +1,11 @@ +from policyengine_us.model_api import * + + +class nj_child_care_subsidies(Variable): + value_type = float + entity = SPMUnit + label = "New Jersey child care subsidies" + unit = USD + definition_period = YEAR + defined_for = StateCode.NJ + adds = ["nj_ccap"]