| name | reorder-points |
| description | Calculate optimal reorder points and trigger inventory replenishment. Use this skill when determining when to place orders, setting inventory thresholds, implementing continuous review systems, or managing lead time demand. |
Reorder Point Calculation
Determine optimal inventory levels at which to trigger replenishment orders.
Installation
pip install pandas numpy scipy
Quick Start
import numpy as np
from scipy import stats
# Basic reorder point calculation
avg_daily_demand = 50
lead_time_days = 7
safety_stock = 150
reorder_point = (avg_daily_demand * lead_time_days) + safety_stock
# ROP = 50 * 7 + 150 = 500 units
Reorder Point Formulas
Basic Reorder Point
def calculate_reorder_point(avg_demand, lead_time, safety_stock):
"""Calculate basic reorder point (ROP)."""
lead_time_demand = avg_demand * lead_time
return lead_time_demand + safety_stock
def rop_with_service_level(avg_demand, demand_std, lead_time, service_level):
"""Calculate ROP with target service level."""
z = stats.norm.ppf(service_level)
lead_time_demand = avg_demand * lead_time
safety_stock = z * demand_std * np.sqrt(lead_time)
return lead_time_demand + safety_stock
Variable Lead Time ROP
def rop_variable_lead_time(avg_demand, demand_std, avg_lead_time,
lead_time_std, service_level):
"""ROP accounting for both demand and lead time variability."""
z = stats.norm.ppf(service_level)
# Expected demand during lead time
expected_dlt = avg_demand * avg_lead_time
# Standard deviation of demand during lead time
std_dlt = np.sqrt(
avg_lead_time * (demand_std ** 2) +
(avg_demand ** 2) * (lead_time_std ** 2)
)
safety_stock = z * std_dlt
return expected_dlt + safety_stock
Periodic Review System
def order_up_to_level(avg_demand, demand_std, review_period,
lead_time, service_level):
"""Calculate order-up-to level for periodic review system."""
z = stats.norm.ppf(service_level)
# Protection period = review period + lead time
protection_period = review_period + lead_time
# Expected demand during protection period
expected_demand = avg_demand * protection_period
# Safety stock for protection period
safety_stock = z * demand_std * np.sqrt(protection_period)
return expected_demand + safety_stock
def calculate_order_quantity_periodic(order_up_to, current_inventory,
on_order=0, backorders=0):
"""Calculate order quantity in periodic review system."""
inventory_position = current_inventory + on_order - backorders
order_qty = max(0, order_up_to - inventory_position)
return order_qty
Dynamic Reorder Points
def seasonal_reorder_points(demand_by_month, lead_time, service_level):
"""Calculate monthly reorder points for seasonal demand."""
reorder_points = {}
z = stats.norm.ppf(service_level)
for month, demands in demand_by_month.items():
avg = np.mean(demands)
std = np.std(demands)
ss = z * std * np.sqrt(lead_time)
reorder_points[month] = avg * lead_time + ss
return reorder_points
def demand_driven_rop(demand_history, lead_time, service_level, window=30):
"""Calculate ROP based on recent demand patterns."""
recent_demand = demand_history[-window:]
avg_demand = np.mean(recent_demand)
std_demand = np.std(recent_demand)
z = stats.norm.ppf(service_level)
safety_stock = z * std_demand * np.sqrt(lead_time)
return avg_demand * lead_time + safety_stock
Inventory Position Tracking
class InventoryMonitor:
def __init__(self, reorder_point, order_quantity):
self.rop = reorder_point
self.order_qty = order_quantity
self.on_hand = 0
self.on_order = 0
self.backorders = 0
@property
def inventory_position(self):
"""Current inventory position."""
return self.on_hand + self.on_order - self.backorders
def check_reorder(self):
"""Check if reorder is needed."""
if self.inventory_position <= self.rop:
return True, self.order_qty
return False, 0
def process_demand(self, quantity):
"""Process demand and update inventory."""
if quantity <= self.on_hand:
self.on_hand -= quantity
else:
self.backorders += quantity - self.on_hand
self.on_hand = 0