Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tax free childcare #1004

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from policyengine_uk.model_api import *


class child_age_eligible(Variable):
value_type = bool
entity = Person
label = "Child age eligibility requirements"
documentation = "Whether this person meets the age and disability requirements for eligibility"
definition_period = YEAR

def formula(person, period, parameters):
"""
Calculate age eligibility based on age and disability conditions.

Returns:
bool: True if eligible (under 12, or under 17 with disability), False otherwise
"""
# Get the benefit unit the person belongs to
benunit = person.benunit

# Get person's characteristics
age = person("age", period)

# Check disability conditions
gc = parameters(period).gov.dwp.pension_credit.guarantee_credit
standard_disability_benefits = gc.child.disability.eligibility
severe_disability_benefits = gc.child.disability.severe.eligibility

is_disabled = (add(person, period, standard_disability_benefits) |
add(person, period, severe_disability_benefits)) > 0

# Check age conditions
basic_age_condition = (age < 12)
age_under_17 = (age < 17)

Comment on lines +33 to +35
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We want to parameterize values such as "12" and "17" - in general we try to avoid hard coding any values that could be adjusted through a parameter reform.

# Combine conditions
eligible = basic_age_condition | (age_under_17 & is_disabled)

return benunit.any(eligible)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since this is a person level variable we do not need to add the benunit.any condition

we want to return basic_age_condition | (age_under_17 & is_disabled)

Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from policyengine_uk.model_api import *


class meets_income_requirements(Variable):
value_type = bool
entity = Person
label = "Income requirements and calculations"
documentation = "Whether this person meets the income requirements for tax-free childcare based on age and income thresholds"
definition_period = YEAR

def formula(person, period):
"""
Calculate if a person meets income requirements based on their age and income.

Returns:
bool: True if they meet the income conditions for their age group
"""
# Get person's characteristics
age = person("age", period)

# Calculate eligible income
total_income = person("total_income", period)
# Extract investment incomes to subtract
investment_income = add(
person,
period,
[
"private_pension_income",
"savings_interest_income",
"dividend_income",
"property_income",
]
)

yearly_eligible_income = total_income - investment_income

# Income thresholds by age group
quarterly_income = yearly_eligible_income / 4

# Age >= 21
meets_adult_condition = (
(age >= 21) &
(quarterly_income >= 2379)
)

# Age 18-20
meets_young_adult_condition = (
(age >= 18) &
(age <= 20) &
(quarterly_income >= 1788)
)

# Age < 18
meets_youth_condition = (
(age < 18) &
(quarterly_income >= 1331)
)

# Combine all conditions
return (
meets_adult_condition |
meets_young_adult_condition |
meets_youth_condition
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from policyengine_uk.model_api import *


class incompatibilities_childcare_eligible(Variable):
value_type = bool
entity = Person
label = "Tax-Free Childcare Exclusions"
documentation = "Whether the person's benefit unit meets the incompatibility conditions for tax-free childcare (not receiving WTC, CTC, or UC)"
definition_period = YEAR

def formula(person, period, parameters):
"""
Calculate eligibility based on incompatible benefits.

Returns:
bool: True if eligible (no incompatible benefits received), False if receiving any incompatible benefits
"""
# Get the benefit unit the person belongs to
benunit = person.benunit

# Check if receiving any of the mutually exclusive benefits
has_wtc = benunit("working_tax_credit", period) > 0
has_ctc = benunit("child_tax_credit", period) > 0
has_uc = benunit("universal_credit", period) > 0

# Returns True when person's benefit unit does NOT receive any of these benefits
return ~(
has_wtc |
has_ctc |
has_uc
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from policyengine_uk.model_api import *

class childcare_work_condition(Variable):
value_type = bool
entity = Person
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar question for each of the files - do we want to compute this for each person or for the entire Benefit Unit?

label = "Work conditions for tax-free childcare"
documentation = "Whether the person/couple meets work requirements for tax-free childcare"
definition_period = YEAR
def formula(person, period, parameters):
"""
Calculate if person meets work conditions for:
- Single working adult
- Couple where either both work or one works and other has disability/incapacity
"""
benunit = person.benunit
is_adult = person("is_adult", period)

# Basic work status
in_work = person("in_work", period)

# Get disability/incapacity conditions like we did in childcare age eligibility
gc = parameters(period).gov.dwp.pension_credit.guarantee_credit
standard_disability_benefits = gc.child.disability.eligibility
severe_disability_benefits = gc.child.disability.severe.eligibility

is_disabled = (add(person, period, standard_disability_benefits) |
add(person, period, severe_disability_benefits)) > 0

has_incapacity = person("incapacity_benefit", period) > 0

# Build conditions
# Single adult conditions
is_single = benunit.sum(is_adult) == 1
single_working = is_single & in_work

# Couple conditions
is_couple = benunit.sum(is_adult) == 2
partner_in_work = in_work
partner_has_condition = (is_disabled | has_incapacity)

couple_both_working = is_couple & in_work & partner_in_work
is_partner_working_with_disabled_person = is_couple & partner_in_work & (is_disabled | has_incapacity)
is_person_working_with_disabled_partner = is_couple & in_work & partner_has_condition

return (
single_working |
couple_both_working |
is_person_working_with_disabled_partner |
is_partner_working_with_disabled_person
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a class

Use underscores when naming files instead of "-"

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from policyengine_uk.model_api import *


def formula(benunit, period, parameters, parents_contribution):
# Define tax-free childcare parameters
p = {
"standard_child": {
"yearly_max": 2000
},
"disabled_child": {
"yearly_max": 4000
},
"government_contribution": 2/8
}

# Check eligibility conditions
meets_age_condition = benunit("child_age_eligible", period)
meets_income_condition = benunit.any(benunit.members("meets_income_requirements", period))
is_eligible = meets_age_condition & meets_income_condition & benunit("incompatibilities_childcare_eligible", period)

# Determine the maximum eligible childcare cost for a single child
max_amount = 0
for child in benunit.members("is_child", period):
if is_eligible[child]:
if child("is_disabled", period):
max_amount = p["disabled_child"]["yearly_max"] # Only consider disabled child's max
else:
max_amount = p["standard_child"]["yearly_max"] # Only consider standard child's max

# Calculate the government contribution
government_contribution = min(parents_contribution * p["government_contribution"], max_amount)

return government_contribution
Loading