Commit c12be945 authored by Douglas Barbosa Alexandre's avatar Douglas Barbosa Alexandre

Merge branch 'vslobodin/user-settings-billings-impr' into 'master'

Add the Upgrade button to the User Billings page

Closes customers-gitlab-com#518

See merge request gitlab-org/gitlab-ee!15075
parents f4b48da3 dcf48326
{
"plan": {
"name": "Gold",
"code": "gold",
"trial": false
},
"usage": {
"seats_in_subscription": 100,
"seats_in_use": 98,
"max_seats_used": 104,
"seats_owed": 4
},
"billing": {
"subscription_start_date": "2018-07-11",
"subscription_end_date": "2019-07-11",
"last_invoice": "2018-09-01",
"next_invoice": "2018-10-01"
}
}
.billing-plan-header { .billing-plan-header {
border-bottom: 0; border-bottom: 0;
padding-bottom: 0;
.billing-plan-logo svg { .billing-plan-logo svg {
height: 100px; height: 100px;
...@@ -18,10 +19,6 @@ ...@@ -18,10 +19,6 @@
} }
} }
.billing-plans-alert {
margin: 0;
}
.billing-plans { .billing-plans {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
......
...@@ -13,10 +13,6 @@ module BillingPlansHelper ...@@ -13,10 +13,6 @@ module BillingPlansHelper
plan.purchase_link&.action == 'current_plan' plan.purchase_link&.action == 'current_plan'
end end
def has_plan_purchase_link?(plans_data)
plans_data.any? { |plan| plan.purchase_link&.href }
end
def plan_purchase_link(href, link_text) def plan_purchase_link(href, link_text)
if href if href
link_to link_text, href, class: 'btn btn-primary btn-inverted' link_to link_text, href, class: 'btn btn-primary btn-inverted'
......
...@@ -69,7 +69,7 @@ module EE ...@@ -69,7 +69,7 @@ module EE
validate :validate_plan_name validate :validate_plan_name
validate :validate_shared_runner_minutes_support validate :validate_shared_runner_minutes_support
delegate :trial?, :trial_ends_on, to: :gitlab_subscription, allow_nil: true delegate :trial?, :trial_ends_on, :upgradable?, to: :gitlab_subscription, allow_nil: true
before_create :sync_membership_lock_with_parent before_create :sync_membership_lock_with_parent
......
...@@ -3,4 +3,4 @@ ...@@ -3,4 +3,4 @@
%p %p
Click #{link_to('here', EE::SUBSCRIPTIONS_PLANS_URL)} to purchase more minutes. Click #{link_to('here', EE::SUBSCRIPTIONS_PLANS_URL)} to purchase more minutes.
%p %p
If you need assistance, please contact #{link_to('GitLab support', 'https://support.gitlab.com')}. If you need assistance, please contact #{link_to('GitLab support', EE::CUSTOMER_SUPPORT_URL)}.
...@@ -2,4 +2,4 @@ This is an automated notification to let you know that your CI Runner Minutes qu ...@@ -2,4 +2,4 @@ This is an automated notification to let you know that your CI Runner Minutes qu
Please visit <%= EE::SUBSCRIPTIONS_PLANS_URL %> to purchase more minutes. Please visit <%= EE::SUBSCRIPTIONS_PLANS_URL %> to purchase more minutes.
If you need assistance, please contact GitLab support (https://support.gitlab.com). If you need assistance, please contact GitLab support (<%= EE::CUSTOMER_SUPPORT_URL %>).
...@@ -3,4 +3,4 @@ ...@@ -3,4 +3,4 @@
%p %p
Click #{link_to('here', EE::SUBSCRIPTIONS_PLANS_URL)} to purchase more minutes. Click #{link_to('here', EE::SUBSCRIPTIONS_PLANS_URL)} to purchase more minutes.
%p %p
If you need assistance, please contact #{link_to('GitLab support', 'https://support.gitlab.com')}. If you need assistance, please contact #{link_to('GitLab support', EE::CUSTOMER_SUPPORT_URL)}.
...@@ -3,4 +3,4 @@ quota for "<%= @namespace_name %>" is below <%= @percentage_of_available_mins %> ...@@ -3,4 +3,4 @@ quota for "<%= @namespace_name %>" is below <%= @percentage_of_available_mins %>
Please visit <%= EE::SUBSCRIPTIONS_PLANS_URL %> to purchase more minutes. Please visit <%= EE::SUBSCRIPTIONS_PLANS_URL %> to purchase more minutes.
If you need assistance, please contact GitLab support (https://support.gitlab.com). If you need assistance, please contact GitLab support (<%= EE::CUSTOMER_SUPPORT_URL %>).
- current_plan = subscription_plan_info(@plans_data, @group.actual_plan_name)
- page_title "Billing" - page_title "Billing"
- current_plan = subscription_plan_info(@plans_data, @group.actual_plan_name)
- support_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: EE::CUSTOMER_SUPPORT_URL }
- support_link_end = '</a>'.html_safe
- if @top_most_group - if @top_most_group
- top_most_group_plan = subscription_plan_info(@plans_data, @top_most_group.actual_plan_name) - top_most_group_plan = subscription_plan_info(@plans_data, @top_most_group.actual_plan_name)
...@@ -11,6 +13,4 @@ ...@@ -11,6 +13,4 @@
- if @group.actual_plan - if @group.actual_plan
.center .center
- support_link = link_to s_("BillingPlans|Contact Support"), "https://support.gitlab.com" = s_('BillingPlans|If you would like to downgrade your plan please contact %{support_link_start}Customer Support%{support_link_end}.').html_safe % { support_link_start: support_link_start, support_link_end: support_link_end }
= s_("BillingPlans|If you would like to downgrade your plan please %{support_link}.").html_safe % { support_link: support_link }
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
%h4 %h4
- plan_link = plan.about_page_href ? link_to(plan.code.titleize, plan.about_page_href) : plan.name - plan_link = plan.about_page_href ? link_to(plan.code.titleize, plan.about_page_href) : plan.name
- if namespace == current_user.namespace - if namespace == current_user.namespace
= s_("BillingPlans|@%{user_name} you are currently on the %{plan_link} plan.").html_safe % { user_name: current_user.username, plan_link: plan_link } = s_("BillingPlans|@%{user_name} you are currently using the %{plan_link} plan.").html_safe % { user_name: current_user.username, plan_link: plan_link }
- else - else
= s_("BillingPlans|%{group_name} is currently using the %{plan_link} plan.").html_safe % { group_name: namespace.full_name, plan_link: plan_link } = s_("BillingPlans|%{group_name} is currently using the %{plan_link} plan.").html_safe % { group_name: namespace.full_name, plan_link: plan_link }
......
- current_plan = subscription_plan_info(plans_data, namespace.actual_plan_name) - current_plan = subscription_plan_info(plans_data, namespace.actual_plan_name)
- support_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: EE::CUSTOMER_SUPPORT_URL }
- support_link_end = '</a>'.html_safe
- if current_plan - if current_plan
= render 'shared/billings/billing_plan_header', namespace: namespace, plan: current_plan = render 'shared/billings/billing_plan_header', namespace: namespace, plan: current_plan
- unless has_plan_purchase_link?(plans_data) - unless namespace.gold_plan?
.billing-plans-alert.card.prepend-top-10 - if namespace.upgradable?
.card-header.bg-warning.text-white .gl-p-4.center
= s_("BillingPlans|Automatic downgrade and upgrade to some plans is currently not available.") = link_to s_('BillingPlan|Upgrade plan'), plan_upgrade_url(namespace, current_plan), class: 'btn btn-success'
- customer_support_url = 'https://about.gitlab.com/sales/';
- customer_support_link = link_to s_("BillingPlans|Customer Support"), customer_support_url
= s_("BillingPlans|Please contact %{customer_support_link} in that case.").html_safe % { customer_support_link: customer_support_link }
.billing-plans - else
- plans_data.each do |plan| .billing-plans
= render 'shared/billings/billing_plan', namespace: namespace, plan: plan - plans_data.each do |plan|
= render 'shared/billings/billing_plan', namespace: namespace, plan: plan
- if namespace.actual_plan
.center
&= s_('BillingPlans|If you would like to downgrade your plan please contact %{support_link_start}Customer Support%{support_link_end}.').html_safe % { support_link_start: support_link_start, support_link_end: support_link_end }
---
title: Add Upgrade button to the User Billing page
merge_request: 15075
author:
type: added
...@@ -4,4 +4,5 @@ module EE ...@@ -4,4 +4,5 @@ module EE
SUBSCRIPTIONS_URL = 'https://customers.gitlab.com'.freeze SUBSCRIPTIONS_URL = 'https://customers.gitlab.com'.freeze
SUBSCRIPTIONS_PLANS_URL = "#{SUBSCRIPTIONS_URL}/plans".freeze SUBSCRIPTIONS_PLANS_URL = "#{SUBSCRIPTIONS_URL}/plans".freeze
SUBSCRIPTIONS_MORE_MINUTES_URL = "#{SUBSCRIPTIONS_URL}/buy_pipeline_minutes".freeze SUBSCRIPTIONS_MORE_MINUTES_URL = "#{SUBSCRIPTIONS_URL}/buy_pipeline_minutes".freeze
CUSTOMER_SUPPORT_URL = 'https://support.gitlab.com'.freeze
end end
require 'spec_helper' require 'spec_helper'
describe 'Billing plan pages', :feature do describe 'Billing plan pages', :feature do
include StubRequests
let(:user) { create(:user) } let(:user) { create(:user) }
let(:namespace) { user.namespace }
let(:free_plan) { create(:free_plan) }
let(:bronze_plan) { create(:bronze_plan) } let(:bronze_plan) { create(:bronze_plan) }
let(:gold_plan) { create(:gold_plan) }
let(:plans_data) do let(:plans_data) do
[ JSON.parse(File.read(Rails.root.join('ee/spec/fixtures/gitlab_com_plans.json'))).map do |data|
{ data.deep_symbolize_keys
name: "Free",
price_per_month: 0,
free: true,
code: "free",
price_per_year: 0,
purchase_link: {
action: "downgrade",
href: nil
},
features: []
},
{
name: "Bronze",
price_per_month: 4,
free: false,
code: "bronze",
price_per_year: 48,
purchase_link: {
action: "current_plan",
href: nil
},
features: []
},
{
name: "Silver",
price_per_month: 19,
free: false,
code: "silver",
price_per_year: 228,
purchase_link: {
action: "upgrade",
href: nil
},
features: []
},
{
name: "Gold",
price_per_month: 99,
free: false,
code: "gold",
price_per_year: 1188,
purchase_link: {
action: "upgrade",
href: nil
},
features: []
}
]
end
shared_examples 'displays all plans and correct actions' do
it 'displays all plans' do
page.within('.billing-plans') do
panels = page.all('.card')
expect(panels.length).to eq(plans_data.length)
plans_data.each.with_index do |data, index|
expect(panels[index].find('.card-header')).to have_content(data[:name])
end
end
end
it 'displays correct plan actions' do
expected_actions = plans_data.map { |data| data.fetch(:purchase_link).fetch(:action) }
plan_actions = page.all('.billing-plans .card .plan-action')
expect(plan_actions.length).to eq(expected_actions.length)
expected_actions.each_with_index do |expected_action, index|
action = plan_actions[index]
case expected_action
when 'downgrade'
expect(action).to have_content('Downgrade')
expect(action).to have_css('.disabled')
when 'current_plan'
expect(action).to have_content('Current plan')
expect(action).to have_css('.disabled')
when 'upgrade'
expect(action).to have_content('Upgrade')
expect(action).to have_css('.disabled')
end
end
end end
end end
before do before do
expect(Gitlab::HTTP).to receive(:get).and_return(double(body: plans_data.to_json)) stub_full_request("#{EE::SUBSCRIPTIONS_URL}/gitlab_plans?plan=#{plan}")
.to_return(status: 200, body: plans_data.to_json)
stub_application_setting(check_namespace_plan: true) stub_application_setting(check_namespace_plan: true)
allow(Gitlab).to receive(:com?) { true } allow(Gitlab).to receive(:com?) { true }
gitlab_sign_in(user) gitlab_sign_in(user)
end end
def external_upgrade_url(namespace, plan)
if Plan::PAID_HOSTED_PLANS.include?(plan.name)
"#{EE::SUBSCRIPTIONS_URL}/gitlab/namespaces/#{namespace.id}/upgrade/#{plan.name}-external-id"
end
end
context 'users profile billing page' do context 'users profile billing page' do
let(:page_path) { profile_billings_path } let(:page_path) { profile_billings_path }
it_behaves_like 'billings gold trial callout' it_behaves_like 'billings gold trial callout'
context 'on bronze' do context 'on free' do
let(:plan) { free_plan.name }
let!(:subscription) do
create(:gitlab_subscription, namespace: namespace, hosted_plan: nil, seats: 15)
end
before do before do
allow_any_instance_of(EE::Namespace).to receive(:plan).and_return(bronze_plan) visit page_path
end
it 'displays all plans' do
page.within('.billing-plans') do
panels = page.all('.card')
expect(panels.length).to eq(plans_data.length)
plans_data.each.with_index do |data, index|
expect(panels[index].find('.card-header')).to have_content(data[:name])
end
end
end
it 'displays correct plan actions' do
expected_actions = plans_data.map { |data| data.fetch(:purchase_link).fetch(:action) }
plan_actions = page.all('.billing-plans .card .plan-action')
expect(plan_actions.length).to eq(expected_actions.length)
expected_actions.each_with_index do |expected_action, index|
action = plan_actions[index]
case expected_action
when 'downgrade'
expect(action).to have_content('Downgrade')
expect(action).to have_css('.disabled')
when 'current_plan'
expect(action).to have_content('Current plan')
expect(action).to have_css('.disabled')
when 'upgrade'
expect(action).to have_content('Upgrade')
expect(action).not_to have_css('.disabled')
end
end
end
end
context 'on bronze' do
let(:plan) { bronze_plan.name }
let!(:subscription) do
create(:gitlab_subscription, namespace: namespace, hosted_plan: bronze_plan, seats: 15)
end
before do
visit page_path visit page_path
end end
include_examples 'displays all plans and correct actions' it 'displays header and actions' do
page.within('.billing-plan-header') do
expect(page).to have_content("#{user.username} you are currently using the Bronze plan.")
it 'displays plan header' do expect(page).to have_css('.billing-plan-logo img')
end
page.within('.content') do
expect(page).to have_link('Upgrade plan', href: external_upgrade_url(namespace, bronze_plan))
expect(page).to have_content('downgrade your plan')
expect(page).to have_link('Customer Support', href: EE::CUSTOMER_SUPPORT_URL)
end
end
end
context 'on gold' do
let(:plan) { gold_plan.name }
let!(:subscription) do
create(:gitlab_subscription, namespace: namespace, hosted_plan: gold_plan, seats: 15)
end
before do
visit page_path
end
it 'displays header and actions' do
page.within('.billing-plan-header') do page.within('.billing-plan-header') do
expect(page).to have_content("@#{user.username} you are currently on the Bronze") expect(page).to have_content("#{user.username} you are currently using the Gold plan.")
expect(page).to have_css('.billing-plan-logo img') expect(page).to have_css('.billing-plan-logo img')
end end
page.within('.content') do
expect(page).not_to have_link('Upgrade plan')
expect(page).to have_content('downgrade your plan')
expect(page).to have_link('Customer Support', href: EE::CUSTOMER_SUPPORT_URL)
end
end end
end end
end end
context 'group billing page' do context 'group billing page' do
let(:group) { create(:group) } let(:namespace) { create(:group) }
let!(:group_member) { create(:group_member, :owner, group: group, user: user) } let!(:group_member) { create(:group_member, :owner, group: namespace, user: user) }
context 'top-most group' do context 'top-most group' do
let(:page_path) { group_billings_path(group) } let(:page_path) { group_billings_path(namespace) }
it_behaves_like 'billings gold trial callout' it_behaves_like 'billings gold trial callout'
context 'on bronze' do context 'on bronze' do
before do let(:plan) { bronze_plan.name }
expect_any_instance_of(EE::Group).to receive(:plan).at_least(:once).and_return(bronze_plan)
let!(:subscription) do
create(:gitlab_subscription, namespace: namespace, hosted_plan: bronze_plan, seats: 15)
end
before do
visit page_path visit page_path
end end
it 'displays plan header' do it 'displays plan header' do
page.within('.billing-plan-header') do page.within('.billing-plan-header') do
expect(page).to have_content("#{group.name} is currently using the Bronze plan") expect(page).to have_content("#{namespace.name} is currently using the Bronze plan")
expect(page).to have_css('.billing-plan-logo .identicon') expect(page).to have_css('.billing-plan-logo .identicon')
end end
...@@ -168,10 +181,17 @@ describe 'Billing plan pages', :feature do ...@@ -168,10 +181,17 @@ describe 'Billing plan pages', :feature do
let(:subgroup2) { create(:group, parent: subgroup1) } let(:subgroup2) { create(:group, parent: subgroup1) }
let!(:subgroup2_member) { create(:group_member, :owner, group: subgroup2, user: user3) } let!(:subgroup2_member) { create(:group_member, :owner, group: subgroup2, user: user3) }
let(:page_path) { group_billings_path(subgroup2) } let(:page_path) { group_billings_path(subgroup2) }
let(:namespace) { group }
it_behaves_like 'billings gold trial callout' it_behaves_like 'billings gold trial callout'
context 'on bronze' do context 'on bronze' do
let(:plan) { bronze_plan.name }
let!(:subscription) do
create(:gitlab_subscription, namespace: namespace, hosted_plan: bronze_plan, seats: 15)
end
before do before do
visit page_path visit page_path
end end
...@@ -189,6 +209,8 @@ describe 'Billing plan pages', :feature do ...@@ -189,6 +209,8 @@ describe 'Billing plan pages', :feature do
end end
context 'with unexpected JSON' do context 'with unexpected JSON' do
let(:plan) { 'free' }
let(:plans_data) do let(:plans_data) do
[ [
{ {
......
...@@ -21,6 +21,7 @@ describe Namespace do ...@@ -21,6 +21,7 @@ describe Namespace do
it { is_expected.to delegate_method(:shared_runners_seconds_last_reset).to(:namespace_statistics) } it { is_expected.to delegate_method(:shared_runners_seconds_last_reset).to(:namespace_statistics) }
it { is_expected.to delegate_method(:trial?).to(:gitlab_subscription) } it { is_expected.to delegate_method(:trial?).to(:gitlab_subscription) }
it { is_expected.to delegate_method(:trial_ends_on).to(:gitlab_subscription) } it { is_expected.to delegate_method(:trial_ends_on).to(:gitlab_subscription) }
it { is_expected.to delegate_method(:upgradable?).to(:gitlab_subscription) }
context 'scopes' do context 'scopes' do
describe '.with_plan' do describe '.with_plan' do
......
...@@ -60,11 +60,13 @@ end ...@@ -60,11 +60,13 @@ end
shared_examples 'billings gold trial callout' do shared_examples 'billings gold trial callout' do
context 'on a free plan' do context 'on a free plan' do
let(:plan) { nil } let(:plan) { 'free' }
before do let!(:subscription) do
allow_any_instance_of(EE::Namespace).to receive(:plan).and_return(plan) create(:gitlab_subscription, namespace: namespace, hosted_plan: nil, seats: 15)
end
before do
visit page_path visit page_path
end end
...@@ -80,11 +82,13 @@ shared_examples 'billings gold trial callout' do ...@@ -80,11 +82,13 @@ shared_examples 'billings gold trial callout' do
where(case_names: ->(plan_type) {"like #{plan_type}"}, plan_type: [:bronze, :silver]) where(case_names: ->(plan_type) {"like #{plan_type}"}, plan_type: [:bronze, :silver])
with_them do with_them do
let(:plan) { plans[plan_type] } let(:plan) { plan_type }
before do let!(:subscription) do
allow_any_instance_of(EE::Namespace).to receive(:plan).and_return(plan) create(:gitlab_subscription, namespace: namespace, hosted_plan: plans[plan_type], seats: 15)
end
before do
visit page_path visit page_path
end end
...@@ -99,11 +103,13 @@ shared_examples 'billings gold trial callout' do ...@@ -99,11 +103,13 @@ shared_examples 'billings gold trial callout' do
end end
context 'on a gold plan' do context 'on a gold plan' do
set(:plan) { create(:gold_plan) } let(:plan) { gold_plan.name }
before do let!(:subscription) do
allow_any_instance_of(EE::Namespace).to receive(:plan).and_return(plan) create(:gitlab_subscription, namespace: namespace, hosted_plan: gold_plan, seats: 15)
end
before do
visit page_path visit page_path
end end
......
...@@ -2224,25 +2224,16 @@ msgstr "" ...@@ -2224,25 +2224,16 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_link} plan." msgid "BillingPlans|%{group_name} is currently using the %{plan_link} plan."
msgstr "" msgstr ""
msgid "BillingPlans|@%{user_name} you are currently on the %{plan_link} plan." msgid "BillingPlans|@%{user_name} you are currently using the %{plan_link} plan."
msgstr ""
msgid "BillingPlans|Automatic downgrade and upgrade to some plans is currently not available."
msgstr ""
msgid "BillingPlans|Contact Support"
msgstr "" msgstr ""
msgid "BillingPlans|Current plan" msgid "BillingPlans|Current plan"
msgstr "" msgstr ""
msgid "BillingPlans|Customer Support"
msgstr ""
msgid "BillingPlans|Downgrade" msgid "BillingPlans|Downgrade"
msgstr "" msgstr ""
msgid "BillingPlans|If you would like to downgrade your plan please %{support_link}." msgid "BillingPlans|If you would like to downgrade your plan please contact %{support_link_start}Customer Support%{support_link_end}."
msgstr "" msgstr ""
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold." msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
...@@ -2254,9 +2245,6 @@ msgstr "" ...@@ -2254,9 +2245,6 @@ msgstr ""
msgid "BillingPlans|Manage plan" msgid "BillingPlans|Manage plan"
msgstr "" msgstr ""
msgid "BillingPlans|Please contact %{customer_support_link} in that case."
msgstr ""
msgid "BillingPlans|Pricing page" msgid "BillingPlans|Pricing page"
msgstr "" msgstr ""
...@@ -2293,6 +2281,9 @@ msgstr "" ...@@ -2293,6 +2281,9 @@ msgstr ""
msgid "BillingPlans|per user" msgid "BillingPlans|per user"
msgstr "" msgstr ""
msgid "BillingPlan|Upgrade plan"
msgstr ""
msgid "Bitbucket Server Import" msgid "Bitbucket Server Import"
msgstr "" msgstr ""
......
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