Install
$ agentstack add skill-kishorkukreja-awesome-supply-chain-capacity-planning ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Capacity Planning
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.
Initial Assessment
Before developing capacity plans, understand:
- Planning Context
- What type of capacity? (production, warehouse, transportation, labor)
- Planning horizon? (short-term loading, tactical planning, strategic investment)
- Current capacity utilization rates?
- Known capacity constraints or bottlenecks?
- Demand Profile
- Demand forecast and variability?
- Seasonality patterns?
- Growth expectations?
- Product mix changes expected?
- Current State
- Existing capacity levels?
- Equipment, facilities, headcount?
- Operating schedules (shifts, days/week)?
- Current performance (OEE, yield, throughput)?
- Constraints & Requirements
- Service level targets?
- Budget constraints for expansion?
- Lead times for capacity additions?
- Union agreements or labor rules?
- Regulatory requirements?
Capacity Planning Framework
Types of Capacity Planning
1. Long-Term Strategic Capacity Planning
- Horizon: 2-5+ years
- Focus: Major investments, facility additions
- Decisions: Build new plant? Add warehouse? Outsource?
- Approach: Scenario analysis, economic modeling
2. Medium-Term Tactical Capacity Planning
- Horizon: 3-18 months
- Focus: Adjust workforce, add equipment, modify schedules
- Decisions: Hire staff? Add shift? Lease equipment?
- Approach: Aggregate planning, linear programming
3. Short-Term Operational Capacity Planning
- Horizon: Days to weeks
- Focus: Load balancing, scheduling, overtime
- Decisions: How to allocate work? Overtime? Outsource batch?
- Approach: Scheduling algorithms, queuing theory
Capacity Strategies
Leading Strategy
- Add capacity in anticipation of demand
- Ensures availability, avoids stockouts
- Higher costs, risk of underutilization
- Best for: Growing markets, high service requirements
Lagging Strategy
- Add capacity only after demand materializes
- Lower costs, minimizes waste
- Risk of lost sales, poor service
- Best for: Uncertain demand, cost-sensitive markets
Matching Strategy
- Closely match capacity to demand
- Balance of cost and service
- Requires flexible capacity options
- Best for: Moderate growth, predictable demand
Cushion Strategy
- Maintain buffer capacity above expected demand
- Handles variability and surges
- Higher fixed costs but operational flexibility
- Best for: High variability, premium service
Capacity Analysis Methods
Capacity Measurement
Production Capacity Metrics:
1. Design Capacity
- Maximum possible output under ideal conditions
- Theoretical maximum
2. Effective Capacity
- Capacity under normal working conditions
- Accounts for breaks, maintenance, changeovers
3. Actual Output
- What's currently achieved
- Reality of operations
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%
Bottleneck Analysis
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)
Capacity Planning Models
Aggregate Planning (Linear Programming)
Objective: Minimize total costs while meeting demand
Decision Variables:
- Production quantity per period
- Workforce levels
- Overtime hours
- Inventory levels
- Subcontracting quantities
Costs:
- Regular time production
- Overtime production
- Hiring and firing
- Inventory holding
- Stockout/backorder
- Subcontracting
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] 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)
Capacity Expansion Analysis
Economic Analysis of Capacity Investments
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")
Decision Tree Analysis for Capacity Timing
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
…
## Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [kishorkukreja](https://github.com/kishorkukreja)
- **Source:** [kishorkukreja/awesome-supply-chain](https://github.com/kishorkukreja/awesome-supply-chain)
- **License:** MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.