support: Fix next plan info missing for customers with no current plan.

Earlier, when a fixed-price plan for a customer with
no current plan was configured via /support, the next plan
info was missing on support page.

It was because we were considering next plan only if the
customer had a current plan.

This commit fixes the incorrect behaviour.
This commit is contained in:
Prakhar Pratyush 2024-01-31 18:40:45 +05:30 committed by Tim Abbott
parent fce50bb4a0
commit c4b6cfe142
4 changed files with 21 additions and 19 deletions

View File

@ -1958,23 +1958,14 @@ class BillingSession(ABC):
return None, None
return None, last_ledger_entry
def get_next_plan(self, plan: CustomerPlan) -> Union[CustomerPlan, CustomerPlanOffer, None]:
customer = plan.customer
def get_next_plan(self, plan: CustomerPlan) -> Optional[CustomerPlan]:
if plan.status == CustomerPlan.SWITCH_PLAN_TIER_AT_PLAN_END:
assert plan.end_date is not None
return CustomerPlan.objects.filter(
customer=customer,
customer=plan.customer,
billing_cycle_anchor=plan.end_date,
status=CustomerPlan.NEVER_STARTED,
).first()
elif customer.required_plan_tier is not None:
# Currently, the only case when a next_plan is scheduled with the
# current_plan.status NOT SET to SWITCH_PLAN_TIER_AT_PLAN_END is a
# fixed price plan configured via /support which the customer is yet
# to buy or schedule a purchase.
return get_configured_fixed_price_plan_offer(
customer=customer, plan_tier=customer.required_plan_tier
)
return None
def get_customer_plan_renewal_amount(
@ -2136,7 +2127,6 @@ class BillingSession(ABC):
next_plan = self.get_next_plan(plan)
if next_plan is not None:
assert type(next_plan) is CustomerPlan
next_plan_context = self.get_billing_context_from_plan(
customer, next_plan, last_ledger_entry, now
)
@ -2394,9 +2384,8 @@ class BillingSession(ABC):
# Switch to a different plan was cancelled. We end the next plan
# and set the current one as active.
if plan.status == CustomerPlan.SWITCH_PLAN_TIER_AT_PLAN_END:
assert type(plan) is CustomerPlan
next_plan = self.get_next_plan(plan)
assert type(next_plan) is CustomerPlan
assert next_plan is not None
do_change_plan_status(next_plan, CustomerPlan.ENDED)
do_change_plan_status(plan, status)
elif status == CustomerPlan.DOWNGRADE_AT_END_OF_CYCLE:

View File

@ -13,6 +13,7 @@ from corporate.lib.stripe import (
BillingSession,
RemoteRealmBillingSession,
RemoteServerBillingSession,
get_configured_fixed_price_plan_offer,
start_of_next_billing_cycle,
)
from corporate.models import (
@ -156,6 +157,15 @@ def get_current_plan_data_for_support_view(billing_session: BillingSession) -> P
customer=customer,
current_plan=plan,
)
# A customer with or without a current plan can have a fixed_price next plan configured.
if customer and customer.required_plan_tier:
plan_data.next_plan = get_configured_fixed_price_plan_offer(
customer, customer.required_plan_tier
)
if plan_data.next_plan:
plan_data.estimated_next_plan_revenue = plan_data.next_plan.fixed_price
if plan is not None:
new_plan, last_ledger_entry = billing_session.make_end_of_cycle_updates_if_needed(
plan, timezone_now()
@ -172,7 +182,8 @@ def get_current_plan_data_for_support_view(billing_session: BillingSession) -> P
)
assert plan_data.current_plan is not None # for mypy
plan_data.next_plan = billing_session.get_next_plan(plan_data.current_plan)
if plan_data.next_plan is None:
plan_data.next_plan = billing_session.get_next_plan(plan_data.current_plan)
if plan_data.next_plan is not None:
if plan_data.next_plan.fixed_price is not None: # nocoverage

View File

@ -6223,6 +6223,12 @@ class TestRemoteRealmBillingFlow(StripeTestCase, RemoteRealmBillingTestCase):
self.assertEqual(fixed_price_plan_offer.fixed_price, annual_fixed_price * 100)
self.assertEqual(fixed_price_plan_offer.get_plan_status_as_text(), "Configured")
result = self.client_get("/activity/remote/support", {"q": "example.com"})
self.assert_in_success_response(
["Next plan information:", "Zulip Basic", "Configured", "Plan has a fixed price."],
result,
)
self.logout()
self.login("hamlet")
hamlet = self.example_user("hamlet")
@ -6886,7 +6892,6 @@ class TestRemoteRealmBillingFlow(StripeTestCase, RemoteRealmBillingTestCase):
new_plan = self.billing_session.get_next_plan(realm_legacy_plan)
assert new_plan is not None
assert type(new_plan) is CustomerPlan
self.assertEqual(new_plan.tier, CustomerPlan.TIER_SELF_HOSTED_BUSINESS)
self.assertEqual(new_plan.status, CustomerPlan.NEVER_STARTED)
self.assertEqual(
@ -7247,7 +7252,6 @@ class TestRemoteServerBillingFlow(StripeTestCase, RemoteServerTestCase):
self.assertEqual(customer_plan.end_date, end_date)
new_customer_plan = self.billing_session.get_next_plan(customer_plan)
assert new_customer_plan is not None
assert type(new_customer_plan) is CustomerPlan
self.assertEqual(new_customer_plan.tier, CustomerPlan.TIER_SELF_HOSTED_BUSINESS)
self.assertEqual(new_customer_plan.status, CustomerPlan.NEVER_STARTED)
self.assertEqual(new_customer_plan.billing_cycle_anchor, end_date)
@ -8082,7 +8086,6 @@ class TestRemoteServerBillingFlow(StripeTestCase, RemoteServerTestCase):
self.assertEqual(legacy_plan.status, CustomerPlan.SWITCH_PLAN_TIER_AT_PLAN_END)
new_plan = self.billing_session.get_next_plan(legacy_plan)
assert new_plan is not None
assert type(new_plan) is CustomerPlan
self.assertEqual(new_plan.tier, CustomerPlan.TIER_SELF_HOSTED_BUSINESS)
self.assertEqual(new_plan.status, CustomerPlan.NEVER_STARTED)
self.assertEqual(

View File

@ -404,7 +404,6 @@ class TestRemoteServerSupportEndpoint(ZulipTestCase):
assert plan is not None
next_plan = billing_session.get_next_plan(plan)
assert next_plan is not None
assert type(next_plan) is CustomerPlan
self.assertEqual(plan.status, CustomerPlan.SWITCH_PLAN_TIER_AT_PLAN_END)
self.assertEqual(next_plan.status, CustomerPlan.NEVER_STARTED)