Functional Weave
Code in TypeScript

finance.tax.vat-rate@1.2.2

impl/rust.rs

4,806 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::finance_tax_vat_rate_data::{VAT_RULES, VAT_RULES_HISTORY};  ← this capability’s own data, compiled from data/vat-rules.json into the same file by fune build

fn is_iso_date(value: &str) -> bool {
    let bytes = value.as_bytes();
    bytes.len() == 10
        && bytes[4] == b'-'
        && bytes[7] == b'-'
        && bytes
            .iter()
            .enumerate()
            .all(|(i, b)| i == 4 || i == 7 || b.is_ascii_digit())
}

/// The VAT rate in force for a jurisdiction and category on a given date.
///
/// The date matters. A credit note against a 2009 invoice has to use the rate
/// that applied in 2009, not the one that applies today, and a system that
/// hardcodes 0.20 cannot do that at all.
///
/// ISO dates compare correctly as strings, so this needs no date crate.
///
/// # Panics
/// Panics if the date is malformed, or no rule covers the request.
pub fn vat_rate(jurisdiction: &str, category: &str, on_date: &str) -> VatRate {
    if !is_iso_date(on_date) {
        panic!(
            "onDate must be an ISO date (YYYY-MM-DD), received \"{}\"",
            on_date
        );
    }

    let mut best: Option<VatRate> = None;
    for rule in VAT_RULES {
        if rule.jurisdiction != jurisdiction || rule.category != category {
            continue;
        }
        if on_date < rule.valid_from {
            continue;
        }
        if let Some(valid_to) = rule.valid_to {
            if on_date > valid_to {
                continue;
            }
        }
        let better = match &best {
            None => true,
            Some(current) => rule.valid_from > current.valid_from.as_str(),
        };
        if better {
            best = Some(VatRate {
                jurisdiction: rule.jurisdiction.to_string(),
                category: rule.category.to_string(),
                basis_points: rule.basis_points,
                valid_from: rule.valid_from.to_string(),
                valid_to: rule.valid_to.map(str::to_string),
            });
        }
    }

    match best {
        Some(rate) => rate,
        None => {
            // A build installed with history=current carries only the rules
            // still in force. Answering an older date with today's rate would
            // be the exact failure this capability exists to prevent, so say
            // what happened instead. The horizon that matters is this
            // jurisdiction and category's own earliest surviving rule, not the
            // registry-wide one.
            if VAT_RULES_HISTORY != "full" {
                let mut earliest: Option<&'static str> = None;
                for rule in VAT_RULES {
                    if rule.jurisdiction != jurisdiction || rule.category != category {
                        continue;
                    }
                    if earliest.is_none() || rule.valid_from < earliest.unwrap() {
                        earliest = Some(rule.valid_from);
                    }
                }
                if let Some(earliest) = earliest {
                    if on_date < earliest {
                        panic!(
                            "no VAT rule for {}/{} on {}: this build was installed with history={}, so it only carries rules from {}. Reinstall with history=full to reprint older invoices.",
                            jurisdiction, category, on_date, VAT_RULES_HISTORY, earliest
                        );
                    }
                }
            }
            panic!(
                "no VAT rule for {}/{} on {}",
                jurisdiction, category, on_date
            )
        }
    }
}

/// Every category this registry knows a rate for, for a jurisdiction and date.
pub fn vat_categories(jurisdiction: &str, on_date: &str) -> Vec<&'static str> {
    let mut seen: Vec<&'static str> = Vec::new();
    for rule in VAT_RULES {
        if rule.jurisdiction != jurisdiction || on_date < rule.valid_from {
            continue;
        }
        if let Some(valid_to) = rule.valid_to {
            if on_date > valid_to {
                continue;
            }
        }
        if !seen.contains(&rule.category) {
            seen.push(rule.category);
        }
    }
    seen.sort_unstable();
    seen
}

pub fn vat_rate_to_value(rate: &VatRate) -> Value {
    Value::obj(vec![
        ("jurisdiction", Value::str(&rate.jurisdiction)),
        ("category", Value::str(&rate.category)),
        ("basisPoints", Value::Int(rate.basis_points)),
        ("validFrom", Value::str(&rate.valid_from)),
        (
            "validTo",
            match &rate.valid_to {
                Some(date) => Value::str(date),
                None => Value::Null,
            },
        ),
    ])
}

pub fn fune_vector(args: &[Value]) -> Value {
    vat_rate_to_value(&vat_rate(
        args[0].as_str(),
        args[1].as_str(),
        args[2].as_str(),
    ))
}