mirror of https://github.com/zulip/zulip.git
support: Add option to change billing method.
This commit is contained in:
parent
367c792968
commit
510efbc1a8
|
@ -461,8 +461,9 @@ class TestSupportEndpoint(ZulipTestCase):
|
|||
'<b>Billing schedule</b>: Annual',
|
||||
'<b>Licenses</b>: 2/10 (Manual)',
|
||||
'<b>Price per license</b>: $80.0',
|
||||
'<b>Payment method</b>: Send invoice',
|
||||
'<b>Next invoice date</b>: 02 January 2017',
|
||||
'<option value="send_invoice" selected>',
|
||||
'<option value="charge_automatically" >'
|
||||
], result)
|
||||
|
||||
def check_preregistration_user_query_result(result: HttpResponse, email: str, invite: bool=False) -> None:
|
||||
|
@ -572,6 +573,28 @@ class TestSupportEndpoint(ZulipTestCase):
|
|||
check_realm_reactivation_link_query_result(result)
|
||||
check_zulip_realm_query_result(result)
|
||||
|
||||
@mock.patch("analytics.views.update_billing_method_of_current_plan")
|
||||
def test_change_billing_method(self, m: mock.Mock) -> None:
|
||||
cordelia = self.example_user('cordelia')
|
||||
self.login_user(cordelia)
|
||||
|
||||
result = self.client_post("/activity/support", {"realm_id": f"{cordelia.realm_id}", "plan_type": "2"})
|
||||
self.assertEqual(result.status_code, 302)
|
||||
self.assertEqual(result["Location"], "/login/")
|
||||
|
||||
iago = self.example_user("iago")
|
||||
self.login_user(iago)
|
||||
|
||||
result = self.client_post("/activity/support", {"realm_id": f"{iago.realm_id}", "billing_method": "charge_automatically"})
|
||||
m.assert_called_once_with(get_realm("zulip"), charge_automatically=True)
|
||||
self.assert_in_success_response(["Billing method of Zulip Dev updated to charge automatically"], result)
|
||||
|
||||
m.reset_mock()
|
||||
|
||||
result = self.client_post("/activity/support", {"realm_id": f"{iago.realm_id}", "billing_method": "send_invoice"})
|
||||
m.assert_called_once_with(get_realm("zulip"), charge_automatically=False)
|
||||
self.assert_in_success_response(["Billing method of Zulip Dev updated to pay by invoice"], result)
|
||||
|
||||
def test_change_plan_type(self) -> None:
|
||||
cordelia = self.example_user('cordelia')
|
||||
self.login_user(cordelia)
|
||||
|
|
|
@ -82,6 +82,7 @@ if settings.BILLING_ENABLED:
|
|||
get_discount_for_realm,
|
||||
get_latest_seat_count,
|
||||
make_end_of_cycle_updates_if_needed,
|
||||
update_billing_method_of_current_plan,
|
||||
update_sponsorship_status,
|
||||
void_all_open_invoices,
|
||||
)
|
||||
|
@ -1174,6 +1175,14 @@ def support(request: HttpRequest) -> HttpResponse:
|
|||
elif status == "deactivated":
|
||||
do_deactivate_realm(realm, request.user)
|
||||
context["message"] = f"{realm.name} deactivated."
|
||||
elif request.POST.get("billing_method", None) is not None:
|
||||
billing_method = request.POST.get("billing_method")
|
||||
if billing_method == "send_invoice":
|
||||
update_billing_method_of_current_plan(realm, charge_automatically=False)
|
||||
context["message"] = f"Billing method of {realm.name} updated to pay by invoice."
|
||||
elif billing_method == "charge_automatically":
|
||||
update_billing_method_of_current_plan(realm, charge_automatically=True)
|
||||
context["message"] = f"Billing method of {realm.name} updated to charge automatically."
|
||||
elif request.POST.get("sponsorship_pending", None) is not None:
|
||||
sponsorship_pending = request.POST.get("sponsorship_pending")
|
||||
if sponsorship_pending == "true":
|
||||
|
|
|
@ -655,3 +655,9 @@ def void_all_open_invoices(realm: Realm) -> int:
|
|||
)
|
||||
voided_invoices_count += 1
|
||||
return voided_invoices_count
|
||||
|
||||
def update_billing_method_of_current_plan(realm: Realm, charge_automatically: bool) -> None:
|
||||
plan = get_current_plan_by_realm(realm)
|
||||
if plan is not None:
|
||||
plan.charge_automatically = charge_automatically
|
||||
plan.save(update_fields=["charge_automatically"])
|
||||
|
|
|
@ -37,6 +37,7 @@ from corporate.lib.stripe import (
|
|||
sign_string,
|
||||
stripe_get_customer,
|
||||
unsign_string,
|
||||
update_billing_method_of_current_plan,
|
||||
update_license_ledger_for_automanaged_plan,
|
||||
update_license_ledger_if_needed,
|
||||
update_or_create_stripe_customer,
|
||||
|
@ -1846,6 +1847,23 @@ class StripeTest(StripeTestCase):
|
|||
for invoice in invoices:
|
||||
self.assertEqual(invoice.status, "void")
|
||||
|
||||
def test_update_billing_method_of_current_plan(self) -> None:
|
||||
realm = get_realm("zulip")
|
||||
customer = Customer.objects.create(realm=realm, stripe_customer_id='cus_12345')
|
||||
plan = CustomerPlan.objects.create(customer=customer, status=CustomerPlan.ACTIVE,
|
||||
billing_cycle_anchor=timezone_now(),
|
||||
billing_schedule=CustomerPlan.ANNUAL,
|
||||
tier=CustomerPlan.STANDARD)
|
||||
self.assertEqual(plan.charge_automatically, False)
|
||||
|
||||
update_billing_method_of_current_plan(realm, True)
|
||||
plan.refresh_from_db()
|
||||
self.assertEqual(plan.charge_automatically, True)
|
||||
|
||||
update_billing_method_of_current_plan(realm, False)
|
||||
plan.refresh_from_db()
|
||||
self.assertEqual(plan.charge_automatically, False)
|
||||
|
||||
class RequiresBillingAccessTest(ZulipTestCase):
|
||||
def setUp(self) -> None:
|
||||
super().setUp()
|
||||
|
|
|
@ -94,18 +94,23 @@ tr.admin td:first-child {
|
|||
top: -40px;
|
||||
}
|
||||
|
||||
.downgrade-plan-form {
|
||||
.billing-method-form {
|
||||
position: relative;
|
||||
top: -70px;
|
||||
}
|
||||
|
||||
.downgrade-plan-form {
|
||||
position: relative;
|
||||
top: -115px;
|
||||
}
|
||||
|
||||
.downgrade-plan-method-select {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.scrub-realm-form {
|
||||
position: relative;
|
||||
top: -40px;
|
||||
top: -70px;
|
||||
}
|
||||
|
||||
.support-search-button {
|
||||
|
|
|
@ -72,10 +72,21 @@
|
|||
{% else %}
|
||||
<b>Fixed price</b>: ${{ realm.current_plan.fixed_price/100 }}<br>
|
||||
{% endif %}
|
||||
<b>Payment method</b>: {% if realm.current_plan.charge_automatically %}Card{% else %}Send invoice{% endif %}<br>
|
||||
<b>Next invoice date</b>: {{ realm.current_plan.next_invoice_date.strftime('%d %B %Y') }}<br>
|
||||
</div>
|
||||
|
||||
<form method="POST" class="billing-method-form">
|
||||
<br>
|
||||
<b>Billing method</b><br>
|
||||
{{ csrf_input }}
|
||||
<input type="hidden" name="realm_id" value="{{ realm.id }}" />
|
||||
<select name="billing_method" class="billing-method-select" required>
|
||||
<option value="charge_automatically" {% if realm.current_plan.charge_automatically %}selected{% endif %}>Charge automatically</option>
|
||||
<option value="send_invoice" {% if not realm.current_plan.charge_automatically %}selected{% endif %}>Pay by invoice</option>
|
||||
</select>
|
||||
<button type="submit" class="button rounded small support-submit-button">Update</button>
|
||||
</form>
|
||||
|
||||
<form method="POST" class="downgrade-plan-form">
|
||||
<br>
|
||||
<b>Downgrade plan</b><br>
|
||||
|
|
Loading…
Reference in New Issue