Functional Weave
Code in Python

legal.disbursements-vat@1.0.0

impl/rust.rs

2,881 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

/// Disbursement (outside the scope of your VAT) or recharge (VAT due), and why.
///
/// The conditions are HMRC VAT Notice 700 section 25.1.1, in HMRC's order; all must be met.
pub fn disbursement_vat(facts: &DisbursementFacts) -> DisbursementTreatment {
    let conditions = [
        ("actedAsAgent", facts.acted_as_agent),
        ("clientReceivedAndUsed", facts.client_received_and_used),
        ("clientResponsibleToPay", facts.client_responsible_to_pay),
        ("clientAuthorisedPayment", facts.client_authorised_payment),
        ("clientKnewThirdParty", facts.client_knew_third_party),
        ("separatelyItemised", facts.separately_itemised),
        ("exactAmountRecovered", facts.exact_amount_recovered),
        ("additionalToOwnSupply", facts.additional_to_own_supply),
    ];
    let failed: Vec<String> = conditions.iter().filter(|(_, met)| !*met).map(|(name, _)| name.to_string()).collect();
    if failed.is_empty() {
        return DisbursementTreatment {
            treatment: "disbursement".to_string(),
            failed_conditions: Vec::new(),
            reason: "all eight conditions of VAT Notice 700 section 25.1.1 are met: pass the cost on at the exact amount, outside the value of your supply, with no VAT added".to_string(),
        };
    }
    let reason = format!(
        "not a disbursement for VAT purposes ({} not met): include the cost in the value of your supply and charge VAT on it at the rate of your main supply",
        failed.join(", ")
    );
    DisbursementTreatment { treatment: "recharge".to_string(), failed_conditions: failed, reason }
}

fn flag(v: &Value, name: &str) -> bool {
    match v.get(name) {
        Value::Bool(b) => *b,
        other => panic!("{} must be true or false, received {:?}", name, other),
    }
}

pub fn disbursement_facts_from_value(v: &Value) -> DisbursementFacts {
    DisbursementFacts {
        acted_as_agent: flag(v, "actedAsAgent"),
        client_received_and_used: flag(v, "clientReceivedAndUsed"),
        client_responsible_to_pay: flag(v, "clientResponsibleToPay"),
        client_authorised_payment: flag(v, "clientAuthorisedPayment"),
        client_knew_third_party: flag(v, "clientKnewThirdParty"),
        separately_itemised: flag(v, "separatelyItemised"),
        exact_amount_recovered: flag(v, "exactAmountRecovered"),
        additional_to_own_supply: flag(v, "additionalToOwnSupply"),
    }
}

pub fn disbursement_treatment_to_value(t: &DisbursementTreatment) -> Value {
    Value::obj(vec![
        ("treatment", Value::str(&t.treatment)),
        ("failedConditions", Value::Arr(t.failed_conditions.iter().map(|s| Value::str(s)).collect())),
        ("reason", Value::str(&t.reason)),
    ])
}

pub fn fune_vector(args: &[Value]) -> Value {
    disbursement_treatment_to_value(&disbursement_vat(&disbursement_facts_from_value(&args[0])))
}