stripe: Create get_price_per_license function.

This commit is contained in:
Vishnu KS 2020-12-04 17:26:58 +05:30 committed by Tim Abbott
parent 023a33dc49
commit 71efcca679
2 changed files with 45 additions and 8 deletions

View File

@ -160,6 +160,11 @@ class StripeCardError(BillingError):
class StripeConnectionError(BillingError):
pass
class InvalidBillingSchedule(Exception):
def __init__(self, billing_schedule: int) -> None:
self.message = f"Unknown billing_schedule: {billing_schedule}"
super().__init__(self.message)
def catch_stripe_errors(func: CallableT) -> CallableT:
@wraps(func)
def wrapped(*args: object, **kwargs: object) -> object:
@ -325,6 +330,21 @@ def update_or_create_stripe_customer(user: UserProfile, stripe_token: Optional[s
do_replace_payment_source(user, stripe_token)
return customer
def get_price_per_license(tier: int, billing_schedule: int, discount: Optional[Decimal]=None) -> int:
# TODO use variables to account for Zulip Plus
assert(tier == CustomerPlan.STANDARD)
price_per_license: Optional[int] = None
if billing_schedule == CustomerPlan.ANNUAL:
price_per_license = 8000
elif billing_schedule == CustomerPlan.MONTHLY:
price_per_license = 800
else: # nocoverage
raise InvalidBillingSchedule(billing_schedule)
if discount is not None:
price_per_license = int(float(price_per_license * (1 - discount / 100)) + .00001)
return price_per_license
def compute_plan_parameters(
automanage_licenses: bool, billing_schedule: int,
discount: Optional[Decimal],
@ -334,17 +354,14 @@ def compute_plan_parameters(
# TODO talk about leapseconds?
billing_cycle_anchor = timezone_now().replace(microsecond=0)
if billing_schedule == CustomerPlan.ANNUAL:
# TODO use variables to account for Zulip Plus
price_per_license = 8000
period_end = add_months(billing_cycle_anchor, 12)
elif billing_schedule == CustomerPlan.MONTHLY:
price_per_license = 800
period_end = add_months(billing_cycle_anchor, 1)
else:
raise AssertionError(f'Unknown billing_schedule: {billing_schedule}')
if discount is not None:
# There are no fractional cents in Stripe, so round down to nearest integer.
price_per_license = int(float(price_per_license * (1 - discount / 100)) + .00001)
else: # nocoverage
raise InvalidBillingSchedule(billing_schedule)
price_per_license = get_price_per_license(CustomerPlan.STANDARD, billing_schedule, discount)
next_invoice_date = period_end
if automanage_licenses:
next_invoice_date = add_months(billing_cycle_anchor, 1)

View File

@ -22,6 +22,7 @@ from corporate.lib.stripe import (
MAX_INVOICED_LICENSES,
MIN_INVOICED_LICENSES,
BillingError,
InvalidBillingSchedule,
StripeCardError,
add_months,
attach_discount_to_realm,
@ -29,6 +30,7 @@ from corporate.lib.stripe import (
compute_plan_parameters,
get_discount_for_realm,
get_latest_seat_count,
get_price_per_license,
invoice_plan,
invoice_plans_as_needed,
make_end_of_cycle_updates_if_needed,
@ -1986,6 +1988,24 @@ class BillingHelpersTest(ZulipTestCase):
)
self.assertEqual(output_, output)
def test_get_price_per_license(self) -> None:
self.assertEqual(
get_price_per_license(CustomerPlan.STANDARD, CustomerPlan.ANNUAL), 8000
)
self.assertEqual(
get_price_per_license(CustomerPlan.STANDARD, CustomerPlan.MONTHLY), 800
)
self.assertEqual(
get_price_per_license(CustomerPlan.STANDARD, CustomerPlan.MONTHLY, discount=Decimal(50)),
400
)
with self.assertRaises(AssertionError):
get_price_per_license(CustomerPlan.PLUS, CustomerPlan.MONTHLY)
with self.assertRaisesRegex(InvalidBillingSchedule, "Unknown billing_schedule: 1000"):
get_price_per_license(CustomerPlan.STANDARD, 1000)
def test_update_or_create_stripe_customer_logic(self) -> None:
user = self.example_user('hamlet')
# No existing Customer object