defmodule ArcadiaCloud.Repo.Migrations.CreateCatalog do use Ecto.Migration def change do # Plan identity — the stable thing customers refer to ("Studio"). create table(:plans, primary_key: false) do add :id, :binary_id, primary_key: true add :code, :string, null: false add :name, :string, null: false add :description, :text add :active, :boolean, null: false, default: true timestamps(type: :utc_datetime) end create unique_index(:plans, [:code]) # Versioned pricing. A subscription binds to a specific plan_version; # raising prices = publishing a new version, existing subs unaffected # until explicitly migrated. create table(:plan_versions, primary_key: false) do add :id, :binary_id, primary_key: true add :plan_id, references(:plans, type: :binary_id, on_delete: :delete_all), null: false add :version, :integer, null: false add :base_price_cents, :integer, null: false, default: 0 add :currency, :string, null: false, default: "AUD" add :status, :string, null: false, default: "draft" add :published_at, :utc_datetime timestamps(type: :utc_datetime) end create unique_index(:plan_versions, [:plan_id, :version]) create index(:plan_versions, [:status]) # What a plan version INCLUDES, per resource kind, plus overage terms. create table(:plan_items, primary_key: false) do add :id, :binary_id, primary_key: true add :plan_version_id, references(:plan_versions, type: :binary_id, on_delete: :delete_all), null: false add :resource_kind, :string, null: false add :included_qty, :decimal, null: false, default: 0 add :overage_unit, :string add :overage_price_cents, :integer add :hard_cap_qty, :decimal timestamps(type: :utc_datetime) end create unique_index(:plan_items, [:plan_version_id, :resource_kind]) # A la carte upgrades. Not versioned for MVP — price changes apply # forward; existing subscription addon refs keep the price snapshotted # on the subscription (phase 3 subscriptions chunk). create table(:addons, primary_key: false) do add :id, :binary_id, primary_key: true add :code, :string, null: false add :name, :string, null: false add :resource_kind, :string, null: false add :qty, :decimal, null: false, default: 0 add :price_cents, :integer, null: false, default: 0 add :currency, :string, null: false, default: "AUD" add :active, :boolean, null: false, default: true timestamps(type: :utc_datetime) end create unique_index(:addons, [:code]) # Fallback per-unit pricing for ad-hoc / pure-usage items not covered # by a plan_item. Effective-dated. create table(:resource_prices, primary_key: false) do add :id, :binary_id, primary_key: true add :resource_kind, :string, null: false add :unit, :string, null: false add :unit_price_cents, :integer, null: false add :currency, :string, null: false, default: "AUD" add :effective_from, :date, null: false add :effective_to, :date timestamps(type: :utc_datetime) end create index(:resource_prices, [:resource_kind, :effective_from]) end end