Commit Graph

375 Commits

Author SHA1 Message Date
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
Rishi Gupta 698aeddc85 billing: Delete test_subscribe_customer_to_second_plan.
This used to be a more likely codepath, before we introduced
Customer.has_billing_relationship. It is no longer literally impossible to
hit this race condition, so I'm not deleting the code, but it's unlikely
enough that it's not worth figuring out how to test it.
2018-11-28 10:45:00 -08:00
Rishi Gupta 33ec86aa00 billing: Delete test_extract_current_subscription.
Already better tested by the upgrade and downgrade tests using mock_stripe.

Note that the line that was removed is actually not possible to reach, since
canceled subscriptions aren't shown on the Customer object.
2018-11-28 10:45:00 -08:00
Rishi Gupta 7bc23a8f85 billing: Turn off process_downgrade. 2018-11-26 16:24:54 -08:00
Rishi Gupta 08daefa4a3 billing: Update payment method string to incorporate billing by invoice.
Also fixes a bug in process_initial_upgrade. If you have a card on file
(e.g. from a previous subscription), and try to upgrade by billing by
invoice, neither the if nor the elif condition applies.
2018-11-24 11:56:13 -08:00
Vishnu Ks d8804a2474 billing: Change plan_interval to plan.interval.
There is no attribute called  plan_interval. The reason
this was missed by mypy is moost likely due to us using
Any instead of Subscription in extract_current_subscription.
2018-11-19 12:36:25 +05:30
Rishi Gupta 99506b486a billing: Add backend for paying by invoice. 2018-11-17 23:08:48 -08:00
Rishi Gupta 61e0c2693d billing: Use Subscription.save() instead of calling save on instances.
Continuation of 03d77bc.
2018-11-17 18:59:21 -08:00
Rishi Gupta 0670976cb1 billing: Remove PRINT_STRIPE_FIXTURE_DATA.
Made obsolete by mock_stripe.
2018-11-16 19:41:46 -08:00
Vishnu Ks 2e04cdbe5e billing: Show estimated subscription revenue on /activity.
[Substantial edits by Rishi Gupta]
2018-11-16 13:30:16 -08:00
Rishi Gupta 2e89ffb0e2 billing: Make it easier to access /billing in tests. 2018-11-07 22:18:54 -05:00
Rishi Gupta 458169928c billing: Rename Zulip Premium to Zulip Standard. 2018-10-24 10:42:16 -07:00
Rishi Gupta 03d77bc6af billing: Replace instance.save() Stripe API calls with class.save(instance).
This will make it easier to mock the calls in our new stripe mocking
framework. I believe the two forms are equivalent, assuming the Stripe
Python bindings aren't doing anything crazy. And if not, well hopefully our
new testing framework will catch it :).

[Idea originally from Vishnu KS.]
2018-10-18 11:16:00 -07:00
Vishnu Ks d8c19cb003 models: Move billing models from zilencer to corporate. 2018-10-11 14:54:29 -07:00
Vishnu Ks 59865797ac billing: Move billing tests from zilencer to corporate. 2018-10-01 15:44:02 -07:00
Vishnu Ks 93b398bc0a billing: Move zilencer/lib/stripe to corporate. 2018-10-01 15:43:44 -07:00