diff --git a/changelog.d/ri-ccap.added.md b/changelog.d/ri-ccap.added.md new file mode 100644 index 00000000000..15427b5e3dd --- /dev/null +++ b/changelog.d/ri-ccap.added.md @@ -0,0 +1 @@ +Add Rhode Island 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 367612a52ae..baa61720584 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 @@ -5,6 +5,7 @@ values: - co_child_care_subsidies # Colorado Child Care Assistance Program - ma_child_care_subsidies # Massachusetts Child Care Financial Assistance - ne_child_care_subsidies # Nebraska Child Care Subsidy + - ri_child_care_subsidies # Rhode Island Child Care Assistance Program metadata: unit: list diff --git a/policyengine_us/parameters/gov/states/ri/dhs/ccap/activity_requirements/weekly_hours.yaml b/policyengine_us/parameters/gov/states/ri/dhs/ccap/activity_requirements/weekly_hours.yaml new file mode 100644 index 00000000000..e69976ed172 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ri/dhs/ccap/activity_requirements/weekly_hours.yaml @@ -0,0 +1,11 @@ +description: Rhode Island sets this amount as the minimum weekly hours of approved activity under the Child Care Assistance Program. +values: + 2020-01-01: 20 + +metadata: + unit: hour + period: year + label: Rhode Island CCAP minimum weekly activity hours + reference: + - title: 218-RICR-20-00-4, Section 4.4.1.A + href: https://rules.sos.ri.gov/regulations/part/218-20-00-4#4.4 diff --git a/policyengine_us/parameters/gov/states/ri/dhs/ccap/age_group/center/infant_max.yaml b/policyengine_us/parameters/gov/states/ri/dhs/ccap/age_group/center/infant_max.yaml new file mode 100644 index 00000000000..cd8ead8c938 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ri/dhs/ccap/age_group/center/infant_max.yaml @@ -0,0 +1,13 @@ +description: Rhode Island defines the licensed center infant age group as children younger than this age under the Child Care Assistance Program. +values: + 2025-07-01: 1.5 + +metadata: + unit: year + period: year + label: Rhode Island CCAP licensed center infant age maximum + reference: + - title: RI DHS CCAP Licensed Center Child Care Weekly Rates, Effective July 1, 2025 + href: https://dhs.ri.gov/media/9356/download?language=en + - title: 218-RICR-20-00-4, Section 4.12.B.2 + href: https://rules.sos.ri.gov/regulations/part/218-20-00-4#4.12 diff --git a/policyengine_us/parameters/gov/states/ri/dhs/ccap/age_group/center/toddler_max.yaml b/policyengine_us/parameters/gov/states/ri/dhs/ccap/age_group/center/toddler_max.yaml new file mode 100644 index 00000000000..3c1b194165b --- /dev/null +++ b/policyengine_us/parameters/gov/states/ri/dhs/ccap/age_group/center/toddler_max.yaml @@ -0,0 +1,13 @@ +description: Rhode Island defines the licensed center toddler age group as children younger than this age under the Child Care Assistance Program. +values: + 2025-07-01: 3 + +metadata: + unit: year + period: year + label: Rhode Island CCAP licensed center toddler age maximum + reference: + - title: RI DHS CCAP Licensed Center Child Care Weekly Rates, Effective July 1, 2025 + href: https://dhs.ri.gov/media/9356/download?language=en + - title: 218-RICR-20-00-4, Section 4.12.B.2 + href: https://rules.sos.ri.gov/regulations/part/218-20-00-4#4.12 diff --git a/policyengine_us/parameters/gov/states/ri/dhs/ccap/age_group/family/infant_toddler_max.yaml b/policyengine_us/parameters/gov/states/ri/dhs/ccap/age_group/family/infant_toddler_max.yaml new file mode 100644 index 00000000000..180edd91121 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ri/dhs/ccap/age_group/family/infant_toddler_max.yaml @@ -0,0 +1,15 @@ +description: Rhode Island defines the licensed family and exempt infant/toddler age group as children younger than this age under the Child Care Assistance Program. +values: + 2024-07-01: 3 + +metadata: + unit: year + period: year + label: Rhode Island CCAP licensed family infant/toddler age maximum + reference: + - title: RI DHS CCAP Licensed Family Child Care Weekly Rates, Effective July 1, 2024 + href: https://dhs.ri.gov/media/7481/download?language=en + - title: RI DHS CCAP Licensed Exempt Child Care Weekly Rates, Effective January 1, 2022 + href: https://dhs.ri.gov/media/3556/download?language=en + - title: 218-RICR-20-00-4, Section 4.12.B.2 + href: https://rules.sos.ri.gov/regulations/part/218-20-00-4#4.12 diff --git a/policyengine_us/parameters/gov/states/ri/dhs/ccap/age_threshold/child.yaml b/policyengine_us/parameters/gov/states/ri/dhs/ccap/age_threshold/child.yaml new file mode 100644 index 00000000000..9039e2345a7 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ri/dhs/ccap/age_threshold/child.yaml @@ -0,0 +1,11 @@ +description: Rhode Island limits the Child Care Assistance Program to children younger than this age. +values: + 2020-01-01: 13 + +metadata: + unit: year + period: year + label: Rhode Island CCAP child age threshold + reference: + - title: 218-RICR-20-00-4, Section 4.3.1.A.1 + href: https://rules.sos.ri.gov/regulations/part/218-20-00-4#4.3.1 diff --git a/policyengine_us/parameters/gov/states/ri/dhs/ccap/age_threshold/disabled_child.yaml b/policyengine_us/parameters/gov/states/ri/dhs/ccap/age_threshold/disabled_child.yaml new file mode 100644 index 00000000000..d00e123db4e --- /dev/null +++ b/policyengine_us/parameters/gov/states/ri/dhs/ccap/age_threshold/disabled_child.yaml @@ -0,0 +1,11 @@ +description: Rhode Island limits the Child Care Assistance Program to disabled children up through this age. +values: + 2020-01-01: 18 + +metadata: + unit: year + period: year + label: Rhode Island CCAP disabled child age threshold + reference: + - title: 218-RICR-20-00-4, Section 4.3.1.A.1 + href: https://rules.sos.ri.gov/regulations/part/218-20-00-4#4.3.1 diff --git a/policyengine_us/parameters/gov/states/ri/dhs/ccap/copay/rate.yaml b/policyengine_us/parameters/gov/states/ri/dhs/ccap/copay/rate.yaml new file mode 100644 index 00000000000..f8246173764 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ri/dhs/ccap/copay/rate.yaml @@ -0,0 +1,30 @@ +description: Rhode Island sets this co-share percentage of gross income under the Child Care Assistance Program. +metadata: + type: single_amount + threshold_unit: /1 + amount_unit: /1 + period: year + label: Rhode Island CCAP co-share rate by FPL ratio + reference: + - title: 218-RICR-20-00-4, Section 4.6.1.C + href: https://rules.sos.ri.gov/regulations/part/218-20-00-4#4.6.1 + - title: RI DHS CCAP Co-Pay Chart effective 02/15/2026 + href: https://dhs.ri.gov/media/10606/download?language=en + +brackets: + - threshold: + 2020-01-01: 0 + amount: + 2020-01-01: 0 + - threshold: + 2020-01-01: 1.0001 + amount: + 2020-01-01: 0.02 + - threshold: + 2020-01-01: 1.2501 + amount: + 2020-01-01: 0.05 + - threshold: + 2020-01-01: 1.5001 + amount: + 2020-01-01: 0.07 diff --git a/policyengine_us/parameters/gov/states/ri/dhs/ccap/income/countable_income/sources.yaml b/policyengine_us/parameters/gov/states/ri/dhs/ccap/income/countable_income/sources.yaml new file mode 100644 index 00000000000..718a1dd10f4 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ri/dhs/ccap/income/countable_income/sources.yaml @@ -0,0 +1,40 @@ +description: Rhode Island counts these income sources under the Child Care Assistance Program. +values: + 2020-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 + - veterans_benefits + - military_retirement_pay + - unemployment_compensation + - workers_compensation + - alimony_income + - child_support_received + # The following are counted per 218-RICR-20-00-4, Section 4.2, + # Definition 30 (Income) but have no matching variables: + # - adoption_subsidy + # - strike_benefits + # - royalties + # - temporary_disability_insurance + # - in-kind assistance + # - non-citizen sponsor income + # - room and board income + # - cash payouts for waiving health insurance + # - foster care payments when child in unit + # - VA educational benefits (separate from veterans_benefits) + # - Americorps payments (non-VISTA) + +metadata: + unit: list + period: year + label: Rhode Island CCAP countable income sources + reference: + - title: 218-RICR-20-00-4, Section 4.2, Definition 30 (Income) + href: https://rules.sos.ri.gov/regulations/part/218-20-00-4#4.2 diff --git a/policyengine_us/parameters/gov/states/ri/dhs/ccap/income/fpl_rate/initial_eligibility.yaml b/policyengine_us/parameters/gov/states/ri/dhs/ccap/income/fpl_rate/initial_eligibility.yaml new file mode 100644 index 00000000000..b1d9fdbc55b --- /dev/null +++ b/policyengine_us/parameters/gov/states/ri/dhs/ccap/income/fpl_rate/initial_eligibility.yaml @@ -0,0 +1,11 @@ +description: Rhode Island limits the Child Care Assistance Program to new applicants with income at or below this share of the federal poverty level. +values: + 2020-01-01: 2.61 + +metadata: + unit: /1 + period: year + label: Rhode Island CCAP initial eligibility FPL rate + reference: + - title: 218-RICR-20-00-4, Section 4.6.1.A + href: https://rules.sos.ri.gov/regulations/part/218-20-00-4#4.6.1 diff --git a/policyengine_us/parameters/gov/states/ri/dhs/ccap/income/fpl_rate/transitional.yaml b/policyengine_us/parameters/gov/states/ri/dhs/ccap/income/fpl_rate/transitional.yaml new file mode 100644 index 00000000000..4ddab21c720 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ri/dhs/ccap/income/fpl_rate/transitional.yaml @@ -0,0 +1,11 @@ +description: Rhode Island limits the Child Care Assistance Program to enrolled families with income at or below this share of the federal poverty level. +values: + 2020-01-01: 3 + +metadata: + unit: /1 + period: year + label: Rhode Island CCAP transitional eligibility FPL rate + reference: + - title: 218-RICR-20-00-4, Section 4.6.1.A.1 + href: https://rules.sos.ri.gov/regulations/part/218-20-00-4#4.6.1 diff --git a/policyengine_us/parameters/gov/states/ri/dhs/ccap/rates/center.yaml b/policyengine_us/parameters/gov/states/ri/dhs/ccap/rates/center.yaml new file mode 100644 index 00000000000..49c8abca01b --- /dev/null +++ b/policyengine_us/parameters/gov/states/ri/dhs/ccap/rates/center.yaml @@ -0,0 +1,200 @@ +description: Rhode Island provides these weekly reimbursement rates for licensed child care centers under the Child Care Assistance Program. +metadata: + period: week + unit: currency-USD + label: Rhode Island CCAP licensed center weekly rates + breakdown: + - ri_ccap_time_category + - ri_ccap_star_rating + - ri_ccap_center_age_group + reference: + - title: RI DHS CCAP Licensed Center Child Care Weekly Rates, Effective July 1, 2025 + href: https://dhs.ri.gov/media/9356/download?language=en + +FULL_TIME: + STAR_1: + INFANT: + 2025-07-01: 334 + TODDLER: + 2025-07-01: 278 + PRESCHOOL: + 2025-07-01: 236 + SCHOOL_AGE: + 2025-07-01: 210 + STAR_2: + INFANT: + 2025-07-01: 341 + TODDLER: + 2025-07-01: 284 + PRESCHOOL: + 2025-07-01: 247 + SCHOOL_AGE: + 2025-07-01: 215 + STAR_3: + INFANT: + 2025-07-01: 355 + TODDLER: + 2025-07-01: 296 + PRESCHOOL: + 2025-07-01: 255 + SCHOOL_AGE: + 2025-07-01: 231 + STAR_4: + INFANT: + 2025-07-01: 364 + TODDLER: + 2025-07-01: 303 + PRESCHOOL: + 2025-07-01: 263 + SCHOOL_AGE: + 2025-07-01: 250 + STAR_5: + INFANT: + 2025-07-01: 378 + TODDLER: + 2025-07-01: 315 + PRESCHOOL: + 2025-07-01: 273 + SCHOOL_AGE: + 2025-07-01: 263 + +THREE_QUARTER_TIME: + STAR_1: + INFANT: + 2025-07-01: 250.50 + TODDLER: + 2025-07-01: 208.50 + PRESCHOOL: + 2025-07-01: 177 + SCHOOL_AGE: + 2025-07-01: 157.50 + STAR_2: + INFANT: + 2025-07-01: 255.75 + TODDLER: + 2025-07-01: 213 + PRESCHOOL: + 2025-07-01: 185.25 + SCHOOL_AGE: + 2025-07-01: 161.25 + STAR_3: + INFANT: + 2025-07-01: 266.25 + TODDLER: + 2025-07-01: 222 + PRESCHOOL: + 2025-07-01: 191.25 + SCHOOL_AGE: + 2025-07-01: 173.25 + STAR_4: + INFANT: + 2025-07-01: 273 + TODDLER: + 2025-07-01: 227.25 + PRESCHOOL: + 2025-07-01: 197.25 + SCHOOL_AGE: + 2025-07-01: 187.50 + STAR_5: + INFANT: + 2025-07-01: 283.50 + TODDLER: + 2025-07-01: 236.25 + PRESCHOOL: + 2025-07-01: 204.75 + SCHOOL_AGE: + 2025-07-01: 197.25 + +HALF_TIME: + STAR_1: + INFANT: + 2025-07-01: 167 + TODDLER: + 2025-07-01: 139 + PRESCHOOL: + 2025-07-01: 118 + SCHOOL_AGE: + 2025-07-01: 105 + STAR_2: + INFANT: + 2025-07-01: 170.50 + TODDLER: + 2025-07-01: 142 + PRESCHOOL: + 2025-07-01: 123.50 + SCHOOL_AGE: + 2025-07-01: 107.50 + STAR_3: + INFANT: + 2025-07-01: 177.50 + TODDLER: + 2025-07-01: 148 + PRESCHOOL: + 2025-07-01: 127.50 + SCHOOL_AGE: + 2025-07-01: 115.50 + STAR_4: + INFANT: + 2025-07-01: 182 + TODDLER: + 2025-07-01: 151.50 + PRESCHOOL: + 2025-07-01: 131.50 + SCHOOL_AGE: + 2025-07-01: 125 + STAR_5: + INFANT: + 2025-07-01: 189 + TODDLER: + 2025-07-01: 157.50 + PRESCHOOL: + 2025-07-01: 136.50 + SCHOOL_AGE: + 2025-07-01: 131.50 + +QUARTER_TIME: + STAR_1: + INFANT: + 2025-07-01: 83.50 + TODDLER: + 2025-07-01: 69.50 + PRESCHOOL: + 2025-07-01: 59 + SCHOOL_AGE: + 2025-07-01: 52.50 + STAR_2: + INFANT: + 2025-07-01: 85.25 + TODDLER: + 2025-07-01: 71 + PRESCHOOL: + 2025-07-01: 61.75 + SCHOOL_AGE: + 2025-07-01: 53.75 + STAR_3: + INFANT: + 2025-07-01: 88.75 + TODDLER: + 2025-07-01: 74 + PRESCHOOL: + 2025-07-01: 63.75 + SCHOOL_AGE: + 2025-07-01: 57.75 + STAR_4: + INFANT: + 2025-07-01: 91 + TODDLER: + 2025-07-01: 75.75 + PRESCHOOL: + 2025-07-01: 65.75 + SCHOOL_AGE: + 2025-07-01: 62.50 + STAR_5: + INFANT: + 2025-07-01: 94.50 + TODDLER: + 2025-07-01: 78.75 + PRESCHOOL: + 2025-07-01: 68.25 + SCHOOL_AGE: + 2025-07-01: 65.75 diff --git a/policyengine_us/parameters/gov/states/ri/dhs/ccap/rates/exempt.yaml b/policyengine_us/parameters/gov/states/ri/dhs/ccap/rates/exempt.yaml new file mode 100644 index 00000000000..19e3eb21153 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ri/dhs/ccap/rates/exempt.yaml @@ -0,0 +1,132 @@ +description: Rhode Island provides these weekly reimbursement rates for license-exempt child care under the Child Care Assistance Program. +metadata: + period: week + unit: currency-USD + label: Rhode Island CCAP license-exempt weekly rates + breakdown: + - ri_ccap_time_category + - ri_ccap_step_rating + - ri_ccap_family_age_group + reference: + - title: RI DHS CCAP Licensed Exempt Child Care Weekly Rates, Effective January 1, 2022 + href: https://dhs.ri.gov/media/3556/download?language=en + +FULL_TIME: + STEP_1: + INFANT_TODDLER: + 2022-01-01: 100.96 + PRESCHOOL: + 2022-01-01: 59.91 + SCHOOL_AGE: + 2022-01-01: 58.80 + STEP_2: + INFANT_TODDLER: + 2022-01-01: 101.95 + PRESCHOOL: + 2022-01-01: 60.49 + SCHOOL_AGE: + 2022-01-01: 59.38 + STEP_3: + INFANT_TODDLER: + 2022-01-01: 102.94 + PRESCHOOL: + 2022-01-01: 61.09 + SCHOOL_AGE: + 2022-01-01: 59.97 + STEP_4: + INFANT_TODDLER: + 2022-01-01: 103.96 + PRESCHOOL: + 2022-01-01: 61.68 + SCHOOL_AGE: + 2022-01-01: 60.53 + +THREE_QUARTER_TIME: + STEP_1: + INFANT_TODDLER: + 2022-01-01: 75.72 + PRESCHOOL: + 2022-01-01: 44.93 + SCHOOL_AGE: + 2022-01-01: 44.10 + STEP_2: + INFANT_TODDLER: + 2022-01-01: 76.46 + PRESCHOOL: + 2022-01-01: 45.37 + SCHOOL_AGE: + 2022-01-01: 44.53 + STEP_3: + INFANT_TODDLER: + 2022-01-01: 77.21 + PRESCHOOL: + 2022-01-01: 45.83 + SCHOOL_AGE: + 2022-01-01: 44.97 + STEP_4: + INFANT_TODDLER: + 2022-01-01: 77.96 + PRESCHOOL: + 2022-01-01: 46.26 + SCHOOL_AGE: + 2022-01-01: 45.40 + +HALF_TIME: + STEP_1: + INFANT_TODDLER: + 2022-01-01: 50.48 + PRESCHOOL: + 2022-01-01: 29.95 + SCHOOL_AGE: + 2022-01-01: 29.40 + STEP_2: + INFANT_TODDLER: + 2022-01-01: 50.98 + PRESCHOOL: + 2022-01-01: 30.26 + SCHOOL_AGE: + 2022-01-01: 29.69 + STEP_3: + INFANT_TODDLER: + 2022-01-01: 51.48 + PRESCHOOL: + 2022-01-01: 30.54 + SCHOOL_AGE: + 2022-01-01: 29.98 + STEP_4: + INFANT_TODDLER: + 2022-01-01: 51.98 + PRESCHOOL: + 2022-01-01: 30.84 + SCHOOL_AGE: + 2022-01-01: 30.28 + +QUARTER_TIME: + STEP_1: + INFANT_TODDLER: + 2022-01-01: 25.24 + PRESCHOOL: + 2022-01-01: 14.71 + SCHOOL_AGE: + 2022-01-01: 14.70 + STEP_2: + INFANT_TODDLER: + 2022-01-01: 25.49 + PRESCHOOL: + 2022-01-01: 15.11 + SCHOOL_AGE: + 2022-01-01: 14.85 + STEP_3: + INFANT_TODDLER: + 2022-01-01: 25.74 + PRESCHOOL: + 2022-01-01: 15.28 + SCHOOL_AGE: + 2022-01-01: 14.99 + STEP_4: + INFANT_TODDLER: + 2022-01-01: 25.98 + PRESCHOOL: + 2022-01-01: 15.42 + SCHOOL_AGE: + 2022-01-01: 15.13 diff --git a/policyengine_us/parameters/gov/states/ri/dhs/ccap/rates/family.yaml b/policyengine_us/parameters/gov/states/ri/dhs/ccap/rates/family.yaml new file mode 100644 index 00000000000..0adda51c479 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ri/dhs/ccap/rates/family.yaml @@ -0,0 +1,160 @@ +description: Rhode Island provides these weekly reimbursement rates for licensed family child care under the Child Care Assistance Program. +metadata: + period: week + unit: currency-USD + label: Rhode Island CCAP licensed family weekly rates + breakdown: + - ri_ccap_time_category + - ri_ccap_star_rating + - ri_ccap_family_age_group + reference: + - title: RI DHS CCAP Licensed Family Child Care Weekly Rates, Effective July 1, 2024 + href: https://dhs.ri.gov/media/7481/download?language=en + +FULL_TIME: + STAR_1: + INFANT_TODDLER: + 2024-07-01: 262.66 + PRESCHOOL: + 2024-07-01: 220.63 + SCHOOL_AGE: + 2024-07-01: 194.37 + STAR_2: + INFANT_TODDLER: + 2024-07-01: 266.86 + PRESCHOOL: + 2024-07-01: 231.14 + SCHOOL_AGE: + 2024-07-01: 199.62 + STAR_3: + INFANT_TODDLER: + 2024-07-01: 270.02 + PRESCHOOL: + 2024-07-01: 239.54 + SCHOOL_AGE: + 2024-07-01: 215.38 + STAR_4: + INFANT_TODDLER: + 2024-07-01: 273.16 + PRESCHOOL: + 2024-07-01: 251.10 + SCHOOL_AGE: + 2024-07-01: 236.40 + STAR_5: + INFANT_TODDLER: + 2024-07-01: 276.31 + PRESCHOOL: + 2024-07-01: 262.66 + SCHOOL_AGE: + 2024-07-01: 246.90 + +THREE_QUARTER_TIME: + STAR_1: + INFANT_TODDLER: + 2024-07-01: 196.99 + PRESCHOOL: + 2024-07-01: 165.47 + SCHOOL_AGE: + 2024-07-01: 145.78 + STAR_2: + INFANT_TODDLER: + 2024-07-01: 200.14 + PRESCHOOL: + 2024-07-01: 173.35 + SCHOOL_AGE: + 2024-07-01: 149.71 + STAR_3: + INFANT_TODDLER: + 2024-07-01: 202.51 + PRESCHOOL: + 2024-07-01: 179.66 + SCHOOL_AGE: + 2024-07-01: 161.54 + STAR_4: + INFANT_TODDLER: + 2024-07-01: 204.87 + PRESCHOOL: + 2024-07-01: 188.33 + SCHOOL_AGE: + 2024-07-01: 177.30 + STAR_5: + INFANT_TODDLER: + 2024-07-01: 207.23 + PRESCHOOL: + 2024-07-01: 196.99 + SCHOOL_AGE: + 2024-07-01: 185.18 + +HALF_TIME: + STAR_1: + INFANT_TODDLER: + 2024-07-01: 131.33 + PRESCHOOL: + 2024-07-01: 110.32 + SCHOOL_AGE: + 2024-07-01: 97.19 + STAR_2: + INFANT_TODDLER: + 2024-07-01: 133.43 + PRESCHOOL: + 2024-07-01: 115.57 + SCHOOL_AGE: + 2024-07-01: 99.81 + STAR_3: + INFANT_TODDLER: + 2024-07-01: 135.01 + PRESCHOOL: + 2024-07-01: 119.77 + SCHOOL_AGE: + 2024-07-01: 107.69 + STAR_4: + INFANT_TODDLER: + 2024-07-01: 136.58 + PRESCHOOL: + 2024-07-01: 125.55 + SCHOOL_AGE: + 2024-07-01: 118.20 + STAR_5: + INFANT_TODDLER: + 2024-07-01: 138.15 + PRESCHOOL: + 2024-07-01: 131.33 + SCHOOL_AGE: + 2024-07-01: 123.45 + +QUARTER_TIME: + STAR_1: + INFANT_TODDLER: + 2024-07-01: 65.66 + PRESCHOOL: + 2024-07-01: 55.16 + SCHOOL_AGE: + 2024-07-01: 48.59 + STAR_2: + INFANT_TODDLER: + 2024-07-01: 66.71 + PRESCHOOL: + 2024-07-01: 57.78 + SCHOOL_AGE: + 2024-07-01: 49.90 + STAR_3: + INFANT_TODDLER: + 2024-07-01: 67.50 + PRESCHOOL: + 2024-07-01: 59.89 + SCHOOL_AGE: + 2024-07-01: 53.85 + STAR_4: + INFANT_TODDLER: + 2024-07-01: 68.29 + PRESCHOOL: + 2024-07-01: 62.78 + SCHOOL_AGE: + 2024-07-01: 59.10 + STAR_5: + INFANT_TODDLER: + 2024-07-01: 69.08 + PRESCHOOL: + 2024-07-01: 65.66 + SCHOOL_AGE: + 2024-07-01: 61.73 diff --git a/policyengine_us/parameters/gov/states/ri/dhs/ccap/time_authorization/thresholds.yaml b/policyengine_us/parameters/gov/states/ri/dhs/ccap/time_authorization/thresholds.yaml new file mode 100644 index 00000000000..ad943177717 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ri/dhs/ccap/time_authorization/thresholds.yaml @@ -0,0 +1,30 @@ +description: Rhode Island sets these time authorization levels based on weekly child care hours under the Child Care Assistance Program. +metadata: + type: single_amount + threshold_unit: hour + amount_unit: /1 + period: year + label: Rhode Island CCAP time authorization thresholds + reference: + - title: 218-RICR-20-00-4, Section 4.7.1.A.2 + href: https://rules.sos.ri.gov/regulations/part/218-20-00-4#4.7.1 + - title: 218-RICR-20-00-4, Section 4.12.B.1 + href: https://rules.sos.ri.gov/regulations/part/218-20-00-4#4.12 + +brackets: + - threshold: + 2020-01-01: 0 + amount: + 2020-01-01: 3 + - threshold: + 2020-01-01: 10 + amount: + 2020-01-01: 2 + - threshold: + 2020-01-01: 20 + amount: + 2020-01-01: 1 + - threshold: + 2020-01-01: 30 + amount: + 2020-01-01: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/copay/ri_ccap_copay.yaml b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/copay/ri_ccap_copay.yaml new file mode 100644 index 00000000000..17895d3d67c --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/copay/ri_ccap_copay.yaml @@ -0,0 +1,148 @@ +# 2025 FPG family of 3: 15_650 + 5_500 * 2 = 26_650 + +- name: Case 1, income at 200 percent FPL with 7 percent copay. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 53_300 + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: RI + output: + # FPL ratio = 53,300 / 26,650 = 2.0 -> 7% rate + # annual copay = 53,300 * 0.07 = 3,731 + # monthly copay = 3,731 / 12 = 310.92 + ri_ccap_copay: 310.92 + +- name: Case 2, family under 100 percent FPL pays zero copay. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: RI + output: + # FPG family of 3: 26_650 + # 20_000 / 26_650 = 75% FPL -> copay rate = 0% + ri_ccap_copay: 0 + +- name: Case 3, housing insecure family pays zero copay. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 35_000 + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: RI + is_homeless: true + output: + # housing insecure -> exempt from copay -> $0 + ri_ccap_copay: 0 + +- name: Case 4, income at 110 percent FPL with 2 percent copay. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 29_315 + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: RI + output: + # FPL ratio = 29,315 / 26,650 = 1.1 -> 2% rate + # annual copay = 29,315 * 0.02 = 586.30 + # monthly copay = 586.30 / 12 = 48.86 + ri_ccap_copay: 48.86 + +- name: Case 5, income at or below 100 percent FPL pays zero. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: RI + output: + # FPL ratio = 20,000 / 26,650 = 0.75 -> 0% rate + # copay = 20,000 * 0 = 0 + ri_ccap_copay: 0 + +- name: Case 6, income at 130 percent FPL with 5 percent copay. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 34_645 + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: RI + output: + # FPL ratio = 34,645 / 26,650 = 1.3 -> 5% rate + # annual copay = 34,645 * 0.05 = 1,732.25 + # monthly copay = 1,732.25 / 12 = 144.35 + ri_ccap_copay: 144.35 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/edge_cases/ri_ccap.yaml b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/edge_cases/ri_ccap.yaml new file mode 100644 index 00000000000..0fbe89a1cef --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/edge_cases/ri_ccap.yaml @@ -0,0 +1,355 @@ +# Edge cases for ri_ccap (top-level benefit) +# 2025 FPG family of 2: 21_150 +# monthly benefit = min(max(pre_subsidy_childcare_expenses - copay, 0), max_weekly_benefit * 52) / 12 + +- name: Case 1, multiple children different providers aggregated. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 25_000 + immigration_status: CITIZEN + person2: + age: 1 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_3 + person3: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + is_in_k12_school: false + childcare_hours_per_week: 20 + ri_ccap_provider_type: LICENSED_FAMILY + ri_ccap_star_rating: STAR_2 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2, person3] + state_code: RI + output: + # FPG family of 3: 26_650 + # FPL ratio = 25_000 / 26_650 = 0.9381 -> 0% copay + # copay = 0 + # child1: Center FT Star 3 Infant = $355/wk + # child2: Family 3QT Star 2 Preschool = $173.35/wk + # max annual = (355 + 173.35) * 52 = 528.35 * 52 = 27_474.20 + # uncapped = max(20_000 - 0, 0) = 20_000 + # annual benefit = min(20_000, 27_474.20) = 20_000 + # monthly = 20_000 / 12 = 1_666.67 + ri_ccap: 1_666.67 + +- name: Case 2, zero income family gets full subsidy with zero copay. + period: 2025-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 + is_in_k12_school: false + childcare_hours_per_week: 35 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_1 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 5_000 + households: + household: + members: [person1, person2] + state_code: RI + output: + # $0 income -> FPL ratio = 0 -> copay rate = 0% -> copay = 0 + # Center FT Star 1 Preschool = $236/wk + # max annual = 236 * 52 = 12_272 + # uncapped = max(5_000 - 0, 0) = 5_000 + # annual benefit = min(5_000, 12_272) = 5_000 + # monthly = 5_000 / 12 = 416.67 + ri_ccap: 416.67 + +- name: Case 3, housing insecure with moderate income gets zero copay. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 45_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + is_in_k12_school: false + childcare_hours_per_week: 35 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_1 + 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: RI + is_homeless: true + output: + # FPG family of 2: 21_150 + # 261% = 55_201.50, income 45_000 <= 55_201.50 -> eligible + # Housing insecure -> $0 copay + # Center FT Star 1 Preschool = $236/wk + # max annual = 236 * 52 = 12_272 + # uncapped = max(10_000 - 0, 0) = 10_000 + # annual benefit = min(10_000, 12_272) = 10_000 + # monthly = 10_000 / 12 = 833.33 + ri_ccap: 833.33 + +- name: Case 4, enrolled family between 261 and 300 percent FPL. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 55_500 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + is_in_k12_school: false + childcare_hours_per_week: 35 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_1 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + ri_ccap_enrolled: true + spm_unit_pre_subsidy_childcare_expenses: 12_000 + households: + household: + members: [person1, person2] + state_code: RI + output: + # FPG family of 2: 21_150 + # 261% = 55_201.50, 300% = 63_450 + # enrolled: 55_500 <= 63_450 -> eligible + # FPL ratio = 55_500 / 21_150 = 2.6241 -> 7% copay + # annual copay = 55_500 * 0.07 = 3_885 + # Center FT Star 1 Preschool = $236/wk + # max annual = 236 * 52 = 12_272 + # uncapped = max(12_000 - 3_885, 0) = 8_115 + # annual benefit = min(8_115, 12_272) = 8_115 + # monthly = 8_115 / 12 = 676.25 + ri_ccap: 676.25 + +- name: Case 5, non-enrolled between 261 and 300 percent gets zero. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 55_500 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + is_in_k12_school: false + childcare_hours_per_week: 35 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_1 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 12_000 + households: + household: + members: [person1, person2] + state_code: RI + output: + # not enrolled: 55_500 > 55_201.50 (261%) -> ineligible -> $0 + ri_ccap: 0 + +- name: Case 6, expenses exactly equal to max annual rate. + period: 2025-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 + is_in_k12_school: false + childcare_hours_per_week: 35 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_1 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + # max annual = 236 * 52 = 12_272 + spm_unit_pre_subsidy_childcare_expenses: 12_272 + households: + household: + members: [person1, person2] + state_code: RI + output: + # FPL ratio = 15_000 / 21_150 = 0.709 -> 0% copay + # copay = 0 + # uncapped = max(12_272 - 0, 0) = 12_272 + # max annual = 12_272 + # annual benefit = min(12_272, 12_272) = 12_272 + # monthly = 12_272 / 12 = 1_022.67 + ri_ccap: 1_022.67 + +- name: Case 7, quarter time care with low expenses. + period: 2025-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 + is_in_k12_school: false + childcare_hours_per_week: 5 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_1 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 4_000 + households: + household: + members: [person1, person2] + state_code: RI + output: + # FPL ratio = 20_000 / 21_150 = 0.946 -> 0% copay + # copay = 0 + # Center QT Star 1 Preschool = $59/wk + # max annual = 59 * 52 = 3_068 + # uncapped = max(4_000 - 0, 0) = 4_000 + # annual benefit = min(4_000, 3_068) = 3_068 + # monthly = 3_068 / 12 = 255.67 + ri_ccap: 255.67 + +- name: Case 8, disabled teenager with license exempt care. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + employment_income: 30_000 + immigration_status: CITIZEN + person2: + age: 17 + is_tax_unit_dependent: true + is_disabled: true + immigration_status: CITIZEN + is_in_k12_school: true + childcare_hours_per_week: 25 + ri_ccap_provider_type: LICENSE_EXEMPT + ri_ccap_step_rating: STEP_3 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 5_000 + households: + household: + members: [person1, person2] + state_code: RI + output: + # disabled, age 17 < 18 -> eligible child + # FPG family of 2: 21_150 + # FPL ratio = 30_000 / 21_150 = 1.4184 -> 5% copay + # annual copay = 30_000 * 0.05 = 1_500 + # Exempt 3QT Step 3 School Age = $44.97/wk + # max annual = 44.97 * 52 = 2_338.44 + # uncapped = max(5_000 - 1_500, 0) = 3_500 + # annual benefit = min(3_500, 2_338.44) = 2_338.44 + # monthly = 2_338.44 / 12 = 194.87 + ri_ccap: 194.87 + +- name: Case 9, negative countable income does not inflate benefit. + period: 2025-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 + is_in_k12_school: false + childcare_hours_per_week: 35 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_1 + 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: RI + output: + # Negative income -> FPL ratio = 0 -> copay rate = 0% -> copay = 0 + # Center FT Star 1 Preschool = $236/wk + # max annual = 236 * 52 = 12_272 + # uncapped = max(10_000 - 0, 0) = 10_000 + # annual benefit = min(10_000, 12_272) = 10_000 + # monthly = 10_000 / 12 = 833.33 + # Benefit capped at max, NOT inflated by negative income + ri_ccap: 833.33 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/edge_cases/ri_ccap_copay.yaml b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/edge_cases/ri_ccap_copay.yaml new file mode 100644 index 00000000000..bd33765dca5 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/edge_cases/ri_ccap_copay.yaml @@ -0,0 +1,68 @@ +# Edge cases for ri_ccap_copay +# 2025 FPG family of 2: 21_150 +# Tests homeless exemption, zero income + +- name: Case 1, housing insecure family with moderate income gets zero copay. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 40_000 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + is_homeless: true + output: + # Housing insecure -> $0 copay regardless of income + ri_ccap_copay: 0 + +- name: Case 2, zero income gives zero copay. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + # income 0 -> FPL ratio 0 -> 0% rate -> copay = 0 * 0 = 0 + ri_ccap_copay: 0 + +- name: Case 3, very high income at 7 percent rate. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 55_000 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + # FPL ratio = 55_000 / 21_150 = 2.6005 -> 7% rate + # annual copay = 55_000 * 0.07 = 3_850 + # monthly copay = 3_850 / 12 = 320.83 + ri_ccap_copay: 320.83 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/edge_cases/ri_ccap_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/edge_cases/ri_ccap_eligible.yaml new file mode 100644 index 00000000000..1cd2f98a763 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/edge_cases/ri_ccap_eligible.yaml @@ -0,0 +1,130 @@ +# Edge cases for ri_ccap_eligible +# Tests activity requirements, degenerate cases + +- name: Case 1, zero income family with eligible child is eligible. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + person2: + age: 5 + 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: RI + output: + # $0 income < 261% FPL, assets < $1M, weekly_hours_worked defaults to 40 + ri_ccap_eligible: true + +- name: Case 2, parent not working enough hours is ineligible. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + weekly_hours_worked: 15 + person2: + age: 5 + 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: RI + output: + # 15 hours < 20 minimum -> activity ineligible + ri_ccap_eligible: false + +- name: Case 3, single adult without child is ineligible. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 10_000 + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_eligible: false + +- name: Case 4, income eligible but assets ineligible. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 5 + 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_500_000 + households: + household: + members: [person1, person2] + state_code: RI + output: + # income ok, but assets 1.5M > 1M -> ineligible + ri_ccap_eligible: false + +- name: Case 5, assets eligible but income ineligible. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 60_000 + immigration_status: CITIZEN + person2: + age: 5 + 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: RI + output: + # FPG family of 2: 21_150 + # 261% FPL = 55_201.50 + # income 60_000 > 55_201.50 -> ineligible + ri_ccap_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/edge_cases/ri_ccap_eligible_child.yaml b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/edge_cases/ri_ccap_eligible_child.yaml new file mode 100644 index 00000000000..8d690091c01 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/edge_cases/ri_ccap_eligible_child.yaml @@ -0,0 +1,150 @@ +# Edge cases for ri_ccap_eligible_child +# Child age threshold: < 13 +# Disabled child age threshold: <= 18 + +- name: Case 1, child age 12 is last eligible year. + period: 2025-01 + input: + people: + person1: + age: 40 + person2: + age: 12 + 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: RI + output: + # age 12 < 13 -> eligible + ri_ccap_eligible_child: [false, true] + +- name: Case 2, non-disabled child age 13 is ineligible. + period: 2025-01 + input: + people: + person1: + age: 40 + person2: + age: 13 + 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: RI + output: + # age 13 not < 13 -> ineligible + ri_ccap_eligible_child: [false, false] + +- name: Case 3, disabled child age 18 is last eligible year. + period: 2025-01 + input: + people: + person1: + age: 45 + person2: + age: 18 + is_tax_unit_dependent: true + is_disabled: 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: RI + output: + # disabled, age 18 <= 18 -> eligible + ri_ccap_eligible_child: [false, true] + +- name: Case 4, disabled child age 19 is ineligible. + period: 2025-01 + input: + people: + person1: + age: 45 + person2: + age: 19 + is_tax_unit_dependent: true + is_disabled: 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: RI + output: + # disabled, age 19 not <= 18 -> ineligible + ri_ccap_eligible_child: [false, false] + +- name: Case 5, disabled child age 13 is still eligible. + period: 2025-01 + input: + people: + person1: + age: 40 + person2: + age: 13 + is_tax_unit_dependent: true + is_disabled: 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: RI + output: + # disabled, age 13 <= 18 -> eligible (uses disabled threshold) + ri_ccap_eligible_child: [false, true] + +- name: Case 6, age 0 infant is eligible. + period: 2025-01 + input: + people: + person1: + age: 25 + person2: + age: 0 + 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: RI + output: + # age 0 < 13 -> eligible + ri_ccap_eligible_child: [false, true] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/edge_cases/ri_ccap_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/edge_cases/ri_ccap_income_eligible.yaml new file mode 100644 index 00000000000..fea3e91e948 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/edge_cases/ri_ccap_income_eligible.yaml @@ -0,0 +1,206 @@ +# Edge cases for ri_ccap_income_eligible +# 2025 FPG (Contiguous US): +# Family of 1: 15_650 +# Family of 2: 21_150 +# Family of 3: 26_650 +# 261% FPL (family of 2): 21_150 * 2.61 = 55_201.50 +# 300% FPL (family of 2): 21_150 * 3.00 = 63_450.00 + +- name: Case 1, new applicant income below 261 percent FPL. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 55_000 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + # 55_000 <= ~55_201 (261% of 21_150) -> eligible + ri_ccap_income_eligible: true + +- name: Case 2, new applicant income above 261 percent FPL. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 55_500 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + # 55_500 > ~55_201 (261% of 21_150) -> ineligible + ri_ccap_income_eligible: false + +- name: Case 3, new applicant income well below 261 percent FPL. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 55_100 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + # 55_100 <= ~55_201 -> eligible + ri_ccap_income_eligible: true + +- name: Case 4, enrolled family income exactly at 300 percent FPL. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 63_450 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + ri_ccap_enrolled: true + households: + household: + members: [person1, person2] + state_code: RI + output: + # enrolled: 63_450 <= 63_450 -> eligible (at boundary) + ri_ccap_income_eligible: true + +- name: Case 5, enrolled family income one cent above 300 percent FPL. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 63_450.01 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + ri_ccap_enrolled: true + households: + household: + members: [person1, person2] + state_code: RI + output: + # enrolled: 63_450.01 > 63_450 -> ineligible + ri_ccap_income_eligible: false + +- name: Case 6, enrolled family income one cent below 300 percent FPL. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 63_449.99 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + ri_ccap_enrolled: true + households: + household: + members: [person1, person2] + state_code: RI + output: + # enrolled: 63_449.99 <= 63_450 -> eligible + ri_ccap_income_eligible: true + +- name: Case 7, enrolled family exactly at 261 percent FPL uses transitional limit. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 55_201.50 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + ri_ccap_enrolled: true + households: + household: + members: [person1, person2] + state_code: RI + output: + # enrolled: 55_201.50 <= 63_450 (300% FPL limit) -> eligible + ri_ccap_income_eligible: true + +- name: Case 8, non-enrolled between 261 and 300 percent is ineligible. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 55_202 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + ri_ccap_enrolled: false + households: + household: + members: [person1, person2] + state_code: RI + output: + # not enrolled: 55_202 > 55_201.50 (261% FPL) -> ineligible + ri_ccap_income_eligible: false + +- name: Case 9, large family of 8 at 261 percent FPL. + period: 2025-01 + input: + people: + person1: + age: 35 + # FPG family of 8: 15_650 + 5_500 * 7 = 54_150 + # 261% = 54_150 * 2.61 = 141_331.50 + employment_income: 141_331.50 + person2: + age: 10 + person3: + age: 8 + person4: + age: 6 + person5: + age: 4 + person6: + age: 3 + person7: + age: 1 + person8: + age: 38 + 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: RI + output: + # 141_331.50 <= 141_331.50 -> eligible + ri_ccap_income_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/edge_cases/ri_ccap_maximum_weekly_benefit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/edge_cases/ri_ccap_maximum_weekly_benefit.yaml new file mode 100644 index 00000000000..6b046880273 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/edge_cases/ri_ccap_maximum_weekly_benefit.yaml @@ -0,0 +1,193 @@ +# Edge cases for ri_ccap_maximum_weekly_benefit +# Tests rate lookup at time category boundaries + +- name: Case 1, center full time star 1 school age with exactly 30 hours. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 7 + is_in_k12_school: true + childcare_hours_per_week: 30 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_1 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + # 30 hrs -> FULL_TIME, Center FT Star 1 School Age = $210 + ri_ccap_maximum_weekly_benefit: [0, 210] + +- name: Case 2, center three quarter time star 1 school age with exactly 29 hours. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 7 + is_in_k12_school: true + childcare_hours_per_week: 29 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_1 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + # 29 hrs -> THREE_QUARTER_TIME, Center 3QT Star 1 School Age = $157.50 + ri_ccap_maximum_weekly_benefit: [0, 157.50] + +- name: Case 3, center half time star 1 school age with exactly 19 hours. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 7 + is_in_k12_school: true + childcare_hours_per_week: 19 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_1 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + # 19 hrs -> HALF_TIME, Center HT Star 1 School Age = $105 + ri_ccap_maximum_weekly_benefit: [0, 105] + +- name: Case 4, center half time star 1 school age with exactly 10 hours. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 7 + is_in_k12_school: true + childcare_hours_per_week: 10 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_1 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + # 10 hrs -> HALF_TIME, Center HT Star 1 School Age = $105 + ri_ccap_maximum_weekly_benefit: [0, 105] + +- name: Case 5, center quarter time star 1 school age with exactly 9 hours. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 7 + is_in_k12_school: true + childcare_hours_per_week: 9 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_1 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + # 9 hrs -> QUARTER_TIME, Center QT Star 1 School Age = $52.50 + ri_ccap_maximum_weekly_benefit: [0, 52.50] + +- name: Case 6, licensed family full time star 1 school age. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 7 + is_in_k12_school: true + childcare_hours_per_week: 35 + ri_ccap_provider_type: LICENSED_FAMILY + ri_ccap_star_rating: STAR_1 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + # Family FT Star 1 School Age = $194.37 + ri_ccap_maximum_weekly_benefit: [0, 194.37] + +- name: Case 7, license exempt full time step 4 infant toddler. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 1 + childcare_hours_per_week: 35 + ri_ccap_provider_type: LICENSE_EXEMPT + ri_ccap_step_rating: STEP_4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + # Exempt FT Step 4 Infant/Toddler = $103.96 + ri_ccap_maximum_weekly_benefit: [0, 103.96] + +- name: Case 8, center full time star 5 school age highest star. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 7 + is_in_k12_school: true + childcare_hours_per_week: 40 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + # Center FT Star 5 School Age = $263 + ri_ccap_maximum_weekly_benefit: [0, 263] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/edge_cases/ri_ccap_time_category.yaml b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/edge_cases/ri_ccap_time_category.yaml new file mode 100644 index 00000000000..aa57b64cb27 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/edge_cases/ri_ccap_time_category.yaml @@ -0,0 +1,46 @@ +# Edge cases for ri_ccap_time_category +# Time authorization thresholds: +# 0-9 hrs -> QUARTER_TIME +# 10-19 hrs -> HALF_TIME +# 20-29 hrs -> THREE_QUARTER_TIME +# 30+ hrs -> FULL_TIME + +- name: Case 1, boundary at 19 hours is half time. + period: 2025-01 + input: + people: + person1: + childcare_hours_per_week: 19 + households: + household: + members: [person1] + state_code: RI + output: + # 19 < 20 -> HALF_TIME + ri_ccap_time_category: HALF_TIME + +- name: Case 2, exactly 1 hour is quarter time. + period: 2025-01 + input: + people: + person1: + childcare_hours_per_week: 1 + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_time_category: QUARTER_TIME + +- name: Case 3, very high hours still full time. + period: 2025-01 + input: + people: + person1: + childcare_hours_per_week: 60 + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_time_category: FULL_TIME diff --git a/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/eligibility/ri_ccap_activity_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/eligibility/ri_ccap_activity_eligible.yaml new file mode 100644 index 00000000000..a71bcb63432 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/eligibility/ri_ccap_activity_eligible.yaml @@ -0,0 +1,133 @@ +- name: Case 1, single parent working 20 hours meets requirement. + period: 2025-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 20 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + ri_ccap_activity_eligible: true + +- name: Case 2, single parent working 19 hours does not meet requirement. + period: 2025-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 19 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + ri_ccap_activity_eligible: false + +- name: Case 3, full time student parent qualifies. + period: 2025-01 + input: + people: + person1: + age: 25 + weekly_hours_worked: 0 + is_full_time_student: true + person2: + age: 3 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + ri_ccap_activity_eligible: true + +- name: Case 4, two parents both working 20 plus hours. + period: 2025-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 25 + person2: + age: 28 + weekly_hours_worked: 20 + person3: + age: 5 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: RI + output: + ri_ccap_activity_eligible: true + +- name: Case 5, two parents one below 20 hours. + period: 2025-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 25 + person2: + age: 28 + weekly_hours_worked: 15 + person3: + age: 5 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: RI + output: + ri_ccap_activity_eligible: false + +- name: Case 6, one parent works and one is a full time student. + period: 2025-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 20 + person2: + age: 25 + weekly_hours_worked: 0 + is_full_time_student: true + person3: + age: 4 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: RI + output: + ri_ccap_activity_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/eligibility/ri_ccap_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/eligibility/ri_ccap_eligible.yaml new file mode 100644 index 00000000000..8e76ece33c5 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/eligibility/ri_ccap_eligible.yaml @@ -0,0 +1,128 @@ +# 2025 FPG family of 3: 15_650 + 5_500 * 2 = 26_650 +# 261% FPL = 69_556.50 + +- name: Case 1, eligible family with child under 13 and low income. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 30_000 + immigration_status: CITIZEN + person2: + age: 5 + 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: RI + output: + ri_ccap_eligible: true + +- name: Case 2, ineligible due to income above 261 percent FPL. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 70_000 + immigration_status: CITIZEN + person2: + age: 5 + 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: RI + output: + # 2025 FPG family of 2: 15_650 + 5_500 = 21_150 + # 261% FPL = 21_150 * 2.61 = 55_201.50 + # income 70,000 > 55,201.50 -> ineligible + ri_ccap_eligible: false + +- name: Case 3, ineligible with no eligible child. + period: 2025-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] + households: + household: + members: [person1] + state_code: RI + output: + # no child in unit -> no eligible child -> ineligible + ri_ccap_eligible: false + +- name: Case 4, ineligible due to assets above limit. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 5 + 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_500_000 + households: + household: + members: [person1, person2] + state_code: RI + output: + ri_ccap_eligible: false + +- name: Case 5, ineligible when child is undocumented. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: UNDOCUMENTED + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + ri_ccap_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/eligibility/ri_ccap_eligible_child.yaml b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/eligibility/ri_ccap_eligible_child.yaml new file mode 100644 index 00000000000..9e61b3abfda --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/eligibility/ri_ccap_eligible_child.yaml @@ -0,0 +1,159 @@ +- name: Case 1, child under 13 who is a citizen and dependent. + period: 2025-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + 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: RI + output: + ri_ccap_eligible_child: [false, true] + +- name: Case 2, child age 13 ineligible without disability. + period: 2025-01 + input: + people: + person1: + age: 35 + person2: + age: 13 + 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: RI + output: + ri_ccap_eligible_child: [false, false] + +- name: Case 3, disabled child age 15 eligible. + period: 2025-01 + input: + people: + person1: + age: 40 + person2: + age: 15 + is_tax_unit_dependent: true + is_disabled: 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: RI + output: + ri_ccap_eligible_child: [false, true] + +- name: Case 4, disabled child age 18 eligible (up through 18). + period: 2025-01 + input: + people: + person1: + age: 45 + person2: + age: 18 + is_tax_unit_dependent: true + is_disabled: 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: RI + output: + ri_ccap_eligible_child: [false, true] + +- name: Case 5, child who is not a dependent is ineligible. + period: 2025-01 + input: + people: + person1: + age: 30 + person2: + age: 8 + is_tax_unit_dependent: false + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + ri_ccap_eligible_child: [false, false] + +- name: Case 6, undocumented child ineligible. + period: 2025-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: UNDOCUMENTED + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + ri_ccap_eligible_child: [false, false] + +- name: Case 7, adult is never an eligible child. + period: 2025-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_eligible_child: [false] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/eligibility/ri_ccap_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/eligibility/ri_ccap_income_eligible.yaml new file mode 100644 index 00000000000..39bf857437d --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/eligibility/ri_ccap_income_eligible.yaml @@ -0,0 +1,140 @@ +# 2025 FPG family of 3 (contiguous US): 15_650 + 5_500 * 2 = 26_650 +# 261% FPL = 26_650 * 2.61 = 69_556.50 +# 300% FPL = 26_650 * 3.00 = 79_950.00 + +- name: Case 1, new applicant income below 261 percent FPL. + period: 2025-01 + absolute_error_margin: 0 + input: + people: + person1: + age: 30 + employment_income: 50_000 + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: RI + output: + # income 50,000 <= 69,556.50 (261% of 26,650) -> eligible + ri_ccap_income_eligible: true + +- name: Case 2, new applicant income above 261 percent FPL. + period: 2025-01 + absolute_error_margin: 0 + input: + people: + person1: + age: 30 + employment_income: 70_000 + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: RI + output: + # income 70,000 > 69,556.50 (261% of 26,650) -> ineligible + ri_ccap_income_eligible: false + +- name: Case 3, enrolled family income between 261 and 300 percent FPL. + period: 2025-01 + absolute_error_margin: 0 + input: + people: + person1: + age: 30 + employment_income: 75_000 + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + ri_ccap_enrolled: true + households: + household: + members: [person1, person2, person3] + state_code: RI + output: + # enrolled: income 75,000 <= 79,950 (300% of 26,650) -> eligible + ri_ccap_income_eligible: true + +- name: Case 4, enrolled family income above 300 percent FPL. + period: 2025-01 + absolute_error_margin: 0 + input: + people: + person1: + age: 30 + employment_income: 80_000 + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + ri_ccap_enrolled: true + households: + household: + members: [person1, person2, person3] + state_code: RI + output: + # enrolled: income 80,000 > 79,950 (300% of 26,650) -> ineligible + ri_ccap_income_eligible: false + +- name: Case 5, non-enrolled family between 261 and 300 percent FPL. + period: 2025-01 + absolute_error_margin: 0 + input: + people: + person1: + age: 30 + employment_income: 75_000 + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + ri_ccap_enrolled: false + households: + household: + members: [person1, person2, person3] + state_code: RI + output: + # not enrolled: income 75,000 > 69,556.50 (261% of 26,650) -> ineligible + ri_ccap_income_eligible: false + +- name: Case 6, zero income family is eligible. + period: 2025-01 + absolute_error_margin: 0 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + ri_ccap_income_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/integration.yaml new file mode 100644 index 00000000000..f1d5666d08c --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/integration.yaml @@ -0,0 +1,493 @@ +# RI CCAP Integration Tests +# 2025 FPG (Contiguous US): +# first_person = 15_650, additional = 5_500 +# Family of 2: 21_150 +# Family of 3: 26_650 +# Family of 4: 32_150 + +- name: Case 1, basic eligible family with licensed center care. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 40_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + is_in_k12_school: false + childcare_hours_per_week: 35 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_3 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 13_000 + households: + household: + members: [person1, person2] + state_code: RI + output: + # === Eligibility === + # Child age 4 < 13 -> age eligible + # Citizen -> immigration eligible + # Dependent -> eligible child + ri_ccap_eligible_child: [false, true] + + # FPG family of 2: 21_150 + # Income 40,000, 261% FPL = 21_150 * 2.61 = 55_201.50 + # 40,000 <= 55,201.50 -> income eligible + ri_ccap_income_eligible: true + + # Assets default 0 <= 1,000,000 -> asset eligible + is_ccdf_asset_eligible: true + + ri_ccap_eligible: true + + # === Copay === + # FPL ratio = 40,000 / 21,150 = 1.8913 -> 7% copay + + # annual copay = 40,000 * 0.07 = 2,800 + # monthly copay = 2,800 / 12 = 233.33 + ri_ccap_copay: 233.33 + + # === Provider rates === + # Center age: 4 years, not in school -> PRESCHOOL + ri_ccap_center_age_group: [PRESCHOOL, PRESCHOOL] + # Parent: 0 hrs/wk -> QUARTER_TIME; Child: 35 hrs/wk -> FULL_TIME + ri_ccap_time_category: [QUARTER_TIME, FULL_TIME] + # Center FT Star 3 Preschool = $255 + ri_ccap_maximum_weekly_benefit: [0, 255] + + # === Benefit === + # max annual = 255 * 52 = 13,260 + # uncapped = max(13,000 - 2,800, 0) = 10,200 + # annual benefit = min(10,200, 13,260) = 10,200 + # monthly = 10,200 / 12 = 850 + ri_ccap: 850 + +- name: Case 2, low income family with zero copay. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + employment_income: 18_000 + immigration_status: CITIZEN + person2: + age: 1 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 40 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_2 + person3: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + is_in_k12_school: false + childcare_hours_per_week: 30 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_2 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_pre_subsidy_childcare_expenses: 25_000 + households: + household: + members: [person1, person2, person3] + state_code: RI + output: + # === Eligibility === + ri_ccap_eligible_child: [false, true, true] + + # FPG family of 3: 26,650 + # 18,000 <= 26,650 * 2.61 = 69,556.50 -> eligible + ri_ccap_income_eligible: true + is_ccdf_asset_eligible: true + ri_ccap_eligible: true + + # === Copay === + # FPL ratio = 18,000 / 26,650 = 0.6754 -> 0% copay + + ri_ccap_copay: 0 + + # === Provider rates === + # child1 (age 1): INFANT center group, FT Star 2 = $341 + # child2 (age 5, not in school): PRESCHOOL center group, FT Star 2 = $247 + ri_ccap_center_age_group: [PRESCHOOL, INFANT, PRESCHOOL] + # Parent: 0 hrs/wk -> QUARTER_TIME; Children: FT + ri_ccap_time_category: [QUARTER_TIME, FULL_TIME, FULL_TIME] + ri_ccap_maximum_weekly_benefit: [0, 341, 247] + + # === Benefit === + # max annual per child: 341*52 = 17,732 + 247*52 = 12,844 = 30,576 + # uncapped = max(25,000 - 0, 0) = 25,000 + # annual benefit = min(25,000, 30,576) = 25,000 + # monthly = 25,000 / 12 = 2,083.33 + ri_ccap: 2_083.33 + +- name: Case 3, enrolled family at transitional FPL level. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 32 + employment_income: 72_000 + immigration_status: CITIZEN + person2: + age: 3 + is_tax_unit_dependent: true + immigration_status: LEGAL_PERMANENT_RESIDENT + is_in_k12_school: false + childcare_hours_per_week: 25 + ri_ccap_provider_type: LICENSED_FAMILY + ri_ccap_star_rating: STAR_4 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + ri_ccap_enrolled: true + spm_unit_pre_subsidy_childcare_expenses: 10_000 + households: + household: + members: [person1, person2] + state_code: RI + output: + # === Eligibility === + ri_ccap_eligible_child: [false, true] + + # FPG family of 2: 21,150 + # 261% = 55,201.50, 300% = 63,450 + # 72,000 > 55,201.50 but enrolled, so use 300% + # 72,000 > 63,450 -> ineligible even for transitional + ri_ccap_income_eligible: false + + is_ccdf_asset_eligible: true + ri_ccap_eligible: false + + # === Benefit === + # Not eligible -> 0 + ri_ccap: 0 + +- name: Case 4, enrolled family within transitional range. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 32 + employment_income: 60_000 + immigration_status: CITIZEN + person2: + age: 3 + is_tax_unit_dependent: true + immigration_status: CITIZEN + is_in_k12_school: false + childcare_hours_per_week: 25 + ri_ccap_provider_type: LICENSED_FAMILY + ri_ccap_star_rating: STAR_4 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + ri_ccap_enrolled: true + spm_unit_pre_subsidy_childcare_expenses: 10_000 + households: + household: + members: [person1, person2] + state_code: RI + output: + # === Eligibility === + ri_ccap_eligible_child: [false, true] + + # FPG family of 2: 21,150 + # 300% = 63,450 + # enrolled: 60,000 <= 63,450 -> eligible + ri_ccap_income_eligible: true + is_ccdf_asset_eligible: true + ri_ccap_eligible: true + + # === Copay === + # FPL ratio = 60,000 / 21,150 = 2.8369 -> 7% copay + + # annual copay = 60,000 * 0.07 = 4,200 + # monthly copay = 4,200 / 12 = 350 + ri_ccap_copay: 350 + + # === Provider rates === + # age 3, not in school -> PRESCHOOL family group + ri_ccap_family_age_group: [PRESCHOOL, PRESCHOOL] + # Parent: 0 hrs/wk -> QUARTER_TIME; Child: 25 hrs -> THREE_QUARTER_TIME + ri_ccap_time_category: [QUARTER_TIME, THREE_QUARTER_TIME] + # Family 3QT Star 4 Preschool = $188.33 + ri_ccap_maximum_weekly_benefit: [0, 188.33] + + # === Benefit === + # max annual = 188.33 * 52 = 9,793.16 + # uncapped = max(10,000 - 4,200, 0) = 5,800 + # annual benefit = min(5,800, 9,793.16) = 5,800 + # monthly = 5,800 / 12 = 483.33 + ri_ccap: 483.33 + +- name: Case 5, housing insecure family with license exempt care. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 25 + employment_income: 35_000 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: REFUGEE + childcare_hours_per_week: 15 + ri_ccap_provider_type: LICENSE_EXEMPT + ri_ccap_step_rating: STEP_2 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 3_000 + households: + household: + members: [person1, person2] + state_code: RI + is_homeless: true + output: + # === Eligibility === + ri_ccap_eligible_child: [false, true] + is_ccdf_immigration_eligible_child: [true, true] + + # FPG family of 2: 21,150 + # 35,000 <= 55,201.50 (261%) -> eligible + ri_ccap_income_eligible: true + is_ccdf_asset_eligible: true + ri_ccap_eligible: true + + # === Copay === + # Housing insecure -> $0 copay + ri_ccap_copay: 0 + + # === Provider rates === + # Parent: not in school -> PRESCHOOL; Child age 2 -> INFANT_TODDLER + ri_ccap_family_age_group: [PRESCHOOL, INFANT_TODDLER] + # Parent: 0 hrs/wk -> QUARTER_TIME; Child: 15 hrs -> HALF_TIME + ri_ccap_time_category: [QUARTER_TIME, HALF_TIME] + # Exempt HT Step 2 Infant/Toddler = $50.98 + ri_ccap_maximum_weekly_benefit: [0, 50.98] + + # === Benefit === + # max annual = 50.98 * 52 = 2,650.96 + # uncapped = max(3,000 - 0, 0) = 3,000 + # annual benefit = min(3,000, 2,650.96) = 2,650.96 + # monthly = 2,650.96 / 12 = 220.91 + ri_ccap: 220.91 + +- name: Case 6, disabled teenager with family day care. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + employment_income: 45_000 + immigration_status: CITIZEN + person2: + age: 15 + is_tax_unit_dependent: true + is_disabled: true + immigration_status: CITIZEN + is_in_k12_school: true + childcare_hours_per_week: 20 + ri_ccap_provider_type: LICENSED_FAMILY + ri_ccap_star_rating: STAR_3 + 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: RI + output: + # === Eligibility === + # age 15 < 18 (disabled threshold) -> age eligible + ri_ccap_eligible_child: [false, true] + + # FPG family of 2: 21,150 + # 45,000 <= 55,201.50 -> income eligible + ri_ccap_income_eligible: true + is_ccdf_asset_eligible: true + ri_ccap_eligible: true + + # === Copay === + # FPL ratio = 45,000 / 21,150 = 2.1277 -> 7% copay + + # annual copay = 45,000 * 0.07 = 3,150 + # monthly copay = 3,150 / 12 = 262.50 + ri_ccap_copay: 262.50 + + # === Provider rates === + # Parent: not in school -> PRESCHOOL; Child age 15, in school -> SCHOOL_AGE + ri_ccap_family_age_group: [PRESCHOOL, SCHOOL_AGE] + # Parent: 0 hrs/wk -> QUARTER_TIME; Child: 20 hrs -> THREE_QUARTER_TIME + ri_ccap_time_category: [QUARTER_TIME, THREE_QUARTER_TIME] + # Family 3QT Star 3 School Age = $161.54 + ri_ccap_maximum_weekly_benefit: [0, 161.54] + + # === Benefit === + # max annual = 161.54 * 52 = 8,400.08 + # uncapped = max(8,000 - 3,150, 0) = 4,850 + # annual benefit = min(4,850, 8,400.08) = 4,850 + # monthly = 4,850 / 12 = 404.17 + ri_ccap: 404.17 + +- name: Case 7, two children with different provider types. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 30_000 + immigration_status: CITIZEN + person2: + age: 1 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_4 + person3: + age: 8 + is_tax_unit_dependent: true + immigration_status: CITIZEN + is_in_k12_school: true + childcare_hours_per_week: 10 + ri_ccap_provider_type: LICENSE_EXEMPT + ri_ccap_step_rating: STEP_1 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_pre_subsidy_childcare_expenses: 15_000 + households: + household: + members: [person1, person2, person3] + state_code: RI + output: + # === Eligibility === + ri_ccap_eligible_child: [false, true, true] + + # FPG family of 3: 26,650 + # 30,000 <= 69,556.50 -> eligible + ri_ccap_income_eligible: true + ri_ccap_eligible: true + + # === Copay === + # FPL ratio = 30,000 / 26,650 = 1.1257 -> 2% copay + + # annual copay = 30,000 * 0.02 = 600 + # monthly copay = 600 / 12 = 50 + ri_ccap_copay: 50 + + # === Provider rates === + # child1 (age 1): Center FT Star 4 Infant = $364 + # child2 (age 8, in school): Exempt HT Step 1 School Age = $29.40 + ri_ccap_center_age_group: [PRESCHOOL, INFANT, SCHOOL_AGE] + # Parent: 0 hrs/wk -> QUARTER_TIME; child1: 35 hrs -> FULL_TIME; child2: 10 hrs -> HALF_TIME + ri_ccap_time_category: [QUARTER_TIME, FULL_TIME, HALF_TIME] + ri_ccap_maximum_weekly_benefit: [0, 364, 29.40] + + # === Benefit === + # max annual = (364 + 29.40) * 52 = 393.40 * 52 = 20,456.80 + # uncapped = max(15,000 - 600, 0) = 14,400 + # annual benefit = min(14,400, 20,456.80) = 14,400 + # monthly = 14,400 / 12 = 1,200 + ri_ccap: 1_200 + +- name: Case 8, zero income family at licensed family care gets full subsidy. + period: 2025-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 + is_in_k12_school: false + childcare_hours_per_week: 35 + ri_ccap_provider_type: LICENSED_FAMILY + ri_ccap_star_rating: STAR_3 + 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: RI + output: + # === Eligibility === + # Age 4 < 13, dependent, citizen -> eligible child + ri_ccap_eligible_child: [false, true] + + # FPG family of 2: 21,150 + # $0 income <= 55,201.50 (261% FPL) -> eligible + ri_ccap_income_eligible: true + is_ccdf_asset_eligible: true + # weekly_hours_worked defaults to 40 >= 20 -> activity eligible + ri_ccap_activity_eligible: true + ri_ccap_eligible: true + + # === Copay === + # FPL ratio = 0 / 21,150 = 0 -> 0% copay rate + + # copay = 0 * 0 = 0 + ri_ccap_copay: 0 + + # === Provider rates === + # Age 4 at licensed family -> PRESCHOOL (age >= 3, not in school) + ri_ccap_family_age_group: [PRESCHOOL, PRESCHOOL] + # Parent: 0 hrs/wk -> QUARTER_TIME; child: 35 hrs/wk -> FULL_TIME + ri_ccap_time_category: [QUARTER_TIME, FULL_TIME] + # Family FT Star 3 Preschool = $239.54/wk + ri_ccap_maximum_weekly_benefit: [0, 239.54] + + # === Benefit === + # max annual = 239.54 * 52 = 12,456.08 + # uncapped = max(15,000 - 0, 0) = 15,000 + # annual benefit = min(15,000, 12,456.08) = 12,456.08 + # monthly = 12,456.08 / 12 = 1,038.01 + ri_ccap: 1_038.01 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/ri_ccap.yaml b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/ri_ccap.yaml new file mode 100644 index 00000000000..22647af9cc5 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/ri_ccap.yaml @@ -0,0 +1,214 @@ +# ri_ccap: SPMUnit, float, MONTH +# monthly benefit = min(max(pre_subsidy_childcare_expenses - copay, 0), max_weekly_benefit * 52) / 12 +# 2025 FPG family of 3: 15_650 + 5_500 * 2 = 26_650 + +- name: Case 1, basic eligible family with childcare expenses. + period: 2025-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 + is_in_k12_school: false + childcare_hours_per_week: 35 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_1 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 12_000 + households: + household: + members: [person1, person2] + state_code: RI + output: + # FPG family of 2: 15_650 + 5_500 = 21_150 + # FPL ratio = 30_000 / 21_150 = 1.4184 -> 5% copay rate + # annual copay = 30_000 * 0.05 = 1_500 + # max weekly = $236 (Center FT Star 1 Preschool) + # max annual = 236 * 52 = 12_272 + # uncapped = max(12_000 - 1_500, 0) = 10_500 + # annual benefit = min(10_500, 12_272) = 10_500 + # monthly = 10_500 / 12 = 875 + ri_ccap: 875 + +- name: Case 2, ineligible family gets zero. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 70_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_1 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 12_000 + households: + household: + members: [person1, person2] + state_code: RI + output: + # income 70,000 > 261% FPL of 21,150 = 55,201.50 -> ineligible + ri_ccap: 0 + +- name: Case 3, benefit capped at maximum annual rate. + period: 2025-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 + is_in_k12_school: false + childcare_hours_per_week: 35 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_1 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2] + state_code: RI + output: + # FPG family of 2: 21_150 + # FPL ratio = 15_000 / 21_150 = 0.709 -> 0% copay rate + # copay = 0 + # max weekly = $236 (Center FT Star 1 Preschool) + # max annual = 236 * 52 = 12_272 + # uncapped = max(20_000 - 0, 0) = 20_000 + # annual benefit = min(20_000, 12_272) = 12_272 + # monthly = 12_272 / 12 = 1_022.67 + ri_ccap: 1_022.67 + +- name: Case 4, zero childcare expenses gives zero benefit. + period: 2025-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 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_1 + 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: RI + output: + ri_ccap: 0 + +- name: Case 5, zero income family gets zero copay and full subsidy. + period: 2025-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 + is_in_k12_school: false + childcare_hours_per_week: 35 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_1 + 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: RI + output: + # $0 income -> FPL ratio = 0 -> copay rate = 0% -> copay = 0 + # max weekly = $236 (Center FT Star 1 Preschool) + # max annual = 236 * 52 = 12_272 + # uncapped = max(10_000 - 0, 0) = 10_000 + # annual benefit = min(10_000, 12_272) = 10_000 + # monthly = 10_000 / 12 = 833.33 + ri_ccap: 833.33 + +- name: Case 6, copay exceeds expenses gives zero benefit. + period: 2025-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 + is_in_k12_school: false + childcare_hours_per_week: 5 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_1 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 2_000 + households: + household: + members: [person1, person2] + state_code: RI + output: + # FPG family of 2: 21_150 + # FPL ratio = 50_000 / 21_150 = 2.364 -> 7% copay rate + # annual copay = 50_000 * 0.07 = 3_500 + # uncapped = max(2_000 - 3_500, 0) = 0 + # benefit = 0 + ri_ccap: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/ri_ccap_center_age_group.yaml b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/ri_ccap_center_age_group.yaml new file mode 100644 index 00000000000..f0c53d6984a --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/ri_ccap_center_age_group.yaml @@ -0,0 +1,100 @@ +# Center age groups: +# Infant: age < 2 +# Toddler: age 2 (i.e., age < 3) +# Preschool: age 3+ and not in K-12 school +# School Age: in K-12 school + +- name: Case 1, infant age 1. + period: 2025-01 + input: + people: + person1: + age: 1 + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_center_age_group: INFANT + +- name: Case 2, toddler age 2. + period: 2025-01 + input: + people: + person1: + age: 2 + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_center_age_group: TODDLER + +- name: Case 3, preschool age 4 not in school. + period: 2025-01 + input: + people: + person1: + age: 4 + is_in_k12_school: false + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_center_age_group: PRESCHOOL + +- name: Case 4, school age child in K-12. + period: 2025-01 + input: + people: + person1: + age: 7 + is_in_k12_school: true + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_center_age_group: SCHOOL_AGE + +- name: Case 5, preschool age 3 not in school. + period: 2025-01 + input: + people: + person1: + age: 3 + is_in_k12_school: false + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_center_age_group: PRESCHOOL + +- name: Case 6, age 5 in school is school age. + period: 2025-01 + input: + people: + person1: + age: 5 + is_in_k12_school: true + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_center_age_group: SCHOOL_AGE + +- name: Case 7, age 0 is infant. + period: 2025-01 + input: + people: + person1: + age: 0 + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_center_age_group: INFANT diff --git a/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/ri_ccap_family_age_group.yaml b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/ri_ccap_family_age_group.yaml new file mode 100644 index 00000000000..a009b3d0e36 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/ri_ccap_family_age_group.yaml @@ -0,0 +1,85 @@ +# Family/Exempt age groups: +# Infant/Toddler: age < 3 +# Preschool: age 3+ and not in K-12 school +# School Age: in K-12 school + +- name: Case 1, infant toddler age 1. + period: 2025-01 + input: + people: + person1: + age: 1 + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_family_age_group: INFANT_TODDLER + +- name: Case 2, infant toddler age 2. + period: 2025-01 + input: + people: + person1: + age: 2 + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_family_age_group: INFANT_TODDLER + +- name: Case 3, preschool age 4 not in school. + period: 2025-01 + input: + people: + person1: + age: 4 + is_in_k12_school: false + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_family_age_group: PRESCHOOL + +- name: Case 4, school age child in K-12. + period: 2025-01 + input: + people: + person1: + age: 7 + is_in_k12_school: true + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_family_age_group: SCHOOL_AGE + +- name: Case 5, preschool age 3 not in school. + period: 2025-01 + input: + people: + person1: + age: 3 + is_in_k12_school: false + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_family_age_group: PRESCHOOL + +- name: Case 6, age 0 is infant toddler. + period: 2025-01 + input: + people: + person1: + age: 0 + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_family_age_group: INFANT_TODDLER diff --git a/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/ri_ccap_maximum_weekly_benefit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/ri_ccap_maximum_weekly_benefit.yaml new file mode 100644 index 00000000000..14dc6a59c86 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/ri_ccap_maximum_weekly_benefit.yaml @@ -0,0 +1,286 @@ +# Tests for ri_ccap_maximum_weekly_benefit +# Rates effective: center July 2025, family July 2024, exempt Jan 2022 +# Person-level variable; parent output is 0 (default), child gets rate + +- name: Case 1, licensed center full time star 1 preschool. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 4 + is_in_k12_school: false + childcare_hours_per_week: 35 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_1 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + # Center FT Star 1 Preschool = $236 + ri_ccap_maximum_weekly_benefit: [0, 236] + +- name: Case 2, licensed center full time star 5 infant. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 1 + childcare_hours_per_week: 40 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + # Center FT Star 5 Infant = $378 + ri_ccap_maximum_weekly_benefit: [0, 378] + +- name: Case 3, licensed center three quarter time star 3 toddler. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 2 + childcare_hours_per_week: 25 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_3 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + # Center 3QT Star 3 Toddler = $222.00 + ri_ccap_maximum_weekly_benefit: [0, 222] + +- name: Case 4, licensed center half time star 4 school age. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 8 + is_in_k12_school: true + childcare_hours_per_week: 15 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + # Center HT Star 4 School Age = $125.00 + ri_ccap_maximum_weekly_benefit: [0, 125] + +- name: Case 5, licensed family full time star 2 infant toddler. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 1 + childcare_hours_per_week: 35 + ri_ccap_provider_type: LICENSED_FAMILY + ri_ccap_star_rating: STAR_2 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + # Family FT Star 2 Infant/Toddler = $266.86 + ri_ccap_maximum_weekly_benefit: [0, 266.86] + +- name: Case 6, licensed family quarter time star 4 preschool. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 4 + is_in_k12_school: false + childcare_hours_per_week: 5 + ri_ccap_provider_type: LICENSED_FAMILY + ri_ccap_star_rating: STAR_4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + # Family QT Star 4 Preschool = $62.78 + ri_ccap_maximum_weekly_benefit: [0, 62.78] + +- name: Case 7, licensed family three quarter time star 5 school age. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 8 + is_in_k12_school: true + childcare_hours_per_week: 22 + ri_ccap_provider_type: LICENSED_FAMILY + ri_ccap_star_rating: STAR_5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + # Family 3QT Star 5 School Age = $185.18 + ri_ccap_maximum_weekly_benefit: [0, 185.18] + +- name: Case 8, license exempt full time step 1 infant toddler. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 2 + childcare_hours_per_week: 35 + ri_ccap_provider_type: LICENSE_EXEMPT + ri_ccap_step_rating: STEP_1 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + # Exempt FT Step 1 Infant/Toddler = $100.96 + ri_ccap_maximum_weekly_benefit: [0, 100.96] + +- name: Case 9, license exempt half time step 3 preschool. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 4 + is_in_k12_school: false + childcare_hours_per_week: 12 + ri_ccap_provider_type: LICENSE_EXEMPT + ri_ccap_step_rating: STEP_3 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + # Exempt HT Step 3 Preschool = $30.54 + ri_ccap_maximum_weekly_benefit: [0, 30.54] + +- name: Case 10, license exempt quarter time step 4 school age. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 8 + is_in_k12_school: true + childcare_hours_per_week: 5 + ri_ccap_provider_type: LICENSE_EXEMPT + ri_ccap_step_rating: STEP_4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + # Exempt QT Step 4 School Age = $15.13 + ri_ccap_maximum_weekly_benefit: [0, 15.13] + +- name: Case 11, licensed center quarter time star 2 infant. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 1 + childcare_hours_per_week: 8 + ri_ccap_provider_type: LICENSED_CENTER + ri_ccap_star_rating: STAR_2 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + # Center QT Star 2 Infant = $85.25 + ri_ccap_maximum_weekly_benefit: [0, 85.25] + +- name: Case 12, license exempt three quarter time step 2 school age. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 7 + is_in_k12_school: true + childcare_hours_per_week: 22 + ri_ccap_provider_type: LICENSE_EXEMPT + ri_ccap_step_rating: STEP_2 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: RI + output: + # Exempt 3QT Step 2 School Age = $44.53 + ri_ccap_maximum_weekly_benefit: [0, 44.53] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/ri_ccap_time_category.yaml b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/ri_ccap_time_category.yaml new file mode 100644 index 00000000000..a94d8ed370a --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ri/dhs/ccap/ri_ccap_time_category.yaml @@ -0,0 +1,135 @@ +# Time authorization thresholds: +# 0-9 hrs -> QUARTER_TIME (enum index 4) +# 10-19 hrs -> HALF_TIME (enum index 3) +# 20-29 hrs -> THREE_QUARTER_TIME (enum index 2) +# 30+ hrs -> FULL_TIME (enum index 1) + +- name: Case 1, full time 35 hours per week. + period: 2025-01 + input: + people: + person1: + childcare_hours_per_week: 35 + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_time_category: FULL_TIME + +- name: Case 2, full time exactly 30 hours per week. + period: 2025-01 + input: + people: + person1: + childcare_hours_per_week: 30 + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_time_category: FULL_TIME + +- name: Case 3, three quarter time 25 hours per week. + period: 2025-01 + input: + people: + person1: + childcare_hours_per_week: 25 + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_time_category: THREE_QUARTER_TIME + +- name: Case 4, three quarter time exactly 20 hours per week. + period: 2025-01 + input: + people: + person1: + childcare_hours_per_week: 20 + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_time_category: THREE_QUARTER_TIME + +- name: Case 5, half time 15 hours per week. + period: 2025-01 + input: + people: + person1: + childcare_hours_per_week: 15 + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_time_category: HALF_TIME + +- name: Case 6, half time exactly 10 hours per week. + period: 2025-01 + input: + people: + person1: + childcare_hours_per_week: 10 + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_time_category: HALF_TIME + +- name: Case 7, quarter time 5 hours per week. + period: 2025-01 + input: + people: + person1: + childcare_hours_per_week: 5 + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_time_category: QUARTER_TIME + +- name: Case 8, quarter time zero hours per week. + period: 2025-01 + input: + people: + person1: + childcare_hours_per_week: 0 + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_time_category: QUARTER_TIME + +- name: Case 9, boundary at 29 hours is three quarter time. + period: 2025-01 + input: + people: + person1: + childcare_hours_per_week: 29 + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_time_category: THREE_QUARTER_TIME + +- name: Case 10, boundary at 9 hours is quarter time. + period: 2025-01 + input: + people: + person1: + childcare_hours_per_week: 9 + households: + household: + members: [person1] + state_code: RI + output: + ri_ccap_time_category: QUARTER_TIME diff --git a/policyengine_us/variables/gov/states/ri/dhs/ccap/copay/ri_ccap_copay.py b/policyengine_us/variables/gov/states/ri/dhs/ccap/copay/ri_ccap_copay.py new file mode 100644 index 00000000000..ab30e110eb8 --- /dev/null +++ b/policyengine_us/variables/gov/states/ri/dhs/ccap/copay/ri_ccap_copay.py @@ -0,0 +1,24 @@ +from policyengine_us.model_api import * + + +class ri_ccap_copay(Variable): + value_type = float + entity = SPMUnit + unit = USD + label = "Rhode Island CCAP family co-payment" + definition_period = MONTH + defined_for = StateCode.RI + reference = ( + "https://rules.sos.ri.gov/regulations/part/218-20-00-4#4.6.1", + "https://dhs.ri.gov/media/10606/download?language=en", + ) + + def formula(spm_unit, period, parameters): + is_homeless = spm_unit.household("is_homeless", period.this_year) + p = parameters(period).gov.states.ri.dhs.ccap.copay + countable_income = spm_unit("ri_ccap_countable_income", period) + fpg = spm_unit("spm_unit_fpg", period) + fpl_ratio = where(fpg > 0, countable_income / fpg, 0) + copay_rate = p.rate.calc(fpl_ratio) + copay = countable_income * copay_rate + return where(is_homeless, 0, copay) diff --git a/policyengine_us/variables/gov/states/ri/dhs/ccap/eligibility/ri_ccap_activity_eligible.py b/policyengine_us/variables/gov/states/ri/dhs/ccap/eligibility/ri_ccap_activity_eligible.py new file mode 100644 index 00000000000..54435d0d38c --- /dev/null +++ b/policyengine_us/variables/gov/states/ri/dhs/ccap/eligibility/ri_ccap_activity_eligible.py @@ -0,0 +1,20 @@ +from policyengine_us.model_api import * + + +class ri_ccap_activity_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for Rhode Island CCAP based on activity requirements" + definition_period = MONTH + defined_for = StateCode.RI + reference = "https://rules.sos.ri.gov/regulations/part/218-20-00-4#4.4" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ri.dhs.ccap.activity_requirements + 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 >= p.weekly_hours + is_student = person("is_full_time_student", period.this_year) + individually_eligible = meets_work_requirement | is_student + return spm_unit.sum(is_head_or_spouse & ~individually_eligible) == 0 diff --git a/policyengine_us/variables/gov/states/ri/dhs/ccap/eligibility/ri_ccap_eligible.py b/policyengine_us/variables/gov/states/ri/dhs/ccap/eligibility/ri_ccap_eligible.py new file mode 100644 index 00000000000..732391fe78d --- /dev/null +++ b/policyengine_us/variables/gov/states/ri/dhs/ccap/eligibility/ri_ccap_eligible.py @@ -0,0 +1,20 @@ +from policyengine_us.model_api import * + + +class ri_ccap_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for Rhode Island CCAP" + definition_period = MONTH + defined_for = StateCode.RI + reference = ( + "https://rules.sos.ri.gov/regulations/part/218-20-00-4", + "https://rules.sos.ri.gov/regulations/part/218-20-00-4#4.5", + ) + + def formula(spm_unit, period, parameters): + has_eligible_child = add(spm_unit, period, ["ri_ccap_eligible_child"]) > 0 + income_eligible = spm_unit("ri_ccap_income_eligible", period) + asset_eligible = spm_unit("is_ccdf_asset_eligible", period.this_year) + activity_eligible = spm_unit("ri_ccap_activity_eligible", period) + return has_eligible_child & income_eligible & asset_eligible & activity_eligible diff --git a/policyengine_us/variables/gov/states/ri/dhs/ccap/eligibility/ri_ccap_eligible_child.py b/policyengine_us/variables/gov/states/ri/dhs/ccap/eligibility/ri_ccap_eligible_child.py new file mode 100644 index 00000000000..2a2f59d5577 --- /dev/null +++ b/policyengine_us/variables/gov/states/ri/dhs/ccap/eligibility/ri_ccap_eligible_child.py @@ -0,0 +1,21 @@ +from policyengine_us.model_api import * + + +class ri_ccap_eligible_child(Variable): + value_type = bool + entity = Person + label = "Eligible child for Rhode Island CCAP" + definition_period = MONTH + defined_for = StateCode.RI + reference = "https://rules.sos.ri.gov/regulations/part/218-20-00-4#4.3.1" + + def formula(person, period, parameters): + p = parameters(period).gov.states.ri.dhs.ccap.age_threshold + age = person("age", period.this_year) + is_disabled = person("is_disabled", period.this_year) + age_eligible = where(is_disabled, age <= p.disabled_child, age < p.child) + is_dependent = person("is_tax_unit_dependent", period.this_year) + immigration_eligible = person( + "is_ccdf_immigration_eligible_child", period.this_year + ) + return age_eligible & is_dependent & immigration_eligible diff --git a/policyengine_us/variables/gov/states/ri/dhs/ccap/eligibility/ri_ccap_income_eligible.py b/policyengine_us/variables/gov/states/ri/dhs/ccap/eligibility/ri_ccap_income_eligible.py new file mode 100644 index 00000000000..4c877ab506b --- /dev/null +++ b/policyengine_us/variables/gov/states/ri/dhs/ccap/eligibility/ri_ccap_income_eligible.py @@ -0,0 +1,24 @@ +from policyengine_us.model_api import * + + +class ri_ccap_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for Rhode Island CCAP based on income" + definition_period = MONTH + defined_for = StateCode.RI + reference = "https://rules.sos.ri.gov/regulations/part/218-20-00-4#4.6.1" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ri.dhs.ccap.income.fpl_rate + countable_income = spm_unit("ri_ccap_countable_income", period) + fpg = spm_unit("spm_unit_fpg", period) + enrolled = spm_unit("ri_ccap_enrolled", period) + initial_limit = fpg * p.initial_eligibility + transitional_limit = fpg * p.transitional + income_limit = where( + enrolled, + transitional_limit, + initial_limit, + ) + return countable_income <= income_limit diff --git a/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap.py b/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap.py new file mode 100644 index 00000000000..5de43c7b179 --- /dev/null +++ b/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap.py @@ -0,0 +1,25 @@ +from policyengine_us.model_api import * + + +class ri_ccap(Variable): + value_type = float + entity = SPMUnit + unit = USD + label = "Rhode Island CCAP benefit amount" + definition_period = MONTH + defined_for = "ri_ccap_eligible" + reference = "https://rules.sos.ri.gov/regulations/part/218-20-00-4" + + def formula(spm_unit, period, parameters): + copay = spm_unit("ri_ccap_copay", period) + maximum_weekly_benefit = add( + spm_unit, period, ["ri_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/ri/dhs/ccap/ri_ccap_center_age_group.py b/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_center_age_group.py new file mode 100644 index 00000000000..72a3bec049e --- /dev/null +++ b/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_center_age_group.py @@ -0,0 +1,37 @@ +from policyengine_us.model_api import * + + +class RICCAPCenterAgeGroup(Enum): + INFANT = "Infant" + TODDLER = "Toddler" + PRESCHOOL = "Preschool" + SCHOOL_AGE = "School Age" + + +class ri_ccap_center_age_group(Variable): + value_type = Enum + entity = Person + possible_values = RICCAPCenterAgeGroup + default_value = RICCAPCenterAgeGroup.PRESCHOOL + definition_period = MONTH + label = "Rhode Island CCAP licensed center age group" + defined_for = StateCode.RI + reference = "https://dhs.ri.gov/media/9356/download?language=en" + + def formula(person, period, parameters): + p = parameters(period).gov.states.ri.dhs.ccap.age_group.center + age = person("age", period.this_year) + is_in_school = person("is_in_k12_school", period.this_year) + return select( + [ + age < p.infant_max, + age < p.toddler_max, + ~is_in_school, + ], + [ + RICCAPCenterAgeGroup.INFANT, + RICCAPCenterAgeGroup.TODDLER, + RICCAPCenterAgeGroup.PRESCHOOL, + ], + default=RICCAPCenterAgeGroup.SCHOOL_AGE, + ) diff --git a/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_countable_income.py b/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_countable_income.py new file mode 100644 index 00000000000..fdfd5fbcfd0 --- /dev/null +++ b/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_countable_income.py @@ -0,0 +1,13 @@ +from policyengine_us.model_api import * + + +class ri_ccap_countable_income(Variable): + value_type = float + entity = SPMUnit + label = "Rhode Island CCAP countable income" + definition_period = MONTH + unit = USD + defined_for = StateCode.RI + reference = "https://rules.sos.ri.gov/regulations/part/218-20-00-4#4.2" + + adds = "gov.states.ri.dhs.ccap.income.countable_income.sources" diff --git a/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_enrolled.py b/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_enrolled.py new file mode 100644 index 00000000000..753f4638dcf --- /dev/null +++ b/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_enrolled.py @@ -0,0 +1,9 @@ +from policyengine_us.model_api import * + + +class ri_ccap_enrolled(Variable): + value_type = bool + entity = SPMUnit + definition_period = MONTH + label = "Whether the family is currently enrolled in Rhode Island CCAP" + defined_for = StateCode.RI diff --git a/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_family_age_group.py b/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_family_age_group.py new file mode 100644 index 00000000000..fb808024eeb --- /dev/null +++ b/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_family_age_group.py @@ -0,0 +1,37 @@ +from policyengine_us.model_api import * + + +class RICCAPFamilyAgeGroup(Enum): + INFANT_TODDLER = "Infant/Toddler" + PRESCHOOL = "Preschool" + SCHOOL_AGE = "School Age" + + +class ri_ccap_family_age_group(Variable): + value_type = Enum + entity = Person + possible_values = RICCAPFamilyAgeGroup + default_value = RICCAPFamilyAgeGroup.PRESCHOOL + definition_period = MONTH + label = "Rhode Island CCAP licensed family and exempt age group" + defined_for = StateCode.RI + reference = ( + "https://dhs.ri.gov/media/7481/download?language=en", + "https://dhs.ri.gov/media/3556/download?language=en", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.states.ri.dhs.ccap.age_group.family + age = person("age", period.this_year) + is_in_school = person("is_in_k12_school", period.this_year) + return select( + [ + age < p.infant_toddler_max, + ~is_in_school, + ], + [ + RICCAPFamilyAgeGroup.INFANT_TODDLER, + RICCAPFamilyAgeGroup.PRESCHOOL, + ], + default=RICCAPFamilyAgeGroup.SCHOOL_AGE, + ) diff --git a/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_maximum_weekly_benefit.py b/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_maximum_weekly_benefit.py new file mode 100644 index 00000000000..cdef9b0fad2 --- /dev/null +++ b/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_maximum_weekly_benefit.py @@ -0,0 +1,45 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.ri.dhs.ccap.ri_ccap_provider_type import ( + RICCAPProviderType, +) + + +class ri_ccap_maximum_weekly_benefit(Variable): + value_type = float + entity = Person + unit = USD + label = "Rhode Island CCAP maximum weekly benefit per child" + definition_period = MONTH + defined_for = "ri_ccap_eligible_child" + reference = ( + "https://dhs.ri.gov/media/9356/download?language=en", + "https://dhs.ri.gov/media/7481/download?language=en", + "https://dhs.ri.gov/media/3556/download?language=en", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.states.ri.dhs.ccap.rates + provider_type = person("ri_ccap_provider_type", period) + time_category = person("ri_ccap_time_category", period) + + center_age = person("ri_ccap_center_age_group", period) + star_rating = person("ri_ccap_star_rating", period) + center_rate = p.center[time_category][star_rating][center_age] + + family_age = person("ri_ccap_family_age_group", period) + family_rate = p.family[time_category][star_rating][family_age] + + step_rating = person("ri_ccap_step_rating", period) + exempt_rate = p.exempt[time_category][step_rating][family_age] + + return select( + [ + provider_type == RICCAPProviderType.LICENSED_CENTER, + provider_type == RICCAPProviderType.LICENSED_FAMILY, + ], + [ + center_rate, + family_rate, + ], + default=exempt_rate, + ) diff --git a/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_provider_type.py b/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_provider_type.py new file mode 100644 index 00000000000..054d4033933 --- /dev/null +++ b/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_provider_type.py @@ -0,0 +1,18 @@ +from policyengine_us.model_api import * + + +class RICCAPProviderType(Enum): + LICENSED_CENTER = "Licensed Center" + LICENSED_FAMILY = "Licensed Family" + LICENSE_EXEMPT = "License Exempt" + + +class ri_ccap_provider_type(Variable): + value_type = Enum + entity = Person + possible_values = RICCAPProviderType + default_value = RICCAPProviderType.LICENSED_CENTER + definition_period = MONTH + label = "Rhode Island CCAP child care provider type" + defined_for = StateCode.RI + reference = "https://rules.sos.ri.gov/regulations/part/218-20-00-4#4.7.1" diff --git a/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_star_rating.py b/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_star_rating.py new file mode 100644 index 00000000000..5bae32f4a70 --- /dev/null +++ b/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_star_rating.py @@ -0,0 +1,20 @@ +from policyengine_us.model_api import * + + +class RICCAPStarRating(Enum): + STAR_1 = "1 Star" + STAR_2 = "2 Stars" + STAR_3 = "3 Stars" + STAR_4 = "4 Stars" + STAR_5 = "5 Stars" + + +class ri_ccap_star_rating(Variable): + value_type = Enum + entity = Person + possible_values = RICCAPStarRating + default_value = RICCAPStarRating.STAR_1 + definition_period = MONTH + label = "Rhode Island CCAP provider star rating" + defined_for = StateCode.RI + reference = "https://rules.sos.ri.gov/regulations/part/218-20-00-4#4.7.1" diff --git a/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_step_rating.py b/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_step_rating.py new file mode 100644 index 00000000000..50e7340b82b --- /dev/null +++ b/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_step_rating.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class RICCAPStepRating(Enum): + STEP_1 = "Step 1" + STEP_2 = "Step 2" + STEP_3 = "Step 3" + STEP_4 = "Step 4" + + +class ri_ccap_step_rating(Variable): + value_type = Enum + entity = Person + possible_values = RICCAPStepRating + default_value = RICCAPStepRating.STEP_1 + definition_period = MONTH + label = "Rhode Island CCAP license-exempt provider step rating" + defined_for = StateCode.RI + reference = "https://dhs.ri.gov/media/3556/download?language=en" diff --git a/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_time_category.py b/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_time_category.py new file mode 100644 index 00000000000..13a14dedc68 --- /dev/null +++ b/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_ccap_time_category.py @@ -0,0 +1,24 @@ +from policyengine_us.model_api import * + + +class RICCAPTimeCategory(Enum): + FULL_TIME = "Full Time" + THREE_QUARTER_TIME = "Three Quarter Time" + HALF_TIME = "Half Time" + QUARTER_TIME = "Quarter Time" + + +class ri_ccap_time_category(Variable): + value_type = Enum + entity = Person + possible_values = RICCAPTimeCategory + default_value = RICCAPTimeCategory.FULL_TIME + definition_period = MONTH + label = "Rhode Island CCAP time authorization category" + defined_for = StateCode.RI + reference = "https://rules.sos.ri.gov/regulations/part/218-20-00-4#4.7.1" + + def formula(person, period, parameters): + hours = person("childcare_hours_per_week", period.this_year) + p = parameters(period).gov.states.ri.dhs.ccap.time_authorization + return p.thresholds.calc(hours) diff --git a/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_child_care_subsidies.py b/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_child_care_subsidies.py new file mode 100644 index 00000000000..b2dbd31ffa6 --- /dev/null +++ b/policyengine_us/variables/gov/states/ri/dhs/ccap/ri_child_care_subsidies.py @@ -0,0 +1,11 @@ +from policyengine_us.model_api import * + + +class ri_child_care_subsidies(Variable): + value_type = float + entity = SPMUnit + label = "Rhode Island child care subsidies" + unit = USD + definition_period = YEAR + defined_for = StateCode.RI + adds = ["ri_ccap"] diff --git a/uv.lock b/uv.lock index efec4d8555d..7adaf13620b 100644 --- a/uv.lock +++ b/uv.lock @@ -1492,7 +1492,7 @@ wheels = [ [[package]] name = "policyengine-us" -version = "1.592.1" +version = "1.598.0" source = { editable = "." } dependencies = [ { name = "microdf-python" },