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_days_between::days_between; ← from dates.days-between ^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_add::add_money; ← from money.add ^1.0.0 · built alongside by fune
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
/// Stripe-style proration for a mid-cycle plan change, by whole days: a credit
/// for the unused remainder of the old plan and a charge for the same
/// remainder on the new plan, each rounded once from the exact fraction.
///
/// # Panics
/// Panics if the period is empty or reversed, the change date is outside it,
/// the prices are in different currencies, or the mode is unknown.
pub fn prorate_change(
old_price: &Money,
new_price: &Money,
period_start: &str,
period_end: &str,
change_date: &str,
mode: &str,
) -> PlanChangeProration {
let total_days = days_between(period_start, period_end);
if total_days <= 0 {
panic!(
"period end must be after period start, received {} to {}",
period_start, period_end
);
}
let elapsed = days_between(period_start, change_date);
if elapsed < 0 || elapsed > total_days {
panic!(
"change date must be within the billing period, received {} for {} to {}",
change_date, period_start, period_end
);
}
assert_same_currency(old_price, new_price);
let remaining_days = total_days - elapsed;
let credit = money(
-round_div(old_price.minor * remaining_days, total_days, mode),
&old_price.currency,
);
let charge = money(
round_div(new_price.minor * remaining_days, total_days, mode),
&new_price.currency,
);
let net = add_money(&charge, &credit);
PlanChangeProration {
total_days,
remaining_days,
credit,
charge,
net,
}
}
pub fn plan_change_proration_to_value(p: &PlanChangeProration) -> Value {
Value::obj(vec![
("totalDays", Value::Int(p.total_days)),
("remainingDays", Value::Int(p.remaining_days)),
("credit", money_to_value(&p.credit)),
("charge", money_to_value(&p.charge)),
("net", money_to_value(&p.net)),
])
}
pub fn fune_vector(args: &[Value]) -> Value {
plan_change_proration_to_value(&prorate_change(
&money_from_value(&args[0]),
&money_from_value(&args[1]),
args[2].as_str(),
args[3].as_str(),
args[4].as_str(),
args[5].as_str(),
))
}