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.
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.
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.
The host of this URL could have been forged to redirect user
to a different subdomain and tests would still pass.
This also fixes the CodeQL warnings related to it.
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.
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.
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.
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.
When normalizing fixture data, all numbers were being
replaced if they matched `exp_month`. This can lead to various
errors and flaky fixture generation. We use a pattern match
which includes the parameter being matched to fix this.
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.
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.
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.
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.
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.
If this is called on a user without is_mirror_dummy=True, that seems
certain to be a bug. Therefore, an assert is preferable in order to
catch this, rather than returning early with noop like some other
function such as do_deactivate_user.
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.
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.
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.
Adds ability to configure a fixed-price plan and to delete a
configured fixed-price plan in the Cloud support view.
Updates the invoice processing to send reminder emails to the
billing support email for these Cloud fixed-price plans about
renewals since we now are able to configure them via our support
panel.
Updates function to get the billing session for stripe webhook
events to handle an intial upgrade for a custom generated invoice
for a fixed-price plan for a Cloud organization, which won't have
a user_id in the invoice metadata.
For cases where a customer is created in Stripe first for the manual
invoice, we want to connect that customer information to our Customer
object in the database. That way the customer can access the billing
page once the invoice is paid.
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.
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>
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.