use super::funejson::Value; use super::dates_add_days::parse_iso_date; use super::dates_add_months::add_months; use super::legal_limitation_date_data::{LIMITATION_PERIODS, LIMITATION_PERIODS_HISTORY}; /// The last day to bring a claim: the anniversary of the accrual date (or the /// later date of knowledge) the period's number of years on, the accrual day /// itself excluded, and the month's last day where no anniversary exists. /// /// # Panics /// Panics on an unknown claim type, a bad date, an accrual date before the /// data, or a knowledge date for a claim type that does not run from knowledge. pub fn limitation_date(claim_type: &str, accrual_date: &str, knowledge_date: Option<&str>) -> LimitationPeriod { parse_iso_date(accrual_date); let rows: Vec<_> = LIMITATION_PERIODS.iter().filter(|r| r.claim_type == claim_type).collect(); if rows.is_empty() { let mut known: Vec<&str> = Vec::new(); for r in LIMITATION_PERIODS { if !known.contains(&r.claim_type) { known.push(r.claim_type); } } panic!("unknown claim type \"{}\": expected one of {}", claim_type, known.join(", ")); } let rule = match rows .iter() .find(|r| accrual_date >= r.valid_from && r.valid_to.map_or(true, |to| accrual_date <= to)) { Some(r) => *r, None => { let earliest = rows.iter().map(|r| r.valid_from).min().unwrap(); if LIMITATION_PERIODS_HISTORY != "full" && accrual_date < earliest { panic!( "no limitation rule for {} accruing on {}: this build was installed with history={}, so it only carries rules from {}. Reinstall with history=full for older claims.", claim_type, accrual_date, LIMITATION_PERIODS_HISTORY, earliest ); } panic!("no limitation rule for {} accruing on {}", claim_type, accrual_date); } }; let mut runs_from = accrual_date; if let Some(knowledge) = knowledge_date { if !rule.from_knowledge { panic!("a {} claim runs from accrual under {}; knowledgeDate must be null", claim_type, rule.section); } parse_iso_date(knowledge); if knowledge > accrual_date { runs_from = knowledge; } } // The corresponding date rule: the anniversary, clamped to the month end. let expiry = add_months(runs_from, rule.years * 12); LimitationPeriod { claim_type: claim_type.to_string(), years: rule.years, section: rule.section.to_string(), runs_from: runs_from.to_string(), expiry, } } pub fn limitation_period_to_value(p: &LimitationPeriod) -> Value { Value::obj(vec![ ("claimType", Value::str(&p.claim_type)), ("years", Value::Int(p.years)), ("section", Value::str(&p.section)), ("runsFrom", Value::str(&p.runs_from)), ("expiry", Value::str(&p.expiry)), ]) } pub fn fune_vector(args: &[Value]) -> Value { let knowledge = if args[2].is_null() { None } else { Some(args[2].as_str()) }; limitation_period_to_value(&limitation_date(args[0].as_str(), args[1].as_str(), knowledge)) }