Skip to content

Commit 1de513d

Browse files
vahid-ahmadiPolicyEngine-Botclaude
authored
Fix basic state pension calculation (#1208)
* fix basic state pension calculation * fix basic state pension calculation * Merge branch 'fix-state-pension-calculation' of https://github.com/policyengine/policyengine-uk into fix-state-pension-calculation * format * debug * debug * debug * Fix basic state pension calculation to work without datasets - Allow basic_state_pension to calculate without a dataset by using the current period when no dataset is present - Keep correct behavior: return 0 for non-BASIC pension types - Only apply triple lock uprating when using dataset data - Use correct indices.triple_lock (cumulative index) not yoy_growth - Fix test expectations for non-BASIC types (should return 0) Fixes #1090 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: policyengine-bot <bot@policyengine.org> Co-authored-by: Claude <noreply@anthropic.com>
1 parent cb6afe8 commit 1de513d

4 files changed

Lines changed: 76 additions & 12 deletions

File tree

.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ policyengine_uk/calibration/*.h5
5656
!docs/**/*.ipynb
5757
!uprating_growth_factors.csv
5858

59-
# Virtual environments
59+
# Virtual environments
6060
.venv/
6161
venv/
6262
env/
@@ -82,4 +82,4 @@ coverage.xml
8282
cover/
8383

8484
# Docs
85-
**/_build/
85+
**/_build/

changelog_entry.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- bump: patch
2+
changes:
3+
fixed:
4+
- Basic state pension calculation.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
- name: Basic state pension calculation with normal parameters
2+
period: 2021
3+
input:
4+
people:
5+
person1:
6+
state_pension_reported: 5000
7+
state_pension_type: BASIC
8+
age: 70
9+
output:
10+
basic_state_pension: 5000 # Reported amount (under maximum)
11+
12+
- name: Basic state pension caps at maximum when reported exceeds maximum
13+
period: 2021
14+
input:
15+
people:
16+
person1:
17+
state_pension_reported: 10000 # Higher than maximum
18+
state_pension_type: BASIC
19+
age: 70
20+
output:
21+
basic_state_pension: 7155.2 # Capped at maximum (137.60 * 52)
22+
23+
- name: Non-basic state pension type returns zero for basic_state_pension
24+
period: 2021
25+
input:
26+
people:
27+
person1:
28+
state_pension_reported: 5000
29+
state_pension_type: NEW # Not basic pension
30+
age: 70
31+
output:
32+
basic_state_pension: 0 # basic_state_pension is only for BASIC type
33+
34+
- name: Basic state pension should be zero when maximum is zero
35+
period: 2021
36+
input:
37+
gov.dwp.state_pension.basic_state_pension.amount: 0
38+
people:
39+
person1:
40+
state_pension_reported: 5000
41+
state_pension_type: BASIC
42+
age: 70
43+
output:
44+
basic_state_pension: 0

policyengine_uk/variables/gov/dwp/basic_state_pension.py

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,38 @@ class basic_state_pension(Variable):
1010

1111
def formula(person, period, parameters):
1212
simulation = person.simulation
13-
if simulation.dataset is None:
14-
return 0
15-
try:
16-
data_year = min(simulation.dataset.years)
17-
except:
13+
has_dataset = simulation.dataset is not None
14+
15+
# Determine the data year: from dataset if available, otherwise current
16+
if has_dataset:
17+
try:
18+
data_year = min(simulation.dataset.years)
19+
except:
20+
data_year = period.start.year
21+
else:
1822
data_year = period.start.year
23+
1924
reported = person("state_pension_reported", data_year) / WEEKS_IN_YEAR
20-
type = person("state_pension_type", period)
25+
pension_type = person("state_pension_type", period)
2126
maximum_basic_sp = parameters(
2227
data_year
2328
).gov.dwp.state_pension.basic_state_pension.amount
29+
30+
# For BASIC pension type, cap at the maximum; otherwise return 0
2431
amount_in_data_year = where(
25-
type == type.possible_values.BASIC,
32+
pension_type == pension_type.possible_values.BASIC,
2633
min_(reported, maximum_basic_sp),
2734
0,
2835
)
29-
triple_lock = parameters.gov.economic_assumptions.indices.triple_lock
30-
uprating_since_data_year = triple_lock(period) / triple_lock(data_year)
31-
return amount_in_data_year * uprating_since_data_year * WEEKS_IN_YEAR
36+
37+
# Apply triple lock uprating only when using dataset
38+
# (i.e., when data year differs from simulation period)
39+
if has_dataset:
40+
triple_lock = (
41+
parameters.gov.economic_assumptions.indices.triple_lock
42+
)
43+
uprating = triple_lock(period) / triple_lock(data_year)
44+
else:
45+
uprating = 1
46+
47+
return amount_in_data_year * uprating * WEEKS_IN_YEAR

0 commit comments

Comments
 (0)