diff --git a/changelog.d/adult-dependants-grant.added.md b/changelog.d/adult-dependants-grant.added.md new file mode 100644 index 000000000..a0e6582f9 --- /dev/null +++ b/changelog.d/adult-dependants-grant.added.md @@ -0,0 +1 @@ +Add a first-pass Adult Dependants' Grant model. diff --git a/policyengine_uk/parameters/gov/dfe/adult_dependants_grant/income_limit.yaml b/policyengine_uk/parameters/gov/dfe/adult_dependants_grant/income_limit.yaml new file mode 100644 index 000000000..a3bdf9774 --- /dev/null +++ b/policyengine_uk/parameters/gov/dfe/adult_dependants_grant/income_limit.yaml @@ -0,0 +1,11 @@ +description: Household income limit for Adult Dependants' Grant +metadata: + label: Adult Dependants' Grant household income limit + unit: currency-GBP + period: year + reference: + - title: Adult Dependants' Grant + href: https://www.gov.uk/adult-dependants-grant/eligibility +values: + 2025-01-01: 15_835.98 + 2026-01-01: 15_835.98 diff --git a/policyengine_uk/parameters/gov/dfe/adult_dependants_grant/maximum.yaml b/policyengine_uk/parameters/gov/dfe/adult_dependants_grant/maximum.yaml new file mode 100644 index 000000000..0aa4f7ce2 --- /dev/null +++ b/policyengine_uk/parameters/gov/dfe/adult_dependants_grant/maximum.yaml @@ -0,0 +1,11 @@ +description: Maximum Adult Dependants' Grant amount +metadata: + label: Adult Dependants' Grant maximum + unit: currency-GBP + period: year + reference: + - title: Adult Dependants' Grant + href: https://www.gov.uk/adult-dependants-grant/what-youll-get +values: + 2025-01-01: 3_545 + 2026-01-01: 3_545 diff --git a/policyengine_uk/parameters/gov/dfe/adult_dependants_grant/other_adult_income_limit.yaml b/policyengine_uk/parameters/gov/dfe/adult_dependants_grant/other_adult_income_limit.yaml new file mode 100644 index 000000000..16295a645 --- /dev/null +++ b/policyengine_uk/parameters/gov/dfe/adult_dependants_grant/other_adult_income_limit.yaml @@ -0,0 +1,11 @@ +description: Income limit for a non-partner adult dependant in the Adult Dependants' Grant assessment +metadata: + label: Adult Dependants' Grant other adult income limit + unit: currency-GBP + period: year + reference: + - title: Adult Dependants' Grant + href: https://www.gov.uk/adult-dependants-grant/eligibility +values: + 2025-01-01: 3_796 + 2026-01-01: 3_796 diff --git a/policyengine_uk/programs.yaml b/policyengine_uk/programs.yaml index dc7b679ca..f1f4ba4f9 100644 --- a/policyengine_uk/programs.yaml +++ b/policyengine_uk/programs.yaml @@ -372,6 +372,18 @@ programs: verified_start_year: 2025 notes: First-pass England model using the published maximum amount and household-income cutoff, with higher-education evidence as the default course proxy and an explicit override for edge cases such as 120-credit or teacher-training routes + - id: adult_dependants_grant + name: Adult Dependants' Grant + full_name: Student Finance England Adult Dependants' Grant + category: Benefits + agency: DfE + status: partial + coverage: England + variable: adult_dependants_grant + parameter_prefix: gov.dfe.adult_dependants_grant + verified_start_year: 2025 + notes: First-pass England model using the published maximum amount and household-income tests, with automatic 25-plus couple detection and explicit inputs for under-25 spouse/civil-partner and non-partner adult dependant cases + - id: bursary_fund_16_to_19 name: 16 to 19 Bursary Fund full_name: 16 to 19 Bursary Fund diff --git a/policyengine_uk/tests/policy/baseline/gov/dfe/adult_dependants_grant/adult_dependants_grant.yaml b/policyengine_uk/tests/policy/baseline/gov/dfe/adult_dependants_grant/adult_dependants_grant.yaml new file mode 100644 index 000000000..f54ef1f94 --- /dev/null +++ b/policyengine_uk/tests/policy/baseline/gov/dfe/adult_dependants_grant/adult_dependants_grant.yaml @@ -0,0 +1,211 @@ +- name: Adult Dependants' Grant pays the maximum for an eligible 25-plus couple student + period: 2025 + input: + people: + student: + age: 25 + current_education: TERTIARY + partner: + age: 29 + benunits: + benunit: + members: ["student", "partner"] + households: + household: + members: ["student", "partner"] + country: ENGLAND + output: + adult_dependants_grant_adult_eligible: [true, true] + adult_dependants_grant_eligible: [true, false] + adult_dependants_grant: [3_545, 0] + +- name: Adult Dependants' Grant uses higher-education evidence as the default course proxy + period: 2025 + input: + people: + student: + age: 26 + current_education: TERTIARY + partner: + age: 30 + benunits: + benunit: + members: ["student", "partner"] + households: + household: + members: ["student", "partner"] + country: ENGLAND + output: + adult_dependants_grant_course_eligible: [true, false] + adult_dependants_grant_eligible: [true, false] + adult_dependants_grant: [3_545, 0] + +- name: Adult Dependants' Grant is nil at the household income cutoff + period: 2025 + input: + people: + student: + age: 30 + current_education: TERTIARY + adult_dependants_grant_household_income: 15_835.98 + partner: + age: 31 + benunits: + benunit: + members: ["student", "partner"] + households: + household: + members: ["student", "partner"] + country: ENGLAND + output: + adult_dependants_grant_eligible: [false, false] + adult_dependants_grant: [0, 0] + +- name: Adult Dependants' Grant allows an explicit non-partner adult dependant at the income cap + period: 2025 + input: + people: + student: + age: 22 + current_education: TERTIARY + adult_dependants_grant_has_other_adult_dependant: true + adult_dependants_grant_other_adult_income: 3_796 + adult_dependants_grant_household_income: 10_000 + benunits: + benunit: + members: ["student"] + households: + household: + members: ["student"] + country: ENGLAND + output: + adult_dependants_grant_adult_eligible: [true] + adult_dependants_grant_eligible: [true] + adult_dependants_grant: [3_545] + +- name: Adult Dependants' Grant excludes non-partner adult dependants above the income cap + period: 2025 + input: + people: + student: + age: 22 + current_education: TERTIARY + adult_dependants_grant_has_other_adult_dependant: true + adult_dependants_grant_other_adult_income: 3_796.01 + adult_dependants_grant_household_income: 10_000 + benunits: + benunit: + members: ["student"] + households: + household: + members: ["student"] + country: ENGLAND + output: + adult_dependants_grant_adult_eligible: [false] + adult_dependants_grant_eligible: [false] + adult_dependants_grant: [0] + +- name: Adult Dependants' Grant is incompatible with Postgraduate Loan support + period: 2025 + input: + people: + student: + age: 27 + current_education: TERTIARY + adult_dependants_grant_receives_postgraduate_loan: true + partner: + age: 28 + benunits: + benunit: + members: ["student", "partner"] + households: + household: + members: ["student", "partner"] + country: ENGLAND + output: + adult_dependants_grant_eligible: [false, false] + adult_dependants_grant: [0, 0] + +- name: Adult Dependants' Grant excludes dependant adults on student finance + period: 2025 + input: + people: + student: + age: 27 + current_education: TERTIARY + partner: + age: 29 + current_education: TERTIARY + benunits: + benunit: + members: ["student", "partner"] + households: + household: + members: ["student", "partner"] + country: ENGLAND + output: + adult_dependants_grant_adult_receives_student_finance: [true, true] + adult_dependants_grant_eligible: [false, false] + adult_dependants_grant: [0, 0] + +- name: Adult Dependants' Grant excludes under-25 couples by default + period: 2025 + input: + people: + student: + age: 24 + current_education: TERTIARY + partner: + age: 24 + benunits: + benunit: + members: ["student", "partner"] + households: + household: + members: ["student", "partner"] + country: ENGLAND + output: + adult_dependants_grant_adult_eligible: [false, false] + adult_dependants_grant_eligible: [false, false] + adult_dependants_grant: [0, 0] + +- name: Adult Dependants' Grant allows an explicit override for under-25 spouse or civil-partner cases + period: 2025 + input: + people: + student: + age: 24 + current_education: TERTIARY + adult_dependants_grant_adult_eligible: true + partner: + age: 24 + benunits: + benunit: + members: ["student", "partner"] + households: + household: + members: ["student", "partner"] + country: ENGLAND + output: + adult_dependants_grant_eligible: [true, false] + adult_dependants_grant: [3_545, 0] + +- name: Adult Dependants' Grant excludes households outside England + period: 2025 + input: + people: + student: + age: 27 + current_education: TERTIARY + partner: + age: 28 + benunits: + benunit: + members: ["student", "partner"] + households: + household: + members: ["student", "partner"] + country: WALES + output: + adult_dependants_grant_eligible: [false, false] + adult_dependants_grant: [0, 0] diff --git a/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant.py b/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant.py new file mode 100644 index 000000000..e89e3c90e --- /dev/null +++ b/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant.py @@ -0,0 +1,20 @@ +from policyengine_uk.model_api import * + + +class adult_dependants_grant(Variable): + value_type = float + entity = Person + label = "Adult Dependants' Grant" + documentation = ( + "Student Finance England Adult Dependants' Grant. " + "GOV.UK publishes the maximum award and income tests, but not a simple public award curve. " + "This first-pass model therefore pays the published maximum amount to eligible students rather than " + "inventing a taper." + ) + definition_period = YEAR + quantity_type = FLOW + unit = GBP + defined_for = "adult_dependants_grant_eligible" + + def formula(person, period, parameters): + return parameters(period).gov.dfe.adult_dependants_grant.maximum diff --git a/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant_adult_eligible.py b/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant_adult_eligible.py new file mode 100644 index 000000000..557e6c7c7 --- /dev/null +++ b/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant_adult_eligible.py @@ -0,0 +1,30 @@ +from policyengine_uk.model_api import * + + +class adult_dependants_grant_adult_eligible(Variable): + value_type = bool + entity = Person + label = "Has an eligible dependant adult for Adult Dependants' Grant" + documentation = ( + "Whether the student has a dependant adult who can qualify them for Adult Dependants' Grant. " + "By default, the model treats co-resident couple students aged 25 or over as satisfying the partner rule, " + "and provides an explicit input path for other adult dependants or under-25 married/civil-partner cases." + ) + definition_period = YEAR + set_input = set_input_dispatch_by_period + + def formula(person, period, parameters): + p = parameters(period).gov.dfe.adult_dependants_grant + is_couple = person.benunit("is_couple", period) + age = person("age", period) + has_other_adult_dependant = person( + "adult_dependants_grant_has_other_adult_dependant", period + ) + other_adult_income = person("adult_dependants_grant_other_adult_income", period) + + partner_path = is_couple & (age >= 25) + other_adult_path = has_other_adult_dependant & ( + other_adult_income <= p.other_adult_income_limit + ) + + return partner_path | other_adult_path diff --git a/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant_adult_receives_student_finance.py b/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant_adult_receives_student_finance.py new file mode 100644 index 000000000..54a4951fb --- /dev/null +++ b/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant_adult_receives_student_finance.py @@ -0,0 +1,22 @@ +from policyengine_uk.model_api import * + + +class adult_dependants_grant_adult_receives_student_finance(Variable): + value_type = bool + entity = Person + label = "Dependant adult receives student finance for Adult Dependants' Grant" + documentation = ( + "Whether the dependant adult receives student finance, which makes the student ineligible for Adult Dependants' Grant. " + "By default, this only detects another higher-education student within the same benefit unit; " + "simulations can set it explicitly for harder-to-observe cases." + ) + definition_period = YEAR + default_value = False + set_input = set_input_dispatch_by_period + + def formula(person, period, parameters): + he_members = person.benunit.sum( + person.benunit.members("maintenance_loan_in_higher_education", period) + ) + own_he = person("maintenance_loan_in_higher_education", period) + return he_members - own_he > 0 diff --git a/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant_course_eligible.py b/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant_course_eligible.py new file mode 100644 index 000000000..a16f2634f --- /dev/null +++ b/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant_course_eligible.py @@ -0,0 +1,18 @@ +from policyengine_uk.model_api import * + + +class adult_dependants_grant_course_eligible(Variable): + value_type = bool + entity = Person + label = "Study-pattern eligible for Adult Dependants' Grant" + documentation = ( + "Whether the person is on a course or study pattern that can qualify for Adult Dependants' Grant. " + "This can be set explicitly in simulations. By default, the model proxies this from higher-education " + "evidence rather than a narrower England-finance rule, so simulations can override the variable for " + "full-time and teacher-training edge cases." + ) + definition_period = YEAR + set_input = set_input_dispatch_by_period + + def formula(person, period, parameters): + return person("maintenance_loan_in_higher_education", period) diff --git a/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant_eligible.py b/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant_eligible.py new file mode 100644 index 000000000..18fcbb3fd --- /dev/null +++ b/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant_eligible.py @@ -0,0 +1,38 @@ +from policyengine_uk.model_api import * + + +class adult_dependants_grant_eligible(Variable): + value_type = bool + entity = Person + label = "Eligible for Adult Dependants' Grant" + documentation = ( + "Whether the person is eligible for Adult Dependants' Grant under the England student-finance scheme. " + "This first-pass model uses the published household-income and dependant-adult income tests, " + "a higher-education default course proxy, and explicit inputs for hard-to-observe dependant-adult cases." + ) + definition_period = YEAR + defined_for = "would_claim_adult_dependants_grant" + + def formula(person, period, parameters): + p = parameters(period).gov.dfe.adult_dependants_grant + country = person.household("country", period) + in_england = country == country.possible_values.ENGLAND + + course_eligible = person("adult_dependants_grant_course_eligible", period) + adult_eligible = person("adult_dependants_grant_adult_eligible", period) + adult_receives_student_finance = person( + "adult_dependants_grant_adult_receives_student_finance", period + ) + household_income = person("adult_dependants_grant_household_income", period) + receives_postgraduate_loan = person( + "adult_dependants_grant_receives_postgraduate_loan", period + ) + + return ( + in_england + & course_eligible + & adult_eligible + & ~adult_receives_student_finance + & ~receives_postgraduate_loan + & (household_income < p.income_limit) + ) diff --git a/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant_has_other_adult_dependant.py b/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant_has_other_adult_dependant.py new file mode 100644 index 000000000..1376de7d4 --- /dev/null +++ b/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant_has_other_adult_dependant.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class adult_dependants_grant_has_other_adult_dependant(Variable): + value_type = bool + entity = Person + label = "Has a non-partner adult dependant for Adult Dependants' Grant" + documentation = ( + "Whether the student has a non-partner adult dependant for Adult Dependants' Grant purposes. " + "This currently has to be set explicitly in simulations because the core model does not expose " + "a reliable non-partner dependant-adult proxy." + ) + definition_period = YEAR + default_value = False + set_input = set_input_dispatch_by_period diff --git a/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant_household_income.py b/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant_household_income.py new file mode 100644 index 000000000..cc19a3d03 --- /dev/null +++ b/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant_household_income.py @@ -0,0 +1,17 @@ +from policyengine_uk.model_api import * + + +class adult_dependants_grant_household_income(Variable): + value_type = float + entity = Person + label = "Adult Dependants' Grant household income" + documentation = ( + "Household income used for Adult Dependants' Grant assessment. This can be set explicitly in simulations. " + "By default, the model uses the maintenance-loan assessed household-income proxy." + ) + definition_period = YEAR + unit = GBP + set_input = set_input_dispatch_by_period + + def formula(person, period, parameters): + return person("maintenance_loan_household_income", period) diff --git a/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant_other_adult_income.py b/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant_other_adult_income.py new file mode 100644 index 000000000..ec4ba8194 --- /dev/null +++ b/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant_other_adult_income.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class adult_dependants_grant_other_adult_income(Variable): + value_type = float + entity = Person + label = "Other adult dependant income for Adult Dependants' Grant" + documentation = ( + "Income of a non-partner adult dependant for Adult Dependants' Grant purposes. " + "This currently has to be set explicitly in simulations." + ) + definition_period = YEAR + unit = GBP + default_value = 0 + set_input = set_input_dispatch_by_period diff --git a/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant_receives_postgraduate_loan.py b/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant_receives_postgraduate_loan.py new file mode 100644 index 000000000..e2ec41070 --- /dev/null +++ b/policyengine_uk/variables/gov/dfe/adult_dependants_grant/adult_dependants_grant_receives_postgraduate_loan.py @@ -0,0 +1,11 @@ +from policyengine_uk.model_api import * + + +class adult_dependants_grant_receives_postgraduate_loan(Variable): + value_type = bool + entity = Person + label = "Receives Postgraduate Loan for Adult Dependants' Grant purposes" + documentation = "Whether the person is receiving a Postgraduate Loan, which makes them ineligible for Adult Dependants' Grant." + definition_period = YEAR + default_value = False + set_input = set_input_dispatch_by_period diff --git a/policyengine_uk/variables/gov/dfe/adult_dependants_grant/would_claim_adult_dependants_grant.py b/policyengine_uk/variables/gov/dfe/adult_dependants_grant/would_claim_adult_dependants_grant.py new file mode 100644 index 000000000..8ee56c4a7 --- /dev/null +++ b/policyengine_uk/variables/gov/dfe/adult_dependants_grant/would_claim_adult_dependants_grant.py @@ -0,0 +1,12 @@ +from policyengine_uk.model_api import * + + +class would_claim_adult_dependants_grant(Variable): + value_type = bool + entity = Person + label = "Would claim Adult Dependants' Grant" + documentation = ( + "Whether this person would claim Adult Dependants' Grant if eligible." + ) + definition_period = YEAR + default_value = True diff --git a/policyengine_uk/variables/gov/gov_spending.py b/policyengine_uk/variables/gov/gov_spending.py index 736d37e82..2da3570b2 100644 --- a/policyengine_uk/variables/gov/gov_spending.py +++ b/policyengine_uk/variables/gov/gov_spending.py @@ -48,6 +48,7 @@ class gov_spending(Variable): "care_to_learn", "childcare_grant", "parents_learning_allowance", + "adult_dependants_grant", "bursary_fund_16_to_19", "dfe_education_spending", "dft_subsidy_spending", diff --git a/policyengine_uk/variables/household/income/hbai_benefits.py b/policyengine_uk/variables/household/income/hbai_benefits.py index d4d97761d..cf3c2fe8c 100644 --- a/policyengine_uk/variables/household/income/hbai_benefits.py +++ b/policyengine_uk/variables/household/income/hbai_benefits.py @@ -38,6 +38,7 @@ class hbai_benefits(Variable): "tax_free_childcare", "childcare_grant", "parents_learning_allowance", + "adult_dependants_grant", "bursary_fund_16_to_19", "healthy_start_vouchers", ] diff --git a/policyengine_uk/variables/household/income/household_benefits.py b/policyengine_uk/variables/household/income/household_benefits.py index 8dac2c951..9b364ef0b 100644 --- a/policyengine_uk/variables/household/income/household_benefits.py +++ b/policyengine_uk/variables/household/income/household_benefits.py @@ -47,6 +47,7 @@ class household_benefits(Variable): "care_to_learn", "childcare_grant", "parents_learning_allowance", + "adult_dependants_grant", "bursary_fund_16_to_19", "nhs_spending", "dfe_education_spending",