Commit Graph

544 Commits

Author SHA1 Message Date
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
Anders Kaseorg 0af62519a1 stripe: Isolate ignored error for undocumented Invoice.list usage.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-04-30 13:58:24 -07:00
Anders Kaseorg e7a3d743d1 stripe: Use more specific type annotations.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-04-30 13:58:24 -07:00
Aman Agrawal 7d1f858273 stripe: Ensure required_plan_tier is set before setting discount. 2024-04-29 17:11:11 -07:00
Aman Agrawal 2d824e85cc stripe: Remove invalid comment.
We use `error_description` in upgrade.ts to determine if the error was
related to customer's card. Doesn't seem like there is any harm
in doing so since we are explicitly handling "stripe.CardError" and
raising these errors with "card error" description.
2024-04-22 09:20:17 -07:00
Aman Agrawal 42bbeb6247 stripe: Change pricing for plus plan.
This also now allows user to upgrade to plus plan from pricing page.

Note that since we don't pass customer_plan on pages like self-hosting
and for/business, `Current plan` status is not displayed on these pages.
2024-04-19 09:57:43 -07:00
Prakhar Pratyush 14415dfa90 invoice_paid_event: Verify invoice before activating fixed-price plan.
Earlier, we were not verifying that the invoice which got paid is
for the fixed-price plan.

That could result in a bug where another support invoice with
collection_method = "send_invoice" got paid while a fixed-price
plam is already configured. The fixed-price plan would be falsely
activated.

This commit verifies the invoice before activating the fixed-price
plan.
2024-04-16 09:49:04 -07:00
Mateusz Mandera 4a2a9176c2 realms: Add caching to the get_seat_count calculation for upload limit.
For simiplicty's sake, we can avoid trying to do cache invalidation in
the variety of events that can cause the seat count to change - since
having an up to 1 day delay between users being added and the upload
limit going up is quite reasonable.
2024-04-15 15:08:56 -07:00
Mateusz Mandera 4eacd25ad5 stripe: Rename CustomerPlan.is_paid.
This might not be the most meaningful change of phrasing, but .is_paid()
sounds like it's a check for whether the customer has already paid their
invoice. is_a_paid_plan() reflects better the meaning that it's whether
it's a plan of a "paid" type.
2024-04-15 15:08:56 -07:00
Aman Agrawal 8a807949df stripe: Disable free trial for customer with any plan in the past. 2024-04-11 21:57:33 -07:00
Aman Agrawal ed2de77895 stripe: Send invoice to customer at the start of free trial.
We send customer an invoice at the start of free trial, if customer
pays we upgrade them to the active plan at the end of free trial,
else we downgrade them and show a custom message on the upgrade
page regarding the current status.
2024-04-11 21:57:33 -07:00
Aman Agrawal 8715ead8bc stripe: Regenerate stripe fixtures with fixed tests.
Tests were broken since #29221 and #28875 didn't account for
other tests failing due to changed stripe data. Also, there
was a bug where we were not fetching the correct setup intent
and stripe session for the current test, it was fixed by narrowing
the fetch to the current customer.

Also, we now run `invoice_plans` in a `while` loop until
`next_invoice_date` is greater than the provided event_time. It
makes sense to generate all the invoices for a customer that
needs to paid by them when `invoice_plans_as_needed` is called
for a `event_time`.
2024-04-11 21:57:33 -07:00
Aman Agrawal a2e0c84a7e stripe: Remove unused parameter. 2024-04-11 21:57:33 -07:00
Prakhar Pratyush e3f8c62e34 registration: Send a group DM to admins when no spare licenses left.
Earlier, when adding a new user failed due to no spare licenses
available, a message was sent to the "New user announcements"
stream.

We plan to disable the stream by default as a part of improving
onboarding experience.

Now, we send a group DM to admins when adding a new user fails
due to no spare licenses available. It makes it independent of
the "New user announcements" setting. These warning messages
are important and shouldn't be missed.
2024-04-03 12:28:05 -07:00
Aman Agrawal b86e37a979 stripe: Add period information for generated invoices.
Invoices need to have period to avoid charges being marked as
point-in-time revenue rather than monthly revenue.
2024-03-30 14:56:12 -07:00
Prakhar Pratyush a0cec2c378 stripe: Skip invoice overdue mail for free plans with no next plan.
Earlier, if a free plan (say legacy plan) with no next plan scheduled
was invoiced, we used to send an invoice overdue email if the last
audit log update is stale.

Actually, we don't need this data as the invoice step is just going
to downgrade the current plan. We should not wait for customer to
start uploading data in this case. Skip the email sending step and
invoice the plan to downgrade.
2024-03-28 09:29:23 -07:00