Functional Weave
Code in Rust

insurance.excess-apply@1.0.1

impl/rust.rs

2,951 bytes · the Rust 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.

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::money_amount::{assert_same_currency, money, money_from_value, money_to_value, Money};  ← from money.amount ^1.0.0 · built alongside by fune

/// The claim payout after the excess, capped at the policy limit.
///
/// The excess is the compulsory and voluntary excess together, and a loss
/// smaller than it pays nothing. By default the limit caps what is paid after
/// the excess; with `excess_within_limit` the excess is taken off the loss
/// after the limit, so it erodes the limit.
///
/// # Panics
/// Panics on mixed currencies or a negative amount.
pub fn apply_excess(
    loss: &Money,
    compulsory_excess: &Money,
    voluntary_excess: &Money,
    policy_limit: Option<&Money>,
    excess_within_limit: bool,
) -> ExcessSettlement {
    assert_same_currency(loss, compulsory_excess);
    assert_same_currency(loss, voluntary_excess);
    if let Some(limit) = policy_limit {
        assert_same_currency(loss, limit);
    }
    if loss.minor < 0 {
        panic!("loss must not be negative, received {}", loss.minor);
    }
    if compulsory_excess.minor < 0 || voluntary_excess.minor < 0 {
        panic!("excess must not be negative");
    }
    if let Some(limit) = policy_limit {
        if limit.minor < 0 {
            panic!("policyLimit must not be negative, received {}", limit.minor);
        }
    }
    let excess = compulsory_excess.minor + voluntary_excess.minor;
    let mut limit_applied = false;
    let payout = if excess_within_limit {
        let mut covered = loss.minor;
        if let Some(limit) = policy_limit {
            if limit.minor < covered {
                covered = limit.minor;
                limit_applied = true;
            }
        }
        (covered - excess).max(0)
    } else {
        let mut p = (loss.minor - excess).max(0);
        if let Some(limit) = policy_limit {
            if limit.minor < p {
                p = limit.minor;
                limit_applied = true;
            }
        }
        p
    };
    let c = &loss.currency;
    ExcessSettlement {
        total_excess: money(excess, c),
        excess_applied: money(excess.min(loss.minor), c),
        payout: money(payout, c),
        limit_applied,
        uninsured: money(loss.minor - payout, c),
    }
}

pub fn excess_settlement_to_value(s: &ExcessSettlement) -> Value {
    Value::obj(vec![
        ("totalExcess", money_to_value(&s.total_excess)),
        ("excessApplied", money_to_value(&s.excess_applied)),
        ("payout", money_to_value(&s.payout)),
        ("limitApplied", Value::Bool(s.limit_applied)),
        ("uninsured", money_to_value(&s.uninsured)),
    ])
}

pub fn fune_vector(args: &[Value]) -> Value {
    let limit = if args[3].is_null() { None } else { Some(money_from_value(&args[3])) };
    excess_settlement_to_value(&apply_excess(
        &money_from_value(&args[0]),
        &money_from_value(&args[1]),
        &money_from_value(&args[2]),
        limit.as_ref(),
        args[4].as_bool(),
    ))
}