stripe: Show tier information correctly on billing and upgrade page.

This commit is contained in:
Aman Agrawal 2023-12-02 03:21:50 +00:00 committed by Tim Abbott
parent 785444b2b8
commit f942bbd70f
564 changed files with 58 additions and 75 deletions

View File

@ -500,6 +500,7 @@ class UpgradeRequest:
salt: str
license_management: Optional[str]
licenses: Optional[int]
tier: int
@dataclass
@ -677,11 +678,29 @@ class BillingSession(ABC):
) -> Dict[str, Any]:
pass
@abstractmethod
def get_data_for_stripe_payment_intent(
self, price_per_license: int, licenses: int
self,
price_per_license: int,
licenses: int,
plan_tier: int,
email: str,
) -> StripePaymentIntentData:
pass
if hasattr(self, "support_session") and self.support_session: # nocoverage
raise BillingError(
"invalid support session",
"Support requests do not set any stripe billing information.",
)
amount = price_per_license * licenses
plan_name = CustomerPlan.name_from_tier(plan_tier)
description = f"Upgrade to {plan_name}, ${price_per_license/100} x {licenses}"
return StripePaymentIntentData(
amount=amount,
description=description,
plan_name=plan_name,
email=email,
)
@abstractmethod
def update_or_create_customer(
@ -807,7 +826,9 @@ class BillingSession(ABC):
# NOTE: This charges users immediately.
customer = self.get_customer()
assert customer is not None and customer.stripe_customer_id is not None
payment_intent_data = self.get_data_for_stripe_payment_intent(price_per_license, licenses)
payment_intent_data = self.get_data_for_stripe_payment_intent(
price_per_license, licenses, metadata["plan_tier"], self.get_email()
)
# Ensure customers have a default payment method set.
stripe_customer = stripe_get_customer(customer.stripe_customer_id)
if not stripe_customer_has_credit_card_as_default_payment_method(stripe_customer):
@ -979,6 +1000,7 @@ class BillingSession(ABC):
"price_per_license": price_per_license,
"seat_count": seat_count,
"type": "upgrade",
"plan_tier": plan_tier,
}
updated_metadata = self.update_data_for_checkout_session_and_payment_intent(
general_metadata
@ -1138,7 +1160,7 @@ class BillingSession(ABC):
# Directly upgrade free trial orgs or invoice payment orgs to standard plan.
if free_trial or not charge_automatically:
self.process_initial_upgrade(
CustomerPlan.TIER_CLOUD_STANDARD,
upgrade_request.tier,
licenses,
automanage_licenses,
billing_schedule,
@ -1148,7 +1170,7 @@ class BillingSession(ABC):
data["organization_upgrade_successful"] = True
else:
stripe_payment_intent_id = self.setup_upgrade_payment_intent_and_charge(
CustomerPlan.TIER_CLOUD_STANDARD,
upgrade_request.tier,
seat_count,
licenses,
license_management,
@ -1480,6 +1502,7 @@ class BillingSession(ABC):
"price_per_license": price_per_license,
"is_sponsorship_pending": customer.sponsorship_pending,
"discount_percent": format_discount_percentage(customer.default_discount),
"is_self_hosted_billing": not isinstance(self, RealmBillingSession),
}
return context
@ -2216,26 +2239,6 @@ class RealmBillingSession(BillingSession):
)
return updated_metadata
@override
def get_data_for_stripe_payment_intent(
self, price_per_license: int, licenses: int
) -> StripePaymentIntentData:
# Support requests do not set any stripe billing information.
assert self.support_session is False
assert self.user is not None
amount = price_per_license * licenses
# TODO: Don't hardcode plan name; it should be looked up for
# the tier.
description = f"Upgrade to Zulip Cloud Standard, ${price_per_license/100} x {licenses}"
plan_name = "Zulip Cloud Standard"
return StripePaymentIntentData(
amount=amount,
description=description,
plan_name=plan_name,
email=self.get_email(),
)
@override
def update_or_create_customer(
self, stripe_customer_id: Optional[str] = None, *, defaults: Optional[Dict[str, Any]] = None
@ -2532,23 +2535,6 @@ class RemoteRealmBillingSession(BillingSession): # nocoverage
)
return updated_metadata
@override
def get_data_for_stripe_payment_intent(
self, price_per_license: int, licenses: int
) -> StripePaymentIntentData:
# Support requests do not set any stripe billing information.
assert self.support_session is False
amount = price_per_license * licenses
# TODO: Don't hardcode plan names.
description = f"Upgrade to Zulip X Standard, ${price_per_license/100} x {licenses}"
plan_name = "Zulip X Standard"
return StripePaymentIntentData(
amount=amount,
description=description,
plan_name=plan_name,
email=self.get_email(),
)
@override
def update_or_create_customer(
self, stripe_customer_id: Optional[str] = None, *, defaults: Optional[Dict[str, Any]] = None
@ -2569,22 +2555,18 @@ class RemoteRealmBillingSession(BillingSession): # nocoverage
@override
def do_change_plan_type(self, *, tier: Optional[int], is_sponsored: bool = False) -> None:
# TODO: Create actual plan types.
# This function needs to translate between the different
# formats of CustomerPlan.tier and Realm.plan_type.
if is_sponsored:
plan_type = RemoteRealm.PLAN_TYPE_COMMUNITY
elif tier == CustomerPlan.TIER_CLOUD_STANDARD:
elif tier == CustomerPlan.TIER_SELF_HOSTED_BUSINESS:
plan_type = RemoteRealm.PLAN_TYPE_BUSINESS
elif (
tier == CustomerPlan.TIER_CLOUD_PLUS
tier == CustomerPlan.TIER_SELF_HOSTED_PLUS
): # nocoverage # Plus plan doesn't use this code path yet.
plan_type = RemoteRealm.PLAN_TYPE_ENTERPRISE
else:
raise AssertionError("Unexpected tier")
# TODO: Audit logging.
# TODO: Audit logging and set usage limits.
self.remote_realm.plan_type = plan_type
self.remote_realm.save(update_fields=["plan_type"])
@ -2817,22 +2799,6 @@ class RemoteServerBillingSession(BillingSession): # nocoverage
)
return updated_metadata
@override
def get_data_for_stripe_payment_intent(
self, price_per_license: int, licenses: int
) -> StripePaymentIntentData:
# Support requests do not set any stripe billing information.
assert self.support_session is False
amount = price_per_license * licenses
description = f"Upgrade to Zulip X Standard, ${price_per_license/100} x {licenses}"
plan_name = "Zulip X Standard"
return StripePaymentIntentData(
amount=amount,
description=description,
plan_name=plan_name,
email=self.get_email(),
)
@override
def update_or_create_customer(
self, stripe_customer_id: Optional[str] = None, *, defaults: Optional[Dict[str, Any]] = None
@ -2859,16 +2825,16 @@ class RemoteServerBillingSession(BillingSession): # nocoverage
# formats of CustomerPlan.tier and RealmZulipServer.plan_type.
if is_sponsored:
plan_type = RemoteZulipServer.PLAN_TYPE_COMMUNITY
elif tier == CustomerPlan.TIER_CLOUD_STANDARD:
elif tier == CustomerPlan.TIER_SELF_HOSTED_BUSINESS:
plan_type = RemoteZulipServer.PLAN_TYPE_BUSINESS
elif (
tier == CustomerPlan.TIER_CLOUD_PLUS
tier == CustomerPlan.TIER_SELF_HOSTED_PLUS
): # nocoverage # Plus plan doesn't use this code path yet.
plan_type = RemoteZulipServer.PLAN_TYPE_ENTERPRISE
else:
raise AssertionError("Unexpected tier")
# TODO: Audit logging.
# TODO: Audit logging and set usage limits.
self.remote_server.plan_type = plan_type
self.remote_server.save(update_fields=["plan_type"])

View File

@ -123,6 +123,7 @@ def handle_payment_intent_succeeded_event(
description=description,
discountable=False,
)
plan_tier = int(metadata["plan_tier"])
try:
ensure_customer_does_not_have_active_plan(payment_intent.customer)
except UpgradeWithExistingPlanError as e:
@ -131,7 +132,8 @@ def handle_payment_intent_succeeded_event(
collection_method="charge_automatically",
customer=stripe_payment_intent.customer,
days_until_due=None,
statement_descriptor="Cloud Standard Credit",
statement_descriptor=CustomerPlan.name_from_tier(plan_tier).replace("Zulip ", "")
+ " Credit",
)
stripe.Invoice.finalize_invoice(stripe_invoice)
raise e
@ -140,7 +142,7 @@ def handle_payment_intent_succeeded_event(
payment_intent.customer, metadata.get("user_id")
)
billing_session.process_initial_upgrade(
CustomerPlan.TIER_CLOUD_STANDARD,
plan_tier,
int(metadata["licenses"]),
metadata["license_management"] == "automatic",
int(metadata["billing_schedule"]),

Some files were not shown because too many files have changed in this diff Show More