use super::funejson::Value; use super::legal_court_fee_data::{ISSUE_FEES, ISSUE_FEES_HISTORY}; use super::money_amount::{money, money_from_value, money_to_value, Money}; use super::money_apply_rate::apply_rate; fn is_iso_date(s: &str) -> bool { let b = s.as_bytes(); b.len() == 10 && b.iter().enumerate().all(|(i, c)| if i == 4 || i == 7 { *c == b'-' } else { c.is_ascii_digit() }) } /// The fee to issue a money claim, from the bands in force on the issue date. /// /// # Panics /// Panics on a non-GBP or non-positive claim, an unknown channel, a bad date, /// a date before the data, or an online claim over GBP 100,000. pub fn court_fee(claim: &Money, channel: &str, on_date: &str) -> Money { if claim.currency != "GBP" { panic!("court fees are set for claims in GBP, received {}", claim.currency); } if claim.minor <= 0 { panic!("claim must be greater than zero"); } if channel != "paper" && channel != "online" { panic!("unknown filing channel \"{}\": expected paper or online", channel); } if !is_iso_date(on_date) { panic!("onDate must be an ISO date (YYYY-MM-DD), received \"{}\"", on_date); } let mut in_force = 0; let mut earliest: Option<&str> = None; for row in ISSUE_FEES { if row.channel != channel { continue; } if earliest.map_or(true, |e| row.valid_from < e) { earliest = Some(row.valid_from); } if on_date < row.valid_from || row.valid_to.map_or(false, |to| on_date > to) { continue; } in_force += 1; if claim.minor <= row.over_minor || row.up_to_minor.map_or(false, |up| claim.minor > up) { continue; } if let Some(fee) = row.fee_minor { return money(fee, "GBP"); } // gov.uk: "round down the result to the nearest 1 pence". return apply_rate(claim, row.basis_points.unwrap(), "down"); } if in_force > 0 { panic!( "a claim of {} pence cannot be issued {} on {}: online claims are limited to GBP 100,000", claim.minor, channel, on_date ); } if let Some(e) = earliest { if ISSUE_FEES_HISTORY != "full" && on_date < e { panic!( "no {} court fee on {}: this build was installed with history={}, so it only carries fees from {}. Reinstall with history=full for older claims.", channel, on_date, ISSUE_FEES_HISTORY, e ); } } panic!("no {} court fee in force on {}", channel, on_date); } pub fn fune_vector(args: &[Value]) -> Value { money_to_value(&court_fee(&money_from_value(&args[0]), args[1].as_str(), args[2].as_str())) }