billing: Rename seat_count to licenses where appropriate.

This commit is contained in:
Rishi Gupta 2018-12-21 16:43:44 -08:00
parent 7ab1406962
commit b4a28f3147
6 changed files with 31 additions and 30 deletions

View File

@ -35,7 +35,7 @@ log_to_file(logging.getLogger('stripe'), BILLING_LOG_PATH)
CallableT = TypeVar('CallableT', bound=Callable[..., Any])
MIN_INVOICED_SEAT_COUNT = 30
MIN_INVOICED_LICENSES = 30
DEFAULT_INVOICE_DAYS_UNTIL_DUE = 30
def get_seat_count(realm: Realm) -> int:

View File

@ -28,7 +28,7 @@ from corporate.lib.stripe import catch_stripe_errors, \
do_subscribe_customer_to_plan, attach_discount_to_realm, \
get_seat_count, extract_current_subscription, sign_string, unsign_string, \
BillingError, StripeCardError, StripeConnectionError, stripe_get_customer, \
DEFAULT_INVOICE_DAYS_UNTIL_DUE, MIN_INVOICED_SEAT_COUNT, do_create_customer
DEFAULT_INVOICE_DAYS_UNTIL_DUE, MIN_INVOICED_LICENSES, do_create_customer
from corporate.models import Customer, CustomerPlan, Plan, Coupon
from corporate.views import payment_method_string
import corporate.urls
@ -250,7 +250,7 @@ class StripeTest(ZulipTestCase):
'schedule': 'annual'} # type: Dict[str, Any]
if invoice: # send_invoice
params.update({
'invoiced_seat_count': 123,
'licenses': 123,
'billing_modality': 'send_invoice'})
else: # charge_automatically
stripe_token = None
@ -482,19 +482,19 @@ class StripeTest(ZulipTestCase):
def test_upgrade_with_insufficient_invoiced_seat_count(self) -> None:
self.login(self.example_email("hamlet"))
# Test invoicing for less than MIN_INVOICED_SEAT_COUNT
# Test invoicing for less than MIN_INVOICED_LICENSES
response = self.upgrade(invoice=True, talk_to_stripe=False,
invoiced_seat_count=MIN_INVOICED_SEAT_COUNT - 1)
self.assert_json_error_contains(response, "at least {} users.".format(MIN_INVOICED_SEAT_COUNT))
self.assertEqual(ujson.loads(response.content)['error_description'], 'lowball seat count')
licenses=MIN_INVOICED_LICENSES - 1)
self.assert_json_error_contains(response, "at least {} users.".format(MIN_INVOICED_LICENSES))
self.assertEqual(ujson.loads(response.content)['error_description'], 'not enough licenses')
# Test invoicing for less than your user count
with patch("corporate.views.MIN_INVOICED_SEAT_COUNT", 3):
response = self.upgrade(invoice=True, talk_to_stripe=False, invoiced_seat_count=4)
with patch("corporate.views.MIN_INVOICED_LICENSES", 3):
response = self.upgrade(invoice=True, talk_to_stripe=False, licenses=4)
self.assert_json_error_contains(response, "at least {} users.".format(self.seat_count))
self.assertEqual(ujson.loads(response.content)['error_description'], 'lowball seat count')
# Test not setting invoiced_seat_count
response = self.upgrade(invoice=True, talk_to_stripe=False, invoiced_seat_count=None)
self.assert_json_error_contains(response, "invoiced_seat_count is not an integer")
self.assertEqual(ujson.loads(response.content)['error_description'], 'not enough licenses')
# Test not setting licenses
response = self.upgrade(invoice=True, talk_to_stripe=False, licenses=None)
self.assert_json_error_contains(response, "licenses is not an integer")
@patch("corporate.lib.stripe.billing_logger.error")
def test_upgrade_with_uncaught_exception(self, mock_: Mock) -> None:

View File

@ -21,7 +21,7 @@ from corporate.lib.stripe import STRIPE_PUBLISHABLE_KEY, \
stripe_get_customer, upcoming_invoice_total, get_seat_count, \
extract_current_subscription, process_initial_upgrade, sign_string, \
unsign_string, BillingError, process_downgrade, do_replace_payment_source, \
MIN_INVOICED_SEAT_COUNT, DEFAULT_INVOICE_DAYS_UNTIL_DUE
MIN_INVOICED_LICENSES, DEFAULT_INVOICE_DAYS_UNTIL_DUE
from corporate.models import Customer, CustomerPlan, Plan
billing_logger = logging.getLogger('corporate.stripe')
@ -72,19 +72,20 @@ def upgrade(request: HttpRequest, user: UserProfile,
signed_seat_count: str=REQ(validator=check_string),
salt: str=REQ(validator=check_string),
billing_modality: str=REQ(validator=check_string),
invoiced_seat_count: int=REQ(validator=check_int, default=None),
licenses: int=REQ(validator=check_int, default=None),
stripe_token: str=REQ(validator=check_string, default=None)) -> HttpResponse:
try:
seat_count, billing_schedule = unsign_and_check_upgrade_parameters(
user, schedule, signed_seat_count, salt, billing_modality)
if billing_modality == 'send_invoice':
min_required_seat_count = max(seat_count, MIN_INVOICED_SEAT_COUNT)
if invoiced_seat_count < min_required_seat_count:
min_required_licenses = max(seat_count, MIN_INVOICED_LICENSES)
if licenses < min_required_licenses:
raise BillingError(
'lowball seat count',
"You must invoice for at least %d users." % (min_required_seat_count,))
seat_count = invoiced_seat_count
process_initial_upgrade(user, seat_count, billing_schedule, stripe_token)
'not enough licenses',
"You must invoice for at least %d users." % (min_required_licenses,))
else:
licenses = seat_count
process_initial_upgrade(user, licenses, billing_schedule, stripe_token)
except BillingError as e:
return json_error(e.message, data={'error_description': e.description})
except Exception as e:
@ -117,7 +118,7 @@ def initial_upgrade(request: HttpRequest) -> HttpResponse:
'seat_count': seat_count,
'signed_seat_count': signed_seat_count,
'salt': salt,
'min_seat_count_for_invoice': max(seat_count, MIN_INVOICED_SEAT_COUNT),
'min_invoiced_licenses': max(seat_count, MIN_INVOICED_LICENSES),
'default_invoice_days_until_due': DEFAULT_INVOICE_DAYS_UNTIL_DUE,
'plan': "Zulip Standard",
'page_params': JSONEncoderForHTML().encode({
@ -159,7 +160,7 @@ def billing_home(request: HttpRequest) -> HttpResponse:
subscription = extract_current_subscription(stripe_customer)
if subscription:
plan_name = PLAN_NAMES[Plan.objects.get(stripe_plan_id=subscription.plan.id).nickname]
seat_count = subscription.quantity
licenses = subscription.quantity
# Need user's timezone to do this properly
renewal_date = '{dt:%B} {dt.day}, {dt.year}'.format(
dt=timestamp_to_datetime(subscription.current_period_end))
@ -170,13 +171,13 @@ def billing_home(request: HttpRequest) -> HttpResponse:
# yet, but keeping this code here since we will soon.
else: # nocoverage
plan_name = "Zulip Free"
seat_count = 0
licenses = 0
renewal_date = ''
renewal_amount = 0
context.update({
'plan_name': plan_name,
'seat_count': seat_count,
'licenses': licenses,
'renewal_date': renewal_date,
'renewal_amount': '{:,.2f}'.format(renewal_amount / 100.),
'payment_method': payment_method_string(stripe_customer),

View File

@ -113,7 +113,7 @@ $(function () {
salt: get_form_input("autopay", "salt"),
schedule: get_form_input("autopay", "schedule"),
license_management: JSON.stringify(license_management),
invoiced_seat_count: $("#" + license_management + "_license_count").val(),
licenses: $("#" + license_management + "_license_count").val(),
billing_modality: get_form_input("autopay", "billing_modality"),
},
success: function () {
@ -150,7 +150,7 @@ $(function () {
});
$("#invoice-button").on("click", function (e) {
if ($("#invoiced_seat_count")[0].checkValidity() === false) {
if ($("#invoiced_licenses")[0].checkValidity() === false) {
return;
}
e.preventDefault();
@ -167,7 +167,7 @@ $(function () {
salt: get_form_input("invoice", "salt"),
schedule: get_form_input("invoice", "schedule"),
billing_modality: get_form_input("invoice", "billing_modality"),
invoiced_seat_count: get_form_input("invoice", "invoiced_seat_count", false),
licenses: get_form_input("invoice", "invoiced_licenses", false),
},
success: function () {
$("#invoice-loading").hide();

View File

@ -30,7 +30,7 @@
<div class="tab-content">
<div class="tab-pane active" id="overview">
<p>Your current plan is <strong>{{ plan_name }}</strong></p>
<p>You are paying for <strong>{{ seat_count }} users</strong>.</p>
<p>You are paying for <strong>{{ licenses }} users</strong>.</p>
<p>Your plan will renew on <strong>{{ renewal_date }}</strong> for <strong>${{ renewal_amount }}</strong>.</p>
{% if account_charges %}
<p>You have <strong>${{ account_charges }}</strong> in charges that will be added to your next bill.</p>

View File

@ -179,7 +179,7 @@
Enter the number of users you would like to pay for. We'll email you an
invoice in 1-2 hours. Invoices can be paid by ACH transfer or credit card.
</p>
<h4>Number of users (minimum {{ min_seat_count_for_invoice }})</h4>
<h4>Number of users (minimum {{ min_invoiced_licenses }})</h4>
<input pattern="\d*" oninvalid="this.setCustomValidity('Invalid input')"
oninput="this.setCustomValidity('')" type="text" autocomplete="off"
id="invoiced_seat_count" name="invoiced_seat_count" required/><br>