Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
use super::funejson::Value; ← the fune runtime: the JSON value the test vectors use; fune build keeps it only where a signature takes one
use super::dates_add_days::add_days; ← from dates.add-days ^1.0.0 · built alongside by fune
use super::dates_add_months::add_months; ← from dates.add-months ^1.0.0 · built alongside by fune
use super::dates_age::age; ← from dates.age ^1.0.0 · built alongside by fune
use super::hr_length_of_service::length_of_service; ← from hr.length-of-service ^1.0.0 · built alongside by fune
use super::math_round_div::round_div; ← from math.round-div ^1.0.0 · built alongside by fune
use super::money_amount::{money, money_from_value, money_to_value, Money}; ← from money.amount ^1.0.0 · built alongside by fune
use super::payroll_redundancy_pay_data::{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
fn week_pay_cap(relevant_date: &str) -> i64 {
for row in WEEK_PAY_CAPS {
if relevant_date >= row.valid_from && row.valid_to.map_or(true, |to| relevant_date <= to) {
return row.cap_minor;
}
}
if WEEK_PAY_CAPS_HISTORY != "full" {
let earliest = WEEK_PAY_CAPS.iter().map(|r| r.valid_from).min();
if let Some(earliest) = earliest {
if relevant_date < earliest {
panic!(
"no statutory week's pay cap for {}: this build was installed with history={}, so it only carries caps from {}. Reinstall with history=full for older dismissals.",
relevant_date, WEEK_PAY_CAPS_HISTORY, earliest
);
}
}
}
panic!("no statutory week's pay cap for {}", relevant_date)
}
/// 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.
///
/// # Panics
/// Panics on malformed dates, negative pay, or a relevant date with no cap.
pub fn statutory_redundancy_pay(birth_date: &str, start_date: &str, relevant_date: &str, weekly_pay: &Money) -> RedundancyPay {
if weekly_pay.minor < 0 {
panic!("weeklyPay must not be negative, received {}", weekly_pay.minor);
}
let cap = week_pay_cap(relevant_date);
let weekly_pay_used = money(weekly_pay.minor.min(cap), &weekly_pay.currency);
let service_years = length_of_service(start_date, relevant_date).years;
let eligible = service_years >= 2;
let years_counted = if eligible { service_years.min(20) } else { 0 };
let mut half_weeks = 0;
for k in 1..=years_counted {
let first_day = add_days(&add_months(relevant_date, -12 * k), 1);
let age_then = age(birth_date, &first_day);
half_weeks += if age_then >= 41 { 3 } else if age_then >= 22 { 2 } else { 1 };
}
let amount = money(round_div(half_weeks * weekly_pay_used.minor, 2, "half-up"), &weekly_pay.currency);
RedundancyPay { eligible, service_years, years_counted, half_weeks, weekly_pay_used, amount }
}
pub fn fune_vector(args: &[Value]) -> Value {
let r = statutory_redundancy_pay(args[0].as_str(), args[1].as_str(), args[2].as_str(), &money_from_value(&args[3]));
Value::obj(vec![
("eligible", Value::Bool(r.eligible)),
("serviceYears", Value::Int(r.service_years)),
("yearsCounted", Value::Int(r.years_counted)),
("halfWeeks", Value::Int(r.half_weeks)),
("weeklyPayUsed", money_to_value(&r.weekly_pay_used)),
("amount", money_to_value(&r.amount)),
])
}