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, parse_iso_date}; ← from dates.add-days ^1.0.0 · built alongside by fune
use super::dates_recurrence::{recurrence, RecurrenceRule}; ← from dates.recurrence ^1.0.0 · built alongside by fune
/// Collection dates for a regular gift. Each date is clamped from the chosen
/// day, not from the previous date (dates.recurrence), so a gift on the 31st
/// is taken on 28 February and on 31 March again.
///
/// # Panics
/// Panics on an unknown frequency, a day outside 1-31, negative lead days or
/// count, or a malformed date.
pub fn regular_giving_schedule(
frequency: &str,
collection_day: i64,
sign_up_date: &str,
lead_days: i64,
end_date: Option<&str>,
count: i64,
) -> Vec<String> {
let interval = match frequency {
"monthly" => 1,
"quarterly" => 3,
"annually" => 12,
_ => panic!("unknown giving frequency \"{}\": expected monthly, quarterly or annually", frequency),
};
if !(1..=31).contains(&collection_day) {
panic!("collectionDay must be 1-31, received {}", collection_day);
}
if lead_days < 0 {
panic!("leadDays must not be negative, received {}", lead_days);
}
if count < 0 {
panic!("count must be a non-negative integer, received {}", count);
}
if let Some(end) = end_date {
parse_iso_date(end);
}
let first = add_days(sign_up_date, lead_days);
if let Some(end) = end_date {
if end < first.as_str() {
return Vec::new();
}
}
let rule = RecurrenceRule {
kind: "monthly-on-day".to_string(),
interval,
day: Some(collection_day),
weekday: None,
};
recurrence(&rule, &first, count)
.into_iter()
.filter(|d| end_date.map_or(true, |end| d.as_str() <= end))
.collect()
}
fn int_arg(v: &Value, name: &str, message: &str) -> i64 {
if let Value::Float(f) = v {
if f.fract() != 0.0 {
panic!("{} {}, received {}", name, message, f);
}
}
v.as_i64()
}
pub fn fune_vector(args: &[Value]) -> Value {
let day = int_arg(&args[1], "collectionDay", "must be 1-31");
let lead = int_arg(&args[3], "leadDays", "must not be negative");
let count = int_arg(&args[5], "count", "must be a non-negative integer");
let end = if args[4].is_null() { None } else { Some(args[4].as_str()) };
let dates = regular_giving_schedule(args[0].as_str(), day, args[2].as_str(), lead, end, count);
Value::Arr(dates.iter().map(|d| Value::str(d)).collect())
}