diff --git a/changelog.d/ga-ccap.added.md b/changelog.d/ga-ccap.added.md new file mode 100644 index 00000000000..0e09b57b64c --- /dev/null +++ b/changelog.d/ga-ccap.added.md @@ -0,0 +1 @@ +Implement Georgia CAPS (Childcare and Parent Services) child care subsidy program. 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 89dc3c0bef2..ed5a8e7d418 100644 --- a/policyengine_us/parameters/gov/hhs/ccdf/child_care_subsidy_programs.yaml +++ b/policyengine_us/parameters/gov/hhs/ccdf/child_care_subsidy_programs.yaml @@ -5,6 +5,7 @@ values: - co_child_care_subsidies # Colorado Child Care Assistance Program - ct_child_care_subsidies # Connecticut Care 4 Kids - de_child_care_subsidies # Delaware Purchase of Care + - ga_child_care_subsidies # Georgia Childcare and Parent Services - ma_child_care_subsidies # Massachusetts Child Care Financial Assistance - me_child_care_subsidies # Maine Child Care Affordability Program - ne_child_care_subsidies # Nebraska Child Care Subsidy diff --git a/policyengine_us/parameters/gov/household/household_state_benefits.yaml b/policyengine_us/parameters/gov/household/household_state_benefits.yaml index b74241a36b5..084d6c6d588 100644 --- a/policyengine_us/parameters/gov/household/household_state_benefits.yaml +++ b/policyengine_us/parameters/gov/household/household_state_benefits.yaml @@ -107,6 +107,8 @@ values: - id_aabd # Kentucky benefits - ky_ssp + # Georgia benefits + - ga_child_care_subsidies # Nebraska benefits - ne_child_care_subsidies # New Mexico benefits diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/activity_requirements/weekly_hours.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/activity_requirements/weekly_hours.yaml new file mode 100644 index 00000000000..9fed6b0d3a5 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/activity_requirements/weekly_hours.yaml @@ -0,0 +1,13 @@ +description: Georgia sets this amount as the minimum weekly hours of approved activity under the Childcare and Parent Services program. +values: + 2026-03-02: 24 + +metadata: + unit: hour + period: year + label: Georgia CAPS minimum weekly activity hours + reference: + - title: Georgia CAPS Policy Manual, Section 6.8 (State-Approved Activities) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=33 + - title: Georgia CCDF Plan FFY 2025-2027, Section 3.1.1(d) (Minimum weekly hours) + href: https://www.decal.ga.gov/documents/attachments/CCDFStatePlan25-27.pdf#page=19 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/preschool_min.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/preschool_min.yaml new file mode 100644 index 00000000000..5e066a0859a --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/preschool_min.yaml @@ -0,0 +1,11 @@ +description: Georgia sets this age as the minimum for the preschool age group under the Childcare and Parent Services program. +values: + 2026-03-02: 3 + +metadata: + unit: year + period: year + label: Georgia CAPS preschool minimum age + reference: + - title: Georgia CAPS Appendix C - Reimbursement Rates (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=1 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/school_age_min.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/school_age_min.yaml new file mode 100644 index 00000000000..956df4c37c7 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/school_age_min.yaml @@ -0,0 +1,11 @@ +description: Georgia sets this age as the minimum for the school age group under the Childcare and Parent Services program. +values: + 2026-03-02: 6 + +metadata: + unit: year + period: year + label: Georgia CAPS school age minimum age + reference: + - title: Georgia CAPS Appendix C - Reimbursement Rates (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=1 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/toddler_min.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/toddler_min.yaml new file mode 100644 index 00000000000..7a070ed6d6b --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/toddler_min.yaml @@ -0,0 +1,11 @@ +description: Georgia sets this age as the minimum for the toddler age group under the Childcare and Parent Services program. +values: + 2026-03-02: 1 + +metadata: + unit: year + period: year + label: Georgia CAPS toddler minimum age + reference: + - title: Georgia CAPS Appendix C - Reimbursement Rates (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=1 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/age_threshold/child.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/age_threshold/child.yaml new file mode 100644 index 00000000000..9e04b43ef40 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/age_threshold/child.yaml @@ -0,0 +1,13 @@ +description: Georgia limits the Childcare and Parent Services program to children younger than this age. +values: + 2026-03-02: 13 + +metadata: + unit: year + period: year + label: Georgia CAPS child age threshold + reference: + - title: Georgia CAPS Policy Manual, Section 6.4 (Age Requirement) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=29 + - title: Georgia CCDF Plan FFY 2025-2027, Section 3.1.1 (Age of children served) + href: https://www.decal.ga.gov/documents/attachments/CCDFStatePlan25-27.pdf#page=16 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/age_threshold/disabled_child.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/age_threshold/disabled_child.yaml new file mode 100644 index 00000000000..4e93c682bd4 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/age_threshold/disabled_child.yaml @@ -0,0 +1,13 @@ +description: Georgia limits the Childcare and Parent Services program to disabled children up through this age. +values: + 2026-03-02: 17 + +metadata: + unit: year + period: year + label: Georgia CAPS disabled child age threshold + reference: + - title: Georgia CAPS Policy Manual, Section 6.4 (Age Requirement) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=29 + - title: Georgia CCDF Plan FFY 2025-2027, Section 3.1.1 (Age of children served) + href: https://www.decal.ga.gov/documents/attachments/CCDFStatePlan25-27.pdf#page=16 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/minor_parent_age.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/minor_parent_age.yaml new file mode 100644 index 00000000000..a98883d8c9b --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/minor_parent_age.yaml @@ -0,0 +1,13 @@ +description: Georgia waives the family fee for parents at or below this age under the Childcare and Parent Services program. +values: + 2026-03-02: 17 + +metadata: + unit: year + period: year + label: Georgia CAPS minor parent age threshold for fee waiver + reference: + - title: Georgia CAPS Policy Manual, Section 9.5 (When Family Fees Are Not Assessed) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=54 + - title: Georgia CCDF Plan FFY 2025-2027, Section 3.3.1 (Family Co-payment Waiver) + href: https://www.decal.ga.gov/documents/attachments/CCDFStatePlan25-27.pdf#page=49 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/rate.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/rate.yaml new file mode 100644 index 00000000000..785c56a9d42 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/rate.yaml @@ -0,0 +1,30 @@ +description: Georgia sets this co-payment percentage under the Childcare and Parent Services program. +metadata: + type: single_amount + threshold_unit: /1 + amount_unit: /1 + period: year + label: Georgia CAPS family fee rate by FPL ratio + reference: + - title: Georgia CAPS Appendix D - Family Fee Assessment Chart (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixD-Family%20Fee%20Assessment%20Chart.pdf + - title: Georgia CCDF Plan FFY 2025-2027, Section 3.3.1 (Family Co-payment Waiver) + href: https://www.decal.ga.gov/documents/attachments/CCDFStatePlan25-27.pdf#page=49 + +brackets: + - threshold: + 2026-03-02: 0 + amount: + 2026-03-02: 0 + - threshold: + 2026-03-02: 0.1 + amount: + 2026-03-02: 0.03 + - threshold: + 2026-03-02: 0.5 + amount: + 2026-03-02: 0.05 + - threshold: + 2026-03-02: 1.0 + amount: + 2026-03-02: 0.07 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/income/countable_income/sources.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/income/countable_income/sources.yaml new file mode 100644 index 00000000000..05147856921 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/income/countable_income/sources.yaml @@ -0,0 +1,29 @@ +description: Georgia counts these income sources under the Childcare and Parent Services program. +values: + 2026-03-02: + - employment_income + - self_employment_income + - unemployment_compensation + - workers_compensation + - alimony_income + - child_support_received + - veterans_benefits + - capital_gains + - rental_income + - dividend_income + - pension_income + - military_basic_pay + # The following are counted per CAPS Policy Manual §8.4 but have + # no matching variables: + # - military_allotments + # - lottery_payments + # - commissions (included in employment_income) + # - cash_bonuses (included in employment_income) + +metadata: + unit: list + period: year + label: Georgia CAPS countable income sources + reference: + - title: Georgia CAPS Policy Manual, Section 8.4 (Applicable Income) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=48 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/income/smi_rate/initial_eligibility.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/income/smi_rate/initial_eligibility.yaml new file mode 100644 index 00000000000..c189db0160b --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/income/smi_rate/initial_eligibility.yaml @@ -0,0 +1,13 @@ +description: Georgia limits the Childcare and Parent Services program to new applicants with income at or below this share of state median income. +values: + 2026-03-02: 0.5 + +metadata: + unit: /1 + period: year + label: Georgia CAPS initial eligibility SMI rate + reference: + - title: Georgia CAPS Policy Manual, Section 8.3 (Gross Income) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=48 + - title: Georgia CAPS Appendix A - Maximum Income Limits by Family Size (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixA-CAPS%20Maximum%20Income%20Limits%20by%20Family%20Size.pdf diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/income/smi_rate/ongoing_eligibility.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/income/smi_rate/ongoing_eligibility.yaml new file mode 100644 index 00000000000..5031d4d77e6 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/income/smi_rate/ongoing_eligibility.yaml @@ -0,0 +1,13 @@ +description: Georgia limits the Childcare and Parent Services program to enrolled families with income at or below this share of state median income. +values: + 2026-03-02: 0.85 + +metadata: + unit: /1 + period: year + label: Georgia CAPS ongoing eligibility SMI rate + reference: + - title: Georgia CAPS Policy Manual, Section 8.3 (Gross Income) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=48 + - title: Georgia CAPS Appendix A - Maximum Income Limits by Family Size (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixA-CAPS%20Maximum%20Income%20Limits%20by%20Family%20Size.pdf diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/quality_rated/bonus_rate.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/quality_rated/bonus_rate.yaml new file mode 100644 index 00000000000..82fa6bddc9a --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/quality_rated/bonus_rate.yaml @@ -0,0 +1,24 @@ +description: Georgia provides this quality bonus rate under the Childcare and Parent Services program. +metadata: + type: single_amount + threshold_unit: /1 + amount_unit: /1 + period: year + label: Georgia CAPS Quality Rated bonus rate + reference: + - title: Georgia CCDF Plan FFY 2025-2027, Section 4.3.3 (Quality Rated Differential) + href: https://www.decal.ga.gov/documents/attachments/CCDFStatePlan25-27.pdf#page=69 + +brackets: + - threshold: + 2024-09-29: 0 + amount: + 2024-09-29: 0 + - threshold: + 2024-09-29: 2 + amount: + 2024-09-29: 0.05 + - threshold: + 2024-09-29: 3 + amount: + 2024-09-29: 0.1 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/rates/center.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/rates/center.yaml new file mode 100644 index 00000000000..d5cb45106ac --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/rates/center.yaml @@ -0,0 +1,102 @@ +description: Georgia provides these reimbursement rates for child care centers under the Childcare and Parent Services program. +metadata: + unit: currency-USD + period: week + label: Georgia CAPS center reimbursement rates + breakdown: + - ga_caps_zone + - ga_caps_age_group + - ga_caps_care_type + reference: + - title: Georgia CAPS Appendix C - Reimbursement Rates (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=1 + +ZONE_1: + INFANT: + FULL_TIME: + 2026-03-02: 260 + PART_TIME: + 2026-03-02: 65 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 84 + TODDLER: + FULL_TIME: + 2026-03-02: 248 + PART_TIME: + 2026-03-02: 65 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 84 + PRESCHOOL: + FULL_TIME: + 2026-03-02: 221 + PART_TIME: + 2026-03-02: 65 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 84 + SCHOOL_AGE: + FULL_TIME: + 2026-03-02: 185 + PART_TIME: + 2026-03-02: 65 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 84 + +ZONE_2: + INFANT: + FULL_TIME: + 2026-03-02: 165 + PART_TIME: + 2026-03-02: 45 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 68 + TODDLER: + FULL_TIME: + 2026-03-02: 160 + PART_TIME: + 2026-03-02: 45 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 68 + PRESCHOOL: + FULL_TIME: + 2026-03-02: 150 + PART_TIME: + 2026-03-02: 45 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 68 + SCHOOL_AGE: + FULL_TIME: + 2026-03-02: 140 + PART_TIME: + 2026-03-02: 45 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 68 + +ZONE_3: + INFANT: + FULL_TIME: + 2026-03-02: 130 + PART_TIME: + 2026-03-02: 38 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 53 + TODDLER: + FULL_TIME: + 2026-03-02: 125 + PART_TIME: + 2026-03-02: 38 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 53 + PRESCHOOL: + FULL_TIME: + 2026-03-02: 120 + PART_TIME: + 2026-03-02: 38 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 53 + SCHOOL_AGE: + FULL_TIME: + 2026-03-02: 115 + PART_TIME: + 2026-03-02: 38 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 53 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/rates/family.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/rates/family.yaml new file mode 100644 index 00000000000..83299c97c4d --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/rates/family.yaml @@ -0,0 +1,102 @@ +description: Georgia provides these reimbursement rates for family child care homes under the Childcare and Parent Services program. +metadata: + unit: currency-USD + period: week + label: Georgia CAPS family child care home reimbursement rates + breakdown: + - ga_caps_zone + - ga_caps_age_group + - ga_caps_care_type + reference: + - title: Georgia CAPS Appendix C - Reimbursement Rates (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=1 + +ZONE_1: + INFANT: + FULL_TIME: + 2026-03-02: 199 + PART_TIME: + 2026-03-02: 53 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 68 + TODDLER: + FULL_TIME: + 2026-03-02: 188 + PART_TIME: + 2026-03-02: 53 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 68 + PRESCHOOL: + FULL_TIME: + 2026-03-02: 180 + PART_TIME: + 2026-03-02: 53 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 68 + SCHOOL_AGE: + FULL_TIME: + 2026-03-02: 156 + PART_TIME: + 2026-03-02: 53 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 68 + +ZONE_2: + INFANT: + FULL_TIME: + 2026-03-02: 145 + PART_TIME: + 2026-03-02: 40 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 58 + TODDLER: + FULL_TIME: + 2026-03-02: 140 + PART_TIME: + 2026-03-02: 40 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 58 + PRESCHOOL: + FULL_TIME: + 2026-03-02: 135 + PART_TIME: + 2026-03-02: 40 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 58 + SCHOOL_AGE: + FULL_TIME: + 2026-03-02: 135 + PART_TIME: + 2026-03-02: 40 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 58 + +ZONE_3: + INFANT: + FULL_TIME: + 2026-03-02: 120 + PART_TIME: + 2026-03-02: 35 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 47 + TODDLER: + FULL_TIME: + 2026-03-02: 110 + PART_TIME: + 2026-03-02: 35 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 47 + PRESCHOOL: + FULL_TIME: + 2026-03-02: 105 + PART_TIME: + 2026-03-02: 35 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 47 + SCHOOL_AGE: + FULL_TIME: + 2026-03-02: 94 + PART_TIME: + 2026-03-02: 35 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 47 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/rates/informal.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/rates/informal.yaml new file mode 100644 index 00000000000..f3dc7ac1f0e --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/rates/informal.yaml @@ -0,0 +1,102 @@ +description: Georgia provides these reimbursement rates for informal child care providers under the Childcare and Parent Services program. +metadata: + unit: currency-USD + period: week + label: Georgia CAPS informal child care reimbursement rates + breakdown: + - ga_caps_zone + - ga_caps_age_group + - ga_caps_care_type + reference: + - title: Georgia CAPS Appendix C - Reimbursement Rates (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=1 + +ZONE_1: + INFANT: + FULL_TIME: + 2026-03-02: 199 + PART_TIME: + 2026-03-02: 53 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 68 + TODDLER: + FULL_TIME: + 2026-03-02: 188 + PART_TIME: + 2026-03-02: 53 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 68 + PRESCHOOL: + FULL_TIME: + 2026-03-02: 180 + PART_TIME: + 2026-03-02: 53 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 68 + SCHOOL_AGE: + FULL_TIME: + 2026-03-02: 156 + PART_TIME: + 2026-03-02: 53 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 68 + +ZONE_2: + INFANT: + FULL_TIME: + 2026-03-02: 145 + PART_TIME: + 2026-03-02: 40 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 58 + TODDLER: + FULL_TIME: + 2026-03-02: 140 + PART_TIME: + 2026-03-02: 40 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 58 + PRESCHOOL: + FULL_TIME: + 2026-03-02: 135 + PART_TIME: + 2026-03-02: 40 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 58 + SCHOOL_AGE: + FULL_TIME: + 2026-03-02: 135 + PART_TIME: + 2026-03-02: 40 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 58 + +ZONE_3: + INFANT: + FULL_TIME: + 2026-03-02: 120 + PART_TIME: + 2026-03-02: 35 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 47 + TODDLER: + FULL_TIME: + 2026-03-02: 110 + PART_TIME: + 2026-03-02: 35 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 47 + PRESCHOOL: + FULL_TIME: + 2026-03-02: 105 + PART_TIME: + 2026-03-02: 35 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 47 + SCHOOL_AGE: + FULL_TIME: + 2026-03-02: 94 + PART_TIME: + 2026-03-02: 35 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 47 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/zone_1_counties.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/zone_1_counties.yaml new file mode 100644 index 00000000000..fd9e02f6b8d --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/zone_1_counties.yaml @@ -0,0 +1,25 @@ +description: Georgia sets these counties as Zone 1 for reimbursement rate purposes under the Childcare and Parent Services program. +values: + 2026-03-02: + - CAMDEN_COUNTY_GA + - CHEROKEE_COUNTY_GA + - CLAYTON_COUNTY_GA + - COBB_COUNTY_GA + - DEKALB_COUNTY_GA + - DOUGLAS_COUNTY_GA + - FAYETTE_COUNTY_GA + - FORSYTH_COUNTY_GA + - FULTON_COUNTY_GA + - GWINNETT_COUNTY_GA + - HALL_COUNTY_GA + - HENRY_COUNTY_GA + - PAULDING_COUNTY_GA + - ROCKDALE_COUNTY_GA + +metadata: + unit: list + period: year + label: Georgia CAPS Zone 1 counties + reference: + - title: Georgia CAPS Appendix C - Reimbursement Rates, Zone Map (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=2 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/zone_2_counties.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/zone_2_counties.yaml new file mode 100644 index 00000000000..4594e8ae28b --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/zone_2_counties.yaml @@ -0,0 +1,57 @@ +description: Georgia sets these counties as Zone 2 for reimbursement rate purposes under the Childcare and Parent Services program. +values: + 2026-03-02: + - BALDWIN_COUNTY_GA + - BARROW_COUNTY_GA + - BARTOW_COUNTY_GA + - BIBB_COUNTY_GA + - BRYAN_COUNTY_GA + - BULLOCH_COUNTY_GA + - BUTTS_COUNTY_GA + - CATOOSA_COUNTY_GA + - CHATHAM_COUNTY_GA + - CLARKE_COUNTY_GA + - COLUMBIA_COUNTY_GA + - COWETA_COUNTY_GA + - DAWSON_COUNTY_GA + - DOUGHERTY_COUNTY_GA + - EFFINGHAM_COUNTY_GA + - FLOYD_COUNTY_GA + - GLYNN_COUNTY_GA + - GORDON_COUNTY_GA + - HARRIS_COUNTY_GA + - HART_COUNTY_GA + - HOUSTON_COUNTY_GA + - JACKSON_COUNTY_GA + - JONES_COUNTY_GA + - LAMAR_COUNTY_GA + - LEE_COUNTY_GA + - LIBERTY_COUNTY_GA + - LOWNDES_COUNTY_GA + - LUMPKIN_COUNTY_GA + - MADISON_COUNTY_GA + - MCDUFFIE_COUNTY_GA + - MERIWETHER_COUNTY_GA + - MORGAN_COUNTY_GA + - MURRAY_COUNTY_GA + - MUSCOGEE_COUNTY_GA + - NEWTON_COUNTY_GA + - OCONEE_COUNTY_GA + - PEACH_COUNTY_GA + - PIKE_COUNTY_GA + - PULASKI_COUNTY_GA + - PUTNAM_COUNTY_GA + - RICHMOND_COUNTY_GA + - SPALDING_COUNTY_GA + - TIFT_COUNTY_GA + - TROUP_COUNTY_GA + - WALTON_COUNTY_GA + - WHITFIELD_COUNTY_GA + +metadata: + unit: list + period: year + label: Georgia CAPS Zone 2 counties + reference: + - title: Georgia CAPS Appendix C - Reimbursement Rates, Zone Map (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=2 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 76b5377b5f3..66b13d48387 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -460,7 +460,7 @@ programs: category: Benefits agency: HHS status: partial - coverage: CA, CO, CT, DE, DC, IL, MA, MD, ME, NC, NH, NJ, PA, RI, SC, TX, VA, VT, WV + coverage: CA, CO, CT, DE, DC, GA, IL, MA, MD, ME, NC, NH, NJ, PA, RI, SC, TX, VA, VT, WV state_implementations: - state: CA status: complete @@ -553,6 +553,12 @@ programs: status: in_progress name: West Virginia CCAP full_name: West Virginia Child Care Assistance Program + - state: GA + status: complete + name: Georgia CAPS + full_name: Georgia Childcare and Parent Services + variable: ga_caps + parameter_prefix: gov.states.ga.decal.caps - id: head_start name: Head Start diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/copay/ga_caps_family_fee.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/copay/ga_caps_family_fee.yaml new file mode 100644 index 00000000000..13e0d14c608 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/copay/ga_caps_family_fee.yaml @@ -0,0 +1,382 @@ +# GA CAPS family fee (co-payment) +# Tiers by FPL ratio: +# <= 10% FPL: 0% (no fee) +# > 10% to 50% FPL: 3% of income +# > 50% to 100% FPL: 5% of income +# > 100% FPL: 7% of income +# Weekly fee = floor(annual_income * rate / 52) +# Monthly fee = weekly_fee * 52 / 12 +# Fee waived for minor parents (age <= 17) +# +# 2026 FPG family of 3: 15,960 + 5,680 * 2 = $27,320 +# 2026 FPG family of 2: 15,960 + 5,680 = $21,640 + +- name: Case 1, income over 100 percent FPL pays 7 percent. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 30_000 + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + # FPL ratio = 30,000 / 27,320 = 1.098 -> 7% rate + # weekly fee = floor(30,000 * 0.07 / 52) = floor(40.38) = $40 + # monthly fee = 40 * 52 / 12 = $173.33 + ga_caps_family_fee: 173.33 + +- name: Case 2, income at or below 10 percent FPL pays zero. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 2_000 + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + # FPL ratio = 2,000 / 27,320 = 0.0732 -> 0% rate + # fee = 0 + ga_caps_family_fee: 0 + +- name: Case 3, income in 3 percent tier. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 10_000 + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + # FPL ratio = 10,000 / 27,320 = 0.3660 -> 3% rate + # weekly fee = floor(10,000 * 0.03 / 52) = floor(5.77) = $5 + # monthly fee = 5 * 52 / 12 = $21.67 + ga_caps_family_fee: 21.67 + +- name: Case 4, income in 5 percent tier. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + # FPL ratio = 20,000 / 27,320 = 0.7320 -> 5% rate + # weekly fee = floor(20,000 * 0.05 / 52) = floor(19.23) = $19 + # monthly fee = 19 * 52 / 12 = $82.33 + ga_caps_family_fee: 82.33 + +- name: Case 5, zero income family has zero fee. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # $0 income -> FPL ratio = 0 -> 0% rate -> $0 fee + ga_caps_family_fee: 0 + +- name: Case 6, minor parent fee waiver. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 17 + employment_income: 30_000 + is_tax_unit_head: true + person2: + age: 1 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # Parent age 17 <= 17 -> minor parent fee waiver -> $0 + ga_caps_family_fee: 0 + +- name: Case 7, income just below 10 percent FPL boundary. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 2_731 + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + # FPL ratio = 2,731 / 27,320 = 0.09996 -> < 0.1 -> 0% rate + ga_caps_family_fee: 0 + +- name: Case 8, income one dollar above 10 percent FPL enters 3 percent tier. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + # 10% of FPG for family of 2 = 21,640 * 0.10 = $2,164 + # One dollar above: $2,165 + employment_income: 2_165 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # FPL ratio = 2,165 / 21,640 = 0.10005 -> > 0.1 -> 3% rate + # weekly fee = floor(2,165 * 0.03 / 52) = floor(1.25) = $1 + # monthly fee = 1 * 52 / 12 = $4.33 + ga_caps_family_fee: 4.33 + +- name: Case 9, mid-range income in 3 percent tier. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 5_000 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # FPL ratio = 5,000 / 21,640 = 0.231 -> > 0.1, < 0.5 -> 3% rate + # weekly fee = floor(5,000 * 0.03 / 52) = floor(2.88) = $2 + # monthly fee = 2 * 52 / 12 = $8.67 + ga_caps_family_fee: 8.67 + +- name: Case 10, income one dollar below 50 percent FPL stays in 3 percent tier. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + # 50% of FPG for family of 2 = 21,640 * 0.50 = $10,820 + # One dollar below: $10,819 + employment_income: 10_819 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # FPL ratio = 10,819 / 21,640 = 0.49995 -> < 0.5 -> 3% rate + # weekly fee = floor(10,819 * 0.03 / 52) = floor(6.24) = $6 + # monthly fee = 6 * 52 / 12 = $26.00 + ga_caps_family_fee: 26.00 + +- name: Case 11, income one dollar above 50 percent FPL enters 5 percent tier. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + # One dollar above 50% FPG (family of 2): $10,821 + employment_income: 10_821 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # FPL ratio = 10,821 / 21,640 = 0.50005 -> > 0.5 -> 5% rate + # weekly fee = floor(10,821 * 0.05 / 52) = floor(10.40) = $10 + # monthly fee = 10 * 52 / 12 = $43.33 + ga_caps_family_fee: 43.33 + +- name: Case 12, income one dollar below 100 percent FPL stays in 5 percent tier. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + # 100% of FPG for family of 2 = $21,640; one dollar below: $21,639 + employment_income: 21_639 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # FPL ratio = 21,639 / 21,640 = 0.99995 -> < 1.0 -> 5% rate + # weekly fee = floor(21,639 * 0.05 / 52) = floor(20.80) = $20 + # monthly fee = 20 * 52 / 12 = $86.67 + ga_caps_family_fee: 86.67 + +- name: Case 13, income one dollar above 100 percent FPL enters 7 percent tier. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + # One dollar above 100% FPG: $21,641 + employment_income: 21_641 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # FPL ratio = 21,641 / 21,640 = 1.00005 -> > 1.0 -> 7% rate + # weekly fee = floor(21,641 * 0.07 / 52) = floor(29.13) = $29 + # monthly fee = 29 * 52 / 12 = $125.67 + ga_caps_family_fee: 125.67 + +- name: Case 14, parent age 18 does not get minor parent fee waiver. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 18 + employment_income: 30_000 + person2: + age: 1 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # Parent age 18 > 17 -> no fee waiver + # FPG family of 2: $21,640 + # FPL ratio = 30,000 / 21,640 = 1.387 -> 7% rate + # weekly fee = floor(30,000 * 0.07 / 52) = floor(40.38) = $40 + # monthly fee = 40 * 52 / 12 = $173.33 + ga_caps_family_fee: 173.33 + +- name: Case 15, larger family of 5 with lower FPL ratio. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 20_000 + person2: + age: 30 + person3: + age: 10 + person4: + age: 7 + person5: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: GA + output: + # FPG family of 5: 15,960 + 5,680 * 4 = $38,680 + # FPL ratio = 20,000 / 38,680 = 0.5171 -> >= 0.5001 -> 5% rate + # weekly fee = floor(20,000 * 0.05 / 52) = floor(19.23) = $19 + # monthly fee = 19 * 52 / 12 = $82.33 + ga_caps_family_fee: 82.33 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.yaml new file mode 100644 index 00000000000..5775c67525b --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.yaml @@ -0,0 +1,370 @@ +# GA CAPS activity eligibility +# Parent must average 24 hours/week in approved activities +# (employment or full-time student). +# All cases pin meets_ccdf_activity_test: false to isolate the GA-specific +# 24-hour rule from the federal CCDF fallback (added in ga_caps_activity_eligible.py). + +- name: Case 1, single parent working 24 hours meets requirement. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 24 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + meets_ccdf_activity_test: false + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_activity_eligible: true + +- name: Case 2, single parent working 23 hours does not meet requirement. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 23 + is_full_time_student: false + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + meets_ccdf_activity_test: false + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_activity_eligible: false + +- name: Case 3, full time student parent qualifies. + period: 2026-01 + input: + people: + person1: + age: 25 + weekly_hours_worked: 0 + is_full_time_student: true + person2: + age: 3 + spm_units: + spm_unit: + members: [person1, person2] + meets_ccdf_activity_test: false + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_activity_eligible: true + +- name: Case 4, two parents both working 24 plus hours. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 30 + person2: + age: 28 + weekly_hours_worked: 24 + person3: + age: 5 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + meets_ccdf_activity_test: false + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + ga_caps_activity_eligible: true + +- name: Case 5, two parents one below 24 hours. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 30 + person2: + age: 28 + weekly_hours_worked: 20 + is_full_time_student: false + person3: + age: 5 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + meets_ccdf_activity_test: false + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + ga_caps_activity_eligible: false + +- name: Case 6, one parent works and one is a full time student. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 24 + person2: + age: 25 + weekly_hours_worked: 0 + is_full_time_student: true + person3: + age: 4 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + meets_ccdf_activity_test: false + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + ga_caps_activity_eligible: true + +- name: Case 7, single parent working exactly 25 hours just above threshold. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 25 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + meets_ccdf_activity_test: false + households: + household: + members: [person1, person2] + state_code: GA + output: + # 25 >= 24 -> eligible + ga_caps_activity_eligible: true + +- name: Case 8, single parent working zero hours and not a student. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 0 + is_full_time_student: false + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + meets_ccdf_activity_test: false + households: + household: + members: [person1, person2] + state_code: GA + output: + # 0 < 24 and not a student -> ineligible + ga_caps_activity_eligible: false + +- name: Case 9, two parents both full-time students. + period: 2026-01 + input: + people: + person1: + age: 22 + weekly_hours_worked: 0 + is_full_time_student: true + person2: + age: 21 + weekly_hours_worked: 0 + is_full_time_student: true + person3: + age: 2 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + meets_ccdf_activity_test: false + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + # Both are students -> both individually eligible + ga_caps_activity_eligible: true + +- name: Case 10, two parents both below 24 hours and not students. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 20 + is_full_time_student: false + person2: + age: 28 + weekly_hours_worked: 15 + is_full_time_student: false + person3: + age: 4 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + meets_ccdf_activity_test: false + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + # Both below 24 hrs and not students -> ineligible + ga_caps_activity_eligible: false + +- name: Case 11, single parent working 40 hours per week. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 40 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + meets_ccdf_activity_test: false + households: + household: + members: [person1, person2] + state_code: GA + output: + # 40 >= 24 -> eligible + ga_caps_activity_eligible: true + +- name: Case 12, child hours do not matter for activity requirement. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 24 + person2: + age: 10 + weekly_hours_worked: 0 + is_full_time_student: false + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + meets_ccdf_activity_test: false + households: + household: + members: [person1, person2] + state_code: GA + output: + # Only heads/spouses checked; child's hours irrelevant + ga_caps_activity_eligible: true + +- name: Case 13, federal CCDF fallback approves when GA 24-hour rule fails. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 10 + is_full_time_student: false + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + meets_ccdf_activity_test: true + households: + household: + members: [person1, person2] + state_code: GA + output: + # GA gate fails (10 < 24, not student), but federal CCDF fallback approves + ga_caps_activity_eligible: true + +- name: Case 14, two-parent family with one disabled spouse passes GA gate. + period: 2026-01 + input: + people: + person1: + age: 35 + weekly_hours_worked: 30 + person2: + age: 33 + weekly_hours_worked: 0 + is_disabled: true + is_full_time_student: false + person3: + age: 4 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + meets_ccdf_activity_test: false + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + # Per Policy Manual §6.8.1.8, disabled spouse is exempt from activity gate; + # non-disabled parent works 30 >= 24 -> family eligible without federal fallback. + ga_caps_activity_eligible: true + +- name: Case 15, single disabled parent passes GA gate. + period: 2026-01 + input: + people: + person1: + age: 40 + weekly_hours_worked: 0 + is_disabled: true + is_full_time_student: false + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + meets_ccdf_activity_test: false + households: + household: + members: [person1, person2] + state_code: GA + output: + # Single disabled head exempt from activity gate per §6.8.1.8 + ga_caps_activity_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible.yaml new file mode 100644 index 00000000000..e414f1f5c4d --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible.yaml @@ -0,0 +1,158 @@ +# GA CAPS family eligibility +# Requires: eligible child, income eligible, activity eligible, asset eligible +# +# GA SMI for 4-person household at 2026-01: $116,773.19 (uprated) +# Family of 2: 116,773.19 * 0.68 = $79,405.77 +# 50% SMI = $39,702.88 + +- name: Case 1, eligible family with child under 13 and low income. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 30_000 + immigration_status: CITIZEN + person2: + age: 5 + + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_eligible: true + +- name: Case 2, ineligible due to income above 50 percent SMI. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 40_000 + immigration_status: CITIZEN + person2: + age: 5 + + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # income 40,000 > 39,702.88 (50% SMI for family of 2) -> ineligible + ga_caps_eligible: false + +- name: Case 3, ineligible with no eligible child. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: GA + output: + # no child in unit -> ineligible + ga_caps_eligible: false + +- name: Case 4, ineligible due to assets above limit. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 5 + + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_500_000 + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_eligible: false + +- name: Case 5, ineligible when child is undocumented. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 5 + + immigration_status: UNDOCUMENTED + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_eligible: false + +- name: Case 6, ineligible due to insufficient activity hours. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + weekly_hours_worked: 20 + is_full_time_student: false + person2: + age: 5 + + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # 20 hrs/wk < 24 required -> activity ineligible -> ineligible + ga_caps_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.yaml new file mode 100644 index 00000000000..ea57bbce23f --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.yaml @@ -0,0 +1,384 @@ +# GA CAPS child eligibility +# Standard: age < 13 (12 or younger) +# Disabled: age <= 17 +# Must be immigration eligible (CCDF) + +- name: Case 1, child under 13 who is a citizen. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_eligible_child: [false, true] + +- name: Case 2, child age 12 is eligible. + period: 2026-01 + input: + people: + person1: + age: 35 + person2: + age: 12 + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # age 12 < 13 -> eligible + ga_caps_eligible_child: [false, true] + +- name: Case 3, child age 13 ineligible without disability. + period: 2026-01 + input: + people: + person1: + age: 35 + person2: + age: 13 + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # age 13 not < 13 -> ineligible + ga_caps_eligible_child: [false, false] + +- name: Case 4, disabled child age 15 eligible. + period: 2026-01 + input: + people: + person1: + age: 40 + person2: + age: 15 + is_disabled: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # disabled, age 15 <= 17 -> eligible + ga_caps_eligible_child: [false, true] + +- name: Case 5, disabled child age 17 eligible. + period: 2026-01 + input: + people: + person1: + age: 45 + person2: + age: 17 + is_disabled: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # disabled, age 17 <= 17 -> eligible + ga_caps_eligible_child: [false, true] + +- name: Case 6, disabled child age 18 ineligible. + period: 2026-01 + input: + people: + person1: + age: 45 + person2: + age: 18 + is_disabled: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # disabled, age 18 > 17 -> ineligible + ga_caps_eligible_child: [false, false] + +- name: Case 7, undocumented child ineligible. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + immigration_status: UNDOCUMENTED + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_eligible_child: [false, false] + +- name: Case 8, adult is never an eligible child. + period: 2026-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: GA + output: + ga_caps_eligible_child: [false] + +- name: Case 9, infant age 0 is eligible. + period: 2026-01 + input: + people: + person1: + age: 25 + person2: + age: 0 + + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # age 0 < 13 -> eligible + ga_caps_eligible_child: [false, true] + +- name: Case 10, toddler age 1 is eligible. + period: 2026-01 + input: + people: + person1: + age: 25 + person2: + age: 1 + + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # age 1 < 13 -> eligible + ga_caps_eligible_child: [false, true] + +- name: Case 11, preschool age 3 at boundary. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 3 + + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # age 3 < 13 -> eligible + ga_caps_eligible_child: [false, true] + +- name: Case 12, school-age 6 at boundary. + period: 2026-01 + input: + people: + person1: + age: 35 + person2: + age: 6 + + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # age 6 < 13 -> eligible + ga_caps_eligible_child: [false, true] + +- name: Case 13, disabled child age 13 eligible with disability. + period: 2026-01 + input: + people: + person1: + age: 40 + person2: + age: 13 + + is_disabled: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # disabled, age 13 <= 17 -> eligible + ga_caps_eligible_child: [false, true] + +- name: Case 14, non-disabled child age 13 ineligible contrasted with disabled. + period: 2026-01 + input: + people: + person1: + age: 40 + person2: + age: 13 + + is_disabled: false + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # not disabled, age 13 >= 13 -> ineligible + ga_caps_eligible_child: [false, false] + +- name: Case 15, two children one eligible and one over age limit. + period: 2026-01 + input: + people: + person1: + age: 40 + person2: + age: 10 + + immigration_status: CITIZEN + person3: + age: 14 + + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + # person2: age 10 < 13 -> eligible + # person3: age 14 >= 13, not disabled -> ineligible + ga_caps_eligible_child: [false, true, false] + +- name: Case 16, legal permanent resident child is eligible. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + + immigration_status: LEGAL_PERMANENT_RESIDENT + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_eligible_child: [false, true] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible.yaml new file mode 100644 index 00000000000..7d6805cbd93 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible.yaml @@ -0,0 +1,336 @@ +# GA CAPS income eligibility +# Initial (not enrolled): income <= 50% SMI +# Ongoing (enrolled): income <= 85% SMI +# +# GA SMI for 4-person household at 2026-01: $116,773.19 (uprated) +# Family of 2: 116,773.19 * 0.68 = $79,405.77 +# 50% SMI = $39,702.88 +# 85% SMI = $67,494.90 + +- name: Case 1, new applicant income below 50 percent SMI. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 30_000 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # income 30,000 <= 39,702.88 (50% SMI for family of 2) -> eligible + ga_caps_income_eligible: true + +- name: Case 2, new applicant income above 50 percent SMI. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 40_000 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # income 40,000 > 39,702.88 (50% SMI for family of 2) -> ineligible + ga_caps_income_eligible: false + +- name: Case 3, enrolled family income between 50 and 85 percent SMI. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + ga_caps_enrolled: true + households: + household: + members: [person1, person2] + state_code: GA + output: + # enrolled: income 50,000 <= 67,494.90 (85% SMI) -> eligible + ga_caps_income_eligible: true + +- name: Case 4, enrolled family income above 85 percent SMI. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 68_000 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + ga_caps_enrolled: true + households: + household: + members: [person1, person2] + state_code: GA + output: + # enrolled: income 68,000 > 67,494.90 (85% SMI) -> ineligible + ga_caps_income_eligible: false + +- name: Case 5, non-enrolled family between 50 and 85 percent SMI. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + ga_caps_enrolled: false + households: + household: + members: [person1, person2] + state_code: GA + output: + # not enrolled: income 50,000 > 39,702.88 (50% SMI) -> ineligible + ga_caps_income_eligible: false + +- name: Case 6, zero income family is eligible. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_income_eligible: true + +# Additional family sizes for boundary tests: +# Family of 3: 116,773.19 * 0.84 = $98,089.48 +# 50% SMI = $49,044.74; 85% SMI = $83,376.06 +# Family of 5: 116,773.19 * 1.16 = $135,456.90 +# 50% SMI = $67,728.45; 85% SMI = $115,138.36 + +- name: Case 7, income exactly at 50 percent SMI threshold for family of 2. + period: 2026-01 + input: + people: + person1: + age: 30 + # 50% SMI for family of 2 is $39,702.88/yr + employment_income: 39_702 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # income 39,702 <= 39,702.88 -> eligible (just at threshold) + ga_caps_income_eligible: true + +- name: Case 8, income one dollar above 50 percent SMI threshold. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 39_703 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # income 39,703 > 39,702.88 -> ineligible + ga_caps_income_eligible: false + +- name: Case 9, enrolled income exactly at 85 percent SMI threshold. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 67_494 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + ga_caps_enrolled: true + households: + household: + members: [person1, person2] + state_code: GA + output: + # enrolled: income 67,494 <= 67,494.90 -> eligible + ga_caps_income_eligible: true + +- name: Case 10, enrolled income one dollar above 85 percent SMI. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 67_495 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + ga_caps_enrolled: true + households: + household: + members: [person1, person2] + state_code: GA + output: + # enrolled: income 67,495 > 67,494.90 -> ineligible + ga_caps_income_eligible: false + +- name: Case 11, very high income family ineligible. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 200_000 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_income_eligible: false + +- name: Case 12, larger family of 5 at 50 percent SMI threshold. + period: 2026-01 + input: + people: + person1: + age: 35 + employment_income: 67_728 + person2: + age: 30 + person3: + age: 10 + person4: + age: 7 + person5: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: GA + output: + # 50% SMI family of 5 = $67,728.45 + # income 67,728 <= 67,728.45 -> eligible + ga_caps_income_eligible: true + +- name: Case 13, larger family of 5 one dollar over threshold. + period: 2026-01 + input: + people: + person1: + age: 35 + employment_income: 67_729 + person2: + age: 30 + person3: + age: 10 + person4: + age: 7 + person5: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: GA + output: + # 50% SMI family of 5 = $67,728.45 + # income 67,729 > 67,728.45 -> ineligible + ga_caps_income_eligible: false + +- name: Case 14, enrolled family of 3 at ongoing threshold. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 83_376 + person2: + age: 28 + person3: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3] + ga_caps_enrolled: true + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + # 85% SMI family of 3 = $83,376.06 + # enrolled: income 83,376 <= 83,376.06 -> eligible + ga_caps_income_eligible: true + +- name: Case 15, multiple income sources combined. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 25_000 + self_employment_income: 10_000 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # total income = 25,000 + 10,000 = 35,000 <= 39,702.88 -> eligible + ga_caps_income_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/ga_caps.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/ga_caps.yaml new file mode 100644 index 00000000000..82276e1ec19 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/ga_caps.yaml @@ -0,0 +1,478 @@ +# GA CAPS benefit +# Subsidy = max(min(expenses, sum_of_max_rates) - fee, 0) * (1 + weighted_quality_bonus_rate) +# +# 2026 FPG (Contiguous US): +# first_person = 15,960, additional = 5,680 +# Family of 2: 21,640 +# Family of 3: 27,320 +# +# GA SMI 4-person at 2026-01: $116,773.19 (uprated) +# Family of 2: 116,773.19 * 0.68 = $79,405.77 -> 50% = $39,702.88 + +- name: Case 1, subsidy zero when fee exceeds expenses. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 35_000 + immigration_status: CITIZEN + person2: + age: 4 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 2_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_eligible: true + # FPG family of 2: $21,640 + # FPL ratio = 35,000 / 21,640 = 1.617 -> 7% rate + # weekly fee = floor(35,000 * 0.07 / 52) = floor(47.12) = $47 + # monthly fee = 47 * 52 / 12 = $203.67 + ga_caps_family_fee: 203.67 + # max annual = 221 * 52 = $11,492 + # annual fee = 47 * 52 = $2,444 + # uncapped = max(2,000 - 2,444, 0) = $0 (fee > expenses) + # base_subsidy = min(0, 11,492) = 0 + # quality bonus = 0 (base_subsidy is 0) + ga_caps: 0 + +- name: Case 2, quality bonus 1-star gives zero bonus. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 4 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: ONE_STAR + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 10_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_eligible: true + # FPG family of 2: $21,640 + # FPL ratio = 20,000 / 21,640 = 0.9242 -> 5% rate + # weekly fee = floor(20,000 * 0.05 / 52) = floor(19.23) = $19 + # monthly fee = 19 * 52 / 12 = $82.33 + ga_caps_family_fee: 82.33 + # max annual = 221 * 52 = $11,492 + # annual fee = 19 * 52 = $988 + # uncapped = max(10,000 - 988, 0) = $9,012 + # base_subsidy = min(9,012, 11,492) = $9,012 + # 1-star bonus rate = 0% (threshold = 2 for 5%, 3 for 10%) + # quality_enhanced = 221 * (1 + 0) = 221/wk + # quality_max_monthly = 221 * 52 / 12 = $957.67 + # quality_bonus = 957.67 - 957.67 = 0 + # total = 9,012 / 12 + 0 = $751.00 + ga_caps: 751.00 + +- name: Case 3, quality bonus 2-star gives 5 percent. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 4 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: TWO_STAR + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 10_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_eligible: true + # Same income/fee as Case 2 + ga_caps_family_fee: 82.33 + # base_max_monthly = 221 * 52 / 12 = $957.67 + # pre_subsidy_monthly = 10,000 / 12 = $833.33 + # base_payment = min(833.33, 957.67) = $833.33 + # net_base = max(833.33 - 82.33, 0) = $751.00 + # effective_bonus = (221 * 0.05) / 221 = 0.05 + # subsidy = 751.00 * 1.05 = $788.55 + ga_caps: 788.55 + +- name: Case 4, quality bonus 3-star gives 10 percent. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 4 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: THREE_STAR + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 10_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_eligible: true + ga_caps_family_fee: 82.33 + # net_base = $751.00 (same as Cases 2-3) + # effective_bonus = (221 * 0.10) / 221 = 0.10 + # subsidy = 751.00 * 1.10 = $826.10 + ga_caps: 826.10 + +- name: Case 5, expenses capped at max rate. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 5_000 + immigration_status: CITIZEN + person2: + age: 4 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + # Very high expenses, well above max rate + spm_unit_pre_subsidy_childcare_expenses: 25_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_eligible: true + # FPL ratio = 5,000 / 21,640 = 0.231 -> 3% rate + # weekly fee = floor(5,000 * 0.03 / 52) = floor(2.88) = $2 + # monthly fee = 2 * 52 / 12 = $8.67 + ga_caps_family_fee: 8.67 + # base_max_monthly = 221 * 52 / 12 = $957.67 + # pre_subsidy_monthly = 25,000 / 12 = $2,083.33 + # base_payment = min(2,083.33, 957.67) = $957.67 + # net_base = max(957.67 - 8.67, 0) = $949.00 + # no quality bonus (NONE rating) + # subsidy = $949.00 + ga_caps: 949.00 + +- name: Case 6, minor parent with zero fee and quality bonus. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 17 + employment_income: 15_000 + immigration_status: CITIZEN + is_tax_unit_head: true + person2: + age: 0 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: THREE_STAR + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 10_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_eligible: true + # Minor parent -> $0 fee + ga_caps_family_fee: 0 + # Zone 1, Center, Infant, FT = $260/week + # base_max_monthly = 260 * 52 / 12 = $1,126.67 + # pre_subsidy_monthly = 10,000 / 12 = $833.33 + # base_payment = min(833.33, 1,126.67) = $833.33 + # net_base = max(833.33 - 0, 0) = $833.33 + # effective_bonus = (260 * 0.10) / 260 = 0.10 + # subsidy = 833.33 * 1.10 = $916.67 + ga_caps: 916.67 + +- name: Case 7, two children different age groups and care types. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 15_000 + immigration_status: CITIZEN + person2: + age: 0 + + immigration_status: CITIZEN + ga_caps_provider_type: FAMILY + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: NONE + person3: + age: 7 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: BEFORE_AFTER_SCHOOL + ga_caps_quality_rating: NONE + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_pre_subsidy_childcare_expenses: 12_000 + households: + household: + members: [person1, person2, person3] + state_code: GA + county_str: CHATHAM_COUNTY_GA + output: + ga_caps_eligible_child: [false, true, true] + ga_caps_eligible: true + # Zone 2 (Chatham County) + # Child1 (age 0, Infant): Zone 2, Family, FT = $145/week + # Child2 (age 7, School Age): Zone 2, Center, B/A School = $68/week + ga_caps_maximum_weekly_benefit: [0, 145, 68] + # FPG family of 3 = $27,320 + # FPL ratio = 15,000 / 27,320 = 0.549 -> >= 0.5001 -> 5% rate + # weekly fee = floor(15,000 * 0.05 / 52) = floor(14.42) = $14 + # monthly fee = 14 * 52 / 12 = $60.67 + ga_caps_family_fee: 60.67 + # sum_max_weekly = 145 + 68 = $213 + # sum_max_monthly = $213 * 52/12 = $923.00 + # expenses_monthly = 12,000 / 12 = $1,000 + # base = min($1,000, $923) = $923 + # net_base = max($923 - $60.67, 0) = $862.33 + # no quality bonus (NONE rating) + ga_caps: 862.33 + +- name: Case 8, zero income family gets maximum subsidy up to expenses. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 0 + immigration_status: CITIZEN + person2: + age: 4 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 8_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_eligible: true + # $0 income -> 0% rate -> $0 fee + ga_caps_family_fee: 0 + # Zone 1, Center, Preschool, FT = $221/week + # base_max annual = 221 * 52 = $11,492 + # uncapped = max(8,000 - 0, 0) = $8,000 + # base_subsidy = min(8,000, 11,492) = $8,000 + # monthly = 8,000 / 12 = $666.67 + ga_caps: 666.67 + +- name: Case 9, subsidy with Zone 3 informal lowest rates. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 10_000 + immigration_status: CITIZEN + person2: + age: 8 + + immigration_status: CITIZEN + ga_caps_provider_type: INFORMAL + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 6_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: APPLING_COUNTY_GA + output: + ga_caps_eligible: true + # FPG family of 2: $21,640 + # FPL ratio = 10,000 / 21,640 = 0.462 -> 3% rate + # weekly fee = floor(10,000 * 0.03 / 52) = floor(5.77) = $5 + # monthly fee = 5 * 52 / 12 = $21.67 + ga_caps_family_fee: 21.67 + # Zone 3, Informal, School Age, FT = $94/week + # base_max_monthly = 94 * 52 / 12 = $407.33 + # pre_subsidy_monthly = 6,000 / 12 = $500 + # base_payment = min(500, 407.33) = $407.33 + # net_base = max(407.33 - 21.67, 0) = $385.67 + # no quality bonus (NONE rating) + # subsidy = $385.67 + ga_caps: 385.67 + +- name: Case 10, zero childcare expenses means zero benefit. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 4 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: THREE_STAR + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 0 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_eligible: true + # uncapped = max(0 - fee, 0) = 0 + # base_subsidy = 0 + # quality bonus = 0 (base_subsidy is 0, so no bonus applied) + ga_caps: 0 + +- name: Case 11, part-time care with daily rate conversion. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 10_000 + immigration_status: CITIZEN + person2: + age: 2 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: PART_TIME + ga_caps_quality_rating: NONE + childcare_days_per_week: 3 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 8_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_eligible: true + # Zone 1, Center, Toddler, Part-time = $65/day + # Weekly = 65 * 3 = $195/week + ga_caps_maximum_weekly_benefit: [0, 195] + # FPG family of 2: $21,640 + # FPL ratio = 10,000 / 21,640 = 0.462 -> 3% rate + # weekly fee = floor(10,000 * 0.03 / 52) = floor(5.77) = $5 + # monthly fee = 5 * 52 / 12 = $21.67 + ga_caps_family_fee: 21.67 + # base_max annual = 195 * 52 = $10,140 + # annual fee = 5 * 52 = $260 + # uncapped = max(8,000 - 260, 0) = $7,740 + # base_subsidy = min(7,740, 10,140) = $7,740 + # monthly = 7,740 / 12 = $645.00 + ga_caps: 645.00 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration.yaml new file mode 100644 index 00000000000..311bf8128f5 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration.yaml @@ -0,0 +1,729 @@ +# GA CAPS Integration Tests +# +# 2026 FPG (Contiguous US): +# first_person = 15,960, additional = 5,680 +# Family of 2: 21,640 +# Family of 3: 27,320 +# Family of 4: 33,000 +# +# GA SMI 4-person at 2026-01: $116,773.19 (uprated) +# Family of 2: 116,773.19 * 0.68 = $79,405.77 -> 50% = $39,702.88 +# Family of 3: 116,773.19 * 0.84 = $98,089.48 -> 50% = $49,044.74 +# Family of 4: 116,773.19 * 1.00 = $116,773.19 -> 50% = $58,386.59 + +- name: Case 1, basic eligible family with Zone 1 center care. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 30_000 + immigration_status: CITIZEN + person2: + age: 4 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 11_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + # === Eligibility === + # Child age 4 < 13 -> age eligible + # Citizen -> immigration eligible + ga_caps_eligible_child: [false, true] + + # income 30,000 <= 39,702.88 (50% SMI for family of 2) -> income eligible + ga_caps_income_eligible: true + is_ccdf_asset_eligible: true + ga_caps_eligible: true + + # === Zone and rate === + # Fulton County -> Zone 1 + ga_caps_zone: ZONE_1 + # Age 4 -> PRESCHOOL + ga_caps_age_group: [PRESCHOOL, PRESCHOOL] + # Zone 1, Center, Preschool, Full-time = $221/week + ga_caps_maximum_weekly_benefit: [0, 221] + + # === Family fee === + # FPG family of 2: $21,640 + # FPL ratio = 30,000 / 21,640 = 1.386 -> 7% rate + # weekly fee = floor(30,000 * 0.07 / 52) = floor(40.38) = $40 + # monthly fee = 40 * 52 / 12 = $173.33 + ga_caps_family_fee: 173.33 + + # === Benefit === + # base_max_monthly = 221 * 52 / 12 = $957.67 + # pre_subsidy_monthly = 11,000 / 12 = $916.67 + # base_payment = min(916.67, 957.67) = $916.67 + # net_base = max(916.67 - 173.33, 0) = $743.33 + # no quality bonus (NONE rating) + # subsidy = $743.33 + ga_caps: 743.33 + +- name: Case 2, low income family with zero fee. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + employment_income: 2_000 + immigration_status: CITIZEN + person2: + age: 0 + + immigration_status: CITIZEN + ga_caps_provider_type: FAMILY + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 8_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + # === Eligibility === + ga_caps_eligible_child: [false, true] + ga_caps_income_eligible: true + ga_caps_eligible: true + + # === Zone and rate === + # Zone 1, Family, Infant, Full-time = $199/week + ga_caps_zone: ZONE_1 + ga_caps_age_group: [PRESCHOOL, INFANT] + ga_caps_maximum_weekly_benefit: [0, 199] + + # === Family fee === + # FPL ratio = 2,000 / 21,640 = 0.0924 -> 0% rate (<=10% FPL) + ga_caps_family_fee: 0 + + # === Benefit === + # base_max_monthly = 199 * 52 / 12 = $862.33 + # pre_subsidy_monthly = 8,000 / 12 = $666.67 + # base_payment = min(666.67, 862.33) = $666.67 + # net_base = max(666.67 - 0, 0) = $666.67 + # no quality bonus (NONE rating) + # subsidy = $666.67 + ga_caps: 666.67 + +- name: Case 3, enrolled family at ongoing threshold with quality bonus. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 32 + employment_income: 60_000 + immigration_status: CITIZEN + person2: + age: 2 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: THREE_STAR + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + ga_caps_enrolled: true + spm_unit_pre_subsidy_childcare_expenses: 12_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: CHATHAM_COUNTY_GA + output: + # === Eligibility === + ga_caps_eligible_child: [false, true] + + # enrolled: 60,000 <= 67,494.90 (85% SMI for family of 2) -> eligible + ga_caps_income_eligible: true + ga_caps_eligible: true + + # === Zone and rate === + # Chatham County -> Zone 2 + ga_caps_zone: ZONE_2 + # Age 2 -> TODDLER + ga_caps_age_group: [PRESCHOOL, TODDLER] + # Zone 2, Center, Toddler, Full-time = $160/week + ga_caps_maximum_weekly_benefit: [0, 160] + + # === Family fee === + # FPG family of 2: $21,640 + # FPL ratio = 60,000 / 21,640 = 2.773 -> 7% rate + # weekly fee = floor(60,000 * 0.07 / 52) = floor(80.77) = $80 + # monthly fee = 80 * 52 / 12 = $346.67 + ga_caps_family_fee: 346.67 + + # === Benefit === + # base_max_monthly = 160 * 52 / 12 = $693.33 + # pre_subsidy_monthly = 12,000 / 12 = $1,000 + # base_payment = min(1,000, 693.33) = $693.33 + # net_base = max(693.33 - 346.67, 0) = $346.67 + # effective_bonus = (160 * 0.10) / 160 = 0.10 + # subsidy = 346.67 * 1.10 = $381.33 + ga_caps: 381.33 + +- name: Case 4, ineligible family gets zero benefit. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 40_000 + immigration_status: CITIZEN + person2: + age: 4 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 12_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + # income 40,000 > 39,702.88 (50% SMI for family of 2) -> ineligible + ga_caps_income_eligible: false + ga_caps_eligible: false + ga_caps: 0 + +- name: Case 5, two children with different ages in Zone 3. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 0 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: TWO_STAR + person3: + age: 8 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: BEFORE_AFTER_SCHOOL + ga_caps_quality_rating: TWO_STAR + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_pre_subsidy_childcare_expenses: 10_000 + households: + household: + members: [person1, person2, person3] + state_code: GA + county_str: APPLING_COUNTY_GA + output: + # === Eligibility === + ga_caps_eligible_child: [false, true, true] + + # FPG family of 3: $27,320 + # 50% SMI family of 3 = $49,044.74 + # income 20,000 <= 49,044.74 -> eligible + ga_caps_income_eligible: true + ga_caps_eligible: true + + # === Zone and rate === + # Appling County -> Zone 3 + ga_caps_zone: ZONE_3 + # child1: age 0 -> INFANT, Zone 3 Center FT = $130/week + # child2: age 8 -> SCHOOL_AGE, Zone 3 Center B/A School = $53/week + ga_caps_age_group: [PRESCHOOL, INFANT, SCHOOL_AGE] + ga_caps_maximum_weekly_benefit: [0, 130, 53] + + # === Family fee === + # FPL ratio = 20,000 / 27,320 = 0.732 -> 5% rate + # weekly fee = floor(20,000 * 0.05 / 52) = floor(19.23) = $19 + # monthly fee = 19 * 52 / 12 = $82.33 + ga_caps_family_fee: 82.33 + + # === Benefit === + # sum_max_weekly = 130 + 53 = $183 + # sum_max_monthly = $183 * 52/12 = $793.00 + # expenses_monthly = 10,000 / 12 = $833.33 + # base = min($833.33, $793) = $793.00 + # net_base = max($793 - $82.33, 0) = $710.67 + # weighted_bonus_rate = (130*0.05 + 53*0.05) / 183 = 0.05 + # subsidy = $710.67 * 1.05 = $746.20 + ga_caps: 746.20 + +- name: Case 6, disabled teenager with family care in Zone 2. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + employment_income: 35_000 + immigration_status: CITIZEN + person2: + age: 15 + + is_disabled: true + immigration_status: CITIZEN + ga_caps_provider_type: FAMILY + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 7_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: BIBB_COUNTY_GA + output: + # === Eligibility === + # disabled, age 15 <= 17 -> eligible child + ga_caps_eligible_child: [false, true] + + # income 35,000 <= 39,702.88 (50% SMI for family of 2) -> eligible + ga_caps_income_eligible: true + ga_caps_eligible: true + + # === Zone and rate === + # Bibb County -> Zone 2 + ga_caps_zone: ZONE_2 + # Age 15 -> SCHOOL_AGE + ga_caps_age_group: [PRESCHOOL, SCHOOL_AGE] + # Zone 2, Family, School Age, Full-time = $135/week + ga_caps_maximum_weekly_benefit: [0, 135] + + # === Family fee === + # FPG family of 2: $21,640 + # FPL ratio = 35,000 / 21,640 = 1.618 -> 7% rate + # weekly fee = floor(35,000 * 0.07 / 52) = floor(47.12) = $47 + # monthly fee = 47 * 52 / 12 = $203.67 + ga_caps_family_fee: 203.67 + + # === Benefit === + # base_max_monthly = 135 * 52 / 12 = $585.00 + # pre_subsidy_monthly = 7,000 / 12 = $583.33 + # base_payment = min(583.33, 585.00) = $583.33 + # net_base = max(583.33 - 203.67, 0) = $379.67 + # no quality bonus (NONE rating) + # subsidy = $379.67 + ga_caps: 379.67 + +- name: Case 7, non-Georgia family gets zero benefit. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 4 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 10_000 + households: + household: + members: [person1, person2] + state_code: FL + output: + ga_caps: 0 + +# 2026 FPG family of 5: 38,680; family of 6: 44,360 +# 50% SMI family of 5 = $67,728.45; family of 6 = $77,070.30 + +- name: Case 8, large family of 6 at income threshold boundary. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 73_085 + immigration_status: CITIZEN + person2: + age: 38 + immigration_status: CITIZEN + person3: + age: 10 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: BEFORE_AFTER_SCHOOL + ga_caps_quality_rating: NONE + person4: + age: 3 + + immigration_status: CITIZEN + ga_caps_provider_type: FAMILY + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: TWO_STAR + person5: + age: 0 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: TWO_STAR + person6: + age: 14 + + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2, person3, person4, person5, person6] + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2, person3, person4, person5, person6] + state_code: GA + county_str: COBB_COUNTY_GA + output: + # === Eligibility === + # person3 (10): age < 13 -> eligible + # person4 (3): age < 13 -> eligible + # person5 (0): age < 13 -> eligible + # person6 (14): age >= 13, not disabled -> ineligible + ga_caps_eligible_child: [false, false, true, true, true, false] + + # 50% SMI family of 6 = $77,070.30 + # income 73,085 <= 77,070.30 -> eligible + ga_caps_income_eligible: true + ga_caps_eligible: true + + # === Zone and rates === + # Cobb County -> Zone 1 + ga_caps_zone: ZONE_1 + # person3 (10): SCHOOL_AGE, Zone 1 Center B/A School = $84/week + # person4 (3): PRESCHOOL, Zone 1 Family FT = $180/week + # person5 (0): INFANT, Zone 1 Center FT = $260/week + ga_caps_age_group: [PRESCHOOL, PRESCHOOL, SCHOOL_AGE, PRESCHOOL, INFANT, PRESCHOOL] + ga_caps_maximum_weekly_benefit: [0, 0, 84, 180, 260, 0] + + # === Family fee === + # FPG family of 6: $44,360 + # FPL ratio = 73,085 / 44,360 = 1.648 -> 7% rate + # weekly fee = floor(73,085 * 0.07 / 52) = floor(98.38) = $98 + # monthly fee = 98 * 52 / 12 = $424.67 + ga_caps_family_fee: 424.67 + + # === Benefit === + # sum_max_weekly = 84 + 180 + 260 = $524 + # sum_max_monthly = $524 * 52/12 = $2,270.67 + # expenses_monthly = 20,000 / 12 = $1,666.67 + # base = min($1,666.67, $2,270.67) = $1,666.67 + # net_base = max($1,666.67 - $424.67, 0) = $1,242.00 + # weighted_bonus_rate = (84*0 + 180*0.05 + 260*0.05) / 524 = 0.04198 + # subsidy = $1,242.00 * 1.04198 = $1,294.14 + ga_caps: 1_294.14 + +- name: Case 9, enrolled family between 50 and 85 percent SMI. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 50_000 + immigration_status: CITIZEN + person2: + age: 1 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: THREE_STAR + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + ga_caps_enrolled: true + spm_unit_pre_subsidy_childcare_expenses: 15_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: DEKALB_COUNTY_GA + output: + # === Eligibility === + ga_caps_eligible_child: [false, true] + # enrolled: 50,000 <= 67,494.90 (85% SMI) -> eligible + # NOT eligible as new applicant: 50,000 > 39,702.88 (50% SMI) + ga_caps_income_eligible: true + ga_caps_eligible: true + + # === Zone and rates === + # DeKalb County -> Zone 1 + ga_caps_zone: ZONE_1 + # Age 1 -> TODDLER, Zone 1 Center FT = $248/week + ga_caps_age_group: [PRESCHOOL, TODDLER] + ga_caps_maximum_weekly_benefit: [0, 248] + + # === Family fee === + # FPG family of 2: $21,640 + # FPL ratio = 50,000 / 21,640 = 2.311 -> 7% rate + # weekly fee = floor(50,000 * 0.07 / 52) = floor(67.31) = $67 + # monthly fee = 67 * 52 / 12 = $290.33 + ga_caps_family_fee: 290.33 + + # === Benefit === + # pre_subsidy_weekly = 15,000 / 52 = $288.46 + # per_child = min($248, $288.46) = $248 + # base_monthly = $248 * 52/12 = $1,074.67 + # net_base = max($1,074.67 - $290.33, 0) = $784.33 + # weighted_bonus_rate = ($248 * 0.10) / $248 = 0.10 + # subsidy = $784.33 * 1.10 = $862.77 + ga_caps: 862.77 + +- name: Case 10, non-enrolled family at 50 percent SMI plus 1 dollar is ineligible. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 39_703 + immigration_status: CITIZEN + person2: + age: 4 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: THREE_STAR + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 12_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_eligible_child: [false, true] + # 39,703 > 39,702.88 (50% SMI for family of 2) -> ineligible + ga_caps_income_eligible: false + ga_caps_eligible: false + ga_caps: 0 + +- name: Case 11, mixed eligible and ineligible children in family. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + employment_income: 30_000 + immigration_status: CITIZEN + person2: + age: 5 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: NONE + person3: + age: 14 + + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_pre_subsidy_childcare_expenses: 10_000 + households: + household: + members: [person1, person2, person3] + state_code: GA + county_str: BIBB_COUNTY_GA + output: + # person2 (5): eligible, person3 (14): ineligible (not disabled) + ga_caps_eligible_child: [false, true, false] + # Family has at least one eligible child -> eligible + ga_caps_eligible: true + # Bibb -> Zone 2 + ga_caps_zone: ZONE_2 + # Only person2 gets a rate: Zone 2 Center Preschool FT = $150/week + # person3 is not an eligible child -> 0 rate + ga_caps_maximum_weekly_benefit: [0, 150, 0] + # FPG family of 3 = $27,320 + # FPL ratio = 30,000 / 27,320 = 1.098 -> 7% rate + # weekly fee = floor(30,000 * 0.07 / 52) = floor(40.38) = $40 + # monthly fee = 40 * 52 / 12 = $173.33 + ga_caps_family_fee: 173.33 + # pre_subsidy_weekly = 10,000 / 52 / 1 = $192.31 (only 1 eligible child) + # per_child = min($150, $192.31) = $150 + # base_monthly = $150 * 52/12 = $650 + # net_base = max($650 - $173.33, 0) = $476.67 + # no quality bonus (NONE) + ga_caps: 476.67 + +- name: Case 12, disabled child age 16 with family provider in Zone 3. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 50 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 16 + + is_disabled: true + immigration_status: CITIZEN + ga_caps_provider_type: FAMILY + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: TWO_STAR + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 5_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: APPLING_COUNTY_GA + output: + # disabled child age 16 <= 17 -> eligible + ga_caps_eligible_child: [false, true] + ga_caps_eligible: true + # Appling -> Zone 3 + ga_caps_zone: ZONE_3 + # Age 16 -> SCHOOL_AGE, Zone 3 Family FT = $94/week + ga_caps_maximum_weekly_benefit: [0, 94] + # FPG family of 2 = $21,640 + # FPL ratio = 20,000 / 21,640 = 0.924 -> 5% rate + # weekly fee = floor(20,000 * 0.05 / 52) = floor(19.23) = $19 + # monthly fee = 19 * 52 / 12 = $82.33 + ga_caps_family_fee: 82.33 + # pre_subsidy_weekly = 5,000 / 52 = $96.15 + # per_child = min($94, $96.15) = $94 + # base_monthly = $94 * 52/12 = $407.33 + # net_base = max($407.33 - $82.33, 0) = $325.00 + # weighted_bonus_rate = ($94 * 0.05) / $94 = 0.05 + # subsidy = $325.00 * 1.05 = $341.25 + ga_caps: 341.25 + +- name: Case 13, two-parent family where one is a student. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + weekly_hours_worked: 24 + person2: + age: 28 + immigration_status: CITIZEN + weekly_hours_worked: 0 + is_full_time_student: true + person3: + age: 4 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: NONE + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + meets_ccdf_activity_test: false + spm_unit_pre_subsidy_childcare_expenses: 10_000 + households: + household: + members: [person1, person2, person3] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_eligible_child: [false, false, true] + # parent1: 24 hrs >= 24 -> ok + # parent2: student -> ok + # GA-specific activity gate isolated by pinning meets_ccdf_activity_test=false + ga_caps_activity_eligible: true + ga_caps_eligible: true + # Zone 1, Center, Preschool, FT = $221/week + ga_caps_maximum_weekly_benefit: [0, 0, 221] + # FPG family of 3 = $27,320 + # FPL ratio = 20,000 / 27,320 = 0.732 -> 5% rate + # weekly fee = floor(20,000 * 0.05 / 52) = floor(19.23) = $19 + # monthly fee = 19 * 52 / 12 = $82.33 + ga_caps_family_fee: 82.33 + # pre_subsidy_weekly = 10,000 / 52 = $192.31 + # per_child = min($221, $192.31) = $192.31 + # base_monthly = $192.31 * 52/12 = $833.33 + # net_base = max($833.33 - $82.33, 0) = $751.00 + # no quality bonus (NONE) + ga_caps: 751.00 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_age_group.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_age_group.yaml new file mode 100644 index 00000000000..1cb9caaec3b --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_age_group.yaml @@ -0,0 +1,168 @@ +# GA CAPS age groups: +# INFANT: age < 1 +# TODDLER: 1 <= age < 3 +# PRESCHOOL: 3 <= age < 6 +# SCHOOL_AGE: age >= 6 +# Age group only computed for eligible children (defined_for = ga_caps_eligible_child). +# Non-eligible persons get default PRESCHOOL. + +- name: Case 1, infant age 0. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 0 + + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_age_group: [PRESCHOOL, INFANT] + +- name: Case 2, toddler age 1. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 1 + + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_age_group: [PRESCHOOL, TODDLER] + +- name: Case 3, toddler age 2. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 2 + + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_age_group: [PRESCHOOL, TODDLER] + +- name: Case 4, preschool age 3. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 3 + + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_age_group: [PRESCHOOL, PRESCHOOL] + +- name: Case 5, preschool age 5. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_age_group: [PRESCHOOL, PRESCHOOL] + +- name: Case 6, school age 6. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 6 + + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_age_group: [PRESCHOOL, SCHOOL_AGE] + +- name: Case 7, school age 10. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 10 + + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_age_group: [PRESCHOOL, SCHOOL_AGE] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit.yaml new file mode 100644 index 00000000000..bb04ce7ebf5 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit.yaml @@ -0,0 +1,425 @@ +# GA CAPS maximum reimbursement rate lookup +# Rates from Appendix C (effective March 2, 2026) +# Person-level variable; parent output is 0, child gets rate + +- name: Case 1, Zone 1 center full-time infant. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 0 + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + # Zone 1, Center, Infant, Full-time = $260/week + ga_caps_maximum_weekly_benefit: [0, 260] + +- name: Case 2, Zone 1 center full-time toddler. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 2 + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: COBB_COUNTY_GA + output: + # Zone 1, Center, Toddler, Full-time = $248/week + ga_caps_maximum_weekly_benefit: [0, 248] + +- name: Case 3, Zone 1 center full-time preschool. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 4 + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: DEKALB_COUNTY_GA + output: + # Zone 1, Center, Preschool, Full-time = $221/week + ga_caps_maximum_weekly_benefit: [0, 221] + +- name: Case 4, Zone 1 center full-time school age. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 8 + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: GWINNETT_COUNTY_GA + output: + # Zone 1, Center, School Age, Full-time = $185/week + ga_caps_maximum_weekly_benefit: [0, 185] + +- name: Case 5, Zone 2 center full-time infant. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 0 + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: CHATHAM_COUNTY_GA + output: + # Zone 2, Center, Infant, Full-time = $165/week + ga_caps_maximum_weekly_benefit: [0, 165] + +- name: Case 6, Zone 3 center full-time school age. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 8 + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: APPLING_COUNTY_GA + output: + # Zone 3, Center, School Age, Full-time = $115/week + ga_caps_maximum_weekly_benefit: [0, 115] + +- name: Case 7, Zone 1 family full-time infant. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 0 + ga_caps_provider_type: FAMILY + ga_caps_care_type: FULL_TIME + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + # Zone 1, Family, Infant, Full-time = $199/week + ga_caps_maximum_weekly_benefit: [0, 199] + +- name: Case 8, Zone 2 family full-time toddler. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 2 + ga_caps_provider_type: FAMILY + ga_caps_care_type: FULL_TIME + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: BIBB_COUNTY_GA + output: + # Zone 2, Family, Toddler, Full-time = $140/week + ga_caps_maximum_weekly_benefit: [0, 140] + +- name: Case 9, Zone 3 informal full-time preschool. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 4 + ga_caps_provider_type: INFORMAL + ga_caps_care_type: FULL_TIME + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: APPLING_COUNTY_GA + output: + # Zone 3, Informal, Preschool, Full-time = $105/week + ga_caps_maximum_weekly_benefit: [0, 105] + +- name: Case 10, Zone 1 center part-time. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 4 + ga_caps_provider_type: CENTER + ga_caps_care_type: PART_TIME + childcare_days_per_week: 1 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + # Zone 1, Center, Part-time = $65/day * 1 day = $65/week + ga_caps_maximum_weekly_benefit: [0, 65] + +- name: Case 11, Zone 2 family part-time. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 2 + ga_caps_provider_type: FAMILY + ga_caps_care_type: PART_TIME + childcare_days_per_week: 1 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: CHATHAM_COUNTY_GA + output: + # Zone 2, Family, Part-time = $40/day * 1 day = $40/week + ga_caps_maximum_weekly_benefit: [0, 40] + +- name: Case 12, Zone 1 center before-after school. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 8 + ga_caps_provider_type: CENTER + ga_caps_care_type: BEFORE_AFTER_SCHOOL + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + # Zone 1, Center, Before/After School = $84/week + ga_caps_maximum_weekly_benefit: [0, 84] + +- name: Case 13, Zone 3 informal before-after school. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 7 + ga_caps_provider_type: INFORMAL + ga_caps_care_type: BEFORE_AFTER_SCHOOL + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: APPLING_COUNTY_GA + output: + # Zone 3, Informal, Before/After School = $47/week + ga_caps_maximum_weekly_benefit: [0, 47] + +- name: Case 14, Zone 3 family full-time school age. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 10 + ga_caps_provider_type: FAMILY + ga_caps_care_type: FULL_TIME + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: APPLING_COUNTY_GA + output: + # Zone 3, Family, School Age, Full-time = $94/week + ga_caps_maximum_weekly_benefit: [0, 94] + +- name: Case 15, Zone 1 center part-time infant 3 days per week. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 0 + ga_caps_provider_type: CENTER + ga_caps_care_type: PART_TIME + childcare_days_per_week: 3 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + # Zone 1, Center, Infant, Part-time = $65/day + # Weekly = 65 * 3 = $195 + ga_caps_maximum_weekly_benefit: [0, 195] + +- name: Case 16, Zone 1 center part-time infant 5 days per week. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 0 + ga_caps_provider_type: CENTER + ga_caps_care_type: PART_TIME + childcare_days_per_week: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + # Zone 1, Center, Infant, Part-time = $65/day + # Weekly = 65 * 5 = $325 + ga_caps_maximum_weekly_benefit: [0, 325] + +- name: Case 17, Zone 3 informal part-time school-age 2 days per week. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 8 + ga_caps_provider_type: INFORMAL + ga_caps_care_type: PART_TIME + childcare_days_per_week: 2 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: APPLING_COUNTY_GA + output: + # Zone 3, Informal, School Age, Part-time = $35/day + # Weekly = 35 * 2 = $70 + ga_caps_maximum_weekly_benefit: [0, 70] + +- name: Case 18, Zone 2 family before-after school toddler. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 2 + ga_caps_provider_type: FAMILY + ga_caps_care_type: BEFORE_AFTER_SCHOOL + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: CHATHAM_COUNTY_GA + output: + # Zone 2, Family, Toddler, Before-After-School = $58/week (not daily) + ga_caps_maximum_weekly_benefit: [0, 58] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_zone.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_zone.yaml new file mode 100644 index 00000000000..c9f57d7d7df --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_zone.yaml @@ -0,0 +1,103 @@ +# GA CAPS zone assignment +# Zone 1: 14 counties (Fulton, Cobb, DeKalb, etc.) +# Zone 2: 46 counties (Chatham, Bibb, etc.) +# Zone 3: all remaining counties (default) + +- name: Case 1, Fulton County is Zone 1. + period: 2026-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_zone: ZONE_1 + +- name: Case 2, Cobb County is Zone 1. + period: 2026-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: GA + county_str: COBB_COUNTY_GA + output: + ga_caps_zone: ZONE_1 + +- name: Case 3, Chatham County is Zone 2. + period: 2026-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: GA + county_str: CHATHAM_COUNTY_GA + output: + ga_caps_zone: ZONE_2 + +- name: Case 4, Bibb County is Zone 2. + period: 2026-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: GA + county_str: BIBB_COUNTY_GA + output: + ga_caps_zone: ZONE_2 + +- name: Case 5, Appling County is Zone 3. + period: 2026-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: GA + county_str: APPLING_COUNTY_GA + output: + # Not in Zone 1 or Zone 2 -> Zone 3 (default) + ga_caps_zone: ZONE_3 + +- name: Case 6, Camden County is Zone 1. + period: 2026-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: GA + county_str: CAMDEN_COUNTY_GA + output: + ga_caps_zone: ZONE_1 + +- name: Case 7, Tift County is Zone 2. + period: 2026-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: GA + county_str: TIFT_COUNTY_GA + output: + ga_caps_zone: ZONE_2 diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/copay/ga_caps_family_fee.py b/policyengine_us/variables/gov/states/ga/decal/caps/copay/ga_caps_family_fee.py new file mode 100644 index 00000000000..8bd0eb2cfc7 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/copay/ga_caps_family_fee.py @@ -0,0 +1,38 @@ +from policyengine_us.model_api import * + + +class ga_caps_family_fee(Variable): + value_type = float + entity = SPMUnit + unit = USD + label = "Georgia CAPS family fee (co-payment)" + definition_period = MONTH + defined_for = StateCode.GA + reference = ( + "https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixD-Family%20Fee%20Assessment%20Chart.pdf", + "https://www.decal.ga.gov/documents/attachments/CCDFStatePlan25-27.pdf#page=49", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ga.decal.caps.family_fee + # Minor parent fee waiver: parents age <= 17 have no fee. + person = spm_unit.members + is_head_or_spouse = person("is_tax_unit_head_or_spouse", period.this_year) + age = person("age", period.this_year) + has_minor_parent = spm_unit.any(is_head_or_spouse & (age <= p.minor_parent_age)) + # Compute fee from FPL-ratio scale bracket. + countable_income = spm_unit("ga_caps_countable_income", period) + fpg = spm_unit("spm_unit_fpg", period) + mask = fpg > 0 + fpl_ratio = np.divide( + countable_income, + fpg, + out=np.zeros_like(countable_income), + where=mask, + ) + fee_rate = p.rate.calc(fpl_ratio) + # Weekly fee = floor(annual income * rate / 52), then convert to monthly. + annual_income = countable_income * MONTHS_IN_YEAR + weekly_fee = np.floor(annual_income * fee_rate / WEEKS_IN_YEAR) + monthly_fee = weekly_fee * (WEEKS_IN_YEAR / MONTHS_IN_YEAR) + return where(has_minor_parent, 0, monthly_fee) diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.py b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.py new file mode 100644 index 00000000000..263747726d5 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.py @@ -0,0 +1,26 @@ +from policyengine_us.model_api import * + + +class ga_caps_activity_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for Georgia CAPS based on activity requirements" + definition_period = MONTH + defined_for = StateCode.GA + reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=33" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ga.decal.caps.activity_requirements + person = spm_unit.members + is_head_or_spouse = person("is_tax_unit_head_or_spouse", period.this_year) + hours_worked = person("weekly_hours_worked", period.this_year) + meets_work_requirement = hours_worked >= p.weekly_hours + is_student = person("is_full_time_student", period.this_year) + is_disabled = person("is_disabled", period.this_year) + # Per Policy Manual §6.8.1.8, a disabled parent who cannot provide care + # is exempt from the activity requirement; authorization is based on + # the non-disabled parent's activity. + individually_eligible = meets_work_requirement | is_student | is_disabled + all_heads_meet = ~spm_unit.any(is_head_or_spouse & ~individually_eligible) + meets_ccdf = spm_unit("meets_ccdf_activity_test", period.this_year) + return all_heads_meet | meets_ccdf diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible.py b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible.py new file mode 100644 index 00000000000..113bc8e6911 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class ga_caps_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for Georgia CAPS" + definition_period = MONTH + defined_for = StateCode.GA + reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=29" + + def formula(spm_unit, period, parameters): + has_eligible_child = add(spm_unit, period, ["ga_caps_eligible_child"]) > 0 + income_eligible = spm_unit("ga_caps_income_eligible", period) + asset_eligible = spm_unit("is_ccdf_asset_eligible", period.this_year) + activity_eligible = spm_unit("ga_caps_activity_eligible", period) + return has_eligible_child & income_eligible & asset_eligible & activity_eligible diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.py b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.py new file mode 100644 index 00000000000..8fc436499bf --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.py @@ -0,0 +1,23 @@ +from policyengine_us.model_api import * + + +class ga_caps_eligible_child(Variable): + value_type = bool + entity = Person + label = "Eligible child for Georgia CAPS" + definition_period = MONTH + defined_for = StateCode.GA + reference = ( + "https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=29", + "https://www.decal.ga.gov/documents/attachments/CCDFStatePlan25-27.pdf#page=16", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.states.ga.decal.caps.age_threshold + age = person("age", period.this_year) + is_disabled = person("is_disabled", period.this_year) + age_eligible = where(is_disabled, age <= p.disabled_child, age < p.child) + immigration_eligible = person( + "is_ccdf_immigration_eligible_child", period.this_year + ) + return age_eligible & immigration_eligible diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible.py b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible.py new file mode 100644 index 00000000000..652a64c41f0 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible.py @@ -0,0 +1,23 @@ +from policyengine_us.model_api import * + + +class ga_caps_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for Georgia CAPS based on income" + definition_period = MONTH + defined_for = StateCode.GA + reference = ( + "https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=48", + "https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixA-CAPS%20Maximum%20Income%20Limits%20by%20Family%20Size.pdf", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ga.decal.caps.income.smi_rate + countable_income = spm_unit("ga_caps_countable_income", period) + smi = spm_unit("hhs_smi", period) + enrolled = spm_unit("ga_caps_enrolled", period) + initial_limit = smi * p.initial_eligibility + ongoing_limit = smi * p.ongoing_eligibility + income_limit = where(enrolled, ongoing_limit, initial_limit) + return countable_income <= income_limit diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/ga_caps.py b/policyengine_us/variables/gov/states/ga/decal/caps/ga_caps.py new file mode 100644 index 00000000000..5a08d46f624 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/ga_caps.py @@ -0,0 +1,50 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.ga.decal.caps.payment.ga_caps_quality_rating import ( + GACAPSQualityRating, +) + + +class ga_caps(Variable): + value_type = float + entity = SPMUnit + unit = USD + label = "Georgia CAPS benefit amount" + definition_period = MONTH + defined_for = "ga_caps_eligible" + reference = ( + "https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=55", + "https://www.decal.ga.gov/documents/attachments/CCDFStatePlan25-27.pdf#page=69", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ga.decal.caps + person = spm_unit.members + + max_weekly = person("ga_caps_maximum_weekly_benefit", period) + sum_max_weekly = spm_unit.sum(max_weekly) + sum_max_monthly = sum_max_weekly * (WEEKS_IN_YEAR / MONTHS_IN_YEAR) + + expenses_monthly = spm_unit("spm_unit_pre_subsidy_childcare_expenses", period) + base_monthly = min_(expenses_monthly, sum_max_monthly) + + family_fee = spm_unit("ga_caps_family_fee", period) + net_base = max_(base_monthly - family_fee, 0) + + quality_rating = person("ga_caps_quality_rating", period) + star_count = select( + [ + quality_rating == GACAPSQualityRating.ONE_STAR, + quality_rating == GACAPSQualityRating.TWO_STAR, + quality_rating == GACAPSQualityRating.THREE_STAR, + ], + [1, 2, 3], + default=0, + ) + bonus_rate = p.quality_rated.bonus_rate.calc(star_count) + weighted_bonus = spm_unit.sum(max_weekly * bonus_rate) + effective_bonus_rate = where( + sum_max_weekly > 0, + weighted_bonus / sum_max_weekly, + 0, + ) + return net_base * (1 + effective_bonus_rate) diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/ga_caps_enrolled.py b/policyengine_us/variables/gov/states/ga/decal/caps/ga_caps_enrolled.py new file mode 100644 index 00000000000..2727868d864 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/ga_caps_enrolled.py @@ -0,0 +1,9 @@ +from policyengine_us.model_api import * + + +class ga_caps_enrolled(Variable): + value_type = bool + entity = SPMUnit + definition_period = MONTH + label = "Whether the family is currently enrolled in Georgia CAPS" + defined_for = StateCode.GA diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/ga_child_care_subsidies.py b/policyengine_us/variables/gov/states/ga/decal/caps/ga_child_care_subsidies.py new file mode 100644 index 00000000000..8da965033d6 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/ga_child_care_subsidies.py @@ -0,0 +1,11 @@ +from policyengine_us.model_api import * + + +class ga_child_care_subsidies(Variable): + value_type = float + entity = SPMUnit + label = "Georgia child care subsidies" + unit = USD + definition_period = YEAR + defined_for = StateCode.GA + adds = ["ga_caps"] diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/income/ga_caps_countable_income.py b/policyengine_us/variables/gov/states/ga/decal/caps/income/ga_caps_countable_income.py new file mode 100644 index 00000000000..d737a5237f7 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/income/ga_caps_countable_income.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class ga_caps_countable_income(Variable): + value_type = float + entity = SPMUnit + label = "Georgia CAPS countable income" + definition_period = MONTH + unit = USD + defined_for = StateCode.GA + reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=48" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ga.decal.caps.income.countable_income + sources = p.sources + person = spm_unit.members + is_adult = person("is_adult", period.this_year) + adult_income = sum(person(source, period) * is_adult for source in sources) + return spm_unit.sum(adult_income) diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_age_group.py b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_age_group.py new file mode 100644 index 00000000000..f141b5ee267 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_age_group.py @@ -0,0 +1,36 @@ +from policyengine_us.model_api import * + + +class GACAPSAgeGroup(Enum): + INFANT = "Infant" + TODDLER = "Toddler" + PRESCHOOL = "Preschool" + SCHOOL_AGE = "School Age" + + +class ga_caps_age_group(Variable): + value_type = Enum + entity = Person + possible_values = GACAPSAgeGroup + default_value = GACAPSAgeGroup.PRESCHOOL + definition_period = MONTH + defined_for = "ga_caps_eligible_child" + label = "Georgia CAPS child age group" + reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=1" + + def formula(person, period, parameters): + age = person("age", period.this_year) + p = parameters(period).gov.states.ga.decal.caps.age_group + return select( + [ + age < p.toddler_min, + age < p.preschool_min, + age < p.school_age_min, + ], + [ + GACAPSAgeGroup.INFANT, + GACAPSAgeGroup.TODDLER, + GACAPSAgeGroup.PRESCHOOL, + ], + default=GACAPSAgeGroup.SCHOOL_AGE, + ) diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_care_type.py b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_care_type.py new file mode 100644 index 00000000000..1a343d704b7 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_care_type.py @@ -0,0 +1,18 @@ +from policyengine_us.model_api import * + + +class GACAPSCareType(Enum): + FULL_TIME = "Full Time" + PART_TIME = "Part Time" + BEFORE_AFTER_SCHOOL = "Before and After School" + + +class ga_caps_care_type(Variable): + value_type = Enum + entity = Person + possible_values = GACAPSCareType + default_value = GACAPSCareType.FULL_TIME + definition_period = MONTH + label = "Georgia CAPS care type" + defined_for = StateCode.GA + reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=1" diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit.py b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit.py new file mode 100644 index 00000000000..8455e3182a1 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit.py @@ -0,0 +1,40 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.ga.decal.caps.payment.ga_caps_provider_type import ( + GACAPSProviderType, +) + + +class ga_caps_maximum_weekly_benefit(Variable): + value_type = float + entity = Person + unit = USD + label = "Georgia CAPS maximum weekly benefit per child" + definition_period = MONTH + defined_for = "ga_caps_eligible_child" + reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=1" + + def formula(person, period, parameters): + p = parameters(period).gov.states.ga.decal.caps.rates + zone = person.household("ga_caps_zone", period) + age_group = person("ga_caps_age_group", period) + care_type = person("ga_caps_care_type", period) + provider_type = person("ga_caps_provider_type", period) + + center_rate = p.center[zone][age_group][care_type] + family_rate = p.family[zone][age_group][care_type] + informal_rate = p.informal[zone][age_group][care_type] + + rate = select( + [ + provider_type == GACAPSProviderType.CENTER, + provider_type == GACAPSProviderType.FAMILY, + provider_type == GACAPSProviderType.INFORMAL, + ], + [center_rate, family_rate, informal_rate], + default=center_rate, + ) + + # Part-time rates are daily; convert to weekly using days per week. + is_part_time = care_type == care_type.possible_values.PART_TIME + days_per_week = person("childcare_days_per_week", period.this_year) + return where(is_part_time, rate * days_per_week, rate) diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_provider_type.py b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_provider_type.py new file mode 100644 index 00000000000..24c0c549d22 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_provider_type.py @@ -0,0 +1,18 @@ +from policyengine_us.model_api import * + + +class GACAPSProviderType(Enum): + CENTER = "Center" + FAMILY = "Family" + INFORMAL = "Informal" + + +class ga_caps_provider_type(Variable): + value_type = Enum + entity = Person + possible_values = GACAPSProviderType + default_value = GACAPSProviderType.CENTER + definition_period = MONTH + label = "Georgia CAPS child care provider type" + defined_for = StateCode.GA + reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=1" diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_quality_rating.py b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_quality_rating.py new file mode 100644 index 00000000000..54996cc9dc8 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_quality_rating.py @@ -0,0 +1,21 @@ +from policyengine_us.model_api import * + + +class GACAPSQualityRating(Enum): + ONE_STAR = "1 Star" + TWO_STAR = "2 Stars" + THREE_STAR = "3 Stars" + NONE = "None" + + +class ga_caps_quality_rating(Variable): + value_type = Enum + entity = Person + possible_values = GACAPSQualityRating + default_value = GACAPSQualityRating.NONE + definition_period = MONTH + label = "Georgia CAPS provider Quality Rated designation" + defined_for = StateCode.GA + reference = ( + "https://www.decal.ga.gov/documents/attachments/CCDFStatePlan25-27.pdf#page=69" + ) diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_zone.py b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_zone.py new file mode 100644 index 00000000000..61cb98c5f76 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_zone.py @@ -0,0 +1,29 @@ +from policyengine_us.model_api import * + + +class GACAPSZone(Enum): + ZONE_1 = "Zone 1" + ZONE_2 = "Zone 2" + ZONE_3 = "Zone 3" + + +class ga_caps_zone(Variable): + value_type = Enum + entity = Household + possible_values = GACAPSZone + default_value = GACAPSZone.ZONE_3 + definition_period = MONTH + defined_for = StateCode.GA + label = "Georgia CAPS geographic zone" + reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=2" + + def formula(household, period, parameters): + county = household("county_str", period) + p = parameters(period).gov.states.ga.decal.caps + is_zone_1 = np.isin(county, p.zone_1_counties) + is_zone_2 = np.isin(county, p.zone_2_counties) + return select( + [is_zone_1, is_zone_2], + [GACAPSZone.ZONE_1, GACAPSZone.ZONE_2], + default=GACAPSZone.ZONE_3, + ) diff --git a/uv.lock b/uv.lock index 76042ff3b95..040a348fa5b 100644 --- a/uv.lock +++ b/uv.lock @@ -2974,7 +2974,7 @@ wheels = [ [[package]] name = "policyengine-us" -version = "1.691.7" +version = "1.691.10" source = { editable = "." } dependencies = [ { name = "microdf-python" },