Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

FFT 142 Tests for attrition and uplift #606

Merged
merged 8 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions payroll/tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from faker import Faker

from chartofaccountDIT.test.factories import NaturalCodeFactory, ProgrammeCodeFactory
from core.models import Attrition, PayUplift
from core.test.factories import FinancialYearFactory
from costcentre.test.factories import CostCentreFactory
from gifthospitality.test.factories import GradeFactory
from payroll.models import Employee, PayElementType, PayElementTypeGroup, Vacancy
Expand Down Expand Up @@ -63,3 +65,31 @@ class Meta:
appointee_name = factory.Faker("name")
hiring_manager = factory.Faker("name")
hr_ref = factory.Faker("name")


class PayModifierFactory(factory.django.DjangoModelFactory):
financial_year = factory.SubFactory(FinancialYearFactory)
apr = 1.0
may = 1.0
jun = 1.0
jul = 1.0
aug = 1.0
sep = 1.0
oct = 1.0
nov = 1.0
dec = 1.0
jan = 1.0
feb = 1.0
mar = 1.0


class PayUpliftFactory(PayModifierFactory):
class Meta:
model = PayUplift


class AttritionFactory(PayModifierFactory):
class Meta:
model = Attrition

cost_centre = factory.SubFactory(CostCentreFactory)
180 changes: 127 additions & 53 deletions payroll/tests/services/test_payroll.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import pytest

from core.constants import MONTHS
from core.models import FinancialYear
from costcentre.test.factories import CostCentreFactory
from payroll.services.payroll import (
Expand All @@ -10,31 +11,33 @@
vacancy_created,
)

from ..factories import EmployeeFactory, VacancyFactory
from ..factories import (
AttritionFactory,
EmployeeFactory,
PayUpliftFactory,
VacancyFactory,
)


def test_payroll_forecast(db):
# NOTE: These must match the PAYROLL.BASIC_PAY_NAC and PAYROLL.PENSION_NAC settings.
SALARY_NAC = "71111001"
PENSION_NAC = "71111002"
# NOTE: These must match the PAYROLL.BASIC_PAY_NAC and PAYROLL.PENSION_NAC settings.
SALARY_NAC = "71111001"
PENSION_NAC = "71111002"
NACS = [SALARY_NAC, PENSION_NAC]

cost_centre = CostCentreFactory.create(cost_centre_code="123456")

# salary_1 = PayElementTypeFactory.create(
# name="Salary 1",
# group__name="Salary",
# group__natural_code__natural_account_code=SALARY_NAC,
# )
# salary_2 = PayElementTypeFactory.create(
# name="Salary 2",
# group__name="Salary",
# group__natural_code__natural_account_code=SALARY_NAC,
# )
# pension_1 = PayElementTypeFactory.create(
# name="Pension 1",
# group__name="Pension",
# group__natural_code__natural_account_code=PENSION_NAC,
# )
def assert_report_results_with_modifiers(report, salary, pension, modifiers=None):
if modifiers is None:
modifiers = {}

for nac in NACS:
for month in MONTHS:
modifier = modifiers.get(month, 1)
expected_result = (salary if nac == SALARY_NAC else pension) * modifier
assert float(report[nac][month]) == pytest.approx(expected_result)


def test_payroll_forecast(db):
cost_centre = CostCentreFactory.create(cost_centre_code="123456")

payroll_employee_1 = EmployeeFactory.create(
cost_centre=cost_centre,
Expand Down Expand Up @@ -64,38 +67,6 @@ def test_payroll_forecast(db):
employee_created(payroll_employee_1)
employee_created(payroll_employee_2)

# payroll_employees[0].pay_element.create(
# type=salary_1,
# debit_amount=2000,
# credit_amount=100,
# )
# payroll_employees[0].pay_element.create(
# type=salary_2,
# debit_amount=100,
# credit_amount=50,
# )
# payroll_employees[0].pay_element.create(
# type=pension_1,
# debit_amount=75.5,
# credit_amount=0,
# )

# payroll_employees[1].pay_element.create(
# type=salary_1,
# debit_amount=1500,
# credit_amount=55.6,
# )
# payroll_employees[1].pay_element.create(
# type=salary_2,
# debit_amount=80,
# credit_amount=0,
# )
# payroll_employees[1].pay_element.create(
# type=pension_1,
# debit_amount=130.25,
# credit_amount=15,
# )

vacancy = VacancyFactory.create(
cost_centre=cost_centre,
programme_code__programme_code="123456",
Expand Down Expand Up @@ -136,3 +107,106 @@ def test_payroll_forecast(db):
assert float(report_by_nac[PENSION_NAC]["may"]) == pytest.approx(e1p)
assert float(report_by_nac[SALARY_NAC]["jun"]) == pytest.approx(v1s)
assert float(report_by_nac[PENSION_NAC]["jun"]) == pytest.approx(0)


def test_one_employee_with_no_modifiers(db):
cost_centre = CostCentreFactory.create(cost_centre_code="123456")

payroll_employee_1 = EmployeeFactory.create(
cost_centre=cost_centre,
basic_pay=195000,
pension=7550,
ernic=0,
)

employee_created(payroll_employee_1)

financial_year = FinancialYear.objects.current()

report = payroll_forecast_report(cost_centre, financial_year)

report_by_nac = {x["natural_account_code"]: x for x in report}

e1s = ((2000 - 100) + (100 - 50)) * 100
e1p = (75.5 - 0) * 100

assert_report_results_with_modifiers(report_by_nac, e1s, e1p)


def test_one_employee_with_pay_uplift(db):
cost_centre = CostCentreFactory.create(cost_centre_code="123456")

payroll_employee_1 = EmployeeFactory.create(
cost_centre=cost_centre,
basic_pay=195000,
pension=7550,
ernic=0,
)

employee_created(payroll_employee_1)

financial_year = FinancialYear.objects.current()

pay_uplift = PayUpliftFactory.create(
financial_year=financial_year,
aug=1.02,
)

report = payroll_forecast_report(cost_centre, financial_year)

report_by_nac = {x["natural_account_code"]: x for x in report}

e1s = ((2000 - 100) + (100 - 50)) * 100
e1p = (75.5 - 0) * 100

assert_report_results_with_modifiers(
report_by_nac,
e1s,
e1p,
modifiers={"aug": pay_uplift.aug},
)


def test_one_employee_with_attrition(db):
cost_centre = CostCentreFactory.create(cost_centre_code="123456")

payroll_employee_1 = EmployeeFactory.create(
cost_centre=cost_centre,
basic_pay=195000,
pension=7550,
ernic=0,
)

employee_created(payroll_employee_1)

financial_year = FinancialYear.objects.current()

attrition = AttritionFactory.create(
cost_centre=cost_centre,
financial_year=financial_year,
aug=0.95,
)
modifier = attrition.aug

report = payroll_forecast_report(cost_centre, financial_year)

report_by_nac = {x["natural_account_code"]: x for x in report}

e1s = ((2000 - 100) + (100 - 50)) * 100
e1p = (75.5 - 0) * 100

assert_report_results_with_modifiers(
report_by_nac,
e1s,
e1p,
modifiers={
"aug": modifier,
"sep": modifier,
"oct": modifier,
"nov": modifier,
"dec": modifier,
"jan": modifier,
"feb": modifier,
"mar": modifier,
},
)
Loading