skills/order-fulfillment/SKILL.md
When the user wants to design or optimize order fulfillment operations, improve pick-pack-ship processes, or reduce fulfillment costs. Also use when the user mentions "order processing," "pick-pack-ship," "picking strategy," "packing operations," "shipping optimization," "wave planning," "batch picking," or "fulfillment center operations." For warehouse layout, see warehouse-design. For routing pickers, see picker-routing-optimization.
npx skillsauth add kishorkukreja/awesome-supply-chain order-fulfillmentInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You are an expert in order fulfillment operations and optimization. Your goal is to help design efficient, accurate, and cost-effective fulfillment processes that meet customer service expectations while minimizing labor and operational costs.
Before optimizing fulfillment, understand:
Order Profile
Service Requirements
Current Operations
Constraints
1. Order Receipt & Validation
2. Picking
3. Packing
4. Shipping
5. Returns Processing
| Strategy | Orders/Hour | Labor Efficiency | Accuracy | Complexity | Best For | |----------|-------------|------------------|----------|------------|----------| | Discrete (Single Order) | 20-40 | Low | High | Low | Low volume, high value | | Batch Picking | 60-100 | Medium | Medium | Medium | Medium volume | | Zone Picking | 80-150 | High | Medium | High | High SKU count | | Wave Picking | 100-200+ | Very High | Medium | Very High | High volume | | Cluster Picking | 100-150 | High | High | Medium | Multi-order picking |
Description:
When to Use:
import numpy as np
import pandas as pd
def discrete_picking_capacity(orders_per_day, lines_per_order,
pick_rate_per_hour=100,
working_hours=8):
"""
Calculate labor requirements for discrete picking
Parameters:
- orders_per_day: Daily order volume
- lines_per_order: Average lines per order
- pick_rate_per_hour: Picks per person per hour (includes travel)
- working_hours: Working hours per shift
"""
picks_per_day = orders_per_day * lines_per_order
# Labor hours needed
labor_hours_needed = picks_per_day / pick_rate_per_hour
# Pickers needed
pickers_needed = labor_hours_needed / working_hours
# Orders per picker per day
orders_per_picker = orders_per_day / pickers_needed
return {
'picks_per_day': picks_per_day,
'labor_hours_needed': round(labor_hours_needed, 1),
'pickers_needed': round(pickers_needed, 1),
'orders_per_picker_per_day': round(orders_per_picker, 0),
'picks_per_picker_per_hour': pick_rate_per_hour
}
# Example
discrete = discrete_picking_capacity(
orders_per_day=500,
lines_per_order=5,
pick_rate_per_hour=100,
working_hours=8
)
print(f"Pickers needed: {discrete['pickers_needed']}")
print(f"Orders per picker: {discrete['orders_per_picker_per_day']}")
Description:
Benefits:
Implementation:
def batch_picking_optimization(orders_df, batch_size=10, sort_time_per_unit=3):
"""
Optimize batch picking
Parameters:
- orders_df: DataFrame with columns ['order_id', 'sku', 'quantity', 'location']
- batch_size: Orders per batch
- sort_time_per_unit: Seconds to sort each unit to order
Returns:
- Batch assignments and performance metrics
"""
# Create batches
orders_df = orders_df.copy()
orders_df['batch'] = (orders_df.index // batch_size) + 1
# Calculate picks per batch
batch_summary = orders_df.groupby('batch').agg({
'order_id': 'nunique',
'sku': 'count',
'quantity': 'sum',
'location': 'nunique'
}).rename(columns={
'order_id': 'orders',
'sku': 'pick_lines',
'location': 'unique_locations'
})
# Estimate time savings
# Discrete: visit each location for each order
# Batch: visit each location once per batch
discrete_picks = len(orders_df)
batch_picks = batch_summary['unique_locations'].sum()
pick_reduction_pct = (discrete_picks - batch_picks) / discrete_picks
# Sort time required
total_units = batch_summary['quantity'].sum()
sort_time_hours = (total_units * sort_time_per_unit) / 3600
return {
'total_batches': len(batch_summary),
'avg_orders_per_batch': batch_summary['orders'].mean(),
'discrete_picks': discrete_picks,
'batch_picks': batch_picks,
'pick_reduction_%': round(pick_reduction_pct * 100, 1),
'sort_time_hours': round(sort_time_hours, 2),
'batch_summary': batch_summary
}
# Example
orders_df = pd.DataFrame({
'order_id': [f'ORD_{i}' for i in range(1, 101)],
'sku': np.random.choice(['SKU_A', 'SKU_B', 'SKU_C', 'SKU_D'], 100),
'quantity': np.random.randint(1, 5, 100),
'location': np.random.choice(['A1', 'A2', 'B1', 'B2', 'C1'], 100)
})
batch_result = batch_picking_optimization(orders_df, batch_size=10)
print(f"Pick reduction: {batch_result['pick_reduction_%']}%")
print(f"Sort time required: {batch_result['sort_time_hours']} hours")
Description:
Types:
Benefits:
def zone_picking_design(warehouse_sq_ft, num_pickers, orders_per_day,
lines_per_order, sku_distribution):
"""
Design zone picking system
Parameters:
- warehouse_sq_ft: Total picking area
- num_pickers: Available pickers
- orders_per_day: Daily order volume
- lines_per_order: Average lines per order
- sku_distribution: Dict with zone: % of picks
"""
picks_per_day = orders_per_day * lines_per_order
# Allocate zones based on pick volume
zone_allocation = {}
for zone, pct in sku_distribution.items():
picks_in_zone = picks_per_day * pct
pickers_needed = picks_in_zone / (100 * 8) # 100 picks/hr, 8 hrs
zone_allocation[zone] = {
'pick_volume': round(picks_in_zone, 0),
'pickers_needed': round(pickers_needed, 1),
'sq_ft': round(warehouse_sq_ft * pct, 0)
}
return zone_allocation
# Example
sku_dist = {
'Zone_A_Fast': 0.40, # 40% of picks
'Zone_B_Medium': 0.35,
'Zone_C_Slow': 0.25
}
zones = zone_picking_design(
warehouse_sq_ft=50000,
num_pickers=20,
orders_per_day=2000,
lines_per_order=5,
sku_distribution=sku_dist
)
print("Zone Allocation:")
for zone, data in zones.items():
print(f"\n {zone}:")
print(f" Pick volume: {data['pick_volume']}")
print(f" Pickers needed: {data['pickers_needed']}")
print(f" Square footage: {data['sq_ft']}")
Description:
Wave Design Factors:
def wave_planning(orders_df, waves_per_day=4, target_wave_size=500):
"""
Plan picking waves
Parameters:
- orders_df: DataFrame with ['order_id', 'priority', 'lines', 'carrier', 'cutoff_time']
- waves_per_day: Number of waves per day
- target_wave_size: Target orders per wave
Returns:
- Wave assignments
"""
orders_df = orders_df.copy()
# Sort by priority and cutoff time
orders_df = orders_df.sort_values(['priority', 'cutoff_time'], ascending=[False, True])
# Assign to waves
orders_df['wave'] = (orders_df.index // target_wave_size) % waves_per_day + 1
# Wave summary
wave_summary = orders_df.groupby('wave').agg({
'order_id': 'count',
'lines': 'sum',
'cutoff_time': 'max'
}).rename(columns={
'order_id': 'orders',
'lines': 'total_picks'
})
# Estimate time required per wave
wave_summary['pick_hours'] = wave_summary['total_picks'] / 100 # 100 picks/hr
wave_summary['pickers_needed'] = np.ceil(wave_summary['pick_hours'] / 2) # 2 hr wave
return orders_df[['order_id', 'wave', 'priority']], wave_summary
# Example
orders_data = pd.DataFrame({
'order_id': [f'ORD_{i}' for i in range(1, 2001)],
'priority': np.random.choice([1, 2, 3], 2000, p=[0.1, 0.3, 0.6]),
'lines': np.random.poisson(5, 2000),
'carrier': np.random.choice(['UPS', 'FedEx', 'USPS'], 2000),
'cutoff_time': np.random.choice(['12:00', '15:00', '17:00'], 2000)
})
wave_assignments, wave_summary = wave_planning(orders_data, waves_per_day=4)
print("Wave Summary:")
print(wave_summary)
Description:
Benefits:
Equipment:
1. S-Shape Routing
2. Return Routing
3. Midpoint Routing
4. Largest Gap
def calculate_pick_path_distance(pick_locations, aisle_length_ft=100,
aisle_width_ft=10, routing='s-shape'):
"""
Calculate travel distance for pick path
Parameters:
- pick_locations: List of tuples [(aisle, position_pct), ...]
- aisle_length_ft: Length of aisle
- aisle_width_ft: Width between aisles
- routing: 's-shape', 'return', 'largest-gap'
Returns:
- Total travel distance
"""
# Group picks by aisle
aisles_with_picks = {}
for aisle, position in pick_locations:
if aisle not in aisles_with_picks:
aisles_with_picks[aisle] = []
aisles_with_picks[aisle].append(position)
total_distance = 0
if routing == 's-shape':
# Traverse aisles with picks, skip empty
for aisle, positions in sorted(aisles_with_picks.items()):
# Full aisle length + cross-aisle
total_distance += aisle_length_ft + aisle_width_ft
elif routing == 'return':
# Enter and exit same end
for aisle, positions in aisles_with_picks.items():
max_position = max(positions)
# Go to furthest pick and return
total_distance += (max_position * aisle_length_ft * 2) + aisle_width_ft
elif routing == 'largest-gap':
# Optimal routing (simplified)
for aisle, positions in aisles_with_picks.items():
positions_sorted = sorted(positions)
# Find largest gap
gaps = [positions_sorted[i+1] - positions_sorted[i]
for i in range(len(positions_sorted)-1)]
if gaps:
largest_gap = max(gaps)
# Distance = full aisle - largest gap
distance_in_aisle = aisle_length_ft * (1 - largest_gap)
else:
distance_in_aisle = positions_sorted[0] * aisle_length_ft
total_distance += distance_in_aisle + aisle_width_ft
return round(total_distance, 1)
# Example pick path
picks = [
(1, 0.2), # Aisle 1, 20% down
(1, 0.8), # Aisle 1, 80% down
(3, 0.5), # Aisle 3, 50% down
(5, 0.3), # Aisle 5, 30% down
]
for routing in ['s-shape', 'return', 'largest-gap']:
distance = calculate_pick_path_distance(picks, routing=routing)
print(f"{routing}: {distance} ft")
1. Single-Pass Packing
2. Pack Station (Traditional)
3. In-Line Packing
4. Automated Packing
def optimize_box_selection(order_items, box_inventory):
"""
Select optimal box size for order
Parameters:
- order_items: List of dicts [{'sku': 'A', 'qty': 2, 'dims': (10,8,4)}, ...]
- box_inventory: List of available boxes [{'box_id': 'Small', 'dims': (12,10,8), 'cost': 0.50}, ...]
Returns:
- Optimal box selection
"""
# Calculate total volume needed
total_volume = sum(
item['qty'] * item['dims'][0] * item['dims'][1] * item['dims'][2]
for item in order_items
)
# Find boxes that fit (with utilization target)
target_utilization = 0.80 # 80% full
required_volume = total_volume / target_utilization
suitable_boxes = [
box for box in box_inventory
if box['dims'][0] * box['dims'][1] * box['dims'][2] >= required_volume
]
if not suitable_boxes:
return None
# Select smallest suitable box (minimize cost)
optimal_box = min(suitable_boxes,
key=lambda b: b['dims'][0] * b['dims'][1] * b['dims'][2])
actual_volume = optimal_box['dims'][0] * optimal_box['dims'][1] * optimal_box['dims'][2]
utilization = total_volume / actual_volume
return {
'box_id': optimal_box['box_id'],
'box_dims': optimal_box['dims'],
'box_cost': optimal_box['cost'],
'utilization_%': round(utilization * 100, 1)
}
# Example
order = [
{'sku': 'A', 'qty': 1, 'dims': (10, 8, 4)},
{'sku': 'B', 'qty': 2, 'dims': (6, 6, 3)}
]
boxes = [
{'box_id': 'Small', 'dims': (12, 10, 8), 'cost': 0.50},
{'box_id': 'Medium', 'dims': (18, 14, 12), 'cost': 0.75},
{'box_id': 'Large', 'dims': (24, 18, 16), 'cost': 1.00}
]
result = optimize_box_selection(order, boxes)
if result:
print(f"Optimal box: {result['box_id']}")
print(f"Utilization: {result['utilization_%']}%")
print(f"Cost: ${result['box_cost']}")
def packing_labor_requirements(orders_per_day, packing_rate_per_hour=40,
working_hours=8, multi_item_pct=0.60):
"""
Calculate packing labor needs
Parameters:
- orders_per_day: Daily order volume
- packing_rate_per_hour: Orders packed per person per hour
- working_hours: Working hours per shift
- multi_item_pct: % of orders with multiple items (slower to pack)
Returns:
- Packing labor requirements
"""
# Adjust rate for multi-item orders
multi_item_orders = orders_per_day * multi_item_pct
single_item_orders = orders_per_day * (1 - multi_item_pct)
# Multi-item takes ~1.5x longer
equivalent_orders = single_item_orders + (multi_item_orders * 1.5)
# Labor hours needed
labor_hours = equivalent_orders / packing_rate_per_hour
# Packers needed
packers_needed = labor_hours / working_hours
# Packing stations needed (assume 80% utilization)
stations_needed = packers_needed / 0.80
return {
'orders_per_day': orders_per_day,
'equivalent_orders': round(equivalent_orders, 0),
'labor_hours_needed': round(labor_hours, 1),
'packers_needed': round(packers_needed, 1),
'packing_stations_needed': int(np.ceil(stations_needed))
}
# Example
packing = packing_labor_requirements(
orders_per_day=2000,
packing_rate_per_hour=40,
working_hours=8,
multi_item_pct=0.60
)
print(f"Packers needed: {packing['packers_needed']}")
print(f"Packing stations: {packing['packing_stations_needed']}")
def carrier_rate_shopping(order_weight_lbs, order_dims, destination_zip,
origin_zip, delivery_speed='ground'):
"""
Compare carrier rates (simplified example)
In practice, integrate with carrier APIs:
- UPS API
- FedEx API
- USPS API
"""
# Simplified rate tables (actual rates vary by contract, zone, etc.)
rates = {
'UPS': {
'ground': 8.50 + (order_weight_lbs * 0.50),
'2day': 15.00 + (order_weight_lbs * 0.75),
'overnight': 35.00 + (order_weight_lbs * 1.50)
},
'FedEx': {
'ground': 8.75 + (order_weight_lbs * 0.48),
'2day': 14.50 + (order_weight_lbs * 0.70),
'overnight': 32.00 + (order_weight_lbs * 1.40)
},
'USPS': {
'ground': 7.50 + (order_weight_lbs * 0.45),
'2day': 13.00 + (order_weight_lbs * 0.65),
'overnight': 30.00 + (order_weight_lbs * 1.30)
}
}
# Calculate dimensional weight
dim_weight = (order_dims[0] * order_dims[1] * order_dims[2]) / 139
billable_weight = max(order_weight_lbs, dim_weight)
carrier_quotes = {}
for carrier, speeds in rates.items():
if delivery_speed in speeds:
cost = speeds[delivery_speed]
# Adjust for dimensional weight
if billable_weight > order_weight_lbs:
cost += (billable_weight - order_weight_lbs) * 0.50
carrier_quotes[carrier] = round(cost, 2)
# Find cheapest
optimal_carrier = min(carrier_quotes, key=carrier_quotes.get)
return {
'carrier_quotes': carrier_quotes,
'optimal_carrier': optimal_carrier,
'optimal_cost': carrier_quotes[optimal_carrier],
'billable_weight': round(billable_weight, 1)
}
# Example
shipping = carrier_rate_shopping(
order_weight_lbs=5.0,
order_dims=(16, 12, 8), # inches
destination_zip='90210',
origin_zip='10001',
delivery_speed='ground'
)
print("Carrier Quotes:")
for carrier, cost in shipping['carrier_quotes'].items():
print(f" {carrier}: ${cost}")
print(f"\nOptimal: {shipping['optimal_carrier']} - ${shipping['optimal_cost']}")
def manifest_optimization(orders_df, trailer_capacity=50000, carrier='UPS'):
"""
Optimize order manifesting and trailer loading
Parameters:
- orders_df: DataFrame with ['order_id', 'weight', 'cube', 'carrier']
- trailer_capacity: Trailer capacity (lbs or cube)
- carrier: Filter orders by carrier
"""
# Filter orders for carrier
carrier_orders = orders_df[orders_df['carrier'] == carrier].copy()
# Sort by weight (LIFO loading - heavy first)
carrier_orders = carrier_orders.sort_values('weight', ascending=False)
# Assign to trailers
trailers = []
current_trailer = {'orders': [], 'weight': 0, 'cube': 0}
for _, order in carrier_orders.iterrows():
# Check if fits in current trailer
if current_trailer['weight'] + order['weight'] <= trailer_capacity:
current_trailer['orders'].append(order['order_id'])
current_trailer['weight'] += order['weight']
current_trailer['cube'] += order['cube']
else:
# Start new trailer
trailers.append(current_trailer)
current_trailer = {
'orders': [order['order_id']],
'weight': order['weight'],
'cube': order['cube']
}
# Add last trailer
if current_trailer['orders']:
trailers.append(current_trailer)
# Summary
manifest_summary = {
'carrier': carrier,
'total_orders': len(carrier_orders),
'trailers_needed': len(trailers),
'avg_weight_per_trailer': round(np.mean([t['weight'] for t in trailers]), 0),
'avg_utilization_%': round(np.mean([t['weight']/trailer_capacity for t in trailers]) * 100, 1)
}
return trailers, manifest_summary
# Example
orders = pd.DataFrame({
'order_id': [f'ORD_{i}' for i in range(1, 501)],
'weight': np.random.uniform(10, 200, 500),
'cube': np.random.uniform(1, 20, 500),
'carrier': np.random.choice(['UPS', 'FedEx', 'USPS'], 500)
})
trailers, summary = manifest_optimization(orders, trailer_capacity=10000, carrier='UPS')
print(f"Carrier: {summary['carrier']}")
print(f"Trailers needed: {summary['trailers_needed']}")
print(f"Average utilization: {summary['avg_utilization_%']}%")
def calculate_fulfillment_kpis(total_orders, orders_on_time, orders_accurate,
total_units, labor_hours, total_cost):
"""
Calculate fulfillment KPIs
Parameters:
- total_orders: Orders processed
- orders_on_time: Orders shipped on time
- orders_accurate: Orders shipped accurately
- total_units: Total units shipped
- labor_hours: Total labor hours
- total_cost: Total fulfillment cost
"""
# On-time delivery rate
on_time_rate = orders_on_time / total_orders
# Order accuracy
accuracy_rate = orders_accurate / total_orders
# Units per labor hour
units_per_hour = total_units / labor_hours
# Orders per labor hour
orders_per_hour = total_orders / labor_hours
# Cost per order
cost_per_order = total_cost / total_orders
# Cost per unit
cost_per_unit = total_cost / total_units
kpis = {
'On_Time_Delivery_%': round(on_time_rate * 100, 2),
'Order_Accuracy_%': round(accuracy_rate * 100, 2),
'Units_per_Labor_Hour': round(units_per_hour, 1),
'Orders_per_Labor_Hour': round(orders_per_hour, 1),
'Cost_per_Order': round(cost_per_order, 2),
'Cost_per_Unit': round(cost_per_unit, 2)
}
return kpis
# Example
kpis = calculate_fulfillment_kpis(
total_orders=10000,
orders_on_time=9700,
orders_accurate=9950,
total_units=50000,
labor_hours=1200,
total_cost=120000
)
print("Fulfillment KPIs:")
for metric, value in kpis.items():
print(f" {metric}: {value}")
| Metric | Target | World-Class | |--------|--------|-------------| | Order Accuracy | 99%+ | 99.8%+ | | On-Time Shipment | 95%+ | 99%+ | | Units per Labor Hour | 100-150 | 200+ | | Pick Accuracy | 99.5%+ | 99.9%+ | | Cost per Order | $3-$8 | <$3 | | Orders per Labor Hour | 15-25 | 30+ | | Dock-to-Stock Time | <24 hrs | <4 hrs |
Strategies:
def multi_channel_inventory_allocation(total_inventory, channels):
"""
Allocate inventory across channels
Parameters:
- total_inventory: Total available inventory
- channels: Dict with channel: {'demand_rate': X, 'priority': Y}
Returns:
- Inventory allocation by channel
"""
# Calculate total demand
total_demand = sum(ch['demand_rate'] for ch in channels.values())
allocations = {}
for channel, data in channels.items():
# Proportional allocation based on demand
base_allocation = (data['demand_rate'] / total_demand) * total_inventory
# Adjust for priority (higher priority gets +10% buffer)
priority_factor = 1 + ((data['priority'] - 2) * 0.10) # Priority 1-3
allocation = base_allocation * priority_factor
allocations[channel] = round(allocation, 0)
# Normalize to total inventory
adjustment_factor = total_inventory / sum(allocations.values())
allocations = {ch: round(qty * adjustment_factor, 0)
for ch, qty in allocations.items()}
return allocations
# Example
channels = {
'Retail_Stores': {'demand_rate': 1000, 'priority': 1},
'Ecommerce': {'demand_rate': 800, 'priority': 2},
'Wholesale': {'demand_rate': 500, 'priority': 3}
}
allocation = multi_channel_inventory_allocation(10000, channels)
print("Inventory Allocation:")
for channel, qty in allocation.items():
print(f" {channel}: {qty} units")
Reverse Logistics Process:
def returns_processing_analysis(returns_per_day, inspection_rate_per_hour=50,
restock_pct=0.70, liquidate_pct=0.25,
destroy_pct=0.05):
"""
Analyze returns processing requirements
Parameters:
- returns_per_day: Daily return volume
- inspection_rate_per_hour: Returns inspected per person per hour
- restock_pct, liquidate_pct, destroy_pct: Disposition percentages
"""
# Labor for inspection
labor_hours = returns_per_day / inspection_rate_per_hour
# Disposition volumes
restock_units = returns_per_day * restock_pct
liquidate_units = returns_per_day * liquidate_pct
destroy_units = returns_per_day * destroy_pct
# Financial impact (example)
# Assume average unit value $50
avg_unit_value = 50
# Restock: 90% recovery
# Liquidate: 20% recovery
# Destroy: 0% recovery
value_recovered = (restock_units * avg_unit_value * 0.90 +
liquidate_units * avg_unit_value * 0.20)
value_lost = (restock_units * avg_unit_value * 0.10 +
liquidate_units * avg_unit_value * 0.80 +
destroy_units * avg_unit_value)
return {
'returns_per_day': returns_per_day,
'inspection_hours': round(labor_hours, 1),
'restock_units': round(restock_units, 0),
'liquidate_units': round(liquidate_units, 0),
'destroy_units': round(destroy_units, 0),
'value_recovered_daily': round(value_recovered, 0),
'value_lost_daily': round(value_lost, 0),
'recovery_rate_%': round((value_recovered / (value_recovered + value_lost)) * 100, 1)
}
# Example
returns = returns_processing_analysis(
returns_per_day=100,
inspection_rate_per_hour=50
)
print(f"Returns per day: {returns['returns_per_day']}")
print(f"Inspection hours: {returns['inspection_hours']}")
print(f"Restock: {returns['restock_units']} units")
print(f"Value recovery rate: {returns['recovery_rate_%']}%")
Enterprise WMS:
Mid-Market WMS:
Open Source:
Hardware:
Software Integrations:
Problem:
Solutions:
Problem:
Solutions:
Problem:
Solutions:
Problem:
Solutions:
Problem:
Solutions:
Executive Summary:
Order Profile:
| Metric | Value | |--------|-------| | Orders per Day (Avg) | 2,000 | | Orders per Day (Peak) | 5,000 | | Lines per Order | 5.2 | | Units per Order | 6.8 | | Order Types | 60% each, 30% case, 10% pallet |
Recommended Picking Strategy:
Labor Requirements:
| Function | Staff Needed | Hours per Day | Shifts | |----------|--------------|---------------|--------| | Picking | 15 | 120 | 2 shifts | | Packing | 10 | 80 | 2 shifts | | Shipping | 5 | 40 | 2 shifts | | Returns | 2 | 16 | 1 shift | | Total | 32 | 256 | - |
Technology Requirements:
Performance Targets:
| KPI | Target | Current (if optimizing) | |-----|--------|-------------------------| | Order Accuracy | 99.5% | 97.2% | | On-Time Shipment | 98% | 92% | | Cost per Order | $5.50 | $7.20 | | Units per Labor Hour | 150 | 110 |
Implementation Plan:
If you need more context:
documentation
When the user wants to optimize yard operations, manage trailer parking, or improve dock door utilization. Also use when the user mentions "yard management," "trailer tracking," "yard jockey," "drop trailer program," "trailer pool," "dock scheduling," or "gate management." For cross-dock operations, see cross-docking. For warehouse design, see warehouse-design.
tools
When the user wants to optimize workforce scheduling, create shift plans, or balance labor demand. Also use when the user mentions "staff scheduling," "labor planning," "shift optimization," "crew scheduling," "roster optimization," or "employee scheduling." For task assignment, see task-assignment-problem. For wave planning labor, see wave-planning-optimization.
testing
When the user wants to optimize pick wave planning, schedule warehouse operations, or improve order fulfillment efficiency. Also use when the user mentions "wave management," "batch picking," "pick wave scheduling," "order release optimization," "wave design," or "pick wave strategy." For order batching, see order-batching-optimization. For workforce scheduling, see workforce-scheduling.
testing
When the user wants to optimize warehouse slot assignments, improve pick efficiency, or design warehouse layouts. Also use when the user mentions "slotting optimization," "slot assignment," "ABC slotting," "pick path optimization," "storage location assignment," "warehouse layout optimization," or "forward pick locations." For picker routing, see picker-routing-optimization. For warehouse design, see warehouse-design.