No renewal ledger entry exists for a scheduled fixed-price plan.
Earlier, when a customer with scheduled fixed-price plan
visited the billing page, the 'get_next_billing_cycle' function
raised an assertion error as no renewal ledger entry exists.
We don't need the ledger entry to determine the next billing
cycle in this case, so we move the code block which determines
the last_renewal time within the else conditional i.e. where it
is needed.
The scheduled plan has NEVER_STARTED status and the
next_invoice_date set to end date of the current plan.
We use this info to determine the next billing cycle.
If the remote realm registered after the legacy plan on server
ENDED, we never migrate the plan to the remote realm. So, we need
to check the server of remote realm whenever we are check remote
realm for legacy plan.
Regardless of plan renewal schedule, we try to invoice all plans
monthly with some exceptions like free trial and fixed price plans,
which help us charge users for additional licenses used during
the previous month.
Includes has_stale_audit_log boolean in the remote support view
data so that we can style the last audit log data for the remote
server to visually highlight if it is stale or current.
Refactors the Cloud support view to pass in any sponsorship or
discount information about the Customer object for the realm,
which allows us to display any information submitted in a
sponsorship request.
Earlier, we were using 'timezone_now' (the time cron job runs)
as the event_time while invoicing plans in 'invoice_plan'.
This is not accurate as it will lead to invoicing ledger entries
created after 'next_invoice_date' and before 'timezone_now'.
We should only invoice the ledger entries created till
next_invoice_date. It should be independent of the time
at which cron job runs.
This commit updates the logic to use next_invoice_date
as the event_time while invoicing via cron.
Earlier, at few places in test_stripe we were doing
incorrect time travel. For example:
A plan was invoiced till self.next_year & while checking
the billing page, we were using the self.now datetime.
To correctly check the billing page state after plan is
invoiced, we should use a datetime greater than or equal
to the time at which plan was invoiced.
This commit fixes such logically incorrect time-travel.
While creating a LicenseLedger entry in 'create_customer_and_plan',
we should set the 'event_time' to the same time at which the plan
is created.
Earlier, the 'event_time' for ledger entry & 'billing_cycle_anchor'
of the plan were set to different values, which is not the
correct behavior.
Earlier, the code block to calculate additional licenses charge
raised assertion error when processing a fixed-price plan.
The code block shouldn't be executed for fixed-price plans as
we don't charge customers on fixed-price plans for additional
licenses.
Earlier, the 'self.on_paid_plan()' check was verifying if the
billing_session/customer is on paid plan and not the plan we
are processing.
This resulted in a bug. While processing a legacy plan, a customer
switches from legacy plan to a paid plan resulting in the
'self.on_paid_plan()' check returning True.
It leads to invoicing legacy plan which shouldn't happen.
The fix is to check if the plan we are processing is paid or not
instead of the remote_realm/remote_server plan_type.
It's best for these to just be consistent. Therefore:
1. The .../not-configured/ error page endpoint should be restricted to
.has_billing_access users only.
2. For consistency, self_hosting_auth_view_common is tweaked to also do
the .has_billing_access check as the first thing, to avoid revealing
configuration information via its redirect/error-handling behavior.
The revealed configuration information seems super harmless, but it's
simpler to not have to worry about it and just be consistent.
Just shows a config error page if the bouncer is not enabled. Uses a new
endpoint for this so that it can work nicely for both browser and
desktop app clients.
It's necessary, because the desktop app expects to get a json response
with either an error or billing_access_url to redirect to. Showing a
nice config error page can't be done via the json error mechanism, so
instead we just serve a redirect to the new error page, which the app
will open in the browser in a new window or tab.
The remote support view now returns results for deactivated remote
servers with those results sorted to the end and formatted to
visually stand out.
Forms to change sponsorship and discount fields on the customer
for the remote server or realm are not shown, but the data stored
on the customer object is shown, including any sponsorship request
information (if the customer had a sponsorship request pending when
it was deactivated).
Forms to schedule a plan are also not shown for deactivated servers
and their associated remote realms.
Forms and information for any current plan or scheduled plan, for
either the deactivated remote server or its associated remote
realms, are shown so that support staff can update those plans if
necessary.
Earlier, the 'next_invoice_date', 'invoiced_through', and
'invoicing_status' fields in 'do_change_schedule_after_free_trial'
were not set correctly.
It resulted in invoicing the ENDED plan and the ledger we create
in this function.
Multiple invoices were created depending on the number of times the
billing frequency was changed for customers who started free-trial
& changed their billing frequency.
This commit sets those fields correctly leading to create only one
invoice.
As a follow-up to commit d66b7ad853, where we send internal emails
when an active paid plan is on a locally deleted remote realm, we
need search queries in the remote support view to return results
for these deactivated remote realms, instead of excluding them.
This is a prep commit which replaces the 'invoice_overdue'
and 'reminder_to_review_plan' email templates with
'internal_billing_notice'.
This will help us to use the same template as we plan to
send an email to sales when a remote realm with paid plan
attached is locally deleted.
Because the remote support page now supports searching by UUID,
the support URL for remote billing entities, which is used for
sponsorship request emails and overdue invoice emails, can now
use the remote server or realm UUID.
Adds the remote realm UUID to the remote support view information.
Earlier, for fixed-price plans we were showing the generic
next payment info on billing page which stated that plan
will automatically renew on end_date. It is no longer correct
for fixed-price plans.
This commit fixes the next payment info for fixed-price plans.
When the next_billing_cycle is the end_date, we inform the customer
that their plan will end on end_date and zulip sales will contact
them a couple of month ago before the end_date for renewal.
Earlier, the 'renewal_amount' context variable passed to the billing
template was always a non-empty string which is a truthy value.
The expected behavior is that 'renewal_amount' should be falsy value
if the renewal_cents is 0. This commit fixes the incorrect behavior
and returns None in this case.
Adds the information returned by get_push_status_for_remote_request
for remote billing users to the support page. Note that getting
the current push status data will result in some duplicate database
queries (getting customer, plan, current billed users, next billing
cycle) when generating the remote support view.
The previous logic incorrectly used the server-level number of users
even when a (presumably smaller) realm-level count was available.
Fixes a bug introduced in 2e1ed4431a.
Instead of querying the database twice for the user counts and
for the currently used licenses, we know pass that information
to the function where we populate the plan data for the remote
server or realm.
Only get the customer information once from the database.
Extract logic for any next plan (either scheduled or an offer) data
into a separate function and do not hit database twice when getting
the number of licenses at the next plan renewal.
Removes prefetch of remote realms on the remote server query
because, by excluding the system bot realm when this is referenced,
we end up hitting the database again.
Strips whitespace from query string and makes a few small updates
for readability.
We no longer want to migrate Legacy plans from server to realms, since
Legacy plans are not really a thing in the original sense anymore, since
February 15th.
Now they're just a tool to give temporary extensions of access to the
push notification service for users, when needed. And as such, it makes
no sense to migrate like that.
The remaining code in this function is for migrating (any) plan from the
server object to the realm object, if the server has just a single
realm.
For fixed-price plans, we send a reminder email to
sales@zulip.com, 2 months before the end date, to review
the pricing and configure a new fixed-price plan accordingly.
Earlier, we were not configuring the end_date while creating
a fixed-price plan which would result in the automatic renewal
of the plan at the end of billing cycle.
Our plan is to re-evaluate the pricing when we are close to the
end date, then:
1. Schedule a new fixed-price plan with the updated or same price.
2. or Don't do anything - the plan will end on the end_date.
Now, we add an end_date of 1 year from the start date when
creating a fixed-price plan.