use super::funejson::Value; use super::math_round_div::round_div; fn whole_units(name: &str, value: i64) { if value < 0 { panic!("{} must be a whole number, not negative, received {}", name, value); } } /// Lead-time demand, rounded up to whole units, plus safety stock. /// /// Rounding up rather than to nearest: 233.33 units of lead-time demand needs /// 234 in hand, or the last third of a unit is a stock-out. /// /// # Panics /// Panics on a negative input or a demand period of less than one day. pub fn reorder_point(demand: i64, demand_period_days: i64, lead_time_days: i64, safety_stock: i64) -> i64 { whole_units("demand", demand); whole_units("leadTimeDays", lead_time_days); whole_units("safetyStock", safety_stock); if demand_period_days <= 0 { panic!( "demandPeriodDays must be a whole number of days, at least 1, received {}", demand_period_days ); } round_div(demand * lead_time_days, demand_period_days, "up") + safety_stock } pub fn fune_vector(args: &[Value]) -> Value { let names = ["demand", "demandPeriodDays", "leadTimeDays", "safetyStock"]; for (i, name) in names.iter().enumerate() { if let Value::Float(f) = &args[i] { panic!("{} must be a whole number, received {}", name, f); } } Value::Int(reorder_point( args[0].as_i64(), args[1].as_i64(), args[2].as_i64(), args[3].as_i64(), )) }