mirror of https://github.com/zulip/zulip.git
billing: Use UserProfile.is_billing_admin instead of Customer.billing_user.
This commit is contained in:
parent
6f57cd4d23
commit
dcb7b15069
|
@ -0,0 +1,20 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.11.14 on 2018-08-22 05:45
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('zerver', '0186_userprofile_starred_message_counts'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='userprofile',
|
||||||
|
name='is_billing_admin',
|
||||||
|
field=models.BooleanField(db_index=True, default=False),
|
||||||
|
),
|
||||||
|
]
|
|
@ -690,6 +690,7 @@ class UserProfile(AbstractBaseUser, PermissionsMixin):
|
||||||
is_active = models.BooleanField(default=True, db_index=True) # type: bool
|
is_active = models.BooleanField(default=True, db_index=True) # type: bool
|
||||||
|
|
||||||
is_realm_admin = models.BooleanField(default=False, db_index=True) # type: bool
|
is_realm_admin = models.BooleanField(default=False, db_index=True) # type: bool
|
||||||
|
is_billing_admin = models.BooleanField(default=False, db_index=True) # type: bool
|
||||||
|
|
||||||
# Guest users are limited users without default access to public streams (etc.)
|
# Guest users are limited users without default access to public streams (etc.)
|
||||||
is_guest = models.BooleanField(default=False, db_index=True) # type: bool
|
is_guest = models.BooleanField(default=False, db_index=True) # type: bool
|
||||||
|
|
|
@ -168,6 +168,8 @@ def do_create_customer(user: UserProfile, stripe_token: Optional[str]=None,
|
||||||
realm=realm,
|
realm=realm,
|
||||||
stripe_customer_id=stripe_customer.id,
|
stripe_customer_id=stripe_customer.id,
|
||||||
billing_user=user)
|
billing_user=user)
|
||||||
|
user.is_billing_admin = True
|
||||||
|
user.save(update_fields=["is_billing_admin"])
|
||||||
return stripe_customer
|
return stripe_customer
|
||||||
|
|
||||||
@catch_stripe_errors
|
@catch_stripe_errors
|
||||||
|
@ -190,7 +192,7 @@ def do_replace_coupon(user: UserProfile, coupon: Coupon) -> stripe.Customer:
|
||||||
return stripe_customer.save()
|
return stripe_customer.save()
|
||||||
|
|
||||||
@catch_stripe_errors
|
@catch_stripe_errors
|
||||||
def do_subscribe_customer_to_plan(stripe_customer: stripe.Customer, stripe_plan_id: str,
|
def do_subscribe_customer_to_plan(user: UserProfile, stripe_customer: stripe.Customer, stripe_plan_id: str,
|
||||||
seat_count: int, tax_percent: float) -> None:
|
seat_count: int, tax_percent: float) -> None:
|
||||||
if extract_current_subscription(stripe_customer) is not None:
|
if extract_current_subscription(stripe_customer) is not None:
|
||||||
# Most likely due to two people in the org going to the billing page,
|
# Most likely due to two people in the org going to the billing page,
|
||||||
|
@ -227,7 +229,7 @@ def do_subscribe_customer_to_plan(stripe_customer: stripe.Customer, stripe_plan_
|
||||||
customer.realm.save(update_fields=['has_seat_based_plan'])
|
customer.realm.save(update_fields=['has_seat_based_plan'])
|
||||||
RealmAuditLog.objects.create(
|
RealmAuditLog.objects.create(
|
||||||
realm=customer.realm,
|
realm=customer.realm,
|
||||||
acting_user=customer.billing_user,
|
acting_user=user,
|
||||||
event_type=RealmAuditLog.STRIPE_PLAN_CHANGED,
|
event_type=RealmAuditLog.STRIPE_PLAN_CHANGED,
|
||||||
event_time=timestamp_to_datetime(stripe_subscription.created),
|
event_time=timestamp_to_datetime(stripe_subscription.created),
|
||||||
extra_data=ujson.dumps({'plan': stripe_plan_id, 'quantity': seat_count}))
|
extra_data=ujson.dumps({'plan': stripe_plan_id, 'quantity': seat_count}))
|
||||||
|
@ -248,6 +250,7 @@ def process_initial_upgrade(user: UserProfile, plan: Plan, seat_count: int, stri
|
||||||
else:
|
else:
|
||||||
stripe_customer = do_replace_payment_source(user, stripe_token)
|
stripe_customer = do_replace_payment_source(user, stripe_token)
|
||||||
do_subscribe_customer_to_plan(
|
do_subscribe_customer_to_plan(
|
||||||
|
user=user,
|
||||||
stripe_customer=stripe_customer,
|
stripe_customer=stripe_customer,
|
||||||
stripe_plan_id=plan.stripe_plan_id,
|
stripe_plan_id=plan.stripe_plan_id,
|
||||||
seat_count=seat_count,
|
seat_count=seat_count,
|
||||||
|
|
|
@ -177,11 +177,11 @@ class StripeTest(ZulipTestCase):
|
||||||
# Check that the non-admin hamlet can still access /billing
|
# Check that the non-admin hamlet can still access /billing
|
||||||
response = self.client_get("/billing/")
|
response = self.client_get("/billing/")
|
||||||
self.assert_in_success_response(["for billing history or to make changes"], response)
|
self.assert_in_success_response(["for billing history or to make changes"], response)
|
||||||
# Check admins can access billing, even though they are not the billing_user
|
# Check admins can access billing, even though they are not a billing admin
|
||||||
self.login(self.example_email('iago'))
|
self.login(self.example_email('iago'))
|
||||||
response = self.client_get("/billing/")
|
response = self.client_get("/billing/")
|
||||||
self.assert_in_success_response(["for billing history or to make changes"], response)
|
self.assert_in_success_response(["for billing history or to make changes"], response)
|
||||||
# Check that non-admin, non-billing_user does not have access
|
# Check that a non-admin, non-billing admin user does not have access
|
||||||
self.login(self.example_email("cordelia"))
|
self.login(self.example_email("cordelia"))
|
||||||
response = self.client_get("/billing/")
|
response = self.client_get("/billing/")
|
||||||
self.assert_in_success_response(["You must be an organization administrator"], response)
|
self.assert_in_success_response(["You must be an organization administrator"], response)
|
||||||
|
@ -310,7 +310,7 @@ class StripeTest(ZulipTestCase):
|
||||||
@mock.patch("stripe.Invoice.upcoming", side_effect=mock_upcoming_invoice)
|
@mock.patch("stripe.Invoice.upcoming", side_effect=mock_upcoming_invoice)
|
||||||
def test_billing_home(self, mock_upcoming_invoice: mock.Mock,
|
def test_billing_home(self, mock_upcoming_invoice: mock.Mock,
|
||||||
mock_customer_with_subscription: mock.Mock) -> None:
|
mock_customer_with_subscription: mock.Mock) -> None:
|
||||||
user = self.example_user("hamlet")
|
user = self.example_user("iago")
|
||||||
self.login(user.email)
|
self.login(user.email)
|
||||||
# No Customer yet; check that we are redirected to /upgrade
|
# No Customer yet; check that we are redirected to /upgrade
|
||||||
response = self.client_get("/billing/")
|
response = self.client_get("/billing/")
|
||||||
|
@ -320,6 +320,7 @@ class StripeTest(ZulipTestCase):
|
||||||
Customer.objects.create(
|
Customer.objects.create(
|
||||||
realm=user.realm, stripe_customer_id=self.stripe_customer_id, billing_user=user,
|
realm=user.realm, stripe_customer_id=self.stripe_customer_id, billing_user=user,
|
||||||
has_billing_relationship=True)
|
has_billing_relationship=True)
|
||||||
|
|
||||||
response = self.client_get("/billing/")
|
response = self.client_get("/billing/")
|
||||||
self.assert_not_in_success_response(['We can also bill by invoice'], response)
|
self.assert_not_in_success_response(['We can also bill by invoice'], response)
|
||||||
for substring in ['Your plan will renew on', '$%s.00' % (80 * self.quantity,),
|
for substring in ['Your plan will renew on', '$%s.00' % (80 * self.quantity,),
|
||||||
|
@ -350,7 +351,8 @@ class StripeTest(ZulipTestCase):
|
||||||
|
|
||||||
def test_subscribe_customer_to_second_plan(self) -> None:
|
def test_subscribe_customer_to_second_plan(self) -> None:
|
||||||
with self.assertRaisesRegex(BillingError, 'subscribing with existing subscription'):
|
with self.assertRaisesRegex(BillingError, 'subscribing with existing subscription'):
|
||||||
do_subscribe_customer_to_plan(mock_customer_with_subscription(),
|
do_subscribe_customer_to_plan(self.example_user("iago"),
|
||||||
|
mock_customer_with_subscription(),
|
||||||
self.stripe_plan_id, self.quantity, 0)
|
self.stripe_plan_id, self.quantity, 0)
|
||||||
|
|
||||||
def test_sign_string(self) -> None:
|
def test_sign_string(self) -> None:
|
||||||
|
|
|
@ -236,7 +236,7 @@ def billing_home(request: HttpRequest) -> HttpResponse:
|
||||||
if not customer.has_billing_relationship:
|
if not customer.has_billing_relationship:
|
||||||
return HttpResponseRedirect(reverse('zilencer.views.initial_upgrade'))
|
return HttpResponseRedirect(reverse('zilencer.views.initial_upgrade'))
|
||||||
|
|
||||||
if not user.is_realm_admin and not user == customer.billing_user:
|
if not user.is_realm_admin and not user.is_billing_admin:
|
||||||
context = {'admin_access': False} # type: Dict[str, Any]
|
context = {'admin_access': False} # type: Dict[str, Any]
|
||||||
return render(request, 'zilencer/billing.html', context=context)
|
return render(request, 'zilencer/billing.html', context=context)
|
||||||
context = {'admin_access': True}
|
context = {'admin_access': True}
|
||||||
|
|
Loading…
Reference in New Issue