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.
This is a prep commit which extracts the write_to_audit_log
code block in `update_end_date_of_current_plan` into a
function named 'write_to_audit_log_plan_property_changed'.
This would be helpful to avoid repetition as we plan to
include another such block when the plan's property
reminder_to_review_plan_email_sent is changed.
The logic in the case where there's only one realm and the function
tries to migrate the server's plan to it, had two main unhandled edge
cases that would throw exceptions:
1.
```
remote_realm = RemoteRealm.objects.get(
uuid=realm_uuids[0], plan_type=RemoteRealm.PLAN_TYPE_SELF_MANAGED
)
```
This could throw an exception if the RemoteRealm exists, but has an
active e.g. Legacy plan. Then there'd be no object matching the
plan_type in the query, raising RemoteRealm.DoesNotExist.
2. If the RemoteRealm had e.g. a Legacy plan in the past, that's now
expired, then it'd have a Customer object. Meaning that the attempt
to move the server's customer to the realm:
`server_plan.customer = remote_realm_customer`
would trigger an IntegrityError since a RemoteRealm can't have two
Customer objects.
In simple cases the situation in (2) can still be easily migrated, by
moving the plan from the server's customer to the realm's customer.
This is kind of too specific, allowing testing for only one single error
when accessing signed_auth_url. Instead, this should use a general
pattern, which will allow other tests to use this to assert other kinds
of error responses that may be returned.
It doesn't make sense to run a loop over "all" query results, when those
results are just two, and each of them has its own distinct asserts.
That for loop is there probably due to copying the structure of the
earlier test_transfer_legacy_plan_from_server_to_all_realms test, for
which the loop does make sense.
In 'invoice_plan()', the primary way to not create
an invoice for a plan is to not have any new ledger entry.
This commit adds a 'self.on_paid_plan()' check which is
an extra layer of defense to avoid creating any invoices
for customers not on paid plan. It saves a DB query too.
RemoteRealm customer takes precedence over RemoteServer
in general. But if an inactive plan is associated with
RemoteRealm and an active plan with RemoteServer, the
ACTIVE plan takes precendence.
Co-authored-by: Prakhar Pratyush <prakhar@zulip.com>
Instead of displaying the end of the day interval for the latest
count stat update for push notifications forwarded on the bouncer,
we display the start of the day interval and format it as a date
instead of a date and time.
In commit 230294c, the logic for creating the support links in the
remote activity chart were broken. Updates the constants so that
the links have the correct server information for the search query.
Earlier, during invoicing we used to send a mail to
sales@zulip.com when the last_audit_log_update was
at least one day ago.
There was an assertion that last_audit_log_update
can't be None which is incorrect as such customers exist.
This commit extends the behaviour to send an invoice
overdue email even if the data was never uploaded.
In cases where a support admin approves a sponsorship for a remote
server without any billing users having been created, note that no
emails were sent in the success message on the support page.
We already do this for remote realms and should be an infrequent
case as ideally most remote servers will submit official
sponsorship requests.
Earlier, on extending end_date for legacy plans, next_invoice_date
was not extended which resulted in invoice_plan() run for such
legacy plans before the end_date.
The intended behaviour is that the legacy plan should be invoiced
only once on the end_date to downgrade or switch to a new tier.
This commit adds logic to update next_invoice_date when end_date
is extended via /support.
Expands the main query for remote servers to get the audit log
event datetime for when the server was created/registered.
The remote realm object has a field for when the remote realm
was created on the remote server.
Adds a link on the upgrade and billing pages that opens a stripe
billing portal for the customer to update their name and address
that will appear on invoices and receipts.
On the billing page, updating the credit card information will
no longer update the customer billing address, since they can
now do this directly through the billing portal. To be consistent
with the credit card form on the upgrade page, we still require
inputting a billing address for the card.
Note that, once an invoice is paid/complete, then changes to the
customer's name and address will not be applied to those invoices.
Set the name on the stripe customer object to the name on the
credit card when one is initially attached to a customer.
Prep commit to adding a stripe billing portal so that billing
admins will be able to update both the name and address that
appears on their stripe generated invoices and receipts.
Instead of charging the customer using the attached payment
method and then creating the invoice, we create an invoice and
force an immediate payment for the invoice via the attached
payment method.
Earlier, we were not setting `free_trial` = False for legacy
customers in `do_upgrade`.
This lead to a bug where customers were upgraded even before the
payment was complete. 'process_initial_upgrade' was always getting
called instead of 'setup_upgrade_payment_intent_and_charge'.
This commit fixes the incorrect behaviour.
Adds a count for mobile users registered for the remote server
with a RemotePushDeviceToken that does not have an associated
remote realm, which was a recently added field.
If the remote server is pre-8.0 and does not have remote realms,
then only the total mobile user count is displayed, as the count
for uncatagorized mobile users would be equal to the total mobile
user count.
This is useful in the support view in case the audit log data is
stale and user counts are not updated for billing.
Also, renames formatting function for optional datetimes that is
used in the support and activity views/charts. And instead of
showing these datetime strings in the eastern US timezone, we
now show and label them as UTC.
This will require customers to include an address when setting
up, or updating, the credit card information for their account.
The billing address for the card will also be saved as the
billing address for the stripe customer object.
The customer object billing address appears on the invoices
that are generated by stripe.
Adds a column with the percentage rate that the remote server
or realm is paying on the displayed plan.
We display 0% for community plans that are 100% sponsored.
For legacy plans or plans with a scheduled downgrade, we
display a placeholder, "---". Otherwise, the value is
calculated from the CustomerPlan discount field.
Earlier, when a fixed-price plan for a customer with
no current plan was configured via /support, the next plan
info was missing on support page.
It was because we were considering next plan only if the
customer had a current plan.
This commit fixes the incorrect behaviour.