demo-orgs: Disable billing and upgrade for demo organizations.

Disables submit buttons on billing / upgrade page for demo
organizations since they will need to become permanent
organizations before upgrading to Zulip Cloud Standard.

Also creates an alert banner on the same page that links to
the help center article on demo organizations.

Updates sub-headers on demo organizations help center
article to match link text and to follow general convention
of using imperative verb forms in help center subheaders.

Part of #19523.

Co-authored by: Lauryn Menard <lauryn@zulip.com>
This commit is contained in:
Eeshan Garg 2021-12-27 15:25:38 -05:00 committed by Tim Abbott
parent 8a20884230
commit 5925ce16b1
6 changed files with 83 additions and 8 deletions

View File

@ -2329,6 +2329,15 @@ class StripeTest(StripeTestCase):
self.assertEqual(response.status_code, 302) self.assertEqual(response.status_code, 302)
self.assertEqual("/upgrade/", response["Location"]) self.assertEqual("/upgrade/", response["Location"])
def test_upgrade_page_for_demo_organizations(self) -> None:
user = self.example_user("iago")
user.realm.demo_organization_scheduled_deletion_date = timezone_now() + timedelta(days=30)
user.realm.save()
self.login_user(user)
response = self.client_get("/billing/", follow=True)
self.assert_in_success_response(["cannot be upgraded"], response)
def test_redirect_for_upgrade_page(self) -> None: def test_redirect_for_upgrade_page(self) -> None:
user = self.example_user("iago") user = self.example_user("iago")
self.login_user(user) self.login_user(user)

View File

@ -276,6 +276,7 @@ def initial_upgrade(
"annual_price": 8000, "annual_price": 8000,
"monthly_price": 800, "monthly_price": 800,
"percent_off": float(percent_off), "percent_off": float(percent_off),
"demo_organization_scheduled_deletion_date": user.realm.demo_organization_scheduled_deletion_date,
}, },
"realm_org_type": user.realm.org_type, "realm_org_type": user.realm.org_type,
"sorted_org_types": sorted( "sorted_org_types": sorted(
@ -286,6 +287,7 @@ def initial_upgrade(
), ),
key=lambda d: d[1]["display_order"], key=lambda d: d[1]["display_order"],
), ),
"is_demo_organization": user.realm.demo_organization_scheduled_deletion_date is not None,
} }
response = render(request, "corporate/upgrade.html", context=context) response = render(request, "corporate/upgrade.html", context=context)
return response return response

View File

@ -177,6 +177,19 @@
.invoice-button { .invoice-button {
font-size: 19px; font-size: 19px;
&:disabled {
opacity: 0.5;
cursor: not-allowed;
&:hover {
pointer-events: all;
}
}
}
.upgrade-button-container {
display: inline-block;
} }
#manual_license_count, #manual_license_count,

View File

@ -401,6 +401,33 @@ html {
font-weight: 400; font-weight: 400;
} }
.demo-organization-warning {
position: relative;
display: block;
background-color: hsl(360, 100%, 93%);
border: 1px solid hsl(0, 0%, 80%);
border-radius: 4px;
padding: 10px;
margin: 10px 0;
font-size: 1rem;
font-weight: 500;
line-height: 1.5;
color: hsl(0, 0%, 27%);
a {
text-decoration: none;
}
&::before {
display: inline;
margin-right: 8px;
font-family: FontAwesome;
font-weight: 600;
content: "\f071";
}
}
.alert { .alert {
&:not(.alert-info) { &:not(.alert-info) {
padding: 0; padding: 0;

View File

@ -24,6 +24,16 @@
</div> </div>
{% endif %} {% endif %}
{% if is_demo_organization %}
<div class="demo-organization-warning">
Demo organizations cannot be directly upgraded to a paid plan. Please start by
<a href="/help/demo-organizations#convert-a-demo-organization-to-a-permanent-organization">
converting your demo organization
</a>
to a permanent organization.
</div>
{% endif %}
{% if error_message %} {% if error_message %}
<div class="alert alert-danger" id="upgrade-error-message-box"> <div class="alert alert-danger" id="upgrade-error-message-box">
{{ error_message }} {{ error_message }}
@ -140,10 +150,14 @@
<h4>Number of licenses (minimum {{ seat_count }})</h4> <h4>Number of licenses (minimum {{ seat_count }})</h4>
<input type="number" name="licenses" min="{{ seat_count }}" autocomplete="off" id="manual_license_count" required/><br /> <input type="number" name="licenses" min="{{ seat_count }}" autocomplete="off" id="manual_license_count" required/><br />
</div> </div>
<!-- Disabled buttons do not fire any events, so we need a container div that isn't disabled for tippyjs to work -->
<button id="add-card-button" class="stripe-button-el invoice-button"> <div class="upgrade-button-container" {% if is_demo_organization %}data-tippy-content="{% trans %}Convert demo organization before upgrading.{% endtrans %}"{% endif %}>
<span id="add-card-button-span">Add card</span> <button id="add-card-button" class="stripe-button-el invoice-button" {% if is_demo_organization %}disabled{% endif %}>
</button> <span id="add-card-button-span">
Add card
</span>
</button>
</div>
</form> </form>
</div> </div>
<div id="autopay-loading"> <div id="autopay-loading">
@ -201,7 +215,12 @@
<h4>Number of licenses (minimum {{ min_invoiced_licenses }})</h4> <h4>Number of licenses (minimum {{ min_invoiced_licenses }})</h4>
<input type="number" min="{{ min_invoiced_licenses }}" autocomplete="off" <input type="number" min="{{ min_invoiced_licenses }}" autocomplete="off"
id="invoiced_licenses" name="licenses" required/><br /> id="invoiced_licenses" name="licenses" required/><br />
<button type="submit" id="invoice-button" class="stripe-button-el invoice-button">Buy Standard</button> <!-- Disabled buttons do not fire any events, so we need a container div that isn't disabled for tippyjs to work -->
<div class="upgrade-button-container" {% if is_demo_organization %}data-tippy-content="{% trans %}Convert demo organization before upgrading.{% endtrans %}"{% endif %}>
<button type="submit" id="invoice-button" class="stripe-button-el invoice-button" {% if is_demo_organization %}disabled{% endif %}>
Buy Standard
</button>
</div>
</form> </form>
</div> </div>
<div id="invoice-loading"> <div id="invoice-loading">
@ -247,7 +266,12 @@
<textarea name="description" style="width: 100%;" cols="100" rows="5" required></textarea> <textarea name="description" style="width: 100%;" cols="100" rows="5" required></textarea>
<br /> <br />
<p id="sponsorship-discount-details"></p> <p id="sponsorship-discount-details"></p>
<button type="submit" id="sponsorship-button" class="stripe-button-el invoice-button">Submit</button> <!-- Disabled buttons do not fire any events, so we need a container div that isn't disabled for tippyjs to work -->
<div class="upgrade-button-container" {% if is_demo_organization %}data-tippy-content="{% trans %}Convert demo organization before upgrading.{% endtrans %}"{% endif %}>
<button type="submit" id="sponsorship-button" class="stripe-button-el invoice-button" {% if is_demo_organization %}disabled{% endif %}>
Submit
</button>
</div>
</form> </form>
</div> </div>
<div id="sponsorship-loading"> <div id="sponsorship-loading">

View File

@ -25,7 +25,7 @@ Other than those limitations, they work exactly like a normal Zulip
organization; you can invite additional users, connect the mobile organization; you can invite additional users, connect the mobile
apps, etc. apps, etc.
## Creating demo organizations ## Create a demo organization
{start_tabs} {start_tabs}
@ -39,7 +39,7 @@ apps, etc.
{end_tabs} {end_tabs}
## Converting a demo organization to a regular organization ## Convert a demo organization to a permanent organization
{start_tabs} {start_tabs}