skills/capacity-planning/SKILL.md
When the user wants to plan production or distribution capacity, analyze capacity requirements, optimize resource utilization, or balance capacity with demand. Also use when the user mentions "capacity analysis," "resource planning," "bottleneck analysis," "capacity expansion," "load balancing," "throughput planning," "utilization optimization," or "capacity modeling." For production scheduling, see master-production-scheduling. For long-term network capacity, see network-design.
npx skillsauth add kishorkukreja/awesome-supply-chain capacity-planningInstall 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 capacity planning and resource optimization. Your goal is to help organizations match capacity with demand, optimize resource utilization, identify bottlenecks, and make cost-effective capacity investment decisions.
Before developing capacity plans, understand:
Planning Context
Demand Profile
Current State
Constraints & Requirements
1. Long-Term Strategic Capacity Planning
2. Medium-Term Tactical Capacity Planning
3. Short-Term Operational Capacity Planning
Leading Strategy
Lagging Strategy
Matching Strategy
Cushion Strategy
Production Capacity Metrics:
1. Design Capacity
2. Effective Capacity
3. Actual Output
Key Formulas:
def calculate_capacity_metrics(design_capacity, effective_capacity, actual_output):
"""
Calculate capacity utilization and efficiency
Returns:
- utilization: actual / design capacity
- efficiency: actual / effective capacity
"""
utilization = (actual_output / design_capacity) * 100
efficiency = (actual_output / effective_capacity) * 100
return {
'utilization': utilization,
'efficiency': efficiency,
'design_capacity': design_capacity,
'effective_capacity': effective_capacity,
'actual_output': actual_output
}
# Example
design = 10000 # units per month
effective = 8500 # accounting for maintenance, breaks
actual = 7500 # what's produced
metrics = calculate_capacity_metrics(design, effective, actual)
print(f"Utilization: {metrics['utilization']:.1f}%") # 75%
print(f"Efficiency: {metrics['efficiency']:.1f}%") # 88.2%
Overall Equipment Effectiveness (OEE):
def calculate_oee(availability, performance, quality):
"""
Calculate OEE (Overall Equipment Effectiveness)
Parameters:
- availability: uptime / planned production time
- performance: actual output / theoretical output at 100% speed
- quality: good units / total units produced
World-class OEE: > 85%
"""
oee = availability * performance * quality * 100
return {
'oee': oee,
'availability': availability * 100,
'performance': performance * 100,
'quality': quality * 100
}
# Example
availability = 0.90 # 90% uptime
performance = 0.85 # 85% of theoretical speed
quality = 0.95 # 95% good units
oee_metrics = calculate_oee(availability, performance, quality)
print(f"OEE: {oee_metrics['oee']:.1f}%") # 72.7%
Theory of Constraints (TOC):
import pandas as pd
import numpy as np
def identify_bottleneck(process_steps):
"""
Identify bottleneck in production process
Parameters:
- process_steps: list of dicts with 'name', 'capacity_per_hour', 'hours_available'
Returns bottleneck step and throughput
"""
df = pd.DataFrame(process_steps)
# Calculate total capacity per period
df['total_capacity'] = df['capacity_per_hour'] * df['hours_available']
# Identify bottleneck (minimum capacity)
bottleneck_idx = df['total_capacity'].idxmin()
bottleneck = df.loc[bottleneck_idx]
# System throughput limited by bottleneck
system_throughput = bottleneck['total_capacity']
# Calculate utilization based on bottleneck
df['utilization'] = (system_throughput / df['total_capacity']) * 100
return {
'bottleneck_step': bottleneck['name'],
'system_throughput': system_throughput,
'bottleneck_capacity': bottleneck['total_capacity'],
'process_analysis': df
}
# Example: Manufacturing process
process = [
{'name': 'Cutting', 'capacity_per_hour': 100, 'hours_available': 160},
{'name': 'Assembly', 'capacity_per_hour': 80, 'hours_available': 160},
{'name': 'Testing', 'capacity_per_hour': 120, 'hours_available': 160},
{'name': 'Packaging', 'capacity_per_hour': 90, 'hours_available': 160}
]
bottleneck_analysis = identify_bottleneck(process)
print(f"Bottleneck: {bottleneck_analysis['bottleneck_step']}")
print(f"System Throughput: {bottleneck_analysis['system_throughput']:,.0f} units/month")
print("\nProcess Analysis:")
print(bottleneck_analysis['process_analysis'])
Drum-Buffer-Rope (DBR) Scheduling:
class DrumBufferRope:
"""
Theory of Constraints scheduling method
- Drum: Bottleneck sets the pace
- Buffer: Protect bottleneck from disruptions
- Rope: Pull mechanism to control material release
"""
def __init__(self, bottleneck_capacity, buffer_time_days=3):
self.bottleneck_capacity = bottleneck_capacity
self.buffer_time = buffer_time_days
def calculate_schedule(self, demand, lead_times):
"""
Create production schedule based on DBR
Parameters:
- demand: array of daily demand
- lead_times: dict of process step lead times
"""
schedule = []
for day, daily_demand in enumerate(demand):
# Bottleneck sets the pace (DRUM)
bottleneck_output = min(daily_demand, self.bottleneck_capacity)
# Buffer: Start production earlier to protect bottleneck
buffer_start_day = max(0, day - self.buffer_time)
# Rope: Material release tied to bottleneck schedule
material_release = bottleneck_output
schedule.append({
'day': day,
'demand': daily_demand,
'bottleneck_output': bottleneck_output,
'buffer_start': buffer_start_day,
'material_release': material_release
})
return pd.DataFrame(schedule)
# Example usage
dbr = DrumBufferRope(bottleneck_capacity=800, buffer_time_days=3)
# Daily demand for next 10 days
demand = np.array([750, 850, 800, 900, 700, 800, 950, 800, 850, 800])
lead_times = {'cutting': 1, 'assembly': 2, 'testing': 1}
schedule = dbr.calculate_schedule(demand, lead_times)
print(schedule)
Objective: Minimize total costs while meeting demand
Decision Variables:
Costs:
from pulp import *
import pandas as pd
import numpy as np
def aggregate_planning(demand, costs, constraints, periods=12):
"""
Aggregate production planning optimization
Parameters:
- demand: array of demand by period
- costs: dict with cost parameters
- constraints: dict with capacity constraints
- periods: planning horizon
Returns optimal plan
"""
# Create problem
prob = LpProblem("Aggregate_Planning", LpMinimize)
# Decision variables
P = LpVariable.dicts("Production", range(periods), lowBound=0)
W = LpVariable.dicts("Workforce", range(periods), lowBound=0, cat='Integer')
O = LpVariable.dicts("Overtime", range(periods), lowBound=0)
I = LpVariable.dicts("Inventory", range(periods), lowBound=0)
H = LpVariable.dicts("Hire", range(periods), lowBound=0, cat='Integer')
F = LpVariable.dicts("Fire", range(periods), lowBound=0, cat='Integer')
B = LpVariable.dicts("Backorder", range(periods), lowBound=0)
S = LpVariable.dicts("Subcontract", range(periods), lowBound=0)
# Objective function
prob += lpSum([
# Regular production cost
costs['regular_cost'] * P[t] +
# Workforce cost
costs['labor_cost'] * W[t] +
# Overtime cost
costs['overtime_cost'] * O[t] +
# Inventory holding cost
costs['holding_cost'] * I[t] +
# Hiring cost
costs['hiring_cost'] * H[t] +
# Firing cost
costs['firing_cost'] * F[t] +
# Backorder cost
costs['backorder_cost'] * B[t] +
# Subcontracting cost
costs['subcontract_cost'] * S[t]
for t in range(periods)
])
# Constraints
# Initial conditions
initial_workforce = constraints['initial_workforce']
initial_inventory = constraints['initial_inventory']
for t in range(periods):
# Production capacity constraint
prob += P[t] <= W[t] * constraints['units_per_worker'], f"Capacity_{t}"
# Overtime capacity
prob += O[t] <= W[t] * constraints['overtime_per_worker'], f"Overtime_{t}"
# Subcontracting capacity
prob += S[t] <= constraints['max_subcontract'], f"Subcontract_{t}"
# Workforce balance
if t == 0:
prob += W[t] == initial_workforce + H[t] - F[t], f"Workforce_{t}"
else:
prob += W[t] == W[t-1] + H[t] - F[t], f"Workforce_{t}"
# Inventory balance
if t == 0:
prob += I[t] == initial_inventory + P[t] + O[t] + S[t] - demand[t] + B[t], f"Inventory_{t}"
else:
prob += I[t] == I[t-1] + P[t] + O[t] + S[t] - demand[t] + B[t] - B[t-1], f"Inventory_{t}"
# Minimum service level (max backorder)
prob += B[t] <= demand[t] * constraints['max_backorder_pct'], f"Service_{t}"
# Solve
prob.solve(PULP_CBC_CMD(msg=0))
# Extract results
results = {
'status': LpStatus[prob.status],
'total_cost': value(prob.objective),
'production': [P[t].varValue for t in range(periods)],
'workforce': [W[t].varValue for t in range(periods)],
'overtime': [O[t].varValue for t in range(periods)],
'inventory': [I[t].varValue for t in range(periods)],
'hired': [H[t].varValue for t in range(periods)],
'fired': [F[t].varValue for t in range(periods)],
'backorders': [B[t].varValue for t in range(periods)],
'subcontract': [S[t].varValue for t in range(periods)]
}
# Create summary DataFrame
df = pd.DataFrame({
'Period': range(1, periods + 1),
'Demand': demand,
'Production': results['production'],
'Workforce': results['workforce'],
'Overtime': results['overtime'],
'Inventory': results['inventory'],
'Backorders': results['backorders'],
'Subcontract': results['subcontract']
})
results['summary'] = df
return results
# Example usage
demand = np.array([1000, 1200, 1500, 1800, 2000, 1800,
1600, 1400, 1300, 1200, 1100, 1000])
costs = {
'regular_cost': 50,
'labor_cost': 2000, # per worker per period
'overtime_cost': 75,
'holding_cost': 5,
'hiring_cost': 1000,
'firing_cost': 1500,
'backorder_cost': 100,
'subcontract_cost': 80
}
constraints = {
'initial_workforce': 40,
'initial_inventory': 500,
'units_per_worker': 30,
'overtime_per_worker': 10,
'max_subcontract': 500,
'max_backorder_pct': 0.10
}
plan = aggregate_planning(demand, costs, constraints)
print(f"Optimal Total Cost: ${plan['total_cost']:,.0f}")
print("\nProduction Plan:")
print(plan['summary'])
Process:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
class CapacityRequirementsPlanning:
"""
CRP - Calculate and analyze capacity requirements
based on production schedule and routings
"""
def __init__(self, work_centers):
"""
Parameters:
- work_centers: dict {name: {'capacity': hours, 'efficiency': 0-1}}
"""
self.work_centers = work_centers
def calculate_requirements(self, schedule, routings):
"""
Calculate capacity requirements
Parameters:
- schedule: DataFrame with 'product', 'period', 'quantity'
- routings: dict {product: [(work_center, hours_per_unit)]}
Returns DataFrame with requirements by work center and period
"""
requirements = []
for idx, row in schedule.iterrows():
product = row['product']
period = row['period']
quantity = row['quantity']
# Get routing for product
routing = routings.get(product, [])
for work_center, hours_per_unit in routing:
total_hours = quantity * hours_per_unit
# Adjust for efficiency
efficiency = self.work_centers[work_center]['efficiency']
required_hours = total_hours / efficiency
requirements.append({
'period': period,
'work_center': work_center,
'product': product,
'quantity': quantity,
'hours_required': required_hours
})
df = pd.DataFrame(requirements)
# Aggregate by work center and period
summary = df.groupby(['period', 'work_center'])['hours_required'].sum().reset_index()
# Add capacity and utilization
summary['capacity'] = summary['work_center'].map(
lambda wc: self.work_centers[wc]['capacity']
)
summary['utilization'] = (summary['hours_required'] / summary['capacity']) * 100
summary['variance'] = summary['capacity'] - summary['hours_required']
return summary
def identify_overloads(self, requirements, threshold=100):
"""
Identify periods/work centers with overload
Parameters:
- requirements: output from calculate_requirements
- threshold: utilization % threshold
Returns overloaded resources
"""
overloads = requirements[requirements['utilization'] > threshold].copy()
overloads = overloads.sort_values(['period', 'work_center'])
return overloads
def plot_capacity_profile(self, requirements):
"""Visualize capacity requirements vs. available"""
work_centers = requirements['work_center'].unique()
fig, axes = plt.subplots(len(work_centers), 1,
figsize=(12, 4 * len(work_centers)),
squeeze=False)
for i, wc in enumerate(work_centers):
wc_data = requirements[requirements['work_center'] == wc]
ax = axes[i, 0]
# Plot capacity line
ax.axhline(y=wc_data['capacity'].iloc[0],
color='green', linestyle='--',
linewidth=2, label='Capacity')
# Plot requirements
ax.bar(wc_data['period'], wc_data['hours_required'],
alpha=0.7, label='Required')
# Highlight overloads
overload = wc_data[wc_data['utilization'] > 100]
if not overload.empty:
ax.bar(overload['period'], overload['hours_required'],
color='red', alpha=0.7, label='Overload')
ax.set_title(f'{wc} - Capacity Profile')
ax.set_xlabel('Period')
ax.set_ylabel('Hours')
ax.legend()
ax.grid(True, alpha=0.3)
plt.tight_layout()
return fig
# Example usage
work_centers = {
'Cutting': {'capacity': 160, 'efficiency': 0.90},
'Welding': {'capacity': 160, 'efficiency': 0.85},
'Assembly': {'capacity': 160, 'efficiency': 0.92},
'Inspection': {'capacity': 160, 'efficiency': 0.95}
}
crp = CapacityRequirementsPlanning(work_centers)
# Production schedule
schedule = pd.DataFrame({
'product': ['A', 'A', 'B', 'B', 'C', 'C'] * 3,
'period': [1, 2, 1, 2, 1, 2] * 3,
'quantity': [100, 120, 80, 90, 60, 70] * 3
})
# Routings: hours per unit at each work center
routings = {
'A': [('Cutting', 0.5), ('Welding', 0.8), ('Assembly', 1.0), ('Inspection', 0.3)],
'B': [('Cutting', 0.6), ('Assembly', 1.2), ('Inspection', 0.4)],
'C': [('Cutting', 0.4), ('Welding', 1.0), ('Assembly', 0.8), ('Inspection', 0.2)]
}
# Calculate requirements
requirements = crp.calculate_requirements(schedule, routings)
print("Capacity Requirements:")
print(requirements)
# Identify overloads
overloads = crp.identify_overloads(requirements)
if not overloads.empty:
print("\nOverloaded Resources:")
print(overloads[['period', 'work_center', 'utilization', 'variance']])
else:
print("\nNo overloads detected")
# Plot
crp.plot_capacity_profile(requirements)
Net Present Value (NPV) Analysis:
import numpy as np
def npv_capacity_investment(initial_investment, annual_benefits,
annual_costs, discount_rate, years):
"""
Calculate NPV of capacity investment
Parameters:
- initial_investment: upfront cost
- annual_benefits: revenue increase per year
- annual_costs: operating costs per year
- discount_rate: cost of capital (e.g., 0.10 for 10%)
- years: investment horizon
"""
cash_flows = [-initial_investment]
for year in range(1, years + 1):
net_benefit = annual_benefits - annual_costs
discounted_benefit = net_benefit / ((1 + discount_rate) ** year)
cash_flows.append(discounted_benefit)
npv = sum(cash_flows)
# Calculate IRR (Internal Rate of Return)
irr = np.irr([-initial_investment] + [annual_benefits - annual_costs] * years)
# Payback period
cumulative = -initial_investment
payback = None
for year in range(1, years + 1):
cumulative += (annual_benefits - annual_costs)
if cumulative > 0 and payback is None:
payback = year
return {
'npv': npv,
'irr': irr * 100,
'payback_years': payback,
'total_investment': initial_investment,
'annual_net_benefit': annual_benefits - annual_costs
}
# Example: Evaluate new production line
investment_analysis = npv_capacity_investment(
initial_investment=5_000_000,
annual_benefits=2_000_000, # Increased revenue
annual_costs=800_000, # Operating costs
discount_rate=0.12, # 12% cost of capital
years=10
)
print("Investment Analysis:")
print(f" NPV: ${investment_analysis['npv']:,.0f}")
print(f" IRR: {investment_analysis['irr']:.1f}%")
print(f" Payback: {investment_analysis['payback_years']} years")
if investment_analysis['npv'] > 0:
print("\n✓ Investment is financially viable")
else:
print("\n✗ Investment is not viable at this discount rate")
import matplotlib.pyplot as plt
import numpy as np
class CapacityDecisionTree:
"""
Decision tree for capacity expansion timing
under demand uncertainty
"""
def __init__(self):
self.scenarios = []
def add_scenario(self, name, probability, demand_growth,
expand_now_cost, expand_later_cost,
revenue_per_unit, shortage_cost):
"""Add demand scenario"""
self.scenarios.append({
'name': name,
'probability': probability,
'demand_growth': demand_growth,
'expand_now_cost': expand_now_cost,
'expand_later_cost': expand_later_cost,
'revenue_per_unit': revenue_per_unit,
'shortage_cost': shortage_cost
})
def evaluate_expand_now(self, current_capacity, periods=5):
"""Calculate expected value of expanding now"""
ev = 0
for scenario in self.scenarios:
# Cost of expanding now
cost = -scenario['expand_now_cost']
# Benefits over periods
for period in range(1, periods + 1):
demand = current_capacity * (1 + scenario['demand_growth']) ** period
capacity_after_expansion = current_capacity * 1.5 # Assume 50% expansion
# Revenue from meeting demand
served = min(demand, capacity_after_expansion)
revenue = served * scenario['revenue_per_unit']
# Discount
discounted_revenue = revenue / (1.10 ** period)
cost += discounted_revenue
# Weight by probability
ev += cost * scenario['probability']
return ev
def evaluate_expand_later(self, current_capacity, expand_period=3, periods=5):
"""Calculate expected value of expanding later"""
ev = 0
for scenario in self.scenarios:
cost = 0
for period in range(1, periods + 1):
demand = current_capacity * (1 + scenario['demand_growth']) ** period
if period < expand_period:
# Before expansion: limited by current capacity
served = min(demand, current_capacity)
shortage = max(0, demand - current_capacity)
revenue = served * scenario['revenue_per_unit']
shortage_penalty = shortage * scenario['shortage_cost']
discounted_value = (revenue - shortage_penalty) / (1.10 ** period)
elif period == expand_period:
# Expansion happens
expansion_cost = -scenario['expand_later_cost']
served = min(demand, current_capacity * 1.5)
revenue = served * scenario['revenue_per_unit']
discounted_value = (expansion_cost + revenue) / (1.10 ** period)
else:
# After expansion
served = min(demand, current_capacity * 1.5)
revenue = served * scenario['revenue_per_unit']
discounted_value = revenue / (1.10 ** period)
cost += discounted_value
# Weight by probability
ev += cost * scenario['probability']
return ev
def evaluate_no_expansion(self, current_capacity, periods=5):
"""Calculate expected value of not expanding"""
ev = 0
for scenario in self.scenarios:
cost = 0
for period in range(1, periods + 1):
demand = current_capacity * (1 + scenario['demand_growth']) ** period
# Limited by current capacity
served = min(demand, current_capacity)
shortage = max(0, demand - current_capacity)
revenue = served * scenario['revenue_per_unit']
shortage_penalty = shortage * scenario['shortage_cost']
discounted_value = (revenue - shortage_penalty) / (1.10 ** period)
cost += discounted_value
# Weight by probability
ev += cost * scenario['probability']
return ev
def recommend(self, current_capacity):
"""Determine optimal capacity decision"""
ev_now = self.evaluate_expand_now(current_capacity)
ev_later = self.evaluate_expand_later(current_capacity)
ev_no = self.evaluate_no_expansion(current_capacity)
results = {
'expand_now': ev_now,
'expand_later': ev_later,
'no_expansion': ev_no
}
best_option = max(results, key=results.get)
return {
'recommendation': best_option,
'expected_values': results,
'best_ev': results[best_option]
}
# Example usage
dt = CapacityDecisionTree()
# Add demand scenarios
dt.add_scenario(
name='High Growth',
probability=0.30,
demand_growth=0.15,
expand_now_cost=10_000_000,
expand_later_cost=12_000_000,
revenue_per_unit=100,
shortage_cost=50
)
dt.add_scenario(
name='Moderate Growth',
probability=0.50,
demand_growth=0.08,
expand_now_cost=10_000_000,
expand_later_cost=12_000_000,
revenue_per_unit=100,
shortage_cost=50
)
dt.add_scenario(
name='Low Growth',
probability=0.20,
demand_growth=0.03,
expand_now_cost=10_000_000,
expand_later_cost=12_000_000,
revenue_per_unit=100,
shortage_cost=50
)
# Get recommendation
current_capacity = 100000 # units per year
recommendation = dt.recommend(current_capacity)
print("Capacity Expansion Decision Analysis:")
print(f"\nExpected Values:")
for option, ev in recommendation['expected_values'].items():
print(f" {option}: ${ev:,.0f}")
print(f"\n✓ Recommendation: {recommendation['recommendation'].upper()}")
print(f" Expected Value: ${recommendation['best_ev']:,.0f}")
1. Workforce Flexibility
2. Equipment Flexibility
3. Facility Flexibility
4. Partnership Flexibility
Flexibility Valuation:
def value_of_flexibility(demand_scenarios, fixed_capacity,
flexible_capacity, flexibility_cost):
"""
Calculate value of flexible capacity using real options approach
Parameters:
- demand_scenarios: list of (probability, demand) tuples
- fixed_capacity: base capacity level
- flexible_capacity: additional flexible capacity available
- flexibility_cost: cost per unit of flexible capacity
Returns value of flexibility option
"""
# Expected value with fixed capacity only
ev_fixed = 0
for prob, demand in demand_scenarios:
served = min(demand, fixed_capacity)
revenue = served * 100 # Revenue per unit
shortage_cost = max(0, demand - fixed_capacity) * 50
ev_fixed += prob * (revenue - shortage_cost)
# Expected value with flexibility
ev_flexible = 0
for prob, demand in demand_scenarios:
# Use flexible capacity only if needed
if demand > fixed_capacity:
flexible_used = min(demand - fixed_capacity, flexible_capacity)
total_served = fixed_capacity + flexible_used
else:
flexible_used = 0
total_served = demand
revenue = total_served * 100
flexibility_usage_cost = flexible_used * flexibility_cost
shortage_cost = max(0, demand - total_served) * 50
ev_flexible += prob * (revenue - flexibility_usage_cost - shortage_cost)
value_of_flexibility = ev_flexible - ev_fixed
return {
'ev_without_flexibility': ev_fixed,
'ev_with_flexibility': ev_flexible,
'value_of_flexibility': value_of_flexibility,
'flexibility_cost': flexible_capacity * flexibility_cost
}
# Example
demand_scenarios = [
(0.20, 8000), # Low demand
(0.50, 10000), # Expected demand
(0.30, 13000) # High demand
]
result = value_of_flexibility(
demand_scenarios=demand_scenarios,
fixed_capacity=10000,
flexible_capacity=3000,
flexibility_cost=15 # Extra cost per unit for flexible capacity
)
print("Flexibility Analysis:")
print(f" EV without flexibility: ${result['ev_without_flexibility']:,.0f}")
print(f" EV with flexibility: ${result['ev_with_flexibility']:,.0f}")
print(f" Value of flexibility: ${result['value_of_flexibility']:,.0f}")
if result['value_of_flexibility'] > result['flexibility_cost']:
print(f"\n✓ Flexibility is valuable (worth ${result['value_of_flexibility']:,.0f})")
else:
print(f"\n✗ Flexibility not cost-effective")
Optimization:
pulp: Linear programming for aggregate planningpyomo: Advanced optimization modelingscipy.optimize: Optimization algorithmsgekko: Dynamic optimizationSimulation:
simpy: Discrete-event simulationnumpy: Numerical computationspandas: Data analysisVisualization:
matplotlib, seaborn: Charts and graphsplotly: Interactive dashboardsnetworkx: Process flow diagramsCapacity Planning Systems:
Simulation:
ERP Capacity Planning:
Problem:
Solutions:
Problem:
Solutions:
Problem:
Solutions:
Problem:
Solutions:
Problem:
Solutions:
Executive Summary:
Current State Analysis:
| Resource | Available Capacity | Current Utilization | Effective Capacity | OEE | |----------|-------------------|---------------------|-------------------|-----| | Line 1 | 10,000 units/mo | 85% | 8,500 units/mo | 72% | | Line 2 | 8,000 units/mo | 92% | 7,360 units/mo | 78% | | Warehouse | 50,000 sq ft | 78% | 39,000 sq ft | N/A | | Labor | 120 FTE | 88% | 105.6 FTE | N/A |
Capacity Requirements Forecast:
| Period | Demand Forecast | Required Capacity | Current Capacity | Gap | Utilization | |--------|----------------|-------------------|------------------|-----|-------------| | Q1 2025 | 15,000 | 15,750 | 18,000 | -2,250 | 88% | | Q2 2025 | 17,500 | 18,375 | 18,000 | +375 | 102% | | Q3 2025 | 19,000 | 19,950 | 18,000 | +1,950 | 111% | | Q4 2025 | 20,000 | 21,000 | 18,000 | +3,000 | 117% |
Bottleneck Analysis:
Capacity Strategy Recommendation:
Option 1: Expand Now (Recommended)
Option 2: Flexible Capacity
Option 3: Delay Expansion
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.