mirror of https://github.com/zulip/zulip.git
free trial: Send users to /upgrade after realm creation.
This commit is contained in:
parent
a5f0379e0f
commit
8784539d53
Binary file not shown.
|
@ -625,6 +625,11 @@ class StripeTest(StripeTestCase):
|
|||
'Visa ending in 4242',
|
||||
'Update card']:
|
||||
self.assert_in_response(substring, response)
|
||||
self.assert_not_in_success_response(["Go to your Zulip organization"], response)
|
||||
|
||||
with patch('corporate.views.timezone_now', return_value=self.now):
|
||||
response = self.client_get("/billing/?onboarding=true")
|
||||
self.assert_in_success_response(["Go to your Zulip organization"], response)
|
||||
|
||||
with patch('corporate.lib.stripe.get_latest_seat_count', return_value=12):
|
||||
update_license_ledger_if_needed(realm, self.now)
|
||||
|
@ -1053,6 +1058,33 @@ class StripeTest(StripeTestCase):
|
|||
self.assertEqual(response.status_code, 302)
|
||||
self.assertEqual('/upgrade/', response.url)
|
||||
|
||||
def test_redirect_for_upgrade_page(self) -> None:
|
||||
user = self.example_user("iago")
|
||||
self.login_user(user)
|
||||
# No Customer yet;
|
||||
response = self.client_get("/upgrade/")
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# Customer, but no CustomerPlan;
|
||||
customer = Customer.objects.create(realm=user.realm, stripe_customer_id='cus_123')
|
||||
response = self.client_get("/upgrade/")
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
CustomerPlan.objects.create(customer=customer, billing_cycle_anchor=timezone_now(),
|
||||
billing_schedule=CustomerPlan.ANNUAL, tier=CustomerPlan.STANDARD)
|
||||
response = self.client_get("/upgrade/")
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertEqual(response.url, "/billing/")
|
||||
|
||||
with self.settings(FREE_TRIAL_DAYS=30):
|
||||
response = self.client_get("/upgrade/")
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertEqual(response.url, "/billing/")
|
||||
|
||||
response = self.client_get("/upgrade/?onboarding=true")
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertEqual(response.url, "/billing/?onboarding=true")
|
||||
|
||||
def test_get_latest_seat_count(self) -> None:
|
||||
realm = get_realm("zulip")
|
||||
initial_count = get_latest_seat_count(realm)
|
||||
|
|
|
@ -129,7 +129,10 @@ def initial_upgrade(request: HttpRequest) -> HttpResponse:
|
|||
user = request.user
|
||||
customer = get_customer_by_realm(user.realm)
|
||||
if customer is not None and get_current_plan_by_customer(customer) is not None:
|
||||
return HttpResponseRedirect(reverse('corporate.views.billing_home'))
|
||||
billing_page_url = reverse('corporate.views.billing_home')
|
||||
if request.GET.get("onboarding") is not None:
|
||||
billing_page_url = "{}?onboarding=true".format(billing_page_url)
|
||||
return HttpResponseRedirect(billing_page_url)
|
||||
|
||||
percent_off = Decimal(0)
|
||||
if customer is not None and customer.default_discount is not None:
|
||||
|
@ -147,6 +150,7 @@ def initial_upgrade(request: HttpRequest) -> HttpResponse:
|
|||
'default_invoice_days_until_due': DEFAULT_INVOICE_DAYS_UNTIL_DUE,
|
||||
'plan': "Zulip Standard",
|
||||
"free_trial_days": settings.FREE_TRIAL_DAYS,
|
||||
"onboarding": request.GET.get("onboarding") is not None,
|
||||
'page_params': {
|
||||
'seat_count': seat_count,
|
||||
'annual_price': 8000,
|
||||
|
@ -212,6 +216,7 @@ def billing_home(request: HttpRequest) -> HttpResponse:
|
|||
'publishable_key': STRIPE_PUBLISHABLE_KEY,
|
||||
'stripe_email': stripe_customer.email,
|
||||
'CustomerPlan': CustomerPlan,
|
||||
'onboarding': request.GET.get("onboarding") is not None,
|
||||
})
|
||||
|
||||
return render(request, 'corporate/billing.html', context=context)
|
||||
|
|
|
@ -25,6 +25,7 @@ run_test('create_ajax_request', () => {
|
|||
const form_success = "#autopay-success";
|
||||
const form_error = "#autopay-error";
|
||||
const form_loading = "#autopay-loading";
|
||||
const zulip_limited_section = "#zulip-limited-section";
|
||||
|
||||
const state = {
|
||||
form_input_section_show: 0,
|
||||
|
@ -34,6 +35,8 @@ run_test('create_ajax_request', () => {
|
|||
form_loading_show: 0,
|
||||
form_loading_hide: 0,
|
||||
form_success_show: 0,
|
||||
zulip_limited_section_show: 0,
|
||||
zulip_limited_section_hide: 0,
|
||||
location_reload: 0,
|
||||
pushState: 0,
|
||||
make_indicator: 0,
|
||||
|
@ -79,6 +82,14 @@ run_test('create_ajax_request', () => {
|
|||
state.form_loading_hide += 1;
|
||||
};
|
||||
|
||||
$(zulip_limited_section).show = () => {
|
||||
state.zulip_limited_section_show += 1;
|
||||
};
|
||||
|
||||
$(zulip_limited_section).hide = () => {
|
||||
state.zulip_limited_section_hide += 1;
|
||||
};
|
||||
|
||||
$("#autopay-form").serializeArray = () => {
|
||||
return jquery("#autopay-form").serializeArray();
|
||||
};
|
||||
|
@ -87,6 +98,8 @@ run_test('create_ajax_request', () => {
|
|||
assert.equal(state.form_input_section_hide, 1);
|
||||
assert.equal(state.form_error_hide, 1);
|
||||
assert.equal(state.form_loading_show, 1);
|
||||
assert.equal(state.zulip_limited_section_hide, 1);
|
||||
assert.equal(state.zulip_limited_section_show, 0);
|
||||
assert.equal(state.make_indicator, 1);
|
||||
|
||||
assert.equal(url, "/json/billing/upgrade");
|
||||
|
@ -119,12 +132,15 @@ run_test('create_ajax_request', () => {
|
|||
assert.equal(state.form_success_show, 1);
|
||||
assert.equal(state.form_error_hide, 2);
|
||||
assert.equal(state.form_loading_hide, 1);
|
||||
assert.equal(state.zulip_limited_section_hide, 1);
|
||||
assert.equal(state.zulip_limited_section_show, 0);
|
||||
|
||||
error({responseText: '{"msg": "response_message"}'});
|
||||
|
||||
assert.equal(state.form_loading_hide, 2);
|
||||
assert.equal(state.form_error_show, 1);
|
||||
assert.equal(state.form_input_section_show, 1);
|
||||
assert.equal(state.zulip_limited_section_hide, 1);
|
||||
};
|
||||
|
||||
helpers.create_ajax_request("/json/billing/upgrade", "autopay", {id: "stripe_token_id"}, ["licenses"]);
|
||||
|
|
|
@ -102,6 +102,7 @@ run_test("initialize", () => {
|
|||
helpers.is_valid_input = () => {
|
||||
return true;
|
||||
};
|
||||
|
||||
add_card_click_handler(e);
|
||||
invoice_click_handler(e);
|
||||
|
||||
|
@ -159,6 +160,8 @@ run_test("autopay_form_fields", () => {
|
|||
assert(document.querySelector("#autopay_loading_indicator"));
|
||||
|
||||
assert(document.querySelector("input[name=csrfmiddlewaretoken]"));
|
||||
|
||||
assert(document.querySelector("#zulip-limited-section"));
|
||||
});
|
||||
|
||||
run_test("invoice_form_fields", () => {
|
||||
|
@ -178,4 +181,6 @@ run_test("invoice_form_fields", () => {
|
|||
assert(document.querySelector("#invoice_loading_indicator"));
|
||||
|
||||
assert(document.querySelector("input[name=csrfmiddlewaretoken]"));
|
||||
|
||||
assert(document.querySelector("#zulip-limited-section"));
|
||||
});
|
||||
|
|
|
@ -6,11 +6,16 @@ exports.create_ajax_request = function (url, form_name, stripe_token = null, num
|
|||
const form_error = "#" + form_name + "-error";
|
||||
const form_loading = "#" + form_name + "-loading";
|
||||
|
||||
const zulip_limited_section = "#zulip-limited-section";
|
||||
const free_trial_alert_message = "#free-trial-alert-message";
|
||||
|
||||
loading.make_indicator($(form_loading_indicator),
|
||||
{text: 'Processing ...', abs_positioned: true});
|
||||
$(form_input_section).hide();
|
||||
$(form_error).hide();
|
||||
$(form_loading).show();
|
||||
$(zulip_limited_section).hide();
|
||||
$(free_trial_alert_message).hide();
|
||||
|
||||
const data = {};
|
||||
if (stripe_token) {
|
||||
|
@ -45,6 +50,8 @@ exports.create_ajax_request = function (url, form_name, stripe_token = null, num
|
|||
$(form_loading).hide();
|
||||
$(form_error).show().text(JSON.parse(xhr.responseText).msg);
|
||||
$(form_input_section).show();
|
||||
$(zulip_limited_section).show();
|
||||
$(free_trial_alert_message).show();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
|
@ -124,6 +124,15 @@
|
|||
<div class="tab-pane" id="loading">
|
||||
</div>
|
||||
</div>
|
||||
<div id="goto-zulip-organization-link">
|
||||
{% if onboarding %}
|
||||
<br>
|
||||
<h3>
|
||||
<b><a href="/">Go to your Zulip organization</a></b>
|
||||
</h3>
|
||||
{% endif %}
|
||||
</div>
|
||||
<hr>
|
||||
<div class="support-link">
|
||||
<p>
|
||||
Contact <a href="mailto:support@zulipchat.com">support@zulipchat.com</a>
|
||||
|
|
|
@ -207,6 +207,15 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if onboarding %}
|
||||
<div id="zulip-limited-section">
|
||||
<br>
|
||||
<h3>
|
||||
<b><a href="/">Or start with Zulip Limited (Free) plan</a></b>
|
||||
</h3>
|
||||
</div>
|
||||
{% endif %}
|
||||
<hr>
|
||||
<div class="support-link">
|
||||
<p>
|
||||
We're happy to help!
|
||||
|
|
|
@ -2150,6 +2150,10 @@ class RealmCreationTest(ZulipTestCase):
|
|||
HTTP_HOST=string_id + ".testserver")
|
||||
self.assertEqual(result.status_code, 302)
|
||||
|
||||
result = self.client_get(result.url, subdomain=string_id)
|
||||
self.assertEqual(result.status_code, 302)
|
||||
self.assertEqual(result.url, 'http://zuliptest.testserver')
|
||||
|
||||
# Make sure the realm is created
|
||||
realm = get_realm(string_id)
|
||||
self.assertEqual(realm.string_id, string_id)
|
||||
|
@ -2158,6 +2162,46 @@ class RealmCreationTest(ZulipTestCase):
|
|||
self.assertEqual(realm.name, realm_name)
|
||||
self.assertEqual(realm.subdomain, string_id)
|
||||
|
||||
@override_settings(OPEN_REALM_CREATION=True, FREE_TRIAL_DAYS=30)
|
||||
def test_create_realm_during_free_trial(self) -> None:
|
||||
password = "test"
|
||||
string_id = "zuliptest"
|
||||
email = "user1@test.com"
|
||||
realm_name = "Test"
|
||||
|
||||
with self.assertRaises(Realm.DoesNotExist):
|
||||
get_realm(string_id)
|
||||
|
||||
result = self.client_post('/new/', {'email': email})
|
||||
self.assertEqual(result.status_code, 302)
|
||||
self.assertTrue(result["Location"].endswith(
|
||||
"/accounts/new/send_confirm/%s" % (email,)))
|
||||
result = self.client_get(result["Location"])
|
||||
self.assert_in_response("Check your email so we can get started.", result)
|
||||
|
||||
confirmation_url = self.get_confirmation_url_from_outbox(email)
|
||||
result = self.client_get(confirmation_url)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
result = self.submit_reg_form_for_user(email, password,
|
||||
realm_subdomain = string_id,
|
||||
realm_name=realm_name,
|
||||
HTTP_HOST=string_id + ".testserver")
|
||||
self.assertEqual(result.status_code, 302)
|
||||
|
||||
result = self.client_get(result.url, subdomain=string_id)
|
||||
self.assertEqual(result.url, 'http://zuliptest.testserver/upgrade/?onboarding=true')
|
||||
|
||||
result = self.client_get(result.url, subdomain=string_id)
|
||||
self.assert_in_success_response(["Or start with Zulip Limited (Free) plan"], result)
|
||||
|
||||
realm = get_realm(string_id)
|
||||
self.assertEqual(realm.string_id, string_id)
|
||||
self.assertEqual(get_user(email, realm).realm, realm)
|
||||
|
||||
self.assertEqual(realm.name, realm_name)
|
||||
self.assertEqual(realm.subdomain, string_id)
|
||||
|
||||
@override_settings(OPEN_REALM_CREATION=True)
|
||||
def test_mailinator_signup(self) -> None:
|
||||
result = self.client_post('/new/', {'email': "hi@mailinator.com"})
|
||||
|
|
|
@ -218,6 +218,7 @@ def register_remote_user(request: HttpRequest, result: ExternalAuthResult) -> Ht
|
|||
# maybe_send_to_registration doesn't take these arguments, so delete them.
|
||||
kwargs.pop('subdomain', None)
|
||||
kwargs.pop('redirect_to', None)
|
||||
kwargs.pop('is_realm_creation', None)
|
||||
|
||||
kwargs["password_required"] = False
|
||||
return maybe_send_to_registration(request, **kwargs)
|
||||
|
@ -247,6 +248,7 @@ def login_or_register_remote_user(request: HttpRequest, result: ExternalAuthResu
|
|||
# Otherwise, the user has successfully authenticated to an
|
||||
# account, and we need to do the right thing depending whether
|
||||
# or not they're using the mobile OTP flow or want a browser session.
|
||||
is_realm_creation = result.data_dict.get('is_realm_creation')
|
||||
mobile_flow_otp = result.data_dict.get('mobile_flow_otp')
|
||||
desktop_flow_otp = result.data_dict.get('desktop_flow_otp')
|
||||
if mobile_flow_otp is not None:
|
||||
|
@ -256,7 +258,11 @@ def login_or_register_remote_user(request: HttpRequest, result: ExternalAuthResu
|
|||
|
||||
do_login(request, user_profile)
|
||||
|
||||
redirect_to = get_safe_redirect_to(result.data_dict.get('redirect_to', ''), user_profile.realm.uri)
|
||||
redirect_to = result.data_dict.get('redirect_to', '')
|
||||
if is_realm_creation is not None and settings.FREE_TRIAL_DAYS not in [None, 0]:
|
||||
redirect_to = "{}?onboarding=true".format(reverse('corporate.views.initial_upgrade'))
|
||||
|
||||
redirect_to = get_safe_redirect_to(redirect_to, user_profile.realm.uri)
|
||||
return HttpResponseRedirect(redirect_to)
|
||||
|
||||
def finish_desktop_flow(request: HttpRequest, user_profile: UserProfile,
|
||||
|
|
|
@ -343,7 +343,8 @@ def accounts_register(request: HttpRequest) -> HttpResponse:
|
|||
# Because for realm creation, registration happens on the
|
||||
# root domain, we need to log them into the subdomain for
|
||||
# their new realm.
|
||||
return redirect_and_log_into_subdomain(ExternalAuthResult(user_profile=user_profile))
|
||||
return redirect_and_log_into_subdomain(ExternalAuthResult(user_profile=user_profile,
|
||||
data_dict={'is_realm_creation': True}))
|
||||
|
||||
# This dummy_backend check below confirms the user is
|
||||
# authenticating to the correct subdomain.
|
||||
|
|
|
@ -920,6 +920,7 @@ ExternalAuthDataDict = TypedDict('ExternalAuthDataDict', {
|
|||
'full_name': str,
|
||||
'email': str,
|
||||
'is_signup': bool,
|
||||
'is_realm_creation': bool,
|
||||
'redirect_to': str,
|
||||
'mobile_flow_otp': Optional[str],
|
||||
'desktop_flow_otp': Optional[str],
|
||||
|
|
Loading…
Reference in New Issue