use crate::evaluator::RuntimeError;
use crate::value::Value;
fn get_number(val: &Value) -> Result<f64, RuntimeError> {
match val {
Value::Number(n) => Ok(*n),
_ => Err(RuntimeError::TypeErrorDetailed {
expected: "Number".to_string(),
got: format!("{:?}", val),
}),
}
}
pub fn calc_personal_tax(args: &[Value]) -> Result<Value, RuntimeError> {
if args.is_empty() {
return Err(RuntimeError::WrongArity {
expected: 1,
got: 0,
});
}
let taxable_income = get_number(&args[0])?;
if taxable_income <= 0.0 {
return Ok(Value::Number(0.0));
}
let tax = if taxable_income <= 36000.0 {
taxable_income * 0.03
} else if taxable_income <= 144000.0 {
taxable_income * 0.10 - 2520.0
} else if taxable_income <= 300000.0 {
taxable_income * 0.20 - 16920.0
} else if taxable_income <= 420000.0 {
taxable_income * 0.25 - 31920.0
} else if taxable_income <= 660000.0 {
taxable_income * 0.30 - 52920.0
} else if taxable_income <= 960000.0 {
taxable_income * 0.35 - 85920.0
} else {
taxable_income * 0.45 - 181920.0
};
Ok(Value::Number(tax.max(0.0)))
}
pub fn calc_taxable_income(args: &[Value]) -> Result<Value, RuntimeError> {
if args.len() < 3 {
return Err(RuntimeError::WrongArity {
expected: 3,
got: args.len(),
});
}
let gross_salary = get_number(&args[0])?;
let social_insurance = get_number(&args[1])?;
let housing_fund = get_number(&args[2])?;
let special_deduction = if args.len() > 3 {
get_number(&args[3])?
} else {
0.0
};
let taxable = gross_salary - social_insurance - housing_fund - 5000.0 - special_deduction;
Ok(Value::Number(taxable.max(0.0)))
}
pub fn calc_annual_bonus_tax(args: &[Value]) -> Result<Value, RuntimeError> {
if args.is_empty() {
return Err(RuntimeError::WrongArity {
expected: 1,
got: 0,
});
}
let bonus = get_number(&args[0])?;
if bonus <= 0.0 {
return Ok(Value::Number(0.0));
}
let monthly_avg = bonus / 12.0;
let (rate, deduction) = if monthly_avg <= 3000.0 {
(0.03, 0.0)
} else if monthly_avg <= 12000.0 {
(0.10, 210.0)
} else if monthly_avg <= 25000.0 {
(0.20, 1410.0)
} else if monthly_avg <= 35000.0 {
(0.25, 2660.0)
} else if monthly_avg <= 55000.0 {
(0.30, 4410.0)
} else if monthly_avg <= 80000.0 {
(0.35, 7160.0)
} else {
(0.45, 15160.0)
};
let tax = bonus * rate - deduction;
Ok(Value::Number(tax.max(0.0)))
}
pub fn calc_effective_tax_rate(args: &[Value]) -> Result<Value, RuntimeError> {
if args.len() < 2 {
return Err(RuntimeError::WrongArity {
expected: 2,
got: args.len(),
});
}
let tax = get_number(&args[0])?;
let total_income = get_number(&args[1])?;
if total_income <= 0.0 {
return Err(RuntimeError::InvalidOperation(
"总收入必须大于0".to_string(),
));
}
let rate = (tax / total_income) * 100.0;
Ok(Value::Number(rate))
}
pub fn calc_gross_from_net(args: &[Value]) -> Result<Value, RuntimeError> {
if args.len() < 3 {
return Err(RuntimeError::WrongArity {
expected: 3,
got: args.len(),
});
}
let net_salary = get_number(&args[0])?;
let social_insurance = get_number(&args[1])?;
let housing_fund = get_number(&args[2])?;
let mut gross = net_salary + social_insurance + housing_fund + 1000.0;
for _ in 0..10 {
let taxable = gross - social_insurance - housing_fund - 5000.0;
let tax = if taxable <= 0.0 {
0.0
} else if taxable <= 36000.0 {
taxable * 0.03
} else if taxable <= 144000.0 {
taxable * 0.10 - 2520.0
} else if taxable <= 300000.0 {
taxable * 0.20 - 16920.0
} else {
taxable * 0.25 - 31920.0
};
let calculated_net = gross - social_insurance - housing_fund - tax;
let diff = net_salary - calculated_net;
if diff.abs() < 0.01 {
break;
}
gross += diff * 0.5;
}
Ok(Value::Number(gross))
}
pub fn calc_tax_refund(args: &[Value]) -> Result<Value, RuntimeError> {
if args.len() < 2 {
return Err(RuntimeError::WrongArity {
expected: 2,
got: args.len(),
});
}
let paid_tax = get_number(&args[0])?;
let due_tax = get_number(&args[1])?;
Ok(Value::Number(paid_tax - due_tax))
}