Commit a9558fdf authored by Vitaly Slobodin's avatar Vitaly Slobodin Committed by Rémy Coutable

Hide deprecated billing plans

When we deprecate a billing plan then
this billing plan:
- should be displayed as legacy for namespaces that use it.
- should not be displayed for namespaces on other plans.
parent 4a92beb1
...@@ -79,6 +79,21 @@ module BillingPlansHelper ...@@ -79,6 +79,21 @@ module BillingPlansHelper
_('Seats usage data is updated every day at 12:00pm UTC') _('Seats usage data is updated every day at 12:00pm UTC')
end end
def upgrade_button_css_classes(namespace, plan, is_current_plan)
css_classes = %w[btn btn-success gl-button]
css_classes << 'disabled' if is_current_plan && !namespace.trial_active?
css_classes << 'invisible' if plan.deprecated?
css_classes.join(' ')
end
def available_plans(plans_data, current_plan)
return plans_data unless ::Feature.enabled?(:hide_deprecated_billing_plans)
plans_data.filter { |plan_data| !plan_data.deprecated? || plan_data.code == current_plan&.code }
end
private private
def plan_purchase_url(group, plan) def plan_purchase_url(group, plan)
......
- purchase_link = plan.purchase_link - purchase_link = plan.purchase_link
- plan_name = plan.name
- show_deprecated_plan = ::Feature.enabled?(:hide_deprecated_billing_plans) && plan.deprecated?
- if show_deprecated_plan
- plan_name += ' (Legacy)'
- faq_link_url = 'https://about.gitlab.com/gitlab-com/#faq'
- faq_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: faq_link_url }
.card.h-100{ class: ("card-active" if is_current) } .card.h-100{ class: ("card-active" if is_current || show_deprecated_plan) }
.card-header.gl-font-weight-bold.d-flex.flex-row.justify-content-between.flex-wrap .card-header.gl-font-weight-bold.d-flex.flex-row.justify-content-between.flex-wrap
%div %div
= plan.name = plan_name
- if is_current - if is_current
.text-muted .text-muted
= _("Current Plan") = _("Current Plan")
.card-body .card-body
.price-per-month - if show_deprecated_plan
.gl-mr-2 = s_("The %{plan_name} is no longer available to purchase. For more information about how this will impact you, check our %{faq_link_start}frequently asked questions%{faq_link_end}.").html_safe % { plan_name: plan.name, faq_link_start: faq_link_start, faq_link_end: '</a>'.html_safe }
= number_to_plan_currency(plan.price_per_month) - else
.price-per-month
.gl-mr-2
= number_to_plan_currency(plan.price_per_month)
%ul.conditions.gl-p-0.gl-my-auto %ul.conditions.gl-p-0.gl-my-auto
%li= s_("BillingPlans|per user") %li= s_("BillingPlans|per user")
%li= s_("BillingPlans|monthly") %li= s_("BillingPlans|monthly")
.price-per-year.text-left{ class: ("invisible" unless plan.price_per_year > 0) } .price-per-year.text-left{ class: ("invisible" unless plan.price_per_year > 0) }
- price_per_year = number_to_plan_currency(plan.price_per_year) - price_per_year = number_to_plan_currency(plan.price_per_year)
= s_("BillingPlans|billed annually at %{price_per_year}") % { price_per_year: price_per_year } = s_("BillingPlans|billed annually at %{price_per_year}") % { price_per_year: price_per_year }
%hr.gl-my-3 %hr.gl-my-3
%ul.unstyled-list %ul.unstyled-list
- plan_feature_short_list(plan).each do |feature| - plan_feature_short_list(plan).each do |feature|
- feature_class = "gl-p-0!" - feature_class = "gl-p-0!"
- if feature.highlight - if feature.highlight
- feature_class += " gl-font-weight-bold" - feature_class += " gl-font-weight-bold"
%li{ class: "#{feature_class}" } %li{ class: "#{feature_class}" }
= feature.title = feature.title
%li.gl-p-0.gl-pt-3 %li.gl-p-0.gl-pt-3
- if plan.about_page_href - if plan.about_page_href
= link_to s_("BillingPlans|See all %{plan_name} features") % { plan_name: plan.name }, EE::SUBSCRIPTIONS_COMPARISON_URL = link_to s_("BillingPlans|See all %{plan_name} features") % { plan_name: plan.name }, EE::SUBSCRIPTIONS_COMPARISON_URL
- if purchase_link - if purchase_link
.card-footer .card-footer
.float-right{ class: ("invisible" unless purchase_link.action == 'upgrade' || is_current) } .float-right{ class: ("invisible" unless purchase_link.action == 'upgrade' || is_current) }
- if show_contact_sales_button?(purchase_link.action) - if show_contact_sales_button?(purchase_link.action)
= link_to s_('BillingPlan|Contact sales'), "#{contact_sales_url}?test=inappcontactsales#{plan.code}", class: "btn btn-success-secondary gl-button", data: { **experiment_tracking_data_for_button_click('contact_sales') } = link_to s_('BillingPlan|Contact sales'), "#{contact_sales_url}?test=inappcontactsales#{plan.code}", class: "btn btn-success-secondary gl-button", data: { **experiment_tracking_data_for_button_click('contact_sales') }
- upgrade_button_class = "disabled" if is_current && !namespace.trial_active?
- cta_class = '-new' if use_new_purchase_flow?(namespace) - cta_class = '-new' if use_new_purchase_flow?(namespace)
= link_to s_('BillingPlan|Upgrade'), plan_purchase_or_upgrade_url(namespace, plan), class: "btn btn-success gl-button #{upgrade_button_class} billing-cta-purchase#{cta_class}", data: { **experiment_tracking_data_for_button_click('upgrade') } - upgrade_button_classes = upgrade_button_css_classes(namespace, plan, is_current)
= link_to s_('BillingPlan|Upgrade'), plan_purchase_or_upgrade_url(namespace, plan), class: "#{upgrade_button_classes} billing-cta-purchase#{cta_class}", data: { **experiment_tracking_data_for_button_click('upgrade') }
...@@ -5,8 +5,10 @@ ...@@ -5,8 +5,10 @@
= render 'shared/billings/billing_plan_header', namespace: namespace, plan: current_plan = render 'shared/billings/billing_plan_header', namespace: namespace, plan: current_plan
- if show_plans?(namespace) - if show_plans?(namespace)
.billing-plans.gl-mt-5.row - plans = available_plans(plans_data, current_plan)
- plans_data.each do |plan|
.billing-plans.gl-mt-5.row.justify-content-center
- plans.each do |plan|
- is_default_plan = current_plan.nil? && plan.default? - is_default_plan = current_plan.nil? && plan.default?
- is_current = plan.code == current_plan&.code || is_default_plan - is_current = plan.code == current_plan&.code || is_default_plan
.col-md-6.col-lg-3.gl-mb-5 .col-md-6.col-lg-3.gl-mb-5
......
---
name: hide_deprecated_billing_plans
introduced_by_url:
rollout_issue_url:
milestone: '13.7'
type: development
group: group::purchase
default_enabled: false
...@@ -18,6 +18,7 @@ RSpec.describe 'Billing plan pages', :feature do ...@@ -18,6 +18,7 @@ RSpec.describe 'Billing plan pages', :feature do
end end
before do before do
stub_feature_flags(hide_deprecated_billing_plans: false)
stub_experiment_for_subject(contact_sales_btn_in_app: true) stub_experiment_for_subject(contact_sales_btn_in_app: true)
stub_full_request("#{EE::SUBSCRIPTIONS_URL}/gitlab_plans?plan=#{plan.name}") stub_full_request("#{EE::SUBSCRIPTIONS_URL}/gitlab_plans?plan=#{plan.name}")
.to_return(status: 200, body: plans_data.to_json) .to_return(status: 200, body: plans_data.to_json)
...@@ -479,4 +480,46 @@ RSpec.describe 'Billing plan pages', :feature do ...@@ -479,4 +480,46 @@ RSpec.describe 'Billing plan pages', :feature do
end end
end end
end end
context 'when ff purchase_deprecated_plans is enabled' do
before do
stub_feature_flags(hide_deprecated_billing_plans: true)
end
context 'when deprecated plan is active' do
let(:plan) { bronze_plan }
let!(:subscription) do
create(:gitlab_subscription, namespace: namespace, hosted_plan: plan, seats: 15)
end
let(:expected_card_header) { "#{plans_data[1][:name]} (Legacy)" }
it 'renders the plan card marked as Legacy' do
visit profile_billings_path
page.within('.billing-plans') do
panels = page.all('.card')
expect(panels.length).to eq(plans_data.length)
panel_with_legacy_plan = panels[1] # free [0], bronze [1]
expect(panel_with_legacy_plan.find('.card-header')).to have_content(expected_card_header)
expect(panel_with_legacy_plan.find('.card-body')).to have_link('frequently asked questions')
end
end
end
context 'when deprecated plan is inactive' do
let(:plan) { free_plan }
it 'does not render the card for that plan' do
visit profile_billings_path
page.within('.billing-plans') do
panels = page.all('.card')
expect(panels.length).to eq(plans_data.length - 1)
end
end
end
end
end end
...@@ -90,7 +90,8 @@ ...@@ -90,7 +90,8 @@
"purchase_link": { "purchase_link": {
"action": "upgrade", "action": "upgrade",
"href": "http://customers.gitlab.com/subscriptions/new?plan_id=2c92a0ff5a840412015aa3cde86f2ba6" "href": "http://customers.gitlab.com/subscriptions/new?plan_id=2c92a0ff5a840412015aa3cde86f2ba6"
} },
"deprecated": true
}, },
{ {
"id": "silver-external-id", "id": "silver-external-id",
......
...@@ -179,4 +179,58 @@ RSpec.describe BillingPlansHelper do ...@@ -179,4 +179,58 @@ RSpec.describe BillingPlansHelper do
helper.plan_purchase_or_upgrade_url(group, plan) helper.plan_purchase_or_upgrade_url(group, plan)
end end
end end
describe '#upgrade_button_css_classe' do
using RSpec::Parameterized::TableSyntax
let(:plan) { double('Plan', deprecated?: false) }
it 'returns button-related classes only' do
expect(helper.upgrade_button_css_classes(nil, plan, false)).to eq('btn btn-success gl-button')
end
where(:is_current_plan, :trial_active, :result) do
false | false | 'btn btn-success gl-button'
false | true | 'btn btn-success gl-button'
true | true | 'btn btn-success gl-button'
true | false | 'btn btn-success gl-button disabled'
false | false | 'btn btn-success gl-button'
end
with_them do
let(:namespace) { Hashie::Mash.new(trial_active: trial_active) }
subject { helper.upgrade_button_css_classes(namespace, plan, is_current_plan) }
it { is_expected.to include(result) }
end
context 'when plan is deprecated' do
let(:deprecated_plan) { double('Plan', deprecated?: true) }
it 'returns invisible class' do
expect(helper.upgrade_button_css_classes(nil, deprecated_plan, false)).to include('invisible')
end
end
end
describe '#available_plans' do
let(:plan) { double('Plan', deprecated?: false, code: 'silver') }
let(:deprecated_plan) { double('Plan', deprecated?: true, code: 'bronze') }
let(:plans_data) { [plan, deprecated_plan] }
context 'when namespace is on an active plan' do
it 'returns plans without deprecated' do
expect(helper.available_plans(plans_data, nil)).to eq([plan])
end
end
context 'when namespace is on a deprecated plan' do
let(:current_plan) { Hashie::Mash.new(code: 'bronze') }
it 'returns plans with a deprecated plan' do
expect(helper.available_plans(plans_data, current_plan)).to eq(plans_data)
end
end
end
end end
...@@ -27017,6 +27017,9 @@ msgstr "" ...@@ -27017,6 +27017,9 @@ msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal." msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
msgstr "" msgstr ""
msgid "The %{plan_name} is no longer available to purchase. For more information about how this will impact you, check our %{faq_link_start}frequently asked questions%{faq_link_end}."
msgstr ""
msgid "The %{type} contains the following error:" msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:" msgid_plural "The %{type} contains the following errors:"
msgstr[0] "" msgstr[0] ""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment