Functional Weave
Code in Python

payroll.redundancy-pay@1.0.1

impl/python.py

2,483 bytes · the Python implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

from .dates_add_days import add_days  ← from dates.add-days ^1.0.0 · built alongside by fune
from .dates_add_months import add_months  ← from dates.add-months ^1.0.0 · built alongside by fune
from .dates_age import age  ← from dates.age ^1.0.0 · built alongside by fune
from .hr_length_of_service import length_of_service  ← from hr.length-of-service ^1.0.0 · built alongside by fune
from .math_round_div import round_div  ← from math.round-div ^1.0.0 · built alongside by fune
from .money_amount import Money, money  ← from money.amount ^1.0.0 · built alongside by fune
from .payroll_redundancy_pay_data import WEEK_PAY_CAPS, WEEK_PAY_CAPS_HISTORY  ← this capability’s own data, compiled from data/week-pay-caps.json into the same file by fune build
from .payroll_redundancy_pay_types import RedundancyPay


def _week_pay_cap(relevant_date: str) -> int:
    for row in WEEK_PAY_CAPS:
        if relevant_date >= row.valid_from and (row.valid_to is None or relevant_date <= row.valid_to):
            return row.cap_minor
    if WEEK_PAY_CAPS_HISTORY != "full":
        earliest = min((row.valid_from for row in WEEK_PAY_CAPS), default=None)
        if earliest is not None and relevant_date < earliest:
            raise ValueError(
                "no statutory week's pay cap for %s: this build was installed with history=%s, "
                "so it only carries caps from %s. Reinstall with history=full for older dismissals."
                % (relevant_date, WEEK_PAY_CAPS_HISTORY, earliest)
            )
    raise ValueError("no statutory week's pay cap for %s" % (relevant_date,))


def statutory_redundancy_pay(birth_date: str, start_date: str, relevant_date: str, weekly_pay: Money) -> RedundancyPay:
    """ERA 1996 s.162 redundancy pay. Years are reckoned backwards from the
    relevant date and each is priced by the age on its first day, so the rate
    steps up only for years spent wholly at 22 or 41 and over.
    """
    if weekly_pay.minor < 0:
        raise ValueError("weeklyPay must not be negative, received %s" % (weekly_pay.minor,))
    cap = _week_pay_cap(relevant_date)
    weekly_pay_used = money(min(weekly_pay.minor, cap), weekly_pay.currency)
    service_years = length_of_service(start_date, relevant_date).years
    eligible = service_years >= 2
    years_counted = min(service_years, 20) if eligible else 0
    half_weeks = 0
    for k in range(1, years_counted + 1):
        first_day = add_days(add_months(relevant_date, -12 * k), 1)
        age_then = age(birth_date, first_day)
        half_weeks += 3 if age_then >= 41 else 2 if age_then >= 22 else 1
    amount = money(round_div(half_weeks * weekly_pay_used.minor, 2, "half-up"), weekly_pay.currency)
    return RedundancyPay(
        eligible=eligible,
        service_years=service_years,
        years_counted=years_counted,
        half_weeks=half_weeks,
        weekly_pay_used=weekly_pay_used,
        amount=amount,
    )