diff --git a/changelog.d/ny-ccdf.added.md b/changelog.d/ny-ccdf.added.md new file mode 100644 index 00000000000..b1ca67224cc --- /dev/null +++ b/changelog.d/ny-ccdf.added.md @@ -0,0 +1 @@ +Add the New York Child Care Assistance Program under its own state namespace, encoding current law: the October 2024 market rates by county group, provider type, age group, and duration of care, with excess periods for a sixth or seventh day and for hours beyond the daily maximum, the 85% state median income limit, the 1% family share with the statutory minimum and categorical exceptions, the foster-care and child-protective-services categorical eligibility routes, the age extensions for a child with special needs, a per-child payment cap, and a New York countable-income measure that excludes capital gains and a dependent child's earnings. 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 0bd49c0fd55..2ce333548a8 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 @@ -34,6 +34,7 @@ values: - nj_child_care_subsidies # New Jersey Child Care Assistance Program - oh_child_care_subsidies # Ohio Publicly Funded Child Care - nv_child_care_subsidies # Nevada Child Care and Development Program (CCDP) + - ny_child_care_subsidies # New York Child Care Assistance Program - ri_child_care_subsidies # Rhode Island Child Care Assistance Program - sc_child_care_subsidies # South Carolina Child Care Scholarship Program - ut_child_care_subsidies # Utah Child Care Assistance (CC) @@ -92,6 +93,7 @@ values: - sd_child_care_subsidies # South Dakota Child Care Assistance (CCA) - nc_child_care_subsidies # North Carolina Subsidized Child Care Assistance - wy_child_care_subsidies # Wyoming Child Care, Purchase of Service + - ny_child_care_subsidies # New York Child Care Assistance Program 2025-01-01: - ak_child_care_subsidies # Alaska Child Care Assistance Program (PASS) - ar_child_care_subsidies # Arkansas School Readiness Assistance @@ -142,6 +144,7 @@ values: - tn_child_care_subsidies # Tennessee Child Care Certificate Program (Smart Steps) - wy_child_care_subsidies # Wyoming Child Care, Purchase of Service - tx_child_care_subsidies # Texas Child Care Services (CCS) + - ny_child_care_subsidies # New York Child Care Assistance Program metadata: unit: list diff --git a/policyengine_us/parameters/gov/household/household_state_benefits.yaml b/policyengine_us/parameters/gov/household/household_state_benefits.yaml index c7d69cf130d..080a049c39f 100644 --- a/policyengine_us/parameters/gov/household/household_state_benefits.yaml +++ b/policyengine_us/parameters/gov/household/household_state_benefits.yaml @@ -89,6 +89,8 @@ values: - la_oss # Washington benefits - wa_child_care_subsidies + # New York benefits + - ny_child_care_subsidies 2024-01-01: # Delaware benefits - de_ssp @@ -189,6 +191,8 @@ values: - oh_child_care_subsidies # Washington child care subsidies - wa_child_care_subsidies + # New York benefits + - ny_child_care_subsidies 2025-01-01: # Delaware benefits - de_ssp @@ -290,6 +294,8 @@ values: - oh_child_care_subsidies # Washington child care subsidies - wa_child_care_subsidies + # New York benefits + - ny_child_care_subsidies 2026-01-01: # Delaware benefits - de_ssp @@ -393,6 +399,8 @@ values: - wa_child_care_subsidies # New Jersey benefits - nj_property_tax_relief + # New York benefits + - ny_child_care_subsidies metadata: unit: list period: year diff --git a/policyengine_us/parameters/gov/states/ny/ocfs/ccap/age_groups.yaml b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/age_groups.yaml new file mode 100644 index 00000000000..c26c0e8b81a --- /dev/null +++ b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/age_groups.yaml @@ -0,0 +1,21 @@ +description: New York classifies children into these age bands for Child Care Assistance Program market rates. +# Center-based providers — day care centers, school-age child care programs, +# and legally exempt group programs — use a lower infant ceiling than +# home-based providers. +# age is a float in PolicyEngine, so 1.5 encodes eighteen months exactly. +center_infant_upper_bound: + 2019-05-01: 1.5 +home_infant_upper_bound: + 2019-05-01: 2 +toddler_upper_bound: + 2019-05-01: 3 +preschool_upper_bound: + 2019-05-01: 6 + +metadata: + unit: year + period: year + label: New York CCAP market-rate age bands + reference: + - title: 24-OCFS-LCM-22, §III.3, age groups for market rates, center-based and home-based provider sets + href: https://ocfs.ny.gov/main/policies/external/2024/lcm/24-OCFS-LCM-22.pdf#page=4 diff --git a/policyengine_us/parameters/gov/states/ny/ocfs/ccap/county_group.yaml b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/county_group.yaml new file mode 100644 index 00000000000..49355e8b071 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/county_group.yaml @@ -0,0 +1,84 @@ +description: New York assigns counties to these market-rate groups under the Child Care Assistance Program. + +group_1: + values: + 2024-10-01: + - NASSAU_COUNTY_NY + - PUTNAM_COUNTY_NY + - ROCKLAND_COUNTY_NY + - SUFFOLK_COUNTY_NY + - WESTCHESTER_COUNTY_NY +group_2: + values: + 2024-10-01: + - ALBANY_COUNTY_NY + - COLUMBIA_COUNTY_NY + - DUTCHESS_COUNTY_NY + - ERIE_COUNTY_NY + - MONROE_COUNTY_NY + - ONONDAGA_COUNTY_NY + - ONTARIO_COUNTY_NY + - ORANGE_COUNTY_NY + - RENSSELAER_COUNTY_NY + - SARATOGA_COUNTY_NY + - SCHENECTADY_COUNTY_NY + - TOMPKINS_COUNTY_NY + - ULSTER_COUNTY_NY + - WARREN_COUNTY_NY +group_3: + values: + 2024-10-01: + - ALLEGANY_COUNTY_NY + - BROOME_COUNTY_NY + - CATTARAUGUS_COUNTY_NY + - CAYUGA_COUNTY_NY + - CHAUTAUQUA_COUNTY_NY + - CHEMUNG_COUNTY_NY + - CHENANGO_COUNTY_NY + - CLINTON_COUNTY_NY + - CORTLAND_COUNTY_NY + - DELAWARE_COUNTY_NY + - ESSEX_COUNTY_NY + - FRANKLIN_COUNTY_NY + - FULTON_COUNTY_NY + - GENESEE_COUNTY_NY + - GREENE_COUNTY_NY + - HAMILTON_COUNTY_NY + - HERKIMER_COUNTY_NY + - JEFFERSON_COUNTY_NY + - LEWIS_COUNTY_NY + - LIVINGSTON_COUNTY_NY + - MADISON_COUNTY_NY + - MONTGOMERY_COUNTY_NY + - NIAGARA_COUNTY_NY + - ONEIDA_COUNTY_NY + - ORLEANS_COUNTY_NY + - OSWEGO_COUNTY_NY + - OTSEGO_COUNTY_NY + - SCHOHARIE_COUNTY_NY + - SCHUYLER_COUNTY_NY + - SENECA_COUNTY_NY + - ST_LAWRENCE_COUNTY_NY + - STEUBEN_COUNTY_NY + - SULLIVAN_COUNTY_NY + - TIOGA_COUNTY_NY + - WASHINGTON_COUNTY_NY + - WAYNE_COUNTY_NY + - WYOMING_COUNTY_NY + - YATES_COUNTY_NY +group_4: + values: + 2024-10-01: + - BRONX_COUNTY_NY + - KINGS_COUNTY_NY + - NEW_YORK_COUNTY_NY + - QUEENS_COUNTY_NY + - RICHMOND_COUNTY_NY + +metadata: + unit: list + period: year + label: New York CCAP county groups + reference: + - title: 24-OCFS-LCM-22 Attachment A + href: https://ocfs.ny.gov/main/policies/external/2024/lcm/24-OCFS-LCM-22.pdf#page=14 diff --git a/policyengine_us/parameters/gov/states/ny/ocfs/ccap/duration/daily_maximum_hours.yaml b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/duration/daily_maximum_hours.yaml new file mode 100644 index 00000000000..f4c9ce213a1 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/duration/daily_maximum_hours.yaml @@ -0,0 +1,11 @@ +description: New York covers this many hours of care in a daily market rate period under the Child Care Assistance Program. +values: + 2019-05-01: 12 + +metadata: + unit: hour + period: day + label: New York CCAP daily rate maximum hours + reference: + - title: 24-OCFS-LCM-22, sec. III.4.b, care of 12 hours or more in a day earns an additional market rate + href: https://ocfs.ny.gov/main/policies/external/2024/lcm/24-OCFS-LCM-22.pdf#page=5 diff --git a/policyengine_us/parameters/gov/states/ny/ocfs/ccap/duration/daily_minimum_hours.yaml b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/duration/daily_minimum_hours.yaml new file mode 100644 index 00000000000..e37a7887dcc --- /dev/null +++ b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/duration/daily_minimum_hours.yaml @@ -0,0 +1,11 @@ +description: New York applies the daily market rate at or above this many hours of care per day under the Child Care Assistance Program. +values: + 2019-05-01: 6 + +metadata: + unit: hour + period: day + label: New York CCAP daily rate minimum hours + reference: + - title: 18 NYCRR 415.9(b)-(c), daily rates at six or more hours per day and part-day rates below six + href: https://ocfs.ny.gov/programs/childcare/regulations/415-Child-Care-Services.pdf#page=44 diff --git a/policyengine_us/parameters/gov/states/ny/ocfs/ccap/duration/weekly_maximum_days.yaml b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/duration/weekly_maximum_days.yaml new file mode 100644 index 00000000000..24e3c031663 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/duration/weekly_maximum_days.yaml @@ -0,0 +1,11 @@ +description: New York covers this many days of care in a weekly market rate period under the Child Care Assistance Program. +values: + 2019-05-01: 5 + +metadata: + unit: day + period: week + label: New York CCAP weekly rate maximum days + reference: + - title: 24-OCFS-LCM-22, sec. III.4.a, weekly rate over five or fewer days in a single week + href: https://ocfs.ny.gov/main/policies/external/2024/lcm/24-OCFS-LCM-22.pdf#page=5 diff --git a/policyengine_us/parameters/gov/states/ny/ocfs/ccap/duration/weekly_minimum_hours.yaml b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/duration/weekly_minimum_hours.yaml new file mode 100644 index 00000000000..1587b824eb9 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/duration/weekly_minimum_hours.yaml @@ -0,0 +1,11 @@ +description: New York applies the weekly market rate at or above this many hours of care per week under the Child Care Assistance Program. +values: + 2019-05-01: 30 + +metadata: + unit: hour + period: week + label: New York CCAP weekly rate minimum hours + reference: + - title: 18 NYCRR 415.9(a), weekly rates for 30 or more hours for five or less days per week + href: https://ocfs.ny.gov/programs/childcare/regulations/415-Child-Care-Services.pdf#page=44 diff --git a/policyengine_us/parameters/gov/states/ny/ocfs/ccap/eligibility/age_limit/base.yaml b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/eligibility/age_limit/base.yaml new file mode 100644 index 00000000000..8fb212486e1 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/eligibility/age_limit/base.yaml @@ -0,0 +1,11 @@ +description: New York serves children under this age under the Child Care Assistance Program. +values: + 2021-10-01: 13 + +metadata: + unit: year + period: year + label: New York CCAP base age limit + reference: + - title: 18 NYCRR 415.1(b)(1), eligible child under 13 years of age + href: https://ocfs.ny.gov/programs/childcare/regulations/415-Child-Care-Services.pdf#page=2 diff --git a/policyengine_us/parameters/gov/states/ny/ocfs/ccap/eligibility/age_limit/special_needs.yaml b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/eligibility/age_limit/special_needs.yaml new file mode 100644 index 00000000000..c4facdbbc0a --- /dev/null +++ b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/eligibility/age_limit/special_needs.yaml @@ -0,0 +1,11 @@ +description: New York serves children with special needs under this age under the Child Care Assistance Program. +values: + 2021-10-01: 18 + +metadata: + unit: year + period: year + label: New York CCAP special needs age limit + reference: + - title: 18 NYCRR 415.1(b)(2), eligible child under 18 with special needs or under court supervision + href: https://ocfs.ny.gov/programs/childcare/regulations/415-Child-Care-Services.pdf#page=2 diff --git a/policyengine_us/parameters/gov/states/ny/ocfs/ccap/eligibility/age_limit/special_needs_student.yaml b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/eligibility/age_limit/special_needs_student.yaml new file mode 100644 index 00000000000..e7cfcf5cf09 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/eligibility/age_limit/special_needs_student.yaml @@ -0,0 +1,11 @@ +description: New York serves full-time secondary students with special needs under this age under the Child Care Assistance Program. +values: + 2021-10-01: 19 + +metadata: + unit: year + period: year + label: New York CCAP special needs student age limit + reference: + - title: 18 NYCRR 415.1(b)(3), eligible child under 19 and a full-time secondary student with special needs or under court supervision + href: https://ocfs.ny.gov/programs/childcare/regulations/415-Child-Care-Services.pdf#page=2 diff --git a/policyengine_us/parameters/gov/states/ny/ocfs/ccap/family_share_rate.yaml b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/family_share_rate.yaml new file mode 100644 index 00000000000..d87c99709f9 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/family_share_rate.yaml @@ -0,0 +1,15 @@ +description: New York applies this rate to income above the state income standard under the Child Care Assistance Program. +values: + 2023-10-01: 0.01 + +metadata: + unit: /1 + period: year + label: New York CCAP family share rate + reference: + - title: NY Social Services Law § 410-w(8), family share capped at one percent of income exceeding the federal poverty level + href: https://www.nysenate.gov/legislation/laws/SOS/410-W + - title: 18 NYCRR 415.3(e)(3), family share as a percentage of income in excess of the state income standard + href: https://ocfs.ny.gov/programs/childcare/regulations/415-Child-Care-Services.pdf#page=19 + - title: 23-OCFS-ADM-18, family share set at 1% of income exceeding the federal poverty level effective October 1, 2023 + href: https://ocfs.ny.gov/main/policies/external/2023/adm/23-OCFS-ADM-18.pdf#page=3 diff --git a/policyengine_us/parameters/gov/states/ny/ocfs/ccap/income/countable_income/earned_sources.yaml b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/income/countable_income/earned_sources.yaml new file mode 100644 index 00000000000..29597085895 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/income/countable_income/earned_sources.yaml @@ -0,0 +1,19 @@ +description: New York excludes these earned income sources for a dependent child under the Child Care Assistance Program. +# The earned subset of countable_income/sources.yaml. 404.5(b)(6)(xiii) +# excludes the earnings of a dependent child under 18, so +# ny_ccap_countable_income subtracts these sources for any member who is a +# child and is not a parent of the child needing care. +values: + 2021-10-01: + - employment_income + - self_employment_income + - sstb_self_employment_income + - farm_operations_income + +metadata: + unit: list + period: year + label: New York CCAP earned income sources + reference: + - title: 18 NYCRR 404.5(b)(6)(xiii), earnings of a dependent child + href: https://ocfs.ny.gov/programs/childcare/regulations/404-Eligibility.pdf#page=12 diff --git a/policyengine_us/parameters/gov/states/ny/ocfs/ccap/income/countable_income/sources.yaml b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/income/countable_income/sources.yaml new file mode 100644 index 00000000000..da7eeff107c --- /dev/null +++ b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/income/countable_income/sources.yaml @@ -0,0 +1,76 @@ +description: New York counts these income sources under the Child Care Assistance Program. +values: + 2021-10-01: + # 404.5(b)(5)(i): wages, salary, commissions, tips and bonuses, counted + # before deductions for taxes, bonds, pensions and union dues. + - employment_income + # 404.5(b)(5)(ii): net income from non-farm self-employment. + - self_employment_income + - sstb_self_employment_income + # 404.5(b)(5)(iii): net income from farm self-employment. + - farm_operations_income + # 404.5(b)(5)(iv): social security pensions and survivor benefits, and + # permanent disability insurance payments made by the Social Security + # Administration. social_security already includes the dependents, + # disability, retirement and survivors components, so those are not + # listed separately. + - social_security + # 404.5(b)(5)(iv) also counts railroad retirement checks from the + # U.S. government, which PolicyEngine records separately. + - railroad_benefits + # 404.5(b)(5)(v): dividends, interest, income from estates or trusts, + # net rental income and royalties. + - dividend_income + - interest_income + - rental_income + # 404.5(b)(5)(vii): pensions and annuities. PolicyEngine records military + # retirement separately from pension_income. + - pension_income + - military_retirement_pay + # 404.5(b)(5)(viii): unemployment compensation, including strike benefits + # received from union funds. + - unemployment_compensation + - strike_benefits + - workers_compensation + - alimony_income + - child_support_received + # 404.5(b)(5)(xii): veterans' pensions. + - veterans_benefits + # + # Counted but not listed here because the amount depends on who receives + # it — see ny_ccap_countable_income: + # - ssi, countable in full under 404.5(b)(5)(vi) except for the SSI of any + # child in the child care services unit, which 404.5(b)(6)(xxi) excludes. + # + # Excluded sources, so simply not listed: + # - capital_gains, excluded by 404.5(b)(6)(viii), and proceeds from the + # sale of stocks, bonds, a house or a car, excluded by 404.5(b)(6)(ii). + # - inheritance and lump-sum insurance payments, 404.5(b)(6)(vii). + # - tax refunds 404.5(b)(6)(v), gifts 404.5(b)(6)(vi), scholarships and + # Higher Education Act grants and loans 404.5(b)(6)(xiv)-(xv). + # - retirement_distributions. 404.5(b)(5)(vii) counts "periodic receipts + # from annuities or insurance"; a lump-sum distribution is not periodic, + # and 404.5(b)(5) is a closed enumeration. + # - gi_cash_assistance, illicit_income and miscellaneous_income, none of + # which appear in the 404.5(b)(5) enumeration. + # - tanf and other public assistance. These are countable under + # 404.5(b)(5)(vi), but counting them closes a circular dependency: + # ny_ccap_countable_income -> tanf -> childcare_expenses -> + # child_care_subsidies -> ny_ccap -> ny_ccap_countable_income. The same + # hazard is documented on the federal ccdf_income variable and in + # gov/states/in/fssa/ccdf/income/sources.yaml. Omitting them understates + # countable income for public-assistance households, which is partly + # offset because 415.3(e)(1) exempts those households from the family + # share entirely. + # - state supplementary payments to SSI recipients, countable under + # 404.5(b)(5)(vi). PolicyEngine has no state supplement variable. + +metadata: + unit: list + period: year + label: New York CCAP countable income sources + reference: + - title: 18 NYCRR 404.5(b)(5), monthly gross income sources + href: https://ocfs.ny.gov/programs/childcare/regulations/404-Eligibility.pdf#page=10 + - title: New York FFY 2022-2024 CCDF State Plan, Q3.1.3(a), sources of income counted + href: https://ocfs.ny.gov/programs/childcare/stateplan/assets/2022-plan/FFY2022-2024-CCDF-Plan.pdf#page=91 diff --git a/policyengine_us/parameters/gov/states/ny/ocfs/ccap/income/income_limit_smi_rate.yaml b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/income/income_limit_smi_rate.yaml new file mode 100644 index 00000000000..6e9fb1628d9 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/income/income_limit_smi_rate.yaml @@ -0,0 +1,23 @@ +description: New York limits income to this share of the state median income under the Child Care Assistance Program. +# 22-OCFS-ADM-18 applied the 85% state median income ceiling to initial +# eligibility and redetermination from August 1, 2022, alongside the 300% +# state income standard limit. The revisions to Social Services Law 410-u(2), +# 410-w(1) and 410-w(3) effective October 1, 2023 then made it the sole +# limit. 85% of the state median income is the federal CCDF maximum at +# 45 CFR 98.20(a)(2). +values: + 2022-08-01: 0.85 + +metadata: + unit: /1 + period: year + label: New York CCAP income limit share of state median income + reference: + - title: 22-OCFS-ADM-18, Increase in Income Eligibility Levels for Child Care Assistance, sec. III Program Implications (income up to 300% of the state income standard provided it does not exceed 85% state median income) + href: https://ocfs.ny.gov/main/policies/external/2022/adm/22-OCFS-ADM-18.pdf#page=2 + - title: NYS Register, May 1, 2024, Rule Making Activities (OCFS), expansion of income eligibility to 85% of the state median income effective October 1, 2023 (file page 12 = printed page 6) + href: https://dos.ny.gov/system/files/documents/2024/05/050124.pdf#page=12 + - title: NY Social Services Law § 410-w, income eligibility at 85 percent of the state median income + href: https://www.nysenate.gov/legislation/laws/SOS/410-W + - title: 45 CFR 98.20(a)(2), CCDF income eligibility maximum of 85% of state median income + href: https://www.ecfr.gov/current/title-45/section-98.20#p-98.20(a)(2) diff --git a/policyengine_us/parameters/gov/states/ny/ocfs/ccap/minimum_weekly_family_share.yaml b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/minimum_weekly_family_share.yaml new file mode 100644 index 00000000000..ea4111e823c --- /dev/null +++ b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/minimum_weekly_family_share.yaml @@ -0,0 +1,11 @@ +description: New York requires this minimum weekly family share from families required to pay an income-based share under the Child Care Assistance Program. +values: + 2019-05-01: 1 + +metadata: + unit: currency-USD + period: week + label: New York CCAP minimum weekly family share + reference: + - title: 18 NYCRR 415.3(e)(4) + href: https://ocfs.ny.gov/programs/childcare/regulations/415-Child-Care-Services.pdf#page=19 diff --git a/policyengine_us/parameters/gov/states/ny/ocfs/ccap/rates/daily.yaml b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/rates/daily.yaml new file mode 100644 index 00000000000..9665cdd28de --- /dev/null +++ b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/rates/daily.yaml @@ -0,0 +1,205 @@ +description: New York sets these daily market rates by county group, provider type, and child age under the Child Care Assistance Program. +# School-age child care programs share the DCC_SACC rates for the 3-5 and +# 6-12 bands only. Attachment A publishes $0 for school-age programs in both +# infant bands, which childcare_provider_type_group cannot express because it +# carries a single enum member for day care centers and school-age programs. +# The LE_GC infant and toddler cells are the $0 that Attachment A publishes, +# not a missing row: 415.9(g)(1) rates legally exempt group programs off the +# day care center schedule and OCFS publishes no under-3 rate for them. + +GROUP_1: + DCC_SACC: + INFANT: + 2024-10-01: 97 + TODDLER: + 2024-10-01: 90 + PRESCHOOLER: + 2024-10-01: 85 + SCHOOL_AGE: + 2024-10-01: 75 + FDC_GFDC: + INFANT: + 2024-10-01: 85 + TODDLER: + 2024-10-01: 80 + PRESCHOOLER: + 2024-10-01: 78 + SCHOOL_AGE: + 2024-10-01: 75 + LE_GC: + INFANT: + 2024-10-01: 0 + TODDLER: + 2024-10-01: 0 + PRESCHOOLER: + 2024-10-01: 64 + SCHOOL_AGE: + 2024-10-01: 56 + LE_STD: + INFANT: + 2024-10-01: 55 + TODDLER: + 2024-10-01: 52 + PRESCHOOLER: + 2024-10-01: 51 + SCHOOL_AGE: + 2024-10-01: 49 + LE_ENH: + INFANT: + 2024-10-01: 60 + TODDLER: + 2024-10-01: 56 + PRESCHOOLER: + 2024-10-01: 55 + SCHOOL_AGE: + 2024-10-01: 53 +GROUP_2: + DCC_SACC: + INFANT: + 2024-10-01: 80 + TODDLER: + 2024-10-01: 75 + PRESCHOOLER: + 2024-10-01: 70 + SCHOOL_AGE: + 2024-10-01: 60 + FDC_GFDC: + INFANT: + 2024-10-01: 65 + TODDLER: + 2024-10-01: 63 + PRESCHOOLER: + 2024-10-01: 60 + SCHOOL_AGE: + 2024-10-01: 55 + LE_GC: + INFANT: + 2024-10-01: 0 + TODDLER: + 2024-10-01: 0 + PRESCHOOLER: + 2024-10-01: 53 + SCHOOL_AGE: + 2024-10-01: 45 + LE_STD: + INFANT: + 2024-10-01: 42 + TODDLER: + 2024-10-01: 41 + PRESCHOOLER: + 2024-10-01: 39 + SCHOOL_AGE: + 2024-10-01: 36 + LE_ENH: + INFANT: + 2024-10-01: 46 + TODDLER: + 2024-10-01: 44 + PRESCHOOLER: + 2024-10-01: 42 + SCHOOL_AGE: + 2024-10-01: 39 +GROUP_3: + DCC_SACC: + INFANT: + 2024-10-01: 67 + TODDLER: + 2024-10-01: 63 + PRESCHOOLER: + 2024-10-01: 58 + SCHOOL_AGE: + 2024-10-01: 58 + FDC_GFDC: + INFANT: + 2024-10-01: 58 + TODDLER: + 2024-10-01: 56 + PRESCHOOLER: + 2024-10-01: 53 + SCHOOL_AGE: + 2024-10-01: 53 + LE_GC: + INFANT: + 2024-10-01: 0 + TODDLER: + 2024-10-01: 0 + PRESCHOOLER: + 2024-10-01: 44 + SCHOOL_AGE: + 2024-10-01: 44 + LE_STD: + INFANT: + 2024-10-01: 38 + TODDLER: + 2024-10-01: 36 + PRESCHOOLER: + 2024-10-01: 34 + SCHOOL_AGE: + 2024-10-01: 34 + LE_ENH: + INFANT: + 2024-10-01: 41 + TODDLER: + 2024-10-01: 39 + PRESCHOOLER: + 2024-10-01: 37 + SCHOOL_AGE: + 2024-10-01: 37 +GROUP_4: + DCC_SACC: + INFANT: + 2024-10-01: 102 + TODDLER: + 2024-10-01: 92 + PRESCHOOLER: + 2024-10-01: 90 + SCHOOL_AGE: + 2024-10-01: 69 + FDC_GFDC: + INFANT: + 2024-10-01: 80 + TODDLER: + 2024-10-01: 70 + PRESCHOOLER: + 2024-10-01: 65 + SCHOOL_AGE: + 2024-10-01: 60 + LE_GC: + INFANT: + 2024-10-01: 0 + TODDLER: + 2024-10-01: 0 + PRESCHOOLER: + 2024-10-01: 68 + SCHOOL_AGE: + 2024-10-01: 52 + LE_STD: + INFANT: + 2024-10-01: 52 + TODDLER: + 2024-10-01: 46 + PRESCHOOLER: + 2024-10-01: 42 + SCHOOL_AGE: + 2024-10-01: 39 + LE_ENH: + INFANT: + 2024-10-01: 56 + TODDLER: + 2024-10-01: 49 + PRESCHOOLER: + 2024-10-01: 46 + SCHOOL_AGE: + 2024-10-01: 42 + +metadata: + unit: currency-USD + period: day + label: New York CCAP daily market rates + breakdown: + - ny_ccap_county_group + - childcare_provider_type_group + - ny_ccap_age_group + reference: + - title: 24-OCFS-LCM-22 Attachment A, daily market rates for county Groups 1-4 (file pages 15-18), effective October 1, 2024 + href: https://ocfs.ny.gov/main/policies/external/2024/lcm/24-OCFS-LCM-22.pdf#page=15 diff --git a/policyengine_us/parameters/gov/states/ny/ocfs/ccap/rates/part_day.yaml b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/rates/part_day.yaml new file mode 100644 index 00000000000..1c3f9539ec6 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/rates/part_day.yaml @@ -0,0 +1,205 @@ +description: New York sets these part-day market rates by county group, provider type, and child age under the Child Care Assistance Program. +# School-age child care programs share the DCC_SACC rates for the 3-5 and +# 6-12 bands only. Attachment A publishes $0 for school-age programs in both +# infant bands, which childcare_provider_type_group cannot express because it +# carries a single enum member for day care centers and school-age programs. +# The LE_GC infant and toddler cells are the $0 that Attachment A publishes, +# not a missing row: 415.9(g)(1) rates legally exempt group programs off the +# day care center schedule and OCFS publishes no under-3 rate for them. + +GROUP_1: + DCC_SACC: + INFANT: + 2024-10-01: 65 + TODDLER: + 2024-10-01: 60 + PRESCHOOLER: + 2024-10-01: 57 + SCHOOL_AGE: + 2024-10-01: 50 + FDC_GFDC: + INFANT: + 2024-10-01: 57 + TODDLER: + 2024-10-01: 53 + PRESCHOOLER: + 2024-10-01: 52 + SCHOOL_AGE: + 2024-10-01: 50 + LE_GC: + INFANT: + 2024-10-01: 0 + TODDLER: + 2024-10-01: 0 + PRESCHOOLER: + 2024-10-01: 43 + SCHOOL_AGE: + 2024-10-01: 38 + LE_STD: + INFANT: + 2024-10-01: 37 + TODDLER: + 2024-10-01: 34 + PRESCHOOLER: + 2024-10-01: 34 + SCHOOL_AGE: + 2024-10-01: 33 + LE_ENH: + INFANT: + 2024-10-01: 40 + TODDLER: + 2024-10-01: 37 + PRESCHOOLER: + 2024-10-01: 36 + SCHOOL_AGE: + 2024-10-01: 35 +GROUP_2: + DCC_SACC: + INFANT: + 2024-10-01: 53 + TODDLER: + 2024-10-01: 50 + PRESCHOOLER: + 2024-10-01: 47 + SCHOOL_AGE: + 2024-10-01: 40 + FDC_GFDC: + INFANT: + 2024-10-01: 43 + TODDLER: + 2024-10-01: 42 + PRESCHOOLER: + 2024-10-01: 40 + SCHOOL_AGE: + 2024-10-01: 37 + LE_GC: + INFANT: + 2024-10-01: 0 + TODDLER: + 2024-10-01: 0 + PRESCHOOLER: + 2024-10-01: 35 + SCHOOL_AGE: + 2024-10-01: 30 + LE_STD: + INFANT: + 2024-10-01: 28 + TODDLER: + 2024-10-01: 27 + PRESCHOOLER: + 2024-10-01: 26 + SCHOOL_AGE: + 2024-10-01: 24 + LE_ENH: + INFANT: + 2024-10-01: 30 + TODDLER: + 2024-10-01: 29 + PRESCHOOLER: + 2024-10-01: 28 + SCHOOL_AGE: + 2024-10-01: 26 +GROUP_3: + DCC_SACC: + INFANT: + 2024-10-01: 45 + TODDLER: + 2024-10-01: 42 + PRESCHOOLER: + 2024-10-01: 39 + SCHOOL_AGE: + 2024-10-01: 39 + FDC_GFDC: + INFANT: + 2024-10-01: 39 + TODDLER: + 2024-10-01: 37 + PRESCHOOLER: + 2024-10-01: 35 + SCHOOL_AGE: + 2024-10-01: 35 + LE_GC: + INFANT: + 2024-10-01: 0 + TODDLER: + 2024-10-01: 0 + PRESCHOOLER: + 2024-10-01: 29 + SCHOOL_AGE: + 2024-10-01: 29 + LE_STD: + INFANT: + 2024-10-01: 25 + TODDLER: + 2024-10-01: 24 + PRESCHOOLER: + 2024-10-01: 23 + SCHOOL_AGE: + 2024-10-01: 23 + LE_ENH: + INFANT: + 2024-10-01: 27 + TODDLER: + 2024-10-01: 26 + PRESCHOOLER: + 2024-10-01: 25 + SCHOOL_AGE: + 2024-10-01: 25 +GROUP_4: + DCC_SACC: + INFANT: + 2024-10-01: 68 + TODDLER: + 2024-10-01: 61 + PRESCHOOLER: + 2024-10-01: 60 + SCHOOL_AGE: + 2024-10-01: 46 + FDC_GFDC: + INFANT: + 2024-10-01: 53 + TODDLER: + 2024-10-01: 47 + PRESCHOOLER: + 2024-10-01: 43 + SCHOOL_AGE: + 2024-10-01: 40 + LE_GC: + INFANT: + 2024-10-01: 0 + TODDLER: + 2024-10-01: 0 + PRESCHOOLER: + 2024-10-01: 45 + SCHOOL_AGE: + 2024-10-01: 35 + LE_STD: + INFANT: + 2024-10-01: 34 + TODDLER: + 2024-10-01: 31 + PRESCHOOLER: + 2024-10-01: 28 + SCHOOL_AGE: + 2024-10-01: 26 + LE_ENH: + INFANT: + 2024-10-01: 37 + TODDLER: + 2024-10-01: 33 + PRESCHOOLER: + 2024-10-01: 30 + SCHOOL_AGE: + 2024-10-01: 28 + +metadata: + unit: currency-USD + period: day + label: New York CCAP part-day market rates + breakdown: + - ny_ccap_county_group + - childcare_provider_type_group + - ny_ccap_age_group + reference: + - title: 24-OCFS-LCM-22 Attachment A, part-day market rates for county Groups 1-4 (file pages 15-18), effective October 1, 2024 + href: https://ocfs.ny.gov/main/policies/external/2024/lcm/24-OCFS-LCM-22.pdf#page=15 diff --git a/policyengine_us/parameters/gov/states/ny/ocfs/ccap/rates/weekly.yaml b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/rates/weekly.yaml new file mode 100644 index 00000000000..7f4a3b38052 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ny/ocfs/ccap/rates/weekly.yaml @@ -0,0 +1,205 @@ +description: New York sets these weekly market rates by county group, provider type, and child age under the Child Care Assistance Program. +# School-age child care programs share the DCC_SACC rates for the 3-5 and +# 6-12 bands only. Attachment A publishes $0 for school-age programs in both +# infant bands, which childcare_provider_type_group cannot express because it +# carries a single enum member for day care centers and school-age programs. +# The LE_GC infant and toddler cells are the $0 that Attachment A publishes, +# not a missing row: 415.9(g)(1) rates legally exempt group programs off the +# day care center schedule and OCFS publishes no under-3 rate for them. + +GROUP_1: + DCC_SACC: + INFANT: + 2024-10-01: 484 + TODDLER: + 2024-10-01: 444 + PRESCHOOLER: + 2024-10-01: 411 + SCHOOL_AGE: + 2024-10-01: 340 + FDC_GFDC: + INFANT: + 2024-10-01: 404 + TODDLER: + 2024-10-01: 400 + PRESCHOOLER: + 2024-10-01: 380 + SCHOOL_AGE: + 2024-10-01: 350 + LE_GC: + INFANT: + 2024-10-01: 0 + TODDLER: + 2024-10-01: 0 + PRESCHOOLER: + 2024-10-01: 308 + SCHOOL_AGE: + 2024-10-01: 255 + LE_STD: + INFANT: + 2024-10-01: 263 + TODDLER: + 2024-10-01: 260 + PRESCHOOLER: + 2024-10-01: 247 + SCHOOL_AGE: + 2024-10-01: 228 + LE_ENH: + INFANT: + 2024-10-01: 283 + TODDLER: + 2024-10-01: 280 + PRESCHOOLER: + 2024-10-01: 266 + SCHOOL_AGE: + 2024-10-01: 245 +GROUP_2: + DCC_SACC: + INFANT: + 2024-10-01: 385 + TODDLER: + 2024-10-01: 365 + PRESCHOOLER: + 2024-10-01: 340 + SCHOOL_AGE: + 2024-10-01: 286 + FDC_GFDC: + INFANT: + 2024-10-01: 315 + TODDLER: + 2024-10-01: 300 + PRESCHOOLER: + 2024-10-01: 285 + SCHOOL_AGE: + 2024-10-01: 270 + LE_GC: + INFANT: + 2024-10-01: 0 + TODDLER: + 2024-10-01: 0 + PRESCHOOLER: + 2024-10-01: 255 + SCHOOL_AGE: + 2024-10-01: 215 + LE_STD: + INFANT: + 2024-10-01: 205 + TODDLER: + 2024-10-01: 195 + PRESCHOOLER: + 2024-10-01: 185 + SCHOOL_AGE: + 2024-10-01: 176 + LE_ENH: + INFANT: + 2024-10-01: 221 + TODDLER: + 2024-10-01: 210 + PRESCHOOLER: + 2024-10-01: 200 + SCHOOL_AGE: + 2024-10-01: 189 +GROUP_3: + DCC_SACC: + INFANT: + 2024-10-01: 320 + TODDLER: + 2024-10-01: 300 + PRESCHOOLER: + 2024-10-01: 277 + SCHOOL_AGE: + 2024-10-01: 257 + FDC_GFDC: + INFANT: + 2024-10-01: 279 + TODDLER: + 2024-10-01: 265 + PRESCHOOLER: + 2024-10-01: 263 + SCHOOL_AGE: + 2024-10-01: 236 + LE_GC: + INFANT: + 2024-10-01: 0 + TODDLER: + 2024-10-01: 0 + PRESCHOOLER: + 2024-10-01: 208 + SCHOOL_AGE: + 2024-10-01: 193 + LE_STD: + INFANT: + 2024-10-01: 181 + TODDLER: + 2024-10-01: 172 + PRESCHOOLER: + 2024-10-01: 171 + SCHOOL_AGE: + 2024-10-01: 153 + LE_ENH: + INFANT: + 2024-10-01: 195 + TODDLER: + 2024-10-01: 186 + PRESCHOOLER: + 2024-10-01: 184 + SCHOOL_AGE: + 2024-10-01: 165 +GROUP_4: + DCC_SACC: + INFANT: + 2024-10-01: 500 + TODDLER: + 2024-10-01: 450 + PRESCHOOLER: + 2024-10-01: 439 + SCHOOL_AGE: + 2024-10-01: 325 + FDC_GFDC: + INFANT: + 2024-10-01: 400 + TODDLER: + 2024-10-01: 350 + PRESCHOOLER: + 2024-10-01: 325 + SCHOOL_AGE: + 2024-10-01: 289 + LE_GC: + INFANT: + 2024-10-01: 0 + TODDLER: + 2024-10-01: 0 + PRESCHOOLER: + 2024-10-01: 329 + SCHOOL_AGE: + 2024-10-01: 244 + LE_STD: + INFANT: + 2024-10-01: 260 + TODDLER: + 2024-10-01: 228 + PRESCHOOLER: + 2024-10-01: 211 + SCHOOL_AGE: + 2024-10-01: 188 + LE_ENH: + INFANT: + 2024-10-01: 280 + TODDLER: + 2024-10-01: 245 + PRESCHOOLER: + 2024-10-01: 228 + SCHOOL_AGE: + 2024-10-01: 202 + +metadata: + unit: currency-USD + period: week + label: New York CCAP weekly market rates + breakdown: + - ny_ccap_county_group + - childcare_provider_type_group + - ny_ccap_age_group + reference: + - title: 24-OCFS-LCM-22 Attachment A, weekly market rates for county Groups 1-4 (file pages 15-18), effective October 1, 2024 + href: https://ocfs.ny.gov/main/policies/external/2024/lcm/24-OCFS-LCM-22.pdf#page=15 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 38adce17872..cb672e7e588 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, AZ, CA, CO, CT, DE, DC, FL, GA, HI, IA, ID, IL, IN, KS, KY, LA, MA, MD, ME, MI, MN, MO, MS, MT, NC, ND, NE, NH, NJ, NM, NV, OH, OK, OR, PA, RI, SC, SD, TN, TX, UT, VA, VT, WA, WI, WV, WY + coverage: AK, AR, AL, AZ, CA, CO, CT, DE, DC, FL, GA, HI, IA, ID, IL, IN, KS, KY, LA, MA, MD, ME, MI, MN, MO, MS, MT, NC, ND, NE, NH, NJ, NM, NV, NY, OH, OK, OR, PA, RI, SC, SD, TN, TX, UT, VA, VT, WA, WI, WV, WY state_implementations: - state: AK status: complete @@ -626,6 +626,13 @@ programs: full_name: Nevada Child Care and Development Program variable: nv_ccdp parameter_prefix: gov.states.nv.dwss.ccdp + - state: NY + status: partial + name: CCAP + full_name: New York Child Care Assistance Program + variable: ny_ccap + parameter_prefix: gov.states.ny.ocfs.ccap + notes: Models New York income eligibility, market rates, and the family share, including the foster-care and child-protective-services categorical routes, the 18 NYCRR 415.1(b) age extensions for a child with special needs, and the statutory family-share exceptions. Excess periods for a sixth or seventh day of care and for hours beyond the daily maximum are priced at the applicable daily or part-day rate under 415.9(d). Household county proxies for provider county and unknown counties default to group 3, which understates rates for the New York City and downstate groups. The SPM unit stands in for the 18 NYCRR 415.1(l) child care services unit, which draws cohabiting adults, 18-to-20-year-olds and child-only units differently. Not modeled - the mandatory non-traditional-hours and homelessness payment differentials required by 18 NYCRR 415.9(f)(2)-(3) and the discretionary accreditation differential, the special-needs substituted market rate under 415.9(h)(4), the separate school-age child care rate table, safety net assistance as public assistance for the family-share exception, preventive services as distinct from protective services, public assistance in countable income (omitted to avoid a circular dependency through the TANF dependent care deduction), the guarantee of care to public-assistance families in required work activities under 415.2(a)(1), a child under court supervision, the 12-month eligibility period, the child-only assistance unit exception to the family share, and waitlist rationing when funds are unavailable - state: OR status: complete name: Oregon ERDC diff --git a/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/integration.yaml new file mode 100644 index 00000000000..7667e070c45 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/integration.yaml @@ -0,0 +1,213 @@ +- name: Case 1, group one weekly center care is capped by the market rate. + period: 2025-01 + input: + people: + person1: + age: 1 + childcare_provider_type_group: DCC_SACC + childcare_hours_per_day: 6 + childcare_days_per_week: 5 + spm_units: + spm_unit: + members: [person1] + meets_ccdf_activity_test: true + ny_ccap_countable_income: 60_000 + spm_unit_fpg: 25_750 + # 85% of SMI is the limit from 2023-10-01; $68,000 > $60,000 income. + hhs_smi: 80_000 + spm_unit_pre_subsidy_childcare_expenses: 36_000 + households: + household: + members: [person1] + county_str: NASSAU_COUNTY_NY + state_code: NY + output: + ny_ccap_income_eligible: true + ny_ccap_county_group: GROUP_1 + ny_ccap_age_group: INFANT + ny_ccap_duration_of_care: WEEKLY + # Market rate: $484/week * 52 / 12. + ny_ccap_market_rate: 484 * 52 / 12 + # Family share: ($60,000 - $25,750) * 1% / 12. + ny_ccap_family_share: (60_000 - 25_750) * 0.01 / 12 + # Expenses are $3,000/month, so the market rate binds. + ny_ccap: (484 * 52 - (60_000 - 25_750) * 0.01) / 12 + ny_child_care_subsidies: (484 * 52 - (60_000 - 25_750) * 0.01) / 12 + child_care_subsidies: (484 * 52 - (60_000 - 25_750) * 0.01) / 12 + absolute_error_margin: 0.01 + +- name: Case 2, group two daily home care is capped by actual expenses. + period: 2025-01 + input: + people: + person1: + age: 2 + childcare_provider_type_group: FDC_GFDC + childcare_hours_per_day: 7 + childcare_days_per_week: 4 + spm_units: + spm_unit: + members: [person1] + meets_ccdf_activity_test: true + ny_ccap_countable_income: 25_750 + spm_unit_fpg: 25_750 + spm_unit_pre_subsidy_childcare_expenses: 9_600 + households: + household: + members: [person1] + county_str: ALBANY_COUNTY_NY + state_code: NY + output: + ny_ccap_county_group: GROUP_2 + ny_ccap_age_group: TODDLER + ny_ccap_duration_of_care: DAILY + # Market rate: $63/day * 4 days/week * 52 / 12. + ny_ccap_market_rate: 63 * 4 * 52 / 12 + ny_ccap_family_share: 0 + # Actual expenses are $800/month and bind below the market rate. + ny_ccap: 800 + ny_child_care_subsidies: 800 + child_care_subsidies: 800 + absolute_error_margin: 0.01 + +- name: Case 3, group four part-day informal care applies the minimum share. + period: 2025-01 + input: + people: + person1: + age: 6 + childcare_provider_type_group: LE_ENH + childcare_hours_per_day: 4 + childcare_days_per_week: 3 + spm_units: + spm_unit: + members: [person1] + meets_ccdf_activity_test: true + ny_ccap_countable_income: 25_751 + spm_unit_fpg: 25_750 + spm_unit_pre_subsidy_childcare_expenses: 12_000 + households: + household: + members: [person1] + county_str: BRONX_COUNTY_NY + state_code: NY + output: + ny_ccap_county_group: GROUP_4 + ny_ccap_age_group: SCHOOL_AGE + ny_ccap_duration_of_care: PART_DAY + # Market rate: $28/part-day * 3 days/week * 52 / 12. + ny_ccap_market_rate: 28 * 3 * 52 / 12 + ny_ccap_family_share: 52 / 12 + ny_ccap: (28 * 3 * 52 - 52) / 12 + ny_child_care_subsidies: (28 * 3 * 52 - 52) / 12 + child_care_subsidies: (28 * 3 * 52 - 52) / 12 + absolute_error_margin: 0.01 + +# The activity test is the sole cause of ineligibility here: hhs_smi is set +# high enough that the income test passes, so the case would fail if the +# reason-for-care gate were dropped. +- name: Case 4, failing the activity test alone zeroes the subsidy. + period: 2025-01 + input: + people: + person1: + age: 4 + childcare_provider_type_group: DCC_SACC + childcare_hours_per_day: 6 + childcare_days_per_week: 5 + spm_units: + spm_unit: + members: [person1] + meets_ccdf_activity_test: false + ny_ccap_countable_income: 60_000 + spm_unit_fpg: 25_750 + hhs_smi: 80_000 + spm_unit_pre_subsidy_childcare_expenses: 36_000 + households: + household: + members: [person1] + county_str: ALLEGANY_COUNTY_NY + state_code: NY + output: + ny_ccap_county_group: GROUP_3 + ny_ccap_age_group: PRESCHOOLER + ny_ccap_duration_of_care: WEEKLY + ny_ccap_market_rate: 277 * 52 / 12 + # 85% of $80,000 is $68,000, above the $60,000 of countable income, so + # the reason-for-care gate is what fires. + ny_ccap_income_eligible: true + ny_ccap_eligible_child: false + ny_ccap: 0 + ny_child_care_subsidies: 0 + child_care_subsidies: 0 + absolute_error_margin: 0.01 + +# The whole chain from raw inputs: a working parent and an infant, with +# countable income, the poverty guideline and the state median income all +# derived rather than supplied. +- name: Case 5, a working parent and an infant build the benefit from raw inputs. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 40_000 + person2: + age: 1 + childcare_provider_type_group: DCC_SACC + childcare_hours_per_day: 8 + childcare_days_per_week: 5 + spm_units: + spm_unit: + members: [person1, person2] + meets_ccdf_activity_test: true + spm_unit_pre_subsidy_childcare_expenses: 30_000 + households: + household: + members: [person1, person2] + county_str: NASSAU_COUNTY_NY + state_code: NY + output: + ny_ccap_countable_income: 40_000 / 12 + spm_unit_fpg: 21_150 / 12 + # New York's $127,802 state median income for a family of four, adjusted + # to 68% for a family of two; 85% of that is far above $40,000. + hhs_smi: 86_905.36 / 12 + ny_ccap_income_eligible: true + ny_ccap_county_group: GROUP_1 + # Market rate for the infant is $484/week * 52 / 12, which binds below + # the $2,500/month of expenses. + # Family share: ($40,000 - $21,150) * 1% / 12. + ny_ccap_family_share: (40_000 - 21_150) * 0.01 / 12 + # Expenses are $2,500/month, so the $2,097.33 market rate binds. + ny_ccap: 484 * 52 / 12 - (40_000 - 21_150) * 0.01 / 12 + absolute_error_margin: 0.01 + +# ny_child_care_subsidies is the annual variable that reaches net income, so +# the twelve-month sum needs an assertion of its own. +- name: Case 6, the annual subsidy is twelve times the monthly benefit. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 40_000 + person2: + age: 1 + childcare_provider_type_group: DCC_SACC + childcare_hours_per_day: 8 + childcare_days_per_week: 5 + spm_units: + spm_unit: + members: [person1, person2] + meets_ccdf_activity_test: true + spm_unit_pre_subsidy_childcare_expenses: 30_000 + households: + household: + members: [person1, person2] + county_str: NASSAU_COUNTY_NY + state_code: NY + output: + ny_child_care_subsidies: 12 * (484 * 52 / 12 - (40_000 - 21_150) * 0.01 / 12) + child_care_subsidies: 12 * (484 * 52 / 12 - (40_000 - 21_150) * 0.01 / 12) + absolute_error_margin: 0.01 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/ny_ccap.yaml b/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/ny_ccap.yaml new file mode 100644 index 00000000000..dee25cf833b --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/ny_ccap.yaml @@ -0,0 +1,260 @@ +- name: Case 1, actual expenses cap the subsidy before family share. + period: 2025-01 + input: + people: + person1: + ny_ccap_eligible_child: true + ny_ccap_market_rate: 1_200 + childcare_hours_per_day: 8 + childcare_days_per_week: 5 + spm_units: + spm_unit: + members: [person1] + spm_unit_pre_subsidy_childcare_expenses: 12_000 + ny_ccap_family_share: 100 + households: + household: + members: [person1] + state_code: NY + output: + ny_ccap: 900 + absolute_error_margin: 0.01 + +- name: Case 2, market rates cap the subsidy before family share. + period: 2025-01 + input: + people: + person1: + ny_ccap_eligible_child: true + ny_ccap_market_rate: 800 + childcare_hours_per_day: 8 + childcare_days_per_week: 5 + person2: + ny_ccap_eligible_child: true + ny_ccap_market_rate: 700 + childcare_hours_per_day: 8 + childcare_days_per_week: 5 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 24_000 + ny_ccap_family_share: 100 + households: + household: + members: [person1, person2] + state_code: NY + output: + ny_ccap: 1_400 + absolute_error_margin: 0.01 + +- name: Case 3, ineligible children receive no subsidy. + period: 2025-01 + input: + people: + person1: + ny_ccap_eligible_child: false + ny_ccap_market_rate: 1_200 + childcare_hours_per_day: 8 + childcare_days_per_week: 5 + spm_units: + spm_unit: + members: [person1] + spm_unit_pre_subsidy_childcare_expenses: 12_000 + ny_ccap_family_share: 0 + households: + household: + members: [person1] + state_code: NY + output: + ny_ccap: 0 + absolute_error_margin: 0.01 + +- name: Case 4, family share cannot make the subsidy negative. + period: 2025-01 + input: + people: + person1: + ny_ccap_eligible_child: true + ny_ccap_market_rate: 100 + childcare_hours_per_day: 8 + childcare_days_per_week: 5 + spm_units: + spm_unit: + members: [person1] + spm_unit_pre_subsidy_childcare_expenses: 1_200 + ny_ccap_family_share: 150 + households: + household: + members: [person1] + state_code: NY + output: + ny_ccap: 0 + absolute_error_margin: 0.01 + +# 18 NYCRR 415.6(e)(3) caps payments per child, not on pooled totals. With +# $4,000 a month of expenses split evenly, child 1 is capped at its own +# $1,000 rate and child 2 draws only its $2,000 share, giving $3,000. A +# pooled cap would have paid min($4,000, $3,500) = $3,500. +- name: Case 5, the payment cap applies per child rather than to pooled totals. + period: 2025-01 + input: + people: + person1: + ny_ccap_eligible_child: true + ny_ccap_market_rate: 1_000 + childcare_hours_per_day: 8 + childcare_days_per_week: 5 + person2: + ny_ccap_eligible_child: true + ny_ccap_market_rate: 2_500 + childcare_hours_per_day: 8 + childcare_days_per_week: 5 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 48_000 + ny_ccap_family_share: 0 + households: + household: + members: [person1, person2] + state_code: NY + output: + ny_ccap: 3_000 + absolute_error_margin: 0.01 + +# A child who is not in paid care must not shrink an eligible sibling's share. +- name: Case 6, expenses prorate across children in paid care only. + period: 2025-01 + input: + people: + person1: + ny_ccap_eligible_child: true + ny_ccap_market_rate: 3_000 + childcare_hours_per_day: 8 + childcare_days_per_week: 5 + person2: + ny_ccap_eligible_child: false + ny_ccap_market_rate: 0 + childcare_hours_per_day: 0 + childcare_days_per_week: 0 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 36_000 + ny_ccap_family_share: 0 + households: + household: + members: [person1, person2] + state_code: NY + output: + ny_ccap: 3_000 + absolute_error_margin: 0.01 + +# The income gate must be exercised in the false direction: with no case +# asserting a zero benefit through the income test, deleting the test would +# leave the suite green. +- name: Case 7, income above the state median income ceiling zeroes the benefit. + period: 2025-01 + input: + people: + parent: + age: 30 + employment_income: 400_000 + childcare_hours_per_day: 0 + childcare_days_per_week: 0 + child: + age: 3 + childcare_hours_per_day: 8 + childcare_days_per_week: 5 + spm_units: + spm_unit: + members: [parent, child] + spm_unit_pre_subsidy_childcare_expenses: 24_000 + meets_ccdf_activity_test: true + households: + household: + members: [parent, child] + state_code: NY + county_str: NEW_YORK_COUNTY_NY + output: + ny_ccap_income_eligible: false + ny_ccap: 0 + absolute_error_margin: 0.01 + +# The in-care gate must bite on its own: an eligible child not actually in +# paid care draws nothing, and does not dilute a sibling's expense share. +- name: Case 8, an eligible child not in care draws no subsidy. + period: 2025-01 + input: + people: + person1: + ny_ccap_eligible_child: true + ny_ccap_market_rate: 1_200 + childcare_hours_per_day: 0 + childcare_days_per_week: 0 + spm_units: + spm_unit: + members: [person1] + spm_unit_pre_subsidy_childcare_expenses: 12_000 + ny_ccap_family_share: 0 + households: + household: + members: [person1] + state_code: NY + output: + ny_ccap: 0 + absolute_error_margin: 0.01 + +# An ineligible child who is in paid care keeps their own share of the +# expenses, so the eligible sibling is reimbursed for half of $3,000 rather +# than the whole amount. +- name: Case 9, an ineligible child in paid care keeps their expense share. + period: 2025-01 + input: + people: + person1: + ny_ccap_eligible_child: true + ny_ccap_market_rate: 3_000 + childcare_hours_per_day: 8 + childcare_days_per_week: 5 + person2: + ny_ccap_eligible_child: false + ny_ccap_market_rate: 3_000 + childcare_hours_per_day: 8 + childcare_days_per_week: 5 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 36_000 + ny_ccap_family_share: 0 + households: + household: + members: [person1, person2] + state_code: NY + output: + ny_ccap: 1_500 + absolute_error_margin: 0.01 + +# The lesser-of comparison at exact equality: expenses per child and the +# market rate both $1,000 a month. +- name: Case 10, expenses equal to the market rate are fully reimbursed. + period: 2025-01 + input: + people: + person1: + ny_ccap_eligible_child: true + ny_ccap_market_rate: 1_000 + childcare_hours_per_day: 8 + childcare_days_per_week: 5 + spm_units: + spm_unit: + members: [person1] + spm_unit_pre_subsidy_childcare_expenses: 12_000 + ny_ccap_family_share: 0 + households: + household: + members: [person1] + state_code: NY + output: + ny_ccap: 1_000 + absolute_error_margin: 0.01 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/ny_ccap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/ny_ccap_countable_income.yaml new file mode 100644 index 00000000000..a3a062693e2 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/ny_ccap_countable_income.yaml @@ -0,0 +1,294 @@ +# 18 NYCRR 404.5(b)(5) sets what New York counts. Each case adds one source +# on top of the same $10,000 of employment income so that deleting any single +# entry from countable_income/sources.yaml fails a test. + +- name: Case 1, employment income alone. + period: 2025 + input: + people: + parent: + age: 30 + employment_income: 10_000 + spm_units: + spm_unit: + members: [parent] + households: + household: + members: [parent] + state_code: NY + output: + ny_ccap_countable_income: 10_000 + +- name: Case 2, child support received is countable. + period: 2025 + input: + people: + parent: + age: 30 + employment_income: 10_000 + child_support_received: 5_000 + spm_units: + spm_unit: + members: [parent] + households: + household: + members: [parent] + state_code: NY + output: + ny_ccap_countable_income: 15_000 + +- name: Case 3, unemployment compensation is countable. + period: 2025 + input: + people: + parent: + age: 30 + employment_income: 10_000 + unemployment_compensation: 4_000 + spm_units: + spm_unit: + members: [parent] + households: + household: + members: [parent] + state_code: NY + output: + ny_ccap_countable_income: 14_000 + +- name: Case 4, workers compensation is countable. + period: 2025 + input: + people: + parent: + age: 30 + employment_income: 10_000 + workers_compensation: 3_000 + spm_units: + spm_unit: + members: [parent] + households: + household: + members: [parent] + state_code: NY + output: + ny_ccap_countable_income: 13_000 + +- name: Case 5, social security is countable. + period: 2025 + input: + people: + parent: + age: 30 + employment_income: 10_000 + social_security_retirement: 6_000 + spm_units: + spm_unit: + members: [parent] + households: + household: + members: [parent] + state_code: NY + output: + ny_ccap_countable_income: 16_000 + +# 404.5(b)(5): veterans' pensions are countable, and New York's CCDF plan +# enumerates them explicitly. +- name: Case 6, veterans benefits are countable. + period: 2025 + input: + people: + parent: + age: 30 + employment_income: 10_000 + veterans_benefits: 7_000 + spm_units: + spm_unit: + members: [parent] + households: + household: + members: [parent] + state_code: NY + output: + ny_ccap_countable_income: 17_000 + +# 404.5(b)(5)(vi) counts SSI as public assistance income; the child +# exclusion reaches only children, so an adult's SSI stays countable. +- name: Case 7, an adult's SSI is countable. + period: 2025 + input: + people: + parent: + age: 30 + employment_income: 10_000 + ssi: 1_000 + spm_units: + spm_unit: + members: [parent] + households: + household: + members: [parent] + state_code: NY + output: + ny_ccap_countable_income: 11_000 + +- name: Case 8, a child's SSI is excluded. + period: 2025 + input: + people: + parent: + age: 30 + employment_income: 10_000 + child: + age: 5 + ssi: 1_000 + spm_units: + spm_unit: + members: [parent, child] + households: + household: + members: [parent, child] + state_code: NY + output: + ny_ccap_countable_income: 10_000 + +# TANF is countable under 404.5(b)(5)(vi) but is deliberately omitted to +# avoid the CCAP-to-TANF circular dependency; this pins that decision. +- name: Case 9, TANF is not counted. + period: 2025 + input: + people: + parent: + age: 30 + employment_income: 10_000 + spm_units: + spm_unit: + members: [parent] + tanf: 6_000 + households: + household: + members: [parent] + state_code: NY + output: + ny_ccap_countable_income: 10_000 + +# 404.5(b)(6)(viii) excludes capital gains, so they must not enter through +# any composite income variable. +- name: Case 10, capital gains are excluded. + period: 2025 + input: + people: + parent: + age: 30 + employment_income: 10_000 + long_term_capital_gains: 20_000 + spm_units: + spm_unit: + members: [parent] + households: + household: + members: [parent] + state_code: NY + output: + ny_ccap_countable_income: 10_000 + +# 404.5(b)(5)(iv) counts railroad retirement checks alongside social security. +- name: Case 11, railroad benefits are countable. + period: 2025 + input: + people: + parent: + age: 30 + employment_income: 10_000 + railroad_benefits: 8_000 + spm_units: + spm_unit: + members: [parent] + households: + household: + members: [parent] + state_code: NY + output: + ny_ccap_countable_income: 18_000 + +# 404.5(b)(6)(xiii) excludes the earnings of a dependent child under 18 who +# is not responsible for the child needing care, with no inquiry to be made. +- name: Case 12, a dependent child's earnings are excluded. + period: 2025 + input: + people: + parent: + age: 30 + employment_income: 10_000 + child: + age: 16 + employment_income: 8_000 + spm_units: + spm_unit: + members: [parent, child] + households: + household: + members: [parent, child] + state_code: NY + output: + ny_ccap_countable_income: 10_000 + +# The exclusion turns on age, so an 18-year-old member's earnings count. +- name: Case 13, an eighteen year old's earnings are countable. + period: 2025 + input: + people: + parent: + age: 30 + employment_income: 10_000 + other: + age: 18 + employment_income: 8_000 + spm_units: + spm_unit: + members: [parent, other] + households: + household: + members: [parent, other] + state_code: NY + output: + ny_ccap_countable_income: 18_000 + +# The child SSI exclusion and the adult SSI inclusion must both hold in the +# same unit, which is the only case a unit-level switch would get wrong. +- name: Case 14, a mixed unit excludes only the child's SSI. + period: 2025 + input: + people: + parent: + age: 30 + employment_income: 10_000 + ssi: 1_000 + child: + age: 5 + ssi: 1_000 + spm_units: + spm_unit: + members: [parent, child] + households: + household: + members: [parent, child] + state_code: NY + output: + ny_ccap_countable_income: 11_000 + +- name: Case 15, a business loss does not inflate countable income. + period: 2025 + input: + people: + parent: + age: 30 + self_employment_income: -60_000 + spm_units: + spm_unit: + members: [parent] + households: + household: + members: [parent] + state_code: NY + output: + ny_ccap_countable_income: -60_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/ny_ccap_eligible_child.yaml b/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/ny_ccap_eligible_child.yaml new file mode 100644 index 00000000000..32f598404b1 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/ny_ccap_eligible_child.yaml @@ -0,0 +1,295 @@ +# 18 NYCRR 415.2(a)(2)(vi): foster care placements and open child protective +# or preventive services cases "must be determined eligible without regard to +# income". The NYS Register waives only the activity requirement for families +# experiencing homelessness, who stay inside the income test. + +- name: Case 1, an over-income child with no categorical route is ineligible. + period: 2025-01 + input: + people: + child: + age: 3 + spm_units: + spm_unit: + members: [child] + ny_ccap_countable_income: 400_000 + hhs_smi: 80_000 + meets_ccdf_activity_test: true + households: + household: + members: [child] + state_code: NY + output: + ny_ccap_eligible_child: false + +- name: Case 2, an over-income child in foster care is eligible without regard to income. + period: 2025-01 + input: + people: + child: + age: 3 + is_in_foster_care: true + spm_units: + spm_unit: + members: [child] + ny_ccap_countable_income: 400_000 + hhs_smi: 80_000 + meets_ccdf_activity_test: false + households: + household: + members: [child] + state_code: NY + output: + ny_ccap_eligible_child: true + +- name: Case 3, an over-income child with an open protective services case is eligible. + period: 2025-01 + input: + people: + child: + age: 3 + receives_or_needs_protective_services: true + spm_units: + spm_unit: + members: [child] + ny_ccap_countable_income: 400_000 + hhs_smi: 80_000 + meets_ccdf_activity_test: false + households: + household: + members: [child] + state_code: NY + output: + ny_ccap_eligible_child: true + +# Homelessness waives the activity requirement but not the income test. +- name: Case 4, a homeless family under the income limit is eligible without the activity test. + period: 2025-01 + input: + people: + child: + age: 3 + spm_units: + spm_unit: + members: [child] + ny_ccap_countable_income: 40_000 + hhs_smi: 80_000 + meets_ccdf_activity_test: false + households: + household: + members: [child] + state_code: NY + is_homeless: true + output: + ny_ccap_eligible_child: true + +- name: Case 5, a homeless family over the income limit remains ineligible. + period: 2025-01 + input: + people: + child: + age: 3 + spm_units: + spm_unit: + members: [child] + ny_ccap_countable_income: 400_000 + hhs_smi: 80_000 + meets_ccdf_activity_test: false + households: + household: + members: [child] + state_code: NY + is_homeless: true + output: + ny_ccap_eligible_child: false + +- name: Case 6, a child at or above the federal age limit is ineligible on every route. + period: 2025-01 + input: + people: + child: + age: 13 + is_in_foster_care: true + spm_units: + spm_unit: + members: [child] + ny_ccap_countable_income: 20_000 + hhs_smi: 80_000 + meets_ccdf_activity_test: true + households: + household: + members: [child] + state_code: NY + output: + ny_ccap_eligible_child: false + +# 415.2(a) conditions eligibility on family resources not exceeding one +# million dollars; without a case the asset test could be deleted unnoticed. +- name: Case 7, a family over the resource limit is ineligible. + period: 2025-01 + input: + people: + child: + age: 3 + spm_units: + spm_unit: + members: [child] + spm_unit_assets: 5_000_000 + ny_ccap_countable_income: 20_000 + hhs_smi: 80_000 + meets_ccdf_activity_test: true + households: + household: + members: [child] + state_code: NY + output: + ny_ccap_eligible_child: false + +- name: Case 8, a family at the resource limit remains eligible. + period: 2025-01 + input: + people: + child: + age: 3 + spm_units: + spm_unit: + members: [child] + spm_unit_assets: 1_000_000 + ny_ccap_countable_income: 20_000 + hhs_smi: 80_000 + meets_ccdf_activity_test: true + households: + household: + members: [child] + state_code: NY + output: + ny_ccap_eligible_child: true + +# 415.1(b)(2) extends eligibility to a child under 18 with special needs. +- name: Case 9, a fifteen year old with special needs is eligible. + period: 2025-01 + input: + people: + child: + age: 15 + is_disabled: true + spm_units: + spm_unit: + members: [child] + ny_ccap_countable_income: 20_000 + hhs_smi: 80_000 + meets_ccdf_activity_test: true + households: + household: + members: [child] + state_code: NY + output: + ny_ccap_eligible_child: true + +- name: Case 10, a fifteen year old without special needs is ineligible. + period: 2025-01 + input: + people: + child: + age: 15 + spm_units: + spm_unit: + members: [child] + ny_ccap_countable_income: 20_000 + hhs_smi: 80_000 + meets_ccdf_activity_test: true + households: + household: + members: [child] + state_code: NY + output: + ny_ccap_eligible_child: false + +# 415.1(b)(3) reaches a full-time secondary student under 19 with special +# needs; an eighteen year old without student status falls outside it. +- name: Case 11, an eighteen year old student with special needs is eligible. + period: 2025-01 + input: + people: + child: + age: 18 + is_disabled: true + is_full_time_student: true + spm_units: + spm_unit: + members: [child] + ny_ccap_countable_income: 20_000 + hhs_smi: 80_000 + meets_ccdf_activity_test: true + households: + household: + members: [child] + state_code: NY + output: + ny_ccap_eligible_child: true + +- name: Case 12, an eighteen year old with special needs who is not a student is ineligible. + period: 2025-01 + input: + people: + child: + age: 18 + is_disabled: true + spm_units: + spm_unit: + members: [child] + ny_ccap_countable_income: 20_000 + hhs_smi: 80_000 + meets_ccdf_activity_test: true + households: + household: + members: [child] + state_code: NY + output: + ny_ccap_eligible_child: false + +# 45 CFR 98.20(a)(1)(ii) conditions CCDF eligibility on the child's status. +- name: Case 13, an undocumented child is ineligible. + period: 2025-01 + input: + people: + child: + age: 3 + immigration_status: UNDOCUMENTED + spm_units: + spm_unit: + members: [child] + ny_ccap_countable_income: 20_000 + hhs_smi: 80_000 + meets_ccdf_activity_test: true + households: + household: + members: [child] + state_code: NY + output: + ny_ccap_eligible_child: false + +# 415.2(a)(2)(vi)(b) attaches the protective services route to the family, so +# a sibling who is not individually flagged is also eligible without regard +# to income. Both children are above the income ceiling. +- name: Case 14, a protective services case reaches every child in the family. + period: 2025-01 + input: + people: + child1: + age: 3 + receives_or_needs_protective_services: true + child2: + age: 5 + spm_units: + spm_unit: + members: [child1, child2] + ny_ccap_countable_income: 200_000 + hhs_smi: 80_000 + meets_ccdf_activity_test: false + households: + household: + members: [child1, child2] + state_code: NY + output: + ny_ccap_eligible_child: [true, true] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/ny_ccap_family_share.yaml b/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/ny_ccap_family_share.yaml new file mode 100644 index 00000000000..7c1cd9dc409 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/ny_ccap_family_share.yaml @@ -0,0 +1,87 @@ +- name: Case 1, the family share is one percent of income above FPL. + period: 2025-01 + input: + ny_ccap_countable_income: 60_000 + spm_unit_fpg: 25_750 + state_code: NY + output: + ny_ccap_family_share: (60_000 - 25_750) * 0.01 / 12 + absolute_error_margin: 0.01 + +- name: Case 2, income at FPL has no family share. + period: 2025-01 + input: + ny_ccap_countable_income: 25_750 + spm_unit_fpg: 25_750 + state_code: NY + output: + # 18 NYCRR 415.3(e)(1) exempts families with income at or below the + # state income standard; the 415.3(e)(4) $1 weekly minimum applies only + # to families required to pay an income-based share. + ny_ccap_family_share: 0 + +- name: Case 3, income just above FPL triggers the weekly minimum. + period: 2025-01 + input: + ny_ccap_countable_income: 25_751 + spm_unit_fpg: 25_750 + state_code: NY + output: + # Income-based share is ($25,751 - $25,750) * 1% = $0.01/year, so the + # 415.3(e)(4) minimum of $1/week ($52/year) binds. + ny_ccap_family_share: 52 / 12 + absolute_error_margin: 0.01 + +# 415.3(e)(4) floors the income-based share at $1 a week. The crossover sits +# at $5,200 of excess income, where 1% is exactly $52 a year. +- name: Case 4, excess income at the minimum crossover pays the minimum. + period: 2025-01 + input: + ny_ccap_countable_income: 30_950 + spm_unit_fpg: 25_750 + state_code: NY + output: + ny_ccap_family_share: 52 / 12 + absolute_error_margin: 0.01 + +- name: Case 5, excess income just below the crossover pays the minimum. + period: 2025-01 + input: + ny_ccap_countable_income: 30_949 + spm_unit_fpg: 25_750 + state_code: NY + output: + ny_ccap_family_share: 52 / 12 + absolute_error_margin: 0.01 + +- name: Case 6, excess income just above the crossover pays the calculated share. + period: 2025-01 + input: + ny_ccap_countable_income: 30_951 + spm_unit_fpg: 25_750 + state_code: NY + output: + ny_ccap_family_share: 5_201 * 0.01 / 12 + absolute_error_margin: 0.01 + +# 415.3(e)(3) applies the rate to income above the standard only, so a family +# at or below it owes nothing and the minimum does not reach them. +- name: Case 7, income at the state income standard owes no family share. + period: 2025-01 + input: + ny_ccap_countable_income: 25_750 + spm_unit_fpg: 25_750 + state_code: NY + output: + ny_ccap_family_share: 0 + absolute_error_margin: 0.01 + +- name: Case 8, negative countable income owes no family share. + period: 2025-01 + input: + ny_ccap_countable_income: -60_000 + spm_unit_fpg: 25_750 + state_code: NY + output: + ny_ccap_family_share: 0 + absolute_error_margin: 0.01 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/ny_ccap_family_share_exempt.yaml b/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/ny_ccap_family_share_exempt.yaml new file mode 100644 index 00000000000..4901d8f47dd --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/ny_ccap_family_share_exempt.yaml @@ -0,0 +1,131 @@ +# 18 NYCRR 415.3(e)(1) excepts public assistance families, families +# experiencing homelessness, families at or below 100% of the state income +# standard, children in foster care, children receiving child care as a +# protective or preventive service, and child-only units. + +- name: Case 1, a family with none of the exceptions is not exempt. + period: 2025-01 + input: + people: + child: + age: 3 + spm_units: + spm_unit: + members: [child] + households: + household: + members: [child] + state_code: NY + output: + ny_ccap_family_share_exempt: false + +- name: Case 2, a public assistance family is exempt. + period: 2025-01 + input: + people: + child: + age: 3 + spm_units: + spm_unit: + members: [child] + receives_tanf: true + households: + household: + members: [child] + state_code: NY + output: + ny_ccap_family_share_exempt: true + +- name: Case 3, a family experiencing homelessness is exempt. + period: 2025-01 + input: + people: + child: + age: 3 + spm_units: + spm_unit: + members: [child] + households: + household: + members: [child] + state_code: NY + is_homeless: true + output: + ny_ccap_family_share_exempt: true + +- name: Case 4, a child in foster care is exempt. + period: 2025-01 + input: + people: + child: + age: 3 + is_in_foster_care: true + spm_units: + spm_unit: + members: [child] + households: + household: + members: [child] + state_code: NY + output: + ny_ccap_family_share_exempt: true + +- name: Case 5, a protective services case is exempt. + period: 2025-01 + input: + people: + child: + age: 3 + receives_or_needs_protective_services: true + spm_units: + spm_unit: + members: [child] + households: + household: + members: [child] + state_code: NY + output: + ny_ccap_family_share_exempt: true + +# The exemption must zero the family share itself, including the $1 weekly +# minimum that would otherwise apply to a family above the standard. +- name: Case 6, an exempt family above the state income standard owes nothing. + period: 2025-01 + input: + people: + child: + age: 3 + spm_units: + spm_unit: + members: [child] + ny_ccap_countable_income: 60_000 + spm_unit_fpg: 25_000 + receives_tanf: true + households: + household: + members: [child] + state_code: NY + output: + ny_ccap_family_share_exempt: true + ny_ccap_family_share: 0 + absolute_error_margin: 0.01 + +- name: Case 7, the same family without the exception pays the income-based share. + period: 2025-01 + input: + people: + child: + age: 3 + spm_units: + spm_unit: + members: [child] + ny_ccap_countable_income: 60_000 + spm_unit_fpg: 25_000 + households: + household: + members: [child] + state_code: NY + output: + ny_ccap_family_share_exempt: false + ny_ccap_family_share: (60_000 - 25_000) * 0.01 / 12 + absolute_error_margin: 0.01 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/ny_ccap_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/ny_ccap_income_eligible.yaml new file mode 100644 index 00000000000..886034a33fb --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/ny_ccap_income_eligible.yaml @@ -0,0 +1,42 @@ +# Social Services Law 410-w caps income eligibility at 85% of the state +# median income, the sole ceiling since October 1, 2023. + +- name: Case 1, income at 85 percent of the state median income is eligible. + period: 2025-01 + input: + ny_ccap_countable_income: 68_000 + hhs_smi: 80_000 + state_code: NY + output: + ny_ccap_income_eligible: true + +- name: Case 2, income above 85 percent of the state median income is ineligible. + period: 2025-01 + input: + ny_ccap_countable_income: 68_001 + hhs_smi: 80_000 + state_code: NY + output: + ny_ccap_income_eligible: false + +# The state income standard limit lapsed on 2023-10-01, so a family far above +# a multiple of the poverty guideline remains eligible while under 85% of the +# state median income. +- name: Case 3, the poverty guideline plays no part in the income test. + period: 2025-01 + input: + ny_ccap_countable_income: 68_000 + spm_unit_fpg: 10_000 + hhs_smi: 80_000 + state_code: NY + output: + ny_ccap_income_eligible: true + +- name: Case 4, income below 85 percent of the state median income is eligible. + period: 2025-01 + input: + ny_ccap_countable_income: 67_999 + hhs_smi: 80_000 + state_code: NY + output: + ny_ccap_income_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/rates/ny_ccap_age_group.yaml b/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/rates/ny_ccap_age_group.yaml new file mode 100644 index 00000000000..5c3feb1bdf6 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/rates/ny_ccap_age_group.yaml @@ -0,0 +1,130 @@ +- name: Case 1, center care below 18 months uses the infant rate. + period: 2025-01 + input: + age: 1.49 + childcare_provider_type_group: DCC_SACC + state_code: NY + output: + ny_ccap_age_group: INFANT + +- name: Case 2, center care at 18 months uses the toddler rate. + period: 2025-01 + input: + age: 1.5 + childcare_provider_type_group: DCC_SACC + state_code: NY + output: + ny_ccap_age_group: TODDLER + +- name: Case 3, legally exempt group care uses center age groups. + period: 2025-01 + input: + age: 2 + childcare_provider_type_group: LE_GC + state_code: NY + output: + ny_ccap_age_group: TODDLER + +- name: Case 4, family day care below age two uses the infant rate. + period: 2025-01 + input: + age: 1.99 + childcare_provider_type_group: FDC_GFDC + state_code: NY + output: + ny_ccap_age_group: INFANT + +- name: Case 5, standard informal care at age two uses the toddler rate. + period: 2025-01 + input: + age: 2 + childcare_provider_type_group: LE_STD + state_code: NY + output: + ny_ccap_age_group: TODDLER + +- name: Case 6, enhanced informal care at age three uses the preschool rate. + period: 2025-01 + input: + age: 3 + childcare_provider_type_group: LE_ENH + state_code: NY + output: + ny_ccap_age_group: PRESCHOOLER + +- name: Case 7, child at age six uses the school-age rate. + period: 2025-01 + input: + age: 6 + childcare_provider_type_group: DCC_SACC + state_code: NY + output: + ny_ccap_age_group: SCHOOL_AGE + +# 24-OCFS-LCM-22 §III.3 puts legally exempt group child care on the +# center-based age bands, where the infant ceiling is 1.5 years, while +# family day care uses the home-based bands with a 2-year ceiling. At age +# 1.75 the two sets disagree, so these paired cases make the LE_GC branch +# functional: removing it from ny_ccap_age_group flips Case 8. +- name: Case 8, legally exempt group care uses the center infant ceiling. + period: 2025-01 + input: + age: 1.75 + childcare_provider_type_group: LE_GC + state_code: NY + output: + ny_ccap_age_group: TODDLER + +- name: Case 9, day care centers use the center infant ceiling. + period: 2025-01 + input: + age: 1.75 + childcare_provider_type_group: DCC_SACC + state_code: NY + output: + ny_ccap_age_group: TODDLER + +- name: Case 10, family day care uses the home infant ceiling at the same age. + period: 2025-01 + input: + age: 1.75 + childcare_provider_type_group: FDC_GFDC + state_code: NY + output: + ny_ccap_age_group: INFANT + +- name: Case 11, legally exempt standard care uses the home infant ceiling. + period: 2025-01 + input: + age: 1.75 + childcare_provider_type_group: LE_STD + state_code: NY + output: + ny_ccap_age_group: INFANT + +- name: Case 12, a newborn is an infant under both provider ladders. + period: 2025-01 + input: + age: 0 + childcare_provider_type_group: DCC_SACC + state_code: NY + output: + ny_ccap_age_group: INFANT + +- name: Case 13, a child just below three is a toddler. + period: 2025-01 + input: + age: 2.99 + childcare_provider_type_group: DCC_SACC + state_code: NY + output: + ny_ccap_age_group: TODDLER + +- name: Case 14, a child just below six is a preschooler. + period: 2025-01 + input: + age: 5.99 + childcare_provider_type_group: DCC_SACC + state_code: NY + output: + ny_ccap_age_group: PRESCHOOLER diff --git a/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/rates/ny_ccap_county_group.yaml b/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/rates/ny_ccap_county_group.yaml new file mode 100644 index 00000000000..6dc38f36e20 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/rates/ny_ccap_county_group.yaml @@ -0,0 +1,123 @@ +- name: Case 1, Nassau is in group one. + period: 2025-01 + input: + county_str: NASSAU_COUNTY_NY + state_code: NY + output: + ny_ccap_county_group: GROUP_1 + +- name: Case 2, Albany is in group two. + period: 2025-01 + input: + county_str: ALBANY_COUNTY_NY + state_code: NY + output: + ny_ccap_county_group: GROUP_2 + +- name: Case 3, Allegany is in group three. + period: 2025-01 + input: + county_str: ALLEGANY_COUNTY_NY + state_code: NY + output: + ny_ccap_county_group: GROUP_3 + +- name: Case 4, Bronx is in group four. + period: 2025-01 + input: + county_str: BRONX_COUNTY_NY + state_code: NY + output: + ny_ccap_county_group: GROUP_4 + +- name: Case 5, unknown county defaults to group three. + period: 2025-01 + input: + county_str: UNKNOWN + state_code: NY + output: + ny_ccap_county_group: GROUP_3 + +- name: Case 6, mixed counties and an unknown county vectorize. + period: 2025-01 + input: + people: + person1: {} + person2: {} + person3: {} + households: + household1: + members: [person1] + county_str: NASSAU_COUNTY_NY + state_code: NY + household2: + members: [person2] + county_str: BRONX_COUNTY_NY + state_code: NY + household3: + members: [person3] + county_str: UNKNOWN + state_code: NY + output: + ny_ccap_county_group: [GROUP_1, GROUP_4, GROUP_3] + +# Groups 1 and 4 carry the highest rates and hold most of New York's child +# population, and an omitted county falls silently into the lowest-rate +# group 3, so every member of both groups is named. +- name: Case 7, every group one and group four county resolves correctly. + period: 2025-01 + input: + people: + person1: {} + person2: {} + person3: {} + person4: {} + person5: {} + person6: {} + person7: {} + person8: {} + households: + household1: + members: [person1] + county_str: PUTNAM_COUNTY_NY + state_code: NY + household2: + members: [person2] + county_str: ROCKLAND_COUNTY_NY + state_code: NY + household3: + members: [person3] + county_str: SUFFOLK_COUNTY_NY + state_code: NY + household4: + members: [person4] + county_str: WESTCHESTER_COUNTY_NY + state_code: NY + household5: + members: [person5] + county_str: KINGS_COUNTY_NY + state_code: NY + household6: + members: [person6] + county_str: NEW_YORK_COUNTY_NY + state_code: NY + household7: + members: [person7] + county_str: QUEENS_COUNTY_NY + state_code: NY + household8: + members: [person8] + county_str: RICHMOND_COUNTY_NY + state_code: NY + output: + ny_ccap_county_group: + [ + GROUP_1, + GROUP_1, + GROUP_1, + GROUP_1, + GROUP_4, + GROUP_4, + GROUP_4, + GROUP_4, + ] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/rates/ny_ccap_duration_of_care.yaml b/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/rates/ny_ccap_duration_of_care.yaml new file mode 100644 index 00000000000..a29e708d286 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/rates/ny_ccap_duration_of_care.yaml @@ -0,0 +1,110 @@ +- name: Case 1, care at the weekly threshold uses the weekly rate. + period: 2025-01 + input: + childcare_hours_per_day: 6 + childcare_days_per_week: 5 + state_code: NY + output: + ny_ccap_duration_of_care: WEEKLY + +- name: Case 2, care below 30 weekly hours and at six daily hours uses the daily rate. + period: 2025-01 + input: + childcare_hours_per_day: 6 + childcare_days_per_week: 4 + state_code: NY + output: + ny_ccap_duration_of_care: DAILY + +- name: Case 3, care below six daily hours uses the part-day rate. + period: 2025-01 + input: + childcare_hours_per_day: 2 + childcare_days_per_week: 5 + state_code: NY + output: + ny_ccap_duration_of_care: PART_DAY + +- name: Case 4, extended daily care retains the daily base category. + period: 2025-01 + input: + childcare_hours_per_day: 12 + childcare_days_per_week: 2 + state_code: NY + output: + ny_ccap_duration_of_care: DAILY + +# 18 NYCRR 415.9(c) makes the part-day rate mandatory below six hours per +# day whatever the weekly total, and 415.9(a) measures the 30-hour weekly +# threshold over five or fewer days. Five hours across six days fails both, +# so it is six part-day periods, not a weekly rate. +- name: Case 5, care across six days below six daily hours uses the part-day rate. + period: 2025-01 + input: + childcare_hours_per_day: 5 + childcare_days_per_week: 6 + state_code: NY + output: + ny_ccap_duration_of_care: PART_DAY + +# The five-day core reaches 30 hours and each day is at the daily minimum, so +# the week is weekly; the sixth day earns an additional period in +# ny_ccap_market_rate. +- name: Case 6, six-hour care over six days is weekly on its five-day core. + period: 2025-01 + input: + childcare_hours_per_day: 6 + childcare_days_per_week: 6 + state_code: NY + output: + ny_ccap_duration_of_care: WEEKLY + +# 415.9(a) requires both limbs: 30 weekly hours AND at least the daily +# minimum. Four hours across seven days reaches 28 hours over a five-day +# core, and is under six hours a day, so it stays part-day. +- name: Case 7, care below six daily hours across seven days stays part-day. + period: 2025-01 + input: + childcare_hours_per_day: 4 + childcare_days_per_week: 7 + state_code: NY + output: + ny_ccap_duration_of_care: PART_DAY + +- name: Case 8, care just below six daily hours over five days is part-day. + period: 2025-01 + input: + childcare_hours_per_day: 5.99 + childcare_days_per_week: 5 + state_code: NY + output: + ny_ccap_duration_of_care: PART_DAY + +# 28 weekly hours misses the weekly threshold while each day clears the daily +# minimum, so the daily rate applies. +- name: Case 9, care above the daily minimum below thirty weekly hours is daily. + period: 2025-01 + input: + childcare_hours_per_day: 7 + childcare_days_per_week: 4 + state_code: NY + output: + ny_ccap_duration_of_care: DAILY + +- name: Case 10, care above the daily maximum over two days retains the daily category. + period: 2025-01 + input: + childcare_hours_per_day: 14 + childcare_days_per_week: 2 + state_code: NY + output: + ny_ccap_duration_of_care: DAILY + +- name: Case 11, care just below the daily maximum over two days is daily. + period: 2025-01 + input: + childcare_hours_per_day: 11.99 + childcare_days_per_week: 2 + state_code: NY + output: + ny_ccap_duration_of_care: DAILY diff --git a/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/rates/ny_ccap_market_rate.yaml b/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/rates/ny_ccap_market_rate.yaml new file mode 100644 index 00000000000..bfd7c10e020 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/rates/ny_ccap_market_rate.yaml @@ -0,0 +1,167 @@ +- name: Case 1, group one center infant weekly rate. + period: 2025-01 + input: + ny_ccap_county_group: GROUP_1 + childcare_provider_type_group: DCC_SACC + ny_ccap_age_group: INFANT + ny_ccap_duration_of_care: WEEKLY + state_code: NY + output: + ny_ccap_market_rate: 484 * 52 / 12 + absolute_error_margin: 0.01 + +- name: Case 2, group two family day care toddler daily rate. + period: 2025-01 + input: + ny_ccap_county_group: GROUP_2 + childcare_provider_type_group: FDC_GFDC + ny_ccap_age_group: TODDLER + ny_ccap_duration_of_care: DAILY + childcare_days_per_week: 4 + state_code: NY + output: + ny_ccap_market_rate: 63 * 4 * 52 / 12 + absolute_error_margin: 0.01 + +- name: Case 3, group three legally exempt group preschool part-day rate. + period: 2025-01 + input: + ny_ccap_county_group: GROUP_3 + childcare_provider_type_group: LE_GC + ny_ccap_age_group: PRESCHOOLER + ny_ccap_duration_of_care: PART_DAY + childcare_days_per_week: 3 + state_code: NY + output: + ny_ccap_market_rate: 29 * 3 * 52 / 12 + absolute_error_margin: 0.01 + +- name: Case 4, group four standard informal school-age weekly rate. + period: 2025-01 + input: + ny_ccap_county_group: GROUP_4 + childcare_provider_type_group: LE_STD + ny_ccap_age_group: SCHOOL_AGE + ny_ccap_duration_of_care: WEEKLY + state_code: NY + output: + ny_ccap_market_rate: 188 * 52 / 12 + absolute_error_margin: 0.01 + +- name: Case 5, group one enhanced informal preschool daily rate. + period: 2025-01 + input: + ny_ccap_county_group: GROUP_1 + childcare_provider_type_group: LE_ENH + ny_ccap_age_group: PRESCHOOLER + ny_ccap_duration_of_care: DAILY + childcare_days_per_week: 5 + state_code: NY + output: + ny_ccap_market_rate: 55 * 5 * 52 / 12 + absolute_error_margin: 0.01 + +# 18 NYCRR 415.9(d) and 24-OCFS-LCM-22 sec. III.5: a sixth day earns an +# additional period priced at the rate for the time that day covers. Six +# hours is at the daily minimum, so the sixth day draws the daily rate. +- name: Case 6, a sixth day of full-day care adds one daily rate. + period: 2025-01 + input: + age: 1 + childcare_provider_type_group: DCC_SACC + childcare_hours_per_day: 6 + childcare_days_per_week: 6 + county_str: NASSAU_COUNTY_NY + state_code: NY + output: + ny_ccap_duration_of_care: WEEKLY + ny_ccap_market_rate: (484 + 97) * 52 / 12 + absolute_error_margin: 0.01 + +# 415.9(c): below six hours a day the part-day rate is mandatory whatever the +# weekly total, so five hours across six days is six part-day periods rather +# than a weekly rate plus an excess day. +- name: Case 7, six short days are priced as six part-day periods. + period: 2025-01 + input: + age: 1 + childcare_provider_type_group: DCC_SACC + childcare_hours_per_day: 5 + childcare_days_per_week: 6 + county_str: NASSAU_COUNTY_NY + state_code: NY + output: + ny_ccap_duration_of_care: PART_DAY + ny_ccap_market_rate: 65 * 6 * 52 / 12 + absolute_error_margin: 0.01 + +# 24-OCFS-LCM-22 sec. III.5 worked example: 16 hours a day Monday through +# Friday is one weekly market rate plus five part-day rates, because the four +# hours past the daily maximum fall below the daily minimum. +- name: Case 8, hours past the daily maximum add a part-day period each day. + period: 2025-01 + input: + age: 1 + childcare_provider_type_group: DCC_SACC + childcare_hours_per_day: 16 + childcare_days_per_week: 5 + county_str: NASSAU_COUNTY_NY + state_code: NY + output: + ny_ccap_duration_of_care: WEEKLY + ny_ccap_market_rate: (484 + 5 * 65) * 52 / 12 + absolute_error_margin: 0.01 + +# The highest-value cell in the schedule, checked across all three duration +# tables at one county group and age group (Cases 9-11). +- name: Case 9, group four center infant weekly rate. + period: 2025-01 + input: + ny_ccap_county_group: GROUP_4 + childcare_provider_type_group: DCC_SACC + ny_ccap_age_group: INFANT + ny_ccap_duration_of_care: WEEKLY + state_code: NY + output: + ny_ccap_market_rate: 500 * 52 / 12 + absolute_error_margin: 0.01 + +- name: Case 10, group four center infant daily rate. + period: 2025-01 + input: + ny_ccap_county_group: GROUP_4 + childcare_provider_type_group: DCC_SACC + ny_ccap_age_group: INFANT + ny_ccap_duration_of_care: DAILY + childcare_days_per_week: 1 + state_code: NY + output: + ny_ccap_market_rate: 102 * 52 / 12 + absolute_error_margin: 0.01 + +- name: Case 11, group four center infant part-day rate. + period: 2025-01 + input: + ny_ccap_county_group: GROUP_4 + childcare_provider_type_group: DCC_SACC + ny_ccap_age_group: INFANT + ny_ccap_duration_of_care: PART_DAY + childcare_days_per_week: 1 + state_code: NY + output: + ny_ccap_market_rate: 68 * 52 / 12 + absolute_error_margin: 0.01 + +# Attachment A publishes $0 for legally exempt group care under age 3, so an +# otherwise eligible infant at such a provider draws no rate. +- name: Case 12, legally exempt group infant care has a zero rate. + period: 2025-01 + input: + ny_ccap_county_group: GROUP_1 + childcare_provider_type_group: LE_GC + ny_ccap_age_group: INFANT + ny_ccap_duration_of_care: WEEKLY + state_code: NY + output: + ny_ccap_market_rate: 0 + absolute_error_margin: 0.01 diff --git a/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap.py b/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap.py new file mode 100644 index 00000000000..766beea851c --- /dev/null +++ b/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap.py @@ -0,0 +1,42 @@ +from policyengine_us.model_api import * + + +class ny_ccap(Variable): + value_type = float + entity = SPMUnit + definition_period = MONTH + label = "New York Child Care Assistance Program benefit" + unit = USD + defined_for = StateCode.NY + reference = ( + "https://ocfs.ny.gov/programs/childcare/regulations/415-Child-Care-Services.pdf#page=39", + "https://ocfs.ny.gov/main/policies/external/2024/lcm/24-OCFS-LCM-22.pdf#page=3", + ) + + def formula(spm_unit, period, parameters): + person = spm_unit.members + market_rate = person("ny_ccap_market_rate", period) + # ny_ccap_eligible_child carries New York's income test as well as the + # categorical routes that waive it, so no separate income gate is + # applied here. + eligible = person("ny_ccap_eligible_child", period) + in_care = person("childcare_hours_per_day", period.this_year) > 0 + counted = eligible & in_care + # The unit's expenses are shared across every child in paid care, so + # an ineligible child's share stays with that child rather than + # raising an eligible sibling against its own rate ceiling. + children_in_care = spm_unit.sum(in_care) + total_expenses = spm_unit("spm_unit_pre_subsidy_childcare_expenses", period) + per_child_expenses = total_expenses / max_(children_in_care, 1) + # 18 NYCRR 415.6(e)(1) and (e)(3): payments do not exceed the actual + # cost of care, and payments per child do not exceed the applicable + # rate for the type of provider used and the age of the child. Capping + # per child rather than on pooled totals stops one child's unused rate + # headroom from absorbing a sibling's above-rate expenses. + reimbursable_care = spm_unit.sum( + min_(spm_unit.project(per_child_expenses), market_rate) * counted + ) + # 415.3(e)(5): one family share per family regardless of the number of + # children receiving care, so it is subtracted once from the total. + family_share = spm_unit("ny_ccap_family_share", period) + return max_(reimbursable_care - family_share, 0) diff --git a/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap_activity_eligible.py b/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap_activity_eligible.py new file mode 100644 index 00000000000..b4505011328 --- /dev/null +++ b/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap_activity_eligible.py @@ -0,0 +1,40 @@ +from policyengine_us.model_api import * + + +class ny_ccap_activity_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for New York CCAP based on the reason for care" + definition_period = MONTH + defined_for = StateCode.NY + documentation = ( + "18 NYCRR 415.2(a)(2)(iv)(a) serves a family whose caretakers are " + "engaged in work, and the section's opening paragraph requires each " + "caretaker of a two-caretaker family to meet one of the criteria. " + "415.1(o)(1)(i) defines engaged in work by a minimum weekly hours " + "figure the Office sets outside Part 415, so any hours count here. " + "Educational and vocational activities under 415.2(a)(2)(iv)(d) are " + "read from full-time student status, and 415.2(a)(1)(i) and (iii) " + "guarantee care to a public assistance family whose caretaker is in " + "a required work activity. The remaining pathways — job search, the " + "individual training programs, domestic violence services, substance " + "abuse treatment, and a caretaker who is incapacitated or has family " + "duties away from home — are represented by the " + "meets_ccdf_activity_test input." + ) + reference = "https://ocfs.ny.gov/programs/childcare/regulations/415-Child-Care-Services.pdf#page=13" + + def formula(spm_unit, period, parameters): + person = spm_unit.members + is_caretaker = person("is_tax_unit_head_or_spouse", period.this_year) + hours = person("weekly_hours_worked_before_lsr", period.this_year) + in_activity = (hours > 0) | person("is_full_time_student", period.this_year) + has_caretaker = spm_unit.sum(is_caretaker) > 0 + every_caretaker_active = spm_unit.sum(is_caretaker & ~in_activity) == 0 + work_eligible = has_caretaker & every_caretaker_active + # is_tanf_enrolled reflects reported enrollment rather than the + # computed tanf amount, so reading it does not close the + # CCAP -> TANF -> child care expenses circular dependency. + public_assistance = spm_unit("is_tanf_enrolled", period) + fallback = spm_unit("meets_ccdf_activity_test", period.this_year) + return work_eligible | public_assistance | fallback diff --git a/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap_age_eligible.py b/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap_age_eligible.py new file mode 100644 index 00000000000..21b646ba9c9 --- /dev/null +++ b/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap_age_eligible.py @@ -0,0 +1,31 @@ +from policyengine_us.model_api import * + + +class ny_ccap_age_eligible(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "Age eligible for the New York Child Care Assistance Program" + defined_for = StateCode.NY + documentation = ( + "New York's age test, which replaces the flat federal under-13 limit. " + "18 NYCRR 415.1(b) extends eligibility to a child under 18 with " + "special needs, and to a full-time secondary student under 19 with " + "special needs. 415.1(c) defines a child with special needs by " + "conditions requiring special education or related services, for " + "which is_disabled is the closest available variable. The parallel " + "route for a child under court supervision is not modeled because " + "PolicyEngine has no variable identifying court supervision." + ) + reference = "https://ocfs.ny.gov/programs/childcare/regulations/415-Child-Care-Services.pdf#page=2" + + def formula(person, period, parameters): + p = parameters(period).gov.states.ny.ocfs.ccap.eligibility.age_limit + age = person("age", period) + special_needs = person("is_disabled", period) + student = person("is_full_time_student", period) + return ( + (age < p.base) + | (special_needs & (age < p.special_needs)) + | (special_needs & student & (age < p.special_needs_student)) + ) diff --git a/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap_countable_income.py b/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap_countable_income.py new file mode 100644 index 00000000000..694af81b98d --- /dev/null +++ b/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap_countable_income.py @@ -0,0 +1,47 @@ +from policyengine_us.model_api import * + + +class ny_ccap_countable_income(Variable): + value_type = float + entity = SPMUnit + label = "New York CCAP countable income" + definition_period = YEAR + unit = USD + defined_for = StateCode.NY + documentation = ( + "Income counted for New York Child Care Assistance Program income " + "eligibility and the family share. New York defines countable income " + "in 18 NYCRR 404.5(b)(5) rather than in Part 415, which contains no " + "income-composition rule. Public assistance is countable under " + "404.5(b)(5)(vi) but is omitted here because counting it creates a " + "CCAP-to-TANF circular dependency through the TANF dependent care " + "deduction; see countable_income/sources.yaml. 404.5(b)(5) measures " + "income over the 415.1(l) child care services unit, which splits " + "cohabiting adults without a common child into separate units, treats " + "an 18-year-old as an adult outside the parent's unit, and reduces to " + "the children alone when they live with no parent; the SPM unit used " + "here merges those cases. Defined annually so the monthly consumers " + "read it with the bare period and Core divides it." + ) + reference = ( + "https://ocfs.ny.gov/programs/childcare/regulations/404-Eligibility.pdf#page=10", + "https://ocfs.ny.gov/main/policies/external/2023/adm/23-OCFS-ADM-18.pdf#page=4", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ny.ocfs.ccap.income.countable_income + countable = add(spm_unit, period, p.sources) + person = spm_unit.members + is_child = person("is_child", period) + # ssi is monthly, so add() sums it across the year. + # 404.5(b)(6)(xxi) excludes the SSI of any child in the unit; an + # adult's SSI stays countable. + adult_ssi = where(is_child, 0, add(person, period, ["ssi"])) + # 404.5(b)(6)(xiii) excludes the earnings of a dependent child under + # 18 who is not legally responsible for the child needing care, and + # directs that no inquiry be made into them. is_child is age under 18. + excluded_earner = is_child & ~person("is_parent", period) + excluded_earnings = where( + excluded_earner, add(person, period, p.earned_sources), 0 + ) + return countable + spm_unit.sum(adult_ssi - excluded_earnings) diff --git a/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap_eligible_child.py b/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap_eligible_child.py new file mode 100644 index 00000000000..b1e44cbeee9 --- /dev/null +++ b/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap_eligible_child.py @@ -0,0 +1,56 @@ +from policyengine_us.model_api import * + + +class ny_ccap_eligible_child(Variable): + value_type = bool + entity = Person + definition_period = MONTH + label = "Eligible child for the New York Child Care Assistance Program" + defined_for = StateCode.NY + documentation = ( + "New York's eligibility test, which replaces the federal " + "is_ccdf_eligible for CCAP. It keeps the federal asset and " + "immigration tests, applies New York's own age limit and income " + "limit, and adds the two categorical routes New York law requires: " + "foster care and open child protective or preventive services cases " + "are eligible without regard to income, and families experiencing " + "homelessness are served without further activity requirements while " + "remaining subject to the income test. The protective services route " + "is family-level and the foster care route is child-level, following " + "415.2(a)(2)(vi)(a)-(b)." + ) + reference = ( + "https://ocfs.ny.gov/programs/childcare/regulations/415-Child-Care-Services.pdf#page=15", + "https://ocfs.ny.gov/main/policies/external/2023/adm/23-OCFS-ADM-18.pdf#page=9", + ) + + def formula(person, period, parameters): + spm_unit = person.spm_unit + age_eligible = person("ny_ccap_age_eligible", period.this_year) + asset_eligible = spm_unit("is_ccdf_asset_eligible", period.this_year) + immigration_eligible = person( + "is_ccdf_immigration_eligible_child", period.this_year + ) + income_eligible = spm_unit("ny_ccap_income_eligible", period) + meets_activity_test = spm_unit("ny_ccap_activity_eligible", period) + protective_services = spm_unit( + "ny_ccap_protective_services_case", period.this_year + ) + in_foster_care = person("is_in_foster_care", period) + homeless = spm_unit.household("is_homeless", period.this_year) + # 415.2(a)(2)(vi) waives the income test for foster care placements + # and open child protective or preventive services cases. + categorically_eligible = in_foster_care | protective_services + # Reason for care mirrors the federal test, which already accepts + # protective services in place of the activity test, and adds the + # foster care and homelessness routes. + reason_for_care_eligible = ( + meets_activity_test | protective_services | in_foster_care | homeless + ) + return ( + age_eligible + & asset_eligible + & immigration_eligible + & reason_for_care_eligible + & (income_eligible | categorically_eligible) + ) diff --git a/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap_family_share.py b/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap_family_share.py new file mode 100644 index 00000000000..39d5cd89ec4 --- /dev/null +++ b/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap_family_share.py @@ -0,0 +1,36 @@ +from policyengine_us.model_api import * + + +class ny_ccap_family_share(Variable): + value_type = float + entity = SPMUnit + definition_period = MONTH + label = "New York CCAP monthly family share" + unit = USD + defined_for = StateCode.NY + reference = ( + "https://ocfs.ny.gov/programs/childcare/regulations/415-Child-Care-Services.pdf#page=19", + "https://ocfs.ny.gov/main/policies/external/2023/adm/23-OCFS-ADM-18.pdf#page=3", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ny.ocfs.ccap + income = spm_unit("ny_ccap_countable_income", period) + # 18 NYCRR 415.1(k) defines the state income standard as the most + # recent federal income official poverty line, so spm_unit_fpg is the + # standard itself rather than a proxy for it. + state_income_standard = spm_unit("spm_unit_fpg", period) + # 415.3(e)(3) applies the rate to income above the standard, so a + # family at or below it has a zero income-based share, and the + # 415.3(e)(4) minimum reaches only a family "required to pay an + # income-based portion of a family share". The categorical exceptions + # in 415.3(e)(1) are applied through ny_ccap_family_share_exempt. + calculated_share = (income - state_income_standard) * p.family_share_rate + minimum_share = p.minimum_weekly_family_share * (WEEKS_IN_YEAR / MONTHS_IN_YEAR) + income_based_share = where( + income > state_income_standard, + max_(calculated_share, minimum_share), + 0, + ) + exempt = spm_unit("ny_ccap_family_share_exempt", period) + return where(exempt, 0, income_based_share) diff --git a/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap_family_share_exempt.py b/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap_family_share_exempt.py new file mode 100644 index 00000000000..e2153db317d --- /dev/null +++ b/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap_family_share_exempt.py @@ -0,0 +1,41 @@ +from policyengine_us.model_api import * + + +class ny_ccap_family_share_exempt(Variable): + value_type = bool + entity = SPMUnit + definition_period = MONTH + label = "Exempt from the New York CCAP family share" + defined_for = StateCode.NY + documentation = ( + "Categorical exceptions to the New York Child Care Assistance " + "Program family share under 18 NYCRR 415.3(e)(1). Three of the " + "exceptions are narrower here than in the regulation. New York " + "counts both family assistance and safety net assistance as public " + "assistance, but PolicyEngine has no safety net assistance variable, " + "so only family assistance enrollment is read. The regulation covers " + "a child receiving preventive as well as protective services, and " + "PolicyEngine has no preventive services variable. The exception for " + "a child care services unit comprised of the eligible children only " + "is not modeled because PolicyEngine has no variable identifying a " + "child-only assistance unit. The regulation has no income-based " + "exception; a family at or below the state income standard owes " + "nothing because 415.3(e)(3) computes their share as zero, which " + "ny_ccap_family_share handles." + ) + reference = ( + "https://ocfs.ny.gov/programs/childcare/regulations/415-Child-Care-Services.pdf#page=18", + "https://ocfs.ny.gov/main/policies/external/2023/adm/23-OCFS-ADM-18.pdf#page=3", + ) + + def formula(spm_unit, period, parameters): + # is_tanf_enrolled reflects reported enrollment rather than the + # computed tanf amount, so reading it does not close the + # CCAP -> TANF -> child care expenses circular dependency. + public_assistance = spm_unit("is_tanf_enrolled", period) + homeless = spm_unit.household("is_homeless", period.this_year) + foster_care = add(spm_unit, period, ["is_in_foster_care"]) > 0 + protective_services = spm_unit( + "ny_ccap_protective_services_case", period.this_year + ) + return public_assistance | homeless | foster_care | protective_services diff --git a/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap_income_eligible.py b/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap_income_eligible.py new file mode 100644 index 00000000000..b4297a3b44c --- /dev/null +++ b/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap_income_eligible.py @@ -0,0 +1,31 @@ +from policyengine_us.model_api import * + + +class ny_ccap_income_eligible(Variable): + value_type = bool + entity = SPMUnit + definition_period = MONTH + label = "Income eligible for the New York Child Care Assistance Program" + defined_for = StateCode.NY + documentation = ( + "Social Services Law 410-w caps eligibility at 85 percent of the " + "state median income, the sole ceiling since the October 1, 2023 " + "statutory revisions replaced the state income standard limit. OCFS " + "publishes its state median income figures for a June 1 to May 31 " + "year, while hhs_smi is keyed to the federal October 1 series and " + "resolved annually, so the ceiling here lags New York's own table " + "for the June to December months of each year." + ) + reference = ( + "https://www.nysenate.gov/legislation/laws/SOS/410-W", + "https://dos.ny.gov/system/files/documents/2024/05/050124.pdf#page=12", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ny.ocfs.ccap.income + income = spm_unit("ny_ccap_countable_income", period) + # Social Services Law 410-w caps eligibility at 85 percent of the + # state median income, the sole ceiling since the October 1, 2023 + # statutory revisions replaced the state income standard limit. + smi_limit = spm_unit("hhs_smi", period) * p.income_limit_smi_rate + return income <= smi_limit diff --git a/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap_protective_services_case.py b/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap_protective_services_case.py new file mode 100644 index 00000000000..eb7abcd01a9 --- /dev/null +++ b/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_ccap_protective_services_case.py @@ -0,0 +1,20 @@ +from policyengine_us.model_api import * + + +class ny_ccap_protective_services_case(Variable): + value_type = bool + entity = SPMUnit + definition_period = YEAR + label = "New York CCAP open protective or preventive services case" + defined_for = StateCode.NY + documentation = ( + "18 NYCRR 415.2(a)(2)(vi)(b) attaches the protective and preventive " + "services route to the family rather than to the individual child, so " + "one flagged member qualifies the whole unit. The preventive-services " + "half of the rule is not separately modeled because PolicyEngine has " + "no preventive-services variable." + ) + reference = "https://ocfs.ny.gov/programs/childcare/regulations/415-Child-Care-Services.pdf#page=15" + + def formula(spm_unit, period, parameters): + return add(spm_unit, period, ["receives_or_needs_protective_services"]) > 0 diff --git a/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_child_care_subsidies.py b/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_child_care_subsidies.py new file mode 100644 index 00000000000..38d6d11e157 --- /dev/null +++ b/policyengine_us/variables/gov/states/ny/ocfs/ccap/ny_child_care_subsidies.py @@ -0,0 +1,12 @@ +from policyengine_us.model_api import * + + +class ny_child_care_subsidies(Variable): + value_type = float + entity = SPMUnit + label = "New York child care subsidies" + unit = USD + definition_period = YEAR + defined_for = StateCode.NY + reference = "https://www.nysenate.gov/legislation/laws/SOS/410-U" + adds = ["ny_ccap"] diff --git a/policyengine_us/variables/gov/states/ny/ocfs/ccap/rates/ny_ccap_age_group.py b/policyengine_us/variables/gov/states/ny/ocfs/ccap/rates/ny_ccap_age_group.py new file mode 100644 index 00000000000..a87d8861e57 --- /dev/null +++ b/policyengine_us/variables/gov/states/ny/ocfs/ccap/rates/ny_ccap_age_group.py @@ -0,0 +1,58 @@ +from policyengine_us.model_api import * + + +class NYCCAPAgeGroup(Enum): + INFANT = "Infant" + TODDLER = "Toddler" + PRESCHOOLER = "Preschooler" + SCHOOL_AGE = "School age" + + +class ny_ccap_age_group(Variable): + value_type = Enum + possible_values = NYCCAPAgeGroup + default_value = NYCCAPAgeGroup.SCHOOL_AGE + entity = Person + label = "New York CCAP market-rate age group" + definition_period = YEAR + defined_for = StateCode.NY + documentation = ( + "24-OCFS-LCM-22 sets a lower infant ceiling for center-based " + "providers — day care centers, school-age child care programs and " + "legally exempt group programs — than for home-based providers. The " + "school-age band has no upper bound: a child over 12 who still meets " + "the 415.1(b) definition of an eligible child draws the 6-12 rate." + ) + reference = ( + "https://ocfs.ny.gov/main/policies/external/2024/lcm/24-OCFS-LCM-22.pdf#page=4" + ) + + def formula(person, period, parameters): + p = parameters(period).gov.states.ny.ocfs.ccap.age_groups + age = person("age", period) + provider_type = person("childcare_provider_type_group", period) + provider_types = provider_type.possible_values + # The center/home split is inlined rather than read from + # is_ccdf_home_based, which treats legally exempt group programs as + # home-based. 24-OCFS-LCM-22 counts them as center-based. + uses_center_age_groups = (provider_type == provider_types.DCC_SACC) | ( + provider_type == provider_types.LE_GC + ) + infant_upper_bound = where( + uses_center_age_groups, + p.center_infant_upper_bound, + p.home_infant_upper_bound, + ) + return select( + [ + age < infant_upper_bound, + age < p.toddler_upper_bound, + age < p.preschool_upper_bound, + ], + [ + NYCCAPAgeGroup.INFANT, + NYCCAPAgeGroup.TODDLER, + NYCCAPAgeGroup.PRESCHOOLER, + ], + default=NYCCAPAgeGroup.SCHOOL_AGE, + ) diff --git a/policyengine_us/variables/gov/states/ny/ocfs/ccap/rates/ny_ccap_county_group.py b/policyengine_us/variables/gov/states/ny/ocfs/ccap/rates/ny_ccap_county_group.py new file mode 100644 index 00000000000..75e309dcfd7 --- /dev/null +++ b/policyengine_us/variables/gov/states/ny/ocfs/ccap/rates/ny_ccap_county_group.py @@ -0,0 +1,55 @@ +from policyengine_us.model_api import * + + +class NYCCAPCountyGroup(Enum): + GROUP_1 = "Group 1" + GROUP_2 = "Group 2" + GROUP_3 = "Group 3" + GROUP_4 = "Group 4" + + +class ny_ccap_county_group(Variable): + value_type = Enum + possible_values = NYCCAPCountyGroup + default_value = NYCCAPCountyGroup.GROUP_3 + entity = Household + label = "New York CCAP county group" + definition_period = YEAR + defined_for = StateCode.NY + documentation = ( + "New York keys rates to the child care provider's county. " + "Because provider location is not represented, this variable uses " + "household county as a proxy and defaults unknown counties to group " + "3. Group 3 carries the lowest rates in the current schedule, so any " + "household whose county does not resolve is understated by 10 to 19 " + "percent against group 2, 24 to 34 percent against group 1 (Nassau, " + "Putnam, Rockland, Suffolk, Westchester), and 21 to 37 percent " + "against group 4 (the five New York City boroughs). Groups 1 and 4 " + "hold the large majority of New York's child population, so the " + "default biases microsimulation results downward wherever county is " + "unimputed." + ) + reference = ( + "https://ocfs.ny.gov/main/policies/external/2024/lcm/24-OCFS-LCM-22.pdf#page=14" + ) + + def formula(household, period, parameters): + county = household("county_str", period) + groups = parameters(period).gov.states.ny.ocfs.ccap.county_group + conditions = [ + np.isin(county, groups.group_1), + np.isin(county, groups.group_2), + np.isin(county, groups.group_3), + np.isin(county, groups.group_4), + ] + values = [ + NYCCAPCountyGroup.GROUP_1, + NYCCAPCountyGroup.GROUP_2, + NYCCAPCountyGroup.GROUP_3, + NYCCAPCountyGroup.GROUP_4, + ] + return select( + conditions, + values, + default=NYCCAPCountyGroup.GROUP_3, + ) diff --git a/policyengine_us/variables/gov/states/ny/ocfs/ccap/rates/ny_ccap_duration_of_care.py b/policyengine_us/variables/gov/states/ny/ocfs/ccap/rates/ny_ccap_duration_of_care.py new file mode 100644 index 00000000000..ee85c5bba73 --- /dev/null +++ b/policyengine_us/variables/gov/states/ny/ocfs/ccap/rates/ny_ccap_duration_of_care.py @@ -0,0 +1,48 @@ +from policyengine_us.model_api import * + + +class NYCCAPDurationOfCare(Enum): + WEEKLY = "Weekly" + DAILY = "Daily" + PART_DAY = "Part-Day" + + +class ny_ccap_duration_of_care(Variable): + value_type = Enum + possible_values = NYCCAPDurationOfCare + default_value = NYCCAPDurationOfCare.PART_DAY + entity = Person + label = "New York CCAP market-rate duration of care" + definition_period = YEAR + defined_for = StateCode.NY + documentation = ( + "18 NYCRR 415.9(a)-(c) sets the base rate unit. The weekly rate is a " + "full-time slot: at least the weekly minimum hours over no more than " + "the weekly maximum days, at or above the daily minimum hours. Below " + "the daily minimum hours 415.9(c) makes the part-day rate mandatory " + "whatever the weekly total. Everything else at or above the daily " + "minimum takes the daily rate. Days past the weekly maximum and hours " + "past the daily maximum earn additional periods in " + "ny_ccap_market_rate rather than changing this base category." + ) + reference = ( + "https://ocfs.ny.gov/programs/childcare/regulations/415-Child-Care-Services.pdf#page=44", + "https://ocfs.ny.gov/main/policies/external/2024/lcm/24-OCFS-LCM-22.pdf#page=5", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.states.ny.ocfs.ccap.duration + hours_per_day = person("childcare_hours_per_day", period) + days_per_week = person("childcare_days_per_week", period) + # 415.9(a) measures the weekly threshold over five or fewer days, so + # days beyond the weekly maximum do not help a schedule reach it. + core_weekly_hours = hours_per_day * min_(days_per_week, p.weekly_maximum_days) + weekly = (core_weekly_hours >= p.weekly_minimum_hours) & ( + hours_per_day >= p.daily_minimum_hours + ) + daily = ~weekly & (hours_per_day >= p.daily_minimum_hours) + return select( + [weekly, daily], + [NYCCAPDurationOfCare.WEEKLY, NYCCAPDurationOfCare.DAILY], + default=NYCCAPDurationOfCare.PART_DAY, + ) diff --git a/policyengine_us/variables/gov/states/ny/ocfs/ccap/rates/ny_ccap_market_rate.py b/policyengine_us/variables/gov/states/ny/ocfs/ccap/rates/ny_ccap_market_rate.py new file mode 100644 index 00000000000..b04ad479a4e --- /dev/null +++ b/policyengine_us/variables/gov/states/ny/ocfs/ccap/rates/ny_ccap_market_rate.py @@ -0,0 +1,75 @@ +from policyengine_us.model_api import * + + +class ny_ccap_market_rate(Variable): + value_type = float + entity = Person + label = "New York CCAP monthly market rate" + definition_period = MONTH + unit = USD + defined_for = StateCode.NY + documentation = ( + "The applicable market rate ceiling for one child, converted to a " + "monthly amount. Under 18 NYCRR 415.9(d) care exceeding one weekly or " + "daily period earns an additional period, priced at the rate for the " + "amount of time that period covers: the daily rate at or above the " + "daily minimum hours, the part-day rate below it. A weekly schedule " + "earns one additional period per day past the weekly maximum days, " + "and any schedule earns one per day for hours past the daily maximum." + ) + reference = ( + "https://ocfs.ny.gov/main/policies/external/2024/lcm/24-OCFS-LCM-22.pdf#page=6", + "https://ocfs.ny.gov/programs/childcare/regulations/415-Child-Care-Services.pdf#page=45", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.states.ny.ocfs.ccap + county_group = person.household("ny_ccap_county_group", period.this_year) + provider_type = person("childcare_provider_type_group", period.this_year) + age_group = person("ny_ccap_age_group", period.this_year) + duration = person("ny_ccap_duration_of_care", period.this_year) + durations = duration.possible_values + hours_per_day = person("childcare_hours_per_day", period.this_year) + days_per_week = person("childcare_days_per_week", period.this_year) + weekly_rate = p.rates.weekly[county_group][provider_type][age_group] + daily_rate = p.rates.daily[county_group][provider_type][age_group] + part_day_rate = p.rates.part_day[county_group][provider_type][age_group] + base_rate = select( + [ + duration == durations.WEEKLY, + duration == durations.DAILY, + duration == durations.PART_DAY, + ], + [ + weekly_rate, + daily_rate * days_per_week, + part_day_rate * days_per_week, + ], + default=0, + ) + # A weekly rate covers the weekly maximum days; each further day is an + # additional period priced by that day's own hours. + excess_days = where( + duration == durations.WEEKLY, + max_(days_per_week - p.duration.weekly_maximum_days, 0), + 0, + ) + excess_day_rate = where( + hours_per_day >= p.duration.daily_minimum_hours, + daily_rate, + part_day_rate, + ) + # Hours past the daily maximum add one further period on each day. + excess_hours = max_(hours_per_day - p.duration.daily_maximum_hours, 0) + excess_hour_rate = where( + excess_hours >= p.duration.daily_minimum_hours, + daily_rate, + part_day_rate, + ) + excess_hour_periods = where(excess_hours > 0, days_per_week, 0) + rate_per_week = ( + base_rate + + excess_days * excess_day_rate + + excess_hour_periods * excess_hour_rate + ) + return rate_per_week * (WEEKS_IN_YEAR / MONTHS_IN_YEAR)