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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.