diff --git a/changelog.d/fix-nj-ccap-copay-attending-children.fixed.md b/changelog.d/fix-nj-ccap-copay-attending-children.fixed.md new file mode 100644 index 00000000000..39b5a2b99fc --- /dev/null +++ b/changelog.d/fix-nj-ccap-copay-attending-children.fixed.md @@ -0,0 +1 @@ +Scale the New Jersey CCAP family co-payment by children actually receiving care, not just all eligible children. diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_copay.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_copay.yaml index c984dd03a56..ae051ede81b 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_copay.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ccap/nj_ccap_copay.yaml @@ -396,3 +396,82 @@ state_code: NJ output: nj_ccap_copay: 0 + +- name: Case 11, two eligible children but only one attending uses first-child rate. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + parent: + age: 35 + employment_income: 31_000 + immigration_status: CITIZEN + kid_in_care: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 35 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + kid_not_in_care: + age: 6 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 0 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [parent, kid_in_care, kid_not_in_care] + spm_units: + spm_unit: + members: [parent, kid_in_care, kid_not_in_care] + households: + household: + members: [parent, kid_in_care, kid_not_in_care] + state_code: NJ + output: + # Copay scales with children actually attending care, not just those + # eligible. FPG family of 3 = 27_320; FPL ratio = 31_000/27_320 = 1.134. + # 1 child FT in care at 101-200% FPL -> first child FT rate 2%. + # monthly copay = 31_000 * 0.02 / 12 = 51.67 + nj_ccap_copay: 51.67 + +- name: Case 12, two eligible children with only one PT attending uses first-child PT rate. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + parent: + age: 35 + employment_income: 40_000 + immigration_status: CITIZEN + kid_in_care: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 20 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + kid_not_in_care: + age: 7 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_week: 0 + nj_ccap_provider_type: LICENSED_CENTER + nj_ccap_grow_nj_kids_rating: NONE + tax_units: + tax_unit: + members: [parent, kid_in_care, kid_not_in_care] + spm_units: + spm_unit: + members: [parent, kid_in_care, kid_not_in_care] + households: + household: + members: [parent, kid_in_care, kid_not_in_care] + state_code: NJ + output: + # FPG family of 3 = 27_320; FPL ratio = 40_000/27_320 = 1.464. + # Only one attending child (PT) -> first child PT rate 1%. + # monthly copay = 40_000 * 0.01 / 12 = 33.33 + nj_ccap_copay: 33.33 diff --git a/policyengine_us/variables/gov/states/nj/njdhs/ccap/copay/nj_ccap_copay.py b/policyengine_us/variables/gov/states/nj/njdhs/ccap/copay/nj_ccap_copay.py index e995ce0bd12..6c79de953b9 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/ccap/copay/nj_ccap_copay.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/ccap/copay/nj_ccap_copay.py @@ -26,10 +26,16 @@ def formula(spm_unit, period, parameters): is_eligible_child = person("nj_ccap_eligible_child", period) time_category = person("nj_ccap_time_category", period) is_ft = time_category == NJCCAPTimeCategory.FULL_TIME - - n_eligible = spm_unit.sum(is_eligible_child) - n_ft = spm_unit.sum(is_eligible_child & is_ft) - has_second_child = n_eligible >= 2 + # Copay scales with children actually receiving care, not merely + # those who would be eligible. Follows the VA CCSP (va_ccsp_copay) + # and SC CCAP (sc_ccap_copay) pattern of gating the child count on + # an "in care" flag. + in_care = person("childcare_hours_per_week", period.this_year) > 0 + is_paying_child = is_eligible_child & in_care + + n_paying = spm_unit.sum(is_paying_child) + n_ft = spm_unit.sum(is_paying_child & is_ft) + has_second_child = n_paying >= 2 # First child rate: use FT rate if any child is FT, else PT first_child_rate = where(