diff --git a/corporate/views.py b/corporate/views.py index edf2cb9ea9..67775e274f 100644 --- a/corporate/views.py +++ b/corporate/views.py @@ -185,6 +185,7 @@ def billing_home(request: HttpRequest) -> HttpResponse: CustomerPlan.PLUS: 'Zulip Plus', }[plan.tier] free_trial = plan.status == CustomerPlan.FREE_TRIAL + downgrade_at_end_of_cycle = plan.status == CustomerPlan.DOWNGRADE_AT_END_OF_CYCLE licenses = last_ledger_entry.licenses licenses_used = get_latest_seat_count(user.realm) # Should do this in javascript, using the user's timezone @@ -201,6 +202,7 @@ def billing_home(request: HttpRequest) -> HttpResponse: 'plan_name': plan_name, 'has_active_plan': True, 'free_trial': free_trial, + 'downgrade_at_end_of_cycle': downgrade_at_end_of_cycle, 'licenses': licenses, 'licenses_used': licenses_used, 'renewal_date': renewal_date, @@ -209,6 +211,7 @@ def billing_home(request: HttpRequest) -> HttpResponse: 'charge_automatically': charge_automatically, 'publishable_key': STRIPE_PUBLISHABLE_KEY, 'stripe_email': stripe_customer.email, + 'CustomerPlan': CustomerPlan, }) return render(request, 'corporate/billing.html', context=context) diff --git a/frontend_tests/node_tests/billing.js b/frontend_tests/node_tests/billing.js index ea852b15e8..f7e149aff3 100644 --- a/frontend_tests/node_tests/billing.js +++ b/frontend_tests/node_tests/billing.js @@ -20,16 +20,22 @@ set_global('$', global.make_zjquery()); run_test("initialize", () => { let token_func; + + let set_tab_called = false; helpers.set_tab = (page_name) => { assert.equal(page_name, "billing"); + set_tab_called = true; }; + let create_ajax_request_called = false; helpers.create_ajax_request = (url, form_name, stripe_token) => { assert.equal(url, "/json/billing/sources/change"); assert.equal(form_name, "cardchange"); assert.equal(stripe_token, "stripe_token"); + create_ajax_request_called = true; }; + let open_func_called = false; const open_func = (config_opts) => { assert.equal(config_opts.name, "Zulip"); assert.equal(config_opts.zipCode, true); @@ -40,13 +46,16 @@ run_test("initialize", () => { assert.equal(config_opts.email, "{{stripe_email}}"); token_func("stripe_token"); + open_func_called = true; }; + let stripe_checkout_configure_called = false; StripeCheckout.configure = (config_opts) => { assert.equal(config_opts.image, '/static/images/logo/zulip-icon-128x128.png'); assert.equal(config_opts.locale, 'auto'); assert.equal(config_opts.key, '{{publishable_key}}'); token_func = config_opts.token; + stripe_checkout_configure_called = true; return { open: open_func, @@ -59,11 +68,28 @@ run_test("initialize", () => { jquery_init(); + assert(set_tab_called); + assert(stripe_checkout_configure_called); const e = { preventDefault: noop, }; - const click_handler = $('#update-card-button').get_on_handler('click'); - click_handler(e); + const update_card_click_handler = $('#update-card-button').get_on_handler('click'); + update_card_click_handler(e); + assert(create_ajax_request_called); + assert(open_func_called); + + create_ajax_request_called = false; + helpers.create_ajax_request = (url, form_name, stripe_token, numeric_inputs) => { + assert.equal(url, "/json/billing/plan/change"); + assert.equal(form_name, "planchange"); + assert.equal(stripe_token, undefined); + assert.deepEqual(numeric_inputs, ["status"]); + create_ajax_request_called = true; + }; + + const change_plan_status_click_handler = $('#change-plan-status').get_on_handler('click'); + change_plan_status_click_handler(e); + assert(create_ajax_request_called); }); run_test("billing_template", () => { diff --git a/static/js/billing/billing.js b/static/js/billing/billing.js index 15e1978ae6..cf3cbf8bdc 100644 --- a/static/js/billing/billing.js +++ b/static/js/billing/billing.js @@ -24,6 +24,11 @@ exports.initialize = function () { }); e.preventDefault(); }); + + $("#change-plan-status").on('click', function (e) { + helpers.create_ajax_request("/json/billing/plan/change", "planchange", undefined, ["status"]); + e.preventDefault(); + }); }; window.billing = exports; diff --git a/static/styles/portico/billing.scss b/static/styles/portico/billing.scss index 6a16112008..f0e9910931 100644 --- a/static/styles/portico/billing.scss +++ b/static/styles/portico/billing.scss @@ -177,6 +177,7 @@ display: none; } + #planchange-loading, #cardchange-loading, #invoice-loading, #autopay-loading { @@ -186,6 +187,7 @@ } + #planchange-success, #cardchange-success, #invoice-success, #autopay-success { @@ -193,6 +195,7 @@ display: none; } + #planchange-error, #cardchange-error, #invoice-error, #autopay-error { @@ -221,12 +224,14 @@ stroke: hsl(0, 0%, 100%); } + #planchange_loading_indicator, #cardchange_loading_indicator, #invoice_loading_indicator, #autopay_loading_indicator { margin: 10px auto; } + #planchange_loading_indicator_box_container, #cardchange_loading_indicator_box_container, #invoice_loading_indicator_box_container, #autopay_loading_indicator_box_container { @@ -234,6 +239,7 @@ left: 50%; } + #planchange_loading_indicator_box, #cardchange_loading_indicator_box, #invoice_loading_indicator_box, #autopay_loading_indicator_box { @@ -244,6 +250,7 @@ border-radius: 6px; } + #planchange_loading_indicator .loading_indicator_text, #cardchange_loading_indicator .loading_indicator_text, #invoice_loading_indicator .loading_indicator_text, #autopay_loading_indicator .loading_indicator_text { diff --git a/templates/corporate/billing.html b/templates/corporate/billing.html index bf53b58124..485fb14068 100644 --- a/templates/corporate/billing.html +++ b/templates/corporate/billing.html @@ -23,6 +23,7 @@
@@ -39,6 +40,8 @@ {% if free_trial %} Your plan will be upgraded to {{ plan_name }} on {{ renewal_date }} for ${{ renewal_amount }}. + {% elif downgrade_at_end_of_cycle %} + Your plan will be downgraded to Zulip Limited on {{ renewal_date }}. {% else %} Your plan will renew on {{ renewal_date }} for ${{ renewal_amount }}. @@ -75,6 +78,49 @@ Card updated. The page will now reload. +