mirror of https://github.com/zulip/zulip.git
server_deactivate: Show error message for server on active plan.
This commit is contained in:
parent
c2636354a5
commit
63f4fc51de
|
@ -424,6 +424,14 @@ class StripeConnectionError(BillingError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ServerDeactivateWithExistingPlanError(BillingError): # nocoverage
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__(
|
||||||
|
"server deactivation with existing plan",
|
||||||
|
"",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class UpgradeWithExistingPlanError(BillingError):
|
class UpgradeWithExistingPlanError(BillingError):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__(
|
super().__init__(
|
||||||
|
@ -3853,10 +3861,9 @@ def do_change_remote_server_plan_type(remote_server: RemoteZulipServer, plan_typ
|
||||||
|
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def do_deactivate_remote_server(remote_server: RemoteZulipServer) -> None:
|
def do_deactivate_remote_server(
|
||||||
# TODO: This should also ensure that the server doesn't have an active plan,
|
remote_server: RemoteZulipServer, billing_session: RemoteServerBillingSession
|
||||||
# and deactivate it otherwise. (Like do_deactivate_realm does.)
|
) -> None:
|
||||||
|
|
||||||
if remote_server.deactivated:
|
if remote_server.deactivated:
|
||||||
billing_logger.warning(
|
billing_logger.warning(
|
||||||
"Cannot deactivate remote server with ID %d, server has already been deactivated.",
|
"Cannot deactivate remote server with ID %d, server has already been deactivated.",
|
||||||
|
@ -3864,6 +3871,36 @@ def do_deactivate_remote_server(remote_server: RemoteZulipServer) -> None:
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
server_plans_to_consider = CustomerPlan.objects.filter(
|
||||||
|
customer__remote_server=remote_server
|
||||||
|
).exclude(status=CustomerPlan.ENDED)
|
||||||
|
realm_plans_to_consider = CustomerPlan.objects.filter(
|
||||||
|
customer__remote_realm__server=remote_server
|
||||||
|
).exclude(status=CustomerPlan.ENDED)
|
||||||
|
|
||||||
|
for possible_plan in list(server_plans_to_consider) + list(realm_plans_to_consider):
|
||||||
|
if possible_plan.tier in [
|
||||||
|
CustomerPlan.TIER_SELF_HOSTED_BASE,
|
||||||
|
CustomerPlan.TIER_SELF_HOSTED_LEGACY,
|
||||||
|
CustomerPlan.TIER_SELF_HOSTED_COMMUNITY,
|
||||||
|
]: # nocoverage
|
||||||
|
# No action required for free plans.
|
||||||
|
continue
|
||||||
|
|
||||||
|
if possible_plan.status in [
|
||||||
|
CustomerPlan.DOWNGRADE_AT_END_OF_FREE_TRIAL,
|
||||||
|
CustomerPlan.DOWNGRADE_AT_END_OF_CYCLE,
|
||||||
|
]: # nocoverage
|
||||||
|
# No action required for plans scheduled to downgrade
|
||||||
|
# automatically.
|
||||||
|
continue
|
||||||
|
|
||||||
|
# This customer has some sort of paid plan; ask the customer
|
||||||
|
# to downgrade their paid plan so that they get the
|
||||||
|
# communication in that flow, and then they can come back and
|
||||||
|
# deactivate their server.
|
||||||
|
raise ServerDeactivateWithExistingPlanError # nocoverage
|
||||||
|
|
||||||
remote_server.deactivated = True
|
remote_server.deactivated = True
|
||||||
remote_server.save(update_fields=["deactivated"])
|
remote_server.save(update_fields=["deactivated"])
|
||||||
RemoteZulipServerAuditLog.objects.create(
|
RemoteZulipServerAuditLog.objects.create(
|
||||||
|
|
|
@ -4604,7 +4604,8 @@ class BillingHelpersTest(ZulipTestCase):
|
||||||
)
|
)
|
||||||
self.assertFalse(remote_server.deactivated)
|
self.assertFalse(remote_server.deactivated)
|
||||||
|
|
||||||
do_deactivate_remote_server(remote_server)
|
billing_session = RemoteServerBillingSession(remote_server)
|
||||||
|
do_deactivate_remote_server(remote_server, billing_session)
|
||||||
|
|
||||||
remote_server = RemoteZulipServer.objects.get(uuid=server_uuid)
|
remote_server = RemoteZulipServer.objects.get(uuid=server_uuid)
|
||||||
remote_realm_audit_log = RemoteZulipServerAuditLog.objects.filter(
|
remote_realm_audit_log = RemoteZulipServerAuditLog.objects.filter(
|
||||||
|
@ -4615,7 +4616,7 @@ class BillingHelpersTest(ZulipTestCase):
|
||||||
|
|
||||||
# Try to deactivate a remote server that is already deactivated
|
# Try to deactivate a remote server that is already deactivated
|
||||||
with self.assertLogs("corporate.stripe", "WARN") as warning_log:
|
with self.assertLogs("corporate.stripe", "WARN") as warning_log:
|
||||||
do_deactivate_remote_server(remote_server)
|
do_deactivate_remote_server(remote_server, billing_session)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
warning_log.output,
|
warning_log.output,
|
||||||
[
|
[
|
||||||
|
|
|
@ -14,6 +14,7 @@ from corporate.lib.stripe import (
|
||||||
RealmBillingSession,
|
RealmBillingSession,
|
||||||
RemoteRealmBillingSession,
|
RemoteRealmBillingSession,
|
||||||
RemoteServerBillingSession,
|
RemoteServerBillingSession,
|
||||||
|
ServerDeactivateWithExistingPlanError,
|
||||||
UpdatePlanRequest,
|
UpdatePlanRequest,
|
||||||
do_deactivate_remote_server,
|
do_deactivate_remote_server,
|
||||||
)
|
)
|
||||||
|
@ -300,11 +301,11 @@ def remote_server_deactivate_page(
|
||||||
return HttpResponseNotAllowed(["GET", "POST"])
|
return HttpResponseNotAllowed(["GET", "POST"])
|
||||||
|
|
||||||
remote_server = billing_session.remote_server
|
remote_server = billing_session.remote_server
|
||||||
if request.method == "GET":
|
|
||||||
context = {
|
context = {
|
||||||
"server_hostname": remote_server.hostname,
|
"server_hostname": remote_server.hostname,
|
||||||
"action_url": reverse(remote_server_deactivate_page, args=[str(remote_server.uuid)]),
|
"action_url": reverse(remote_server_deactivate_page, args=[str(remote_server.uuid)]),
|
||||||
}
|
}
|
||||||
|
if request.method == "GET":
|
||||||
return render(request, "corporate/remote_billing_server_deactivate.html", context=context)
|
return render(request, "corporate/remote_billing_server_deactivate.html", context=context)
|
||||||
|
|
||||||
assert request.method == "POST"
|
assert request.method == "POST"
|
||||||
|
@ -312,7 +313,12 @@ def remote_server_deactivate_page(
|
||||||
# Should be impossible if the user is using the UI.
|
# Should be impossible if the user is using the UI.
|
||||||
raise JsonableError(_("Parameter 'confirmed' is required"))
|
raise JsonableError(_("Parameter 'confirmed' is required"))
|
||||||
|
|
||||||
do_deactivate_remote_server(remote_server)
|
try:
|
||||||
|
do_deactivate_remote_server(remote_server, billing_session)
|
||||||
|
except ServerDeactivateWithExistingPlanError: # nocoverage
|
||||||
|
context["show_existing_plan_error"] = "true"
|
||||||
|
return render(request, "corporate/remote_billing_server_deactivate.html", context=context)
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
"corporate/remote_billing_server_deactivated_success.html",
|
"corporate/remote_billing_server_deactivated_success.html",
|
||||||
|
|
|
@ -15,6 +15,13 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="white-box">
|
<div class="white-box">
|
||||||
<div id="server-deactivate-details">
|
<div id="server-deactivate-details">
|
||||||
|
{% if show_existing_plan_error %}
|
||||||
|
<div id="server-deactivate-error" class="alert alert-danger">
|
||||||
|
Could not deactivate registration. You must first
|
||||||
|
<a href="https://zulip.com/help/self-hosted-billing#cancel-paid-plan">cancel</a>
|
||||||
|
all paid plans associated with this server, including scheduled plan upgrades.
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
<form id="server-deactivate-form" method="post" action="{{ action_url }}">
|
<form id="server-deactivate-form" method="post" action="{{ action_url }}">
|
||||||
{{ csrf_input }}
|
{{ csrf_input }}
|
||||||
<div id="server-deactivate-form-top-description" class="input-box server-deactivate-form-field no-validation">
|
<div id="server-deactivate-form-top-description" class="input-box server-deactivate-form-field no-validation">
|
||||||
|
|
|
@ -669,6 +669,7 @@ input[name="licenses"] {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#server-deactivate-error,
|
||||||
#server-login-error,
|
#server-login-error,
|
||||||
#autopay-error {
|
#autopay-error {
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
@ -697,6 +698,7 @@ input[name="licenses"] {
|
||||||
top: 5px;
|
top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#server-deactivate-error,
|
||||||
#server-login-error {
|
#server-login-error {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
|
@ -479,6 +479,7 @@ html {
|
||||||
|
|
||||||
.alert {
|
.alert {
|
||||||
&:not(
|
&:not(
|
||||||
|
#server-deactivate-error,
|
||||||
#server-login-error,
|
#server-login-error,
|
||||||
.alert-info,
|
.alert-info,
|
||||||
.billing-page-success,
|
.billing-page-success,
|
||||||
|
|
|
@ -92,7 +92,8 @@ def deactivate_remote_server(
|
||||||
request: HttpRequest,
|
request: HttpRequest,
|
||||||
remote_server: RemoteZulipServer,
|
remote_server: RemoteZulipServer,
|
||||||
) -> HttpResponse:
|
) -> HttpResponse:
|
||||||
do_deactivate_remote_server(remote_server)
|
billing_session = RemoteServerBillingSession(remote_server)
|
||||||
|
do_deactivate_remote_server(remote_server, billing_session)
|
||||||
return json_success(request)
|
return json_success(request)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue