mycopunk-swag/cli/mycopunk/catalog.py

200 lines
6.3 KiB
Python

"""
Catalog and product management for POD services.
"""
from pathlib import Path
from typing import Optional
import yaml
from rich.console import Console
from rich.table import Table
console = Console()
def get_project_root() -> Path:
"""Find the project root."""
current = Path.cwd()
while current != current.parent:
if (current / "designs").is_dir():
return current
current = current.parent
return Path.cwd()
DESIGNS_DIR = get_project_root() / "designs"
CONFIG_DIR = get_project_root() / "config"
def create_product(path: str, provider: str, sandbox: bool = False) -> None:
"""Create a product on a POD service."""
design_dir = DESIGNS_DIR / path
if not design_dir.exists():
console.print(f"[red]Error: Design not found at {design_dir}[/red]")
raise SystemExit(1)
metadata_path = design_dir / "metadata.yaml"
if not metadata_path.exists():
console.print("[red]Error: metadata.yaml not found[/red]")
raise SystemExit(1)
with open(metadata_path) as f:
metadata = yaml.safe_load(f)
products = metadata.get("products", [])
matching_products = [p for p in products if p.get("provider") == provider]
if not matching_products:
console.print(f"[yellow]No products configured for provider '{provider}'[/yellow]")
console.print("Add products to metadata.yaml first.")
raise SystemExit(1)
mode = "SANDBOX" if sandbox else "PRODUCTION"
console.print(f"\n[bold]Creating products on {provider} ({mode})[/bold]\n")
for product in matching_products:
product_type = product.get("type", "unknown")
sku = product.get("sku", "N/A")
price = product.get("retail_price", 0)
console.print(f" Product: {product_type}")
console.print(f" SKU: {sku}")
console.print(f" Price: ${price:.2f}")
if provider == "printful":
_create_printful_product(design_dir, metadata, product, sandbox)
elif provider == "prodigi":
_create_prodigi_product(design_dir, metadata, product, sandbox)
else:
console.print(f"[red] Unknown provider: {provider}[/red]")
console.print()
def _create_printful_product(
design_dir: Path,
metadata: dict,
product: dict,
sandbox: bool
) -> None:
"""Create product on Printful."""
console.print("[yellow] → Printful API integration not yet implemented[/yellow]")
console.print("[dim] Would create product with Printful API[/dim]")
# TODO: Implement Printful API call
# 1. Upload design file to Printful
# 2. Create sync product
# 3. Add sync variants
# 4. Store Printful product ID in metadata
def _create_prodigi_product(
design_dir: Path,
metadata: dict,
product: dict,
sandbox: bool
) -> None:
"""Create product on Prodigi."""
console.print("[yellow] → Prodigi API integration not yet implemented[/yellow]")
console.print("[dim] Would create product with Prodigi API[/dim]")
# TODO: Implement Prodigi API call
# 1. Upload design file to Prodigi
# 2. Create product template
# 3. Store Prodigi template ID in metadata
def push_product(path: str, provider: Optional[str] = None) -> None:
"""Push design updates to POD product."""
design_dir = DESIGNS_DIR / path
if not design_dir.exists():
console.print(f"[red]Error: Design not found at {design_dir}[/red]")
raise SystemExit(1)
metadata_path = design_dir / "metadata.yaml"
if not metadata_path.exists():
console.print("[red]Error: metadata.yaml not found[/red]")
raise SystemExit(1)
with open(metadata_path) as f:
metadata = yaml.safe_load(f)
products = metadata.get("products", [])
if provider:
products = [p for p in products if p.get("provider") == provider]
if not products:
console.print("[yellow]No products to push[/yellow]")
raise SystemExit(1)
console.print(f"\n[bold]Pushing updates for: {metadata.get('name', path)}[/bold]\n")
for product in products:
prod_provider = product.get("provider", "unknown")
product_type = product.get("type", "unknown")
console.print(f" Pushing {product_type} to {prod_provider}...")
console.print("[yellow] → API integration not yet implemented[/yellow]")
# TODO: Implement push logic
# 1. Check if product exists on provider
# 2. Upload updated design file
# 3. Sync any metadata changes
def list_products(provider: Optional[str] = None) -> None:
"""List all products across designs."""
table = Table(title="🍄 Mycopunk Products")
table.add_column("Design", style="cyan")
table.add_column("Type", style="green")
table.add_column("Provider", style="yellow")
table.add_column("SKU", style="blue")
table.add_column("Price", style="magenta", justify="right")
table.add_column("Status", style="dim")
products_found = 0
for category_dir in DESIGNS_DIR.iterdir():
if not category_dir.is_dir():
continue
for design_dir in category_dir.iterdir():
if not design_dir.is_dir():
continue
metadata_path = design_dir / "metadata.yaml"
if not metadata_path.exists():
continue
try:
with open(metadata_path) as f:
metadata = yaml.safe_load(f)
except Exception:
continue
design_path = f"{category_dir.name}/{design_dir.name}"
design_status = metadata.get("status", "unknown")
products = metadata.get("products", [])
for product in products:
prod_provider = product.get("provider", "unknown")
if provider and prod_provider != provider:
continue
products_found += 1
table.add_row(
design_path,
product.get("type", "unknown"),
prod_provider,
product.get("sku", "N/A"),
f"${product.get('retail_price', 0):.2f}",
design_status,
)
if products_found == 0:
console.print("[yellow]No products found.[/yellow]")
else:
console.print(table)
console.print(f"\n[dim]Total: {products_found} product(s)[/dim]")