Commit Graph

559 Commits

Author SHA1 Message Date
Lauryn Menard cac4adac5f billing: Keep stripe_customer_id when migrating to legacy plan.
The removal of the stripe_customer_id when creating a legacy plan
actually disconnects any existing information in Stripe about a
customer, who may have previously had a paid plan, so we don't
want that removal to happen. Instead we get or create the customer
associated with the billing session entity.

Also, updates some of the code comments in the function for legacy
plan migrations to be clearer.
2024-09-27 11:55:07 -07:00
Aman Agrawal 790d5c44a1 stripe: Allow customer to switch license management type.
Fixes #28633

Added a button to switch license management type on billing page.

Tested that the plan switch works correctly.

Tested that when switching from manual to automatic license
management, customer is only billed for billable users for the
next billing cycle.
2024-09-26 16:13:28 -07:00
Anders Kaseorg f0f048de69 corporate: Import corporate.lib.stripe lazily.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-09-24 18:18:26 -07:00
Anders Kaseorg fcafcb24d7 corporate: Fix decorators to pass arguments and update signatures.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-09-24 18:18:26 -07:00
Anders Kaseorg 5e62903d29 corporate: Use Literal types for upgrade parameters.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-09-24 18:18:26 -07:00
Lauryn Menard a89deb5e5c activity: Use icon for activity links and realm name for support view.
In the installation and integrations activity views, updates the
links to a realm's activity view to use the 'fa fa-table' icon,
instead of the realm name. Now, the realm name links instead to
the realm's support page.

Also, the integrations activity page now includes a link to a
realm's stats view.
2024-09-24 10:37:22 -07:00
Lauryn Menard 4bd4534450 billing: Enforce manual license management for guest role changes.
Adds a check for changing an existing guest user's role before
calling do_update_user in the case that a realm has a current
paid plan with manual license management.
2024-09-20 12:02:39 -07:00
Lauryn Menard 7861c1ba63 billing: Enforce manual billing renewal licenses for new users.
In addition to checking for available licenses in the current
billing period when adding or inviting new non-guest users, for
manual billing, we also verify that the number of licenses set
for the next billing period will be enough when adding/inviting
new users.

Realms that are exempt from license number checks do not have
this restriction applied.

Admins are notified via group direct message when a user fails
to register due to this restriction.
2024-09-20 12:02:39 -07:00
Lauryn Menard 73cb08265c billing: Extract helper for getting manual license management plans.
Prep commit for expanding these checks for the number of licenses
set for the next billing period (renewal licenses) and for changing
guest users' roles.
2024-09-20 12:02:39 -07:00
Lauryn Menard 137f4fccde billing: Highlight manual license management errors for admins.
In the billing portal UI for manual license management, limit
decreasing the number of licenses for the next billing period to
be less than the currently used licenses. If the customer is exempt
from license number checks, then this limit is not applied.

Also, visually highlight manual license management errors so that
the billing admin is aware of potential issues.

As of these changes, current licenses can be under the seat count
when a guest user is changed to a non-guest user. And next billing
period licenses can be under the seat cout when a user joins with a
currently available, purchased license after a billing admin has
decreased the number of licenses set for the next billing period.
2024-09-20 12:02:39 -07:00
Lauryn Menard b02cf53d5e billing: Validate license management at end of billing cycle.
For plans where we're enforcing correct manual license management,
before we create the renewal entry for the licenses ledger at the
end of a billing cycle, we should check that the current count of
billed licenses is not higher than what the renewal license count
would be.

Co-authored-by: Aman Agrawal <amanagr@zulip.com>
2024-09-20 12:02:39 -07:00
Lauryn Menard 900a7fa3ac billing: Remove settings tab from billing urls.
In commit 89003dcb25, we removed the tabs from the billing page.
2024-09-20 12:02:39 -07:00
Aman Agrawal 4d8e6ba094 stripe: Change stripe email on the upgrade page if available. 2024-09-19 11:26:21 -07:00
Aman Agrawal 9a4a07d933 stripe: Allow user to update email for sending invoice. 2024-09-19 11:26:21 -07:00
Lauryn Menard 2e394f3913 billing: Check minimum for plan tier for stale license count check. 2024-09-18 09:40:42 -07:00
Lauryn Menard 0147578de6 corporate: Make initial upgrade license checks more robust.
In cases where the seat count for automated license management is
stale when the upgrade process is initiated and the user has chosen
automated license management, we should get the current billable
license count when doing the initial payment/charge.

Also, makes the post-payment check for inconsistencies more robust
in that we check for both under and over billing cases. In the case
where the customer may have been overbilled, an email is sent to
the billing support team so that manual investigation can happen.
2024-09-11 11:16:55 -07:00
Lauryn Menard aad93e149e audit-log: Move remote server event types to AuditLogEventType enum.
Event types moved: REMOTE_SERVER_DEACTIVATED, REMOTE_SERVER_REACTIVATED
REMOTE_SERVER_PLAN_TYPE_CHANGED, REMOTE_SERVER_DISCOUNT_CHANGED
REMOTE_SERVER_SPONSORSHIP_APPROVED, REMOTE_SERVER_BILLING_MODALITY_CHANGED
REMOTE_SERVER_SPONSORSHIP_PENDING_STATUS_CHANGED, REMOTE_SERVER_CREATED
2024-09-09 11:50:13 -07:00
Lauryn Menard f7e07e91a2 audit-log: Move customer event types to AuditLogEventType enum.
Event types moved: CUSTOMER_CREATED, CUSTOMER_PLAN_CREATED
CUSTOMER_SWITCHED_FROM_MONTHLY_TO_ANNUAL_PLAN,
CUSTOMER_SWITCHED_FROM_ANNUAL_TO_MONTHLY_PLAN,
CUSTOMER_PROPERTY_CHANGED, CUSTOMER_PLAN_PROPERTY_CHANGED
2024-09-09 11:50:13 -07:00
Lauryn Menard bf4a650999 audit-log: Move stripe event types to AuditLogEventType enum.
Event types moved: STRIPE_CUSTOMER_CREATED, STRIPE_CARD_CHANGED
STRIPE_PLAN_CHANGED, STRIPE_PLAN_QUANTITY_RESET
2024-09-09 11:50:13 -07:00
Lauryn Menard d2c32f23db audit-log: Move realm event types to AuditLogEventType enum.
Event types moved: REALM_DEACTIVATED, REALM_REACTIVATED, REALM_SCRUBBED
REALM_PLAN_TYPE_CHANGED, REALM_LOGO_CHANGED, REALM_EXPORTED
REALM_PROPERTY_CHANGED, REALM_ICON_SOURCE_CHANGED, REALM_DISCOUNT_CHANGED
REALM_SPONSORSHIP_APPROVED, REALM_BILLING_MODALITY_CHANGED
REALM_REACTIVATION_EMAIL_SENT, REALM_SPONSORSHIP_PENDING_STATUS_CHANGED
REALM_SUBDOMAIN_CHANGED
2024-09-09 11:50:13 -07:00
Lauryn Menard c0100a3c4c billing: Rename AuditLogEventType to BillingSessionEventType.
This enum class is used only in billing code for mapping billing
actions to audit log event types, so the class name should clearly
reflect that.
2024-09-09 11:50:13 -07:00
Anders Kaseorg 91ade25ba3 python: Simplify with str.removeprefix, str.removesuffix.
These are available in Python ≥ 3.9.
https://docs.python.org/3/library/stdtypes.html#str.removeprefix

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-09-03 12:30:16 -07:00
Lauryn Menard d1e7c082b3 activity: Add header area to user activity view. 2024-08-28 14:12:36 -07:00
Lauryn Menard d54ca85de2 activity: Add view to see the ledger entries for a customer plan.
Adds a link to the plan ledger view in the current plan information
shown in the support views. Link is not shown if the plan is 100%
sponsored, e.g., the Community plan.

Adds a formatted header area to the activity table template so
that it's easy to add useful information to these activity views.
2024-08-28 14:12:36 -07:00
Lauryn Menard 44e73eecc1 support: Add basic information about realm.
Adds non-form section to Zulip Cloud support view with some basic
realm information: organization type, plan type, non-guest user
count and guest user count.

Uses a shared template for the basic realm data and adds a shared
support context dict for variables that are used in both remote
and Zulip Cloud support views.
2024-08-26 20:52:38 -07:00
Lauryn Menard b52b1bcca8 support: Consolidate sponsorship forms for remote and Zulip Cloud views.
In the Zulip Cloud support view, adds a "Realm management" section
for support actions that are specific to that view, (e.g., changing
an organization's type or deactivating an organization).

Moves the note about emailing organization owners when a full
sponsorship is approved for Zulip Cloud Standard to the success
message for that action, which mirrors the remote server/realm
support view.
2024-08-20 09:45:49 -07:00
Lauryn Menard 3d58a7ec04 remote-support: Add ability to configure temporary courtesy plan.
Expands section for scheduling plans in the remote support view to
have a form to create a temporary courtesy plan (aka our legacy
plan for remote servers and realms).

Form is not shown if there is a current plan for the remote billing
entity, and would raise a SupportRequestError in that case as well.
2024-08-16 16:40:18 -07:00
Lauryn Menard 391c52639f support: Show discount information on remote support views.
In commit 7203661d99, we removed the default_discount field on the
Customer model, but we didn't update the remote support views for
this change.

Adds a has_discount boolean to the SponsorshipData that's used in
the support views for headers, and updates the discount information
on a deactivated remote realm to show any pre-existing discounted
prices.
2024-08-15 09:51:35 -07:00
Alex Vandiver 8e1582d82e support: Reject attempts to approve sponsorship for deactivated orgs. 2024-08-13 20:29:02 -07:00
Anders Kaseorg 05e54a0af2 ruff: Fix E721 Use `isinstance()` for isinstance checks.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-08-01 16:46:58 -07:00
Anders Kaseorg 818bad300e corporate: Set assume_scheme="https" for django.forms.URLField.
The previous default of "http" is deprecated and will change to
"https" in Django 6.0.

https://docs.djangoproject.com/en/5.0/releases/5.0/#id2
https://docs.djangoproject.com/en/5.0/ref/forms/fields/#django.forms.URLField.assume_scheme

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-07-16 13:40:59 -07:00
Anders Kaseorg 1e9b6445a9 ruff: Fix PLR6104 Use `+=` to perform an augmented assignment directly.
This is a preview rule, not yet enabled by default.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-07-14 13:49:51 -07:00
Anders Kaseorg 48202389b8 ruff: Bump target-version from py38 to py310.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-07-13 22:28:22 -07:00
Anders Kaseorg 3f29bc42b1 ruff: Fix B905 `zip()` without an explicit `strict=` parameter.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-07-13 22:28:22 -07:00
Anders Kaseorg 1464009fae ruff: Fix UP038 Use `X | Y` in `isinstance` call instead of `(X, Y)`.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-07-13 22:28:22 -07:00
Anders Kaseorg 0fa5e7f629 ruff: Fix UP035 Import from `collections.abc`, `typing` instead.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-07-13 22:28:22 -07:00
Anders Kaseorg 531b34cb4c ruff: Fix UP007 Use `X | Y` for type annotations.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-07-13 22:28:22 -07:00
Anders Kaseorg e08a24e47f ruff: Fix UP006 Use `list` instead of `List` for type annotation.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-07-13 22:28:22 -07:00
Lauryn Menard 1969698cf6 stripe: Use comma for collection method Literal values. 2024-06-10 16:10:42 -07:00
Lauryn Menard 4fcf7945b0 support: Show annual revenue for active fixed price plans.
In the activity and support views, we want to see the annual
revenue for fixed price plans. While on billing pages, we do
not display this information as these plans are renegotiated
annually.

Adds get_annual_recurring_revenue_for_support_data function
to BillingSession class, so that we can get the fixed price
plan data for these views without changing the logic for
what is displayed on the billing pages.
2024-05-22 15:57:59 -07:00
Lauryn Menard 37afad038c support: Add link to stripe customer dashboard.
Adds a link to the stripe customer dashboard if the Customer
object for an active plan has a stripe_customer_id. If there
is no stripe ID to link to, then the icon is shown without
a link, which is the case for remote server/realm sponsorships
and legacy plans.
2024-05-22 11:32:46 -07:00
Anders Kaseorg b545abe1e2 typos: Fix typos caught by mwic.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-05-20 13:55:00 -07:00
Aman Agrawal 7203661d99 support: Set discounted price instead percentage for customers.
This allows us to set the price of a plan exactly as discussed with
the customer.
2024-05-16 02:18:43 -07:00
Vector73 8ab526a25a models: Replace realm.uri with realm.url.
In #23380, we are changing all occurrences of uri with url in order to
follow the latest URL standard. Previous PRs #25038 and #25045 has
replaced the occurences of uri that has no direct relation with realm.

This commit changes just the model property, which has no API
compatibility concerns.
2024-05-08 11:12:43 -07:00
Anders Kaseorg 31c7b2bfd7 stripe: Add assertions to fix errors flagged by mypy 1.10.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-04-30 13:58:24 -07:00
Anders Kaseorg b195dc5a89 stripe: Add missing stripe_customer_id assertions.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-04-30 13:58:24 -07:00
Anders Kaseorg 7b2a4304fc stripe: Stringify invoice metadata.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-04-30 13:58:24 -07:00
Anders Kaseorg 385cd038b0 stripe: Pass ids, not objects, to pagination API.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-04-30 13:58:24 -07:00
Anders Kaseorg 9ca64b21f3 stripe: Properly convert Period object to CreateParamsPeriod dict.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-04-30 13:58:24 -07:00
Anders Kaseorg 228ade86be stripe: Use absent days_until_due rather than invalid None.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-04-30 13:58:24 -07:00