mirror of https://github.com/zulip/zulip.git
remote_billing: Remove code migrating Legacy plan from server to realms.
We no longer want to migrate Legacy plans from server to realms, since Legacy plans are not really a thing in the original sense anymore, since February 15th. Now they're just a tool to give temporary extensions of access to the push notification service for users, when needed. And as such, it makes no sense to migrate like that. The remaining code in this function is for migrating (any) plan from the server object to the realm object, if the server has just a single realm.
This commit is contained in:
parent
2598596ad2
commit
ea863bab5b
|
@ -23,7 +23,6 @@ from corporate.models import (
|
|||
get_customer_by_remote_server,
|
||||
)
|
||||
from corporate.views.remote_billing_page import generate_confirmation_link_for_server_deactivation
|
||||
from zerver.actions.realm_settings import do_deactivate_realm
|
||||
from zerver.lib.exceptions import RemoteRealmServerMismatchError
|
||||
from zerver.lib.rate_limiter import RateLimitedIPAddr
|
||||
from zerver.lib.remote_server import send_server_data_to_push_bouncer
|
||||
|
@ -662,98 +661,6 @@ class RemoteBillingAuthenticationTest(RemoteRealmBillingTestCase):
|
|||
],
|
||||
)
|
||||
|
||||
@responses.activate
|
||||
def test_transfer_legacy_plan_from_server_to_all_realms(self) -> None:
|
||||
self.login("desdemona")
|
||||
desdemona = self.example_user("desdemona")
|
||||
|
||||
# Assert current server is not on any plan.
|
||||
self.assertIsNone(get_customer_by_remote_server(self.server))
|
||||
|
||||
start_date = timezone_now()
|
||||
end_date = add_months(timezone_now(), 10)
|
||||
|
||||
# Migrate server to legacy to plan.
|
||||
server_billing_session = RemoteServerBillingSession(self.server)
|
||||
server_billing_session.migrate_customer_to_legacy_plan(start_date, end_date)
|
||||
|
||||
server_customer = server_billing_session.get_customer()
|
||||
assert server_customer is not None
|
||||
server_plan = get_current_plan_by_customer(server_customer)
|
||||
assert server_plan is not None
|
||||
self.assertEqual(self.server.plan_type, RemoteZulipServer.PLAN_TYPE_SELF_MANAGED_LEGACY)
|
||||
self.assertEqual(server_plan.tier, CustomerPlan.TIER_SELF_HOSTED_LEGACY)
|
||||
self.assertEqual(server_plan.status, CustomerPlan.ACTIVE)
|
||||
|
||||
# There are four test realms on this server:
|
||||
# <Realm: zulipinternal 1>, <Realm: zephyr 3>, <Realm: lear 4>, <Realm: zulip 2>
|
||||
self.assert_length(Realm.objects.all(), 4)
|
||||
|
||||
# Make lear deactivated, to have verification for that case.
|
||||
do_deactivate_realm(Realm.objects.get(string_id="lear"), acting_user=None)
|
||||
|
||||
# Delete any existing remote realms.
|
||||
RemoteRealm.objects.all().delete()
|
||||
|
||||
# First, set a sponsorship as pending.
|
||||
# TODO: Ideally, we'd submit a proper sponsorship request.
|
||||
server_customer.sponsorship_pending = True
|
||||
server_customer.save()
|
||||
|
||||
# Send server data to push bouncer.
|
||||
self.add_mock_response()
|
||||
send_server_data_to_push_bouncer(consider_usage_statistics=False)
|
||||
|
||||
# Login to plan management.
|
||||
result = self.execute_remote_billing_authentication_flow(
|
||||
desdemona, return_from_auth_url=True
|
||||
)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
self.assert_in_response("Plan management not available", result)
|
||||
|
||||
# RemoteRealm objects should be created for all realms on the server.
|
||||
self.assert_length(RemoteRealm.objects.all(), 4)
|
||||
|
||||
# Server's plan should not have been migrated yet.
|
||||
self.server.refresh_from_db()
|
||||
self.assertEqual(self.server.plan_type, RemoteZulipServer.PLAN_TYPE_SELF_MANAGED_LEGACY)
|
||||
|
||||
# Now clear sponsorship_pending.
|
||||
# TODO: Ideally, this would approve the sponsorship.
|
||||
server_customer.sponsorship_pending = False
|
||||
server_customer.save()
|
||||
|
||||
# Login to plan management. Performs customer migration from server to realms.
|
||||
result = self.execute_remote_billing_authentication_flow(
|
||||
desdemona, return_from_auth_url=False
|
||||
)
|
||||
self.assertEqual(result.status_code, 302)
|
||||
|
||||
# Server plan status was reset
|
||||
self.server.refresh_from_db()
|
||||
self.assertEqual(self.server.plan_type, RemoteZulipServer.PLAN_TYPE_SELF_MANAGED)
|
||||
# Check no CustomerPlan exists for server.
|
||||
self.assertIsNone(get_current_plan_by_customer(server_customer))
|
||||
|
||||
# Check legacy CustomerPlan exists for all realms except bot realm.
|
||||
no_customer_plan_realms = set()
|
||||
for remote_realm in RemoteRealm.objects.all():
|
||||
if remote_realm.is_system_bot_realm or remote_realm.realm_deactivated:
|
||||
self.assertIsNone(get_customer_by_remote_realm(remote_realm))
|
||||
no_customer_plan_realms.add(remote_realm.host.split(".")[0])
|
||||
continue
|
||||
|
||||
customer = get_customer_by_remote_realm(remote_realm)
|
||||
assert customer is not None
|
||||
plan = get_current_plan_by_customer(customer)
|
||||
assert plan is not None
|
||||
self.assertEqual(remote_realm.plan_type, RemoteRealm.PLAN_TYPE_SELF_MANAGED_LEGACY)
|
||||
self.assertEqual(plan.tier, CustomerPlan.TIER_SELF_HOSTED_LEGACY)
|
||||
self.assertEqual(plan.status, CustomerPlan.ACTIVE)
|
||||
self.assertEqual(plan.billing_cycle_anchor, start_date)
|
||||
self.assertEqual(plan.end_date, end_date)
|
||||
self.assertEqual(no_customer_plan_realms, {"zulipinternal", "lear"})
|
||||
|
||||
@responses.activate
|
||||
def test_transfer_legacy_plan_scheduled_for_upgrade_from_server_to_realm(
|
||||
self,
|
||||
|
|
|
@ -91,6 +91,7 @@ from corporate.models import (
|
|||
get_current_plan_by_customer,
|
||||
get_current_plan_by_realm,
|
||||
get_customer_by_realm,
|
||||
get_customer_by_remote_realm,
|
||||
)
|
||||
from corporate.tests.test_remote_billing import RemoteRealmBillingTestCase, RemoteServerTestCase
|
||||
from corporate.views.remote_billing_page import generate_confirmation_link_for_server_deactivation
|
||||
|
@ -6699,33 +6700,27 @@ class TestRemoteRealmBillingFlow(StripeTestCase, RemoteRealmBillingTestCase):
|
|||
@responses.activate
|
||||
@mock_stripe()
|
||||
def test_schedule_legacy_plan_upgrade_to_fixed_price_plan(self, *mocks: Mock) -> None:
|
||||
self.login("hamlet")
|
||||
hamlet = self.example_user("hamlet")
|
||||
|
||||
remote_server = RemoteZulipServer.objects.get(hostname="demo.example.com")
|
||||
server_billing_session = RemoteServerBillingSession(remote_server=remote_server)
|
||||
remote_realm = RemoteRealm.objects.get(uuid=hamlet.realm.uuid)
|
||||
remote_realm_billing_session = RemoteRealmBillingSession(remote_realm=remote_realm)
|
||||
|
||||
# Migrate server to legacy plan.
|
||||
# Migrate realm to legacy plan.
|
||||
with time_machine.travel(self.now, tick=False):
|
||||
start_date = timezone_now()
|
||||
end_date = add_months(start_date, months=3)
|
||||
server_billing_session.migrate_customer_to_legacy_plan(start_date, end_date)
|
||||
remote_realm_billing_session.migrate_customer_to_legacy_plan(start_date, end_date)
|
||||
|
||||
self.add_mock_response()
|
||||
with time_machine.travel(self.now, tick=False):
|
||||
send_server_data_to_push_bouncer(consider_usage_statistics=False)
|
||||
|
||||
# Login. Performs customer migration from server to realms.
|
||||
self.execute_remote_billing_authentication_flow(hamlet)
|
||||
self.remote_realm.refresh_from_db()
|
||||
|
||||
customer = Customer.objects.get(remote_realm=self.remote_realm)
|
||||
legacy_plan = get_current_plan_by_customer(customer)
|
||||
assert legacy_plan is not None
|
||||
self.assertEqual(legacy_plan.tier, CustomerPlan.TIER_SELF_HOSTED_LEGACY)
|
||||
self.assertEqual(legacy_plan.next_invoice_date, end_date)
|
||||
|
||||
self.logout()
|
||||
self.login("iago")
|
||||
|
||||
# Schedule a fixed-price business plan at current plan end_date.
|
||||
|
@ -6759,7 +6754,7 @@ class TestRemoteRealmBillingFlow(StripeTestCase, RemoteRealmBillingTestCase):
|
|||
self.logout()
|
||||
self.login("hamlet")
|
||||
self.execute_remote_billing_authentication_flow(
|
||||
hamlet, expect_tos=False, confirm_tos=False, first_time_login=False
|
||||
hamlet, expect_tos=False, confirm_tos=True, first_time_login=True
|
||||
)
|
||||
|
||||
# Schedule upgrade to business plan
|
||||
|
@ -7050,6 +7045,14 @@ class TestRemoteRealmBillingFlow(StripeTestCase, RemoteRealmBillingTestCase):
|
|||
self.assertEqual(server_customer_plan.status, CustomerPlan.ACTIVE)
|
||||
self.assertEqual(remote_server.plan_type, RemoteZulipServer.PLAN_TYPE_SELF_MANAGED_LEGACY)
|
||||
|
||||
# The plan gets migrated if there's only a single human realm.
|
||||
Realm.objects.exclude(string_id__in=["zulip", "zulipinternal"]).delete()
|
||||
|
||||
# First, set a sponsorship as pending.
|
||||
# TODO: Ideally, we'd submit a proper sponsorship request.
|
||||
server_customer.sponsorship_pending = True
|
||||
server_customer.save()
|
||||
|
||||
# Upload data.
|
||||
with time_machine.travel(self.now, tick=False):
|
||||
self.add_mock_response()
|
||||
|
@ -7059,23 +7062,38 @@ class TestRemoteRealmBillingFlow(StripeTestCase, RemoteRealmBillingTestCase):
|
|||
hamlet = self.example_user("hamlet")
|
||||
billing_base_url = self.billing_session.billing_base_url
|
||||
|
||||
# Login. Performs customer migration from server to realms.
|
||||
# Login. The server has a pending sponsorship, in which case migrating
|
||||
# can't be done, as that'd be a fairly confusing process.
|
||||
result = self.execute_remote_billing_authentication_flow(hamlet, return_from_auth_url=True)
|
||||
|
||||
self.assertEqual(result.status_code, 200)
|
||||
self.assert_in_response("Plan management not available", result)
|
||||
# Server's plan should not have been migrated yet.
|
||||
self.server.refresh_from_db()
|
||||
self.assertEqual(self.server.plan_type, RemoteZulipServer.PLAN_TYPE_SELF_MANAGED_LEGACY)
|
||||
|
||||
# Now clear the pending sponsorship state, which will allow login
|
||||
# and migration to proceed.
|
||||
# TODO: Ideally, this would approve the sponsorship and then be testing
|
||||
# the migration of the Community plan.
|
||||
server_customer.sponsorship_pending = False
|
||||
server_customer.save()
|
||||
|
||||
# Login. Performs customer migration from server to realm.
|
||||
result = self.execute_remote_billing_authentication_flow(hamlet)
|
||||
|
||||
self.assertEqual(result.status_code, 302)
|
||||
self.assertEqual(result["Location"], f"{billing_base_url}/plans/")
|
||||
|
||||
remote_server.refresh_from_db()
|
||||
server_customer_plan.refresh_from_db()
|
||||
self.assertEqual(server_customer_plan.status, CustomerPlan.ENDED)
|
||||
remote_realm = RemoteRealm.objects.get(uuid=hamlet.realm.uuid)
|
||||
# The customer object was moved, together with the plan, from server to realm.
|
||||
customer = get_customer_by_remote_realm(remote_realm)
|
||||
assert customer is not None
|
||||
self.assertEqual(server_customer, customer)
|
||||
self.assertEqual(remote_server.plan_type, RemoteZulipServer.PLAN_TYPE_SELF_MANAGED)
|
||||
self.assertEqual(remote_realm.plan_type, RemoteRealm.PLAN_TYPE_SELF_MANAGED_LEGACY)
|
||||
|
||||
remote_realms = RemoteRealm.objects.filter(
|
||||
server=remote_server,
|
||||
plan_type=RemoteRealm.PLAN_TYPE_SELF_MANAGED_LEGACY,
|
||||
is_system_bot_realm=False,
|
||||
)
|
||||
for remote_realm in remote_realms:
|
||||
customer = Customer.objects.get(remote_realm=remote_realm)
|
||||
customer_plan = get_current_plan_by_customer(customer)
|
||||
assert customer_plan is not None
|
||||
self.assertEqual(customer_plan.tier, CustomerPlan.TIER_SELF_HOSTED_LEGACY)
|
||||
|
@ -7090,17 +7108,15 @@ class TestRemoteRealmBillingFlow(StripeTestCase, RemoteRealmBillingTestCase):
|
|||
with time_machine.travel(self.now, tick=False):
|
||||
stripe_customer = self.add_card_and_upgrade()
|
||||
|
||||
zulip_realm_customer = Customer.objects.get(stripe_customer_id=stripe_customer.id)
|
||||
zulip_realm_plan = CustomerPlan.objects.get(
|
||||
customer=zulip_realm_customer, status=CustomerPlan.ACTIVE
|
||||
)
|
||||
self.assertEqual(zulip_realm_plan.tier, CustomerPlan.TIER_SELF_HOSTED_BUSINESS)
|
||||
self.assertEqual(customer, Customer.objects.get(stripe_customer_id=stripe_customer.id))
|
||||
business_plan = CustomerPlan.objects.get(customer=customer, status=CustomerPlan.ACTIVE)
|
||||
self.assertEqual(business_plan.tier, CustomerPlan.TIER_SELF_HOSTED_BUSINESS)
|
||||
|
||||
realm_user_count = UserProfile.objects.filter(
|
||||
realm=hamlet.realm, is_bot=False, is_active=True
|
||||
).count()
|
||||
licenses = max(
|
||||
realm_user_count, self.billing_session.min_licenses_for_plan(zulip_realm_plan.tier)
|
||||
realm_user_count, self.billing_session.min_licenses_for_plan(business_plan.tier)
|
||||
)
|
||||
with time_machine.travel(self.now + timedelta(days=1), tick=False):
|
||||
response = self.client_get(f"{billing_base_url}/billing/", subdomain="selfhosting")
|
||||
|
@ -7130,11 +7146,11 @@ class TestRemoteRealmBillingFlow(StripeTestCase, RemoteRealmBillingTestCase):
|
|||
"/billing/plan",
|
||||
{"status": CustomerPlan.DOWNGRADE_AT_END_OF_CYCLE},
|
||||
)
|
||||
expected_log = f"INFO:corporate.stripe:Change plan status: Customer.id: {zulip_realm_customer.id}, CustomerPlan.id: {zulip_realm_plan.id}, status: {CustomerPlan.DOWNGRADE_AT_END_OF_CYCLE}"
|
||||
expected_log = f"INFO:corporate.stripe:Change plan status: Customer.id: {customer.id}, CustomerPlan.id: {business_plan.id}, status: {CustomerPlan.DOWNGRADE_AT_END_OF_CYCLE}"
|
||||
self.assertEqual(m.output[0], expected_log)
|
||||
self.assert_json_success(response)
|
||||
zulip_realm_plan.refresh_from_db()
|
||||
self.assertEqual(zulip_realm_plan.licenses_at_next_renewal(), None)
|
||||
business_plan.refresh_from_db()
|
||||
self.assertEqual(business_plan.licenses_at_next_renewal(), None)
|
||||
|
||||
@responses.activate
|
||||
@mock_stripe()
|
||||
|
@ -7277,14 +7293,16 @@ class TestRemoteRealmBillingFlow(StripeTestCase, RemoteRealmBillingTestCase):
|
|||
@responses.activate
|
||||
@mock_stripe()
|
||||
def test_invoice_scheduled_upgrade_realm_legacy_plan(self, *mocks: Mock) -> None:
|
||||
remote_server = RemoteZulipServer.objects.get(hostname="demo.example.com")
|
||||
server_billing_session = RemoteServerBillingSession(remote_server=remote_server)
|
||||
hamlet = self.example_user("hamlet")
|
||||
|
||||
# Migrate server to legacy plan.
|
||||
remote_realm = RemoteRealm.objects.get(uuid=hamlet.realm.uuid)
|
||||
remote_realm_billing_session = RemoteRealmBillingSession(remote_realm=remote_realm)
|
||||
|
||||
# Migrate realm to legacy plan.
|
||||
with time_machine.travel(self.now, tick=False):
|
||||
start_date = timezone_now()
|
||||
end_date = add_months(start_date, months=3)
|
||||
server_billing_session.migrate_customer_to_legacy_plan(start_date, end_date)
|
||||
remote_realm_billing_session.migrate_customer_to_legacy_plan(start_date, end_date)
|
||||
|
||||
# Upload data.
|
||||
self.add_mock_response()
|
||||
|
@ -7292,11 +7310,9 @@ class TestRemoteRealmBillingFlow(StripeTestCase, RemoteRealmBillingTestCase):
|
|||
send_server_data_to_push_bouncer(consider_usage_statistics=False)
|
||||
|
||||
self.login("hamlet")
|
||||
hamlet = self.example_user("hamlet")
|
||||
|
||||
# Login. Performs customer migration from server to realms.
|
||||
# Login.
|
||||
self.execute_remote_billing_authentication_flow(hamlet)
|
||||
remote_server.refresh_from_db()
|
||||
|
||||
# Schedule upgrade to business plan
|
||||
with time_machine.travel(self.now, tick=False):
|
||||
|
|
|
@ -65,7 +65,7 @@ from zilencer.models import (
|
|||
RemoteZulipServer,
|
||||
get_remote_server_by_uuid,
|
||||
)
|
||||
from zilencer.views import handle_customer_migration_from_server_to_realms
|
||||
from zilencer.views import handle_customer_migration_from_server_to_realm
|
||||
|
||||
billing_logger = logging.getLogger("corporate.stripe")
|
||||
|
||||
|
@ -200,7 +200,7 @@ def remote_realm_billing_finalize_login(
|
|||
raise AssertionError
|
||||
|
||||
try:
|
||||
handle_customer_migration_from_server_to_realms(server=remote_server)
|
||||
handle_customer_migration_from_server_to_realm(server=remote_server)
|
||||
except JsonableError:
|
||||
# JsonableError should be propagated up, as they are meant to convey
|
||||
# a json error response to be returned.
|
||||
|
|
|
@ -935,7 +935,7 @@ def get_human_user_realm_uuids(
|
|||
|
||||
|
||||
@transaction.atomic
|
||||
def handle_customer_migration_from_server_to_realms(
|
||||
def handle_customer_migration_from_server_to_realm(
|
||||
server: RemoteZulipServer,
|
||||
) -> None:
|
||||
server_billing_session = RemoteServerBillingSession(server)
|
||||
|
@ -967,42 +967,7 @@ def handle_customer_migration_from_server_to_realms(
|
|||
event_time = timezone_now()
|
||||
remote_realm_audit_logs = []
|
||||
|
||||
if (
|
||||
server_plan.tier == CustomerPlan.TIER_SELF_HOSTED_LEGACY
|
||||
and server_plan.status == CustomerPlan.ACTIVE
|
||||
):
|
||||
assert server.plan_type == RemoteZulipServer.PLAN_TYPE_SELF_MANAGED_LEGACY
|
||||
assert server_plan.end_date is not None
|
||||
remote_realms = RemoteRealm.objects.filter(
|
||||
uuid__in=realm_uuids, server=server, plan_type=RemoteRealm.PLAN_TYPE_SELF_MANAGED
|
||||
)
|
||||
|
||||
# Verify that all the realms are on self hosted plan.
|
||||
assert remote_realms.count() == len(realm_uuids)
|
||||
|
||||
# End existing plan for server.
|
||||
server_plan.status = CustomerPlan.ENDED
|
||||
server_plan.save(update_fields=["status"])
|
||||
|
||||
server.plan_type = RemoteZulipServer.PLAN_TYPE_SELF_MANAGED
|
||||
server.save(update_fields=["plan_type"])
|
||||
|
||||
# Create new legacy plan for each remote realm.
|
||||
for remote_realm in remote_realms:
|
||||
RemoteRealmBillingSession(remote_realm).migrate_customer_to_legacy_plan(
|
||||
server_plan.billing_cycle_anchor, server_plan.end_date
|
||||
)
|
||||
remote_realm_audit_logs.append(
|
||||
RemoteRealmAuditLog(
|
||||
server=server,
|
||||
remote_realm=remote_realm,
|
||||
event_type=RemoteRealmAuditLog.REMOTE_PLAN_TRANSFERRED_SERVER_TO_REALM,
|
||||
event_time=event_time,
|
||||
# No extra_data since there was no real change in any RemoteRealm attribute.
|
||||
)
|
||||
)
|
||||
|
||||
elif len(realm_uuids) == 1:
|
||||
if len(realm_uuids) == 1:
|
||||
# Here, we have exactly one non-system-bot realm, and some
|
||||
# sort of plan on the server; move it to the realm.
|
||||
remote_realm = RemoteRealm.objects.get(uuid=realm_uuids[0], server=server)
|
||||
|
|
Loading…
Reference in New Issue