
Supply Chain Optimization Shopify
- 11 installs
- 558 repo stars
- Updated July 23, 2026
- nexscope-ai/ecommerce-skills
Helps with ai & agent building tasks during AI-assisted development.
About
supply-chain-optimization-shopify is a Claude Code skill in the AI & Agent Building category.
- supply-chain-optimization-shopify
- AI & Agent Building
- AI-coding skill
Supply Chain Optimization Shopify by the numbers
- 11 all-time installs (skills.sh)
- Ranked #11,696 of 16,556 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/nexscope-ai/ecommerce-skills --skill supply-chain-optimization-shopifyAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 11 |
|---|---|
| repo stars | ★ 558 |
| Last updated | July 23, 2026 |
| Repository | nexscope-ai/ecommerce-skills ↗ |
What it does
Helps with ai & agent building tasks during AI-assisted development.
Files
Supply Chain Optimization — Shopify/DTC 📦
Supply chain bottleneck analyzer for Shopify and Direct-to-Consumer stores. Diagnose cash flow, inventory, shipping, and customer acquisition costs.
Installation
npx skills add nexscope-ai/eCommerce-Skills --skill supply-chain-optimization-shopify -gPlatform Characteristics
| Feature | Shopify/DTC | vs Amazon |
|---|---|---|
| Fulfillment | Self-select (ShipBob/self) | FBA |
| Platform fee | None | 8-15% |
| Payment fee | 2.9% + $0.30 | Included in fee |
| Payment cycle | 2-3 days | 14 days |
| Traffic cost | High (self-built) | Low (platform) |
| Data ownership | Full | Limited |
Cost Structure (Shopify/DTC)
Selling Price $XX
├── Product Cost
├── Inbound Shipping (to warehouse)
├── 3PL Storage Fee (e.g., ShipBob)
├── 3PL Fulfillment Fee
├── Payment Processing (2.9% + $0.30)
├── Shopify Subscription (allocated)
├── Advertising (Meta/Google/TikTok) ← Key Cost
└── Net ProfitBenchmark Configuration
BENCHMARKS = {
"shopify": {
"gross_margin": {
"healthy": 0.60, # DTC needs high margin for ads
"warning": 0.50,
"danger": 0.40
},
"shipping_ratio": {
"healthy": 0.08, # 3PL fees
"warning": 0.12,
"danger": 0.18
},
"inventory_days": {
"healthy": 45,
"warning": 60,
"danger": 90
},
"cash_cycle": {
"healthy": 45, # Fast payment
"warning": 70,
"danger": 100
},
"net_margin": {
"healthy": 0.20,
"warning": 0.12,
"danger": 0.05
},
# DTC-specific metrics
"cac": { # Customer Acquisition Cost
"healthy": 0.25, # CAC < 25% of price
"warning": 0.35,
"danger": 0.50
},
"ltv_cac_ratio": { # LTV/CAC
"healthy": 3.0, # LTV > 3x CAC
"warning": 2.0,
"danger": 1.0
},
"ad_spend_ratio": { # Ad spend ratio
"healthy": 0.25,
"warning": 0.35,
"danger": 0.45
}
}
}DTC-Specific Costs
Advertising Costs (Critical!)
Meta Ads (Facebook/Instagram): CPM $10-30
Google Ads: CPC $1-5
TikTok Ads: CPM $5-15
Influencer Marketing: Variable
DTC ad spend typically 20-40% of revenue3PL Logistics Costs
Common 3PL Options:
├── ShipBob
├── Deliverr
├── ShipMonk
└── Red Stag
Fee Structure:
├── Receiving: $2-5/case
├── Storage: $0.5-1/cubic ft/month
├── Pick & Pack: $2-4/order
└── Shipping: By weight/zonePayment Processing Fees
Shopify Payments: 2.9% + $0.30
PayPal: 2.9% + $0.30
Stripe: 2.9% + $0.30
High AOV: Ratio acceptable
Low AOV: Erodes profitInput Data
**Sales (Shopify-specific)**
• Average Selling Price: $___
• Average Order Value (AOV): $___
• Payment Fee: 2.9% + $0.30
**Logistics (3PL)**
• 3PL Fulfillment Fee: $___/order
• 3PL Storage Fee: $___/unit/month
• Receiving Fee: $___/case
**Marketing (Critical!)**
• Ad Spend Ratio: ___%
• Customer Acquisition Cost (CAC): $___
• Customer Lifetime Value (LTV): $___
• Repeat Purchase Rate: ___%API Integration
Shopify Admin API
export SHOPIFY_STORE_URL="xxx.myshopify.com"
export SHOPIFY_ACCESS_TOKEN="xxx"Available Data
| Data | API |
|---|---|
| Orders | Orders API |
| Products | Products API |
| Inventory | Inventory API |
| Customers | Customers API |
3PL API (e.g., ShipBob)
export SHIPBOB_API_TOKEN="xxx"Bottleneck Diagnosis Focus
DTC-specific bottlenecks:
1. High CAC → Low ad efficiency, acquisition cost eating profit 2. LTV/CAC < 3 → Customer value insufficient to support CAC 3. High 3PL costs → Poor logistics choice 4. Low repeat rate → Reliant on new customers, high cost 5. Low gross margin → Cannot support ad spend
DTC Health Formula
Net Profit = Price - Product Cost - Shipping - Payment Fee - Ad Spend - Ops Cost
DTC Golden Ratios:
├── Gross Margin > 60%
├── Ad Spend < 30%
├── Shipping < 15%
├── Net Margin > 15%
└── LTV/CAC > 3vs Amazon Comparison
| Item | Amazon | Shopify/DTC |
|---|---|---|
| Platform fee | 8-15% | 0% |
| Payment fee | Included | 2.9% + $0.30 |
| Payment cycle | 14 days | 2-3 days |
| Ad spend | 10-20% | 20-40% |
| Traffic | Platform | Self-built |
| Margin need | 40%+ | 60%+ |
| Data | Limited | Full ownership |
---
Part of [Nexscope AI](https://www.nexscope.ai/?co-from=skill) — AI tools for e-commerce sellers.
#!/usr/bin/env python3
"""
Supply Chain Analyzer - Core Calculator
Supply Chain Analyzer - Core Calculator
Purpose: Calculate key metrics and diagnose bottlenecks
Version: 1.0.0
"""
import json
from dataclasses import dataclass
from typing import Optional, List, Dict
from enum import Enum
class HealthStatus(Enum):
HEALTHY = "healthy"
WARNING = "warning"
DANGER = "danger"
# ============================================================
# Benchmark Configuration (customizable)
# ============================================================
BENCHMARKS = {
"amazon": {
"gross_margin": {
"healthy": 0.40, # >40% Healthy
"warning": 0.30, # 30-40% Warning
"danger": 0.20 # <20% Danger
},
"shipping_ratio": {
"healthy": 0.05, # <5% Healthy
"warning": 0.10, # 5-10% Warning
"danger": 0.15 # >15% Danger
},
"inventory_days": {
"healthy": 45, # <45days Healthy
"warning": 60, # 45-60days Warning
"danger": 90 # >90days Danger
},
"cash_cycle": {
"healthy": 90, # <90days Healthy
"warning": 120, # 90-120days Warning
"danger": 150 # >150days Danger
},
"net_margin": {
"healthy": 0.20, # >20% Healthy
"warning": 0.10, # 10-20% Warning
"danger": 0.05 # <5% Danger
}
},
"walmart": {
"gross_margin": {
"healthy": 0.35, # Walmart Commission more low
"warning": 0.25,
"danger": 0.15
},
"shipping_ratio": {
"healthy": 0.06, # WFS ShippingSlightly higher
"warning": 0.10,
"danger": 0.15
},
"inventory_days": {
"healthy": 45,
"warning": 60,
"danger": 90
},
"cash_cycle": {
"healthy": 100, # Payment CycleSlightly longer
"warning": 130,
"danger": 160
},
"net_margin": {
"healthy": 0.18,
"warning": 0.10,
"danger": 0.05
}
},
"tiktok": {
"gross_margin": {
"healthy": 0.45, # NeedCoverInfluencerCommission
"warning": 0.35,
"danger": 0.25
},
"shipping_ratio": {
"healthy": 0.05,
"warning": 0.08,
"danger": 0.12
},
"inventory_days": {
"healthy": 30, # TikTok Best sellerweeksPeriod short
"warning": 45,
"danger": 60
},
"cash_cycle": {
"healthy": 60, # Fast payment
"warning": 90,
"danger": 120
},
"net_margin": {
"healthy": 0.15, # InfluencerShare after
"warning": 0.08,
"danger": 0.03
}
},
"shopify": {
"gross_margin": {
"healthy": 0.60, # DTC Requires high gross marginAdvertising
"warning": 0.50,
"danger": 0.40
},
"shipping_ratio": {
"healthy": 0.08, # 3PL Fee
"warning": 0.12,
"danger": 0.18
},
"inventory_days": {
"healthy": 45,
"warning": 60,
"danger": 90
},
"cash_cycle": {
"healthy": 45, # Fast payment (2-3days)
"warning": 70,
"danger": 100
},
"net_margin": {
"healthy": 0.20,
"warning": 0.12,
"danger": 0.05
}
}
}
# ============================================================
# Data Structures
# ============================================================
@dataclass
class SupplyChainInput:
"""Supply ChainInput Data"""
# Procurementend
product_cost: float # ProductCost (FOB)
supplier_payment_days: int # SupplierPayment terms (days)
production_days: int # ProductionweeksPeriod (days)
# Logisticsend
shipping_cost_per_unit: float # Single pieceInboundCost
shipping_days: int # TransportTimeeffect (days)
# Saleend
selling_price: float # Selling Price
fba_fee: float # FBA Fulfillment
storage_fee: float # monthsaverageStoragefee ( each piece)
ad_spend_ratio: float # AdvertisingfeeProportion (0-1)
# Inventoryend
inventory_days: int # CurrentInventorydays
has_long_term_storage: bool # is no has PeriodStoragefee
# Optional: from API Get
daily_sales: Optional[float] = None # DayAverage sales
current_inventory: Optional[int] = None # CurrentInventoryquantity
# Platform
platform: str = "amazon"
@dataclass
class MetricResult:
"""singleItemMetricsResult"""
name: str
value: float
unit: str
status: HealthStatus
benchmark: float
description: str
@dataclass
class BottleneckItem:
"""BottleneckItem"""
priority: int # excellent first Level 1-3
severity: str # High/ in / low
title: str
problem: str
impact: str
suggestion: str
@dataclass
class AnalysisResult:
"""AnalyzeResult"""
metrics: List[MetricResult]
cost_breakdown: Dict[str, float]
bottlenecks: List[BottleneckItem]
summary: str
# ============================================================
# CoreCalculateFunction
# ============================================================
def evaluate_status(value: float, thresholds: dict, higher_is_better: bool = True) -> HealthStatus:
"""
EvaluateMetricsHealthyStatus
Args:
value: MetricsValue
thresholds: ThresholdDictionary {"healthy": x, "warning": y, "danger": z}
higher_is_better: True=ValueexceedHighexceed good , False=Valueexceed low exceed good
"""
if higher_is_better:
if value >= thresholds["healthy"]:
return HealthStatus.HEALTHY
elif value >= thresholds["warning"]:
return HealthStatus.WARNING
else:
return HealthStatus.DANGER
else:
if value <= thresholds["healthy"]:
return HealthStatus.HEALTHY
elif value <= thresholds["warning"]:
return HealthStatus.WARNING
else:
return HealthStatus.DANGER
def calculate_metrics(data: SupplyChainInput) -> List[MetricResult]:
"""
Calculateplace has Key Metrics
"""
benchmarks = BENCHMARKS.get(data.platform, BENCHMARKS["amazon"])
metrics = []
# 1. Gross Margin
gross_profit = data.selling_price - data.product_cost - data.shipping_cost_per_unit - data.fba_fee
gross_margin = gross_profit / data.selling_price
metrics.append(MetricResult(
name="Gross Margin",
value=round(gross_margin * 100, 1),
unit="%",
status=evaluate_status(gross_margin, benchmarks["gross_margin"], higher_is_better=True),
benchmark=benchmarks["gross_margin"]["healthy"] * 100,
description=f"(Selling Price - ProductCost - Inbound - FBAfee) / Selling Price"
))
# 2. InboundProportion
shipping_ratio = data.shipping_cost_per_unit / data.selling_price
metrics.append(MetricResult(
name="InboundProportion",
value=round(shipping_ratio * 100, 1),
unit="%",
status=evaluate_status(shipping_ratio, benchmarks["shipping_ratio"], higher_is_better=False),
benchmark=benchmarks["shipping_ratio"]["healthy"] * 100,
description="InboundCost / Selling Price"
))
# 3. Net Margin
ad_cost = data.selling_price * data.ad_spend_ratio
other_cost = data.selling_price * 0.05 # Other FeesEstimate 5%
net_profit = gross_profit - data.storage_fee - ad_cost - other_cost
net_margin = net_profit / data.selling_price
metrics.append(MetricResult(
name="Net Margin",
value=round(net_margin * 100, 1),
unit="%",
status=evaluate_status(net_margin, benchmarks["net_margin"], higher_is_better=True),
benchmark=benchmarks["net_margin"]["healthy"] * 100,
description="Deduct allCost after Profit Margin"
))
# 4. Inventory Days
metrics.append(MetricResult(
name="Inventoryweeksconvert",
value=data.inventory_days,
unit="days",
status=evaluate_status(data.inventory_days, benchmarks["inventory_days"], higher_is_better=False),
benchmark=benchmarks["inventory_days"]["healthy"],
description="CurrentInventoryCanselldays"
))
# 5. CashweeksconvertweeksPeriod
cash_cycle = (
data.production_days +
data.shipping_days +
data.inventory_days +
14 # AmazonPayment Cycle
- data.supplier_payment_days
)
metrics.append(MetricResult(
name="Cash Cycle",
value=cash_cycle,
unit="days",
status=evaluate_status(cash_cycle, benchmarks["cash_cycle"], higher_is_better=False),
benchmark=benchmarks["cash_cycle"]["healthy"],
description=" from PaymentComplete payment cycleweeksPeriod"
))
return metrics
def calculate_cost_breakdown(data: SupplyChainInput) -> Dict[str, float]:
"""
CalculateCostStructure breakdown
"""
ad_cost = data.selling_price * data.ad_spend_ratio
other_cost = data.selling_price * 0.05
net_profit = (
data.selling_price
- data.product_cost
- data.shipping_cost_per_unit
- data.fba_fee
- data.storage_fee
- ad_cost
- other_cost
)
return {
"selling_price": data.selling_price,
"product_cost": data.product_cost,
"shipping_cost": data.shipping_cost_per_unit,
"fba_fee": data.fba_fee,
"storage_fee": data.storage_fee,
"ad_cost": round(ad_cost, 2),
"other_cost": round(other_cost, 2),
"net_profit": round(net_profit, 2),
# Proportion
"product_cost_ratio": round(data.product_cost / data.selling_price * 100, 1),
"shipping_ratio": round(data.shipping_cost_per_unit / data.selling_price * 100, 1),
"fba_ratio": round(data.fba_fee / data.selling_price * 100, 1),
"storage_ratio": round(data.storage_fee / data.selling_price * 100, 1),
"ad_ratio": round(ad_cost / data.selling_price * 100, 1),
"net_margin": round(net_profit / data.selling_price * 100, 1)
}
def diagnose_bottlenecks(data: SupplyChainInput, metrics: List[MetricResult]) -> List[BottleneckItem]:
"""
DiagnoseBottleneckandSort
"""
bottlenecks = []
benchmarks = BENCHMARKS.get(data.platform, BENCHMARKS["amazon"])
# Check each Metrics
for metric in metrics:
if metric.status == HealthStatus.DANGER:
severity = "High"
priority = 1
elif metric.status == HealthStatus.WARNING:
severity = " in "
priority = 2
else:
continue # HealthyNot addBottleneck
# Based onMetricsCategoryTypeGenerateRecommendation
if metric.name == "Inventoryweeksconvert":
bottlenecks.append(BottleneckItem(
priority=priority,
severity=severity,
title="Inventoryweeksconvert slow ",
problem=f"Current {metric.value} days vs Recommendation <{benchmarks['inventory_days']['healthy']} days",
impact="CapitalOccupyIncrease,MayGeneratePeriodStoragefee",
suggestion="1. Clear slow-movingSKU 2. Set safetyInventoryFormula 3. small BatchHigh frequencyRestock"
))
elif metric.name == "Cash Cycle":
bottlenecks.append(BottleneckItem(
priority=priority,
severity=severity,
title="Cash Cycle ",
problem=f"Current {metric.value} days vs Recommendation <{benchmarks['cash_cycle']['healthy']} days",
impact="CapitalUtilizeeffectRate low ,ImpactExpansionCapability",
suggestion="1. StriveSupplierPayment terms 2. shrink short Inventorydays 3. ConsiderSupply ChainFinance"
))
elif metric.name == "InboundProportion":
bottlenecks.append(BottleneckItem(
priority=priority,
severity=severity,
title="LogisticsCost High",
problem=f"Current {metric.value}% vs Recommendation <{benchmarks['shipping_ratio']['healthy']*100}%",
impact="ErodeProfitempty",
suggestion="1. Sea freightReplaceAir freight 2. LCL/Full containerOptimization 3. Compare multiple freight forwarders"
))
elif metric.name == "Gross Margin":
bottlenecks.append(BottleneckItem(
priority=priority,
severity=severity,
title="Gross Marginbias low ",
problem=f"Current {metric.value}% vs Recommendation >{benchmarks['gross_margin']['healthy']*100}%",
impact="Risk resistanceCapabilityWeak,difficult to SupportAdvertisingInput",
suggestion="1. Raise price or Optimizationlistingconvert 2. reduce low ProcurementCost 3. OptimizationProductCombo"
))
elif metric.name == "Net Margin":
bottlenecks.append(BottleneckItem(
priority=priority,
severity=severity,
title="Net Margin low ",
problem=f"Current {metric.value}% vs Recommendation >{benchmarks['net_margin']['healthy']*100}%",
impact="ProfitCapabilityWeak,BusinessCannotSustain",
suggestion="1. OptimizationAdvertisingACOS 2. ControlStoragefee 3. Increase average order value"
))
# CheckPeriodStoragefee
if data.has_long_term_storage:
bottlenecks.append(BottleneckItem(
priority=2,
severity=" in ",
title="ExistPeriodStoragefee",
problem="PartInventorysuper 365days",
impact="amount outside CostExpenditure,CapitalWaste",
suggestion="1. ExportLibraryageReport 2. On-site promotion clearanceInventory 3. Remove or destroy"
))
# by excellent first LevelSort
bottlenecks.sort(key=lambda x: x.priority)
return bottlenecks[:3] # only Return Top 3
def analyze(data: SupplyChainInput) -> AnalysisResult:
"""
ExecuteCompleteAnalyze
"""
metrics = calculate_metrics(data)
cost_breakdown = calculate_cost_breakdown(data)
bottlenecks = diagnose_bottlenecks(data, metrics)
# GenerateSummary
danger_count = sum(1 for m in metrics if m.status == HealthStatus.DANGER)
warning_count = sum(1 for m in metrics if m.status == HealthStatus.WARNING)
if danger_count > 0:
summary = f"Found {danger_count} CriticalIssueNeedImmediatelyProcess"
elif warning_count > 0:
summary = f"Found {warning_count} potential in IssueRecommendationOptimization"
else:
summary = "Supply ChainOverallHealthy,CanAttentionSustainOptimization"
return AnalysisResult(
metrics=metrics,
cost_breakdown=cost_breakdown,
bottlenecks=bottlenecks,
summary=summary
)
# ============================================================
# OutputFormat
# ============================================================
def format_metrics_table(metrics: List[MetricResult]) -> str:
"""FormatMetricsTable"""
status_icons = {
HealthStatus.HEALTHY: "✅",
HealthStatus.WARNING: "⚠️",
HealthStatus.DANGER: "🔴"
}
lines = ["| Metrics | Value | Benchmark | Status |", "|------|------|------|------|"]
for m in metrics:
icon = status_icons[m.status]
lines.append(f"| {m.name} | {m.value}{m.unit} | {m.benchmark}{m.unit} | {icon} |")
return "\n".join(lines)
def format_cost_breakdown(breakdown: Dict[str, float]) -> str:
"""FormatCostBreakdown"""
lines = [
f"Selling Price ${breakdown['selling_price']:.2f} 100%",
"─────────────────────────────",
f"ProductCost -${breakdown['product_cost']:.2f} {breakdown['product_cost_ratio']}%",
f"InboundLogistics -${breakdown['shipping_cost']:.2f} {breakdown['shipping_ratio']}%",
f"FBA Fulfillment -${breakdown['fba_fee']:.2f} {breakdown['fba_ratio']}%",
f"FBA Storagefee -${breakdown['storage_fee']:.2f} {breakdown['storage_ratio']}%",
f"Advertisingfee -${breakdown['ad_cost']:.2f} {breakdown['ad_ratio']}%",
f"OtherFee -${breakdown['other_cost']:.2f} 5.0%",
"─────────────────────────────",
f"Net Profit ${breakdown['net_profit']:.2f} {breakdown['net_margin']}%"
]
return "\n".join(lines)
def format_bottlenecks(bottlenecks: List[BottleneckItem]) -> str:
"""FormatBottleneckcolumnTable"""
if not bottlenecks:
return "✅ No obvious bottleneck found"
lines = []
priority_icons = {1: "🥇", 2: "🥈", 3: "🥉"}
for i, b in enumerate(bottlenecks, 1):
icon = priority_icons.get(i, "•")
lines.append(f"\n{icon} **【{b.severity}】{b.title}**")
lines.append(f" Issue: {b.problem}")
lines.append(f" Impact: {b.impact}")
lines.append(f" Recommendation: {b.suggestion}")
return "\n".join(lines)
def format_full_report(result: AnalysisResult) -> str:
"""GenerateCompleteReport"""
report = f"""
🔍 **Supply ChainBottleneck DiagnosisReport**
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📊 **Key Metrics**
{format_metrics_table(result.metrics)}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
💰 **CostStructure breakdown** ( each piece)
```
{format_cost_breakdown(result.cost_breakdown)}
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🎯 **Top 3 Bottleneck Diagnosis**
{format_bottlenecks(result.bottlenecks)}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📋 **Summary**: {result.summary}
"""
return report
# ============================================================
# CLI Entry Point
# ============================================================
def main():
"""CLI Entry Point - use at Test"""
import sys
# ExampleData
test_data = SupplyChainInput(
product_cost=8.00,
supplier_payment_days=0,
production_days=25,
shipping_cost_per_unit=0.75,
shipping_days=35,
selling_price=25.00,
fba_fee=5.00,
storage_fee=0.50,
ad_spend_ratio=0.10,
inventory_days=60,
has_long_term_storage=True,
platform="amazon"
)
# If JSON input provided
if len(sys.argv) > 1:
try:
input_json = json.loads(sys.argv[1])
test_data = SupplyChainInput(**input_json)
except Exception as e:
print(f"Error parsing input: {e}")
sys.exit(1)
# ExecuteAnalyze
result = analyze(test_data)
# OutputReport
print(format_full_report(result))
# Output JSON (For program call)
# print(json.dumps({
# "metrics": [{"name": m.name, "value": m.value, "status": m.status.value} for m in result.metrics],
# "bottlenecks": [{"title": b.title, "severity": b.severity} for b in result.bottlenecks],
# "summary": result.summary
# }, ensure_ascii=False, indent=2))
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
Supply Chain Analyzer - Document Report Generator
Supply ChainAnalyze - Report documentGenerate(Suitable for sharing/Demo)
"""
from datetime import datetime
from calculator import SupplyChainInput, analyze, HealthStatus
def generate_doc_report(data: SupplyChainInput, output_path: str = "report.md") -> str:
"""
GenerateReport document(Markdown Format,SuitableExport PDF/PPT)
"""
result = analyze(data)
# StatusIcon
status_icons = {
HealthStatus.HEALTHY: "🟢",
HealthStatus.WARNING: "🟡",
HealthStatus.DANGER: "🔴"
}
# MetricsTable
metrics_table = "| Metrics | CurrentValue | HealthyBenchmark | Status |\n|:---:|:---:|:---:|:---:|\n"
for m in result.metrics:
icon = status_icons[m.status]
metrics_table += f"| {m.name} | **{m.value}{m.unit}** | {m.benchmark}{m.unit} | {icon} |\n"
# CostStructure
cost = result.cost_breakdown
cost_bars = ""
cost_items = [
("ProductCost", cost['product_cost_ratio'], "🔴"),
("FBAFulfillment", cost['fba_ratio'], "🔵"),
("Advertisingfee", cost['ad_ratio'], "🟣"),
("InboundLogistics", cost['shipping_ratio'], "🟠"),
("Storagefee", cost['storage_ratio'], "🟤"),
("Other", 5, "⚪"),
("Net Profit", cost['net_margin'], "🟢"),
]
for name, ratio, emoji in cost_items:
bar = "█" * int(ratio / 2) if ratio > 0 else ""
cost_bars += f"| {emoji} {name} | {bar} | {ratio}% |\n"
# BottleneckPart
bottlenecks_section = ""
if result.bottlenecks:
for i, b in enumerate(result.bottlenecks, 1):
emoji = "🥇" if i == 1 else "🥈" if i == 2 else "🥉"
bottlenecks_section += f"""
### {emoji} Bottleneck {i}: {b.title}
**CriticalprocessDegree**: {b.severity}
**IssueDescription**
{b.problem}
**BusinessImpact**
{b.impact}
**Optimization Suggestions**
{b.suggestion}
---
"""
else:
bottlenecks_section = "\n✅ **No obvious bottleneck found,Supply ChainOverallHealthy**\n"
# ExecuteList
action_items = """
### 📋 ExecuteList
**basicweeks**
- [ ] Export FBA LibraryageReport,Mark exceeds 60 days SKU
- [ ] Calculate each SKU safe all Inventoryquantity
- [ ] OrganizeSupplierContact info,Prepare negotiation
** below weeks**
- [ ] Clear slow-movingInventory(On-site promotion/Off-site clearance)
- [ ] ContactSuppliertalkPayment terms
- [ ] AdjustRestockfrequencyRate
**basicmonths**
- [ ] InventorydaysTarget:Drop to 45 days to inside
- [ ] Evaluate small BatchHigh frequencyRestockModeFeasibility
- [ ] Review execution results
"""
# Assemble document
doc = f"""---
title: Supply ChainBottleneckAnalyzeReport
date: {datetime.now().strftime("%Y-%m-%d")}
author: Supply Chain Analyzer
---
# 📦 Supply ChainBottleneckAnalyzeReport
> **GenerateTime**: {datetime.now().strftime("%Yyears%mmonths%dDay %H:%M")}
> **AnalyzePlatform**: Amazon ({data.platform.upper()})
---
## 📌 CoreConclusion
<div style="background: #f0f9ff; padding: 20px; border-radius: 8px; border-left: 4px solid #3b82f6;">
**{result.summary}**
Based onProvided by youData,Found **{len([m for m in result.metrics if m.status != HealthStatus.HEALTHY])}** MetricsNeedAttention。
</div>
---
## 📊 Key MetricsOverview
{metrics_table}
---
## 💰 CostStructureAnalyze
** each pieceProductCostBreakdown** (Selling Price ${cost['selling_price']:.2f})
| Itemitem | Proportion | Ratio |
|:---|:---|---:|
{cost_bars}
**Net Profit: ${cost['net_profit']:.2f}/piece ({cost['net_margin']}%)**
---
## 🎯 Bottleneck Diagnosis & Optimization Suggestions
{bottlenecks_section}
---
## 🚀 Action Plan
{action_items}
---
## 📈 prePeriodEffect
| OptimizationItem | Current | Target | prePeriodRevenue |
|:---|:---:|:---:|:---|
| Inventoryweeksconvert | {data.inventory_days}days | 45days | ReleaseInventoryCapital,ReduceStoragefee |
| PeriodStoragefee | has | no | Save $500+/months |
| SupplierPayment terms | {data.supplier_payment_days}days | 30days | Improve cash flow |
---
## 📎 Appendix
### DataSource
- ProductCost: ${data.product_cost}/piece (UserInput)
- InboundCost: ${data.shipping_cost_per_unit}/piece (UserInput)
- FBA Fee: ${data.fba_fee}/piece (UserInput)
- Selling Price: ${data.selling_price}/piece (UserInput)
- Inventorydays: {data.inventory_days}days (UserInput)
### BenchmarkValueDescription
basicReportUseHealthyBenchmarkValueBased onAmazonSellerIndustryData,Can be adjusted according to actual situation。
---
<div style="text-align: center; color: #6b7280; font-size: 12px; margin-top: 40px;">
**Powered by Supply Chain Analyzer Skill | NexScope**
</div>
"""
with open(output_path, 'w', encoding='utf-8') as f:
f.write(doc)
return output_path
if __name__ == "__main__":
# TestData
test_data = SupplyChainInput(
product_cost=8.00,
supplier_payment_days=0,
production_days=25,
shipping_cost_per_unit=0.75,
shipping_days=35,
selling_price=25.00,
fba_fee=5.00,
storage_fee=0.50,
ad_spend_ratio=0.10,
inventory_days=60,
has_long_term_storage=True,
platform="amazon"
)
output = generate_doc_report(test_data, "supply_chain_report.md")
print(f"✅ Report documentGenerate: {output}")
#!/usr/bin/env python3
"""
Supply Chain Analyzer - HTML Report Generator
Supply ChainAnalyze - WebchartTableReportGenerate
"""
import json
from datetime import datetime
from calculator import SupplyChainInput, analyze, HealthStatus
def generate_html_report(data: SupplyChainInput, output_path: str = "report.html") -> str:
"""
GenerateWebchartTableReport
"""
result = analyze(data)
# Prepare imageTableData
metrics_data = [
{"name": m.name, "value": m.value, "benchmark": m.benchmark, "status": m.status.value}
for m in result.metrics
]
cost_data = result.cost_breakdown
bottlenecks_html = ""
severity_colors = {"High": "#ef4444", " in ": "#f59e0b", " low ": "#22c55e"}
for i, b in enumerate(result.bottlenecks, 1):
color = severity_colors.get(b.severity, "#6b7280")
bottlenecks_html += f"""
<div class="bottleneck-card">
<div class="bottleneck-header">
<span class="priority">#{i}</span>
<span class="severity" style="background: {color}">{b.severity}</span>
<span class="title">{b.title}</span>
</div>
<div class="bottleneck-body">
<p><strong>Issue:</strong> {b.problem}</p>
<p><strong>Impact:</strong> {b.impact}</p>
<p><strong>Recommendation:</strong> {b.suggestion}</p>
</div>
</div>
"""
html = f"""<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Supply ChainAnalyzeReport</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
* {{ margin: 0; padding: 0; box-sizing: border-box; }}
body {{
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
color: #fff;
min-height: 100vh;
padding: 40px 20px;
}}
.container {{ max-width: 1200px; margin: 0 auto; }}
.header {{
text-align: center;
margin-bottom: 40px;
}}
.header h1 {{
font-size: 32px;
margin-bottom: 8px;
}}
.header p {{
color: rgba(255,255,255,0.6);
}}
.summary-banner {{
background: linear-gradient(135deg, rgba(99, 102, 241, 0.2) 0%, rgba(139, 92, 246, 0.2) 100%);
border: 1px solid rgba(99, 102, 241, 0.3);
border-radius: 16px;
padding: 24px 32px;
margin-bottom: 40px;
text-align: center;
}}
.summary-banner h2 {{
font-size: 20px;
margin-bottom: 8px;
}}
.grid {{
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 24px;
margin-bottom: 40px;
}}
.card {{
background: rgba(255,255,255,0.05);
border: 1px solid rgba(255,255,255,0.1);
border-radius: 16px;
padding: 24px;
}}
.card h3 {{
font-size: 18px;
margin-bottom: 20px;
display: flex;
align-items: center;
gap: 8px;
}}
.metrics-table {{
width: 100%;
border-collapse: collapse;
}}
.metrics-table th, .metrics-table td {{
padding: 12px;
text-align: left;
border-bottom: 1px solid rgba(255,255,255,0.1);
}}
.metrics-table th {{
color: rgba(255,255,255,0.6);
font-weight: 500;
}}
.status {{
display: inline-flex;
align-items: center;
gap: 4px;
}}
.status.healthy {{ color: #22c55e; }}
.status.warning {{ color: #f59e0b; }}
.status.danger {{ color: #ef4444; }}
.chart-container {{
position: relative;
height: 300px;
}}
.bottleneck-card {{
background: rgba(0,0,0,0.2);
border-radius: 12px;
padding: 16px;
margin-bottom: 16px;
}}
.bottleneck-header {{
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 12px;
}}
.priority {{
background: rgba(99, 102, 241, 0.3);
padding: 4px 10px;
border-radius: 6px;
font-weight: 600;
}}
.severity {{
padding: 4px 10px;
border-radius: 6px;
font-size: 12px;
font-weight: 600;
}}
.title {{
font-weight: 600;
font-size: 16px;
}}
.bottleneck-body p {{
color: rgba(255,255,255,0.7);
font-size: 14px;
margin-bottom: 8px;
}}
.footer {{
text-align: center;
color: rgba(255,255,255,0.4);
font-size: 12px;
margin-top: 40px;
}}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>📦 Supply ChainBottleneckAnalyzeReport</h1>
<p>GenerateTime: {datetime.now().strftime("%Y-%m-%d %H:%M")}</p>
</div>
<div class="summary-banner">
<h2>{result.summary}</h2>
<p>Based onProvided by youData,WeFound {len(result.bottlenecks)} NeedAttentionIssue</p>
</div>
<div class="grid">
<div class="card">
<h3>📊 Key Metrics</h3>
<table class="metrics-table">
<thead>
<tr>
<th>Metrics</th>
<th>Value</th>
<th>Benchmark</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{"".join(f'''
<tr>
<td>{m.name}</td>
<td>{m.value}{m.unit}</td>
<td>{m.benchmark}{m.unit}</td>
<td><span class="status {m.status.value}">
{"✅" if m.status == HealthStatus.HEALTHY else "⚠️" if m.status == HealthStatus.WARNING else "🔴"}
</span></td>
</tr>
''' for m in result.metrics)}
</tbody>
</table>
</div>
<div class="card">
<h3>💰 CostStructure</h3>
<div class="chart-container">
<canvas id="costChart"></canvas>
</div>
</div>
</div>
<div class="card">
<h3>🎯 Top 3 Bottleneck Diagnosis</h3>
{bottlenecks_html if bottlenecks_html else "<p>✅ No obvious bottleneck found,Supply ChainOverallHealthy</p>"}
</div>
<div class="footer">
<p>Powered by Supply Chain Analyzer Skill | NexScope</p>
</div>
</div>
<script>
// CostStructure pie chart
const costCtx = document.getElementById('costChart').getContext('2d');
new Chart(costCtx, {{
type: 'doughnut',
data: {{
labels: ['ProductCost', 'InboundLogistics', 'FBAFulfillment', 'Storagefee', 'Advertisingfee', 'Other', 'Net Profit'],
datasets: [{{
data: [
{cost_data['product_cost_ratio']},
{cost_data['shipping_ratio']},
{cost_data['fba_ratio']},
{cost_data['storage_ratio']},
{cost_data['ad_ratio']},
5,
{cost_data['net_margin']}
],
backgroundColor: [
'#ef4444',
'#f59e0b',
'#3b82f6',
'#8b5cf6',
'#ec4899',
'#6b7280',
'#22c55e'
],
borderWidth: 0
}}]
}},
options: {{
responsive: true,
maintainAspectRatio: false,
plugins: {{
legend: {{
position: 'right',
labels: {{
color: '#fff',
padding: 12
}}
}}
}}
}}
}});
</script>
</body>
</html>
"""
with open(output_path, 'w', encoding='utf-8') as f:
f.write(html)
return output_path
if __name__ == "__main__":
# TestData
test_data = SupplyChainInput(
product_cost=8.00,
supplier_payment_days=0,
production_days=25,
shipping_cost_per_unit=0.75,
shipping_days=35,
selling_price=25.00,
fba_fee=5.00,
storage_fee=0.50,
ad_spend_ratio=0.10,
inventory_days=60,
has_long_term_storage=True,
platform="amazon"
)
output = generate_html_report(test_data, "supply_chain_report.html")
print(f"✅ Report already Generate: {output}")