PIG208
72f9f964a1
billing: Refactor BillingError to subclass JsonableError.
...
This lets us remove unnecessary BillingError to json_error conversion
code.
2021-07-05 10:43:49 -07:00
Vishnu KS
e0f5fadb79
billing: Downgrade small realms that are behind on payments.
...
An organization with at most 5 users that is behind on payments isn't
worth spending time on investigating the situation.
For larger organizations, we likely want somewhat different logic that
at least does not void invoices.
2021-07-02 13:19:12 -07:00
Vishnu KS
cb64a19edf
models: Rename get_human_billing_admin_users to be more explicit.
2021-07-02 12:04:41 -07:00
Vishnu KS
e64296b3e9
stripe: Create get_all_invoices function.
...
stripe.Invoice.list by default would only get 10 invoices at a
time. So a function like this would be really handy if we have
to go through a lot of invoices.
This also means void_all_open_invoices used to void only the last
10 invoices. The main reason we implemented this function was to
void the invoices generated by realms on free trial so I don't
think there were cases where we had to void realms with more than
10 invoices.
2021-07-02 12:04:41 -07:00
Vishnu KS
1d579ec567
billing: Fix the type annotation of Customer.stripe_customer_id.
...
This also fixes a bug in void_all_open_invoices function. If a realm
with a local Customer object but without an associated stripe.Customer
is passed to void_all_open_invoices, then the function will end up
voiding the last 10 invoices created by billing system instead of voiding
no invoices at all. This is because stripe.Invoice.list(customer=None)
return last 10 invoices across all customers.
But this bug won't cauuse any issue in production since
void_all_open_invoices can be only invoked from /support page. And we
show the option to void invoices in support page only if the realm
has a paid plan. And it's not really possible for a realm to have
a paid plan without having an associated stripe_customer_id. Plus I
went through the void events in stripe stream since the PR to add
void invoices was merged and there does not seems to be any suspicious
events.
2021-07-02 12:04:41 -07:00
Mateusz Mandera
bae86ad3da
billing: Move exempt_from_from_license_number_check to Customer model.
...
This belongs more on the Customer model, since this is a similar
attribute to default_discount.
2021-06-18 14:05:42 -07:00
Vishnu KS
203ddfc546
billing: Create cents_to_dollar_string helper function.
2021-06-14 16:56:18 -07:00
Vishnu KS
1eb83cbadc
billing: Create is_sponsored_realm function.
2021-06-14 16:49:53 -07:00
Vishnu KS
cdf683e36f
billing: Create customer_has_credit_card_as_default_source function.
2021-06-14 16:49:53 -07:00
Vishnu KS
6e3d4e7e75
billing: Create is_free_trial_offer_enabled function.
2021-06-14 16:49:53 -07:00
Vishnu KS
f55dbe33bb
billing: Create is_realm_on_free_trial helper function.
2021-06-14 16:49:53 -07:00
Vishnu KS
06b5f9feae
billing: Create is_free_trial function in CustomerPlan model.
2021-06-14 16:49:53 -07:00
Vishnu KS
40ab415005
activity: Show effective rate of realms in /activity page.
2021-06-11 07:41:02 -07:00
Vishnu KS
42119c136b
billing: Allow to exclude realms from license limit check.
2021-06-09 17:42:38 -07:00
Vishnu KS
1938076f67
billing: Enforce license limit for plans on manual license management.
2021-06-09 17:42:38 -07:00
Vishnu KS
3d5ee69b21
stripe: Create make_user_billing_admin helper function.
2021-06-03 10:13:59 -07:00
Vishnu KS
20d2e00cf9
billing: Create update_license_ledger_for_manual_plan.
2021-05-14 15:10:02 -07:00
Vishnu KS
c9f4439850
billing: Extract out validate_licenses function.
2021-05-14 15:10:02 -07:00
Anders Kaseorg
e7ed907cf6
python: Convert deprecated Django ugettext alias to gettext.
...
django.utils.translation.ugettext is a deprecated alias of
django.utils.translation.gettext as of Django 3.0, and will be removed
in Django 4.0.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-04-15 18:01:34 -07:00
Siddharth Asthana
80c9243c6a
support: Create RealmAuditLog when updating sponsorship status.
2021-04-03 08:01:46 -07:00
Siddharth Asthana
233c4d520c
support: Create RealmAuditLog when updating billing_method.
...
This commit also makes acting_user as a mandantory argument and fixes
the tests accordingly.
2021-04-03 08:01:46 -07:00
Siddharth Asthana
44c34cb39a
support: Create RealmAuditLog when approving sponsorship.
2021-04-03 08:01:46 -07:00
Siddharth Asthana
6945ed3587
support: Pass acting_user to attach_discount_to_realm.
2021-04-03 08:01:46 -07:00
Siddharth Asthana
c3f37c2a64
support: Pass acting_user to do_change_plan_type.
...
acting_user is now a mandatory field, so wherever this function is used,
we are passing acting_user as well.
2021-04-03 08:01:46 -07:00
Mateusz Mandera
09fc79f911
actions: Remove realm argument to internal_send_private_message.
...
The argument is redundant.
2021-02-23 15:26:47 -08:00
Anders Kaseorg
6e4c3e41dc
python: Normalize quotes with Black.
...
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-02-12 13:11:19 -08:00
Anders Kaseorg
11741543da
python: Reformat with Black, except quotes.
...
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-02-12 13:11:19 -08:00
Vishnu KS
bd2642a7b8
billing: Make attach discount update the current price per license.
2020-12-17 17:09:20 -08:00
Vishnu KS
480288643c
billing: Create calculate_discounted_price_per_license.
2020-12-17 17:09:20 -08:00
Vishnu KS
71efcca679
stripe: Create get_price_per_license function.
2020-12-17 17:09:20 -08:00
Anders Kaseorg
f461a64a6b
i18n: Fix some ineffective calls to ugettext at top level.
...
Translation has no effect when we don’t yet know what language we’re
translating for.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-10-18 14:31:15 -07:00
Vishnu KS
510efbc1a8
support: Add option to change billing method.
2020-09-28 15:37:49 -07:00
Vishnu KS
dbaea757ae
billing: Create downgrade_at_the_end_of_billing_cycle.
2020-09-28 15:37:49 -07:00
Vishnu KS
b8b2e443bc
stripe: Create void_all_open_invoices.
2020-09-28 15:37:49 -07:00
Vishnu KS
0d30f59c97
billing: downgrade_now -> downgrade_now_without_creating_additional_invoice.
2020-09-28 15:37:49 -07:00
Alex Vandiver
ab4f6b54ea
stripe: Do not log credit card issues as errors.
...
Problems with the card itself should not be logged as errors -- while
perhaps notable in aggregate, they are not worthy of being logged to
Sentry, for instance.
Downgrade these to `info`; continue to log other problems at the
`error` level. This updates tests for this change, and in so doing
corrects a test that does not do its job, due to a missing
`reset_mock`.
2020-09-23 15:29:47 -07:00
Anders Kaseorg
b7b7475672
python: Use standard secrets module to generate random tokens.
...
There are three functional side effects:
• Correct an insignificant but mathematically offensive bias toward
repeated characters in generate_api_key introduced in commit
47b4283c4b4c70ecde4d3c8de871c90ee2506d87; its entropy is increased
from 190.52864 bits to 190.53428 bits.
• Use the base32 alphabet in confirmation.models.generate_key; its
entropy is reduced from 124.07820 bits to the documented 120 bits, but
now it uses 1 syscall instead of 24.
• Use the base32 alphabet in get_bigbluebutton_url; its entropy is
reduced from 51.69925 bits to 50 bits, but now it uses 1 syscall
instead of 10.
(The base32 alphabet is A-Z 2-7. We could probably replace all of
these with plain secrets.token_urlsafe, since I expect most callers
can handle the full urlsafe_b64 alphabet A-Z a-z 0-9 - _ without
problems.)
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-09-09 15:52:57 -07:00
Anders Kaseorg
61d0417e75
python: Replace ujson with orjson.
...
Fixes #6507 .
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-08-11 10:55:12 -07:00
Anders Kaseorg
60a25b2721
docs: Fix spelling errors caught by codespell.
...
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-08-11 10:23:06 -07:00
Vishnu KS
5b0b1efb15
support: Add functionality to approve sponsorship requests.
...
This should make it much easier to process these requests.
2020-07-24 17:55:38 -07:00
Vishnu KS
4c6350fa4b
billing: Add option to request a sponsorship in /upgrade.
2020-07-01 16:45:38 -07:00
Anders Kaseorg
f2e7076e2a
decorator: Replace type: ignore with cast, avoid Any.
...
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-06-30 18:58:23 -07:00
Anders Kaseorg
8667e632c8
python: Use isinstance with a tuple for testing multiple types.
...
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-06-30 18:58:23 -07:00
Anders Kaseorg
b95fc4858d
corporate: Replace unchecked cast calls with assert.
...
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-06-22 17:11:42 -07:00
Vishnu KS
508ba663dc
billing: Wrap make_end_of_cycle_updates_if_needed with transaction.atomic.
...
Otherwise, the plan would be left in an inconsistent state if one of the
queries fail.
2020-06-18 17:34:03 -07:00
Vishnu KS
cde4486f8c
billing: Support switching from monthly to annual plan.
2020-06-18 17:34:03 -07:00
Anders Kaseorg
f364d06fb5
python: Convert percent formatting to .format for translated strings.
...
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-06-15 16:24:46 -07:00
Anders Kaseorg
5dc9b55c43
python: Manually convert more percent-formatting to f-strings.
...
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-06-14 23:27:22 -07:00
Anders Kaseorg
69c0959f34
python: Fix misuse of Optional types for optional parameters.
...
There seems to have been a confusion between two different uses of the
word “optional”:
• An optional parameter may be omitted and replaced with a default
value.
• An Optional type has None as a possible value.
Sometimes an optional parameter has a default value of None, or None
is otherwise a meaningful value to provide, in which case it makes
sense for the optional parameter to have an Optional type. But in
other cases, optional parameters should not have Optional type. Fix
them.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-06-13 15:31:27 -07:00
Anders Kaseorg
365fe0b3d5
python: Sort imports with isort.
...
Fixes #2665 .
Regenerated by tabbott with `lint --fix` after a rebase and change in
parameters.
Note from tabbott: In a few cases, this converts technical debt in the
form of unsorted imports into different technical debt in the form of
our largest files having very long, ugly import sequences at the
start. I expect this change will increase pressure for us to split
those files, which isn't a bad thing.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-06-11 16:45:32 -07:00
Anders Kaseorg
67e7a3631d
python: Convert percent formatting to Python 3.6 f-strings.
...
Generated by pyupgrade --py36-plus.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-06-10 15:02:09 -07:00
Anders Kaseorg
8dd83228e7
python: Convert "".format to Python 3.6 f-strings.
...
Generated by pyupgrade --py36-plus --keep-percent-format, but with the
NamedTuple changes reverted (see commit
ba7906a3c6
, #15132 ).
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-06-08 15:31:20 -07:00
Vishnu Ks
66b1ad7002
billing: User FREE_TRIAL_DAYS instead of FREE_TRIAL_MONTHS.
2020-05-16 14:52:01 -07:00
Vishnu KS
f1b1bf5a0d
billing: Add support for Zulip Standard free trial.
2020-05-11 17:20:54 -07:00
Vishnu Ks
66a437bbf1
billing: Restrict max licenses to 1000 during upgrade via invoice.
2020-05-11 17:09:49 -07:00
Anders Kaseorg
7271fb68aa
logging: Pass format arguments to unconventionally-named loggers too.
...
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-05-02 16:37:07 -07:00
Vishnu KS
3f69500765
billing: Rename downgrade_realm_for_deactivation to downgrade_now.
2020-04-28 22:05:49 -07:00
Anders Kaseorg
fead14951c
python: Convert assignment type annotations to Python 3.6 style.
...
This commit was split by tabbott; this piece covers the vast majority
of files in Zulip, but excludes scripts/, tools/, and puppet/ to help
ensure we at least show the right error messages for Xenial systems.
We can likely further refine the remaining pieces with some testing.
Generated by com2ann, with whitespace fixes and various manual fixes
for runtime issues:
- invoiced_through: Optional[LicenseLedger] = models.ForeignKey(
+ invoiced_through: Optional["LicenseLedger"] = models.ForeignKey(
-_apns_client: Optional[APNsClient] = None
+_apns_client: Optional["APNsClient"] = None
- notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- signup_notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ signup_notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- author: Optional[UserProfile] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
+ author: Optional["UserProfile"] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
- bot_owner: Optional[UserProfile] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
+ bot_owner: Optional["UserProfile"] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
- default_sending_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
- default_events_register_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_sending_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_events_register_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
-descriptors_by_handler_id: Dict[int, ClientDescriptor] = {}
+descriptors_by_handler_id: Dict[int, "ClientDescriptor"] = {}
-worker_classes: Dict[str, Type[QueueProcessingWorker]] = {}
-queues: Dict[str, Dict[str, Type[QueueProcessingWorker]]] = {}
+worker_classes: Dict[str, Type["QueueProcessingWorker"]] = {}
+queues: Dict[str, Dict[str, Type["QueueProcessingWorker"]]] = {}
-AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional[LDAPSearch] = None
+AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional["LDAPSearch"] = None
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-22 11:02:32 -07:00
Anders Kaseorg
f8c95cda51
mypy: Add specific codes to type: ignore annotations.
...
https://mypy.readthedocs.io/en/stable/error_codes.html
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-22 10:46:33 -07:00
Stefan Weil
d2fa058cc1
text: Fix some typos (most of them found and fixed by codespell).
...
Signed-off-by: Stefan Weil <sw@weilnetz.de>
2020-03-27 17:25:56 -07:00
Vishnu KS
8b24d40585
billing: Create get_current_plan_by_realm helper function.
2020-03-25 10:54:10 -07:00
Vishnu KS
83da23c0d4
billing: Rename get_current_plan to get_current_plan_by_customer.
...
Also add tests.
2020-03-25 10:54:10 -07:00
Vishnu KS
9a2c64f3f4
billing: Create get_customer_by_realm helper function.
2020-03-25 10:54:10 -07:00
Vishnu KS
f8ddab58ba
billing: Downgrade plan to Limited during realm deactivation.
...
The realm would be instantly downgraded to Limited plan when
deactivated. Any extra users that were added in the final month
would not be charged.
2020-03-25 10:54:10 -07:00
Tim Abbott
f83871c182
corporate: Consistently use delivery_email for billing.
...
This is yet another corner case where EMAIL_ADDRESS_VISIBILITY_ADMINS
broke existing code.
2019-11-18 17:02:57 -08:00
Anders Kaseorg
93b1c3d94b
settings: Extract config file functions to a module.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2019-11-13 12:38:45 -08:00
Rishi Gupta
0b39263ec0
billing: Rename get_seat_count to get_latest_seat_count.
...
This will help as our billing system becomes more async to accommodate
on-prem billing.
2019-10-21 16:06:18 -07:00
Rishi Gupta
e10361a832
models: Replace is_guest and is_realm_admin with UserProfile.role.
...
This new data model will be more extensible for future work on
features like a primary administrator.
2019-10-06 16:24:37 -07:00
Anders Kaseorg
9a9de156c3
lint: Fix calls to _() on computed strings.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2019-04-23 15:23:03 -07:00
Rishi Gupta
1a7a449572
billing: Add backend support for downgrading.
2019-04-11 23:27:42 -07:00
Rishi Gupta
a529080f01
billing: Rename add_plan_renewal_to_license_ledger_if_needed.
2019-04-11 23:20:29 -07:00
Rishi Gupta
03d21c6317
billing: Refactor renewal_amount to return 0 instead of None.
2019-04-11 23:20:29 -07:00
Rishi Gupta
447ae77b24
billing: Add another live CustomerPlan.status.
...
Only CustomerPlan.ACTIVE is being used in the code / in production, so don't
need a db migration to move the other CustomerPlan.status constants around.
2019-04-11 23:20:29 -07:00
Rishi Gupta
4430f78aa3
billing: Rename next_renewal_date to start_of_next_billing_cycle.
2019-04-11 23:20:29 -07:00
Rishi Gupta
2270d4d192
billing: Try paying invoices when user puts a new card on file.
...
Previously, when users got a "payment failed" email from Stripe (e.g. if
their card failed on renewal), they would enter in a new card on
/billing#payment-method, and wouldn't find out if the card worked till
Stripe retried the payment 4 days later.
2019-04-05 13:36:03 -07:00
Rishi Gupta
28a586e502
billing: Add default value for event_time in invoice_plans_as_needed.
2019-04-05 11:24:45 -07:00
Vishnu Ks
ca1276961d
billing: Create get_discount_for_realm function.
2019-03-11 12:01:11 -07:00
Anders Kaseorg
f5197518a9
analytics/zilencer/zproject: Remove unused imports.
...
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2019-02-02 17:31:45 -08:00
Rishi Gupta
8f7e38c559
billing: Remove deprecated billing tables and fields from corporate/models.
2019-01-31 15:12:43 -08:00
Rishi Gupta
a37558b021
billing: Update get_seat_count to incorporate guests.
2019-01-30 10:35:01 -08:00
Rishi Gupta
db6e6472b1
billing: Set idempotency key to None when running test suite.
2019-01-30 10:35:01 -08:00
Rishi Gupta
4ccbeeb4a9
billing: Add an event_time argument to renewal_amount.
2019-01-29 07:37:21 -08:00
Rishi Gupta
a5324b6ea7
billing: Add a test for a race condition in process_initial_upgrade.
2019-01-29 07:01:31 -08:00
Rishi Gupta
9018ef5175
billing: Do not require a Stripe account to store Customer discounts.
2019-01-29 06:09:11 -08:00
Rishi Gupta
4aa2ac1b52
billing: Add functions for automatic invoicing of plans.
2019-01-28 16:04:11 -08:00
Rishi Gupta
421cda0e34
billing: Adding invoicing fields to CustomerPlan.
2019-01-28 16:04:11 -08:00
Rishi Gupta
83a7595feb
billing: Update next_renewal_date to take an event_time.
...
Also changes a < into a <= in add_plan_renewal_to_license_ledger_if_needed.
2019-01-28 16:04:11 -08:00
Rishi Gupta
7c11fe819a
billing: Update license ledger when users are added and removed.
2019-01-28 16:04:11 -08:00
Rishi Gupta
03c71dad17
billing: Fix misuses of CustomerPlan.discount.
2019-01-28 16:04:11 -08:00
Rishi Gupta
ad7a7b246e
billing: Move license management from CustomerPlan into its own table.
2019-01-19 16:00:44 +05:30
Rishi Gupta
112eb01728
billing: Remove PLAN_NAMES and other legacy code.
2019-01-18 11:46:17 +05:30
Rishi Gupta
e7220fd71f
billing: Do subscription management in-house instead of with Stripe Billing.
...
This is a major rewrite of the billing system. It moves subscription
information off of stripe Subscriptions and into a local CustomerPlan
table.
To keep this manageable, it leaves several things unimplemented
(downgrading, etc), and a variety of other TODOs in the code. There are also
some known regressions, e.g. error-handling on /upgrade is broken.
2018-12-22 13:39:30 -08:00
Rishi Gupta
5633049292
billing: Restructure validation of upgrade parameters.
2018-12-22 13:30:15 -08:00
Rishi Gupta
b4a28f3147
billing: Rename seat_count to licenses where appropriate.
2018-12-22 13:30:15 -08:00
Rishi Gupta
7ab1406962
billing: Prepare for moving Plan to CustomerPlan.billing_schedule.
2018-12-22 13:30:15 -08:00
Rishi Gupta
7b5d15d254
billing: Move discount to local Customer object.
...
A lot of the seemingly unrelated test fixture changes are because we're
removing a query to stripe in the upgrade path, in cases when the user's
realm has an existing Customer object.
2018-12-22 13:30:15 -08:00
Rishi Gupta
8ec91fc42d
billing: Remove process_downgrade.
2018-12-22 13:30:15 -08:00
Rishi Gupta
84a31ca800
billing: Remove BillingProcessor.
...
Leaving the model in place, so that we can do the database migration by
hand.
2018-12-22 13:30:15 -08:00
Rishi Gupta
b245c661da
billing: Change do_change_plan_type to take a realm instead of a user.
...
More often than not, changes in plan type are not directly due to user
action.
2018-12-13 13:26:24 -08:00
Rishi Gupta
c9c842ae2b
billing: Add randomness to idempotency key while testing.
...
Makes it easier to test or regenerate fixtures for
test_billing_quantity_changes_end_to_end with generate=True.
2018-11-30 23:14:52 -08:00