mirror of
https://github.com/zulip/zulip.git
synced 2026-07-18 21:04:19 +08:00
stripe: Render upgrade page for remote servers on legacy plan.
This commit is contained in:
parent
7d83508235
commit
f22ccd3125
@ -608,6 +608,7 @@ class UpgradePageContext(TypedDict):
|
||||
page_params: UpgradePageParams
|
||||
payment_method: Optional[str]
|
||||
plan: str
|
||||
remote_server_legacy_plan_end_date: Optional[str]
|
||||
salt: str
|
||||
seat_count: int
|
||||
signed_seat_count: str
|
||||
@ -767,6 +768,31 @@ class BillingSession(ABC):
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_remote_server_legacy_plan(
|
||||
self, customer: Optional[Customer], status: int = CustomerPlan.ACTIVE
|
||||
) -> Optional[CustomerPlan]:
|
||||
# status = CustomerPlan.ACTIVE means that the legacy plan is not scheduled for an upgrade.
|
||||
# status = CustomerPlan.SWITCH_PLAN_TIER_AT_PLAN_END means that the legacy plan is scheduled for an upgrade.
|
||||
if customer is None:
|
||||
return None
|
||||
|
||||
return CustomerPlan.objects.filter(
|
||||
customer=customer,
|
||||
tier=CustomerPlan.TIER_SELF_HOSTED_LEGACY,
|
||||
status=status,
|
||||
next_invoice_date=None,
|
||||
).first()
|
||||
|
||||
def get_formatted_remote_server_legacy_plan_end_date(
|
||||
self, customer: Optional[Customer], status: int = CustomerPlan.ACTIVE
|
||||
) -> Optional[str]: # nocoverage
|
||||
plan = self.get_remote_server_legacy_plan(customer, status)
|
||||
if plan is None:
|
||||
return None
|
||||
|
||||
assert plan.end_date is not None
|
||||
return plan.end_date.strftime("%B %d, %Y")
|
||||
|
||||
@catch_stripe_errors
|
||||
def create_stripe_customer(self) -> Customer:
|
||||
stripe_customer_data = self.get_data_for_stripe_customer()
|
||||
@ -1514,9 +1540,14 @@ class BillingSession(ABC):
|
||||
if self.is_sponsored_or_pending(customer):
|
||||
return f"{self.billing_session_url}/sponsorship", None
|
||||
|
||||
billing_page_url = reverse("billing_page")
|
||||
if customer is not None and (get_current_plan_by_customer(customer) is not None):
|
||||
return billing_page_url, None
|
||||
remote_server_legacy_plan_end_date = self.get_formatted_remote_server_legacy_plan_end_date(
|
||||
customer
|
||||
)
|
||||
# Show upgrade page for remote servers on legacy plan.
|
||||
if customer is not None and remote_server_legacy_plan_end_date is None:
|
||||
customer_plan = get_current_plan_by_customer(customer)
|
||||
if customer_plan is not None:
|
||||
return f"{self.billing_session_url}/billing", None
|
||||
|
||||
percent_off = Decimal(0)
|
||||
if customer is not None and customer.default_discount is not None:
|
||||
@ -1540,13 +1571,18 @@ class BillingSession(ABC):
|
||||
signed_seat_count, salt = sign_string(str(seat_count))
|
||||
tier = initial_upgrade_request.tier
|
||||
|
||||
free_trial_days = settings.FREE_TRIAL_DAYS
|
||||
free_trial_days = None
|
||||
free_trial_end_date = None
|
||||
if free_trial_days is not None:
|
||||
_, _, free_trial_end, _ = compute_plan_parameters(
|
||||
tier, False, CustomerPlan.BILLING_SCHEDULE_ANNUAL, None, True
|
||||
)
|
||||
free_trial_end_date = f"{free_trial_end:%B} {free_trial_end.day}, {free_trial_end.year}"
|
||||
# Don't show free trial for remote servers on legacy plan.
|
||||
if remote_server_legacy_plan_end_date is None:
|
||||
free_trial_days = settings.FREE_TRIAL_DAYS
|
||||
if free_trial_days is not None:
|
||||
_, _, free_trial_end, _ = compute_plan_parameters(
|
||||
tier, False, CustomerPlan.BILLING_SCHEDULE_ANNUAL, None, True
|
||||
)
|
||||
free_trial_end_date = (
|
||||
f"{free_trial_end:%B} {free_trial_end.day}, {free_trial_end.year}"
|
||||
)
|
||||
|
||||
context: UpgradePageContext = {
|
||||
"customer_name": customer_specific_context["customer_name"],
|
||||
@ -1557,6 +1593,7 @@ class BillingSession(ABC):
|
||||
"free_trial_days": free_trial_days,
|
||||
"free_trial_end_date": free_trial_end_date,
|
||||
"is_demo_organization": customer_specific_context["is_demo_organization"],
|
||||
"remote_server_legacy_plan_end_date": remote_server_legacy_plan_end_date,
|
||||
"manual_license_management": initial_upgrade_request.manual_license_management,
|
||||
"min_invoiced_licenses": max(seat_count, MIN_INVOICED_LICENSES),
|
||||
"page_params": {
|
||||
|
||||
@ -859,7 +859,7 @@ class StripeTest(StripeTestCase):
|
||||
# Check that we can no longer access /upgrade
|
||||
response = self.client_get("/upgrade/")
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertEqual("/billing/", response["Location"])
|
||||
self.assertEqual("http://zulip.testserver/billing", response["Location"])
|
||||
|
||||
# Check /billing/ has the correct information
|
||||
with time_machine.travel(self.now, tick=False):
|
||||
@ -1007,7 +1007,7 @@ class StripeTest(StripeTestCase):
|
||||
# Check that we can no longer access /upgrade
|
||||
response = self.client_get("/upgrade/")
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertEqual("/billing/", response["Location"])
|
||||
self.assertEqual("http://zulip.testserver/billing", response["Location"])
|
||||
|
||||
# Check /billing/ has the correct information
|
||||
with time_machine.travel(self.now, tick=False):
|
||||
@ -1983,12 +1983,12 @@ class StripeTest(StripeTestCase):
|
||||
)
|
||||
response = self.client_get("/upgrade/")
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertEqual(response["Location"], "/billing/")
|
||||
self.assertEqual(response["Location"], "http://zulip.testserver/billing")
|
||||
|
||||
with self.settings(FREE_TRIAL_DAYS=30):
|
||||
response = self.client_get("/upgrade/")
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertEqual(response["Location"], "/billing/")
|
||||
self.assertEqual(response["Location"], "http://zulip.testserver/billing")
|
||||
|
||||
def test_get_latest_seat_count(self) -> None:
|
||||
realm = get_realm("zulip")
|
||||
|
||||
@ -58,6 +58,16 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if remote_server_legacy_plan_end_date %}
|
||||
<div class="input-box upgrade-page-field no-validation">
|
||||
<select name="remote_server_plan_start_date" id="remote-server-plan-start-date-select">
|
||||
<option value="billing_cycle_end_date">{{ remote_server_legacy_plan_end_date }}</option>
|
||||
<option value="today">Today</option>
|
||||
</select>
|
||||
<label for="remote-server-plan-start-date-select">Plan start date</label>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if manual_license_management %}
|
||||
<div class="input-box upgrade-page-field" id="upgrade-manual-license-count-wrapper">
|
||||
<label for="licenses" class="inline-block label-title">Number of licenses {% if not exempt_from_license_number_check %}(minimum {{ seat_count }}){% endif %}</label>
|
||||
@ -69,13 +79,32 @@
|
||||
<input type="hidden" name="license_management" value="automatic" />
|
||||
{% endif %}
|
||||
|
||||
{% if remote_server_legacy_plan_end_date %}
|
||||
<div class="input-box upgrade-page-field no-validation" id="due-today-for-future-update-wrapper">
|
||||
<label for="due-today-for-future-update" class="inline-block label-title">
|
||||
Due today
|
||||
</label>
|
||||
<div id="due-today-for-future-update" class="not-editable-realm-field">
|
||||
<h1>$0</h1>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="input-box upgrade-page-field no-validation">
|
||||
<label for="due-today" class="inline-block label-title">Due
|
||||
{% if free_trial_days %}
|
||||
on {{ free_trial_end_date }}
|
||||
{% else %}
|
||||
today
|
||||
<label for="due-today" class="inline-block label-title">
|
||||
{% if remote_server_legacy_plan_end_date %}
|
||||
<span id="due-today-remote-server-title">
|
||||
Due {{ remote_server_legacy_plan_end_date }}
|
||||
</span>
|
||||
{% endif %}
|
||||
<span id="due-today-title">
|
||||
Due
|
||||
{% if free_trial_days %}
|
||||
on {{ free_trial_end_date }}
|
||||
{% else %}
|
||||
today
|
||||
{% endif %}
|
||||
</span>
|
||||
</label>
|
||||
<div id="due-today" class="not-editable-realm-field">
|
||||
$<span class="due-today-unit-price"></span> x
|
||||
@ -149,11 +178,18 @@
|
||||
<div class="upgrade-button-container input-box upgrade-page-field" {% if is_demo_organization %}data-tippy-content="{% trans %}Convert demo organization before upgrading.{% endtrans %}"{% endif %}>
|
||||
<button id="org-upgrade-button{% if is_demo_organization %} permanent-disabled{% endif %}" {% if not payment_method %}disabled{% endif %}>
|
||||
<span id="org-upgrade-button-text">
|
||||
{% if free_trial_days %}
|
||||
Start {{ free_trial_days }}-day free trial
|
||||
{% else %}
|
||||
Purchase {{ plan }}
|
||||
{% if remote_server_legacy_plan_end_date %}
|
||||
<span id="org-future-upgrade-button-text-remote-server">
|
||||
Schedule upgrade to {{ plan }}
|
||||
</span>
|
||||
{% endif %}
|
||||
<span id="org-today-upgrade-button-text">
|
||||
{% if free_trial_days %}
|
||||
Start {{ free_trial_days }}-day free trial
|
||||
{% else %}
|
||||
Purchase {{ plan }}
|
||||
{% endif %}
|
||||
</span>
|
||||
</span>
|
||||
<object class="loader upgrade-button-loader" type="image/svg+xml" data="{{ static('images/loading/loader-white.svg') }}"></object>
|
||||
</button>
|
||||
|
||||
@ -14,6 +14,13 @@ const prices: Prices = {
|
||||
|
||||
const ls = localstorage();
|
||||
const ls_selected_schedule = ls.get("selected_schedule");
|
||||
const ls_remote_server_plan_start_date = ls.get("remote_server_plan_start_date");
|
||||
// The special value "billing_cycle_end_date" is used internally; it
|
||||
// should not appear in the UI.
|
||||
let remote_server_plan_start_date: string =
|
||||
typeof ls_remote_server_plan_start_date === "string"
|
||||
? ls_remote_server_plan_start_date
|
||||
: "billing_cycle_end_date";
|
||||
let selected_schedule: string =
|
||||
typeof ls_selected_schedule === "string" ? ls_selected_schedule : "monthly";
|
||||
let current_license_count = page_params.seat_count;
|
||||
@ -39,6 +46,27 @@ function update_due_today(schedule: string): void {
|
||||
$("#due-today .due-today-unit-price").text(helpers.format_money(unit_price));
|
||||
}
|
||||
|
||||
function update_due_today_for_remote_server(start_date: string): void {
|
||||
const $due_today_for_future_update_wrapper = $("#due-today-for-future-update-wrapper");
|
||||
if ($due_today_for_future_update_wrapper.length === 0) {
|
||||
// Only present legacy remote server page.
|
||||
return;
|
||||
}
|
||||
if (start_date === "billing_cycle_end_date") {
|
||||
$due_today_for_future_update_wrapper.show();
|
||||
$("#due-today-title").hide();
|
||||
$("#due-today-remote-server-title").show();
|
||||
$("#org-future-upgrade-button-text-remote-server").show();
|
||||
$("#org-today-upgrade-button-text").hide();
|
||||
} else {
|
||||
$due_today_for_future_update_wrapper.hide();
|
||||
$("#due-today-title").show();
|
||||
$("#due-today-remote-server-title").hide();
|
||||
$("#org-future-upgrade-button-text-remote-server").hide();
|
||||
$("#org-today-upgrade-button-text").show();
|
||||
}
|
||||
}
|
||||
|
||||
function update_license_count(license_count: number): void {
|
||||
$("#upgrade-licenses-change-error").text("");
|
||||
if (!license_count || license_count < page_params.seat_count) {
|
||||
@ -122,6 +150,14 @@ export const initialize = (): void => {
|
||||
update_due_today(selected_schedule);
|
||||
});
|
||||
|
||||
update_due_today_for_remote_server(remote_server_plan_start_date);
|
||||
$("#remote-server-plan-start-date-select").val(remote_server_plan_start_date);
|
||||
$<HTMLInputElement>("#remote-server-plan-start-date-select").on("change", function () {
|
||||
remote_server_plan_start_date = this.value;
|
||||
ls.set("remote_server_plan_start_date", remote_server_plan_start_date);
|
||||
update_due_today_for_remote_server(remote_server_plan_start_date);
|
||||
});
|
||||
|
||||
$("#autopay_annual_price_per_month").text(
|
||||
`Pay annually ($${helpers.format_money(prices.annual / 12)}/user/month)`,
|
||||
);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user