# Seed example hosting plans. Idempotent — skips plans that already exist. # Run with: mix run priv/repo/seeds/catalog_seed.exs # # Prices are AUD placeholders for Sky AI's hosted-tenant offering; tune # them against real DO COGS once the cost-vs-revenue dashboard is live. alias ArcadiaCloud.Catalog # {plan_code, name, description, base_price_cents, [plan_items]} # plan_item: {resource_kind, included_qty, overage_unit, overage_price_cents, hard_cap_qty} plans = [ {"starter", "Starter", "Single small instance — good for a low-traffic app.", 2000, [ {"droplet_hours", 744, "hour", 1, nil}, {"spaces_gb_month", 25, "gb_month", 2, nil}, {"snapshot_gb_month", 10, "gb_month", 3, nil}, {"bandwidth_gb", 1000, "gb", 1, nil}, {"dns_zones", 1, "zone", 100, nil} ]}, {"studio", "Studio", "Two instances + room for assets and a managed LLM budget.", 5000, [ {"droplet_hours", 1488, "hour", 1, nil}, {"spaces_gb_month", 100, "gb_month", 2, nil}, {"snapshot_gb_month", 50, "gb_month", 3, nil}, {"bandwidth_gb", 3000, "gb", 1, nil}, {"dns_zones", 3, "zone", 100, nil}, {"llm_tokens_input", 1_000_000, "1k_tokens", 1, nil}, {"llm_tokens_output", 200_000, "1k_tokens", 3, nil} ]}, {"pro", "Pro", "Production workloads — generous compute, storage and LLM allowance.", 12000, [ {"droplet_hours", 4464, "hour", 1, nil}, {"spaces_gb_month", 500, "gb_month", 2, nil}, {"snapshot_gb_month", 200, "gb_month", 3, nil}, {"bandwidth_gb", 10000, "gb", 1, nil}, {"dns_zones", 10, "zone", 100, nil}, {"llm_tokens_input", 10_000_000, "1k_tokens", 1, nil}, {"llm_tokens_output", 2_000_000, "1k_tokens", 3, nil} ]} ] for {code, name, desc, base_cents, items} <- plans do case Catalog.get_plan_by_code(code) do nil -> {:ok, plan} = Catalog.create_plan(%{code: code, name: name, description: desc}) {:ok, version} = Catalog.create_version(%{ plan_id: plan.id, version: 1, base_price_cents: base_cents, currency: "AUD", status: "draft" }) for {kind, incl, unit, overage, cap} <- items do {:ok, _} = Catalog.add_plan_item(%{ plan_version_id: version.id, resource_kind: kind, included_qty: incl, overage_unit: unit, overage_price_cents: overage, hard_cap_qty: cap }) end {:ok, _} = Catalog.publish_version(version) IO.puts("seeded plan #{code} (#{length(items)} items) @ $#{base_cents / 100}/mo AUD") _existing -> IO.puts("plan #{code} already exists — skipped") end end # Example addons addons = [ {"storage_50gb", "+50 GB Spaces storage", "spaces_gb_month", 50, 750}, {"storage_250gb", "+250 GB Spaces storage", "spaces_gb_month", 250, 3000}, {"llm_5m_input", "+5M LLM input tokens", "llm_tokens_input", 5_000_000, 4000} ] for {code, name, kind, qty, price} <- addons do case ArcadiaCloud.Repo.get_by(ArcadiaCloud.Catalog.Addon, code: code) do nil -> {:ok, _} = Catalog.create_addon(%{ code: code, name: name, resource_kind: kind, qty: qty, price_cents: price, currency: "AUD" }) IO.puts("seeded addon #{code} @ $#{price / 100}/mo AUD") _ -> IO.puts("addon #{code} already exists — skipped") end end