mirror of
https://github.com/zulip/zulip.git
synced 2025-11-01 20:44:04 +00:00
upgrade: Fix allowed free trails for ended legacy plans on server.
If the remote realm registered after the legacy plan on server ENDED, we never migrate the plan to the remote realm. So, we need to check the server of remote realm whenever we are check remote realm for legacy plan.
This commit is contained in:
@@ -51,7 +51,6 @@ from corporate.models import (
|
||||
get_customer_by_realm,
|
||||
get_customer_by_remote_realm,
|
||||
get_customer_by_remote_server,
|
||||
is_legacy_customer,
|
||||
)
|
||||
from zerver.lib.exceptions import JsonableError
|
||||
from zerver.lib.logging_util import log_to_file
|
||||
@@ -761,6 +760,32 @@ class BillingSession(ABC):
|
||||
def org_name(self) -> str:
|
||||
pass
|
||||
|
||||
def is_legacy_customer(self) -> bool:
|
||||
if isinstance(self, RealmBillingSession):
|
||||
return False
|
||||
|
||||
customers_to_check = []
|
||||
if isinstance(self, RemoteRealmBillingSession):
|
||||
customer = self.get_customer()
|
||||
if customer is not None:
|
||||
customers_to_check.append(customer)
|
||||
|
||||
# Also, check if server for a remote realm was ever on a legacy plan.
|
||||
# We don't migrate ENDED legacy plans from server to remote realm, so we can end
|
||||
# in this state if the first time they registered with us was after the legacy plan.
|
||||
server_customer = get_customer_by_remote_server(self.remote_realm.server)
|
||||
if server_customer is not None:
|
||||
customers_to_check.append(server_customer)
|
||||
|
||||
if isinstance(self, RemoteServerBillingSession):
|
||||
customer = self.get_customer()
|
||||
if customer is not None:
|
||||
customers_to_check.append(customer)
|
||||
|
||||
return CustomerPlan.objects.filter(
|
||||
customer__in=customers_to_check, tier=CustomerPlan.TIER_SELF_HOSTED_LEGACY
|
||||
).exists()
|
||||
|
||||
def get_past_invoices_session_url(self) -> str:
|
||||
headline = "List of past invoices"
|
||||
customer = self.get_customer()
|
||||
@@ -1860,9 +1885,9 @@ class BillingSession(ABC):
|
||||
if fixed_price_plan_offer is not None:
|
||||
free_trial = False
|
||||
|
||||
if is_legacy_customer(customer):
|
||||
# Free trial is not available for legacy customers.
|
||||
free_trial = False
|
||||
if self.is_legacy_customer():
|
||||
# Free trial is not available for legacy customers.
|
||||
free_trial = False
|
||||
|
||||
remote_server_legacy_plan = self.get_remote_server_legacy_plan(customer)
|
||||
should_schedule_upgrade_for_legacy_remote_server = (
|
||||
@@ -2454,7 +2479,7 @@ class BillingSession(ABC):
|
||||
is_self_hosted_billing = not isinstance(self, RealmBillingSession)
|
||||
if fixed_price is None and remote_server_legacy_plan_end_date is None:
|
||||
free_trial_days = get_free_trial_days(is_self_hosted_billing, tier)
|
||||
if customer is not None and is_legacy_customer(customer):
|
||||
if self.is_legacy_customer():
|
||||
# Free trial is not available for legacy customers.
|
||||
free_trial_days = None
|
||||
if free_trial_days is not None:
|
||||
|
||||
@@ -484,12 +484,6 @@ def get_current_plan_by_customer(customer: Customer) -> Optional[CustomerPlan]:
|
||||
).first()
|
||||
|
||||
|
||||
def is_legacy_customer(customer: Customer) -> bool:
|
||||
return CustomerPlan.objects.filter(
|
||||
customer=customer, tier=CustomerPlan.TIER_SELF_HOSTED_LEGACY
|
||||
).exists()
|
||||
|
||||
|
||||
def get_current_plan_by_realm(realm: Realm) -> Optional[CustomerPlan]:
|
||||
customer = get_customer_by_realm(realm)
|
||||
if customer is None:
|
||||
|
||||
@@ -91,7 +91,6 @@ from corporate.models import (
|
||||
get_current_plan_by_realm,
|
||||
get_customer_by_realm,
|
||||
get_customer_by_remote_realm,
|
||||
is_legacy_customer,
|
||||
)
|
||||
from corporate.tests.test_remote_billing import RemoteRealmBillingTestCase, RemoteServerTestCase
|
||||
from corporate.views.remote_billing_page import generate_confirmation_link_for_server_deactivation
|
||||
@@ -640,7 +639,7 @@ class StripeTestCase(ZulipTestCase):
|
||||
is_free_trial_offer_enabled(is_self_hosted_billing)
|
||||
and
|
||||
# Free trial is not applicable for legacy customers.
|
||||
not is_legacy_customer(customer)
|
||||
not self.billing_session.is_legacy_customer()
|
||||
):
|
||||
# Upgrade already happened for free trial, invoice realms or schedule
|
||||
# upgrade for legacy remote servers.
|
||||
@@ -6087,6 +6086,84 @@ class TestRemoteRealmBillingFlow(StripeTestCase, RemoteRealmBillingTestCase):
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertTrue(response["Location"].startswith("https://billing.stripe.com"))
|
||||
|
||||
@responses.activate
|
||||
@mock_stripe()
|
||||
def test_upgrade_user_to_basic_plan_free_trial_fails_special_case(self, *mocks: Mock) -> None:
|
||||
# Here we test if server had a legacy plan but never it ended before we could ever migrate
|
||||
# it to remote realm resulting in the upgrade for remote realm creating a new customer which
|
||||
# doesn't have any legacy plan associated with it. In this case, free trail should not be offered.
|
||||
with self.settings(SELF_HOSTING_FREE_TRIAL_DAYS=30):
|
||||
self.login("hamlet")
|
||||
hamlet = self.example_user("hamlet")
|
||||
|
||||
self.add_mock_response()
|
||||
with time_machine.travel(self.now, tick=False):
|
||||
send_server_data_to_push_bouncer(consider_usage_statistics=False)
|
||||
|
||||
result = self.execute_remote_billing_authentication_flow(hamlet)
|
||||
self.assertEqual(result.status_code, 302)
|
||||
self.assertEqual(result["Location"], f"{self.billing_session.billing_base_url}/plans/")
|
||||
|
||||
# Test under normal circumstances it will show free trial.
|
||||
with time_machine.travel(self.now, tick=False):
|
||||
result = self.client_get(
|
||||
f"{self.billing_session.billing_base_url}/upgrade/?tier={CustomerPlan.TIER_SELF_HOSTED_BASIC}",
|
||||
subdomain="selfhosting",
|
||||
)
|
||||
|
||||
self.assert_in_success_response(
|
||||
[
|
||||
"Start free trial",
|
||||
"Zulip Basic",
|
||||
"Start 30-day free trial",
|
||||
],
|
||||
result,
|
||||
)
|
||||
|
||||
# Add ended legacy plan for remote realm server.
|
||||
new_server_customer = Customer.objects.create(remote_server=self.remote_realm.server)
|
||||
CustomerPlan.objects.create(
|
||||
customer=new_server_customer,
|
||||
status=CustomerPlan.ENDED,
|
||||
tier=CustomerPlan.TIER_SELF_HOSTED_LEGACY,
|
||||
billing_cycle_anchor=timezone_now(),
|
||||
billing_schedule=CustomerPlan.BILLING_SCHEDULE_ANNUAL,
|
||||
)
|
||||
|
||||
# No longer eligible for free trial
|
||||
with time_machine.travel(self.now, tick=False):
|
||||
result = self.client_get(
|
||||
f"{self.billing_session.billing_base_url}/upgrade/?tier={CustomerPlan.TIER_SELF_HOSTED_BASIC}",
|
||||
subdomain="selfhosting",
|
||||
)
|
||||
|
||||
self.assert_not_in_success_response(
|
||||
[
|
||||
"Start free trial",
|
||||
"Start 30-day free trial",
|
||||
],
|
||||
result,
|
||||
)
|
||||
|
||||
self.assert_in_success_response(
|
||||
[
|
||||
"Purchase Zulip Basic",
|
||||
],
|
||||
result,
|
||||
)
|
||||
|
||||
result = self.client_get(
|
||||
f"{self.billing_session.billing_base_url}/plans/",
|
||||
subdomain="selfhosting",
|
||||
)
|
||||
|
||||
self.assert_not_in_success_response(
|
||||
[
|
||||
"Start 30-day free trial",
|
||||
],
|
||||
result,
|
||||
)
|
||||
|
||||
@responses.activate
|
||||
@mock_stripe()
|
||||
def test_upgrade_user_to_basic_plan_free_trial(self, *mocks: Mock) -> None:
|
||||
|
||||
@@ -21,12 +21,7 @@ from corporate.lib.stripe import (
|
||||
get_configured_fixed_price_plan_offer,
|
||||
get_free_trial_days,
|
||||
)
|
||||
from corporate.models import (
|
||||
CustomerPlan,
|
||||
get_current_plan_by_customer,
|
||||
get_customer_by_realm,
|
||||
is_legacy_customer,
|
||||
)
|
||||
from corporate.models import CustomerPlan, get_current_plan_by_customer, get_customer_by_realm
|
||||
from zerver.context_processors import get_realm_from_request, latest_info_context
|
||||
from zerver.decorator import add_google_analytics, zulip_login_required
|
||||
from zerver.lib.github import (
|
||||
@@ -193,9 +188,9 @@ def remote_realm_plans_page(
|
||||
status=CustomerPlan.NEVER_STARTED,
|
||||
)
|
||||
|
||||
if is_legacy_customer(customer):
|
||||
# Free trial is disabled for legacy customers.
|
||||
context.free_trial_days = None
|
||||
if billing_session.is_legacy_customer():
|
||||
# Free trial is disabled for legacy customers.
|
||||
context.free_trial_days = None
|
||||
|
||||
context.is_new_customer = (
|
||||
not context.on_free_tier and context.customer_plan is None and not context.is_sponsored
|
||||
@@ -256,7 +251,7 @@ def remote_server_plans_page(
|
||||
status=CustomerPlan.NEVER_STARTED,
|
||||
)
|
||||
|
||||
if is_legacy_customer(customer):
|
||||
if billing_session.is_legacy_customer():
|
||||
# Free trial is disabled for legacy customers.
|
||||
context.free_trial_days = None
|
||||
|
||||
|
||||
Reference in New Issue
Block a user