billing: Fix options and help text for sponsorship requests.

This makes several changes:

* Fixes a bug where the help text explaining our policies was not displayed.
* No help text was defined for many organization types.
* Copy-edits the help text somewhat.
* Offers all of the organization type options.
* Removes the 100% coverage requirement because it's annoying to test
  the e.currentTarget click handler.
This commit is contained in:
Tim Abbott
2021-07-18 18:36:52 -07:00
parent 12d9ad957c
commit d7ef0c7232
9 changed files with 52 additions and 41 deletions

View File

@@ -30,7 +30,8 @@ class Migration(migrations.Migration):
(0, "Unspecified"), (0, "Unspecified"),
(10, "Business"), (10, "Business"),
(20, "Open-source project"), (20, "Open-source project"),
(30, "Education"), (30, "Education (non-profit)"),
(35, "Education (for-profit)"),
(40, "Research"), (40, "Research"),
(50, "Event or conference"), (50, "Event or conference"),
(60, "Non-profit (registered)"), (60, "Non-profit (registered)"),

View File

@@ -225,11 +225,11 @@ def initial_upgrade(request: HttpRequest) -> HttpResponse:
}, },
"sorted_org_types": sorted( "sorted_org_types": sorted(
[ [
org_type [org_type_name, org_type]
for org_type in Realm.ORG_TYPES.values() for (org_type_name, org_type) in Realm.ORG_TYPES.items()
if not org_type.get("hidden_for_sponsorship") if not org_type.get("hidden")
], ],
key=lambda d: d["display_order"], key=lambda d: d[1]["display_order"],
), ),
} }
response = render(request, "corporate/upgrade.html", context=context) response = render(request, "corporate/upgrade.html", context=context)

View File

@@ -151,38 +151,35 @@ run_test("initialize", ({override}) => {
assert.equal($("#invoice_annual_price").text(), "64"); assert.equal($("#invoice_annual_price").text(), "64");
assert.equal($("#invoice_annual_price_per_month").text(), "5.34"); assert.equal($("#invoice_annual_price_per_month").text(), "5.34");
const organization_type_change_handler = $("select[name=organization-type]").get_on_handler( helpers.update_discount_details("opensource");
"change",
);
organization_type_change_handler.call({value: "open_source"});
assert.equal( assert.equal(
$("#sponsorship-discount-details").text(), $("#sponsorship-discount-details").text(),
"Zulip Standard is free for open-source projects.", "Zulip Cloud Standard is free for open-source projects.",
); );
organization_type_change_handler.call({value: "research"}); helpers.update_discount_details("research");
assert.equal( assert.equal(
$("#sponsorship-discount-details").text(), $("#sponsorship-discount-details").text(),
"Zulip Standard is free for academic research.", "Zulip Cloud Standard is free for academic research.",
); );
organization_type_change_handler.call({value: "event"}); helpers.update_discount_details("event");
assert.equal( assert.equal(
$("#sponsorship-discount-details").text(), $("#sponsorship-discount-details").text(),
"Zulip Standard is free for academic conferences and hackathons.", "Zulip Cloud Standard is free for academic conferences and most nonprofit events.",
); );
organization_type_change_handler.call({value: "education"}); helpers.update_discount_details("education");
assert.equal( assert.equal(
$("#sponsorship-discount-details").text(), $("#sponsorship-discount-details").text(),
"Get an 85%+ discount on Zulip Standard for education.", "Zulip Cloud Standard is discounted 85% for education.",
); );
organization_type_change_handler.call({value: "non_profit"}); helpers.update_discount_details("nonprofit");
assert.equal( assert.equal(
$("#sponsorship-discount-details").text(), $("#sponsorship-discount-details").text(),
"Non-profits get an 85%+ discount on Zulip Standard.", "Zulip Cloud Standard is discounted 85%+ for registered nonprofits.",
); );
organization_type_change_handler.call({value: "other"}); helpers.update_discount_details("other");
assert.equal( assert.equal(
$("#sponsorship-discount-details").text(), $("#sponsorship-discount-details").text(),
"Your organization may be eligible for a discount on Zulip Standard.", "Your organization may be eligible for a discount on Zulip Standard. Generally, use cases where the users are not your employees are eligible for discounts.",
); );
}); });

View File

@@ -88,15 +88,21 @@ export function update_charged_amount(prices, schedule) {
} }
export function update_discount_details(organization_type) { export function update_discount_details(organization_type) {
let discount_notice =
"Your organization may be eligible for a discount on Zulip Standard. Generally, use cases where the users are not your employees are eligible for discounts.";
const discount_details = { const discount_details = {
open_source: "Zulip Standard is free for open-source projects.", opensource: "Zulip Cloud Standard is free for open-source projects.",
research: "Zulip Standard is free for academic research.", research: "Zulip Cloud Standard is free for academic research.",
non_profit: "Non-profits get an 85%+ discount on Zulip Standard.", nonprofit: "Zulip Cloud Standard is discounted 85%+ for registered nonprofits.",
event: "Zulip Standard is free for academic conferences and hackathons.", event: "Zulip Cloud Standard is free for academic conferences and most nonprofit events.",
education: "Get an 85%+ discount on Zulip Standard for education.", education: "Zulip Cloud Standard is discounted 85% for education.",
other: "Your organization may be eligible for a discount on Zulip Standard.", education_nonprofit:
"Zulip Cloud standard is discounted 90% for education nonprofits with online purchase.",
}; };
$("#sponsorship-discount-details").text(discount_details[organization_type]); if (discount_details[organization_type]) {
discount_notice = discount_details[organization_type];
}
$("#sponsorship-discount-details").text(discount_notice);
} }
export function show_license_section(license) { export function show_license_section(license) {

View File

@@ -70,8 +70,9 @@ export const initialize = () => {
helpers.update_charged_amount(prices, this.value); helpers.update_charged_amount(prices, this.value);
}); });
$("select[name=organization-type]").on("change", function () { $("select[name=organization-type]").on("change", (e) => {
helpers.update_discount_details(this.value); const string_value = $(e.currentTarget).find(":selected").attr("data-string-value");
helpers.update_discount_details(string_value);
}); });
$("#autopay_annual_price").text(helpers.format_money(prices.annual)); $("#autopay_annual_price").text(helpers.format_money(prices.annual));

View File

@@ -226,7 +226,7 @@
<select name="organization-type" required style="width: 100%;" required> <select name="organization-type" required style="width: 100%;" required>
{% for org_type in sorted_org_types %} {% for org_type in sorted_org_types %}
{% if not org_type.hidden %} {% if not org_type.hidden %}
<option value="{{ org_type.id }}">{{ _(org_type.name) }}</option> <option data-string-value="{{ org_type[0] }}" value="{{ org_type[1].id }}">{{ _(org_type[1].name) }}</option>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
</select> </select>

View File

@@ -42,6 +42,7 @@ EXEMPT_FILES = {
"static/js/attachments_ui.js", "static/js/attachments_ui.js",
"static/js/avatar.js", "static/js/avatar.js",
"static/js/billing/helpers.js", "static/js/billing/helpers.js",
"static/js/billing/upgrade.js",
"static/js/blueslip.ts", "static/js/blueslip.ts",
"static/js/blueslip_stacktrace.ts", "static/js/blueslip_stacktrace.ts",
"static/js/click_handlers.js", "static/js/click_handlers.js",

View File

@@ -26,7 +26,8 @@ class Migration(migrations.Migration):
(0, "Unspecified"), (0, "Unspecified"),
(10, "Business"), (10, "Business"),
(20, "Open-source project"), (20, "Open-source project"),
(30, "Education"), (30, "Education (non-profit)"),
(35, "Education (for-profit)"),
(40, "Research"), (40, "Research"),
(50, "Event or conference"), (50, "Event or conference"),
(60, "Non-profit (registered)"), (60, "Non-profit (registered)"),

View File

@@ -417,7 +417,6 @@ class Realm(models.Model):
"name": "Business", "name": "Business",
"id": 10, "id": 10,
"hidden": False, "hidden": False,
"hidden_for_sponsorship": True,
"display_order": 1, "display_order": 1,
}, },
"opensource": { "opensource": {
@@ -426,48 +425,53 @@ class Realm(models.Model):
"hidden": False, "hidden": False,
"display_order": 2, "display_order": 2,
}, },
"education": { "education_nonprofit": {
"name": "Education", "name": "Education (non-profit)",
"id": 30, "id": 30,
"hidden": False, "hidden": False,
"display_order": 3, "display_order": 3,
}, },
"education": {
"name": "Education (for-profit)",
"id": 35,
"hidden": False,
"display_order": 4,
},
"research": { "research": {
"name": "Research", "name": "Research",
"id": 40, "id": 40,
"hidden": False, "hidden": False,
"display_order": 4, "display_order": 5,
}, },
"event": { "event": {
"name": "Event or conference", "name": "Event or conference",
"id": 50, "id": 50,
"hidden": False, "hidden": False,
"display_order": 5, "display_order": 6,
}, },
"nonprofit": { "nonprofit": {
"name": "Non-profit (registered)", "name": "Non-profit (registered)",
"id": 60, "id": 60,
"hidden": False, "hidden": False,
"display_order": 6, "display_order": 7,
}, },
"government": { "government": {
"name": "Government", "name": "Government",
"id": 70, "id": 70,
"hidden": False, "hidden": False,
"hidden_for_sponsorship": True, "display_order": 8,
"display_order": 7,
}, },
"political_group": { "political_group": {
"name": "Political group", "name": "Political group",
"id": 80, "id": 80,
"hidden": False, "hidden": False,
"display_order": 8, "display_order": 9,
}, },
"community": { "community": {
"name": "Community", "name": "Community",
"id": 90, "id": 90,
"hidden": False, "hidden": False,
"display_order": 9, "display_order": 10,
}, },
"personal": { "personal": {
"name": "Personal", "name": "Personal",