billing: Use better variable names for plan tiers.

The existing values didn't have our standard type-prefixing naming
scheme.

Add some extra unused placeholder values while we're at it.
This commit is contained in:
Tim Abbott 2023-11-29 22:43:06 -08:00
parent 408a273ba0
commit 5d6b635efe
12 changed files with 116 additions and 86 deletions

View File

@ -293,7 +293,7 @@ class TestSupportEndpoint(ZulipTestCase):
customer=customer, customer=customer,
billing_cycle_anchor=now, billing_cycle_anchor=now,
billing_schedule=CustomerPlan.ANNUAL, billing_schedule=CustomerPlan.ANNUAL,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
price_per_license=8000, price_per_license=8000,
next_invoice_date=add_months(now, 12), next_invoice_date=add_months(now, 12),
) )

View File

@ -1068,7 +1068,7 @@ class BillingSession(ABC):
# Directly upgrade free trial orgs or invoice payment orgs to standard plan. # Directly upgrade free trial orgs or invoice payment orgs to standard plan.
if free_trial or not charge_automatically: if free_trial or not charge_automatically:
self.process_initial_upgrade( self.process_initial_upgrade(
CustomerPlan.STANDARD, CustomerPlan.TIER_CLOUD_STANDARD,
licenses, licenses,
automanage_licenses, automanage_licenses,
billing_schedule, billing_schedule,
@ -1078,7 +1078,7 @@ class BillingSession(ABC):
data["organization_upgrade_successful"] = True data["organization_upgrade_successful"] = True
else: else:
stripe_payment_intent_id = self.setup_upgrade_payment_intent_and_charge( stripe_payment_intent_id = self.setup_upgrade_payment_intent_and_charge(
CustomerPlan.STANDARD, CustomerPlan.TIER_CLOUD_STANDARD,
seat_count, seat_count,
licenses, licenses,
license_management, license_management,
@ -2000,9 +2000,11 @@ class RealmBillingSession(BillingSession):
# formats of CustomerPlan.tier and Realm.plan_type. # formats of CustomerPlan.tier and Realm.plan_type.
if is_sponsored: if is_sponsored:
plan_type = Realm.PLAN_TYPE_STANDARD_FREE plan_type = Realm.PLAN_TYPE_STANDARD_FREE
elif tier == CustomerPlan.STANDARD: elif tier == CustomerPlan.TIER_CLOUD_STANDARD:
plan_type = Realm.PLAN_TYPE_STANDARD plan_type = Realm.PLAN_TYPE_STANDARD
elif tier == CustomerPlan.PLUS: # nocoverage # Plus plan doesn't use this code path yet. elif (
tier == CustomerPlan.TIER_CLOUD_PLUS
): # nocoverage # Plus plan doesn't use this code path yet.
plan_type = Realm.PLAN_TYPE_PLUS plan_type = Realm.PLAN_TYPE_PLUS
else: else:
raise AssertionError("Unexpected tier") raise AssertionError("Unexpected tier")
@ -2075,11 +2077,11 @@ class RealmBillingSession(BillingSession):
@override @override
def is_valid_plan_tier_switch(self, current_plan_tier: int, new_plan_tier: int) -> bool: def is_valid_plan_tier_switch(self, current_plan_tier: int, new_plan_tier: int) -> bool:
if current_plan_tier == CustomerPlan.STANDARD: if current_plan_tier == CustomerPlan.TIER_CLOUD_STANDARD:
return new_plan_tier == CustomerPlan.PLUS return new_plan_tier == CustomerPlan.TIER_CLOUD_PLUS
else: # nocoverage, not currently implemented else: # nocoverage, not currently implemented
assert current_plan_tier == CustomerPlan.PLUS assert current_plan_tier == CustomerPlan.TIER_CLOUD_PLUS
return new_plan_tier == CustomerPlan.STANDARD return new_plan_tier == CustomerPlan.TIER_CLOUD_STANDARD
@override @override
def has_billing_access(self) -> bool: def has_billing_access(self) -> bool:
@ -2274,9 +2276,11 @@ class RemoteRealmBillingSession(BillingSession): # nocoverage
# formats of CustomerPlan.tier and Realm.plan_type. # formats of CustomerPlan.tier and Realm.plan_type.
if is_sponsored: if is_sponsored:
plan_type = RemoteRealm.PLAN_TYPE_COMMUNITY plan_type = RemoteRealm.PLAN_TYPE_COMMUNITY
elif tier == CustomerPlan.STANDARD: elif tier == CustomerPlan.TIER_CLOUD_STANDARD:
plan_type = RemoteRealm.PLAN_TYPE_BUSINESS plan_type = RemoteRealm.PLAN_TYPE_BUSINESS
elif tier == CustomerPlan.PLUS: # nocoverage # Plus plan doesn't use this code path yet. elif (
tier == CustomerPlan.TIER_CLOUD_PLUS
): # nocoverage # Plus plan doesn't use this code path yet.
plan_type = RemoteRealm.PLAN_TYPE_ENTERPRISE plan_type = RemoteRealm.PLAN_TYPE_ENTERPRISE
else: else:
raise AssertionError("Unexpected tier") raise AssertionError("Unexpected tier")
@ -2519,9 +2523,11 @@ class RemoteServerBillingSession(BillingSession): # nocoverage
# formats of CustomerPlan.tier and RealmZulipServer.plan_type. # formats of CustomerPlan.tier and RealmZulipServer.plan_type.
if is_sponsored: if is_sponsored:
plan_type = RemoteZulipServer.PLAN_TYPE_COMMUNITY plan_type = RemoteZulipServer.PLAN_TYPE_COMMUNITY
elif tier == CustomerPlan.STANDARD: elif tier == CustomerPlan.TIER_CLOUD_STANDARD:
plan_type = RemoteZulipServer.PLAN_TYPE_BUSINESS plan_type = RemoteZulipServer.PLAN_TYPE_BUSINESS
elif tier == CustomerPlan.PLUS: # nocoverage # Plus plan doesn't use this code path yet. elif (
tier == CustomerPlan.TIER_CLOUD_PLUS
): # nocoverage # Plus plan doesn't use this code path yet.
plan_type = RemoteZulipServer.PLAN_TYPE_ENTERPRISE plan_type = RemoteZulipServer.PLAN_TYPE_ENTERPRISE
else: else:
raise AssertionError("Unexpected tier") raise AssertionError("Unexpected tier")
@ -2651,14 +2657,14 @@ def get_price_per_license(
) -> int: ) -> int:
price_per_license: Optional[int] = None price_per_license: Optional[int] = None
if tier == CustomerPlan.STANDARD: if tier == CustomerPlan.TIER_CLOUD_STANDARD:
if billing_schedule == CustomerPlan.ANNUAL: if billing_schedule == CustomerPlan.ANNUAL:
price_per_license = 8000 price_per_license = 8000
elif billing_schedule == CustomerPlan.MONTHLY: elif billing_schedule == CustomerPlan.MONTHLY:
price_per_license = 800 price_per_license = 800
else: # nocoverage else: # nocoverage
raise InvalidBillingScheduleError(billing_schedule) raise InvalidBillingScheduleError(billing_schedule)
elif tier == CustomerPlan.PLUS: elif tier == CustomerPlan.TIER_CLOUD_PLUS:
if billing_schedule == CustomerPlan.ANNUAL: if billing_schedule == CustomerPlan.ANNUAL:
price_per_license = 16000 price_per_license = 16000
elif billing_schedule == CustomerPlan.MONTHLY: elif billing_schedule == CustomerPlan.MONTHLY:

View File

@ -128,7 +128,7 @@ def handle_payment_intent_succeeded_event(
billing_session = RealmBillingSession(user) billing_session = RealmBillingSession(user)
billing_session.process_initial_upgrade( billing_session.process_initial_upgrade(
CustomerPlan.STANDARD, CustomerPlan.TIER_CLOUD_STANDARD,
int(metadata["licenses"]), int(metadata["licenses"]),
metadata["license_management"] == "automatic", metadata["license_management"] == "automatic",
int(metadata["billing_schedule"]), int(metadata["billing_schedule"]),

View File

@ -52,4 +52,4 @@ def update_realm_billing_method(
def switch_realm_from_standard_to_plus_plan(realm: Realm) -> None: def switch_realm_from_standard_to_plus_plan(realm: Realm) -> None:
billing_session = RealmBillingSession(realm=realm) billing_session = RealmBillingSession(realm=realm)
billing_session.do_change_plan_to_new_tier(new_plan_tier=CustomerPlan.PLUS) billing_session.do_change_plan_to_new_tier(new_plan_tier=CustomerPlan.TIER_CLOUD_PLUS)

View File

@ -256,9 +256,18 @@ class CustomerPlan(models.Model):
# state. # state.
invoicing_status = models.SmallIntegerField(default=DONE) invoicing_status = models.SmallIntegerField(default=DONE)
STANDARD = 1 TIER_CLOUD_STANDARD = 1
PLUS = 2 # not available through self-serve signup TIER_CLOUD_PLUS = 2
ENTERPRISE = 10 # Reserved tier IDs for future use
TIER_CLOUD_COMMUNITY = 3
TIER_CLOUD_ENTERPRISE = 4
TIER_SELF_HOSTED_BASE = 100
TIER_SELF_HOSTED_LEGACY = 101
TIER_SELF_HOSTED_COMMUNITY = 102
TIER_SELF_HOSTED_BUSINESS = 103
TIER_SELF_HOSTED_PLUS = 104
TIER_SELF_HOSTED_ENTERPRISE = 105
tier = models.SmallIntegerField() tier = models.SmallIntegerField()
ACTIVE = 1 ACTIVE = 1
@ -281,9 +290,9 @@ class CustomerPlan(models.Model):
@property @property
def name(self) -> str: def name(self) -> str:
return { return {
CustomerPlan.STANDARD: "Zulip Cloud Standard", CustomerPlan.TIER_CLOUD_STANDARD: "Zulip Cloud Standard",
CustomerPlan.PLUS: "Zulip Plus", CustomerPlan.TIER_CLOUD_PLUS: "Zulip Plus",
CustomerPlan.ENTERPRISE: "Zulip Enterprise", CustomerPlan.TIER_CLOUD_ENTERPRISE: "Zulip Enterprise",
}[self.tier] }[self.tier]
def get_plan_status_as_text(self) -> str: def get_plan_status_as_text(self) -> str:

View File

@ -669,7 +669,7 @@ class StripeTestCase(ZulipTestCase):
hamlet = self.example_user("hamlet") hamlet = self.example_user("hamlet")
billing_session = RealmBillingSession(hamlet) billing_session = RealmBillingSession(hamlet)
return billing_session.process_initial_upgrade( return billing_session.process_initial_upgrade(
CustomerPlan.STANDARD, CustomerPlan.TIER_CLOUD_STANDARD,
licenses, licenses,
automanage_licenses, automanage_licenses,
billing_schedule, billing_schedule,
@ -824,7 +824,7 @@ class StripeTest(StripeTestCase):
billing_schedule=CustomerPlan.ANNUAL, billing_schedule=CustomerPlan.ANNUAL,
invoiced_through=LicenseLedger.objects.first(), invoiced_through=LicenseLedger.objects.first(),
next_invoice_date=self.next_month, next_invoice_date=self.next_month,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
status=CustomerPlan.ACTIVE, status=CustomerPlan.ACTIVE,
) )
LicenseLedger.objects.get( LicenseLedger.objects.get(
@ -973,7 +973,7 @@ class StripeTest(StripeTestCase):
billing_schedule=CustomerPlan.ANNUAL, billing_schedule=CustomerPlan.ANNUAL,
invoiced_through=LicenseLedger.objects.first(), invoiced_through=LicenseLedger.objects.first(),
next_invoice_date=self.next_year, next_invoice_date=self.next_year,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
status=CustomerPlan.ACTIVE, status=CustomerPlan.ACTIVE,
) )
LicenseLedger.objects.get( LicenseLedger.objects.get(
@ -1083,7 +1083,7 @@ class StripeTest(StripeTestCase):
billing_schedule=CustomerPlan.ANNUAL, billing_schedule=CustomerPlan.ANNUAL,
invoiced_through=LicenseLedger.objects.first(), invoiced_through=LicenseLedger.objects.first(),
next_invoice_date=free_trial_end_date, next_invoice_date=free_trial_end_date,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
status=CustomerPlan.FREE_TRIAL, status=CustomerPlan.FREE_TRIAL,
# For payment through card. # For payment through card.
charge_automatically=True, charge_automatically=True,
@ -1293,7 +1293,7 @@ class StripeTest(StripeTestCase):
billing_schedule=CustomerPlan.ANNUAL, billing_schedule=CustomerPlan.ANNUAL,
invoiced_through=LicenseLedger.objects.first(), invoiced_through=LicenseLedger.objects.first(),
next_invoice_date=free_trial_end_date, next_invoice_date=free_trial_end_date,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
status=CustomerPlan.FREE_TRIAL, status=CustomerPlan.FREE_TRIAL,
# For invoice billing. # For invoice billing.
charge_automatically=False, charge_automatically=False,
@ -1972,7 +1972,7 @@ class StripeTest(StripeTestCase):
customer=customer, customer=customer,
billing_cycle_anchor=timezone_now(), billing_cycle_anchor=timezone_now(),
billing_schedule=CustomerPlan.ANNUAL, billing_schedule=CustomerPlan.ANNUAL,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
) )
response = self.client_get("/upgrade/") response = self.client_get("/upgrade/")
self.assertEqual(response.status_code, 302) self.assertEqual(response.status_code, 302)
@ -2892,7 +2892,7 @@ class StripeTest(StripeTestCase):
billing_schedule=CustomerPlan.ANNUAL, billing_schedule=CustomerPlan.ANNUAL,
invoiced_through=None, invoiced_through=None,
next_invoice_date=free_trial_end_date, next_invoice_date=free_trial_end_date,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
status=CustomerPlan.FREE_TRIAL, status=CustomerPlan.FREE_TRIAL,
charge_automatically=True, charge_automatically=True,
) )
@ -2946,7 +2946,7 @@ class StripeTest(StripeTestCase):
billing_schedule=CustomerPlan.MONTHLY, billing_schedule=CustomerPlan.MONTHLY,
invoiced_through=None, invoiced_through=None,
next_invoice_date=free_trial_end_date, next_invoice_date=free_trial_end_date,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
status=CustomerPlan.FREE_TRIAL, status=CustomerPlan.FREE_TRIAL,
charge_automatically=True, charge_automatically=True,
) )
@ -3805,7 +3805,7 @@ class StripeTest(StripeTestCase):
# Test upgrading to Plus when realm has no active subscription # Test upgrading to Plus when realm has no active subscription
with self.assertRaises(BillingError) as billing_context: with self.assertRaises(BillingError) as billing_context:
iago_billing_session.do_change_plan_to_new_tier(CustomerPlan.PLUS) iago_billing_session.do_change_plan_to_new_tier(CustomerPlan.TIER_CLOUD_PLUS)
self.assertEqual( self.assertEqual(
"Organization does not have an active plan", "Organization does not have an active plan",
billing_context.exception.error_description, billing_context.exception.error_description,
@ -3816,7 +3816,7 @@ class StripeTest(StripeTestCase):
) )
# Test upgrading to Plus when realm has no stripe_customer_id # Test upgrading to Plus when realm has no stripe_customer_id
with self.assertRaises(BillingError) as billing_context: with self.assertRaises(BillingError) as billing_context:
iago_billing_session.do_change_plan_to_new_tier(CustomerPlan.PLUS) iago_billing_session.do_change_plan_to_new_tier(CustomerPlan.TIER_CLOUD_PLUS)
self.assertEqual( self.assertEqual(
"Organization missing Stripe customer.", billing_context.exception.error_description "Organization missing Stripe customer.", billing_context.exception.error_description
) )
@ -3830,7 +3830,7 @@ class StripeTest(StripeTestCase):
automanage_licenses=True, automanage_licenses=True,
billing_cycle_anchor=timezone_now(), billing_cycle_anchor=timezone_now(),
billing_schedule=CustomerPlan.MONTHLY, billing_schedule=CustomerPlan.MONTHLY,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
) )
ledger = LicenseLedger.objects.create( ledger = LicenseLedger.objects.create(
plan=plan, plan=plan,
@ -3842,22 +3842,24 @@ class StripeTest(StripeTestCase):
realm.plan_type = Realm.PLAN_TYPE_STANDARD realm.plan_type = Realm.PLAN_TYPE_STANDARD
realm.save(update_fields=["plan_type"]) realm.save(update_fields=["plan_type"])
plan.invoiced_through = ledger plan.invoiced_through = ledger
plan.price_per_license = get_price_per_license(CustomerPlan.STANDARD, CustomerPlan.MONTHLY) plan.price_per_license = get_price_per_license(
CustomerPlan.TIER_CLOUD_STANDARD, CustomerPlan.MONTHLY
)
plan.save(update_fields=["invoiced_through", "price_per_license"]) plan.save(update_fields=["invoiced_through", "price_per_license"])
with self.assertRaises(BillingError) as billing_context: with self.assertRaises(BillingError) as billing_context:
king_billing_session.do_change_plan_to_new_tier(CustomerPlan.STANDARD) king_billing_session.do_change_plan_to_new_tier(CustomerPlan.TIER_CLOUD_STANDARD)
self.assertEqual( self.assertEqual(
"Invalid change of customer plan tier.", billing_context.exception.error_description "Invalid change of customer plan tier.", billing_context.exception.error_description
) )
king_billing_session.do_change_plan_to_new_tier(CustomerPlan.PLUS) king_billing_session.do_change_plan_to_new_tier(CustomerPlan.TIER_CLOUD_PLUS)
plan.refresh_from_db() plan.refresh_from_db()
self.assertEqual(plan.status, CustomerPlan.ENDED) self.assertEqual(plan.status, CustomerPlan.ENDED)
plus_plan = get_current_plan_by_realm(realm) plus_plan = get_current_plan_by_realm(realm)
assert plus_plan is not None assert plus_plan is not None
self.assertEqual(plus_plan.tier, CustomerPlan.PLUS) self.assertEqual(plus_plan.tier, CustomerPlan.TIER_CLOUD_PLUS)
self.assertEqual(LicenseLedger.objects.filter(plan=plus_plan).count(), 1) self.assertEqual(LicenseLedger.objects.filter(plan=plus_plan).count(), 1)
realm.refresh_from_db() realm.refresh_from_db()
@ -4221,45 +4223,45 @@ class BillingHelpersTest(ZulipTestCase):
test_cases = [ test_cases = [
# test all possibilities, since there aren't that many # test all possibilities, since there aren't that many
( (
(CustomerPlan.STANDARD, True, CustomerPlan.ANNUAL, None), (CustomerPlan.TIER_CLOUD_STANDARD, True, CustomerPlan.ANNUAL, None),
(anchor, month_later, year_later, 8000), (anchor, month_later, year_later, 8000),
), ),
( (
(CustomerPlan.STANDARD, True, CustomerPlan.ANNUAL, 85), (CustomerPlan.TIER_CLOUD_STANDARD, True, CustomerPlan.ANNUAL, 85),
(anchor, month_later, year_later, 1200), (anchor, month_later, year_later, 1200),
), ),
( (
(CustomerPlan.STANDARD, True, CustomerPlan.MONTHLY, None), (CustomerPlan.TIER_CLOUD_STANDARD, True, CustomerPlan.MONTHLY, None),
(anchor, month_later, month_later, 800), (anchor, month_later, month_later, 800),
), ),
( (
(CustomerPlan.STANDARD, True, CustomerPlan.MONTHLY, 85), (CustomerPlan.TIER_CLOUD_STANDARD, True, CustomerPlan.MONTHLY, 85),
(anchor, month_later, month_later, 120), (anchor, month_later, month_later, 120),
), ),
( (
(CustomerPlan.STANDARD, False, CustomerPlan.ANNUAL, None), (CustomerPlan.TIER_CLOUD_STANDARD, False, CustomerPlan.ANNUAL, None),
(anchor, year_later, year_later, 8000), (anchor, year_later, year_later, 8000),
), ),
( (
(CustomerPlan.STANDARD, False, CustomerPlan.ANNUAL, 85), (CustomerPlan.TIER_CLOUD_STANDARD, False, CustomerPlan.ANNUAL, 85),
(anchor, year_later, year_later, 1200), (anchor, year_later, year_later, 1200),
), ),
( (
(CustomerPlan.STANDARD, False, CustomerPlan.MONTHLY, None), (CustomerPlan.TIER_CLOUD_STANDARD, False, CustomerPlan.MONTHLY, None),
(anchor, month_later, month_later, 800), (anchor, month_later, month_later, 800),
), ),
( (
(CustomerPlan.STANDARD, False, CustomerPlan.MONTHLY, 85), (CustomerPlan.TIER_CLOUD_STANDARD, False, CustomerPlan.MONTHLY, 85),
(anchor, month_later, month_later, 120), (anchor, month_later, month_later, 120),
), ),
# test exact math of Decimals; 800 * (1 - 87.25) = 101.9999999.. # test exact math of Decimals; 800 * (1 - 87.25) = 101.9999999..
( (
(CustomerPlan.STANDARD, False, CustomerPlan.MONTHLY, 87.25), (CustomerPlan.TIER_CLOUD_STANDARD, False, CustomerPlan.MONTHLY, 87.25),
(anchor, month_later, month_later, 102), (anchor, month_later, month_later, 102),
), ),
# test dropping of fractional cents; without the int it's 102.8 # test dropping of fractional cents; without the int it's 102.8
( (
(CustomerPlan.STANDARD, False, CustomerPlan.MONTHLY, 87.15), (CustomerPlan.TIER_CLOUD_STANDARD, False, CustomerPlan.MONTHLY, 87.15),
(anchor, month_later, month_later, 102), (anchor, month_later, month_later, 102),
), ),
] ]
@ -4274,27 +4276,37 @@ class BillingHelpersTest(ZulipTestCase):
self.assertEqual(output_, output) self.assertEqual(output_, output)
def test_get_price_per_license(self) -> None: def test_get_price_per_license(self) -> None:
self.assertEqual(get_price_per_license(CustomerPlan.STANDARD, CustomerPlan.ANNUAL), 8000) self.assertEqual(
self.assertEqual(get_price_per_license(CustomerPlan.STANDARD, CustomerPlan.MONTHLY), 800) get_price_per_license(CustomerPlan.TIER_CLOUD_STANDARD, CustomerPlan.ANNUAL), 8000
)
self.assertEqual(
get_price_per_license(CustomerPlan.TIER_CLOUD_STANDARD, CustomerPlan.MONTHLY), 800
)
self.assertEqual( self.assertEqual(
get_price_per_license( get_price_per_license(
CustomerPlan.STANDARD, CustomerPlan.MONTHLY, discount=Decimal(50) CustomerPlan.TIER_CLOUD_STANDARD, CustomerPlan.MONTHLY, discount=Decimal(50)
), ),
400, 400,
) )
self.assertEqual(get_price_per_license(CustomerPlan.PLUS, CustomerPlan.ANNUAL), 16000)
self.assertEqual(get_price_per_license(CustomerPlan.PLUS, CustomerPlan.MONTHLY), 1600)
self.assertEqual( self.assertEqual(
get_price_per_license(CustomerPlan.PLUS, CustomerPlan.MONTHLY, discount=Decimal(50)), get_price_per_license(CustomerPlan.TIER_CLOUD_PLUS, CustomerPlan.ANNUAL), 16000
)
self.assertEqual(
get_price_per_license(CustomerPlan.TIER_CLOUD_PLUS, CustomerPlan.MONTHLY), 1600
)
self.assertEqual(
get_price_per_license(
CustomerPlan.TIER_CLOUD_PLUS, CustomerPlan.MONTHLY, discount=Decimal(50)
),
800, 800,
) )
with self.assertRaisesRegex(InvalidBillingScheduleError, "Unknown billing_schedule: 1000"): with self.assertRaisesRegex(InvalidBillingScheduleError, "Unknown billing_schedule: 1000"):
get_price_per_license(CustomerPlan.STANDARD, 1000) get_price_per_license(CustomerPlan.TIER_CLOUD_STANDARD, 1000)
with self.assertRaisesRegex(InvalidTierError, "Unknown tier: 10"): with self.assertRaisesRegex(InvalidTierError, "Unknown tier: 4"):
get_price_per_license(CustomerPlan.ENTERPRISE, CustomerPlan.ANNUAL) get_price_per_license(CustomerPlan.TIER_CLOUD_ENTERPRISE, CustomerPlan.ANNUAL)
def test_get_plan_renewal_or_end_date(self) -> None: def test_get_plan_renewal_or_end_date(self) -> None:
realm = get_realm("zulip") realm = get_realm("zulip")
@ -4305,7 +4317,7 @@ class BillingHelpersTest(ZulipTestCase):
status=CustomerPlan.ACTIVE, status=CustomerPlan.ACTIVE,
billing_cycle_anchor=billing_cycle_anchor, billing_cycle_anchor=billing_cycle_anchor,
billing_schedule=CustomerPlan.MONTHLY, billing_schedule=CustomerPlan.MONTHLY,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
) )
renewal_date = get_plan_renewal_or_end_date(plan, billing_cycle_anchor) renewal_date = get_plan_renewal_or_end_date(plan, billing_cycle_anchor)
self.assertEqual(renewal_date, add_months(billing_cycle_anchor, 1)) self.assertEqual(renewal_date, add_months(billing_cycle_anchor, 1))
@ -4374,7 +4386,7 @@ class BillingHelpersTest(ZulipTestCase):
status=CustomerPlan.ACTIVE, status=CustomerPlan.ACTIVE,
billing_cycle_anchor=timezone_now(), billing_cycle_anchor=timezone_now(),
billing_schedule=CustomerPlan.ANNUAL, billing_schedule=CustomerPlan.ANNUAL,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
) )
self.assertEqual(get_current_plan_by_customer(customer), plan) self.assertEqual(get_current_plan_by_customer(customer), plan)
@ -4403,7 +4415,7 @@ class BillingHelpersTest(ZulipTestCase):
status=CustomerPlan.ACTIVE, status=CustomerPlan.ACTIVE,
billing_cycle_anchor=timezone_now(), billing_cycle_anchor=timezone_now(),
billing_schedule=CustomerPlan.ANNUAL, billing_schedule=CustomerPlan.ANNUAL,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
) )
self.assertEqual(get_current_plan_by_realm(realm), plan) self.assertEqual(get_current_plan_by_realm(realm), plan)
@ -4417,7 +4429,7 @@ class BillingHelpersTest(ZulipTestCase):
status=CustomerPlan.ACTIVE, status=CustomerPlan.ACTIVE,
billing_cycle_anchor=timezone_now(), billing_cycle_anchor=timezone_now(),
billing_schedule=CustomerPlan.ANNUAL, billing_schedule=CustomerPlan.ANNUAL,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
) )
self.assertFalse(is_realm_on_free_trial(realm)) self.assertFalse(is_realm_on_free_trial(realm))
@ -4871,7 +4883,7 @@ class TestTestClasses(ZulipTestCase):
plan.refresh_from_db() plan.refresh_from_db()
self.assertEqual(plan.automanage_licenses, False) self.assertEqual(plan.automanage_licenses, False)
self.assertEqual(plan.billing_schedule, CustomerPlan.ANNUAL) self.assertEqual(plan.billing_schedule, CustomerPlan.ANNUAL)
self.assertEqual(plan.tier, CustomerPlan.STANDARD) self.assertEqual(plan.tier, CustomerPlan.TIER_CLOUD_STANDARD)
self.assertEqual(plan.licenses(), 50) self.assertEqual(plan.licenses(), 50)
self.assertEqual(plan.licenses_at_next_renewal(), 60) self.assertEqual(plan.licenses_at_next_renewal(), 60)
@ -4892,7 +4904,7 @@ class TestTestClasses(ZulipTestCase):
plan.refresh_from_db() plan.refresh_from_db()
self.assertEqual(plan.automanage_licenses, False) self.assertEqual(plan.automanage_licenses, False)
self.assertEqual(plan.billing_schedule, CustomerPlan.MONTHLY) self.assertEqual(plan.billing_schedule, CustomerPlan.MONTHLY)
self.assertEqual(plan.tier, CustomerPlan.STANDARD) self.assertEqual(plan.tier, CustomerPlan.TIER_CLOUD_STANDARD)
self.assertEqual(plan.licenses(), 20) self.assertEqual(plan.licenses(), 20)
self.assertEqual(plan.licenses_at_next_renewal(), 30) self.assertEqual(plan.licenses_at_next_renewal(), 30)
@ -5110,7 +5122,7 @@ class TestSupportBillingHelpers(StripeTestCase):
status=CustomerPlan.ACTIVE, status=CustomerPlan.ACTIVE,
billing_cycle_anchor=timezone_now(), billing_cycle_anchor=timezone_now(),
billing_schedule=CustomerPlan.ANNUAL, billing_schedule=CustomerPlan.ANNUAL,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
) )
self.assertEqual(plan.charge_automatically, False) self.assertEqual(plan.charge_automatically, False)
@ -5146,10 +5158,10 @@ class TestSupportBillingHelpers(StripeTestCase):
assert customer is not None assert customer is not None
original_plan = get_current_plan_by_customer(customer) original_plan = get_current_plan_by_customer(customer)
assert original_plan is not None assert original_plan is not None
self.assertEqual(original_plan.tier, CustomerPlan.STANDARD) self.assertEqual(original_plan.tier, CustomerPlan.TIER_CLOUD_STANDARD)
switch_realm_from_standard_to_plus_plan(user.realm) switch_realm_from_standard_to_plus_plan(user.realm)
customer.refresh_from_db() customer.refresh_from_db()
new_plan = get_current_plan_by_customer(customer) new_plan = get_current_plan_by_customer(customer)
assert new_plan is not None assert new_plan is not None
self.assertEqual(new_plan.tier, CustomerPlan.PLUS) self.assertEqual(new_plan.tier, CustomerPlan.TIER_CLOUD_PLUS)

View File

@ -90,7 +90,7 @@ def upgrade_page(
initial_upgrade_request = InitialUpgradeRequest( initial_upgrade_request = InitialUpgradeRequest(
manual_license_management=manual_license_management, manual_license_management=manual_license_management,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
) )
billing_session = RealmBillingSession(user) billing_session = RealmBillingSession(user)
redirect_url, context = billing_session.get_initial_upgrade_context(initial_upgrade_request) redirect_url, context = billing_session.get_initial_upgrade_context(initial_upgrade_request)
@ -113,7 +113,7 @@ def remote_realm_upgrade_page(
) -> HttpResponse: # nocoverage ) -> HttpResponse: # nocoverage
initial_upgrade_request = InitialUpgradeRequest( initial_upgrade_request = InitialUpgradeRequest(
manual_license_management=manual_license_management, manual_license_management=manual_license_management,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
) )
billing_session = RemoteRealmBillingSession(remote_realm) billing_session = RemoteRealmBillingSession(remote_realm)
redirect_url, context = billing_session.get_initial_upgrade_context(initial_upgrade_request) redirect_url, context = billing_session.get_initial_upgrade_context(initial_upgrade_request)

View File

@ -1796,7 +1796,7 @@ Output:
automanage_licenses=False, automanage_licenses=False,
billing_cycle_anchor=timezone_now(), billing_cycle_anchor=timezone_now(),
billing_schedule=billing_schedule, billing_schedule=billing_schedule,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
) )
ledger = LicenseLedger.objects.create( ledger = LicenseLedger.objects.create(
plan=plan, plan=plan,

View File

@ -599,7 +599,7 @@ class PlansPageTest(ZulipTestCase):
customer = Customer.objects.create(realm=get_realm("zulip"), stripe_customer_id="cus_id") customer = Customer.objects.create(realm=get_realm("zulip"), stripe_customer_id="cus_id")
plan = CustomerPlan.objects.create( plan = CustomerPlan.objects.create(
customer=customer, customer=customer,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
status=CustomerPlan.FREE_TRIAL, status=CustomerPlan.FREE_TRIAL,
billing_cycle_anchor=timezone_now(), billing_cycle_anchor=timezone_now(),
billing_schedule=CustomerPlan.MONTHLY, billing_schedule=CustomerPlan.MONTHLY,

View File

@ -854,7 +854,7 @@ class HomeTest(ZulipTestCase):
billing_cycle_anchor=timezone_now(), billing_cycle_anchor=timezone_now(),
billing_schedule=CustomerPlan.ANNUAL, billing_schedule=CustomerPlan.ANNUAL,
next_invoice_date=timezone_now(), next_invoice_date=timezone_now(),
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
status=CustomerPlan.ENDED, status=CustomerPlan.ENDED,
) )
with self.settings(CORPORATE_ENABLED=True): with self.settings(CORPORATE_ENABLED=True):

View File

@ -48,12 +48,12 @@ class Command(BaseCommand):
CustomerProfile( CustomerProfile(
unique_id="annual-standard", unique_id="annual-standard",
billing_schedule=CustomerPlan.ANNUAL, billing_schedule=CustomerPlan.ANNUAL,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
), ),
CustomerProfile( CustomerProfile(
unique_id="annual-plus", unique_id="annual-plus",
billing_schedule=CustomerPlan.ANNUAL, billing_schedule=CustomerPlan.ANNUAL,
tier=CustomerPlan.PLUS, tier=CustomerPlan.TIER_CLOUD_PLUS,
), ),
CustomerProfile( CustomerProfile(
unique_id="monthly-free", unique_id="monthly-free",
@ -62,52 +62,52 @@ class Command(BaseCommand):
CustomerProfile( CustomerProfile(
unique_id="monthly-standard", unique_id="monthly-standard",
billing_schedule=CustomerPlan.MONTHLY, billing_schedule=CustomerPlan.MONTHLY,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
), ),
CustomerProfile( CustomerProfile(
unique_id="monthly-plus", unique_id="monthly-plus",
billing_schedule=CustomerPlan.MONTHLY, billing_schedule=CustomerPlan.MONTHLY,
tier=CustomerPlan.PLUS, tier=CustomerPlan.TIER_CLOUD_PLUS,
), ),
CustomerProfile( CustomerProfile(
unique_id="downgrade-end-of-cycle", unique_id="downgrade-end-of-cycle",
billing_schedule=CustomerPlan.MONTHLY, billing_schedule=CustomerPlan.MONTHLY,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
status=CustomerPlan.DOWNGRADE_AT_END_OF_CYCLE, status=CustomerPlan.DOWNGRADE_AT_END_OF_CYCLE,
), ),
CustomerProfile( CustomerProfile(
unique_id="standard-automanage-licenses", unique_id="standard-automanage-licenses",
billing_schedule=CustomerPlan.MONTHLY, billing_schedule=CustomerPlan.MONTHLY,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
automanage_licenses=True, automanage_licenses=True,
), ),
CustomerProfile( CustomerProfile(
unique_id="standard-automatic-card", unique_id="standard-automatic-card",
billing_schedule=CustomerPlan.MONTHLY, billing_schedule=CustomerPlan.MONTHLY,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
card="pm_card_visa", card="pm_card_visa",
), ),
CustomerProfile( CustomerProfile(
unique_id="standard-invoice-payment", unique_id="standard-invoice-payment",
billing_schedule=CustomerPlan.MONTHLY, billing_schedule=CustomerPlan.MONTHLY,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
charge_automatically=False, charge_automatically=False,
), ),
CustomerProfile( CustomerProfile(
unique_id="standard-switch-to-annual-eoc", unique_id="standard-switch-to-annual-eoc",
billing_schedule=CustomerPlan.MONTHLY, billing_schedule=CustomerPlan.MONTHLY,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
status=CustomerPlan.SWITCH_TO_ANNUAL_AT_END_OF_CYCLE, status=CustomerPlan.SWITCH_TO_ANNUAL_AT_END_OF_CYCLE,
), ),
CustomerProfile( CustomerProfile(
unique_id="sponsored", unique_id="sponsored",
is_sponsored=True, is_sponsored=True,
billing_schedule=CustomerPlan.MONTHLY, billing_schedule=CustomerPlan.MONTHLY,
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
), ),
CustomerProfile( CustomerProfile(
unique_id="free-trial", unique_id="free-trial",
tier=CustomerPlan.STANDARD, tier=CustomerPlan.TIER_CLOUD_STANDARD,
status=CustomerPlan.FREE_TRIAL, status=CustomerPlan.FREE_TRIAL,
), ),
] ]
@ -117,11 +117,14 @@ class Command(BaseCommand):
unique_id = customer_profile.unique_id unique_id = customer_profile.unique_id
if customer_profile.tier is None: if customer_profile.tier is None:
plan_type = Realm.PLAN_TYPE_LIMITED plan_type = Realm.PLAN_TYPE_LIMITED
elif customer_profile.tier == CustomerPlan.STANDARD and customer_profile.is_sponsored: elif (
customer_profile.tier == CustomerPlan.TIER_CLOUD_STANDARD
and customer_profile.is_sponsored
):
plan_type = Realm.PLAN_TYPE_STANDARD_FREE plan_type = Realm.PLAN_TYPE_STANDARD_FREE
elif customer_profile.tier == CustomerPlan.STANDARD: elif customer_profile.tier == CustomerPlan.TIER_CLOUD_STANDARD:
plan_type = Realm.PLAN_TYPE_STANDARD plan_type = Realm.PLAN_TYPE_STANDARD
elif customer_profile.tier == CustomerPlan.PLUS: elif customer_profile.tier == CustomerPlan.TIER_CLOUD_PLUS:
plan_type = Realm.PLAN_TYPE_PLUS plan_type = Realm.PLAN_TYPE_PLUS
else: else:
raise AssertionError("Unexpected tier!") raise AssertionError("Unexpected tier!")

View File

@ -25,4 +25,4 @@ class Command(ZulipBaseCommand):
if settings.BILLING_ENABLED: if settings.BILLING_ENABLED:
billing_session = RealmBillingSession(realm=realm) billing_session = RealmBillingSession(realm=realm)
billing_session.do_change_plan_to_new_tier(new_plan_tier=CustomerPlan.PLUS) billing_session.do_change_plan_to_new_tier(new_plan_tier=CustomerPlan.TIER_CLOUD_PLUS)