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 annual_to_monthly(args: &[Value]) -> Result<Value, RuntimeError> {
if args.is_empty() {
return Err(RuntimeError::WrongArity {
expected: 1,
got: 0,
});
}
let annual = get_number(&args[0])?;
Ok(Value::Number(annual / 12.0))
}
pub fn monthly_to_annual(args: &[Value]) -> Result<Value, RuntimeError> {
if args.is_empty() {
return Err(RuntimeError::WrongArity {
expected: 1,
got: 0,
});
}
let monthly = get_number(&args[0])?;
Ok(Value::Number(monthly * 12.0))
}
pub fn daily_to_monthly(args: &[Value]) -> Result<Value, RuntimeError> {
if args.is_empty() {
return Err(RuntimeError::WrongArity {
expected: 1,
got: 0,
});
}
let daily = get_number(&args[0])?;
Ok(Value::Number(daily * 21.75))
}
pub fn monthly_to_daily(args: &[Value]) -> Result<Value, RuntimeError> {
if args.is_empty() {
return Err(RuntimeError::WrongArity {
expected: 1,
got: 0,
});
}
let monthly = get_number(&args[0])?;
Ok(Value::Number(monthly / 21.75))
}
pub fn hourly_to_monthly(args: &[Value]) -> Result<Value, RuntimeError> {
if args.is_empty() {
return Err(RuntimeError::WrongArity {
expected: 1,
got: 0,
});
}
let hourly = get_number(&args[0])?;
let daily_hours = if args.len() > 1 {
get_number(&args[1])?
} else {
8.0
};
let monthly_days = if args.len() > 2 {
get_number(&args[2])?
} else {
21.75
};
Ok(Value::Number(hourly * daily_hours * monthly_days))
}
pub fn monthly_to_hourly(args: &[Value]) -> Result<Value, RuntimeError> {
if args.is_empty() {
return Err(RuntimeError::WrongArity {
expected: 1,
got: 0,
});
}
let monthly = get_number(&args[0])?;
let daily_hours = if args.len() > 1 {
get_number(&args[1])?
} else {
8.0
};
let monthly_days = if args.len() > 2 {
get_number(&args[2])?
} else {
21.75
};
Ok(Value::Number(monthly / (daily_hours * monthly_days)))
}
pub fn prorate_by_natural_days(args: &[Value]) -> Result<Value, RuntimeError> {
if args.len() < 3 {
return Err(RuntimeError::WrongArity {
expected: 3,
got: args.len(),
});
}
let monthly_salary = get_number(&args[0])?;
let worked_days = get_number(&args[1])?;
let total_days = get_number(&args[2])?;
Ok(Value::Number(monthly_salary * worked_days / total_days))
}
pub fn prorate_by_legal_days(args: &[Value]) -> Result<Value, RuntimeError> {
if args.len() < 2 {
return Err(RuntimeError::WrongArity {
expected: 2,
got: args.len(),
});
}
let monthly_salary = get_number(&args[0])?;
let worked_days = get_number(&args[1])?;
Ok(Value::Number(monthly_salary * worked_days / 21.75))
}
pub fn prorate_by_workdays(args: &[Value]) -> Result<Value, RuntimeError> {
if args.len() < 3 {
return Err(RuntimeError::WrongArity {
expected: 3,
got: args.len(),
});
}
let monthly_salary = get_number(&args[0])?;
let worked_days = get_number(&args[1])?;
let total_workdays = get_number(&args[2])?;
Ok(Value::Number(monthly_salary * worked_days / total_workdays))
}
pub fn calc_onboarding_salary(args: &[Value]) -> Result<Value, RuntimeError> {
if args.len() < 4 {
return Err(RuntimeError::WrongArity {
expected: 4,
got: args.len(),
});
}
let monthly_salary = get_number(&args[0])?;
let onboarding_day = get_number(&args[1])?;
let total_days = get_number(&args[2])?;
let calc_type = get_number(&args[3])? as i32;
let worked_days = total_days - onboarding_day + 1.0;
match calc_type {
0 => {
Ok(Value::Number(monthly_salary * worked_days / total_days))
}
1 => {
Ok(Value::Number(monthly_salary * worked_days / 21.75))
}
2 => {
if args.len() < 5 {
return Err(RuntimeError::InvalidOperation(
"按工作日折算需要提供当月工作日总数".to_string(),
));
}
let total_workdays = get_number(&args[4])?;
Ok(Value::Number(monthly_salary * worked_days / total_workdays))
}
_ => Err(RuntimeError::InvalidOperation(
"折算方式必须是0(自然天)、1(21.75天)或2(工作日)".to_string(),
)),
}
}
pub fn calc_resignation_salary(args: &[Value]) -> Result<Value, RuntimeError> {
if args.len() < 4 {
return Err(RuntimeError::WrongArity {
expected: 4,
got: args.len(),
});
}
let monthly_salary = get_number(&args[0])?;
let resignation_day = get_number(&args[1])?;
let total_days = get_number(&args[2])?;
let calc_type = get_number(&args[3])? as i32;
let worked_days = resignation_day;
match calc_type {
0 => {
Ok(Value::Number(monthly_salary * worked_days / total_days))
}
1 => {
Ok(Value::Number(monthly_salary * worked_days / 21.75))
}
2 => {
if args.len() < 5 {
return Err(RuntimeError::InvalidOperation(
"按工作日折算需要提供当月工作日总数".to_string(),
));
}
let total_workdays = get_number(&args[4])?;
Ok(Value::Number(monthly_salary * worked_days / total_workdays))
}
_ => Err(RuntimeError::InvalidOperation(
"折算方式必须是0(自然天)、1(21.75天)或2(工作日)".to_string(),
)),
}
}
pub fn calc_14th_salary(args: &[Value]) -> Result<Value, RuntimeError> {
if args.len() < 2 {
return Err(RuntimeError::WrongArity {
expected: 2,
got: args.len(),
});
}
let monthly_salary = get_number(&args[0])?;
let worked_months = get_number(&args[1])?;
let ratio = (worked_months / 12.0).min(1.0);
Ok(Value::Number(monthly_salary * 2.0 * ratio))
}