upgrade: Make purchase upgrade work for remove servers and realms.

We are upgrading them to cloud standard right now, we can easily
change tiers in future while adding pricing and configuration for
them.
This commit is contained in:
Aman Agrawal
2023-12-01 06:14:12 +00:00
committed by Tim Abbott
parent e9bbb67035
commit d0c0b11fbf
6 changed files with 109 additions and 12 deletions

View File

@@ -107,10 +107,6 @@ def handle_payment_intent_succeeded_event(
payment_intent.status = PaymentIntent.SUCCEEDED payment_intent.status = PaymentIntent.SUCCEEDED
payment_intent.save() payment_intent.save()
metadata: Dict[str, Any] = stripe_payment_intent.metadata metadata: Dict[str, Any] = stripe_payment_intent.metadata
assert payment_intent.customer.realm is not None
user_id = metadata.get("user_id")
assert user_id is not None
user = get_active_user_profile_by_id_in_realm(user_id, payment_intent.customer.realm)
description = "" description = ""
charge: stripe.Charge charge: stripe.Charge
@@ -140,7 +136,9 @@ def handle_payment_intent_succeeded_event(
stripe.Invoice.finalize_invoice(stripe_invoice) stripe.Invoice.finalize_invoice(stripe_invoice)
raise e raise e
billing_session = RealmBillingSession(user) billing_session = get_billing_session_for_stripe_webhook(
payment_intent.customer, metadata.get("user_id")
)
billing_session.process_initial_upgrade( billing_session.process_initial_upgrade(
CustomerPlan.TIER_CLOUD_STANDARD, CustomerPlan.TIER_CLOUD_STANDARD,
int(metadata["licenses"]), int(metadata["licenses"]),

View File

@@ -46,7 +46,9 @@ from corporate.views.sponsorship import (
) )
from corporate.views.support import support_request from corporate.views.support import support_request
from corporate.views.upgrade import ( from corporate.views.upgrade import (
remote_realm_upgrade,
remote_realm_upgrade_page, remote_realm_upgrade_page,
remote_server_upgrade,
remote_server_upgrade_page, remote_server_upgrade_page,
upgrade, upgrade,
upgrade_page, upgrade_page,
@@ -230,6 +232,8 @@ urlpatterns += [
), ),
path("json/realm/<realm_uuid>/billing/event/status", remote_realm_event_status), path("json/realm/<realm_uuid>/billing/event/status", remote_realm_event_status),
path("json/server/<server_uuid>/billing/event/status", remote_server_event_status), path("json/server/<server_uuid>/billing/event/status", remote_server_event_status),
path("json/realm/<realm_uuid>/billing/upgrade", remote_realm_upgrade),
path("json/server/<server_uuid>/billing/upgrade", remote_server_upgrade),
] ]
urlpatterns += [ urlpatterns += [

View File

@@ -79,6 +79,96 @@ def upgrade(
raise BillingError(error_description, error_message) raise BillingError(error_description, error_message)
@authenticated_remote_realm_management_endpoint
@has_request_variables
def remote_realm_upgrade(
request: HttpRequest,
billing_session: RemoteRealmBillingSession,
billing_modality: str = REQ(str_validator=check_string_in(VALID_BILLING_MODALITY_VALUES)),
schedule: str = REQ(str_validator=check_string_in(VALID_BILLING_SCHEDULE_VALUES)),
signed_seat_count: str = REQ(),
salt: str = REQ(),
license_management: Optional[str] = REQ(
default=None, str_validator=check_string_in(VALID_LICENSE_MANAGEMENT_VALUES)
),
licenses: Optional[int] = REQ(json_validator=check_int, default=None),
) -> HttpResponse: # nocoverage
try:
upgrade_request = UpgradeRequest(
billing_modality=billing_modality,
schedule=schedule,
signed_seat_count=signed_seat_count,
salt=salt,
license_management=license_management,
licenses=licenses,
)
data = billing_session.do_upgrade(upgrade_request)
return json_success(request, data)
except BillingError as e:
billing_logger.warning(
"BillingError during upgrade: %s. remote_realm=%s (%s), billing_modality=%s, "
"schedule=%s, license_management=%s, licenses=%s",
e.error_description,
billing_session.remote_realm.id,
billing_session.remote_realm.host,
billing_modality,
schedule,
license_management,
licenses,
)
raise e
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"
raise BillingError(error_description, error_message)
@authenticated_remote_server_management_endpoint
@has_request_variables
def remote_server_upgrade(
request: HttpRequest,
billing_session: RemoteServerBillingSession,
billing_modality: str = REQ(str_validator=check_string_in(VALID_BILLING_MODALITY_VALUES)),
schedule: str = REQ(str_validator=check_string_in(VALID_BILLING_SCHEDULE_VALUES)),
signed_seat_count: str = REQ(),
salt: str = REQ(),
license_management: Optional[str] = REQ(
default=None, str_validator=check_string_in(VALID_LICENSE_MANAGEMENT_VALUES)
),
licenses: Optional[int] = REQ(json_validator=check_int, default=None),
) -> HttpResponse: # nocoverage
try:
upgrade_request = UpgradeRequest(
billing_modality=billing_modality,
schedule=schedule,
signed_seat_count=signed_seat_count,
salt=salt,
license_management=license_management,
licenses=licenses,
)
data = billing_session.do_upgrade(upgrade_request)
return json_success(request, data)
except BillingError as e:
billing_logger.warning(
"BillingError during upgrade: %s. remote_server=%s (%s), billing_modality=%s, "
"schedule=%s, license_management=%s, licenses=%s",
e.error_description,
billing_session.remote_server.id,
billing_session.remote_server.hostname,
billing_modality,
schedule,
license_management,
licenses,
)
raise e
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"
raise BillingError(error_description, error_message)
@zulip_login_required @zulip_login_required
@has_request_variables @has_request_variables
def upgrade_page( def upgrade_page(

View File

@@ -81,7 +81,9 @@ async function stripe_checkout_session_status_check(stripe_session_id: string):
export async function stripe_payment_intent_status_check( export async function stripe_payment_intent_status_check(
stripe_payment_intent_id: string, stripe_payment_intent_id: string,
): Promise<boolean> { ): Promise<boolean> {
const response: unknown = await $.get("/json/billing/event/status", {stripe_payment_intent_id}); const response: unknown = await $.get(`/json${billing_base_url}/billing/event/status`, {
stripe_payment_intent_id,
});
const response_schema = z.object({ const response_schema = z.object({
payment_intent: z.object({ payment_intent: z.object({
@@ -108,7 +110,7 @@ export async function stripe_payment_intent_status_check(
switch (response_data.payment_intent.status) { switch (response_data.payment_intent.status) {
case "succeeded": case "succeeded":
if (response_data.payment_intent.event_handler!.status === "succeeded") { if (response_data.payment_intent.event_handler!.status === "succeeded") {
helpers.redirect_to_billing_with_successful_upgrade(); helpers.redirect_to_billing_with_successful_upgrade(billing_base_url);
return true; return true;
} }
if (response_data.payment_intent.event_handler!.status === "failed") { if (response_data.payment_intent.event_handler!.status === "failed") {

View File

@@ -153,9 +153,10 @@ export function is_valid_input(elem: JQuery<HTMLFormElement>): boolean {
return elem[0].checkValidity(); return elem[0].checkValidity();
} }
export function redirect_to_billing_with_successful_upgrade(): void { export function redirect_to_billing_with_successful_upgrade(billing_base_url: string): void {
window.location.replace( window.location.replace(
"/billing/?success_message=" + billing_base_url +
"/billing/?success_message=" +
encodeURIComponent("Your organization has been upgraded to Zulip Cloud Standard."), encodeURIComponent("Your organization has been upgraded to Zulip Cloud Standard."),
); );
} }

View File

@@ -86,7 +86,7 @@ export const initialize = (): void => {
$("#org-upgrade-button-text").hide(); $("#org-upgrade-button-text").hide();
$("#org-upgrade-button .upgrade-button-loader").show(); $("#org-upgrade-button .upgrade-button-loader").show();
helpers.create_ajax_request( helpers.create_ajax_request(
"/json/billing/upgrade", `/json${page_params.billing_base_url}/billing/upgrade`,
"autopay", "autopay",
[], [],
"POST", "POST",
@@ -94,10 +94,12 @@ export const initialize = (): void => {
const response_data = upgrade_response_schema.parse(response); const response_data = upgrade_response_schema.parse(response);
if (response_data.stripe_payment_intent_id) { if (response_data.stripe_payment_intent_id) {
window.location.replace( window.location.replace(
`/billing/event_status?stripe_payment_intent_id=${response_data.stripe_payment_intent_id}`, `${page_params.billing_base_url}/billing/event_status?stripe_payment_intent_id=${response_data.stripe_payment_intent_id}`,
); );
} else if (response_data.organization_upgrade_successful) { } else if (response_data.organization_upgrade_successful) {
helpers.redirect_to_billing_with_successful_upgrade(); helpers.redirect_to_billing_with_successful_upgrade(
page_params.billing_base_url,
);
} }
}, },
(xhr) => { (xhr) => {