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.
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.
Now visiting `/customer_portal` will correctly take you to the stripe
customer portal corresponding to the customer for editing.
There is no reason for us to block access to this page.
Renames should_schedule_upgrade_for_legacy_remote_server parameter
to upgrade_when_complimentary_access_plan_ends in both
process_initial_upgrade and compute_plan_parameters, as well as
associated variable names and relevant code comments.
Renames the remote_server_legacy_plan parameter in
process_initial_upgrade to instead be complimentary_access_plan,
as well as some relevant code comments in that function.
Adds COMPLIMENTARY_PLAN_TIERS to the CustomerPlan model so that
we start transitioning from the "legacy plan" language in the
billing system code. Adds a helper function that checks if the
plan tier is in COMPLIMENTARY_PLAN_TIERS.
Updates the sponsorship page context to use that helper function
and updates the relevant template for the updated user-facing
terminology.
Renames add_sponsorship_info_to_context to instead be
add_org_type_data_to_sponsorship_context since this function for
all billing entities is adding information about the organization
type for the sponsorship request form.
Being on a free trial also means that the billing entity is on a
paid plan.
If they are on a sponsored plan, then they are not on a free trial.
If they have a pending sponsorship request, then they will be
redirected to the billing page. Otherwise, they will be shown the
form to request a sponsored/discounted plan, which does not use
the free_trial boolean.
Reorders the logic in get_sponsorship_request_context so that the
early return for billing entities with a pending sponsorship request
that are also on a current paid plan is clearer.
Updates next_invoice_date since, as of commit caba57fe1e, we no
longer consider the plan's billing schedule (annual or monthly)
when invoicing for additional licenses.