diff --git a/changelog.d/ms-ccap.added.md b/changelog.d/ms-ccap.added.md new file mode 100644 index 00000000000..1f1714ea2c6 --- /dev/null +++ b/changelog.d/ms-ccap.added.md @@ -0,0 +1 @@ +Add Mississippi Child Care Payment Program (CCPP). 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 748e5f5bffc..28f19090689 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 @@ -17,6 +17,7 @@ values: - ky_child_care_subsidies # Kentucky Child Care Assistance Program - ma_child_care_subsidies # Massachusetts Child Care Financial Assistance - me_child_care_subsidies # Maine Child Care Affordability Program + - ms_child_care_subsidies # Mississippi Child Care Payment Program (CCPP) - ne_child_care_subsidies # Nebraska Child Care Subsidy - vt_child_care_subsidies # Vermont Child Care Financial Assistance Program - nh_child_care_subsidies # New Hampshire Child Care Scholarship Program diff --git a/policyengine_us/parameters/gov/states/ms/dhs/ccpp/age_group/age.yaml b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/age_group/age.yaml new file mode 100644 index 00000000000..d673eaa4bdd --- /dev/null +++ b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/age_group/age.yaml @@ -0,0 +1,35 @@ +description: Mississippi determines a child's age group for payment rates under the Child Care Payment Program. +# Maps age in years to the 4-band age-group index used by the rate tables: +# 0 = INFANT (birth through 12 months, i.e. under 1 year) +# 1 = TODDLER (12 months up to 36 months, i.e. 1 to under 3 years) +# 2 = PRESCHOOL (3 years up to kindergarten, i.e. 3 to under 5 years) +# 3 = SCHOOL_AGE (5 years and older) +# Boundaries from the CCPP Policy Manual definitions of Infant (#49), Toddler +# (#87), Preschool (#66), and School Age (#74). +metadata: + type: single_amount + threshold_unit: year + amount_unit: /1 + period: year + label: Mississippi CCPP child age group by age + reference: + - title: Mississippi CCPP Policy Manual, Definitions (Infant #49 p.13, Toddler #87 p.16, Preschool #66 p.14, School Age #74 p.15) + href: https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=13 + +brackets: + - threshold: + 2021-11-01: 0 + amount: + 2021-11-01: 0 + - threshold: + 2021-11-01: 1 + amount: + 2021-11-01: 1 + - threshold: + 2021-11-01: 3 + amount: + 2021-11-01: 2 + - threshold: + 2021-11-01: 5 + amount: + 2021-11-01: 3 diff --git a/policyengine_us/parameters/gov/states/ms/dhs/ccpp/copay/fpg_exempt_rate.yaml b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/copay/fpg_exempt_rate.yaml new file mode 100644 index 00000000000..fcb669fab81 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/copay/fpg_exempt_rate.yaml @@ -0,0 +1,13 @@ +description: Mississippi waives the co-payment for families at or below this share of the federal poverty line under the Child Care Payment Program. +# Families with gross income at or below the federal poverty line pay no +# co-payment. +values: + 2021-11-01: 1 + +metadata: + unit: /1 + period: year + label: Mississippi CCPP co-payment poverty line exemption rate + reference: + - title: Mississippi CCPP Policy Manual, Rule 6.2 (Co-Payment Fee) + href: https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=40 diff --git a/policyengine_us/parameters/gov/states/ms/dhs/ccpp/copay/max_family_size.yaml b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/copay/max_family_size.yaml new file mode 100644 index 00000000000..b902528f7af --- /dev/null +++ b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/copay/max_family_size.yaml @@ -0,0 +1,13 @@ +description: Mississippi caps family size at this number when determining the co-payment rate under the Child Care Payment Program. +# The published fee scale's largest family-size row is "6 or more", so families +# of 6+ all use the size-6 co-payment percentage. +values: + 2021-11-01: 6 + +metadata: + unit: person + period: year + label: Mississippi CCPP co-payment maximum family size + reference: + - title: Mississippi CCPP Family Co-Payment Fee Scale (effective November 1, 2021) + href: https://www.mdhs.ms.gov/wp-content/uploads/2021/11/Copay-Table-Update-11_01_21.pdf diff --git a/policyengine_us/parameters/gov/states/ms/dhs/ccpp/copay/minimum_fee_categories_cap.yaml b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/copay/minimum_fee_categories_cap.yaml new file mode 100644 index 00000000000..4e499f32173 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/copay/minimum_fee_categories_cap.yaml @@ -0,0 +1,16 @@ +description: Mississippi caps the monthly co-payment at this amount for minimum-fee categories under the Child Care Payment Program. +# Minimum-fee categories (income above the federal poverty line) include +# protective-services children, parents with a disability receiving SSI, and +# special-needs children. The categories that cannot be tracked at the moment +# (transitional child care, teen parents, Healthy Families Mississippi) are +# handled on the variable side. +values: + 2021-11-01: 10 + +metadata: + unit: currency-USD + period: month + label: Mississippi CCPP minimum-fee co-payment cap + reference: + - title: Mississippi CCPP Policy Manual, Rule 6.2 (Co-Payment Fee) + href: https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=41 diff --git a/policyengine_us/parameters/gov/states/ms/dhs/ccpp/copay/rate/low_income.yaml b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/copay/rate/low_income.yaml new file mode 100644 index 00000000000..1402ee13a5a --- /dev/null +++ b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/copay/rate/low_income.yaml @@ -0,0 +1,36 @@ +description: Mississippi sets the co-payment as this share of gross income for families above 50% and up to 85% of state median income under the Child Care Payment Program. +# Co-payment percentage by family size for the "50% to 85% SMI" band. Family size +# is capped at 6 (the published table's "6 or more" row) before lookup. +metadata: + type: single_amount + threshold_unit: person + amount_unit: /1 + period: year + label: Mississippi CCPP co-payment rate above 50% SMI + reference: + - title: Mississippi CCDF State Plan FFY 2025-2027, Section 3.1 Family Co-payments (pp. 39-40) + href: https://www.mdhs.ms.gov/wp-content/uploads/2025/01/ACF-118-CCDF-FFY-2025-2027-For-Mississippi.pdf#page=39 + - title: Mississippi CCPP Family Co-Payment Fee Scale (effective November 1, 2021) + href: https://www.mdhs.ms.gov/wp-content/uploads/2021/11/Copay-Table-Update-11_01_21.pdf + +brackets: + - threshold: + 2021-11-01: 2 + amount: + 2021-11-01: 0.065 + - threshold: + 2021-11-01: 3 + amount: + 2021-11-01: 0.06 + - threshold: + 2021-11-01: 4 + amount: + 2021-11-01: 0.055 + - threshold: + 2021-11-01: 5 + amount: + 2021-11-01: 0.05 + - threshold: + 2021-11-01: 6 + amount: + 2021-11-01: 0.045 diff --git a/policyengine_us/parameters/gov/states/ms/dhs/ccpp/copay/rate/very_low_income.yaml b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/copay/rate/very_low_income.yaml new file mode 100644 index 00000000000..5ce939b72c2 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/copay/rate/very_low_income.yaml @@ -0,0 +1,39 @@ +description: Mississippi sets the co-payment as this share of gross income for families at or below 50% of state median income under the Child Care Payment Program. +# Co-payment percentage by family size for the "up to 50% SMI" band. Family size +# is capped at 6 (the fee scale's "6 or more" column) before lookup. These per-size +# rates are published directly in the Copay Fee Scale "Table 2: Family Co-Pay Rates" +# (5.5/5/4.5/4/3.5%); they also equal the State Plan's 5.5% cap stepped down +# 0.5 percentage point per family size. +metadata: + type: single_amount + threshold_unit: person + amount_unit: /1 + period: year + label: Mississippi CCPP co-payment rate at or below 50% SMI + reference: + - title: Mississippi CCDF State Plan FFY 2025-2027, Section 3.1 Family Co-payments (pp. 39-40) + href: https://www.mdhs.ms.gov/wp-content/uploads/2025/01/ACF-118-CCDF-FFY-2025-2027-For-Mississippi.pdf#page=39 + - title: Mississippi CCPP Family Co-Payment Fee Scale (effective November 1, 2021) + href: https://www.mdhs.ms.gov/wp-content/uploads/2021/11/Copay-Table-Update-11_01_21.pdf + +brackets: + - threshold: + 2021-11-01: 2 + amount: + 2021-11-01: 0.055 + - threshold: + 2021-11-01: 3 + amount: + 2021-11-01: 0.05 + - threshold: + 2021-11-01: 4 + amount: + 2021-11-01: 0.045 + - threshold: + 2021-11-01: 5 + amount: + 2021-11-01: 0.04 + - threshold: + 2021-11-01: 6 + amount: + 2021-11-01: 0.035 diff --git a/policyengine_us/parameters/gov/states/ms/dhs/ccpp/eligibility/activity_hours.yaml b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/eligibility/activity_hours.yaml new file mode 100644 index 00000000000..ff3ec50a23c --- /dev/null +++ b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/eligibility/activity_hours.yaml @@ -0,0 +1,13 @@ +description: Mississippi sets this minimum weekly activity hours requirement under the Child Care Payment Program. +# Parents or caretakers must work at least this many hours per week, or be +# enrolled full-time in education or approved job training (or a combination). +values: + 2021-11-01: 25 + +metadata: + unit: hour + period: week + label: Mississippi CCPP minimum weekly activity hours + reference: + - title: Mississippi CCPP Policy Manual, Rule 5.5 (Proof of Work/Education or Training) + href: https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=30 diff --git a/policyengine_us/parameters/gov/states/ms/dhs/ccpp/eligibility/child_age_limit.yaml b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/eligibility/child_age_limit.yaml new file mode 100644 index 00000000000..9e2a2a1ac8f --- /dev/null +++ b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/eligibility/child_age_limit.yaml @@ -0,0 +1,11 @@ +description: Mississippi limits the Child Care Payment Program to children younger than this age. +values: + 2021-11-01: 13 + +metadata: + unit: year + period: year + label: Mississippi CCPP child age limit + reference: + - title: Mississippi CCPP Policy Manual, Rule 5.1 (Eligibility Requirements) + href: https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=25 diff --git a/policyengine_us/parameters/gov/states/ms/dhs/ccpp/eligibility/special_needs_child_age_limit.yaml b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/eligibility/special_needs_child_age_limit.yaml new file mode 100644 index 00000000000..c8624b9a820 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/eligibility/special_needs_child_age_limit.yaml @@ -0,0 +1,11 @@ +description: Mississippi limits the Child Care Payment Program to special-needs children younger than this age. +values: + 2021-11-01: 19 + +metadata: + unit: year + period: year + label: Mississippi CCPP special-needs child age limit + reference: + - title: Mississippi CCPP Policy Manual, Rule 5.1 (Eligibility Requirements) + href: https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=25 diff --git a/policyengine_us/parameters/gov/states/ms/dhs/ccpp/geography/metro_counties.yaml b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/geography/metro_counties.yaml new file mode 100644 index 00000000000..3144507001f --- /dev/null +++ b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/geography/metro_counties.yaml @@ -0,0 +1,33 @@ +description: Mississippi designates these counties as metropolitan for payment rates under the Child Care Payment Program. +# The 17 Mississippi counties in a Metropolitan Statistical Area under the OMB +# February 2013 delineation (the basis for the 2013 NCHS Urban-Rural scheme the +# Market Rate Survey uses). Every other Mississippi county is treated as +# non-metro. Grouped by MSA: Jackson, Gulfport-Biloxi-Pascagoula, Hattiesburg, +# and the Mississippi portion of Memphis. +values: + 2023-07-01: + - COPIAH_COUNTY_MS + - HINDS_COUNTY_MS + - MADISON_COUNTY_MS + - RANKIN_COUNTY_MS + - SIMPSON_COUNTY_MS + - YAZOO_COUNTY_MS + - HANCOCK_COUNTY_MS + - HARRISON_COUNTY_MS + - JACKSON_COUNTY_MS + - FORREST_COUNTY_MS + - LAMAR_COUNTY_MS + - PERRY_COUNTY_MS + - BENTON_COUNTY_MS + - DESOTO_COUNTY_MS + - MARSHALL_COUNTY_MS + - TATE_COUNTY_MS + - TUNICA_COUNTY_MS + +metadata: + unit: list + period: year + label: Mississippi CCPP metropolitan counties + reference: + - title: OMB Bulletin No. 13-01, Metropolitan and Micropolitan Statistical Area delineations (February 2013) + href: https://www2.census.gov/programs-surveys/metro-micro/geographies/reference-files/2013/delineation-files/list1.xls diff --git a/policyengine_us/parameters/gov/states/ms/dhs/ccpp/income/countable_income/self_employment_sources.yaml b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/income/countable_income/self_employment_sources.yaml new file mode 100644 index 00000000000..77d895f6a7f --- /dev/null +++ b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/income/countable_income/self_employment_sources.yaml @@ -0,0 +1,18 @@ +description: Mississippi counts these self-employment income sources for eligibility and the co-payment under the Child Care Payment Program. +# Self-employment is counted as gross income (Rule 5.3 "Total Sales and +# Receipts"), so the variable floors the sum of these net sources at zero: a +# business loss does not offset other income. PolicyEngine's self-employment +# income is net, so this may still understate gross receipts. +values: + 2021-11-01: + - self_employment_income + - sstb_self_employment_income + - farm_operations_income + +metadata: + unit: list + period: year + label: Mississippi CCPP countable self-employment income sources + reference: + - title: Mississippi CCPP Policy Manual, Rule 5.4 (How Income is Calculated — Countable Income) + href: https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=28 diff --git a/policyengine_us/parameters/gov/states/ms/dhs/ccpp/income/countable_income/unearned_sources.yaml b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/income/countable_income/unearned_sources.yaml new file mode 100644 index 00000000000..3386d136047 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/income/countable_income/unearned_sources.yaml @@ -0,0 +1,23 @@ +description: Mississippi counts these gross unearned income sources for eligibility and the co-payment under the Child Care Payment Program. +values: + 2021-11-01: + - social_security # SSA benefits for parent and child (umbrella; do not also add social_security_disability) + - ssi # SSI for parent and child (separate from the social_security umbrella) + - unemployment_compensation # counted at redetermination only; simplified to always countable + - workers_compensation + - alimony_income + - veterans_benefits + - pension_income # retirement and pension + - rental_income + - dividend_income # dividends (regular and ongoing); interest is not on the manual's list + - capital_gains + # Countable items in the manual with no matching variable at the moment: + # military allotments, lump sums, short-term disability payments. + +metadata: + unit: list + period: year + label: Mississippi CCPP countable unearned income sources + reference: + - title: Mississippi CCPP Policy Manual, Rule 5.4 (How Income is Calculated — Countable Income) + href: https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=28 diff --git a/policyengine_us/parameters/gov/states/ms/dhs/ccpp/income/smi_rate.yaml b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/income/smi_rate.yaml new file mode 100644 index 00000000000..ec79519e969 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/income/smi_rate.yaml @@ -0,0 +1,11 @@ +description: Mississippi limits income to this share of state median income for eligibility under the Child Care Payment Program. +values: + 2021-11-01: 0.85 + +metadata: + unit: /1 + period: year + label: Mississippi CCPP SMI income limit rate + reference: + - title: Mississippi CCPP Policy Manual, Rule 5.1 (Eligibility Requirements) + href: https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=25 diff --git a/policyengine_us/parameters/gov/states/ms/dhs/ccpp/income/student_earner_age_limit.yaml b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/income/student_earner_age_limit.yaml new file mode 100644 index 00000000000..f534594399e --- /dev/null +++ b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/income/student_earner_age_limit.yaml @@ -0,0 +1,11 @@ +description: Mississippi excludes the earned income of students younger than this age from countable income under the Child Care Payment Program. +values: + 2021-11-01: 18 + +metadata: + unit: year + period: year + label: Mississippi CCPP student earner age limit + reference: + - title: Mississippi CCPP Policy Manual, Rule 5.4 (How Income is Calculated — Non-Countable Income) + href: https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=29 diff --git a/policyengine_us/parameters/gov/states/ms/dhs/ccpp/income/very_low_income_smi_rate.yaml b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/income/very_low_income_smi_rate.yaml new file mode 100644 index 00000000000..9087bdedb10 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/income/very_low_income_smi_rate.yaml @@ -0,0 +1,15 @@ +description: Mississippi uses this share of state median income to split the co-payment bands under the Child Care Payment Program. +# Families at or below 50% of state median income use the lower co-payment band; +# families above 50% (up to the 85% entry limit) use the higher band. +values: + 2021-11-01: 0.5 + +metadata: + unit: /1 + period: year + label: Mississippi CCPP very low income SMI rate + reference: + - title: Mississippi CCDF State Plan FFY 2025-2027, Section 3.1 Family Co-payments (pp. 39-40) + href: https://www.mdhs.ms.gov/wp-content/uploads/2025/01/ACF-118-CCDF-FFY-2025-2027-For-Mississippi.pdf#page=39 + - title: Mississippi CCPP Family Co-Payment Fee Scale (effective November 1, 2021) + href: https://www.mdhs.ms.gov/wp-content/uploads/2021/11/Copay-Table-Update-11_01_21.pdf diff --git a/policyengine_us/parameters/gov/states/ms/dhs/ccpp/rates/center.yaml b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/rates/center.yaml new file mode 100644 index 00000000000..4984c5e0adf --- /dev/null +++ b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/rates/center.yaml @@ -0,0 +1,77 @@ +description: Mississippi provides these maximum weekly payment rates for licensed child care centers under the Child Care Payment Program. +# Two rate eras, keyed by the facility's location (metro / non-metro); we use the +# household's county as a proxy for facility location. +# - 2023-07-01 = July-2023 "Current CCPP Rates" (2024 Market Rate Survey Table 1, p.9). +# - 2024-10-01 = FY2025-2027 State Plan adopted full-time base rates. The State Plan +# reports rates by "most populous region" (encoded in the METRO slot) and "lowest +# region" (NON_METRO slot); the most-populous figure equals the statewide 75th +# percentile. +# The FY2025-2027 State Plan publishes FULL-TIME base rates only; the adopted part-time +# rates for that era are not publicly available (only the family copay fee scale is +# published), so the part-time leaves below retain their 2023-07 values — a documented +# limitation we don't track at the moment. Special-needs children are paid the flat +# all-ages special-needs rate (see special_needs_center). +metadata: + period: week + unit: currency-USD + label: Mississippi CCPP center weekly rates + breakdown: + - ms_ccpp_facility_location + - ms_ccpp_age_group + - ms_ccpp_time_category + reference: + - title: 2024 Mississippi Child Care Market Rate Survey, Table 1 (Current CCPP Rates, Licensed Centers) + href: https://www.mdhs.ms.gov/wp-content/uploads/2024/06/Mississippi-Child-Care-Market-Rate-Survey-2024.pdf#page=9 + - title: Mississippi FFY 2025-2027 CCDF State Plan, §4.3.2 (adopted full-time base rates, most-populous region pp.59-60); effective date §4.3.1(b) p.57 + href: https://www.mdhs.ms.gov/wp-content/uploads/2025/01/ACF-118-CCDF-FFY-2025-2027-For-Mississippi.pdf#page=59 + +METRO: + INFANT: + FULL_TIME: + 2023-07-01: 152 + 2024-10-01: 167 + PART_TIME: + 2023-07-01: 90 + TODDLER: + FULL_TIME: + 2023-07-01: 145 + 2024-10-01: 160 + PART_TIME: + 2023-07-01: 90 + PRESCHOOL: + FULL_TIME: + 2023-07-01: 135 + 2024-10-01: 150 + PART_TIME: + 2023-07-01: 75 + SCHOOL_AGE: + FULL_TIME: + # Unchanged across eras (FY2025-2027 adopted full-time value is also $130). + 2023-07-01: 130 + PART_TIME: + 2023-07-01: 80 +NON_METRO: + INFANT: + FULL_TIME: + 2023-07-01: 125 + 2024-10-01: 140 + PART_TIME: + 2023-07-01: 80 + TODDLER: + FULL_TIME: + 2023-07-01: 120 + 2024-10-01: 135 + PART_TIME: + 2023-07-01: 75 + PRESCHOOL: + FULL_TIME: + 2023-07-01: 120 + 2024-10-01: 125 + PART_TIME: + 2023-07-01: 75 + SCHOOL_AGE: + FULL_TIME: + 2023-07-01: 110 + 2024-10-01: 120 + PART_TIME: + 2023-07-01: 74 diff --git a/policyengine_us/parameters/gov/states/ms/dhs/ccpp/rates/family_home.yaml b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/rates/family_home.yaml new file mode 100644 index 00000000000..46c02fc7bd9 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/rates/family_home.yaml @@ -0,0 +1,77 @@ +description: Mississippi provides these maximum weekly payment rates for registered family child care homes under the Child Care Payment Program. +# Two rate eras, keyed by the facility's location (metro / non-metro); we use the +# household's county as a proxy for facility location. +# - 2023-07-01 = July-2023 "Current CCPP Rates" (2024 Market Rate Survey Table 2, p.10). +# - 2024-10-01 = FY2025-2027 State Plan adopted full-time base rates. The State Plan +# reports rates by "most populous region" (encoded in the METRO slot) and "lowest +# region" (NON_METRO slot); the most-populous figure equals the statewide 75th +# percentile. +# The FY2025-2027 State Plan publishes FULL-TIME base rates only; the adopted part-time +# rates for that era are not publicly available (only the family copay fee scale is +# published), so the part-time leaves below retain their 2023-07 values — a documented +# limitation we don't track at the moment. Special-needs children are paid the flat +# all-ages special-needs rate (see special_needs_home). +metadata: + period: week + unit: currency-USD + label: Mississippi CCPP family home weekly rates + breakdown: + - ms_ccpp_facility_location + - ms_ccpp_age_group + - ms_ccpp_time_category + reference: + - title: 2024 Mississippi Child Care Market Rate Survey, Table 2 (Current CCPP Rates, Registered Family Homes) + href: https://www.mdhs.ms.gov/wp-content/uploads/2024/06/Mississippi-Child-Care-Market-Rate-Survey-2024.pdf#page=10 + - title: Mississippi FFY 2025-2027 CCDF State Plan, §4.3.2 (adopted full-time base rates, most-populous region pp.59-60); effective date §4.3.1(b) p.57 + href: https://www.mdhs.ms.gov/wp-content/uploads/2025/01/ACF-118-CCDF-FFY-2025-2027-For-Mississippi.pdf#page=59 + +METRO: + INFANT: + FULL_TIME: + 2023-07-01: 115 + 2024-10-01: 140 + PART_TIME: + 2023-07-01: 68 + TODDLER: + FULL_TIME: + 2023-07-01: 120 + 2024-10-01: 131 + PART_TIME: + 2023-07-01: 75 + PRESCHOOL: + FULL_TIME: + 2023-07-01: 120 + 2024-10-01: 125 + PART_TIME: + 2023-07-01: 60 + SCHOOL_AGE: + FULL_TIME: + 2023-07-01: 95 + 2024-10-01: 115 + PART_TIME: + 2023-07-01: 58 +NON_METRO: + INFANT: + FULL_TIME: + 2023-07-01: 94 + 2024-10-01: 128 + PART_TIME: + 2023-07-01: 60 + TODDLER: + FULL_TIME: + 2023-07-01: 98 + 2024-10-01: 125 + PART_TIME: + 2023-07-01: 61 + PRESCHOOL: + FULL_TIME: + 2023-07-01: 106 + 2024-10-01: 120 + PART_TIME: + 2023-07-01: 60 + SCHOOL_AGE: + FULL_TIME: + 2023-07-01: 79 + 2024-10-01: 95 + PART_TIME: + 2023-07-01: 53 diff --git a/policyengine_us/parameters/gov/states/ms/dhs/ccpp/rates/special_needs_center.yaml b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/rates/special_needs_center.yaml new file mode 100644 index 00000000000..3caf978f88a --- /dev/null +++ b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/rates/special_needs_center.yaml @@ -0,0 +1,28 @@ +description: Mississippi provides these maximum weekly payment rates for special-needs children in licensed child care centers under the Child Care Payment Program. +# Flat all-ages special-needs rate effective July 2023 (2024 Market Rate Survey +# Table 1, p.9). This rate is the same for metro and non-metro facilities, but is +# keyed by location for structural consistency with the standard center rates. +# These retain the 2023-07 values for the 2024-10 (FY2025-2027) era because the +# FY2025-2027 adopted special-needs dollar rates are not publicly available — a +# limitation we don't track at the moment. +metadata: + period: week + unit: currency-USD + label: Mississippi CCPP special-needs center weekly rates + breakdown: + - ms_ccpp_facility_location + - ms_ccpp_time_category + reference: + - title: 2024 Mississippi Child Care Market Rate Survey, Table 1 (Current CCPP Rates, Licensed Centers, Special Needs) + href: https://www.mdhs.ms.gov/wp-content/uploads/2024/06/Mississippi-Child-Care-Market-Rate-Survey-2024.pdf#page=9 + +METRO: + FULL_TIME: + 2023-07-01: 145 + PART_TIME: + 2023-07-01: 87 +NON_METRO: + FULL_TIME: + 2023-07-01: 145 + PART_TIME: + 2023-07-01: 87 diff --git a/policyengine_us/parameters/gov/states/ms/dhs/ccpp/rates/special_needs_home.yaml b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/rates/special_needs_home.yaml new file mode 100644 index 00000000000..95cbd34b251 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/rates/special_needs_home.yaml @@ -0,0 +1,29 @@ +description: Mississippi provides these maximum weekly payment rates for special-needs children in registered family child care homes under the Child Care Payment Program. +# Flat all-ages special-needs rate effective July 2023 (2024 Market Rate Survey +# Table 2, p.10). This rate is the same for metro and non-metro facilities, but is +# keyed by location for structural consistency with the standard family-home rates. +# In-home care (special-needs only, child's own home) is paid this home-based rate. +# These retain the 2023-07 values for the 2024-10 (FY2025-2027) era because the +# FY2025-2027 adopted special-needs dollar rates are not publicly available — a +# limitation we don't track at the moment. +metadata: + period: week + unit: currency-USD + label: Mississippi CCPP special-needs family home weekly rates + breakdown: + - ms_ccpp_facility_location + - ms_ccpp_time_category + reference: + - title: 2024 Mississippi Child Care Market Rate Survey, Table 2 (Current CCPP Rates, Registered Family Homes, Special Needs) + href: https://www.mdhs.ms.gov/wp-content/uploads/2024/06/Mississippi-Child-Care-Market-Rate-Survey-2024.pdf#page=10 + +METRO: + FULL_TIME: + 2023-07-01: 125 + PART_TIME: + 2023-07-01: 63 +NON_METRO: + FULL_TIME: + 2023-07-01: 125 + PART_TIME: + 2023-07-01: 63 diff --git a/policyengine_us/parameters/gov/states/ms/dhs/ccpp/time_category/hours.yaml b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/time_category/hours.yaml new file mode 100644 index 00000000000..679f44683d0 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ms/dhs/ccpp/time_category/hours.yaml @@ -0,0 +1,25 @@ +description: Mississippi determines a child's care time category from daily care hours under the Child Care Payment Program. +# Maps childcare hours per day to the time-category index used by the rate tables: +# 0 = PART_TIME (fewer than 6 hours of a 24-hour day) +# 1 = FULL_TIME (6 or more hours of a 24-hour day) +# Threshold from the CCPP Policy Manual definitions of Full-Time (#44) and +# Part-Time (#65) care. +metadata: + type: single_amount + threshold_unit: hour + amount_unit: /1 + period: year + label: Mississippi CCPP time category by daily hours + reference: + - title: Mississippi CCPP Policy Manual, Definitions (Full-Time #44 p.12, Part-Time #65 p.14) + href: https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=12 + +brackets: + - threshold: + 2021-11-01: 0 + amount: + 2021-11-01: 0 + - threshold: + 2021-11-01: 6 + amount: + 2021-11-01: 1 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 83ef1f1f1a0..d7394fe7457 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -460,7 +460,7 @@ programs: category: Benefits agency: HHS status: partial - coverage: AK, AR, AL, CA, CO, CT, DE, DC, FL, HI, IA, ID, IL, IN, KS, KY, MA, MD, ME, NC, NH, NJ, PA, RI, SC, TX, VA, VT, WA, WV + coverage: AK, AR, AL, CA, CO, CT, DE, DC, FL, HI, IA, ID, IL, IN, KS, KY, MA, MD, ME, MS, NC, NH, NJ, PA, RI, SC, TX, VA, VT, WA, WV state_implementations: - state: AK status: complete @@ -554,6 +554,12 @@ programs: name: Maine CCAP full_name: Maine Child Care Affordability Program variable: me_ccap + - state: MS + status: complete + name: CCPP + full_name: Mississippi Child Care Payment Program + variable: ms_ccpp + parameter_prefix: gov.states.ms.dhs.ccpp - state: IA status: complete name: Iowa CCA diff --git a/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/copay/ms_ccpp_copay.yaml b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/copay/ms_ccpp_copay.yaml new file mode 100644 index 00000000000..6ac834ee3ad --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/copay/ms_ccpp_copay.yaml @@ -0,0 +1,437 @@ +# ms_ccpp_copay is SPMUnit, MONTH. +# Family copay = monthly countable income (floored at 0) x rate, where the rate +# comes from the family-size band selected by position relative to 50% SMI. +# $0 at/below the federal poverty line, for TANF, and for homeless-no-income. +# $10/month cap for minimum-fee categories (protective services, SSI-disabled +# parent, special-needs child) when income is above the poverty line. +# +# Monthly federal SMI / FPG (MS, 2024), and copay rates: +# Size 2: 50% SMI = 2,133.50; FPG = 1,703.33; very-low 5.5% / low 6.5% +# Size 3: 50% SMI = 2,635.50; FPG = 2,151.67; very-low 5.0% / low 6.0% +# Size 4: 50% SMI = 3,137.50; FPG = 2,600.00; very-low 4.5% / low 5.5% + +- name: Case 1, very-low-income band above FPL, family of 3. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 28_800 # YEAR -> 2,400/mo + person2: + age: 30 + person3: + age: 4 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: MS + output: + # Monthly income 2,400: > FPG 2,151.67 (not exempt), <= 50% SMI 2,635.50 + # -> very-low band, family size 3 rate 5.0% + # Copay = 2,400 * 0.05 = 120 + ms_ccpp_copay: 120 + +- name: Case 2, low-income band (50-85 percent SMI), family of 4. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 48_000 # YEAR -> 4,000/mo + person2: + age: 33 + person3: + age: 4 + person4: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: MS + output: + # Monthly income 4,000: > 50% SMI 3,137.50 -> low band, size 4 rate 5.5% + # Copay = 4,000 * 0.055 = 220 + ms_ccpp_copay: 220 + +- name: Case 3, income at or below the federal poverty line pays zero copay. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 18_000 # YEAR -> 1,500/mo + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + # Monthly income 1,500 <= FPG 1,703.33 (family of 2) -> $0 copay + ms_ccpp_copay: 0 + +- name: Case 4, special-needs child caps the copay at $10. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 28_800 # YEAR -> 2,400/mo + person2: + age: 30 + person3: + age: 4 + is_disabled: true # special-needs child -> minimum-fee category + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: MS + output: + # Uncapped very-low band copay = 2,400 * 0.05 = 120; above FPL 2,151.67 + # -> minimum-fee category caps at $10 + ms_ccpp_copay: 10 + +- name: Case 5, protective-services child caps the copay at $10. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 24_000 # YEAR -> 2,000/mo + person2: + age: 4 + receives_or_needs_protective_services: true + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + # Uncapped very-low band copay = 2,000 * 0.055 = 110; above FPL 1,703.33 + # -> minimum-fee category caps at $10 + ms_ccpp_copay: 10 + +- name: Case 6, parent with a disability receiving SSI caps the copay at $10. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 24_000 # YEAR -> 2,000/mo + is_ssi_disabled: true + ssi: 300 # MONTH, receiving SSI (counts as income) + person2: + age: 4 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + # Income 2,300/mo (2,000 wages + 300 SSI) > 50% SMI 2,133.50 -> low band; + # above FPL 1,703.33; disabled parent receiving SSI -> minimum-fee cap $10 + ms_ccpp_copay: 10 + +- name: Case 7, TANF family pays zero copay even above FPL. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 24_000 # YEAR -> 2,000/mo + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: true + households: + household: + members: [person1, person2] + state_code: MS + output: + # Income 2,000 > FPG 1,703.33, but TANF enrollment waives the copay + ms_ccpp_copay: 0 + +- name: Case 8, negative countable income floors at zero copay. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + self_employment_income: -60_000 # YEAR -> -5,000/mo + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + # Income floored at 0; 0 <= FPG -> $0 copay (no negative-income inflation) + ms_ccpp_copay: 0 + +- name: Case 9, band boundary just below 50 percent SMI uses very-low rate, family of 4. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 37_649.88 # YEAR -> 3,137.49/mo, 0.01 below 50% SMI + person2: + age: 33 + person3: + age: 4 + person4: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: MS + output: + # Monthly 3,137.49 <= 50% SMI 3,137.50 -> very-low band, rate 4.5% + # Copay = 3,137.49 * 0.045 = 141.19 + ms_ccpp_copay: 141.19 + +- name: Case 10, band boundary just above 50 percent SMI uses low rate, family of 4. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 37_650.12 # YEAR -> 3,137.51/mo, 0.01 above 50% SMI + person2: + age: 33 + person3: + age: 4 + person4: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: MS + output: + # Monthly 3,137.51 > 50% SMI 3,137.50 -> low band, rate 5.5% + # Copay = 3,137.51 * 0.055 = 172.56 + ms_ccpp_copay: 172.56 + +# === Edge cases (see Cases 1-10 above) === +- name: Case 11, zero income pays zero copay. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + # No income; 0 <= FPG (family of 2, 1,703.33) -> $0 copay + ms_ccpp_copay: 0 + +# Family-size cap at 6: families of 7-8 use the published "6 or more" copay row. +# For size 7, FPG/mo = 3,945.00 and 50% SMI/mo = 4,235.63. +- name: Case 12, family of 7 in very-low band uses the size-6 capped rate. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 49_200 # YEAR -> 4,100/mo + person2: + age: 38 + person3: + age: 4 + person4: + age: 6 + person5: + age: 8 + person6: + age: 10 + person7: + age: 12 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6, person7] + households: + household: + members: [person1, person2, person3, person4, person5, person6, person7] + state_code: MS + output: + # Income 4,100/mo: > FPG 3,945.00 (not exempt), <= 50% SMI 4,235.63 + # -> very-low band; size 7 capped to size-6 row rate 3.5% + # Copay = 4,100 * 0.035 = 143.50 + ms_ccpp_copay: 143.50 + +- name: Case 13, family of 7 in low band uses the size-6 capped rate. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 60_000 # YEAR -> 5,000/mo + person2: + age: 38 + person3: + age: 4 + person4: + age: 6 + person5: + age: 8 + person6: + age: 10 + person7: + age: 12 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6, person7] + households: + household: + members: [person1, person2, person3, person4, person5, person6, person7] + state_code: MS + output: + # Income 5,000/mo: > 50% SMI 4,235.63 -> low band; size 7 capped to + # the size-6 row rate 4.5% + # Copay = 5,000 * 0.045 = 225.00 + ms_ccpp_copay: 225.00 + +- name: Case 14, homeless family with no countable income pays zero copay. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + is_homeless: true + output: + # is_homeless and zero countable income -> homeless_no_income branch -> $0 + ms_ccpp_copay: 0 + +- name: Case 15, special-needs child at or below the poverty line pays zero copay. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 18_000 # YEAR -> 1,500/mo + person2: + age: 4 + is_disabled: true # special-needs child -> minimum-fee category + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + # Monthly income 1,500 <= FPG 1,703.33 (family of 2): minimum-fee category + # (special-needs child) would cap at $10, but the $0 poverty-line exemption + # takes precedence -> $0 copay + ms_ccpp_copay: 0 + +- name: Case 16, a disabled parent not receiving SSI is not a minimum-fee category. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 24_000 # YEAR -> 2,000/mo + is_disabled: true # disabled but not receiving SSI, and an adult (not a child) + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + # Above FPL 1,703.33 and <= 50% SMI 2,133.50 -> very-low band 5.5% = 110. + # The parent's disability does not cap: not receiving SSI, and a disabled + # adult is not a special-needs child (under 19). + ms_ccpp_copay: 110 + +- name: Case 17, a disabled 18-year-old head is not a special-needs child. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 18 + employment_income: 24_000 # YEAR -> 2,000/mo + is_disabled: true + is_tax_unit_head: true + person2: + age: 4 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + # The disabled head is under 19 but is not a dependent child, so the + # special-needs child minimum-fee cap does not apply. + ms_ccpp_copay: 110 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/copay/ms_ccpp_copay_waived.yaml b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/copay/ms_ccpp_copay_waived.yaml new file mode 100644 index 00000000000..af14fafc716 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/copay/ms_ccpp_copay_waived.yaml @@ -0,0 +1,57 @@ +- name: Case 1, family at or below the poverty line has waived copay. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income: 18_000 # YEAR -> 1,500/mo + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + ms_ccpp_copay_waived: true + +- name: Case 2, TANF family has waived copay. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income: 60_000 + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: true + households: + household: + members: [person1, person2] + state_code: MS + output: + ms_ccpp_copay_waived: true + +- name: Case 3, family above the poverty line without waiver category does not have waived copay. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income: 24_000 # YEAR -> 2,000/mo + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + ms_ccpp_copay_waived: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/copay/ms_ccpp_income_based_copay.yaml b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/copay/ms_ccpp_income_based_copay.yaml new file mode 100644 index 00000000000..3557ae6cf47 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/copay/ms_ccpp_income_based_copay.yaml @@ -0,0 +1,61 @@ +- name: Case 1, family of two in the very-low-income band. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 24_000 # YEAR -> 2,000/mo + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + # Family of 2, income <= 50% SMI, rate = 5.5%. + ms_ccpp_income_based_copay: 110 + +- name: Case 2, family of two in the low-income band. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 27_600 # YEAR -> 2,300/mo + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + # Family of 2, income > 50% SMI, rate = 6.5%. + ms_ccpp_income_based_copay: 149.5 + +- name: Case 3, negative countable income is floored at zero. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + self_employment_income: -12_000 # YEAR -> -1,000/mo, floored + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + ms_ccpp_income_based_copay: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/copay/ms_ccpp_minimum_fee_category.yaml b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/copay/ms_ccpp_minimum_fee_category.yaml new file mode 100644 index 00000000000..9b2f1b3eb64 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/copay/ms_ccpp_minimum_fee_category.yaml @@ -0,0 +1,104 @@ +- name: Case 1, protective-services child is a minimum-fee category. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 4 + receives_or_needs_protective_services: true + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + ms_ccpp_minimum_fee_category: true + +- name: Case 2, SSI-disabled parent receiving SSI is a minimum-fee category. + period: 2024-01 + input: + people: + person1: + age: 30 + is_tax_unit_head: true + is_ssi_disabled: true + ssi: 300 + person2: + age: 4 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + ms_ccpp_minimum_fee_category: true + +- name: Case 3, disabled parent not receiving SSI is not a minimum-fee category. + period: 2024-01 + input: + people: + person1: + age: 30 + is_tax_unit_head: true + is_disabled: true + person2: + age: 4 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + ms_ccpp_minimum_fee_category: false + +- name: Case 4, disabled dependent child under nineteen is a minimum-fee category. + period: 2024-01 + input: + people: + person1: + age: 30 + is_tax_unit_head: true + person2: + age: 18 + is_disabled: true + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + ms_ccpp_minimum_fee_category: true + +- name: Case 5, disabled 18-year-old head is not a minimum-fee category. + period: 2024-01 + input: + people: + person1: + age: 18 + is_disabled: true + is_tax_unit_head: true + person2: + age: 4 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + ms_ccpp_minimum_fee_category: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_activity_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_activity_eligible.yaml new file mode 100644 index 00000000000..20f91d2f64b --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_activity_eligible.yaml @@ -0,0 +1,196 @@ +# ms_ccpp_activity_eligible is SPMUnit, MONTH. +# Each parent/caretaker (tax unit head/spouse) must work >= 25 hr/wk OR be a +# full-time student OR be an SSI-disabled parent (activity waived). +# Uses weekly_hours_worked_before_lsr (default 40), NOT weekly_hours_worked. + +- name: Case 1, single parent working 40 hours per week. + period: 2024-01 + input: + people: + person1: + age: 30 + weekly_hours_worked_before_lsr: 40 + person2: + age: 4 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + ms_ccpp_activity_eligible: true + +- name: Case 2, single parent working exactly 25 hours per week (lower boundary). + period: 2024-01 + input: + people: + person1: + age: 30 + weekly_hours_worked_before_lsr: 25 + person2: + age: 4 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + ms_ccpp_activity_eligible: true + +- name: Case 3, single parent working 24 hours per week and not a student. + period: 2024-01 + input: + people: + person1: + age: 30 + weekly_hours_worked_before_lsr: 24 + is_full_time_student: false + person2: + age: 4 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + ms_ccpp_activity_eligible: false + +- name: Case 4, single parent full-time student working under 25 hours. + period: 2024-01 + input: + people: + person1: + age: 22 + weekly_hours_worked_before_lsr: 10 + is_full_time_student: true + person2: + age: 4 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + ms_ccpp_activity_eligible: true + +- name: Case 5, SSI-disabled parent has activity requirement waived. + period: 2024-01 + input: + people: + person1: + age: 40 + weekly_hours_worked_before_lsr: 0 + is_full_time_student: false + is_ssi_disabled: true + person2: + age: 4 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + ms_ccpp_activity_eligible: true + +- name: Case 6, two-parent household one parent working under 25 hours. + period: 2024-01 + input: + people: + person1: + age: 35 + weekly_hours_worked_before_lsr: 40 + person2: + age: 33 + weekly_hours_worked_before_lsr: 10 + is_full_time_student: false + is_ssi_disabled: false + 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: MS + output: + # Every head/spouse must individually meet activity; person2 fails -> not eligible + ms_ccpp_activity_eligible: false + +- name: Case 7, two-parent household both meeting activity. + period: 2024-01 + input: + people: + person1: + age: 35 + weekly_hours_worked_before_lsr: 40 + person2: + age: 33 + weekly_hours_worked_before_lsr: 30 + 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: MS + output: + ms_ccpp_activity_eligible: true + +- name: Case 8, assistance unit of only dependents has no head or spouse. + period: 2024-01 + input: + people: + person1: + age: 16 + is_tax_unit_dependent: true + person2: + age: 10 + is_tax_unit_dependent: true + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + # No head/spouse in the unit -> has_head_or_spouse is false, so the unit + # does not vacuously pass the activity requirement. + ms_ccpp_activity_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_categorically_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_categorically_eligible.yaml new file mode 100644 index 00000000000..bd6cc96aa27 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_categorically_eligible.yaml @@ -0,0 +1,81 @@ +# ms_ccpp_categorically_eligible is SPMUnit, MONTH. +# Modeled categorical pathways that bypass the income test: TANF enrollment, +# homelessness, and protective services. TCC, Healthy Families Mississippi, and +# teen parents are not tracked at the moment. + +- name: Case 1, TANF-enrolled family is categorically eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: true + households: + household: + members: [person1, person2] + state_code: MS + output: + ms_ccpp_categorically_eligible: true + +- name: Case 2, homeless family is categorically eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + is_homeless: true + output: + ms_ccpp_categorically_eligible: true + +- name: Case 3, protective-services child is categorically eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 4 + receives_or_needs_protective_services: true + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + ms_ccpp_categorically_eligible: true + +- name: Case 4, no categorical pathway. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: false + households: + household: + members: [person1, person2] + state_code: MS + is_homeless: false + output: + ms_ccpp_categorically_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_eligible.yaml new file mode 100644 index 00000000000..7e682b04a7d --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_eligible.yaml @@ -0,0 +1,168 @@ +# ms_ccpp_eligible is SPMUnit, MONTH. +# Standard path: eligible child AND assets AND income AND activity. +# Categorical path: eligible child AND assets AND (TANF | homeless | protective), +# which bypasses the income and activity tests. + +- name: Case 1, working low-income family with eligible child is eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income: 24_000 + weekly_hours_worked_before_lsr: 40 + person2: + age: 4 + is_tax_unit_dependent: true + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + ms_ccpp_income_eligible: true + ms_ccpp_activity_eligible: true + ms_ccpp_eligible: true + +- name: Case 2, income over 85 percent SMI and not working is ineligible. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income: 70_000 + weekly_hours_worked_before_lsr: 10 + is_full_time_student: false + person2: + age: 4 + is_tax_unit_dependent: true + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + # Family of 2: 70,000 > 43,523.40 (85% SMI) and activity not met + ms_ccpp_income_eligible: false + ms_ccpp_activity_eligible: false + ms_ccpp_eligible: false + +- name: Case 3, TANF family over income limit is eligible via categorical bypass. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income: 70_000 # above 85% SMI for family of 2 + weekly_hours_worked_before_lsr: 0 # activity not met + is_full_time_student: false + person2: + age: 4 + is_tax_unit_dependent: true + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: true + households: + household: + members: [person1, person2] + state_code: MS + output: + # Income and activity both fail, but TANF categorical bypasses them + ms_ccpp_income_eligible: false + ms_ccpp_activity_eligible: false + ms_ccpp_categorically_eligible: true + ms_ccpp_eligible: true + +- name: Case 4, no eligible child means not eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income: 24_000 + weekly_hours_worked_before_lsr: 40 + person2: + age: 15 # over 13, not disabled -> not an eligible child + is_tax_unit_dependent: true + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + ms_ccpp_eligible: false + +- name: Case 5, non-Mississippi household is not eligible (defined_for gate). + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income: 24_000 + weekly_hours_worked_before_lsr: 40 + person2: + age: 4 + is_tax_unit_dependent: true + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 6_000 + households: + household: + members: [person1, person2] + state_code: AL # not Mississippi + output: + # defined_for = StateCode.MS zeroes the gate and the benefit for non-MS + ms_ccpp_eligible: false + ms_ccpp: 0 + +- name: Case 6, otherwise-eligible family over the asset limit is not eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income: 24_000 + weekly_hours_worked_before_lsr: 40 + person2: + age: 4 + is_tax_unit_dependent: true + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_100_000 # above the $1,000,000 CCDF asset limit + households: + household: + members: [person1, person2] + state_code: MS + output: + # Income and activity both pass, but the asset gate fails the AND, so + # neither the standard nor the categorical path is eligible. + ms_ccpp_income_eligible: true + ms_ccpp_activity_eligible: true + ms_ccpp_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_eligible_child.yaml b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_eligible_child.yaml new file mode 100644 index 00000000000..9e9c12468aa --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_eligible_child.yaml @@ -0,0 +1,127 @@ +# ms_ccpp_eligible_child is Person, MONTH. +# A child is eligible when under age 13 (under 19 if special-needs/disabled), +# immigration-eligible (citizen or qualified non-citizen), and a tax-unit dependent. + +- name: Case 1, age 12 child is eligible. + period: 2024-01 + input: + people: + person1: + age: 35 + person2: + age: 12 + is_tax_unit_dependent: true + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + # age 12 < 13 -> eligible + ms_ccpp_eligible_child: [false, true] + +- name: Case 2, age 13 child is not eligible. + period: 2024-01 + input: + people: + person1: + age: 35 + person2: + age: 13 + is_tax_unit_dependent: true + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + # age 13 not < 13 -> ineligible + ms_ccpp_eligible_child: [false, false] + +- name: Case 3, disabled child age 18 is eligible. + period: 2024-01 + input: + people: + person1: + age: 45 + person2: + age: 18 + is_disabled: true + is_tax_unit_dependent: true + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + # disabled, age 18 < 19 -> eligible + ms_ccpp_eligible_child: [false, true] + +- name: Case 4, disabled child age 19 is not eligible. + period: 2024-01 + input: + people: + person1: + age: 45 + person2: + age: 19 + is_disabled: true + is_tax_unit_dependent: true + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + # disabled, age 19 not < 19 -> ineligible + ms_ccpp_eligible_child: [false, false] + +- name: Case 5, undocumented child is not immigration eligible. + period: 2024-01 + input: + people: + person1: + age: 35 + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: UNDOCUMENTED + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + # undocumented child is not a qualified non-citizen -> ineligible + ms_ccpp_eligible_child: [false, false] + +- name: Case 6, refugee child is immigration eligible. + period: 2024-01 + input: + people: + person1: + age: 35 + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: REFUGEE + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + # refugee is a qualified non-citizen -> eligible + ms_ccpp_eligible_child: [false, true] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_income_eligible.yaml new file mode 100644 index 00000000000..9ca7186cd7e --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_income_eligible.yaml @@ -0,0 +1,112 @@ +# ms_ccpp_income_eligible is SPMUnit, MONTH. +# Eligible when monthly countable income <= 0.85 * monthly hhs_smi. +# Federal hhs_smi (MS, 2024), annual / 85% annual: +# Family of 2: 51,204 / 43,523.40 +# Family of 3: 63,252 / 53,764.20 +# Family of 4: 75,300 / 64,005.00 + +- name: Case 1, family of 2 well below 85 percent SMI. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income: 24_000 + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + # 24,000 < 43,523.40 -> eligible + ms_ccpp_income_eligible: true + +- name: Case 2, family of 2 just below 85 percent SMI boundary. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income: 43_523.39 # 0.01 below 85% SMI to avoid float round-trip flip + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + ms_ccpp_income_eligible: true + +- name: Case 3, family of 2 just above 85 percent SMI boundary. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income: 43_523.41 # 0.01 above 85% SMI + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + ms_ccpp_income_eligible: false + +- name: Case 4, family of 4 below 85 percent SMI. + period: 2024-01 + input: + people: + person1: + age: 35 + employment_income: 60_000 + person2: + age: 33 + person3: + age: 4 + person4: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: MS + output: + # 60,000 < 64,005 (85% SMI, family of 4) -> eligible + ms_ccpp_income_eligible: true + +- name: Case 5, family of 4 above 85 percent SMI. + period: 2024-01 + input: + people: + person1: + age: 35 + employment_income: 70_000 + person2: + age: 33 + person3: + age: 4 + person4: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: MS + output: + # 70,000 > 64,005 -> ineligible + ms_ccpp_income_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/integration.yaml new file mode 100644 index 00000000000..2bc63d42209 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/integration.yaml @@ -0,0 +1,451 @@ +# MS CCPP integration tests — full pipeline at YEAR period. +# ms_ccpp is MONTH; the YEAR aggregator ms_child_care_subsidies sums 12 months +# and feeds the federal child_care_subsidies (YEAR). +# Weekly rate -> monthly: x 52/12. Monthly benefit x 12 = annual. +# Monthly federal SMI / FPG (MS, 2024): +# Size 2: 85% SMI = 3,626.95; 50% SMI = 2,133.50; FPG = 1,703.33 +# Size 3: 85% SMI = 4,480.35; 50% SMI = 2,635.50; FPG = 2,151.67 +# Size 4: 85% SMI = 5,333.75; 50% SMI = 3,137.50; FPG = 2,600.00 + +- name: Case 1, single parent one preschooler metro center full time, full pipeline. + # Era-1 month (2024-01): rates use the 2023-07 schedule, before the 2024-10 increase. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 24_000 # 2,000/mo + weekly_hours_worked_before_lsr: 40 + person2: + age: 4 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 12_000 # 1,000/mo + households: + household: + members: [person1, person2] + state_code: MS + county: HINDS_COUNTY_MS + output: + ms_ccpp_eligible: true + # Rate center metro FT preschool 135/wk -> 135 * 52/12 = 585/mo + # Copay: 2,000/mo, size 2, <= 50% SMI 2,133.50 -> very-low 5.5% = 110 + # Monthly benefit = min(1,000, 585) - 110 = 475 + ms_ccpp: 475 + +- name: Case 2, two-parent family two children family home non-metro low band. + # Era-1 month (2024-01): rates use the 2023-07 schedule, before the 2024-10 increase. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 48_000 # 4,000/mo + weekly_hours_worked_before_lsr: 40 + person2: + age: 33 + weekly_hours_worked_before_lsr: 40 + person3: + age: 1 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: FAMILY_HOME + person4: + age: 8 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: FAMILY_HOME + tax_units: + tax_unit: + members: [person1, person2, person3, person4] + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + spm_unit_pre_subsidy_childcare_expenses: 18_000 # 1,500/mo + households: + household: + members: [person1, person2, person3, person4] + state_code: MS + county: BOLIVAR_COUNTY_MS + output: + ms_ccpp_income_eligible: true + ms_ccpp_eligible: true + # Rates home non-metro FT: toddler 98 + school-age 79 = 177/wk -> 177 * 52/12 = 767/mo + # Copay: 4,000/mo size 4 > 50% SMI 3,137.50 -> low 5.5% = 220 + # Monthly benefit = min(1,500, 767) - 220 = 547 + ms_ccpp: 547 + +- name: Case 3, homeless family above income limit eligible via categorical bypass. + # Era-1 month (2024-01): rates use the 2023-07 schedule, before the 2024-10 increase. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 48_000 # 4,000/mo, above 85% SMI for family of 2 + weekly_hours_worked_before_lsr: 0 # activity not met + is_full_time_student: false + person2: + age: 4 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 12_000 # 1,000/mo + households: + household: + members: [person1, person2] + state_code: MS + county: HINDS_COUNTY_MS + is_homeless: true + output: + # Income and activity both fail; homeless categorical bypass -> eligible + ms_ccpp_income_eligible: false + ms_ccpp_categorically_eligible: true + ms_ccpp_eligible: true + # Has income (4,000) so not homeless-no-income -> scale copay applies + # Copay: 4,000/mo size 2 > 50% SMI 2,133.50 -> low 6.5% = 260 + # Rate center metro FT preschool 135/wk -> 135 * 52/12 = 585/mo + # Monthly benefit = min(1,000, 585) - 260 = 325 + ms_ccpp: 325 + +- name: Case 4, special-needs child draws special-needs rate with $10 copay cap. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 24_000 # 2,000/mo + weekly_hours_worked_before_lsr: 40 + person2: + age: 8 + is_disabled: true + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 12_000 # 1,000/mo + households: + household: + members: [person1, person2] + state_code: MS + county: HINDS_COUNTY_MS + output: + ms_ccpp_eligible: true + # Disabled child age 8 < 19 -> eligible; draws special-needs center FT = 145/wk + # 145 * 52/12 = 628.33/mo + # Special-needs child -> minimum-fee cap; 2,000 > FPG 1,703.33 -> copay $10 + # Monthly benefit = min(1,000, 628.33) - 10 = 618.33; annual = 7,420 + ms_ccpp: 7_420 + child_care_subsidies: 7_420 + +- name: Case 5, single parent two children part time metro center very-low band. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 28_800 # 2,400/mo + weekly_hours_worked_before_lsr: 40 + person2: + age: 0 + is_tax_unit_dependent: true + childcare_hours_per_day: 4 # part time + childcare_hours_per_week: 20 + ms_ccpp_provider_type: CENTER + person3: + age: 3 + is_tax_unit_dependent: true + childcare_hours_per_day: 4 # part time + childcare_hours_per_week: 20 + ms_ccpp_provider_type: CENTER + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_pre_subsidy_childcare_expenses: 18_000 # 1,500/mo + households: + household: + members: [person1, person2, person3] + state_code: MS + county: HINDS_COUNTY_MS + output: + ms_ccpp_eligible: true + # Rates PT center metro: infant 90 + preschool 75 = 165/wk -> 715/mo + # Copay: 2,400/mo size 3 <= 50% SMI 2,635.50 -> very-low 5.0% = 120 + # Monthly benefit = min(1,500, 715) - 120 = 595; annual = 7,140 + ms_ccpp: 7_140 + child_care_subsidies: 7_140 + +- name: Case 6, family above 85 percent SMI without categorical pathway is ineligible. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 48_000 # 4,000/mo > 85% SMI for family of 2 + weekly_hours_worked_before_lsr: 10 + is_full_time_student: false + person2: + age: 4 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + 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: MS + county: HINDS_COUNTY_MS + output: + ms_ccpp_income_eligible: false + ms_ccpp_eligible: false + ms_ccpp: 0 + child_care_subsidies: 0 + +- name: Case 7, non-Mississippi household is excluded (defined_for gate). + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 24_000 + weekly_hours_worked_before_lsr: 40 + person2: + age: 4 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + 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: AL # not Mississippi + county: BALDWIN_COUNTY_AL + output: + # defined_for = StateCode.MS zeroes the eligibility gate and the benefit + ms_ccpp_eligible: false + ms_ccpp: 0 + ms_child_care_subsidies: 0 + +# Era-2 coverage (period 2025-01, a pure 2024-10 schedule month, before the +# unmodeled July-2025 increase). Cases 8-11 confirm the FY2025-2027 full-time +# base rates flow through and that part-time + special-needs leaves correctly +# carry forward their era-1 (2023-07) values. +- name: Case 8, era-2 metro center infant full time draws the FY2025-2027 rate. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 12_000 # 1,000/mo, at/below FPL size 2 -> copay 0 + weekly_hours_worked_before_lsr: 40 + person2: + age: 0 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 12_000 # 1,000/mo + households: + household: + members: [person1, person2] + state_code: MS + county: HINDS_COUNTY_MS + output: + ms_ccpp_eligible: true + # Era-2 metro center infant FT = 167/wk -> 167 * 52/12 = 723.67/mo + # Income 1,000/mo <= FPL (size 2) -> copay 0 + # Benefit = min(1,000, 723.67) - 0 = 723.67 + ms_ccpp: 723.67 + +- name: Case 9, era-2 non-metro center infant full time draws the lower regional rate. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 12_000 # 1,000/mo, at/below FPL size 2 -> copay 0 + weekly_hours_worked_before_lsr: 40 + person2: + age: 0 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 12_000 # 1,000/mo + households: + household: + members: [person1, person2] + state_code: MS + county: BOLIVAR_COUNTY_MS # non-metro + output: + ms_ccpp_eligible: true + # Era-2 non-metro center infant FT = 140/wk -> 140 * 52/12 = 606.67/mo + # Income 1,000/mo <= FPL (size 2) -> copay 0 + # Benefit = min(1,000, 606.67) - 0 = 606.67 + ms_ccpp: 606.67 + +- name: Case 10, era-2 family home metro infant full time draws the FY2025-2027 rate. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 12_000 # 1,000/mo, at/below FPL size 2 -> copay 0 + weekly_hours_worked_before_lsr: 40 + person2: + age: 0 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: FAMILY_HOME + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 12_000 # 1,000/mo + households: + household: + members: [person1, person2] + state_code: MS + county: HINDS_COUNTY_MS + output: + ms_ccpp_eligible: true + # Era-2 metro family home infant FT = 140/wk -> 140 * 52/12 = 606.67/mo + # Income 1,000/mo <= FPL (size 2) -> copay 0 + # Benefit = min(1,000, 606.67) - 0 = 606.67 + ms_ccpp: 606.67 + +- name: Case 11, era-2 part time and special needs leaves carry forward era-1 rates. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 12_000 # 1,000/mo, at/below FPL size 2 -> copay 0 + weekly_hours_worked_before_lsr: 40 + person2: # part-time infant: PT rate has no era-2 entry -> carries era-1 + age: 0 + is_tax_unit_dependent: true + childcare_hours_per_day: 4 # part time + childcare_hours_per_week: 20 + ms_ccpp_provider_type: CENTER + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 12_000 # 1,000/mo + households: + household: + members: [person1, person2] + state_code: MS + county: HINDS_COUNTY_MS + output: + ms_ccpp_eligible: true + # PART_TIME has no 2024-10 entry, so the 2023-07 value carries forward: + # metro center infant PT = 90/wk -> 90 * 52/12 = 390/mo + # Income 1,000/mo <= FPL (size 2) -> copay 0 + # Benefit = min(1,000, 390) - 0 = 390 + ms_ccpp: 390 + +- name: Case 12, era-2 special needs child draws the carried-forward flat rate. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 12_000 # 1,000/mo, at/below FPL size 2 -> copay 0 + weekly_hours_worked_before_lsr: 40 + person2: + age: 8 + is_disabled: true + is_tax_unit_dependent: true + childcare_hours_per_day: 8 # full time + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 12_000 # 1,000/mo + households: + household: + members: [person1, person2] + state_code: MS + county: HINDS_COUNTY_MS + output: + ms_ccpp_eligible: true + # Special-needs rate has no 2024-10 entry, so the 2023-07 flat value carries + # forward: special-needs center FT = 145/wk -> 145 * 52/12 = 628.33/mo + # Income 1,000/mo <= FPL (size 2) -> copay 0 (so the $10 min-fee cap does not bind) + # Benefit = min(1,000, 628.33) - 0 = 628.33 + ms_ccpp: 628.33 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/ms_ccpp.yaml b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/ms_ccpp.yaml new file mode 100644 index 00000000000..a3ab0854b42 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/ms_ccpp.yaml @@ -0,0 +1,225 @@ +# ms_ccpp is SPMUnit, MONTH. +# Benefit = max( min(monthly childcare expenses, sum of per-child weekly max +# rates x 52/12) - monthly family copay, 0 ). +# spm_unit_pre_subsidy_childcare_expenses is annual; read monthly it divides by 12. + +- name: Case 1, single parent one preschooler in metro center full time. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 24_000 # 2,000/mo + weekly_hours_worked_before_lsr: 40 + person2: + age: 4 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 # full time + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 12_000 # 1,000/mo + households: + household: + members: [person1, person2] + state_code: MS + county: HINDS_COUNTY_MS + output: + ms_ccpp_eligible: true + # Rate: center metro FT preschool = 135/wk -> 135 * 52/12 = 585.00/mo + # Copay: 2,000/mo, size 2, <= 50% SMI 2,133.50 -> very-low 5.5% = 110 + # Benefit = max(min(1,000, 585) - 110, 0) = 585 - 110 = 475.00 + ms_ccpp: 475 + +- name: Case 2, provider charge below the maximum rate caps the subsidy at the charge. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 24_000 # 2,000/mo + weekly_hours_worked_before_lsr: 40 + person2: + age: 4 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 3_000 # 250/mo + households: + household: + members: [person1, person2] + state_code: MS + county: HINDS_COUNTY_MS + output: + ms_ccpp_eligible: true + # Monthly rate 585 > monthly expenses 250 -> capped at 250 + # Copay = 110 (very-low band, size 2) + # Benefit = max(min(250, 585) - 110, 0) = 250 - 110 = 140.00 + ms_ccpp: 140 + +- name: Case 3, copay exceeds capped expenses so benefit floors at zero. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 48_000 # 4,000/mo + weekly_hours_worked_before_lsr: 40 + person2: + age: 33 + person3: + age: 4 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + person4: + age: 8 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + tax_units: + tax_unit: + members: [person1, person2, person3, person4] + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + spm_unit_pre_subsidy_childcare_expenses: 1_200 # 100/mo + households: + household: + members: [person1, person2, person3, person4] + state_code: MS + county: HINDS_COUNTY_MS + output: + ms_ccpp_eligible: true + # Rates: preschool 135 + school-age 130 = 265/wk -> 1,148.33/mo + # Copay: 4,000/mo, size 4, > 50% SMI 3,137.50 -> low band 5.5% = 220 + # Monthly expenses = 100 + # Benefit = max(min(100, 1,148.33) - 220, 0) = max(100 - 220, 0) = 0 + ms_ccpp: 0 + +- name: Case 4, negative countable income does not inflate the benefit. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + self_employment_income: -60_000 # -5,000/mo + weekly_hours_worked_before_lsr: 40 + person2: + age: 4 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 12_000 # 1,000/mo + households: + household: + members: [person1, person2] + state_code: MS + county: HINDS_COUNTY_MS + output: + ms_ccpp_eligible: true + # Income floored at 0 -> copay $0 (at/below FPL) + # Rate: center metro FT preschool = 135/wk -> 585/mo + # Benefit = max(min(1,000, 585) - 0, 0) = 585.00 (capped at rate, not inflated) + ms_ccpp: 585 + +# Edge case: two children in care aggregate per-child rates, with the single +# family copay subtracted once (not per child). See Cases 1-4 above. +- name: Case 5, two children aggregate distinct per-child rates with one copay. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 28_800 # 2,400/mo + weekly_hours_worked_before_lsr: 40 + person2: # infant + age: 0 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + person3: # preschool + age: 3 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_pre_subsidy_childcare_expenses: 24_000 # 2,000/mo + households: + household: + members: [person1, person2, person3] + state_code: MS + county: HINDS_COUNTY_MS + output: + ms_ccpp_eligible: true + # Per-child rates: infant 152 + preschool 135 = 287/wk -> 287 * 52/12 = 1,243.67/mo + # Copay: 2,400/mo, size 3, > FPG 2,151.67 and <= 50% SMI 2,635.50 + # -> very-low band 5.0% = 120 (single family copay, subtracted once) + # Benefit = max(min(2,000, 1,243.67) - 120, 0) = 1,243.67 - 120 = 1,123.67 + ms_ccpp: 1_123.67 + +- name: Case 6, income above 85 percent SMI is ineligible and receives no subsidy. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 60_000 # 5,000/mo + weekly_hours_worked_before_lsr: 40 + person2: + age: 4 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 12_000 # 1,000/mo + households: + household: + members: [person1, person2] + state_code: MS + county: HINDS_COUNTY_MS + output: + # Monthly income 5,000 > 85% SMI for family of 2 (4,267 * 0.85 = 3,626.95) + # -> income-ineligible, no categorical pathway -> not eligible, $0 subsidy + ms_ccpp_eligible: false + ms_ccpp: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/ms_ccpp_age_group.yaml b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/ms_ccpp_age_group.yaml new file mode 100644 index 00000000000..7b7bd2bf4d2 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/ms_ccpp_age_group.yaml @@ -0,0 +1,96 @@ +# ms_ccpp_age_group is a Person enum derived from age (years): +# INFANT age < 1 +# TODDLER 1 <= age < 3 +# PRESCHOOL 3 <= age < 5 +# SCHOOL_AGE age >= 5 + +- name: Case 1, infant under 1 year. + period: 2024-01 + input: + people: + person1: + age: 0 + households: + household: + members: [person1] + state_code: MS + output: + ms_ccpp_age_group: INFANT + +- name: Case 2, toddler at age 1 (lower boundary). + period: 2024-01 + input: + people: + person1: + age: 1 + households: + household: + members: [person1] + state_code: MS + output: + ms_ccpp_age_group: TODDLER + +- name: Case 3, toddler at age 2. + period: 2024-01 + input: + people: + person1: + age: 2 + households: + household: + members: [person1] + state_code: MS + output: + ms_ccpp_age_group: TODDLER + +- name: Case 4, preschool at age 3 (lower boundary). + period: 2024-01 + input: + people: + person1: + age: 3 + households: + household: + members: [person1] + state_code: MS + output: + ms_ccpp_age_group: PRESCHOOL + +- name: Case 5, preschool at age 4. + period: 2024-01 + input: + people: + person1: + age: 4 + households: + household: + members: [person1] + state_code: MS + output: + ms_ccpp_age_group: PRESCHOOL + +- name: Case 6, school age at age 5 (lower boundary). + period: 2024-01 + input: + people: + person1: + age: 5 + households: + household: + members: [person1] + state_code: MS + output: + ms_ccpp_age_group: SCHOOL_AGE + +- name: Case 7, school age at age 10. + period: 2024-01 + input: + people: + person1: + age: 10 + households: + household: + members: [person1] + state_code: MS + output: + ms_ccpp_age_group: SCHOOL_AGE diff --git a/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/ms_ccpp_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/ms_ccpp_countable_income.yaml new file mode 100644 index 00000000000..d9640aadaa0 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/ms_ccpp_countable_income.yaml @@ -0,0 +1,97 @@ +# ms_ccpp_countable_income is SPMUnit, MONTH. Gross income, no deductions. +# Earned income of students under 18 is excluded (Rule 5.4); the self-employment +# sum is floored at zero (a loss does not offset other income). SSI and Social +# Security both count (for parent and child); child support received and EITC are +# not countable. + +- name: Case 1, employment, Social Security, and SSI count; child support does not. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 24_000 # YEAR -> 2,000/mo + social_security: 6_000 # YEAR -> 500/mo, counts + ssi: 400 # MONTH -> 400/mo, counts (separate from social_security) + child_support_received: 12_000 # YEAR, NOT countable + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + # 2,000 + 500 + 400 = 2,900 (child support excluded) + ms_ccpp_countable_income: 2_900 + +- name: Case 2, a self-employment loss is floored and does not reduce countable income. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 24_000 # YEAR -> 2,000/mo + self_employment_income: -6_000 # YEAR -> -500/mo loss, floored at 0 + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + # 2,000 + max(-500, 0) = 2,000 (the loss does not offset wages) + ms_ccpp_countable_income: 2_000 + +- name: Case 3, child's SSI and Social Security count toward family income. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 18_000 # YEAR -> 1,500/mo + person2: + age: 6 + ssi: 300 # MONTH, child SSI counts + social_security: 2_400 # YEAR -> 200/mo, child SSA counts + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + # 1,500 + 300 + 200 = 2,000 + ms_ccpp_countable_income: 2_000 + +- name: Case 4, earned income of a student under 18 is excluded; their unearned income still counts. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 24_000 # YEAR -> 2,000/mo, adult, counts + person2: + age: 16 + employment_income: 6_000 # YEAR -> 500/mo, student under 18 -> excluded + ssi: 100 # MONTH, the student's unearned income still counts + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + output: + # adult 2,000 + excluded student wages 0 + student SSI 100 = 2,100 + ms_ccpp_countable_income: 2_100 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/ms_ccpp_facility_location.yaml b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/ms_ccpp_facility_location.yaml new file mode 100644 index 00000000000..f62949c06dc --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/ms_ccpp_facility_location.yaml @@ -0,0 +1,74 @@ +# ms_ccpp_facility_location is a Household enum derived from county_str. +# Households in one of the 17 Mississippi metropolitan counties (OMB Feb-2013 +# MSA delineation) are METRO; every other Mississippi county is NON_METRO. +# We use the household's county as a proxy for the child care facility location. + +- name: Case 1, Hinds County (Jackson MSA) is metro. + period: 2024-01 + input: + people: + person1: + age: 5 + households: + household: + members: [person1] + state_code: MS + county: HINDS_COUNTY_MS + output: + ms_ccpp_facility_location: METRO + +- name: Case 2, DeSoto County (Memphis MSA portion) is metro. + period: 2024-01 + input: + people: + person1: + age: 5 + households: + household: + members: [person1] + state_code: MS + county: DESOTO_COUNTY_MS + output: + ms_ccpp_facility_location: METRO + +- name: Case 3, Lauderdale County (Meridian, micropolitan) is non-metro. + period: 2024-01 + input: + people: + person1: + age: 5 + households: + household: + members: [person1] + state_code: MS + county: LAUDERDALE_COUNTY_MS + output: + ms_ccpp_facility_location: NON_METRO + +- name: Case 4, Bolivar County (rural) is non-metro. + period: 2024-01 + input: + people: + person1: + age: 5 + households: + household: + members: [person1] + state_code: MS + county: BOLIVAR_COUNTY_MS + output: + ms_ccpp_facility_location: NON_METRO + +- name: Case 5, George County (not in Feb-2013 Gulfport MSA) is non-metro. + period: 2024-01 + input: + people: + person1: + age: 5 + households: + household: + members: [person1] + state_code: MS + county: GEORGE_COUNTY_MS + output: + ms_ccpp_facility_location: NON_METRO diff --git a/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/ms_ccpp_maximum_weekly_rate.yaml b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/ms_ccpp_maximum_weekly_rate.yaml new file mode 100644 index 00000000000..006db66da49 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/ms_ccpp_maximum_weekly_rate.yaml @@ -0,0 +1,598 @@ +# ms_ccpp_maximum_weekly_rate is Person, MONTH. +# Per-child weekly max rate by provider type x age band x full/part time x +# metro/non-metro, with a flat all-ages special-needs rate set. Gated to 0 when +# the child is not actually in care (childcare_hours_per_week < 1) or is not an +# eligible child. childcare_hours_per_day drives full/part time (>=6 = FT); +# childcare_hours_per_week drives the in-care gate. +# Operative weekly grid (eff 2023-07-01): +# Center metro FT: Infant 152 Toddler 145 Preschool 135 School-age 130 +# Center metro PT: Infant 90 Toddler 90 Preschool 75 School-age 80 +# Center nonmetro FT: Infant 125 Toddler 120 Preschool 120 School-age 110 +# Center nonmetro PT: Infant 80 Toddler 75 Preschool 75 School-age 74 +# Home metro FT: Infant 115 Toddler 120 Preschool 120 School-age 95 +# Home metro PT: Infant 68 Toddler 75 Preschool 60 School-age 58 +# Home nonmetro FT: Infant 94 Toddler 98 Preschool 106 School-age 79 +# Home nonmetro PT: Infant 60 Toddler 61 Preschool 60 School-age 53 +# Special-needs center FT 145 / PT 87 (metro = non-metro) +# Special-needs home FT 125 / PT 63 (metro = non-metro) + +# === Center, metro (Hinds County), full time — all 4 age bands === +- name: Case 1, center metro full time, all age bands. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + person2: # infant + age: 0 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + person3: # toddler + age: 1 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + person4: # preschool + age: 3 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + person5: # school age + age: 8 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + tax_units: + tax_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: MS + county: HINDS_COUNTY_MS + output: + # Parent: not an eligible child -> 0 + # Infant 152, Toddler 145, Preschool 135, School-age 130 + ms_ccpp_maximum_weekly_rate: [0, 152, 145, 135, 130] + +# === Center, metro, part time — all 4 age bands === +- name: Case 2, center metro part time, all age bands. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + person2: + age: 0 + is_tax_unit_dependent: true + childcare_hours_per_day: 4 + childcare_hours_per_week: 20 + ms_ccpp_provider_type: CENTER + person3: + age: 1 + is_tax_unit_dependent: true + childcare_hours_per_day: 4 + childcare_hours_per_week: 20 + ms_ccpp_provider_type: CENTER + person4: + age: 3 + is_tax_unit_dependent: true + childcare_hours_per_day: 4 + childcare_hours_per_week: 20 + ms_ccpp_provider_type: CENTER + person5: + age: 8 + is_tax_unit_dependent: true + childcare_hours_per_day: 4 + childcare_hours_per_week: 20 + ms_ccpp_provider_type: CENTER + tax_units: + tax_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: MS + county: HINDS_COUNTY_MS + output: + # Infant 90, Toddler 90, Preschool 75, School-age 80 + ms_ccpp_maximum_weekly_rate: [0, 90, 90, 75, 80] + +# === Center, non-metro (Bolivar County), full time — all 4 age bands === +- name: Case 3, center non-metro full time, all age bands. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + person2: + age: 0 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + person3: + age: 1 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + person4: + age: 3 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + person5: + age: 8 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + tax_units: + tax_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: MS + county: BOLIVAR_COUNTY_MS + output: + # Infant 125, Toddler 120, Preschool 120, School-age 110 + ms_ccpp_maximum_weekly_rate: [0, 125, 120, 120, 110] + +# === Center, non-metro, part time — all 4 age bands === +- name: Case 4, center non-metro part time, all age bands. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + person2: + age: 0 + is_tax_unit_dependent: true + childcare_hours_per_day: 4 + childcare_hours_per_week: 20 + ms_ccpp_provider_type: CENTER + person3: + age: 1 + is_tax_unit_dependent: true + childcare_hours_per_day: 4 + childcare_hours_per_week: 20 + ms_ccpp_provider_type: CENTER + person4: + age: 3 + is_tax_unit_dependent: true + childcare_hours_per_day: 4 + childcare_hours_per_week: 20 + ms_ccpp_provider_type: CENTER + person5: + age: 8 + is_tax_unit_dependent: true + childcare_hours_per_day: 4 + childcare_hours_per_week: 20 + ms_ccpp_provider_type: CENTER + tax_units: + tax_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: MS + county: BOLIVAR_COUNTY_MS + output: + # Infant 80, Toddler 75, Preschool 75, School-age 74 + ms_ccpp_maximum_weekly_rate: [0, 80, 75, 75, 74] + +# === Family home, metro, full time — all 4 age bands === +- name: Case 5, family home metro full time, all age bands. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + person2: + age: 0 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: FAMILY_HOME + person3: + age: 1 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: FAMILY_HOME + person4: + age: 3 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: FAMILY_HOME + person5: + age: 8 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: FAMILY_HOME + tax_units: + tax_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: MS + county: HINDS_COUNTY_MS + output: + # Infant 115, Toddler 120, Preschool 120, School-age 95 + ms_ccpp_maximum_weekly_rate: [0, 115, 120, 120, 95] + +# === Family home, metro, part time — all 4 age bands === +- name: Case 6, family home metro part time, all age bands. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + person2: + age: 0 + is_tax_unit_dependent: true + childcare_hours_per_day: 4 + childcare_hours_per_week: 20 + ms_ccpp_provider_type: FAMILY_HOME + person3: + age: 1 + is_tax_unit_dependent: true + childcare_hours_per_day: 4 + childcare_hours_per_week: 20 + ms_ccpp_provider_type: FAMILY_HOME + person4: + age: 3 + is_tax_unit_dependent: true + childcare_hours_per_day: 4 + childcare_hours_per_week: 20 + ms_ccpp_provider_type: FAMILY_HOME + person5: + age: 8 + is_tax_unit_dependent: true + childcare_hours_per_day: 4 + childcare_hours_per_week: 20 + ms_ccpp_provider_type: FAMILY_HOME + tax_units: + tax_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: MS + county: HINDS_COUNTY_MS + output: + # Infant 68, Toddler 75, Preschool 60, School-age 58 + ms_ccpp_maximum_weekly_rate: [0, 68, 75, 60, 58] + +# === Family home, non-metro, full time — all 4 age bands === +- name: Case 7, family home non-metro full time, all age bands. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + person2: + age: 0 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: FAMILY_HOME + person3: + age: 1 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: FAMILY_HOME + person4: + age: 3 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: FAMILY_HOME + person5: + age: 8 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: FAMILY_HOME + tax_units: + tax_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: MS + county: BOLIVAR_COUNTY_MS + output: + # Infant 94, Toddler 98, Preschool 106, School-age 79 + ms_ccpp_maximum_weekly_rate: [0, 94, 98, 106, 79] + +# === Family home, non-metro, part time — all 4 age bands === +- name: Case 8, family home non-metro part time, all age bands. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + person2: + age: 0 + is_tax_unit_dependent: true + childcare_hours_per_day: 4 + childcare_hours_per_week: 20 + ms_ccpp_provider_type: FAMILY_HOME + person3: + age: 1 + is_tax_unit_dependent: true + childcare_hours_per_day: 4 + childcare_hours_per_week: 20 + ms_ccpp_provider_type: FAMILY_HOME + person4: + age: 3 + is_tax_unit_dependent: true + childcare_hours_per_day: 4 + childcare_hours_per_week: 20 + ms_ccpp_provider_type: FAMILY_HOME + person5: + age: 8 + is_tax_unit_dependent: true + childcare_hours_per_day: 4 + childcare_hours_per_week: 20 + ms_ccpp_provider_type: FAMILY_HOME + tax_units: + tax_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: MS + county: BOLIVAR_COUNTY_MS + output: + # Infant 60, Toddler 61, Preschool 60, School-age 53 + ms_ccpp_maximum_weekly_rate: [0, 60, 61, 60, 53] + +# === Special needs — center and home, full and part time === +- name: Case 9, special-needs child center full time draws flat special-needs rate. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + person2: # disabled school-age child -> special-needs center rate, not age-band rate + age: 8 + is_disabled: true + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + county: HINDS_COUNTY_MS + output: + # Special-needs center FT = 145 (flat all-ages; overrides the school-age 130) + ms_ccpp_maximum_weekly_rate: [0, 145] + +- name: Case 10, special-needs child center part time. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + person2: + age: 1 + is_disabled: true + is_tax_unit_dependent: true + childcare_hours_per_day: 4 + childcare_hours_per_week: 20 + ms_ccpp_provider_type: CENTER + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + county: BOLIVAR_COUNTY_MS + output: + # Special-needs center PT = 87 (metro = non-metro) + ms_ccpp_maximum_weekly_rate: [0, 87] + +- name: Case 11, special-needs (in-home) child draws home-based special-needs rate. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + person2: # disabled child in family-home/in-home setting + age: 3 + is_disabled: true + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: FAMILY_HOME + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + county: HINDS_COUNTY_MS + output: + # Special-needs home FT = 125 + ms_ccpp_maximum_weekly_rate: [0, 125] + +- name: Case 12, special-needs home part time. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + person2: + age: 0 + is_disabled: true + is_tax_unit_dependent: true + childcare_hours_per_day: 4 + childcare_hours_per_week: 20 + ms_ccpp_provider_type: FAMILY_HOME + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + county: BOLIVAR_COUNTY_MS + output: + # Special-needs home PT = 63 + ms_ccpp_maximum_weekly_rate: [0, 63] + +# === In-care gate === +- name: Case 13, child not in care draws no rate. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + person2: + age: 3 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 0 # not in care + ms_ccpp_provider_type: CENTER + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MS + county: HINDS_COUNTY_MS + output: + ms_ccpp_maximum_weekly_rate: [0, 0] + +# === Age-group rate-band transitions (edge cases; see Cases 1-13 above) === +# The center metro full-time rate changes at each age-band boundary. Each case +# places two children straddling one boundary so the rate band on each side is +# verified directly. Boundaries: infant<1, toddler 1-<3, preschool 3-<5, +# school-age >=5 (whole-year cuts). +- name: Case 14, infant-to-toddler rate transition (age 0 vs 1), center metro full time. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + person2: # infant (age 0) + age: 0 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + person3: # toddler (age 1, lower boundary) + age: 1 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: MS + county: HINDS_COUNTY_MS + output: + # Infant FT 152 -> Toddler FT 145 at age 1 + ms_ccpp_maximum_weekly_rate: [0, 152, 145] + +- name: Case 15, toddler-to-preschool rate transition (age 2 vs 3), center metro full time. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + person2: # toddler (age 2) + age: 2 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + person3: # preschool (age 3, lower boundary) + age: 3 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: MS + county: HINDS_COUNTY_MS + output: + # Toddler FT 145 -> Preschool FT 135 at age 3 + ms_ccpp_maximum_weekly_rate: [0, 145, 135] + +- name: Case 16, preschool-to-school-age rate transition (age 4 vs 5), center metro full time. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + person2: # preschool (age 4) + age: 4 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + person3: # school-age (age 5, lower boundary) + age: 5 + is_tax_unit_dependent: true + childcare_hours_per_day: 8 + childcare_hours_per_week: 40 + ms_ccpp_provider_type: CENTER + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: MS + county: HINDS_COUNTY_MS + output: + # Preschool FT 135 -> School-age FT 130 at age 5 + ms_ccpp_maximum_weekly_rate: [0, 135, 130] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/ms_ccpp_time_category.yaml b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/ms_ccpp_time_category.yaml new file mode 100644 index 00000000000..2ba674d35e6 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ms/dhs/ccpp/ms_ccpp_time_category.yaml @@ -0,0 +1,75 @@ +# ms_ccpp_time_category is a Person enum derived from childcare_hours_per_day: +# FULL_TIME hours/day >= 6 +# PART_TIME hours/day < 6 + +- name: Case 1, full time at 6 hours per day (lower boundary). + period: 2024-01 + input: + people: + person1: + age: 3 + childcare_hours_per_day: 6 + households: + household: + members: [person1] + state_code: MS + output: + ms_ccpp_time_category: FULL_TIME + +- name: Case 2, full time at 8 hours per day. + period: 2024-01 + input: + people: + person1: + age: 3 + childcare_hours_per_day: 8 + households: + household: + members: [person1] + state_code: MS + output: + ms_ccpp_time_category: FULL_TIME + +- name: Case 3, part time at 5 hours per day. + period: 2024-01 + input: + people: + person1: + age: 3 + childcare_hours_per_day: 5 + households: + household: + members: [person1] + state_code: MS + output: + ms_ccpp_time_category: PART_TIME + +- name: Case 4, part time at 3 hours per day. + period: 2024-01 + input: + people: + person1: + age: 3 + childcare_hours_per_day: 3 + households: + household: + members: [person1] + state_code: MS + output: + ms_ccpp_time_category: PART_TIME + +# Edge case: just below the 6-hour full-time threshold (see Case 1 at exactly 6). +- name: Case 5, part time at 5.99 hours per day (just below full-time boundary). + period: 2024-01 + input: + people: + person1: + age: 3 + childcare_hours_per_day: 5.99 + households: + household: + members: [person1] + state_code: MS + output: + # 5.99 < 6 -> part time (full time begins at exactly 6 hours, see Case 1) + ms_ccpp_time_category: PART_TIME diff --git a/policyengine_us/variables/gov/states/ms/dhs/ccpp/copay/ms_ccpp_copay.py b/policyengine_us/variables/gov/states/ms/dhs/ccpp/copay/ms_ccpp_copay.py new file mode 100644 index 00000000000..5f1656c5d96 --- /dev/null +++ b/policyengine_us/variables/gov/states/ms/dhs/ccpp/copay/ms_ccpp_copay.py @@ -0,0 +1,22 @@ +from policyengine_us.model_api import * + + +class ms_ccpp_copay(Variable): + value_type = float + entity = SPMUnit + unit = USD + label = "Mississippi CCPP monthly family co-payment" + definition_period = MONTH + defined_for = StateCode.MS + reference = "https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=41" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ms.dhs.ccpp.copay + income_based_copay = spm_unit("ms_ccpp_income_based_copay", period) + minimum_fee_copay = where( + spm_unit("ms_ccpp_minimum_fee_category", period), + min_(income_based_copay, p.minimum_fee_categories_cap), + income_based_copay, + ) + + return where(spm_unit("ms_ccpp_copay_waived", period), 0, minimum_fee_copay) diff --git a/policyengine_us/variables/gov/states/ms/dhs/ccpp/copay/ms_ccpp_copay_waived.py b/policyengine_us/variables/gov/states/ms/dhs/ccpp/copay/ms_ccpp_copay_waived.py new file mode 100644 index 00000000000..df45bf9f0fc --- /dev/null +++ b/policyengine_us/variables/gov/states/ms/dhs/ccpp/copay/ms_ccpp_copay_waived.py @@ -0,0 +1,23 @@ +from policyengine_us.model_api import * + + +class ms_ccpp_copay_waived(Variable): + value_type = bool + entity = SPMUnit + label = "Mississippi CCPP co-payment is waived" + definition_period = MONTH + defined_for = StateCode.MS + reference = "https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=40" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ms.dhs.ccpp.copay + monthly_income = max_(spm_unit("ms_ccpp_countable_income", period), 0) + at_or_below_fpl = monthly_income <= ( + spm_unit("spm_unit_fpg", period) * p.fpg_exempt_rate + ) + homeless_no_income = spm_unit.household("is_homeless", period.this_year) & ( + monthly_income == 0 + ) + return ( + at_or_below_fpl | spm_unit("is_tanf_enrolled", period) | homeless_no_income + ) diff --git a/policyengine_us/variables/gov/states/ms/dhs/ccpp/copay/ms_ccpp_income_based_copay.py b/policyengine_us/variables/gov/states/ms/dhs/ccpp/copay/ms_ccpp_income_based_copay.py new file mode 100644 index 00000000000..66a15382504 --- /dev/null +++ b/policyengine_us/variables/gov/states/ms/dhs/ccpp/copay/ms_ccpp_income_based_copay.py @@ -0,0 +1,31 @@ +from policyengine_us.model_api import * + + +class ms_ccpp_income_based_copay(Variable): + value_type = float + entity = SPMUnit + unit = USD + label = "Mississippi CCPP monthly income-based co-payment" + definition_period = MONTH + defined_for = StateCode.MS + reference = "https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=41" + + def formula(spm_unit, period, parameters): + # NOTE: Applies the published rate to exact monthly income, not to the + # fee scale's rounded $1,000 income rows. + p = parameters(period).gov.states.ms.dhs.ccpp.copay + p_income = parameters(period).gov.states.ms.dhs.ccpp.income + monthly_income = max_(spm_unit("ms_ccpp_countable_income", period), 0) + fee_scale_size = min_( + spm_unit("spm_unit_size", period.this_year), p.max_family_size + ) + monthly_smi = spm_unit("hhs_smi", period) + very_low_income = ( + monthly_income <= monthly_smi * p_income.very_low_income_smi_rate + ) + copay_rate = where( + very_low_income, + p.rate.very_low_income.calc(fee_scale_size), + p.rate.low_income.calc(fee_scale_size), + ) + return monthly_income * copay_rate diff --git a/policyengine_us/variables/gov/states/ms/dhs/ccpp/copay/ms_ccpp_minimum_fee_category.py b/policyengine_us/variables/gov/states/ms/dhs/ccpp/copay/ms_ccpp_minimum_fee_category.py new file mode 100644 index 00000000000..ea117ad8145 --- /dev/null +++ b/policyengine_us/variables/gov/states/ms/dhs/ccpp/copay/ms_ccpp_minimum_fee_category.py @@ -0,0 +1,30 @@ +from policyengine_us.model_api import * + + +class ms_ccpp_minimum_fee_category(Variable): + value_type = bool + entity = SPMUnit + label = "Mississippi CCPP minimum-fee category" + definition_period = MONTH + defined_for = StateCode.MS + reference = "https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=41" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ms.dhs.ccpp.eligibility + person = spm_unit.members + has_protective_child = spm_unit.any( + person("receives_or_needs_protective_services", period.this_year) + ) + is_head_or_spouse = person("is_tax_unit_head_or_spouse", period.this_year) + has_ssi_disabled_parent = spm_unit.any( + is_head_or_spouse + & person("is_ssi_disabled", period.this_year) + & (person("ssi", period) > 0) + ) + age = person("age", period.this_year) + has_special_needs_child = spm_unit.any( + person("is_tax_unit_dependent", period.this_year) + & person("is_disabled", period.this_year) + & (age < p.special_needs_child_age_limit) + ) + return has_protective_child | has_ssi_disabled_parent | has_special_needs_child diff --git a/policyengine_us/variables/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_activity_eligible.py b/policyengine_us/variables/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_activity_eligible.py new file mode 100644 index 00000000000..c9c2c93654f --- /dev/null +++ b/policyengine_us/variables/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_activity_eligible.py @@ -0,0 +1,32 @@ +from policyengine_us.model_api import * + + +class ms_ccpp_activity_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for Mississippi CCPP based on activity requirements" + definition_period = MONTH + defined_for = StateCode.MS + reference = "https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=30" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ms.dhs.ccpp.eligibility + person = spm_unit.members + is_head_or_spouse = person("is_tax_unit_head_or_spouse", period.this_year) + # Use the pre-labor-supply-response hours to avoid a circular dependency + # with the labor supply response cycle. + hours_worked = person("weekly_hours_worked_before_lsr", period.this_year) + meets_work_requirement = hours_worked >= p.activity_hours + # Full-time school or approved training also satisfies the requirement. + is_student = person("is_full_time_student", period.this_year) + # The activity requirement is waived for an SSI-disabled parent. + is_ssi_disabled = person("is_ssi_disabled", period.this_year) + # Rule 5.1(3) also waives the requirement for a parent with a + # life-threatening illness; we don't track that at the moment. + individually_eligible = meets_work_requirement | is_student | is_ssi_disabled + # Require at least one head/spouse so a unit of only dependents does not + # vacuously pass, and require every head/spouse to be individually + # eligible. + has_head_or_spouse = spm_unit.sum(is_head_or_spouse) >= 1 + all_covered = spm_unit.sum(is_head_or_spouse & ~individually_eligible) == 0 + return has_head_or_spouse & all_covered diff --git a/policyengine_us/variables/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_categorically_eligible.py b/policyengine_us/variables/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_categorically_eligible.py new file mode 100644 index 00000000000..178028c21eb --- /dev/null +++ b/policyengine_us/variables/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_categorically_eligible.py @@ -0,0 +1,27 @@ +from policyengine_us.model_api import * + + +class ms_ccpp_categorically_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Categorically eligible for Mississippi CCPP" + definition_period = MONTH + defined_for = StateCode.MS + reference = "https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=18" + + def formula(spm_unit, period, parameters): + # Categorical pathways bypass the income test. We model TANF + # recipients, homeless children, and children in protective services. + # Transitional Child Care, Healthy Families Mississippi, and teen-parent + # pathways are not tracked at the moment. + is_tanf = spm_unit("is_tanf_enrolled", period) + is_homeless = spm_unit.household("is_homeless", period.this_year) + has_protective_child = ( + add( + spm_unit, + period.this_year, + ["receives_or_needs_protective_services"], + ) + > 0 + ) + return is_tanf | is_homeless | has_protective_child diff --git a/policyengine_us/variables/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_eligible.py b/policyengine_us/variables/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_eligible.py new file mode 100644 index 00000000000..1f8eb7406eb --- /dev/null +++ b/policyengine_us/variables/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_eligible.py @@ -0,0 +1,30 @@ +from policyengine_us.model_api import * + + +class ms_ccpp_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for Mississippi CCPP" + definition_period = MONTH + defined_for = StateCode.MS + reference = "https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=25" + + def formula(spm_unit, period, parameters): + has_eligible_child = add(spm_unit, period, ["ms_ccpp_eligible_child"]) > 0 + asset_eligible = spm_unit("is_ccdf_asset_eligible", period.this_year) + income_eligible = spm_unit("ms_ccpp_income_eligible", period) + activity_eligible = spm_unit("ms_ccpp_activity_eligible", period) + + # Standard low-income pathway: eligible child, assets, income, and a + # qualifying parent activity. + standard = ( + has_eligible_child & asset_eligible & income_eligible & activity_eligible + ) + + # Categorical pathways (TANF, homeless, protective services) bypass the + # income and activity tests; the eligible child and asset tests still + # apply. + categorical = spm_unit("ms_ccpp_categorically_eligible", period) + categorical_path = has_eligible_child & asset_eligible & categorical + + return standard | categorical_path diff --git a/policyengine_us/variables/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_eligible_child.py b/policyengine_us/variables/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_eligible_child.py new file mode 100644 index 00000000000..a250f2dedef --- /dev/null +++ b/policyengine_us/variables/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_eligible_child.py @@ -0,0 +1,26 @@ +from policyengine_us.model_api import * + + +class ms_ccpp_eligible_child(Variable): + value_type = bool + entity = Person + label = "Eligible child for Mississippi CCPP" + definition_period = MONTH + defined_for = StateCode.MS + reference = "https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=25" + + def formula(person, period, parameters): + p = parameters(period).gov.states.ms.dhs.ccpp.eligibility + age = person("age", period.this_year) + is_special_needs = person("is_disabled", period.this_year) + # Children must be under 13, or under 19 if they have special needs. + age_eligible = where( + is_special_needs, + age < p.special_needs_child_age_limit, + age < p.child_age_limit, + ) + # Children must be citizens or qualified non-citizens (no parent bar). + immigration_eligible = person( + "is_ccdf_immigration_eligible_child", period.this_year + ) + return age_eligible & immigration_eligible diff --git a/policyengine_us/variables/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_income_eligible.py b/policyengine_us/variables/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_income_eligible.py new file mode 100644 index 00000000000..85a93447c1a --- /dev/null +++ b/policyengine_us/variables/gov/states/ms/dhs/ccpp/eligibility/ms_ccpp_income_eligible.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class ms_ccpp_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for Mississippi CCPP based on income" + definition_period = MONTH + defined_for = StateCode.MS + reference = "https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=25" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ms.dhs.ccpp.income + countable_income = spm_unit("ms_ccpp_countable_income", period) + # hhs_smi is annual; reading it with the monthly period auto-converts. + monthly_smi = spm_unit("hhs_smi", period) + return countable_income <= monthly_smi * p.smi_rate diff --git a/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_ccpp.py b/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_ccpp.py new file mode 100644 index 00000000000..a2d4fd22fa2 --- /dev/null +++ b/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_ccpp.py @@ -0,0 +1,24 @@ +from policyengine_us.model_api import * + + +class ms_ccpp(Variable): + value_type = float + entity = SPMUnit + unit = USD + label = "Mississippi CCPP benefit amount" + definition_period = MONTH + defined_for = "ms_ccpp_eligible" + reference = "https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=57" + + def formula(spm_unit, period, parameters): + copay = spm_unit("ms_ccpp_copay", period) + # Sum the per-child weekly maximum rates and convert to monthly. + weekly_rate = add(spm_unit, period, ["ms_ccpp_maximum_weekly_rate"]) + monthly_rate = weekly_rate * (WEEKS_IN_YEAR / MONTHS_IN_YEAR) + # The subsidy covers the lesser of the provider's charge and the + # maximum rate, net of the family co-payment. + pre_subsidy_childcare_expenses = spm_unit( + "spm_unit_pre_subsidy_childcare_expenses", period + ) + capped_expenses = min_(pre_subsidy_childcare_expenses, monthly_rate) + return max_(capped_expenses - copay, 0) diff --git a/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_ccpp_age_group.py b/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_ccpp_age_group.py new file mode 100644 index 00000000000..2268a31bae9 --- /dev/null +++ b/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_ccpp_age_group.py @@ -0,0 +1,26 @@ +from policyengine_us.model_api import * + + +class MSCCPPAgeGroup(Enum): + INFANT = "Infant" + TODDLER = "Toddler" + PRESCHOOL = "Preschool" + SCHOOL_AGE = "School age" + + +class ms_ccpp_age_group(Variable): + value_type = Enum + entity = Person + possible_values = MSCCPPAgeGroup + default_value = MSCCPPAgeGroup.SCHOOL_AGE + definition_period = MONTH + label = "Mississippi CCPP child age group for payment rates" + defined_for = StateCode.MS + reference = "https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=13" + + def formula(person, period, parameters): + age = person("age", period.this_year) + p = parameters(period).gov.states.ms.dhs.ccpp.age_group + # The bracket returns 0=INFANT, 1=TODDLER, 2=PRESCHOOL, 3=SCHOOL_AGE, + # which PolicyEngine maps to the enum index. + return p.age.calc(age) diff --git a/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_ccpp_countable_earned_income.py b/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_ccpp_countable_earned_income.py new file mode 100644 index 00000000000..e36dd33cccc --- /dev/null +++ b/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_ccpp_countable_earned_income.py @@ -0,0 +1,27 @@ +from policyengine_us.model_api import * + + +class ms_ccpp_countable_earned_income(Variable): + value_type = float + entity = Person + label = "Mississippi CCPP countable earned income" + definition_period = MONTH + unit = USD + defined_for = StateCode.MS + reference = "https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=28" + + def formula(person, period, parameters): + p = parameters(period).gov.states.ms.dhs.ccpp.income + # Rule 5.4: earned income of students under 18 is non-countable; the + # countable wage list applies to adults only. + age = person("age", period.this_year) + is_excluded_student = person("is_in_k12_school", period.this_year) & ( + age < p.student_earner_age_limit + ) + # Self-employment is counted as gross (Rule 5.3); a net business loss + # does not offset other income, so floor the self-employment sum at zero. + self_employment = max_( + add(person, period, p.countable_income.self_employment_sources), 0 + ) + earned = person("employment_income", period) + self_employment + return where(is_excluded_student, 0, earned) diff --git a/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_ccpp_countable_income.py b/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_ccpp_countable_income.py new file mode 100644 index 00000000000..350c6669976 --- /dev/null +++ b/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_ccpp_countable_income.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class ms_ccpp_countable_income(Variable): + value_type = float + entity = SPMUnit + label = "Mississippi CCPP countable income" + definition_period = MONTH + unit = USD + defined_for = StateCode.MS + reference = "https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=28" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ms.dhs.ccpp.income + earned = add(spm_unit, period, ["ms_ccpp_countable_earned_income"]) + unearned = add(spm_unit, period, p.countable_income.unearned_sources) + return earned + unearned diff --git a/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_ccpp_facility_location.py b/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_ccpp_facility_location.py new file mode 100644 index 00000000000..d5096262022 --- /dev/null +++ b/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_ccpp_facility_location.py @@ -0,0 +1,32 @@ +from policyengine_us.model_api import * + + +class MSCCPPFacilityLocation(Enum): + METRO = "Metro" + NON_METRO = "Non-metro" + + +class ms_ccpp_facility_location(Variable): + value_type = Enum + entity = Household + possible_values = MSCCPPFacilityLocation + default_value = MSCCPPFacilityLocation.NON_METRO + definition_period = YEAR + label = "Mississippi CCPP facility metro or non-metro location" + defined_for = StateCode.MS + # The metro / non-metro split is a Market Rate Survey rate-table dimension + # (Table 1 and Table 2 disaggregate rates by metro status), not a manual rule. + reference = "https://www.mdhs.ms.gov/wp-content/uploads/2024/06/Mississippi-Child-Care-Market-Rate-Survey-2024.pdf#page=9" + + def formula(household, period, parameters): + # CCPP rates vary by the facility's metro / non-metro location. We don't + # track the child care facility's location at the moment, so we use the + # household's county as a proxy for the facility location. + county = household("county_str", period) + p = parameters(period).gov.states.ms.dhs.ccpp.geography + is_metro = np.isin(county, p.metro_counties) + return where( + is_metro, + MSCCPPFacilityLocation.METRO, + MSCCPPFacilityLocation.NON_METRO, + ) diff --git a/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_ccpp_maximum_weekly_rate.py b/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_ccpp_maximum_weekly_rate.py new file mode 100644 index 00000000000..3eb01f91624 --- /dev/null +++ b/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_ccpp_maximum_weekly_rate.py @@ -0,0 +1,45 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.ms.dhs.ccpp.ms_ccpp_provider_type import ( + MSCCPPProviderType, +) + + +class ms_ccpp_maximum_weekly_rate(Variable): + value_type = float + entity = Person + unit = USD + label = "Mississippi CCPP maximum weekly rate per child" + definition_period = MONTH + defined_for = "ms_ccpp_eligible_child" + # 2024 Market Rate Survey, Table 1 (licensed center, p.9) and Table 2 + # (registered family home, p.10); operative "Current CCPP Rates" pp.9-10. + reference = "https://www.mdhs.ms.gov/wp-content/uploads/2024/06/Mississippi-Child-Care-Market-Rate-Survey-2024.pdf#page=9" + + def formula(person, period, parameters): + rates = parameters(period).gov.states.ms.dhs.ccpp.rates + provider_type = person("ms_ccpp_provider_type", period) + time_category = person("ms_ccpp_time_category", period) + age_group = person("ms_ccpp_age_group", period) + location = person.household("ms_ccpp_facility_location", period.this_year) + + is_center = provider_type == MSCCPPProviderType.CENTER + + # Standard rates by location, age band, and time category. + center_rate = rates.center[location][age_group][time_category] + family_home_rate = rates.family_home[location][age_group][time_category] + standard_rate = where(is_center, center_rate, family_home_rate) + + # Special-needs (and in-home) children draw the flat all-ages + # special-needs rate set; in-home care is paid the home-based rate. + special_needs_center_rate = rates.special_needs_center[location][time_category] + special_needs_home_rate = rates.special_needs_home[location][time_category] + special_needs_rate = where( + is_center, special_needs_center_rate, special_needs_home_rate + ) + + is_special_needs = person("is_disabled", period.this_year) + rate = where(is_special_needs, special_needs_rate, standard_rate) + + # A child not actually in care draws no rate. + in_care = person("childcare_hours_per_week", period.this_year) > 0 + return where(in_care, rate, 0) diff --git a/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_ccpp_provider_type.py b/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_ccpp_provider_type.py new file mode 100644 index 00000000000..c5b8c97bc7c --- /dev/null +++ b/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_ccpp_provider_type.py @@ -0,0 +1,21 @@ +from policyengine_us.model_api import * + + +class MSCCPPProviderType(Enum): + CENTER = "Licensed child care center" + FAMILY_HOME = "Registered family child care home" + + +class ms_ccpp_provider_type(Variable): + value_type = Enum + entity = Person + possible_values = MSCCPPProviderType + default_value = MSCCPPProviderType.CENTER + definition_period = MONTH + label = "Mississippi CCPP child care provider type" + defined_for = StateCode.MS + # In-home care is special-needs-only and is paid the home-based special-needs + # rate, so there is no separate in-home provider type; route in-home and + # special-needs children through FAMILY_HOME (or CENTER) and the special-needs + # rate set. + reference = "https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=43" diff --git a/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_ccpp_time_category.py b/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_ccpp_time_category.py new file mode 100644 index 00000000000..b1d950f3d36 --- /dev/null +++ b/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_ccpp_time_category.py @@ -0,0 +1,25 @@ +from policyengine_us.model_api import * + + +class MSCCPPTimeCategory(Enum): + PART_TIME = "Part time" + FULL_TIME = "Full time" + + +class ms_ccpp_time_category(Variable): + value_type = Enum + entity = Person + possible_values = MSCCPPTimeCategory + default_value = MSCCPPTimeCategory.FULL_TIME + definition_period = MONTH + label = "Mississippi CCPP care time category" + defined_for = StateCode.MS + reference = "https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=12" + + def formula(person, period, parameters): + hours_per_day = person("childcare_hours_per_day", period.this_year) + p = parameters(period).gov.states.ms.dhs.ccpp.time_category + # Part-time = care for fewer than 6 hours of a 24-hour day; full-time is + # 6 or more hours. The bracket returns 0=PART_TIME, 1=FULL_TIME, which + # PolicyEngine maps to the enum index. + return p.hours.calc(hours_per_day) diff --git a/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_child_care_subsidies.py b/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_child_care_subsidies.py new file mode 100644 index 00000000000..e3885c4a698 --- /dev/null +++ b/policyengine_us/variables/gov/states/ms/dhs/ccpp/ms_child_care_subsidies.py @@ -0,0 +1,12 @@ +from policyengine_us.model_api import * + + +class ms_child_care_subsidies(Variable): + value_type = float + entity = SPMUnit + label = "Mississippi child care subsidies" + unit = USD + definition_period = YEAR + defined_for = StateCode.MS + reference = "https://www.mdhs.ms.gov/wp-content/uploads/2026/01/CCPP-Policy-Manual_Final_1142025.pdf#page=57" + adds = ["ms_ccpp"]