use super::funejson::Value; /// 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 = 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]))) }