641 Commits

Author SHA1 Message Date
Anders Kaseorg
f04f3bcbfc stripe: Order downgrade_small_realms_behind_on_payments_as_needed query.
Fixes nondeterminism that broke
test_downgrade_small_realms_behind_on_payments_as_needed.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-10-10 09:41:45 -07:00
Anders Kaseorg
c1a4dcf33d requirements: Upgrade Python requirements.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-09-30 16:47:54 -07:00
Anders Kaseorg
f24a0a6b81 ruff: Fix RUF059 Unpacked variable is never used.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-09-30 16:47:54 -07:00
Aman Agrawal
203da5008a stripe: Fix licenses not updated to latest seat count after trial ends.
Since we are forward dating the LicenseLedger entry user initially
paid for, we need to create the new LicenseLedger entry with
current license count so that user can be billed for the difference
in licenses.
2025-09-08 14:38:54 -07:00
Lauryn Menard
1caff10df7 corporate: Send fixed-price stale audit log internal billing email.
Still send an internal billing notice when a fixed-price plan is
invoiced while the remote server has stale audit log data. This
does not trigger updating the stale_audit_log_data_email_sent
field on the CustomerPlan as the plan will be invoiced in this
case.
2025-08-27 11:54:33 -07:00
Lauryn Menard
208f1b30db corporate: Invoice self-hosted fixed-price plans with stale data.
Because license counts do not change the amount due for plans with
a fixed-price, we invoice them for self-hosted customers even when
the audit log data from the server is stale.
2025-08-27 11:54:33 -07:00
Aman Agrawal
b771f92ea1 stripe: Return 400 error instead of 500 on invalid tier. 2025-08-27 09:08:55 -07:00
Aman Agrawal
9d643ba31b stripe: Add test to verify charge for new users during free trial.
Added test to check if customer is charged for new users after
invoice payment at the end of free trial.
2025-07-22 17:13:37 -07:00
Anders Kaseorg
d24eab02d2 request: Use Django 5.2 HttpRequest.get_preferred_type.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-07-17 14:37:11 -07:00
Aman Agrawal
c105bcc322 stripe: Fix free trial pay by invoice customer billed twice.
This was a result of us moving `billing_cycle_anchor` ahead in time
of the `LicenseLedger` entry the customer paid for. Thus, this
confused our logic in thinking that customer hasn't paid for
the current billing cycle.
2025-07-10 08:30:44 -07:00
Lauryn Menard
bbd0f6e11c support: Revise view for scrubbed realms.
When a realm is scrubbed, there should be no support actions to
take and all user information has been removed.
2025-06-18 16:51:25 -07:00
Anders Kaseorg
717cf60edf python: Use Django 5.2 reverse(…, query=…).
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-06-12 09:32:38 -07:00
Lauryn Menard
2912d48579 corporate: Rename CustomerPlan.invoice_overdue_email_sent field.
Renames invoice_overdue_email_sent to stale_audit_log_data_email_sent
to better reflect the email and state that field is tracking for
the CustomerPlan.
2025-05-30 14:57:00 -07:00
Lauryn Menard
9edabf5ac8 corporate: Revise internal billing emails for stale audit log data.
These emails are not necessarily sent when an self-hosted customer
has an outstanding invoice, e.g., they are on an annual plan and
the monthly check for additional licenses happens when the audit
log data is stale.

Updates the notice_reason to be "stale_audit_log_data" instead of
"invoice_overdue". Revises the email subject and text to better
reflect what the support admin needs to investigate.
2025-05-30 14:57:00 -07:00
Alex Vandiver
33f7da23a0 stripe: Do not place Realm objects into context. 2025-05-16 11:30:48 -07:00
Aman Agrawal
ac671e2e4b stripe: Fix bugged tracking of invoicing status of plan.
Properly track the current invoicing status using `invoicing_status`
and `invoiced_through` fields.
2025-05-16 10:55:57 -07:00
Aman Agrawal
e04a32dee6 stripe: Upgrade API_VERSION to "2025-04-30.basil".
This involves the following major changes to the code:
* `Invoice.upcoming` removed in https://docs.stripe.com/changelog/basil/2025-03-31/invoice-preview-api-deprecations.

* InvoiceItem always needs to be created with an Invoice id for
  InvoiceItem to be attached to the Invoice.

  This seems to just be required after the upgrade and looking at
  stripe python SDK history, this was how it was always supposed to work.

  This is a welcome change since it adds to the clarity of the code.

* Change due to following breaking changes:

  - https://docs.stripe.com/changelog/basil/2025-03-31/invoice-pricing-configurations
  - https://docs.stripe.com/changelog/basil/2025-03-31/add-support-for-multiple-partial-payments-on-invoices

  which removes and adds various parameters and attributes to the
  invoice related objects.

  Also, out of band invoices now count in `amount_paid` in Invoice as
  part of above linked changes.

  See https://github.com/stripe/stripe-python/blob/master/CHANGELOG.md
  for an easier to search list of changes.

* Removed `proration` parameter from testing since we were not using it
  and testing its constant `false` value would require us writing more
  custom code to access its value.

* Added test for "usd" for the currency, since there were some changes
  in the API related local currency and I wanted to check Invoices
  were being created as expected.
2025-05-14 13:45:35 -07:00
Aman Agrawal
3cdda91afe stripe: Link InvoiceItem to Invoice.
This is required for upgrading to the basil version of stripe.
Changes haven't been tested in this commit. It is just for easy
verification of changes.
2025-05-14 13:45:35 -07:00
Aman Agrawal
6fb7a21cef stripe: Update plan in database outside for loop.
Since we are not doing an early return here and the updated information
is not immediately used, we can skip updating the plan in database
till the end of for loop.
2025-05-14 13:45:35 -07:00
Aman Agrawal
ba9d183721 stripe: Only create flat discounts for renewal invoices.
If we only created invoice for additional licenses, we don't need
to add discount to the invoice.

Changes haven't been tested in this commit. It is just for easy
verification of changes.
2025-05-14 13:45:35 -07:00
Aman Agrawal
cfa7458797 stripe: Link InvoiceItem to Invoice.
This is required for upgrading to the basil version of stripe.
Changes haven't been tested in this commit. It is just for easy
verification of changes.
2025-05-14 13:45:35 -07:00
Aman Agrawal
af4cee9479 stripe: Link InvoiceItem to Invoice.
This is required for upgrading to the basil version of stripe.
Changes haven't been tested in this commit. It is just for easy
verification of changes.
2025-05-14 13:45:35 -07:00
Aman Agrawal
fbec6ab123 stripe: Only attempt payment if invoice is not paid.
Since it is possible that invoice can be paid before we reach here,
so only attempt payment if the invoice is not marked as 'paid'.

Fixes invoice already paid error from stripe when running tests.
2025-05-14 13:45:35 -07:00
Lauryn Menard
c2007ebf30 support: Fix unit for file upload usage information. 2025-05-09 09:04:57 -07:00
Lauryn Menard
7fc9d29c1e support: Show file upload usage compared to realm upload quota.
Implemented on Zulip Cloud support view only since this information
isn't relevant for self-hosted support actions.

Looking up the realm's currently used upload space adds 3 database
queries to the support view test as there is no RealmCount data for
the upload quota used in the test. And therefore installation_epoch
is called for the realm.

With RealmCount upload quota used data, only 2 additional database
queries would be made for the realm's support view data.
2025-05-08 09:38:02 -07:00
Lauryn Menard
4d1bfe6537 demo-orgs: Disable corporate upgrade and sponsorship pages.
Use a shared error template for demo organizations when rendering
the upgrade or sponsorship pages.

Demo organizations must be converted into a permanent organization,
i.e., not be automatically scheduled for deletion, to either apply
for a sponsorship/discount or upgrade to a paid plan.
2025-04-23 09:23:24 -07:00
Lauryn Menard
cb3dc88dcf corporate: Show "Fixed" as rate for fixed-rate plans in activity charts. 2025-04-21 11:18:40 -07:00
Lauryn Menard
b074288bac upgrade: Remove demo_organization_scheduled_deletion_date page param.
The demo_organization_scheduled_deletion_date has never been used
on the upgrade page, and currently raises a Zod error as what is
being sent for the value of that page param is a datetime object,
and not the datetime object converted to an integer.

We really only need the boolean value that checks if the demo
organization scheduled deletion date is not None for the upgrade
page logic, which is set in the context dict for that page, but
not in the page params.
2025-04-17 10:49:02 -07:00
Ethan Mayer
c12b94aea4 models: Refactor corporate/models.py into models package.
Fixes #34318.

Seperated models file into a package with component files.
2025-04-08 10:16:35 -07:00
Lauryn Menard
ec89e5afd2 billing: Improve error handling when invoicing plans as needed.
When we're unable to process an invoice for a customer due to a billing
or assertion error, we log the error and add the customer ID to a set
of failed customer IDs. This allows us to continuing invoicing other
customers, and at the same time not invoice any other pending plans
attached to a customer we failed to invoice.
2025-03-27 12:51:52 -07:00
Lauryn Menard
10fff6a691 billing: Extract helper for invoicing check of remote server audit log.
Extracts the logic for making sure that, for self-hosted plans, the
remote server audit log data is current before invoicing an active
plan.
2025-03-27 12:51:52 -07:00
Lauryn Menard
0f567a1a66 billing: Extract helper for sending invoice overdue email.
Extracts the logic for sending an email to billing support when
a remote server's audit log data is stale and there is an active
CustomerPlan that needs to be invoiced.
2025-03-27 12:51:52 -07:00
Lauryn Menard
10a02142dc billing: Extract helper for sending fixed price plan renewal email.
Extracts the logic for sending a reminder email about the end of a
fixed price plan to billing support into a separate function.
2025-03-27 12:51:52 -07:00
Anders Kaseorg
13bd8771f9 corporate: Parse Accept header instead of X-Requested-With.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-03-26 22:29:09 -07:00
Vector73
c049259d07 user: Remove is_billing_admin user property.
Removed `is_billing_admin` user property as it is no longer used since
billing permissions are now determined by `can_manage_billing_group`
realm setting.
2025-03-10 09:36:30 -07:00
Vector73
158fd58cde settings: Add "can_manage_billing_group" realm setting.
Added "can_manage_billing_group" realm group permission setting
to control who can manage billing and plans in the organization.

Fixes #32745.
2025-03-10 09:36:30 -07:00
Lauryn Menard
c4e3ccafa2 stripe: Delete fixed price plan offer if customer on comp access plan.
Updates delete_fixed_price_plan to use the same structure as
configure_fixed_price_plan. If there is a customer plan and it's
billable, then we delete the configured CustomerPlan object. If
there is no customer plan or it's a complimentary access plan, we
delete the configured CustomerPlanOffer object.
2025-02-28 17:42:04 -08:00
Lauryn Menard
add58e3795 billing: Use customer.minimum_licenses for minimum plan check.
Allow for manually setting a minimum_licenses value on a customer
to return that for min_licenses_for_plan in cases where we wanted
to override the general plan minimum for a particular case.
2025-02-20 14:17:25 -08:00
Anders Kaseorg
4e04eed745 typos: Fix typos caught by typos and mwic.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-02-18 19:44:02 -08:00
Anders Kaseorg
3b84dd3b8c stripe_event_handler: Fix UP038.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-01-24 22:59:58 -08:00
Aman Agrawal
b549562a4d sponsorship: Ask user how they plan to use Zulip.
This will help avoid some back-and-forth on sponsorship requests.
2025-01-22 09:22:52 -08:00
Aman Agrawal
6e1bb56519 stripe: Check for min_licenses when switching plan tier.
When we are upgrading a customer to a different plan tier, we should
check if switching plans would lead to different licenses due to
different minimum license requirement between plans.
2025-01-21 15:53:53 -08:00
Lauryn Menard
10b2e2a092 support: Update support view PlanData to use "complimentary access".
Prep for implementing a complimentary access plan for Zulip Cloud.
2025-01-21 15:40:27 -08:00
Lauryn Menard
261333c37f corporate: Clean up code remaining comments with "legacy plan".
Replaces documentation in billing code and tests to use
"complimentary access plan" instead of "legacy plan".
2025-01-21 15:40:27 -08:00
Lauryn Menard
bc20a0f086 support: Update "temporary courtesy" to "complimentary access".
Updates support actions for "temporary courtesy" plans to instead
use "complimentary access" to refer to these plans and actions.

Prep for implementing a complimentary access plan for Zulip Cloud.
2025-01-21 15:40:27 -08:00
Lauryn Menard
d3bc9bec1d billing: Rename migrate_customer_to_legacy_plan.
Renames migrate_customer_to_legacy_plan to
create_complimentary_access_plan for how this
function is currently used.

Prep for adding a complimentary access plan
for Zulip Cloud.
2025-01-21 15:40:27 -08:00
Aman Agrawal
b870faec5a stripe: Require 10 minimum licenses for cloud plus plan. 2025-01-16 11:32:03 -08:00
Aman Agrawal
e0767b23ed stripe: Validate licenses for the correct plan.
Since licenses are being created for the `new_plan` we need to
check licenses for the new plan here.
2025-01-16 11:32:03 -08:00
Lauryn Menard
e963d5eaa9 billing: Fix deleting next fixed-price plan via support.
If the customer has a current fixed-price plan and a support admin
configures a fixed-price plan for the upcoming billing year, then
a CustomerPlan object is created and not a CustomerPlanOffer.

Fix the support action for deleting a configured fixed-price next
plan.

Updates the success strings for these actions to be specify if the
deleted object was a plan offer or a scheduled plan.
2025-01-15 11:23:24 -08:00
Anders Kaseorg
653b0b0436 ruff: Partially reformat Python with Ruff 0.9 (2025 style).
These are the changes that are backwards compatible with the 2024
style.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-01-14 09:42:16 -08:00