Clarify what the invoiced_through field on a CustomerPlan indicates
after the changes to the billing state machine as ledger entries
are processed in invoice_plan.
Updates the plan activity page where this field is shown to support
admin users for these changes as well.
Follow-up to #34643.
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.
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.
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.
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.
This commit removes the `/try-zulip` landing page.
The URLs are replaced with `chat.zulip.org/?show_try_zulip_modal`,
which leads to display a modal for spectators.
Fixes#34181.
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.
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.
Updates the name for the self-hosted complimentary access plan
to "Zulip Basic (complimentary)" instead of "Free (legacy plan)".
Since these plans are never billed in Stripe, we don't need to
hold to the 22 character limit for the plan name.
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.