mirror of https://github.com/zulip/zulip.git
billing: Refactor BillingError to subclass JsonableError.
This lets us remove unnecessary BillingError to json_error conversion code.
This commit is contained in:
parent
53e2193b10
commit
72f9f964a1
|
@ -26,6 +26,7 @@ from corporate.models import (
|
|||
get_current_plan_by_realm,
|
||||
get_customer_by_realm,
|
||||
)
|
||||
from zerver.lib.exceptions import JsonableError
|
||||
from zerver.lib.logging_util import log_to_file
|
||||
from zerver.lib.send_email import FromAddress, send_email_to_billing_admins_and_realm_owners
|
||||
from zerver.lib.timestamp import datetime_to_timestamp, timestamp_to_datetime
|
||||
|
@ -196,17 +197,18 @@ def cents_to_dollar_string(cents: int) -> str:
|
|||
return f"{cents / 100.:,.2f}"
|
||||
|
||||
|
||||
class BillingError(Exception):
|
||||
class BillingError(JsonableError):
|
||||
data_fields = ["error_description"]
|
||||
# error messages
|
||||
CONTACT_SUPPORT = gettext_lazy("Something went wrong. Please contact {email}.")
|
||||
TRY_RELOADING = gettext_lazy("Something went wrong. Please reload the page.")
|
||||
|
||||
# description is used only for tests
|
||||
def __init__(self, description: str, message: Optional[str] = None) -> None:
|
||||
self.description = description
|
||||
self.error_description = description
|
||||
if message is None:
|
||||
message = BillingError.CONTACT_SUPPORT.format(email=settings.ZULIP_ADMINISTRATOR)
|
||||
self.message = message
|
||||
super().__init__(message)
|
||||
|
||||
|
||||
class LicenseLimitError(Exception):
|
||||
|
|
|
@ -464,7 +464,7 @@ class StripeTest(StripeTestCase):
|
|||
with self.assertLogs("corporate.stripe", "ERROR") as error_log:
|
||||
with self.assertRaises(BillingError) as context:
|
||||
raise_invalid_request_error()
|
||||
self.assertEqual("other stripe error", context.exception.description)
|
||||
self.assertEqual("other stripe error", context.exception.error_description)
|
||||
self.assertEqual(
|
||||
error_log.output, ["ERROR:corporate.stripe:Stripe error: None None None None"]
|
||||
)
|
||||
|
@ -480,8 +480,8 @@ class StripeTest(StripeTestCase):
|
|||
with self.assertLogs("corporate.stripe", "INFO") as info_log:
|
||||
with self.assertRaises(StripeCardError) as context:
|
||||
raise_card_error()
|
||||
self.assertIn("not a valid credit card", context.exception.message)
|
||||
self.assertEqual("card error", context.exception.description)
|
||||
self.assertIn("not a valid credit card", str(context.exception))
|
||||
self.assertEqual("card error", context.exception.error_description)
|
||||
self.assertEqual(
|
||||
info_log.output, ["INFO:corporate.stripe:Stripe card error: None None None None"]
|
||||
)
|
||||
|
@ -1305,7 +1305,9 @@ class StripeTest(StripeTestCase):
|
|||
with self.assertLogs("corporate.stripe", "WARNING") as m:
|
||||
with self.assertRaises(BillingError) as context:
|
||||
self.local_upgrade(self.seat_count, True, CustomerPlan.ANNUAL, "token")
|
||||
self.assertEqual("subscribing with existing subscription", context.exception.description)
|
||||
self.assertEqual(
|
||||
"subscribing with existing subscription", context.exception.error_description
|
||||
)
|
||||
self.assertEqual(
|
||||
m.output[0],
|
||||
f"WARNING:corporate.stripe:Customer <Customer <Realm: zulip {hamlet.realm.id}> id> trying to upgrade, but has an active subscription",
|
||||
|
@ -2336,7 +2338,9 @@ class StripeTest(StripeTestCase):
|
|||
m.output[0],
|
||||
f"WARNING:corporate.stripe:Customer <Customer <Realm: zulip {user.realm.id}> id> trying to upgrade, but has an active subscription",
|
||||
)
|
||||
self.assertEqual(context.exception.description, "subscribing with existing subscription")
|
||||
self.assertEqual(
|
||||
context.exception.error_description, "subscribing with existing subscription"
|
||||
)
|
||||
|
||||
invoice_plans_as_needed(self.next_year)
|
||||
|
||||
|
@ -3384,10 +3388,12 @@ class InvoiceTest(StripeTestCase):
|
|||
assert plan and plan.customer
|
||||
plan.customer.stripe_customer_id = None
|
||||
plan.customer.save(update_fields=["stripe_customer_id"])
|
||||
with self.assertRaisesRegex(
|
||||
BillingError, "Realm zulip has a paid plan without a Stripe customer"
|
||||
):
|
||||
with self.assertRaises(BillingError) as context:
|
||||
invoice_plan(plan, timezone_now())
|
||||
self.assertRegex(
|
||||
context.exception.error_description,
|
||||
"Realm zulip has a paid plan without a Stripe customer",
|
||||
)
|
||||
|
||||
@mock_stripe()
|
||||
def test_invoice_plan(self, *mocks: Mock) -> None:
|
||||
|
|
|
@ -49,7 +49,7 @@ from zerver.decorator import (
|
|||
from zerver.lib.actions import do_make_user_billing_admin
|
||||
from zerver.lib.exceptions import JsonableError
|
||||
from zerver.lib.request import REQ, has_request_variables
|
||||
from zerver.lib.response import json_error, json_success
|
||||
from zerver.lib.response import json_success
|
||||
from zerver.lib.send_email import FromAddress, send_email
|
||||
from zerver.lib.validator import check_int, check_int_in, check_string_in
|
||||
from zerver.models import UserProfile, get_realm
|
||||
|
@ -156,7 +156,7 @@ def upgrade(
|
|||
billing_logger.warning(
|
||||
"BillingError during upgrade: %s. user=%s, realm=%s (%s), billing_modality=%s, "
|
||||
"schedule=%s, license_management=%s, licenses=%s, has stripe_token: %s",
|
||||
e.description,
|
||||
e.error_description,
|
||||
user.id,
|
||||
user.realm.id,
|
||||
user.realm.string_id,
|
||||
|
@ -166,12 +166,12 @@ def upgrade(
|
|||
licenses,
|
||||
stripe_token is not None,
|
||||
)
|
||||
return json_error(e.message, data={"error_description": e.description})
|
||||
raise
|
||||
except Exception:
|
||||
billing_logger.exception("Uncaught exception in billing:", stack_info=True)
|
||||
error_message = BillingError.CONTACT_SUPPORT.format(email=settings.ZULIP_ADMINISTRATOR)
|
||||
error_description = "uncaught exception during upgrade"
|
||||
return json_error(error_message, data={"error_description": error_description})
|
||||
raise BillingError(error_description, error_message)
|
||||
else:
|
||||
return json_success()
|
||||
|
||||
|
@ -417,12 +417,7 @@ def update_plan(
|
|||
licenses=licenses
|
||||
)
|
||||
)
|
||||
try:
|
||||
validate_licenses(
|
||||
plan.charge_automatically, licenses, get_latest_seat_count(user.realm)
|
||||
)
|
||||
except BillingError as e:
|
||||
return json_error(e.message, data={"error_description": e.description})
|
||||
validate_licenses(plan.charge_automatically, licenses, get_latest_seat_count(user.realm))
|
||||
update_license_ledger_for_manual_plan(plan, timezone_now(), licenses=licenses)
|
||||
return json_success()
|
||||
|
||||
|
@ -439,14 +434,11 @@ def update_plan(
|
|||
"Your plan is already scheduled to renew with {licenses_at_next_renewal} licenses."
|
||||
).format(licenses_at_next_renewal=licenses_at_next_renewal)
|
||||
)
|
||||
try:
|
||||
validate_licenses(
|
||||
plan.charge_automatically,
|
||||
licenses_at_next_renewal,
|
||||
get_latest_seat_count(user.realm),
|
||||
)
|
||||
except BillingError as e:
|
||||
return json_error(e.message, data={"error_description": e.description})
|
||||
validate_licenses(
|
||||
plan.charge_automatically,
|
||||
licenses_at_next_renewal,
|
||||
get_latest_seat_count(user.realm),
|
||||
)
|
||||
update_license_ledger_for_manual_plan(
|
||||
plan, timezone_now(), licenses_at_next_renewal=licenses_at_next_renewal
|
||||
)
|
||||
|
@ -462,8 +454,5 @@ def replace_payment_source(
|
|||
user: UserProfile,
|
||||
stripe_token: str = REQ(),
|
||||
) -> HttpResponse:
|
||||
try:
|
||||
do_replace_payment_source(user, stripe_token, pay_invoices=True)
|
||||
except BillingError as e:
|
||||
return json_error(e.message, data={"error_description": e.description})
|
||||
do_replace_payment_source(user, stripe_token, pay_invoices=True)
|
||||
return json_success()
|
||||
|
|
Loading…
Reference in New Issue