Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/controllers/api/v1/plans_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ def input_params
:amount_currency,
:trial_period,
:pay_in_advance,
:self_serve,
:bill_charges_monthly,
:bill_fixed_charges_monthly,
:cascade_updates,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ def resolve(product_key: nil, exclude_current: false)
customer = context[:customer_portal_user]
organization = customer.organization

# `self_serve: false` plans (contract-only tiers like enterprise /
# white-label) never appear in the portal, but stay assignable by
# operators (this filter only runs here).
plans = organization.plans.where(parent_id: nil)
.where(self_serve: true)
.includes(:metadata)
.order(:amount_cents)
plans = plans.where("code LIKE ?", "#{product_key}-%") if product_key.present?
Expand Down
1 change: 1 addition & 0 deletions app/graphql/types/plans/create_input.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class CreateInput < Types::BaseInputObject
argument :metadata, [Types::Metadata::Input], required: false, **Types::Metadata::Input::ARGUMENT_OPTIONS
argument :name, String, required: true
argument :pay_in_advance, Boolean, required: true
argument :self_serve, Boolean, required: false
argument :tax_codes, [String], required: false
argument :trial_period, Float, required: false

Expand Down
1 change: 1 addition & 0 deletions app/graphql/types/plans/object.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class Object < Types::BaseObject
field :name, String, null: false
field :parent, Types::Plans::Object, null: true
field :pay_in_advance, Boolean, null: false
field :self_serve, Boolean, null: false, description: "Whether the plan is offered in the self-serve customer portal"
field :trial_period, Float

field :applicable_usage_thresholds, [Types::UsageThresholds::Object]
Expand Down
1 change: 1 addition & 0 deletions app/graphql/types/plans/update_input.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class UpdateInput < Types::BaseInputObject
argument :metadata, [Types::Metadata::Input], required: false, **Types::Metadata::Input::ARGUMENT_OPTIONS
argument :name, String, required: true
argument :pay_in_advance, Boolean, required: true
argument :self_serve, Boolean, required: false
argument :tax_codes, [String], required: false
argument :trial_period, Float, required: false

Expand Down
1 change: 1 addition & 0 deletions app/serializers/v1/plan_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ def serialize
amount_currency: model.amount_currency,
trial_period: model.trial_period,
pay_in_advance: model.pay_in_advance,
self_serve: model.self_serve,
bill_charges_monthly: model.bill_charges_monthly,
bill_fixed_charges_monthly: model.bill_fixed_charges_monthly,
customers_count: 0,
Expand Down
3 changes: 2 additions & 1 deletion app/services/plans/create_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ def call
amount_currency: args[:amount_currency],
trial_period: args[:trial_period],
bill_charges_monthly: bill_charges_monthly(args),
bill_fixed_charges_monthly: bill_fixed_charges_monthly(args)
bill_fixed_charges_monthly: bill_fixed_charges_monthly(args),
self_serve: args[:self_serve].nil? ? true : args[:self_serve]
)

chargeables_validation_result = Plans::ChargeablesValidationService.call(
Expand Down
3 changes: 3 additions & 0 deletions app/services/plans/update_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ def call
plan.invoice_display_name = params[:invoice_display_name] if params.key?(:invoice_display_name)
plan.description = params[:description] if params.key?(:description)
plan.amount_cents = params[:amount_cents] if params.key?(:amount_cents)
# Portal visibility — editable even while attached to subscriptions
# (it doesn't affect billing, only the self-serve plan list).
plan.self_serve = params[:self_serve] if params.key?(:self_serve)

# NOTE: If plan is attached to subscriptions the editable attributes are:
# name, invoice_display_name, description, amount_cents
Expand Down
12 changes: 12 additions & 0 deletions db/migrate/20260701000000_add_self_serve_to_plans.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

# Adds a first-class `self_serve` flag to plans. When false, the plan is
# hidden from the customer-portal self-serve list (AvailablePlansResolver)
# but stays fully assignable by operators — used for contract-only tiers
# such as enterprise / white-label. Defaults true so every existing plan
# stays self-serve (non-breaking).
class AddSelfServeToPlans < ActiveRecord::Migration[8.0]
def change
add_column :plans, :self_serve, :boolean, default: true, null: false
end
end
Loading