Because the main indexes on end_time either don't include realm_id or
do include subgroup, passing an explicit subgroup=None for
single-realm queries to read CountStats that don't use the subgroups
feature greatly improves the query plans.
The removal of the stripe_customer_id when creating a legacy plan
actually disconnects any existing information in Stripe about a
customer, who may have previously had a paid plan, so we don't
want that removal to happen. Instead we get or create the customer
associated with the billing session entity.
Also, updates some of the code comments in the function for legacy
plan migrations to be clearer.
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.
In the installation and integrations activity views, updates the
links to a realm's activity view to use the 'fa fa-table' icon,
instead of the realm name. Now, the realm name links instead to
the realm's support page.
Also, the integrations activity page now includes a link to a
realm's stats view.
Adds a boolean export parameter to the installation activity view.
When true, the initial links column is removed from the chart, a
blank column is removed before human message counts anda column
with all organization owner and admin emails is added.
Updates the links at the top of the installation activity page to
have an option to toggle between the export and non-export versions
of the chart.
Adds a check for changing an existing guest user's role before
calling do_update_user in the case that a realm has a current
paid plan with manual license management.
In addition to checking for available licenses in the current
billing period when adding or inviting new non-guest users, for
manual billing, we also verify that the number of licenses set
for the next billing period will be enough when adding/inviting
new users.
Realms that are exempt from license number checks do not have
this restriction applied.
Admins are notified via group direct message when a user fails
to register due to this restriction.
Prep commit for expanding these checks for the number of licenses
set for the next billing period (renewal licenses) and for changing
guest users' roles.
In the billing portal UI for manual license management, limit
decreasing the number of licenses for the next billing period to
be less than the currently used licenses. If the customer is exempt
from license number checks, then this limit is not applied.
Also, visually highlight manual license management errors so that
the billing admin is aware of potential issues.
As of these changes, current licenses can be under the seat count
when a guest user is changed to a non-guest user. And next billing
period licenses can be under the seat cout when a user joins with a
currently available, purchased license after a billing admin has
decreased the number of licenses set for the next billing period.
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.
As guest users are charged at a different rate on Zulip Cloud, it
makes sense to track these changes in our LicenseLedger table so
that we can have an accurate record of the use of licenses that
a realm has purchased.
We only make `id` and `timestamp` field of the fixture unique whose
uniqueness matters to us in the tests. Other fields don't matter, so
we normalized them completely with a constant so that they don't
have different values when generating fixtures repeatedly.
Expands the header information on the plan activity view to include
the license ledger that was set as invoiced_through when the last
billing cycle generated an invoice.
Also, updates the name of the header information for the next
invoice date to match what's show in the support view for the plan.
Includes the license counts, date and renewal information as well
as the id field, so that print debugging and displaying these
objects is easier and more useful.
Adds a link to the plan ledger view in the current plan information
shown in the support views. Link is not shown if the plan is 100%
sponsored, e.g., the Community plan.
Adds a formatted header area to the activity table template so
that it's easy to add useful information to these activity views.
Adds non-form section to Zulip Cloud support view with some basic
realm information: organization type, plan type, non-guest user
count and guest user count.
Uses a shared template for the basic realm data and adds a shared
support context dict for variables that are used in both remote
and Zulip Cloud support views.
Gives a baseline of current database queries for these single realm
or remote realm support views, so that as we add features to these
views, we can better manage how those changes impact the performance
of our support views in general.
There are a few places where we want to set the max invites for a
realm to the default for a realm's plan type, so this creates a
helper function that can be used consistently to get that default
value.
Generated using manage.py squashmigrations, with some work:
- Used my patch to support squashing AddConstraint/RemoveConstraint
operations.
- Manually removed the add/deletion of cloud_xor_self_hosted, since it
didn't squash properly.
- Temporarily removed a couple operations from their migration files,
and added them back manually both to the original file and the
squash file, to allow later operations to squash
properly. Specifically, these are the two unsquashed operations
documented with comments at the end of the squash migration file.
Adds some validation for changing the realm's max invites via the
support view so that it is not set below the default max for the
realm's plan type, and so that if it's currently set to the default
max it's not reset to that same value.
In the Zulip Cloud support view, adds a "Realm management" section
for support actions that are specific to that view, (e.g., changing
an organization's type or deactivating an organization).
Moves the note about emailing organization owners when a full
sponsorship is approved for Zulip Cloud Standard to the success
message for that action, which mirrors the remote server/realm
support view.
Expands section for scheduling plans in the remote support view to
have a form to create a temporary courtesy plan (aka our legacy
plan for remote servers and realms).
Form is not shown if there is a current plan for the remote billing
entity, and would raise a SupportRequestError in that case as well.