From 998c96bc3f5de1f63c14b36b3dd2b31cf643ccc4 Mon Sep 17 00:00:00 2001 From: Nikhil Woodruff Date: Thu, 3 Apr 2025 16:14:07 +0100 Subject: [PATCH 01/39] Add fix to is_parent --- .../variables/household/demographic/is_parent.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/policyengine_uk/variables/household/demographic/is_parent.py b/policyengine_uk/variables/household/demographic/is_parent.py index 415bae7aa..540c8202d 100644 --- a/policyengine_uk/variables/household/demographic/is_parent.py +++ b/policyengine_uk/variables/household/demographic/is_parent.py @@ -14,22 +14,19 @@ def formula(person, period, parameters): # Find two oldest members benunit_ages = benunit.members("age", period) - first_highest = benunit.max(benunit_ages) - second_highest = benunit.max( - where(benunit_ages < first_highest, benunit_ages, -np.inf) - ) + adult_index = person("adult_index", period) # Get family types enum family_types = family_type.possible_values # For lone parents (FamilyType.LONE_PARENT), only the eldest is parent is_lone_parent = (family_type == family_types.LONE_PARENT) & ( - age == first_highest + adult_index == 1 ) # For couples with children (FamilyType.COUPLE_WITH_CHILDREN), two eldest are parents is_couple_parent = ( family_type == family_types.COUPLE_WITH_CHILDREN - ) & ((age == first_highest) | (age == second_highest)) + ) & ((adult_index == 1) | (adult_index == 2)) return is_lone_parent | is_couple_parent From ab37356e0a40c84e740cdaec52f1d06d8e04689c Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Fri, 4 Apr 2025 10:48:42 +0100 Subject: [PATCH 02/39] Add total targets for universal childcare --- .../universal_childcare_entitlement_total.yaml | 5 +++++ .../universal_childcare_entitlement_total.py | 13 +++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 policyengine_uk/tests/policy/baseline/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_total.yaml create mode 100644 policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_total.py diff --git a/policyengine_uk/tests/policy/baseline/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_total.yaml b/policyengine_uk/tests/policy/baseline/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_total.yaml new file mode 100644 index 000000000..b99cc5d8d --- /dev/null +++ b/policyengine_uk/tests/policy/baseline/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_total.yaml @@ -0,0 +1,5 @@ +# Population-wide aggregation test +- name: Total universal childcare entitlement across UK + period: 2024 + output: + universal_childcare_entitlement_total: 1_000_000_000 # Target: £1 billion \ No newline at end of file diff --git a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_total.py b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_total.py new file mode 100644 index 000000000..dd5438acf --- /dev/null +++ b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_total.py @@ -0,0 +1,13 @@ +from policyengine_uk.model_api import * + + +class universal_childcare_entitlement_total(Variable): + value_type = float + entity = Household + label = "Total universal childcare entitlement across UK" + definition_period = YEAR + unit = "currency-GBP" + + def formula(household, period, parameters): + individual_entitlements = household.members("universal_childcare_entitlement", period) + return household.sum(individual_entitlements) \ No newline at end of file From 3420504fd33f49da0c85615988d2a99ff5454417 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Fri, 4 Apr 2025 11:01:42 +0100 Subject: [PATCH 03/39] Add a pytest --- .../test_universal_childcare.py | 23 +++++++++++++++++++ ...universal_childcare_entitlement_total.yaml | 5 ---- .../universal_childcare_entitlement_total.py | 13 ----------- 3 files changed, 23 insertions(+), 18 deletions(-) create mode 100644 policyengine_uk/tests/microsimulation/test_universal_childcare.py delete mode 100644 policyengine_uk/tests/policy/baseline/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_total.yaml delete mode 100644 policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_total.py diff --git a/policyengine_uk/tests/microsimulation/test_universal_childcare.py b/policyengine_uk/tests/microsimulation/test_universal_childcare.py new file mode 100644 index 000000000..f09e59dbc --- /dev/null +++ b/policyengine_uk/tests/microsimulation/test_universal_childcare.py @@ -0,0 +1,23 @@ +from policyengine import Simulation +import pytest + + +def test_universal_childcare_entitlement_aggregate(): + """ + Test that the total universal childcare entitlement has a reasonable value. + """ + sim = Simulation(scope="macro", country="uk") + sim = sim.baseline_simulation + year = 2024 + + # Calculate individual entitlements and sum them up + individual_entitlements = sim.calculate("universal_childcare_entitlement", period=year) + total_entitlement = individual_entitlements.sum() + + lower_bound = 800_000_000 + upper_bound = 1_200_000_000 + + assert lower_bound <= total_entitlement <= upper_bound, ( + f"Universal childcare entitlement total (£{total_entitlement:,.0f}) " + f"is outside the expected range of £{lower_bound:,.0f} to £{upper_bound:,.0f}" + ) \ No newline at end of file diff --git a/policyengine_uk/tests/policy/baseline/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_total.yaml b/policyengine_uk/tests/policy/baseline/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_total.yaml deleted file mode 100644 index b99cc5d8d..000000000 --- a/policyengine_uk/tests/policy/baseline/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_total.yaml +++ /dev/null @@ -1,5 +0,0 @@ -# Population-wide aggregation test -- name: Total universal childcare entitlement across UK - period: 2024 - output: - universal_childcare_entitlement_total: 1_000_000_000 # Target: £1 billion \ No newline at end of file diff --git a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_total.py b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_total.py deleted file mode 100644 index dd5438acf..000000000 --- a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_total.py +++ /dev/null @@ -1,13 +0,0 @@ -from policyengine_uk.model_api import * - - -class universal_childcare_entitlement_total(Variable): - value_type = float - entity = Household - label = "Total universal childcare entitlement across UK" - definition_period = YEAR - unit = "currency-GBP" - - def formula(household, period, parameters): - individual_entitlements = household.members("universal_childcare_entitlement", period) - return household.sum(individual_entitlements) \ No newline at end of file From b0af312e1876869d5ecaa8512041553cbb50a222 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Fri, 4 Apr 2025 11:02:19 +0100 Subject: [PATCH 04/39] Edit pytest --- .../tests/microsimulation/test_universal_childcare.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/policyengine_uk/tests/microsimulation/test_universal_childcare.py b/policyengine_uk/tests/microsimulation/test_universal_childcare.py index f09e59dbc..e35d46173 100644 --- a/policyengine_uk/tests/microsimulation/test_universal_childcare.py +++ b/policyengine_uk/tests/microsimulation/test_universal_childcare.py @@ -8,7 +8,7 @@ def test_universal_childcare_entitlement_aggregate(): """ sim = Simulation(scope="macro", country="uk") sim = sim.baseline_simulation - year = 2024 + year = 2025 # Calculate individual entitlements and sum them up individual_entitlements = sim.calculate("universal_childcare_entitlement", period=year) @@ -18,6 +18,6 @@ def test_universal_childcare_entitlement_aggregate(): upper_bound = 1_200_000_000 assert lower_bound <= total_entitlement <= upper_bound, ( - f"Universal childcare entitlement total (£{total_entitlement:,.0f}) " - f"is outside the expected range of £{lower_bound:,.0f} to £{upper_bound:,.0f}" + f"Universal childcare entitlement total (£{total_entitlement:,.1f}) " + f"is outside the expected range of £{lower_bound:,.1f} to £{upper_bound:,.1f}" ) \ No newline at end of file From 339e8b9ac5f679aea79a0ffa4b35cdd2b5af008f Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Fri, 4 Apr 2025 11:03:17 +0100 Subject: [PATCH 05/39] Edit pytest --- .../tests/microsimulation/test_universal_childcare.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/policyengine_uk/tests/microsimulation/test_universal_childcare.py b/policyengine_uk/tests/microsimulation/test_universal_childcare.py index e35d46173..7cb13be0f 100644 --- a/policyengine_uk/tests/microsimulation/test_universal_childcare.py +++ b/policyengine_uk/tests/microsimulation/test_universal_childcare.py @@ -6,7 +6,7 @@ def test_universal_childcare_entitlement_aggregate(): """ Test that the total universal childcare entitlement has a reasonable value. """ - sim = Simulation(scope="macro", country="uk") + sim = Simulation(scope="macro", country="uk", time_period= "2025") sim = sim.baseline_simulation year = 2025 From 2efbca436a29a50f836d5792cd376d18285d6ed6 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Fri, 4 Apr 2025 11:08:01 +0100 Subject: [PATCH 06/39] Edit year --- .../tests/microsimulation/test_universal_childcare.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/policyengine_uk/tests/microsimulation/test_universal_childcare.py b/policyengine_uk/tests/microsimulation/test_universal_childcare.py index 7cb13be0f..c56585c2f 100644 --- a/policyengine_uk/tests/microsimulation/test_universal_childcare.py +++ b/policyengine_uk/tests/microsimulation/test_universal_childcare.py @@ -6,9 +6,9 @@ def test_universal_childcare_entitlement_aggregate(): """ Test that the total universal childcare entitlement has a reasonable value. """ - sim = Simulation(scope="macro", country="uk", time_period= "2025") + sim = Simulation(scope="macro", country="uk", time_period= "2024") sim = sim.baseline_simulation - year = 2025 + year = 2024 # Calculate individual entitlements and sum them up individual_entitlements = sim.calculate("universal_childcare_entitlement", period=year) From acfa39488130fb222a8ad64a9e69b932b8c1e50e Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Fri, 4 Apr 2025 11:18:19 +0100 Subject: [PATCH 07/39] Edit bounds --- .../tests/microsimulation/test_universal_childcare.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/policyengine_uk/tests/microsimulation/test_universal_childcare.py b/policyengine_uk/tests/microsimulation/test_universal_childcare.py index c56585c2f..6d31c6559 100644 --- a/policyengine_uk/tests/microsimulation/test_universal_childcare.py +++ b/policyengine_uk/tests/microsimulation/test_universal_childcare.py @@ -14,8 +14,8 @@ def test_universal_childcare_entitlement_aggregate(): individual_entitlements = sim.calculate("universal_childcare_entitlement", period=year) total_entitlement = individual_entitlements.sum() - lower_bound = 800_000_000 - upper_bound = 1_200_000_000 + lower_bound = 2_200_000_000 + upper_bound = 3_000_000_000 assert lower_bound <= total_entitlement <= upper_bound, ( f"Universal childcare entitlement total (£{total_entitlement:,.1f}) " From 50b3a9b4f3734f3627065f530bfd30fc2acbf148 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Fri, 4 Apr 2025 11:35:43 +0100 Subject: [PATCH 08/39] Hard code takeup rate --- .../tests/microsimulation/test_universal_childcare.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/policyengine_uk/tests/microsimulation/test_universal_childcare.py b/policyengine_uk/tests/microsimulation/test_universal_childcare.py index 6d31c6559..a4b518723 100644 --- a/policyengine_uk/tests/microsimulation/test_universal_childcare.py +++ b/policyengine_uk/tests/microsimulation/test_universal_childcare.py @@ -6,13 +6,19 @@ def test_universal_childcare_entitlement_aggregate(): """ Test that the total universal childcare entitlement has a reasonable value. """ - sim = Simulation(scope="macro", country="uk", time_period= "2024") + sim = Simulation(scope="macro", country="uk", time_period="2024") sim = sim.baseline_simulation year = 2024 + # Hard coded take-up rate + # Move this take-up rate to the uk-data package + universal_childcare_entitlement_take_up_rate = 0.6 + # Calculate individual entitlements and sum them up individual_entitlements = sim.calculate("universal_childcare_entitlement", period=year) - total_entitlement = individual_entitlements.sum() + + # Apply the take-up rate to the total + total_entitlement = individual_entitlements.sum() * universal_childcare_entitlement_take_up_rate lower_bound = 2_200_000_000 upper_bound = 3_000_000_000 From 47c04cf817872e25d336cffcb891fc55a034fb64 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Fri, 4 Apr 2025 11:37:19 +0100 Subject: [PATCH 09/39] Black --- .../test_universal_childcare.py | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/policyengine_uk/tests/microsimulation/test_universal_childcare.py b/policyengine_uk/tests/microsimulation/test_universal_childcare.py index a4b518723..0925c46f4 100644 --- a/policyengine_uk/tests/microsimulation/test_universal_childcare.py +++ b/policyengine_uk/tests/microsimulation/test_universal_childcare.py @@ -9,21 +9,26 @@ def test_universal_childcare_entitlement_aggregate(): sim = Simulation(scope="macro", country="uk", time_period="2024") sim = sim.baseline_simulation year = 2024 - + # Hard coded take-up rate # Move this take-up rate to the uk-data package universal_childcare_entitlement_take_up_rate = 0.6 - + # Calculate individual entitlements and sum them up - individual_entitlements = sim.calculate("universal_childcare_entitlement", period=year) - + individual_entitlements = sim.calculate( + "universal_childcare_entitlement", period=year + ) + # Apply the take-up rate to the total - total_entitlement = individual_entitlements.sum() * universal_childcare_entitlement_take_up_rate - + total_entitlement = ( + individual_entitlements.sum() + * universal_childcare_entitlement_take_up_rate + ) + lower_bound = 2_200_000_000 upper_bound = 3_000_000_000 - + assert lower_bound <= total_entitlement <= upper_bound, ( f"Universal childcare entitlement total (£{total_entitlement:,.1f}) " f"is outside the expected range of £{lower_bound:,.1f} to £{upper_bound:,.1f}" - ) \ No newline at end of file + ) From 7dd14d8adbb6bb3c68439b878563ba9a05b0a200 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Fri, 4 Apr 2025 12:05:43 +0100 Subject: [PATCH 10/39] Add no TFC condition --- .../universal_childcare_entitlement_eligible.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py index 811f34a75..5331a5db1 100644 --- a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py +++ b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py @@ -8,6 +8,9 @@ class universal_childcare_entitlement_eligible(Variable): definition_period = YEAR def formula(person, period, parameters): + # Check if person is not receiving tax-free childcare + no_tax_free_childcare = person("tax_free_childcare", period) <= 0 + country = person.household("country", period) countries = country.possible_values in_england = country == countries.ENGLAND @@ -20,4 +23,4 @@ def formula(person, period, parameters): not_compulsory_age = ~person("is_of_compulsory_school_age", period) # Section 7 of the Childcare Act 2006 # The regulation above limits free early years provision to children under compulsory school age. - return in_england & meets_age_condition & not_compulsory_age + return in_england & meets_age_condition & not_compulsory_age & no_tax_free_childcare From 2f273b347d86913774edcec8f1dc62f9589bb2e1 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Fri, 4 Apr 2025 12:11:54 +0100 Subject: [PATCH 11/39] Format --- .../universal_childcare_entitlement_eligible.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py index 5331a5db1..4c5566177 100644 --- a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py +++ b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py @@ -10,7 +10,7 @@ class universal_childcare_entitlement_eligible(Variable): def formula(person, period, parameters): # Check if person is not receiving tax-free childcare no_tax_free_childcare = person("tax_free_childcare", period) <= 0 - + country = person.household("country", period) countries = country.possible_values in_england = country == countries.ENGLAND @@ -23,4 +23,9 @@ def formula(person, period, parameters): not_compulsory_age = ~person("is_of_compulsory_school_age", period) # Section 7 of the Childcare Act 2006 # The regulation above limits free early years provision to children under compulsory school age. - return in_england & meets_age_condition & not_compulsory_age & no_tax_free_childcare + return ( + in_england + & meets_age_condition + & not_compulsory_age + & no_tax_free_childcare + ) From 6d55de2e008ffb000c9784e344915931358c1644 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Fri, 4 Apr 2025 12:51:01 +0100 Subject: [PATCH 12/39] Replace <= 0 with ==0 --- .../universal_childcare_entitlement_eligible.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py index 4c5566177..b9082ce93 100644 --- a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py +++ b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py @@ -9,7 +9,7 @@ class universal_childcare_entitlement_eligible(Variable): def formula(person, period, parameters): # Check if person is not receiving tax-free childcare - no_tax_free_childcare = person("tax_free_childcare", period) <= 0 + no_tax_free_childcare = person("tax_free_childcare", period) == 0 country = person.household("country", period) countries = country.possible_values From 4eb683d30bbd563ea7092854931d77642b301de6 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Fri, 4 Apr 2025 13:00:51 +0100 Subject: [PATCH 13/39] Edit condition --- .../universal_childcare_entitlement_eligible.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py index b9082ce93..801dd552d 100644 --- a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py +++ b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py @@ -8,8 +8,6 @@ class universal_childcare_entitlement_eligible(Variable): definition_period = YEAR def formula(person, period, parameters): - # Check if person is not receiving tax-free childcare - no_tax_free_childcare = person("tax_free_childcare", period) == 0 country = person.household("country", period) countries = country.possible_values @@ -27,5 +25,4 @@ def formula(person, period, parameters): in_england & meets_age_condition & not_compulsory_age - & no_tax_free_childcare ) From bb0e7acfabd3e9716c450d05a5a7006959687b86 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Fri, 4 Apr 2025 14:43:14 +0100 Subject: [PATCH 14/39] Edit changes --- .../universal_childcare_entitlement_eligible.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py index 801dd552d..811f34a75 100644 --- a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py +++ b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py @@ -8,7 +8,6 @@ class universal_childcare_entitlement_eligible(Variable): definition_period = YEAR def formula(person, period, parameters): - country = person.household("country", period) countries = country.possible_values in_england = country == countries.ENGLAND @@ -21,8 +20,4 @@ def formula(person, period, parameters): not_compulsory_age = ~person("is_of_compulsory_school_age", period) # Section 7 of the Childcare Act 2006 # The regulation above limits free early years provision to children under compulsory school age. - return ( - in_england - & meets_age_condition - & not_compulsory_age - ) + return in_england & meets_age_condition & not_compulsory_age From 2199f71e39864ad515890de559a96e4ea52bef8a Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Mon, 7 Apr 2025 12:37:59 +0100 Subject: [PATCH 15/39] Add other pytests --- .../tests/microsimulation/test_childcare.py | 129 ++++++++++++++++++ .../test_universal_childcare.py | 34 ----- 2 files changed, 129 insertions(+), 34 deletions(-) create mode 100644 policyengine_uk/tests/microsimulation/test_childcare.py delete mode 100644 policyengine_uk/tests/microsimulation/test_universal_childcare.py diff --git a/policyengine_uk/tests/microsimulation/test_childcare.py b/policyengine_uk/tests/microsimulation/test_childcare.py new file mode 100644 index 000000000..a3b3f7332 --- /dev/null +++ b/policyengine_uk/tests/microsimulation/test_childcare.py @@ -0,0 +1,129 @@ +from policyengine import Simulation +import pytest + + +def test_universal_childcare_entitlement_aggregate(): + """ + Test that the total universal childcare entitlement has a reasonable value. + """ + sim = Simulation(scope="macro", country="uk", time_period="2024") + sim = sim.baseline_simulation + year = 2024 + + # Hard coded take-up rate + # Move this take-up rate to the uk-data package + universal_childcare_entitlement_take_up_rate = 0.6 + + # Calculate individual entitlements and sum them up + individual_entitlements = sim.calculate( + "universal_childcare_entitlement", period=year + ) + + # Apply the take-up rate to the total + total_entitlement = ( + individual_entitlements.sum() + * universal_childcare_entitlement_take_up_rate + ) + + lower_bound = 2_200_000_000 + upper_bound = 3_000_000_000 + + assert lower_bound <= total_entitlement <= upper_bound, ( + f"Universal childcare entitlement total (£{total_entitlement:,.1f}) " + f"is outside the expected range of £{lower_bound:,.1f} to £{upper_bound:,.1f}" + ) + + +def test_extended_childcare_entitlement_aggregate(): + """ + Test that the total extended childcare entitlement has a reasonable value. + """ + sim = Simulation(scope="macro", country="uk", time_period="2024") + sim = sim.baseline_simulation + year = 2024 + + # Hard coded take-up rate + extended_childcare_entitlement_take_up_rate = 0.6 + + # Calculate individual entitlements and sum them up + individual_entitlements = sim.calculate( + "extended_childcare_entitlement", period=year + ) + + # Apply the take-up rate to the total + total_entitlement = ( + individual_entitlements.sum() + * extended_childcare_entitlement_take_up_rate + ) + + lower_bound = 2_800_000_000 + upper_bound = 3_300_000_000 + + assert lower_bound <= total_entitlement <= upper_bound, ( + f"Extended childcare entitlement total (£{total_entitlement:,.1f}) " + f"is outside the expected range of £{lower_bound:,.1f} to £{upper_bound:,.1f}" + ) + + +def test_targeted_childcare_entitlement_aggregate(): + """ + Test that the total targeted childcare entitlement has a reasonable value. + """ + sim = Simulation(scope="macro", country="uk", time_period="2024") + sim = sim.baseline_simulation + year = 2024 + + # Hard coded take-up rate + targeted_childcare_entitlement_take_up_rate = 0.6 + + # Calculate individual entitlements and sum them up + individual_entitlements = sim.calculate( + "targeted_childcare_entitlement", period=year + ) + + # Apply the take-up rate to the total + total_entitlement = ( + individual_entitlements.sum() + * targeted_childcare_entitlement_take_up_rate + ) + + lower_bound = 400_000_000 + upper_bound = 700_000_000 + + assert lower_bound <= total_entitlement <= upper_bound, ( + f"Targeted childcare entitlement total (£{total_entitlement:,.1f}) " + f"is outside the expected range of £{lower_bound:,.1f} to £{upper_bound:,.1f}" + ) + + +def test_care_to_learn_childcare_entitlement_aggregate(): + """ + Test that the total Care to Learn childcare entitlement has a reasonable value. + """ + sim = Simulation(scope="macro", country="uk", time_period="2024") + sim = sim.baseline_simulation + year = 2024 + + # Hard coded take-up rate + care_to_learn_take_up_rate = 0.6 + + # Calculate individual entitlements and sum them up + individual_entitlements = sim.calculate( + "study_childcare_entitlement", period=year + ) + + # Apply the take-up rate to the total + total_entitlement = ( + individual_entitlements.sum() + * care_to_learn_take_up_rate + ) + + # Currently, the entitlement is zero, so we test for that + # If implementation changes in the future, update these bounds + lower_bound = 0 + upper_bound = 1_000_000 + + assert lower_bound <= total_entitlement <= upper_bound, ( + f"Care to Learn childcare entitlement total (£{total_entitlement:,.1f}) " + f"is outside the expected range of £{lower_bound:,.1f} to £{upper_bound:,.1f}" + ) diff --git a/policyengine_uk/tests/microsimulation/test_universal_childcare.py b/policyengine_uk/tests/microsimulation/test_universal_childcare.py deleted file mode 100644 index 0925c46f4..000000000 --- a/policyengine_uk/tests/microsimulation/test_universal_childcare.py +++ /dev/null @@ -1,34 +0,0 @@ -from policyengine import Simulation -import pytest - - -def test_universal_childcare_entitlement_aggregate(): - """ - Test that the total universal childcare entitlement has a reasonable value. - """ - sim = Simulation(scope="macro", country="uk", time_period="2024") - sim = sim.baseline_simulation - year = 2024 - - # Hard coded take-up rate - # Move this take-up rate to the uk-data package - universal_childcare_entitlement_take_up_rate = 0.6 - - # Calculate individual entitlements and sum them up - individual_entitlements = sim.calculate( - "universal_childcare_entitlement", period=year - ) - - # Apply the take-up rate to the total - total_entitlement = ( - individual_entitlements.sum() - * universal_childcare_entitlement_take_up_rate - ) - - lower_bound = 2_200_000_000 - upper_bound = 3_000_000_000 - - assert lower_bound <= total_entitlement <= upper_bound, ( - f"Universal childcare entitlement total (£{total_entitlement:,.1f}) " - f"is outside the expected range of £{lower_bound:,.1f} to £{upper_bound:,.1f}" - ) From 721530cf10be4ec031463e418da4b9d1edbd6068 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Mon, 7 Apr 2025 13:16:33 +0100 Subject: [PATCH 16/39] Format --- policyengine_uk/tests/microsimulation/test_childcare.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/policyengine_uk/tests/microsimulation/test_childcare.py b/policyengine_uk/tests/microsimulation/test_childcare.py index a3b3f7332..907f96f5f 100644 --- a/policyengine_uk/tests/microsimulation/test_childcare.py +++ b/policyengine_uk/tests/microsimulation/test_childcare.py @@ -114,8 +114,7 @@ def test_care_to_learn_childcare_entitlement_aggregate(): # Apply the take-up rate to the total total_entitlement = ( - individual_entitlements.sum() - * care_to_learn_take_up_rate + individual_entitlements.sum() * care_to_learn_take_up_rate ) # Currently, the entitlement is zero, so we test for that From a18277b5521ced72e327ffec27b7f65e70dcd189 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Mon, 7 Apr 2025 13:22:51 +0100 Subject: [PATCH 17/39] Rename variable --- policyengine_uk/tests/microsimulation/test_childcare.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/policyengine_uk/tests/microsimulation/test_childcare.py b/policyengine_uk/tests/microsimulation/test_childcare.py index 907f96f5f..d9899a510 100644 --- a/policyengine_uk/tests/microsimulation/test_childcare.py +++ b/policyengine_uk/tests/microsimulation/test_childcare.py @@ -108,9 +108,7 @@ def test_care_to_learn_childcare_entitlement_aggregate(): care_to_learn_take_up_rate = 0.6 # Calculate individual entitlements and sum them up - individual_entitlements = sim.calculate( - "study_childcare_entitlement", period=year - ) + individual_entitlements = sim.calculate("care_to_learn", period=year) # Apply the take-up rate to the total total_entitlement = ( From 2e053dde480cb69ad8e021cd752003286b8b1ff6 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Mon, 7 Apr 2025 14:34:17 +0100 Subject: [PATCH 18/39] Add intractions --- .../targeted_childcare_entitlement_eligible.py | 10 +++++++++- .../universal_childcare_entitlement_eligible.py | 12 +++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement_eligible.py b/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement_eligible.py index 4bee5e243..d26292136 100644 --- a/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement_eligible.py +++ b/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement_eligible.py @@ -16,6 +16,10 @@ def formula(benunit, period, parameters): # Get parameters p = parameters(period).gov.dfe.targeted_childcare_entitlement + has_extended_childcare = benunit( + "extended_childcare_entitlement_eligible", period + ) + # Check if household receives any qualifying benefits has_qualifying_benefits = ( add(benunit, period, p.qualifying_benefits) > 0 @@ -24,4 +28,8 @@ def formula(benunit, period, parameters): # Check if household meets any additional qualifying criteria # from qualifying_criteria.yaml (UC/TC specific criteria) meets_any_criteria = add(benunit, period, p.qualifying_criteria) > 0 - return in_england & (has_qualifying_benefits | meets_any_criteria) + return ( + in_england + & (has_qualifying_benefits | meets_any_criteria) + & ~has_extended_childcare + ) diff --git a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py index 811f34a75..998548029 100644 --- a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py +++ b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py @@ -18,6 +18,16 @@ def formula(person, period, parameters): p = parameters(period).gov.dfe.universal_childcare_entitlement meets_age_condition = (age >= p.min_age) & (age < p.max_age) not_compulsory_age = ~person("is_of_compulsory_school_age", period) + + has_extended_childcare = person.benunit( + "extended_childcare_entitlement_eligible", period + ) + # Section 7 of the Childcare Act 2006 # The regulation above limits free early years provision to children under compulsory school age. - return in_england & meets_age_condition & not_compulsory_age + return ( + in_england + & meets_age_condition + & not_compulsory_age + & ~has_extended_childcare + ) From 07bb018b96190820973b7c76b661ddcd46ba7fe4 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Mon, 7 Apr 2025 14:51:48 +0100 Subject: [PATCH 19/39] Edit test --- policyengine_uk/tests/microsimulation/test_childcare.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/policyengine_uk/tests/microsimulation/test_childcare.py b/policyengine_uk/tests/microsimulation/test_childcare.py index d9899a510..71ae04d19 100644 --- a/policyengine_uk/tests/microsimulation/test_childcare.py +++ b/policyengine_uk/tests/microsimulation/test_childcare.py @@ -25,8 +25,8 @@ def test_universal_childcare_entitlement_aggregate(): * universal_childcare_entitlement_take_up_rate ) - lower_bound = 2_200_000_000 - upper_bound = 3_000_000_000 + lower_bound = 1_500_000_000 + upper_bound = 2_000_000_000 assert lower_bound <= total_entitlement <= upper_bound, ( f"Universal childcare entitlement total (£{total_entitlement:,.1f}) " From bc879883481e30316ee75dc9070e9d21dec1d750 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Mon, 7 Apr 2025 15:53:56 +0100 Subject: [PATCH 20/39] Add TFC --- .../tests/microsimulation/test_childcare.py | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/policyengine_uk/tests/microsimulation/test_childcare.py b/policyengine_uk/tests/microsimulation/test_childcare.py index 71ae04d19..e45f12398 100644 --- a/policyengine_uk/tests/microsimulation/test_childcare.py +++ b/policyengine_uk/tests/microsimulation/test_childcare.py @@ -28,6 +28,8 @@ def test_universal_childcare_entitlement_aggregate(): lower_bound = 1_500_000_000 upper_bound = 2_000_000_000 + print(f"Universal childcare entitlement total: £{total_entitlement:,.2f}") + assert lower_bound <= total_entitlement <= upper_bound, ( f"Universal childcare entitlement total (£{total_entitlement:,.1f}) " f"is outside the expected range of £{lower_bound:,.1f} to £{upper_bound:,.1f}" @@ -59,6 +61,8 @@ def test_extended_childcare_entitlement_aggregate(): lower_bound = 2_800_000_000 upper_bound = 3_300_000_000 + print(f"Extended childcare entitlement total: £{total_entitlement:,.2f}") + assert lower_bound <= total_entitlement <= upper_bound, ( f"Extended childcare entitlement total (£{total_entitlement:,.1f}) " f"is outside the expected range of £{lower_bound:,.1f} to £{upper_bound:,.1f}" @@ -90,6 +94,8 @@ def test_targeted_childcare_entitlement_aggregate(): lower_bound = 400_000_000 upper_bound = 700_000_000 + print(f"Targeted childcare entitlement total: £{total_entitlement:,.2f}") + assert lower_bound <= total_entitlement <= upper_bound, ( f"Targeted childcare entitlement total (£{total_entitlement:,.1f}) " f"is outside the expected range of £{lower_bound:,.1f} to £{upper_bound:,.1f}" @@ -120,7 +126,42 @@ def test_care_to_learn_childcare_entitlement_aggregate(): lower_bound = 0 upper_bound = 1_000_000 + print( + f"Care to Learn childcare entitlement total: £{total_entitlement:,.2f}" + ) + assert lower_bound <= total_entitlement <= upper_bound, ( f"Care to Learn childcare entitlement total (£{total_entitlement:,.1f}) " f"is outside the expected range of £{lower_bound:,.1f} to £{upper_bound:,.1f}" ) + + +def test_tax_free_childcare_aggregate(): + """ + Test that the total tax-free childcare entitlement has a reasonable value. + """ + sim = Simulation(scope="macro", country="uk", time_period="2024") + sim = sim.baseline_simulation + year = 2024 + + # Hard coded take-up rate + tax_free_childcare_take_up_rate = 0.6 + + # Calculate individual entitlements and sum them up + individual_entitlements = sim.calculate("tax_free_childcare", period=year) + + # Apply the take-up rate to the total + total_entitlement = ( + individual_entitlements.sum() * tax_free_childcare_take_up_rate + ) + + # Expected range for tax-free childcare + lower_bound = 300_000_000 + upper_bound = 600_000_000 + + print(f"Tax-free childcare entitlement total: £{total_entitlement:,.2f}") + + assert lower_bound <= total_entitlement <= upper_bound, ( + f"Tax-free childcare entitlement total (£{total_entitlement:,.1f}) " + f"is outside the expected range of £{lower_bound:,.1f} to £{upper_bound:,.1f}" + ) From 8a0839e28cdddacf751bd56417b8f571e306d337 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Mon, 7 Apr 2025 15:54:52 +0100 Subject: [PATCH 21/39] Edit --- .../tests/microsimulation/test_childcare.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/policyengine_uk/tests/microsimulation/test_childcare.py b/policyengine_uk/tests/microsimulation/test_childcare.py index e45f12398..42f0b8010 100644 --- a/policyengine_uk/tests/microsimulation/test_childcare.py +++ b/policyengine_uk/tests/microsimulation/test_childcare.py @@ -28,7 +28,7 @@ def test_universal_childcare_entitlement_aggregate(): lower_bound = 1_500_000_000 upper_bound = 2_000_000_000 - print(f"Universal childcare entitlement total: £{total_entitlement:,.2f}") + print(f"Universal childcare entitlement total: £{total_entitlement:,.1f}") assert lower_bound <= total_entitlement <= upper_bound, ( f"Universal childcare entitlement total (£{total_entitlement:,.1f}) " @@ -61,7 +61,7 @@ def test_extended_childcare_entitlement_aggregate(): lower_bound = 2_800_000_000 upper_bound = 3_300_000_000 - print(f"Extended childcare entitlement total: £{total_entitlement:,.2f}") + print(f"Extended childcare entitlement total: £{total_entitlement:,.1f}") assert lower_bound <= total_entitlement <= upper_bound, ( f"Extended childcare entitlement total (£{total_entitlement:,.1f}) " @@ -94,7 +94,7 @@ def test_targeted_childcare_entitlement_aggregate(): lower_bound = 400_000_000 upper_bound = 700_000_000 - print(f"Targeted childcare entitlement total: £{total_entitlement:,.2f}") + print(f"Targeted childcare entitlement total: £{total_entitlement:,.1f}") assert lower_bound <= total_entitlement <= upper_bound, ( f"Targeted childcare entitlement total (£{total_entitlement:,.1f}) " @@ -127,7 +127,7 @@ def test_care_to_learn_childcare_entitlement_aggregate(): upper_bound = 1_000_000 print( - f"Care to Learn childcare entitlement total: £{total_entitlement:,.2f}" + f"Care to Learn childcare entitlement total: £{total_entitlement:,.1f}" ) assert lower_bound <= total_entitlement <= upper_bound, ( @@ -159,7 +159,7 @@ def test_tax_free_childcare_aggregate(): lower_bound = 300_000_000 upper_bound = 600_000_000 - print(f"Tax-free childcare entitlement total: £{total_entitlement:,.2f}") + print(f"Tax-free childcare entitlement total: £{total_entitlement:,.1f}") assert lower_bound <= total_entitlement <= upper_bound, ( f"Tax-free childcare entitlement total (£{total_entitlement:,.1f}) " From c9771f3d0b60944b1f2147f812410382b033ca97 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Mon, 7 Apr 2025 16:01:22 +0100 Subject: [PATCH 22/39] Add number of eligible children --- .../tests/microsimulation/test_childcare.py | 183 ++++++++++++++++++ 1 file changed, 183 insertions(+) diff --git a/policyengine_uk/tests/microsimulation/test_childcare.py b/policyengine_uk/tests/microsimulation/test_childcare.py index 42f0b8010..2654a9a74 100644 --- a/policyengine_uk/tests/microsimulation/test_childcare.py +++ b/policyengine_uk/tests/microsimulation/test_childcare.py @@ -36,6 +36,45 @@ def test_universal_childcare_entitlement_aggregate(): ) +def test_universal_childcare_entitlement_recipients(): + """ + Test that the number of children receiving universal childcare entitlement + has a reasonable value. + """ + sim = Simulation(scope="macro", country="uk", time_period="2024") + sim = sim.baseline_simulation + year = 2024 + + # Hard coded take-up rate + universal_childcare_entitlement_take_up_rate = 0.6 + + # Calculate eligible children + individual_entitlements = sim.calculate( + "universal_childcare_entitlement", period=year + ) + + # Count non-zero entitlements + eligible_children = (individual_entitlements > 0).sum() + + # Apply take-up rate + receiving_children = ( + eligible_children * universal_childcare_entitlement_take_up_rate + ) + + # Expected range + lower_bound = 400_000 + upper_bound = 500_000 + + print( + f"Children receiving universal childcare entitlement: {receiving_children:,.0f}" + ) + + assert lower_bound <= receiving_children <= upper_bound, ( + f"Number of children receiving universal childcare entitlement ({receiving_children:,.0f}) " + f"is outside the expected range of {lower_bound:,.0f} to {upper_bound:,.0f}" + ) + + def test_extended_childcare_entitlement_aggregate(): """ Test that the total extended childcare entitlement has a reasonable value. @@ -69,6 +108,45 @@ def test_extended_childcare_entitlement_aggregate(): ) +def test_extended_childcare_entitlement_recipients(): + """ + Test that the number of children receiving extended childcare entitlement + has a reasonable value. + """ + sim = Simulation(scope="macro", country="uk", time_period="2024") + sim = sim.baseline_simulation + year = 2024 + + # Hard coded take-up rate + extended_childcare_entitlement_take_up_rate = 0.6 + + # Calculate eligible children + individual_entitlements = sim.calculate( + "extended_childcare_entitlement", period=year + ) + + # Count non-zero entitlements + eligible_children = (individual_entitlements > 0).sum() + + # Apply take-up rate + receiving_children = ( + eligible_children * extended_childcare_entitlement_take_up_rate + ) + + # Expected range + lower_bound = 400_000 + upper_bound = 500_000 + + print( + f"Children receiving extended childcare entitlement: {receiving_children:,.0f}" + ) + + assert lower_bound <= receiving_children <= upper_bound, ( + f"Number of children receiving extended childcare entitlement ({receiving_children:,.0f}) " + f"is outside the expected range of {lower_bound:,.0f} to {upper_bound:,.0f}" + ) + + def test_targeted_childcare_entitlement_aggregate(): """ Test that the total targeted childcare entitlement has a reasonable value. @@ -102,6 +180,45 @@ def test_targeted_childcare_entitlement_aggregate(): ) +def test_targeted_childcare_entitlement_recipients(): + """ + Test that the number of children receiving targeted childcare entitlement + has a reasonable value. + """ + sim = Simulation(scope="macro", country="uk", time_period="2024") + sim = sim.baseline_simulation + year = 2024 + + # Hard coded take-up rate + targeted_childcare_entitlement_take_up_rate = 0.6 + + # Calculate eligible children + individual_entitlements = sim.calculate( + "targeted_childcare_entitlement", period=year + ) + + # Count non-zero entitlements + eligible_children = (individual_entitlements > 0).sum() + + # Apply take-up rate + receiving_children = ( + eligible_children * targeted_childcare_entitlement_take_up_rate + ) + + # Expected range + lower_bound = 100_000 + upper_bound = 150_000 + + print( + f"Children receiving targeted childcare entitlement: {receiving_children:,.0f}" + ) + + assert lower_bound <= receiving_children <= upper_bound, ( + f"Number of children receiving targeted childcare entitlement ({receiving_children:,.0f}) " + f"is outside the expected range of {lower_bound:,.0f} to {upper_bound:,.0f}" + ) + + def test_care_to_learn_childcare_entitlement_aggregate(): """ Test that the total Care to Learn childcare entitlement has a reasonable value. @@ -136,6 +253,39 @@ def test_care_to_learn_childcare_entitlement_aggregate(): ) +def test_care_to_learn_childcare_recipients(): + """ + Test that the number of young people receiving Care to Learn + has a reasonable value. + """ + sim = Simulation(scope="macro", country="uk", time_period="2024") + sim = sim.baseline_simulation + year = 2024 + + # Hard coded take-up rate + care_to_learn_take_up_rate = 0.6 + + # Calculate eligible young people + individual_entitlements = sim.calculate("care_to_learn", period=year) + + # Count non-zero entitlements + eligible_children = (individual_entitlements > 0).sum() + + # Apply take-up rate + receiving_children = eligible_children * care_to_learn_take_up_rate + + # Expected range (currently zero, update when implemented) + lower_bound = 0 + upper_bound = 10_000 + + print(f"Young people receiving Care to Learn: {receiving_children:,.0f}") + + assert lower_bound <= receiving_children <= upper_bound, ( + f"Number of young people receiving Care to Learn ({receiving_children:,.0f}) " + f"is outside the expected range of {lower_bound:,.0f} to {upper_bound:,.0f}" + ) + + def test_tax_free_childcare_aggregate(): """ Test that the total tax-free childcare entitlement has a reasonable value. @@ -165,3 +315,36 @@ def test_tax_free_childcare_aggregate(): f"Tax-free childcare entitlement total (£{total_entitlement:,.1f}) " f"is outside the expected range of £{lower_bound:,.1f} to £{upper_bound:,.1f}" ) + + +def test_tax_free_childcare_recipients(): + """ + Test that the number of children receiving tax-free childcare + has a reasonable value. + """ + sim = Simulation(scope="macro", country="uk", time_period="2024") + sim = sim.baseline_simulation + year = 2024 + + # Hard coded take-up rate + tax_free_childcare_take_up_rate = 0.6 + + # Calculate eligible children + individual_entitlements = sim.calculate("tax_free_childcare", period=year) + + # Count non-zero entitlements + eligible_children = (individual_entitlements > 0).sum() + + # Apply take-up rate + receiving_children = eligible_children * tax_free_childcare_take_up_rate + + # Expected range + lower_bound = 600_000 + upper_bound = 800_000 + + print(f"Children receiving tax-free childcare: {receiving_children:,.0f}") + + assert lower_bound <= receiving_children <= upper_bound, ( + f"Number of children receiving tax-free childcare ({receiving_children:,.0f}) " + f"is outside the expected range of {lower_bound:,.0f} to {upper_bound:,.0f}" + ) From 1dd716a13b4290cea312352a4292169fe553b88e Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Tue, 8 Apr 2025 11:19:33 +0100 Subject: [PATCH 23/39] Remove test_childcare.py to be excluded from PR --- .../tests/microsimulation/test_childcare.py | 350 ------------------ 1 file changed, 350 deletions(-) delete mode 100644 policyengine_uk/tests/microsimulation/test_childcare.py diff --git a/policyengine_uk/tests/microsimulation/test_childcare.py b/policyengine_uk/tests/microsimulation/test_childcare.py deleted file mode 100644 index 2654a9a74..000000000 --- a/policyengine_uk/tests/microsimulation/test_childcare.py +++ /dev/null @@ -1,350 +0,0 @@ -from policyengine import Simulation -import pytest - - -def test_universal_childcare_entitlement_aggregate(): - """ - Test that the total universal childcare entitlement has a reasonable value. - """ - sim = Simulation(scope="macro", country="uk", time_period="2024") - sim = sim.baseline_simulation - year = 2024 - - # Hard coded take-up rate - # Move this take-up rate to the uk-data package - universal_childcare_entitlement_take_up_rate = 0.6 - - # Calculate individual entitlements and sum them up - individual_entitlements = sim.calculate( - "universal_childcare_entitlement", period=year - ) - - # Apply the take-up rate to the total - total_entitlement = ( - individual_entitlements.sum() - * universal_childcare_entitlement_take_up_rate - ) - - lower_bound = 1_500_000_000 - upper_bound = 2_000_000_000 - - print(f"Universal childcare entitlement total: £{total_entitlement:,.1f}") - - assert lower_bound <= total_entitlement <= upper_bound, ( - f"Universal childcare entitlement total (£{total_entitlement:,.1f}) " - f"is outside the expected range of £{lower_bound:,.1f} to £{upper_bound:,.1f}" - ) - - -def test_universal_childcare_entitlement_recipients(): - """ - Test that the number of children receiving universal childcare entitlement - has a reasonable value. - """ - sim = Simulation(scope="macro", country="uk", time_period="2024") - sim = sim.baseline_simulation - year = 2024 - - # Hard coded take-up rate - universal_childcare_entitlement_take_up_rate = 0.6 - - # Calculate eligible children - individual_entitlements = sim.calculate( - "universal_childcare_entitlement", period=year - ) - - # Count non-zero entitlements - eligible_children = (individual_entitlements > 0).sum() - - # Apply take-up rate - receiving_children = ( - eligible_children * universal_childcare_entitlement_take_up_rate - ) - - # Expected range - lower_bound = 400_000 - upper_bound = 500_000 - - print( - f"Children receiving universal childcare entitlement: {receiving_children:,.0f}" - ) - - assert lower_bound <= receiving_children <= upper_bound, ( - f"Number of children receiving universal childcare entitlement ({receiving_children:,.0f}) " - f"is outside the expected range of {lower_bound:,.0f} to {upper_bound:,.0f}" - ) - - -def test_extended_childcare_entitlement_aggregate(): - """ - Test that the total extended childcare entitlement has a reasonable value. - """ - sim = Simulation(scope="macro", country="uk", time_period="2024") - sim = sim.baseline_simulation - year = 2024 - - # Hard coded take-up rate - extended_childcare_entitlement_take_up_rate = 0.6 - - # Calculate individual entitlements and sum them up - individual_entitlements = sim.calculate( - "extended_childcare_entitlement", period=year - ) - - # Apply the take-up rate to the total - total_entitlement = ( - individual_entitlements.sum() - * extended_childcare_entitlement_take_up_rate - ) - - lower_bound = 2_800_000_000 - upper_bound = 3_300_000_000 - - print(f"Extended childcare entitlement total: £{total_entitlement:,.1f}") - - assert lower_bound <= total_entitlement <= upper_bound, ( - f"Extended childcare entitlement total (£{total_entitlement:,.1f}) " - f"is outside the expected range of £{lower_bound:,.1f} to £{upper_bound:,.1f}" - ) - - -def test_extended_childcare_entitlement_recipients(): - """ - Test that the number of children receiving extended childcare entitlement - has a reasonable value. - """ - sim = Simulation(scope="macro", country="uk", time_period="2024") - sim = sim.baseline_simulation - year = 2024 - - # Hard coded take-up rate - extended_childcare_entitlement_take_up_rate = 0.6 - - # Calculate eligible children - individual_entitlements = sim.calculate( - "extended_childcare_entitlement", period=year - ) - - # Count non-zero entitlements - eligible_children = (individual_entitlements > 0).sum() - - # Apply take-up rate - receiving_children = ( - eligible_children * extended_childcare_entitlement_take_up_rate - ) - - # Expected range - lower_bound = 400_000 - upper_bound = 500_000 - - print( - f"Children receiving extended childcare entitlement: {receiving_children:,.0f}" - ) - - assert lower_bound <= receiving_children <= upper_bound, ( - f"Number of children receiving extended childcare entitlement ({receiving_children:,.0f}) " - f"is outside the expected range of {lower_bound:,.0f} to {upper_bound:,.0f}" - ) - - -def test_targeted_childcare_entitlement_aggregate(): - """ - Test that the total targeted childcare entitlement has a reasonable value. - """ - sim = Simulation(scope="macro", country="uk", time_period="2024") - sim = sim.baseline_simulation - year = 2024 - - # Hard coded take-up rate - targeted_childcare_entitlement_take_up_rate = 0.6 - - # Calculate individual entitlements and sum them up - individual_entitlements = sim.calculate( - "targeted_childcare_entitlement", period=year - ) - - # Apply the take-up rate to the total - total_entitlement = ( - individual_entitlements.sum() - * targeted_childcare_entitlement_take_up_rate - ) - - lower_bound = 400_000_000 - upper_bound = 700_000_000 - - print(f"Targeted childcare entitlement total: £{total_entitlement:,.1f}") - - assert lower_bound <= total_entitlement <= upper_bound, ( - f"Targeted childcare entitlement total (£{total_entitlement:,.1f}) " - f"is outside the expected range of £{lower_bound:,.1f} to £{upper_bound:,.1f}" - ) - - -def test_targeted_childcare_entitlement_recipients(): - """ - Test that the number of children receiving targeted childcare entitlement - has a reasonable value. - """ - sim = Simulation(scope="macro", country="uk", time_period="2024") - sim = sim.baseline_simulation - year = 2024 - - # Hard coded take-up rate - targeted_childcare_entitlement_take_up_rate = 0.6 - - # Calculate eligible children - individual_entitlements = sim.calculate( - "targeted_childcare_entitlement", period=year - ) - - # Count non-zero entitlements - eligible_children = (individual_entitlements > 0).sum() - - # Apply take-up rate - receiving_children = ( - eligible_children * targeted_childcare_entitlement_take_up_rate - ) - - # Expected range - lower_bound = 100_000 - upper_bound = 150_000 - - print( - f"Children receiving targeted childcare entitlement: {receiving_children:,.0f}" - ) - - assert lower_bound <= receiving_children <= upper_bound, ( - f"Number of children receiving targeted childcare entitlement ({receiving_children:,.0f}) " - f"is outside the expected range of {lower_bound:,.0f} to {upper_bound:,.0f}" - ) - - -def test_care_to_learn_childcare_entitlement_aggregate(): - """ - Test that the total Care to Learn childcare entitlement has a reasonable value. - """ - sim = Simulation(scope="macro", country="uk", time_period="2024") - sim = sim.baseline_simulation - year = 2024 - - # Hard coded take-up rate - care_to_learn_take_up_rate = 0.6 - - # Calculate individual entitlements and sum them up - individual_entitlements = sim.calculate("care_to_learn", period=year) - - # Apply the take-up rate to the total - total_entitlement = ( - individual_entitlements.sum() * care_to_learn_take_up_rate - ) - - # Currently, the entitlement is zero, so we test for that - # If implementation changes in the future, update these bounds - lower_bound = 0 - upper_bound = 1_000_000 - - print( - f"Care to Learn childcare entitlement total: £{total_entitlement:,.1f}" - ) - - assert lower_bound <= total_entitlement <= upper_bound, ( - f"Care to Learn childcare entitlement total (£{total_entitlement:,.1f}) " - f"is outside the expected range of £{lower_bound:,.1f} to £{upper_bound:,.1f}" - ) - - -def test_care_to_learn_childcare_recipients(): - """ - Test that the number of young people receiving Care to Learn - has a reasonable value. - """ - sim = Simulation(scope="macro", country="uk", time_period="2024") - sim = sim.baseline_simulation - year = 2024 - - # Hard coded take-up rate - care_to_learn_take_up_rate = 0.6 - - # Calculate eligible young people - individual_entitlements = sim.calculate("care_to_learn", period=year) - - # Count non-zero entitlements - eligible_children = (individual_entitlements > 0).sum() - - # Apply take-up rate - receiving_children = eligible_children * care_to_learn_take_up_rate - - # Expected range (currently zero, update when implemented) - lower_bound = 0 - upper_bound = 10_000 - - print(f"Young people receiving Care to Learn: {receiving_children:,.0f}") - - assert lower_bound <= receiving_children <= upper_bound, ( - f"Number of young people receiving Care to Learn ({receiving_children:,.0f}) " - f"is outside the expected range of {lower_bound:,.0f} to {upper_bound:,.0f}" - ) - - -def test_tax_free_childcare_aggregate(): - """ - Test that the total tax-free childcare entitlement has a reasonable value. - """ - sim = Simulation(scope="macro", country="uk", time_period="2024") - sim = sim.baseline_simulation - year = 2024 - - # Hard coded take-up rate - tax_free_childcare_take_up_rate = 0.6 - - # Calculate individual entitlements and sum them up - individual_entitlements = sim.calculate("tax_free_childcare", period=year) - - # Apply the take-up rate to the total - total_entitlement = ( - individual_entitlements.sum() * tax_free_childcare_take_up_rate - ) - - # Expected range for tax-free childcare - lower_bound = 300_000_000 - upper_bound = 600_000_000 - - print(f"Tax-free childcare entitlement total: £{total_entitlement:,.1f}") - - assert lower_bound <= total_entitlement <= upper_bound, ( - f"Tax-free childcare entitlement total (£{total_entitlement:,.1f}) " - f"is outside the expected range of £{lower_bound:,.1f} to £{upper_bound:,.1f}" - ) - - -def test_tax_free_childcare_recipients(): - """ - Test that the number of children receiving tax-free childcare - has a reasonable value. - """ - sim = Simulation(scope="macro", country="uk", time_period="2024") - sim = sim.baseline_simulation - year = 2024 - - # Hard coded take-up rate - tax_free_childcare_take_up_rate = 0.6 - - # Calculate eligible children - individual_entitlements = sim.calculate("tax_free_childcare", period=year) - - # Count non-zero entitlements - eligible_children = (individual_entitlements > 0).sum() - - # Apply take-up rate - receiving_children = eligible_children * tax_free_childcare_take_up_rate - - # Expected range - lower_bound = 600_000 - upper_bound = 800_000 - - print(f"Children receiving tax-free childcare: {receiving_children:,.0f}") - - assert lower_bound <= receiving_children <= upper_bound, ( - f"Number of children receiving tax-free childcare ({receiving_children:,.0f}) " - f"is outside the expected range of {lower_bound:,.0f} to {upper_bound:,.0f}" - ) From 87146df1dc79898119b4db835436d26b014c75f0 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Tue, 8 Apr 2025 11:24:24 +0100 Subject: [PATCH 24/39] Remove test_childcare.py to be excluded from PR --- .../tests/microsimulation/test_childcare.py | 350 ------------------ 1 file changed, 350 deletions(-) delete mode 100644 policyengine_uk/tests/microsimulation/test_childcare.py diff --git a/policyengine_uk/tests/microsimulation/test_childcare.py b/policyengine_uk/tests/microsimulation/test_childcare.py deleted file mode 100644 index 2654a9a74..000000000 --- a/policyengine_uk/tests/microsimulation/test_childcare.py +++ /dev/null @@ -1,350 +0,0 @@ -from policyengine import Simulation -import pytest - - -def test_universal_childcare_entitlement_aggregate(): - """ - Test that the total universal childcare entitlement has a reasonable value. - """ - sim = Simulation(scope="macro", country="uk", time_period="2024") - sim = sim.baseline_simulation - year = 2024 - - # Hard coded take-up rate - # Move this take-up rate to the uk-data package - universal_childcare_entitlement_take_up_rate = 0.6 - - # Calculate individual entitlements and sum them up - individual_entitlements = sim.calculate( - "universal_childcare_entitlement", period=year - ) - - # Apply the take-up rate to the total - total_entitlement = ( - individual_entitlements.sum() - * universal_childcare_entitlement_take_up_rate - ) - - lower_bound = 1_500_000_000 - upper_bound = 2_000_000_000 - - print(f"Universal childcare entitlement total: £{total_entitlement:,.1f}") - - assert lower_bound <= total_entitlement <= upper_bound, ( - f"Universal childcare entitlement total (£{total_entitlement:,.1f}) " - f"is outside the expected range of £{lower_bound:,.1f} to £{upper_bound:,.1f}" - ) - - -def test_universal_childcare_entitlement_recipients(): - """ - Test that the number of children receiving universal childcare entitlement - has a reasonable value. - """ - sim = Simulation(scope="macro", country="uk", time_period="2024") - sim = sim.baseline_simulation - year = 2024 - - # Hard coded take-up rate - universal_childcare_entitlement_take_up_rate = 0.6 - - # Calculate eligible children - individual_entitlements = sim.calculate( - "universal_childcare_entitlement", period=year - ) - - # Count non-zero entitlements - eligible_children = (individual_entitlements > 0).sum() - - # Apply take-up rate - receiving_children = ( - eligible_children * universal_childcare_entitlement_take_up_rate - ) - - # Expected range - lower_bound = 400_000 - upper_bound = 500_000 - - print( - f"Children receiving universal childcare entitlement: {receiving_children:,.0f}" - ) - - assert lower_bound <= receiving_children <= upper_bound, ( - f"Number of children receiving universal childcare entitlement ({receiving_children:,.0f}) " - f"is outside the expected range of {lower_bound:,.0f} to {upper_bound:,.0f}" - ) - - -def test_extended_childcare_entitlement_aggregate(): - """ - Test that the total extended childcare entitlement has a reasonable value. - """ - sim = Simulation(scope="macro", country="uk", time_period="2024") - sim = sim.baseline_simulation - year = 2024 - - # Hard coded take-up rate - extended_childcare_entitlement_take_up_rate = 0.6 - - # Calculate individual entitlements and sum them up - individual_entitlements = sim.calculate( - "extended_childcare_entitlement", period=year - ) - - # Apply the take-up rate to the total - total_entitlement = ( - individual_entitlements.sum() - * extended_childcare_entitlement_take_up_rate - ) - - lower_bound = 2_800_000_000 - upper_bound = 3_300_000_000 - - print(f"Extended childcare entitlement total: £{total_entitlement:,.1f}") - - assert lower_bound <= total_entitlement <= upper_bound, ( - f"Extended childcare entitlement total (£{total_entitlement:,.1f}) " - f"is outside the expected range of £{lower_bound:,.1f} to £{upper_bound:,.1f}" - ) - - -def test_extended_childcare_entitlement_recipients(): - """ - Test that the number of children receiving extended childcare entitlement - has a reasonable value. - """ - sim = Simulation(scope="macro", country="uk", time_period="2024") - sim = sim.baseline_simulation - year = 2024 - - # Hard coded take-up rate - extended_childcare_entitlement_take_up_rate = 0.6 - - # Calculate eligible children - individual_entitlements = sim.calculate( - "extended_childcare_entitlement", period=year - ) - - # Count non-zero entitlements - eligible_children = (individual_entitlements > 0).sum() - - # Apply take-up rate - receiving_children = ( - eligible_children * extended_childcare_entitlement_take_up_rate - ) - - # Expected range - lower_bound = 400_000 - upper_bound = 500_000 - - print( - f"Children receiving extended childcare entitlement: {receiving_children:,.0f}" - ) - - assert lower_bound <= receiving_children <= upper_bound, ( - f"Number of children receiving extended childcare entitlement ({receiving_children:,.0f}) " - f"is outside the expected range of {lower_bound:,.0f} to {upper_bound:,.0f}" - ) - - -def test_targeted_childcare_entitlement_aggregate(): - """ - Test that the total targeted childcare entitlement has a reasonable value. - """ - sim = Simulation(scope="macro", country="uk", time_period="2024") - sim = sim.baseline_simulation - year = 2024 - - # Hard coded take-up rate - targeted_childcare_entitlement_take_up_rate = 0.6 - - # Calculate individual entitlements and sum them up - individual_entitlements = sim.calculate( - "targeted_childcare_entitlement", period=year - ) - - # Apply the take-up rate to the total - total_entitlement = ( - individual_entitlements.sum() - * targeted_childcare_entitlement_take_up_rate - ) - - lower_bound = 400_000_000 - upper_bound = 700_000_000 - - print(f"Targeted childcare entitlement total: £{total_entitlement:,.1f}") - - assert lower_bound <= total_entitlement <= upper_bound, ( - f"Targeted childcare entitlement total (£{total_entitlement:,.1f}) " - f"is outside the expected range of £{lower_bound:,.1f} to £{upper_bound:,.1f}" - ) - - -def test_targeted_childcare_entitlement_recipients(): - """ - Test that the number of children receiving targeted childcare entitlement - has a reasonable value. - """ - sim = Simulation(scope="macro", country="uk", time_period="2024") - sim = sim.baseline_simulation - year = 2024 - - # Hard coded take-up rate - targeted_childcare_entitlement_take_up_rate = 0.6 - - # Calculate eligible children - individual_entitlements = sim.calculate( - "targeted_childcare_entitlement", period=year - ) - - # Count non-zero entitlements - eligible_children = (individual_entitlements > 0).sum() - - # Apply take-up rate - receiving_children = ( - eligible_children * targeted_childcare_entitlement_take_up_rate - ) - - # Expected range - lower_bound = 100_000 - upper_bound = 150_000 - - print( - f"Children receiving targeted childcare entitlement: {receiving_children:,.0f}" - ) - - assert lower_bound <= receiving_children <= upper_bound, ( - f"Number of children receiving targeted childcare entitlement ({receiving_children:,.0f}) " - f"is outside the expected range of {lower_bound:,.0f} to {upper_bound:,.0f}" - ) - - -def test_care_to_learn_childcare_entitlement_aggregate(): - """ - Test that the total Care to Learn childcare entitlement has a reasonable value. - """ - sim = Simulation(scope="macro", country="uk", time_period="2024") - sim = sim.baseline_simulation - year = 2024 - - # Hard coded take-up rate - care_to_learn_take_up_rate = 0.6 - - # Calculate individual entitlements and sum them up - individual_entitlements = sim.calculate("care_to_learn", period=year) - - # Apply the take-up rate to the total - total_entitlement = ( - individual_entitlements.sum() * care_to_learn_take_up_rate - ) - - # Currently, the entitlement is zero, so we test for that - # If implementation changes in the future, update these bounds - lower_bound = 0 - upper_bound = 1_000_000 - - print( - f"Care to Learn childcare entitlement total: £{total_entitlement:,.1f}" - ) - - assert lower_bound <= total_entitlement <= upper_bound, ( - f"Care to Learn childcare entitlement total (£{total_entitlement:,.1f}) " - f"is outside the expected range of £{lower_bound:,.1f} to £{upper_bound:,.1f}" - ) - - -def test_care_to_learn_childcare_recipients(): - """ - Test that the number of young people receiving Care to Learn - has a reasonable value. - """ - sim = Simulation(scope="macro", country="uk", time_period="2024") - sim = sim.baseline_simulation - year = 2024 - - # Hard coded take-up rate - care_to_learn_take_up_rate = 0.6 - - # Calculate eligible young people - individual_entitlements = sim.calculate("care_to_learn", period=year) - - # Count non-zero entitlements - eligible_children = (individual_entitlements > 0).sum() - - # Apply take-up rate - receiving_children = eligible_children * care_to_learn_take_up_rate - - # Expected range (currently zero, update when implemented) - lower_bound = 0 - upper_bound = 10_000 - - print(f"Young people receiving Care to Learn: {receiving_children:,.0f}") - - assert lower_bound <= receiving_children <= upper_bound, ( - f"Number of young people receiving Care to Learn ({receiving_children:,.0f}) " - f"is outside the expected range of {lower_bound:,.0f} to {upper_bound:,.0f}" - ) - - -def test_tax_free_childcare_aggregate(): - """ - Test that the total tax-free childcare entitlement has a reasonable value. - """ - sim = Simulation(scope="macro", country="uk", time_period="2024") - sim = sim.baseline_simulation - year = 2024 - - # Hard coded take-up rate - tax_free_childcare_take_up_rate = 0.6 - - # Calculate individual entitlements and sum them up - individual_entitlements = sim.calculate("tax_free_childcare", period=year) - - # Apply the take-up rate to the total - total_entitlement = ( - individual_entitlements.sum() * tax_free_childcare_take_up_rate - ) - - # Expected range for tax-free childcare - lower_bound = 300_000_000 - upper_bound = 600_000_000 - - print(f"Tax-free childcare entitlement total: £{total_entitlement:,.1f}") - - assert lower_bound <= total_entitlement <= upper_bound, ( - f"Tax-free childcare entitlement total (£{total_entitlement:,.1f}) " - f"is outside the expected range of £{lower_bound:,.1f} to £{upper_bound:,.1f}" - ) - - -def test_tax_free_childcare_recipients(): - """ - Test that the number of children receiving tax-free childcare - has a reasonable value. - """ - sim = Simulation(scope="macro", country="uk", time_period="2024") - sim = sim.baseline_simulation - year = 2024 - - # Hard coded take-up rate - tax_free_childcare_take_up_rate = 0.6 - - # Calculate eligible children - individual_entitlements = sim.calculate("tax_free_childcare", period=year) - - # Count non-zero entitlements - eligible_children = (individual_entitlements > 0).sum() - - # Apply take-up rate - receiving_children = eligible_children * tax_free_childcare_take_up_rate - - # Expected range - lower_bound = 600_000 - upper_bound = 800_000 - - print(f"Children receiving tax-free childcare: {receiving_children:,.0f}") - - assert lower_bound <= receiving_children <= upper_bound, ( - f"Number of children receiving tax-free childcare ({receiving_children:,.0f}) " - f"is outside the expected range of {lower_bound:,.0f} to {upper_bound:,.0f}" - ) From 06e1cf63b81226fb5bbb50dc44b9291307db1f04 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Tue, 8 Apr 2025 11:38:42 +0100 Subject: [PATCH 25/39] add changelog --- changelog_entry.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/changelog_entry.yaml b/changelog_entry.yaml index e69de29bb..de81c8784 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -0,0 +1,5 @@ +bump: minor +changes: + added: + - is_parent variable correction + - childcare programs' logic correction \ No newline at end of file From 8750641fa56ea4976c82ce969df18439c8bd3b53 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Tue, 8 Apr 2025 13:29:21 +0100 Subject: [PATCH 26/39] Edit changelog --- changelog_entry.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/changelog_entry.yaml b/changelog_entry.yaml index de81c8784..084f3bf34 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -1,5 +1,5 @@ bump: minor changes: - added: - - is_parent variable correction - - childcare programs' logic correction \ No newline at end of file + fixed: + - Corrected the is_parent variable to properly identify parents. + - Fixed logic in childcare programs to ensure accurate calculations. \ No newline at end of file From c8b64c06c91fb9bf3010c286cef6c7265732b0ce Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Tue, 8 Apr 2025 13:36:19 +0100 Subject: [PATCH 27/39] Add comments --- changelog_entry.yaml | 10 +++++----- .../targeted_childcare_entitlement_eligible.py | 2 ++ .../universal_childcare_entitlement_eligible.py | 2 ++ 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/changelog_entry.yaml b/changelog_entry.yaml index 084f3bf34..73f27e810 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -1,5 +1,5 @@ -bump: minor -changes: - fixed: - - Corrected the is_parent variable to properly identify parents. - - Fixed logic in childcare programs to ensure accurate calculations. \ No newline at end of file +- bump: patch + changes: + fixed: + - Corrected the is_parent variable to properly identify parents. + - Fixed logic in childcare programs to ensure accurate calculations. \ No newline at end of file diff --git a/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement_eligible.py b/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement_eligible.py index d26292136..3bfc43629 100644 --- a/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement_eligible.py +++ b/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement_eligible.py @@ -16,6 +16,8 @@ def formula(benunit, period, parameters): # Get parameters p = parameters(period).gov.dfe.targeted_childcare_entitlement + # Check if household has extended childcare. If so, they are not eligible. Combining extended childcare and targeted childcare is not allowed. + # https://www.childcarechoices.gov.uk/combining-schemes has_extended_childcare = benunit( "extended_childcare_entitlement_eligible", period ) diff --git a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py index 998548029..100dc4bcd 100644 --- a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py +++ b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py @@ -19,6 +19,8 @@ def formula(person, period, parameters): meets_age_condition = (age >= p.min_age) & (age < p.max_age) not_compulsory_age = ~person("is_of_compulsory_school_age", period) + # Check if person has extended childcare. If so, they are not eligible. Combining extended childcare and universal childcare is not allowed. + # https://www.childcarechoices.gov.uk/combining-schemes has_extended_childcare = person.benunit( "extended_childcare_entitlement_eligible", period ) From ced9dd41e57d4ff1ff930f078fa7583e9bb75858 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Tue, 8 Apr 2025 13:37:22 +0100 Subject: [PATCH 28/39] Black --- .../targeted_childcare_entitlement_eligible.py | 2 +- .../universal_childcare_entitlement_eligible.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement_eligible.py b/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement_eligible.py index 3bfc43629..a41a9447a 100644 --- a/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement_eligible.py +++ b/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement_eligible.py @@ -16,7 +16,7 @@ def formula(benunit, period, parameters): # Get parameters p = parameters(period).gov.dfe.targeted_childcare_entitlement - # Check if household has extended childcare. If so, they are not eligible. Combining extended childcare and targeted childcare is not allowed. + # Check if household has extended childcare. If so, they are not eligible. Combining extended childcare and targeted childcare is not allowed. # https://www.childcarechoices.gov.uk/combining-schemes has_extended_childcare = benunit( "extended_childcare_entitlement_eligible", period diff --git a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py index 100dc4bcd..4c0d2be3b 100644 --- a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py +++ b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py @@ -19,7 +19,7 @@ def formula(person, period, parameters): meets_age_condition = (age >= p.min_age) & (age < p.max_age) not_compulsory_age = ~person("is_of_compulsory_school_age", period) - # Check if person has extended childcare. If so, they are not eligible. Combining extended childcare and universal childcare is not allowed. + # Check if person has extended childcare. If so, they are not eligible. Combining extended childcare and universal childcare is not allowed. # https://www.childcarechoices.gov.uk/combining-schemes has_extended_childcare = person.benunit( "extended_childcare_entitlement_eligible", period From 03b6ece44d60b7c5820cebda944495ed817edb6c Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Tue, 8 Apr 2025 14:00:51 +0100 Subject: [PATCH 29/39] Add would claim variable --- .../gov/dfe/care_to_learn/care_to_learn_eligible.py | 1 + .../dfe/care_to_learn/would_claim_care_to_learn.py | 12 ++++++++++++ .../extended_childcare_entitlement_eligible.py | 1 + .../would_claim_extended_childcare.py | 10 ++++++++++ .../targeted_childcare_entitlement_eligible.py | 1 + .../would_claim_targeted_childcare.py | 10 ++++++++++ .../universal_childcare_entitlement_eligible.py | 1 + .../would_claim_universal_childcare.py | 10 ++++++++++ .../tax_free_childcare_eligibility.py | 1 + .../gov/hmrc/tax_free_childcare/would_claim_tfc.py | 12 ++++++++++++ 10 files changed, 59 insertions(+) create mode 100644 policyengine_uk/variables/gov/dfe/care_to_learn/would_claim_care_to_learn.py create mode 100644 policyengine_uk/variables/gov/dfe/extended_childcare_entitlement/would_claim_extended_childcare.py create mode 100644 policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/would_claim_targeted_childcare.py create mode 100644 policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/would_claim_universal_childcare.py create mode 100644 policyengine_uk/variables/gov/hmrc/tax_free_childcare/would_claim_tfc.py diff --git a/policyengine_uk/variables/gov/dfe/care_to_learn/care_to_learn_eligible.py b/policyengine_uk/variables/gov/dfe/care_to_learn/care_to_learn_eligible.py index 4f75d59a8..8e5d70a2e 100644 --- a/policyengine_uk/variables/gov/dfe/care_to_learn/care_to_learn_eligible.py +++ b/policyengine_uk/variables/gov/dfe/care_to_learn/care_to_learn_eligible.py @@ -6,6 +6,7 @@ class care_to_learn_eligible(Variable): entity = Person label = "eligible for Care to Learn childcare support" definition_period = YEAR + defined_for = "would_claim_care_to_learn" def formula(person, period, parameters): # Link for instruction: https://www.gov.uk/care-to-learn/eligibility diff --git a/policyengine_uk/variables/gov/dfe/care_to_learn/would_claim_care_to_learn.py b/policyengine_uk/variables/gov/dfe/care_to_learn/would_claim_care_to_learn.py new file mode 100644 index 000000000..b6a7fad53 --- /dev/null +++ b/policyengine_uk/variables/gov/dfe/care_to_learn/would_claim_care_to_learn.py @@ -0,0 +1,12 @@ +from policyengine_uk.model_api import * + + +class would_claim_care_to_learn(Variable): + value_type = bool + entity = BenUnit + label = "would claim Care to Learn" + documentation = ( + "Whether this BenUnit would claim Care to Learn if eligible" + ) + definition_period = YEAR + default_value = True diff --git a/policyengine_uk/variables/gov/dfe/extended_childcare_entitlement/extended_childcare_entitlement_eligible.py b/policyengine_uk/variables/gov/dfe/extended_childcare_entitlement/extended_childcare_entitlement_eligible.py index 1238d2c4b..c7bc26dce 100644 --- a/policyengine_uk/variables/gov/dfe/extended_childcare_entitlement/extended_childcare_entitlement_eligible.py +++ b/policyengine_uk/variables/gov/dfe/extended_childcare_entitlement/extended_childcare_entitlement_eligible.py @@ -6,6 +6,7 @@ class extended_childcare_entitlement_eligible(Variable): entity = BenUnit label = "eligibility for extended childcare entitlement" definition_period = YEAR + defined_for = "would_claim_extended_childcare" def formula(benunit, period, parameters): # Check if household is in England diff --git a/policyengine_uk/variables/gov/dfe/extended_childcare_entitlement/would_claim_extended_childcare.py b/policyengine_uk/variables/gov/dfe/extended_childcare_entitlement/would_claim_extended_childcare.py new file mode 100644 index 000000000..070c50542 --- /dev/null +++ b/policyengine_uk/variables/gov/dfe/extended_childcare_entitlement/would_claim_extended_childcare.py @@ -0,0 +1,10 @@ +from policyengine_uk.model_api import * + + +class would_claim_extended_childcare(Variable): + value_type = bool + entity = BenUnit + label = "would claim extended childcare entitlement" + documentation = "Whether this family would claim extended childcare entitlement if eligible" + definition_period = YEAR + default_value = True diff --git a/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement_eligible.py b/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement_eligible.py index a41a9447a..47be60f5e 100644 --- a/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement_eligible.py +++ b/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement_eligible.py @@ -6,6 +6,7 @@ class targeted_childcare_entitlement_eligible(Variable): entity = BenUnit label = "eligibility for targeted childcare entitlement" definition_period = YEAR + defined_for = "would_claim_targeted_childcare" def formula(benunit, period, parameters): diff --git a/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/would_claim_targeted_childcare.py b/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/would_claim_targeted_childcare.py new file mode 100644 index 000000000..bb755228f --- /dev/null +++ b/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/would_claim_targeted_childcare.py @@ -0,0 +1,10 @@ +from policyengine_uk.model_api import * + + +class would_claim_targeted_childcare(Variable): + value_type = bool + entity = BenUnit + label = "would claim targeted childcare entitlement" + documentation = "Whether this family would claim targeted childcare entitlement if eligible" + definition_period = YEAR + default_value = True diff --git a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py index 4c0d2be3b..9e6a9892f 100644 --- a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py +++ b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement_eligible.py @@ -6,6 +6,7 @@ class universal_childcare_entitlement_eligible(Variable): entity = Person label = "eligible for universal childcare entitlement" definition_period = YEAR + defined_for = "would_claim_universal_childcare" def formula(person, period, parameters): country = person.household("country", period) diff --git a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/would_claim_universal_childcare.py b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/would_claim_universal_childcare.py new file mode 100644 index 000000000..b6066b4bc --- /dev/null +++ b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/would_claim_universal_childcare.py @@ -0,0 +1,10 @@ +from policyengine_uk.model_api import * + + +class would_claim_universal_childcare(Variable): + value_type = bool + entity = BenUnit + label = "would claim universal childcare entitlement" + documentation = "Whether this BenUnit would claim universal childcare entitlement if eligible" + definition_period = YEAR + default_value = True diff --git a/policyengine_uk/variables/gov/hmrc/tax_free_childcare/tax_free_childcare_eligibility.py b/policyengine_uk/variables/gov/hmrc/tax_free_childcare/tax_free_childcare_eligibility.py index d3ac579c3..92686b15b 100644 --- a/policyengine_uk/variables/gov/hmrc/tax_free_childcare/tax_free_childcare_eligibility.py +++ b/policyengine_uk/variables/gov/hmrc/tax_free_childcare/tax_free_childcare_eligibility.py @@ -6,6 +6,7 @@ class tax_free_childcare_eligible(Variable): entity = BenUnit label = "overall eligibility for tax-free childcare" definition_period = YEAR + defined_for = "would_claim_tfc" def formula(benunit, period, parameters): meets_age_condition = benunit.any( diff --git a/policyengine_uk/variables/gov/hmrc/tax_free_childcare/would_claim_tfc.py b/policyengine_uk/variables/gov/hmrc/tax_free_childcare/would_claim_tfc.py new file mode 100644 index 000000000..2a623372c --- /dev/null +++ b/policyengine_uk/variables/gov/hmrc/tax_free_childcare/would_claim_tfc.py @@ -0,0 +1,12 @@ +from policyengine_uk.model_api import * + + +class would_claim_tfc(Variable): + value_type = bool + entity = BenUnit + label = "would claim Tax-Free Childcare" + documentation = ( + "Whether this family would claim Tax-Free Childcare if eligible" + ) + definition_period = YEAR + default_value = True From da5393b6b31b35d5bcdae69bc58fd9df206cb490 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Mon, 14 Apr 2025 14:11:14 +0100 Subject: [PATCH 30/39] Add max_free_entitlement_hours_used --- .../gov/dfe/max_free_entitlement_hours_used.py | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 policyengine_uk/variables/gov/dfe/max_free_entitlement_hours_used.py diff --git a/policyengine_uk/variables/gov/dfe/max_free_entitlement_hours_used.py b/policyengine_uk/variables/gov/dfe/max_free_entitlement_hours_used.py new file mode 100644 index 000000000..a68133274 --- /dev/null +++ b/policyengine_uk/variables/gov/dfe/max_free_entitlement_hours_used.py @@ -0,0 +1,10 @@ +from policyengine_uk.model_api import * + + +class max_free_entitlement_hours_used(Variable): + value_type = float + entity = Person + label = "maximum hours of free childcare entitlement used" + documentation = "The maximum weekly hours of free childcare entitlement used by the person" + definition_period = WEEK + default_value = 30 \ No newline at end of file From 058c166538d4a0b541336c22673ca8db83b9ac88 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Mon, 14 Apr 2025 14:12:30 +0100 Subject: [PATCH 31/39] Edit py file --- .../variables/gov/dfe/max_free_entitlement_hours_used.py | 1 - 1 file changed, 1 deletion(-) diff --git a/policyengine_uk/variables/gov/dfe/max_free_entitlement_hours_used.py b/policyengine_uk/variables/gov/dfe/max_free_entitlement_hours_used.py index a68133274..57f489954 100644 --- a/policyengine_uk/variables/gov/dfe/max_free_entitlement_hours_used.py +++ b/policyengine_uk/variables/gov/dfe/max_free_entitlement_hours_used.py @@ -6,5 +6,4 @@ class max_free_entitlement_hours_used(Variable): entity = Person label = "maximum hours of free childcare entitlement used" documentation = "The maximum weekly hours of free childcare entitlement used by the person" - definition_period = WEEK default_value = 30 \ No newline at end of file From ed9973545337b739e38ea32ae336db42dfe4766f Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Mon, 14 Apr 2025 14:15:08 +0100 Subject: [PATCH 32/39] Format --- .../variables/gov/dfe/max_free_entitlement_hours_used.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/policyengine_uk/variables/gov/dfe/max_free_entitlement_hours_used.py b/policyengine_uk/variables/gov/dfe/max_free_entitlement_hours_used.py index 57f489954..adb2ec36a 100644 --- a/policyengine_uk/variables/gov/dfe/max_free_entitlement_hours_used.py +++ b/policyengine_uk/variables/gov/dfe/max_free_entitlement_hours_used.py @@ -6,4 +6,4 @@ class max_free_entitlement_hours_used(Variable): entity = Person label = "maximum hours of free childcare entitlement used" documentation = "The maximum weekly hours of free childcare entitlement used by the person" - default_value = 30 \ No newline at end of file + default_value = 30 From 95dbe12e9915763de7e884acc2f264c7ae942286 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Mon, 14 Apr 2025 14:16:14 +0100 Subject: [PATCH 33/39] edit definition_period --- .../variables/gov/dfe/max_free_entitlement_hours_used.py | 1 + 1 file changed, 1 insertion(+) diff --git a/policyengine_uk/variables/gov/dfe/max_free_entitlement_hours_used.py b/policyengine_uk/variables/gov/dfe/max_free_entitlement_hours_used.py index adb2ec36a..d93d1afe7 100644 --- a/policyengine_uk/variables/gov/dfe/max_free_entitlement_hours_used.py +++ b/policyengine_uk/variables/gov/dfe/max_free_entitlement_hours_used.py @@ -6,4 +6,5 @@ class max_free_entitlement_hours_used(Variable): entity = Person label = "maximum hours of free childcare entitlement used" documentation = "The maximum weekly hours of free childcare entitlement used by the person" + definition_period = WEEK default_value = 30 From 475a2b1e7b3bae8267821c5e04d9b8e2e2286183 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Mon, 14 Apr 2025 14:19:04 +0100 Subject: [PATCH 34/39] edit definition_period --- .../variables/gov/dfe/max_free_entitlement_hours_used.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/policyengine_uk/variables/gov/dfe/max_free_entitlement_hours_used.py b/policyengine_uk/variables/gov/dfe/max_free_entitlement_hours_used.py index d93d1afe7..3dc51f346 100644 --- a/policyengine_uk/variables/gov/dfe/max_free_entitlement_hours_used.py +++ b/policyengine_uk/variables/gov/dfe/max_free_entitlement_hours_used.py @@ -6,5 +6,5 @@ class max_free_entitlement_hours_used(Variable): entity = Person label = "maximum hours of free childcare entitlement used" documentation = "The maximum weekly hours of free childcare entitlement used by the person" - definition_period = WEEK + definition_period = YEAR default_value = 30 From 1eb4943c5e24e1e0240f0fe69e9b2868fddf1dff Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Mon, 14 Apr 2025 15:41:36 +0100 Subject: [PATCH 35/39] Add weeks_per_year --- .../parameters/gov/dfe/weeks_per_year.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 policyengine_uk/parameters/gov/dfe/weeks_per_year.yaml diff --git a/policyengine_uk/parameters/gov/dfe/weeks_per_year.yaml b/policyengine_uk/parameters/gov/dfe/weeks_per_year.yaml new file mode 100644 index 000000000..52d25a49e --- /dev/null +++ b/policyengine_uk/parameters/gov/dfe/weeks_per_year.yaml @@ -0,0 +1,14 @@ +description: The Department for Education provides targeted, extended, and universal childcare entitlement for these weeks per year. +metadata: + period: year + unit: week + label: childcare entitlement weeks per year + reference: + - title: The Local Authority (Duty to Secure Early Years Provision Free of Charge) Regulations 2014 - regulation 4 + href: https://www.legislation.gov.uk/uksi/2014/2147/regulation/4/made + - title: Childcare Choices document - 15 and 30 hours childcare support + href: https://www.childcarechoices.gov.uk/15-and-30-hours-childcare-support/working-families/eligibility + - title: Childcare (Early Years Provision Free of Charge) (Extended Entitlement) Regulations 2016 - Regulation 35(3) + href: https://www.legislation.gov.uk/uksi/2016/1257/part/4/made +values: + 2016-01-01: 38 \ No newline at end of file From c1ca65ed456d3cc7bda4f1ee50cbdb7e5057a56c Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Tue, 15 Apr 2025 11:41:50 +0100 Subject: [PATCH 36/39] Add hours condition --- .../extended_childcare_entitlement.py | 14 +++++++++----- .../targeted_childcare_entitlement.py | 7 ++++++- .../universal_childcare_entitlement.py | 7 ++++++- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/policyengine_uk/variables/gov/dfe/extended_childcare_entitlement/extended_childcare_entitlement.py b/policyengine_uk/variables/gov/dfe/extended_childcare_entitlement/extended_childcare_entitlement.py index b95066c39..c8123bb89 100644 --- a/policyengine_uk/variables/gov/dfe/extended_childcare_entitlement/extended_childcare_entitlement.py +++ b/policyengine_uk/variables/gov/dfe/extended_childcare_entitlement/extended_childcare_entitlement.py @@ -19,13 +19,17 @@ def formula(benunit, period, parameters): age ) + # Get max hours used per child + max_hours_used = benunit.members("max_free_entitlement_hours_used", period) + + # Use the appropriate hours based on the condition + weekly_hours_to_use = min_(max_hours_used, weekly_hours_per_child) + # Compute weekly subsidy per child weekly_subsidy_per_child = ( - weekly_hours_per_child * p.childcare_funding_rate.calc(age) + weekly_hours_to_use * p.childcare_funding_rate.calc(age) ) # Compute total annual expenses - return ( - benunit.sum(weekly_subsidy_per_child) - * p.extended_childcare_entitlement.weeks_per_year - ) + weeks = p.weeks_per_year + return benunit.sum(weekly_subsidy_per_child) * weeks diff --git a/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement.py b/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement.py index 0f20aafb7..ce9cddd5b 100644 --- a/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement.py +++ b/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement.py @@ -19,4 +19,9 @@ def formula(person, period, parameters): p.targeted_childcare_entitlement.hours_entitlement * eligible_by_age ) - return hours * p.childcare_funding_rate.calc(age) + max_hours_used = person("max_free_entitlement_hours_used", period) + weeks = p.weeks_per_year + total_hours_used = max_hours_used * weeks + + hours_to_use = min_(total_hours_used, hours) + return hours_to_use * p.childcare_funding_rate.calc(age) diff --git a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement.py b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement.py index 6a65101a9..19eea0f44 100644 --- a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement.py +++ b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement.py @@ -13,4 +13,9 @@ def formula(person, period, parameters): p = parameters(period).gov.dfe age = person("age", period) hours = p.universal_childcare_entitlement.hours - return hours * p.childcare_funding_rate.calc(age) + max_hours_used = person("max_free_entitlement_hours_used", period) + weeks = p.weeks_per_year + total_hours_used = max_hours_used * weeks + + hours_to_use = min_(total_hours_used, hours) + return hours_to_use * p.childcare_funding_rate.calc(age) From d79745eb16c31d5815d59908370bb6537282bf92 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Tue, 15 Apr 2025 11:44:16 +0100 Subject: [PATCH 37/39] Format --- .../extended_childcare_entitlement.py | 6 ++++-- .../targeted_childcare_entitlement.py | 2 +- .../universal_childcare_entitlement.py | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/policyengine_uk/variables/gov/dfe/extended_childcare_entitlement/extended_childcare_entitlement.py b/policyengine_uk/variables/gov/dfe/extended_childcare_entitlement/extended_childcare_entitlement.py index c8123bb89..cbc4fe0e2 100644 --- a/policyengine_uk/variables/gov/dfe/extended_childcare_entitlement/extended_childcare_entitlement.py +++ b/policyengine_uk/variables/gov/dfe/extended_childcare_entitlement/extended_childcare_entitlement.py @@ -20,8 +20,10 @@ def formula(benunit, period, parameters): ) # Get max hours used per child - max_hours_used = benunit.members("max_free_entitlement_hours_used", period) - + max_hours_used = benunit.members( + "max_free_entitlement_hours_used", period + ) + # Use the appropriate hours based on the condition weekly_hours_to_use = min_(max_hours_used, weekly_hours_per_child) diff --git a/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement.py b/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement.py index ce9cddd5b..c5e3e7ef4 100644 --- a/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement.py +++ b/policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement.py @@ -22,6 +22,6 @@ def formula(person, period, parameters): max_hours_used = person("max_free_entitlement_hours_used", period) weeks = p.weeks_per_year total_hours_used = max_hours_used * weeks - + hours_to_use = min_(total_hours_used, hours) return hours_to_use * p.childcare_funding_rate.calc(age) diff --git a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement.py b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement.py index 19eea0f44..1e6ebf520 100644 --- a/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement.py +++ b/policyengine_uk/variables/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement.py @@ -16,6 +16,6 @@ def formula(person, period, parameters): max_hours_used = person("max_free_entitlement_hours_used", period) weeks = p.weeks_per_year total_hours_used = max_hours_used * weeks - + hours_to_use = min_(total_hours_used, hours) return hours_to_use * p.childcare_funding_rate.calc(age) From a2bdba24c0bd67691b6a2726cee631d3b46be59c Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Tue, 15 Apr 2025 12:41:41 +0100 Subject: [PATCH 38/39] Add unit tests --- .../extended_childcare_entitlement.yaml | 35 ++++++- .../targeted_childcare_entitlement.yaml | 80 ++++++++++++++++ .../universal_childcare_entitlement.yaml | 94 +++++++++++++++---- 3 files changed, 191 insertions(+), 18 deletions(-) create mode 100644 policyengine_uk/tests/policy/baseline/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement.yaml diff --git a/policyengine_uk/tests/policy/baseline/gov/dfe/extended_childcare_entitlement/extended_childcare_entitlement.yaml b/policyengine_uk/tests/policy/baseline/gov/dfe/extended_childcare_entitlement/extended_childcare_entitlement.yaml index 287af4c21..cdc9875c6 100644 --- a/policyengine_uk/tests/policy/baseline/gov/dfe/extended_childcare_entitlement/extended_childcare_entitlement.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/dfe/extended_childcare_entitlement/extended_childcare_entitlement.yaml @@ -103,4 +103,37 @@ members: [child1] extended_childcare_entitlement_eligible: false output: - extended_childcare_entitlement: 0 # Not eligible \ No newline at end of file + extended_childcare_entitlement: 0 # Not eligible + +- name: Child using fewer hours than maximum entitlement + period: 2025 + absolute_error_margin: 1 + input: + people: + child1: + age: 3 + max_free_entitlement_hours_used: 20 + benunits: + benunit1: + members: [child1] + extended_childcare_entitlement_eligible: true + output: + extended_childcare_entitlement: 4611.457 # 20 hours * 38 weeks * £6.07 per hour (2025 rate) + +- name: Child using fewer hours than maximum entitlement - multiple children + period: 2025 + absolute_error_margin: 100 + input: + people: + child1: + age: 2 + max_free_entitlement_hours_used: 10 + child2: + age: 3 + max_free_entitlement_hours_used: 15 + benunits: + benunit1: + members: [child1, child2] + extended_childcare_entitlement_eligible: true + output: + extended_childcare_entitlement: 6705.43 # (10 hours * 38 weeks * £8.58 per hour) + (15 hours * 38 weeks * £6.07 per hour) for 2025 rates \ No newline at end of file diff --git a/policyengine_uk/tests/policy/baseline/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement.yaml b/policyengine_uk/tests/policy/baseline/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement.yaml new file mode 100644 index 000000000..e22dc843b --- /dev/null +++ b/policyengine_uk/tests/policy/baseline/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement.yaml @@ -0,0 +1,80 @@ +- name: Child under 2 (ineligible) + period: 2024 + input: + people: + child: + age: 1 + benunits: + benunit: + members: [child] + targeted_childcare_entitlement_eligible: False + output: + targeted_childcare_entitlement: 0.0 + +- name: Child aged 2 (eligible) + period: 2024 + input: + people: + child: + age: 2 + benunits: + benunit: + members: [child] + targeted_childcare_entitlement_eligible: True + output: + targeted_childcare_entitlement: 4719.60 # 15 hours * 38 weeks * £8.28 per hour + +- name: Child aged 3 (not eligible by age, but has targeting) + period: 2024 + input: + people: + child: + age: 3 + benunits: + benunit: + members: [child] + targeted_childcare_entitlement_eligible: True + output: + targeted_childcare_entitlement: 0.0 # Not eligible by age even if targeting criteria met + +- name: Child using fewer hours than maximum entitlement + period: 2024 + input: + people: + child: + age: 2 + max_free_entitlement_hours_used: 10 + benunits: + benunit: + members: [child] + targeted_childcare_entitlement_eligible: True + output: + targeted_childcare_entitlement: 3146.4 # 10 hours * 38 weeks * £8.28 per hour + +- name: Child using exactly maximum entitlement + period: 2024 + input: + people: + child: + age: 2 + max_free_entitlement_hours_used: 15 + benunits: + benunit: + members: [child] + targeted_childcare_entitlement_eligible: True + output: + targeted_childcare_entitlement: 4719.6 # 15 hours * 38 weeks * £8.28 per hour + +- name: Child using more than maximum entitlement (capped) + period: 2024 + input: + people: + child: + age: 2 + max_free_entitlement_hours_used: 20 + benunits: + benunit: + members: [child] + targeted_childcare_entitlement_eligible: True + output: + targeted_childcare_entitlement: 4719.6 # Capped at 15 hours * 38 weeks * £8.28 per hour \ No newline at end of file diff --git a/policyengine_uk/tests/policy/baseline/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement.yaml b/policyengine_uk/tests/policy/baseline/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement.yaml index 6dcc8c55e..9d70b3959 100644 --- a/policyengine_uk/tests/policy/baseline/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement.yaml @@ -1,63 +1,123 @@ - name: Child under 3 isn't eligible (person-level) period: 2024 input: - age: 2 - universal_childcare_entitlement_eligible: False + people: + child: + age: 2 + universal_childcare_entitlement_eligible: False output: universal_childcare_entitlement: 0.0 - name: Child aged 3 is eligible (person-level) period: 2024 input: - age: 3 - universal_childcare_entitlement_eligible: True + people: + child: + age: 3 + universal_childcare_entitlement_eligible: True output: universal_childcare_entitlement: 3351.60 - name: Child aged 4 is eligible (person-level) period: 2024 input: - age: 4 - universal_childcare_entitlement_eligible: True + people: + child: + age: 4 + universal_childcare_entitlement_eligible: True output: universal_childcare_entitlement: 3351.60 - name: Parent (ineligible) period: 2024 input: - age: 35 - universal_childcare_entitlement_eligible: False + people: + parent: + age: 35 + universal_childcare_entitlement_eligible: False output: universal_childcare_entitlement: 0.0 - name: Child aged 2 (ineligible) period: 2024 input: - age: 2 - universal_childcare_entitlement_eligible: False + people: + child: + age: 2 + universal_childcare_entitlement_eligible: False output: universal_childcare_entitlement: 0.0 - name: Child aged 3 (eligible) period: 2024 input: - age: 3 - universal_childcare_entitlement_eligible: True + people: + child: + age: 3 + universal_childcare_entitlement_eligible: True output: universal_childcare_entitlement: 3351.60 - name: Child aged 4 (eligible) period: 2024 input: - age: 4 - universal_childcare_entitlement_eligible: True + people: + child: + age: 4 + universal_childcare_entitlement_eligible: True output: universal_childcare_entitlement: 3351.60 - name: Child aged 5 (ineligible) period: 2024 input: - age: 5 - universal_childcare_entitlement_eligible: False + people: + child: + age: 5 + universal_childcare_entitlement_eligible: False output: - universal_childcare_entitlement: 0.0 \ No newline at end of file + universal_childcare_entitlement: 0.0 + +- name: Child using fewer hours than maximum entitlement + period: 2024 + input: + people: + child: + age: 3 + universal_childcare_entitlement_eligible: True + max_free_entitlement_hours_used: 10 + output: + universal_childcare_entitlement: 2234.4 # 10 hours * 38 weeks * £5.88 per hour + +- name: Child using half of maximum entitlement + period: 2024 + input: + people: + child: + age: 3 + universal_childcare_entitlement_eligible: True + max_free_entitlement_hours_used: 15 + output: + universal_childcare_entitlement: 3351.6 # 15 hours * 38 weeks * £5.88 per hour + +- name: Child using exactly maximum entitlement + period: 2024 + input: + people: + child: + age: 4 + universal_childcare_entitlement_eligible: True + max_free_entitlement_hours_used: 15 + output: + universal_childcare_entitlement: 3351.6 # 15 hours * 38 weeks * £5.88 per hour + +- name: Child using more than maximum entitlement (capped) + period: 2024 + input: + people: + child: + age: 3 + universal_childcare_entitlement_eligible: True + max_free_entitlement_hours_used: 20 + output: + universal_childcare_entitlement: 3351.6 # Capped at 15 hours * 38 weeks * £5.88 per hour \ No newline at end of file From 76ad70242379e8dc5292e54d3862f1aeedf4204e Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Tue, 15 Apr 2025 12:43:18 +0100 Subject: [PATCH 39/39] Edit unit tests --- .../targeted_childcare_entitlement.yaml | 8 ++++---- .../universal_childcare_entitlement.yaml | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/policyengine_uk/tests/policy/baseline/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement.yaml b/policyengine_uk/tests/policy/baseline/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement.yaml index e22dc843b..cdf663efd 100644 --- a/policyengine_uk/tests/policy/baseline/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement.yaml @@ -22,7 +22,7 @@ members: [child] targeted_childcare_entitlement_eligible: True output: - targeted_childcare_entitlement: 4719.60 # 15 hours * 38 weeks * £8.28 per hour + targeted_childcare_entitlement: 4_719.60 # 15 hours * 38 weeks * £8.28 per hour - name: Child aged 3 (not eligible by age, but has targeting) period: 2024 @@ -49,7 +49,7 @@ members: [child] targeted_childcare_entitlement_eligible: True output: - targeted_childcare_entitlement: 3146.4 # 10 hours * 38 weeks * £8.28 per hour + targeted_childcare_entitlement: 3_146.4 # 10 hours * 38 weeks * £8.28 per hour - name: Child using exactly maximum entitlement period: 2024 @@ -63,7 +63,7 @@ members: [child] targeted_childcare_entitlement_eligible: True output: - targeted_childcare_entitlement: 4719.6 # 15 hours * 38 weeks * £8.28 per hour + targeted_childcare_entitlement: 4_719.6 # 15 hours * 38 weeks * £8.28 per hour - name: Child using more than maximum entitlement (capped) period: 2024 @@ -77,4 +77,4 @@ members: [child] targeted_childcare_entitlement_eligible: True output: - targeted_childcare_entitlement: 4719.6 # Capped at 15 hours * 38 weeks * £8.28 per hour \ No newline at end of file + targeted_childcare_entitlement: 4_719.6 # Capped at 15 hours * 38 weeks * £8.28 per hour \ No newline at end of file diff --git a/policyengine_uk/tests/policy/baseline/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement.yaml b/policyengine_uk/tests/policy/baseline/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement.yaml index 9d70b3959..9176525d1 100644 --- a/policyengine_uk/tests/policy/baseline/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/dfe/universal_childcare_entitlement/universal_childcare_entitlement.yaml @@ -16,7 +16,7 @@ age: 3 universal_childcare_entitlement_eligible: True output: - universal_childcare_entitlement: 3351.60 + universal_childcare_entitlement: 3_351.60 - name: Child aged 4 is eligible (person-level) period: 2024 @@ -26,7 +26,7 @@ age: 4 universal_childcare_entitlement_eligible: True output: - universal_childcare_entitlement: 3351.60 + universal_childcare_entitlement: 3_351.60 - name: Parent (ineligible) period: 2024 @@ -56,7 +56,7 @@ age: 3 universal_childcare_entitlement_eligible: True output: - universal_childcare_entitlement: 3351.60 + universal_childcare_entitlement: 3_351.60 - name: Child aged 4 (eligible) period: 2024 @@ -66,7 +66,7 @@ age: 4 universal_childcare_entitlement_eligible: True output: - universal_childcare_entitlement: 3351.60 + universal_childcare_entitlement: 3_351.60 - name: Child aged 5 (ineligible) period: 2024 @@ -87,7 +87,7 @@ universal_childcare_entitlement_eligible: True max_free_entitlement_hours_used: 10 output: - universal_childcare_entitlement: 2234.4 # 10 hours * 38 weeks * £5.88 per hour + universal_childcare_entitlement: 2_234.4 # 10 hours * 38 weeks * £5.88 per hour - name: Child using half of maximum entitlement period: 2024 @@ -98,7 +98,7 @@ universal_childcare_entitlement_eligible: True max_free_entitlement_hours_used: 15 output: - universal_childcare_entitlement: 3351.6 # 15 hours * 38 weeks * £5.88 per hour + universal_childcare_entitlement: 3_351.6 # 15 hours * 38 weeks * £5.88 per hour - name: Child using exactly maximum entitlement period: 2024 @@ -109,7 +109,7 @@ universal_childcare_entitlement_eligible: True max_free_entitlement_hours_used: 15 output: - universal_childcare_entitlement: 3351.6 # 15 hours * 38 weeks * £5.88 per hour + universal_childcare_entitlement: 3_351.6 # 15 hours * 38 weeks * £5.88 per hour - name: Child using more than maximum entitlement (capped) period: 2024 @@ -120,4 +120,4 @@ universal_childcare_entitlement_eligible: True max_free_entitlement_hours_used: 20 output: - universal_childcare_entitlement: 3351.6 # Capped at 15 hours * 38 weeks * £5.88 per hour \ No newline at end of file + universal_childcare_entitlement: 3_351.6 # Capped at 15 hours * 38 weeks * £5.88 per hour \ No newline at end of file