Apparent error in oncost calculation
This came about from me trying to understand by matching a simple result with HR's online calculator. To repeat run the salaries-commitments
container:
cd $DEVOPS_HOME/research-dashboard/salaries-commitments
docker-compose run commitments python3
Then using HR's online calculator select:
- Scheme: USS (exchange)
- Period: 1st August 2019
- Grades: Grade 8
.. and select the Salary, NIC, and Total for Scale point 052 (you will see these value are plugged in below). Then run the following in the console:
import ucamstaffoncosts
import salaries
from datetime import date
# target oncost etc retrieved from HR's online calculator
uss_exchange_grade_8_point_52_salary=45361
uss_exchange_grade_8_point_52_nic=4518
uss_exchange_grade_8_point_52_oncost=58930
# we calculate for a small time period (31 days) to avoid going into a different table
start=date(2019, 8, 1)
until=date(2019, 9, 1)
proportion_of_year=(until - start).days / 365
# note that NIC won't kick in for this small period (31 days)
print(f'Expected oncosts: {(uss_exchange_grade_8_point_52_oncost - uss_exchange_grade_8_point_52_nic) * proportion_of_year}')
grade, point, table = salaries.grade_and_point_for_staff_member(
{'GRADE': 'Grade 8', 'POINT_VALUE_FTE': uss_exchange_grade_8_point_52_salary}
)
_, commitment, explanations = ucamstaffoncosts.employment_expenditure_and_commitments(
start_date=start,
from_date=start,
until_date=until,
next_anniversary_date=until,
initial_grade=grade,
initial_point=point,
occupancy=1,
scheme=ucamstaffoncosts.Scheme.USS_EXCHANGE,
scale_table=table,
)
print(f'Actual oncosts: {commitment}')
You will see that the values differ by about £13. If we look at the explanations
we will see that this is due mainly to the salary:
print(f'Expected salary: {uss_exchange_grade_8_point_52_salary * proportion_of_year}')
from ucamstaffoncosts.util import pprinttable
def print_explanations(explanations, from_date):
running_commitment = 0
for explanation in explanations:
print('=' * 60)
print('TAX YEAR: {}/{}'.format(explanation.tax_year, explanation.tax_year+1))
print('\nSalaries\n--------\n')
pprinttable(explanation.salaries)
print('\nCosts\n-----')
if explanation.cost.tax_year != explanation.tax_year:
print('(approximated using tax tables for {})'.format(explanation.cost.tax_year))
print('\n')
pprinttable([explanation.cost])
print('\nSalary for year: {}'.format(explanation.salary))
print('Salary earned after {}: {}'.format(from_date, explanation.salary_to_come))
print('Expenditure until {}: {}'.format(from_date, explanation.expenditure))
print('Commitment from {}: {}'.format(from_date, explanation.commitment))
running_commitment += explanation.commitment
print('Running total commitment: {}'.format(running_commitment))
print('\n')
print_explanations(explanations, start)
This shows a £10 difference (assumption: the remain £3 comes from amplification of the original error)