diff --git a/corporate/lib/stripe.py b/corporate/lib/stripe.py
index d9bc15e3ea..8a00b90e54 100644
--- a/corporate/lib/stripe.py
+++ b/corporate/lib/stripe.py
@@ -154,23 +154,27 @@ def get_cached_seat_count(realm: Realm) -> int:
return get_latest_seat_count(realm)
-def get_seat_count(
- realm: Realm, extra_non_guests_count: int = 0, extra_guests_count: int = 0
-) -> int:
- non_guests = (
+def get_non_guest_user_count(realm: Realm) -> int:
+ return (
UserProfile.objects.filter(realm=realm, is_active=True, is_bot=False)
.exclude(role=UserProfile.ROLE_GUEST)
.count()
- ) + extra_non_guests_count
-
- # This guest count calculation should match the similar query in render_stats().
- guests = (
- UserProfile.objects.filter(
- realm=realm, is_active=True, is_bot=False, role=UserProfile.ROLE_GUEST
- ).count()
- + extra_guests_count
)
+
+def get_guest_user_count(realm: Realm) -> int:
+ # Same query to get guest user count as in render_stats in analytics/views/stats.py.
+ return UserProfile.objects.filter(
+ realm=realm, is_active=True, is_bot=False, role=UserProfile.ROLE_GUEST
+ ).count()
+
+
+def get_seat_count(
+ realm: Realm, extra_non_guests_count: int = 0, extra_guests_count: int = 0
+) -> int:
+ non_guests = get_non_guest_user_count(realm) + extra_non_guests_count
+ guests = get_guest_user_count(realm) + extra_guests_count
+
# This formula achieves the pricing of the first 5*N guests
# being free of charge (where N is the number of non-guests in the organization)
# and each consecutive one being worth 1/5 the non-guest price.
diff --git a/corporate/lib/support.py b/corporate/lib/support.py
index cb008d992e..192734c1c1 100644
--- a/corporate/lib/support.py
+++ b/corporate/lib/support.py
@@ -15,6 +15,8 @@ from corporate.lib.stripe import (
RemoteRealmBillingSession,
RemoteServerBillingSession,
get_configured_fixed_price_plan_offer,
+ get_guest_user_count,
+ get_non_guest_user_count,
get_price_per_license,
get_push_status_for_remote_request,
start_of_next_billing_cycle,
@@ -110,10 +112,17 @@ class RemoteSupportData:
mobile_push_data: MobilePushData
+@dataclass
+class UserData:
+ guest_user_count: int
+ non_guest_user_count: int
+
+
@dataclass
class CloudSupportData:
plan_data: PlanData
sponsorship_data: SponsorshipData
+ user_data: UserData
def get_stripe_customer_url(stripe_id: str) -> str:
@@ -129,6 +138,15 @@ def get_realm_support_url(realm: Realm) -> str:
return support_url
+def get_realm_user_data(realm: Realm) -> UserData:
+ non_guests = get_non_guest_user_count(realm)
+ guests = get_guest_user_count(realm)
+ return UserData(
+ guest_user_count=guests,
+ non_guest_user_count=non_guests,
+ )
+
+
def get_customer_sponsorship_data(customer: Customer) -> SponsorshipData:
pending = customer.sponsorship_pending
licenses = customer.minimum_licenses
@@ -421,6 +439,7 @@ def get_data_for_remote_support_view(billing_session: BillingSession) -> RemoteS
def get_data_for_cloud_support_view(billing_session: BillingSession) -> CloudSupportData:
assert isinstance(billing_session, RealmBillingSession)
+ user_data = get_realm_user_data(billing_session.realm)
plan_data = get_plan_data_for_support_view(billing_session)
if plan_data.customer is not None:
sponsorship_data = get_customer_sponsorship_data(plan_data.customer)
@@ -430,4 +449,5 @@ def get_data_for_cloud_support_view(billing_session: BillingSession) -> CloudSup
return CloudSupportData(
plan_data=plan_data,
sponsorship_data=sponsorship_data,
+ user_data=user_data,
)
diff --git a/corporate/tests/test_support_views.py b/corporate/tests/test_support_views.py
index 373a20a3c0..1ddad1e3a2 100644
--- a/corporate/tests/test_support_views.py
+++ b/corporate/tests/test_support_views.py
@@ -747,7 +747,7 @@ class TestSupportEndpoint(ZulipTestCase):
def test_realm_support_view_queries(self) -> None:
iago = self.example_user("iago")
self.login_user(iago)
- with self.assert_database_query_count(16):
+ with self.assert_database_query_count(18):
result = self.client_get("/activity/support", {"q": "zulip"}, subdomain="zulip")
self.assertEqual(result.status_code, 200)
diff --git a/corporate/views/support.py b/corporate/views/support.py
index 60b05f04b7..cb13c229b9 100644
--- a/corporate/views/support.py
+++ b/corporate/views/support.py
@@ -344,6 +344,12 @@ VALID_BILLING_MODALITY_VALUES = Literal[
"charge_automatically",
]
+SHARED_SUPPORT_CONTEXT = {
+ "get_org_type_display_name": get_org_type_display_name,
+ "get_plan_type_name": get_plan_type_string,
+ "dollar_amount": cents_to_dollar_string,
+}
+
@require_server_admin
@typed_endpoint
@@ -368,7 +374,7 @@ def support(
org_type: Json[NonNegativeInt] | None = None,
max_invites: Json[NonNegativeInt] | None = None,
) -> HttpResponse:
- context: dict[str, Any] = {}
+ context: dict[str, Any] = {**SHARED_SUPPORT_CONTEXT}
if "success_message" in request.session:
context["success_message"] = request.session["success_message"]
@@ -602,7 +608,6 @@ def support(
context["get_realm_owner_emails_as_string"] = get_realm_owner_emails_as_string
context["get_realm_admin_emails_as_string"] = get_realm_admin_emails_as_string
- context["dollar_amount"] = cents_to_dollar_string
context["realm_icon_url"] = realm_icon_url
context["Confirmation"] = Confirmation
context["REALM_PLAN_TYPES"] = get_realm_plan_type_options()
@@ -691,7 +696,7 @@ def remote_servers_support(
]
| None = None,
) -> HttpResponse:
- context: dict[str, Any] = {}
+ context: dict[str, Any] = {**SHARED_SUPPORT_CONTEXT}
if "success_message" in request.session:
context["success_message"] = request.session["success_message"]
@@ -876,10 +881,7 @@ def remote_servers_support(
context["remote_server_to_max_monthly_messages"] = remote_server_to_max_monthly_messages
context["remote_realms"] = remote_realms
context["remote_realms_support_data"] = realm_support_data
- context["get_plan_type_name"] = get_plan_type_string
- context["get_org_type_display_name"] = get_org_type_display_name
context["format_optional_datetime"] = format_optional_datetime
- context["dollar_amount"] = cents_to_dollar_string
context["server_analytics_link"] = remote_installation_stats_link
context["REMOTE_PLAN_TIERS"] = get_remote_plan_tier_options()
context["get_remote_server_billing_user_emails"] = (
diff --git a/templates/corporate/support/basic_realm_data.html b/templates/corporate/support/basic_realm_data.html
new file mode 100644
index 0000000000..07d65be5b2
--- /dev/null
+++ b/templates/corporate/support/basic_realm_data.html
@@ -0,0 +1,4 @@
+Organization type: {{ get_org_type_display_name(realm.org_type) }}
+Plan type: {{ get_plan_type_name(realm.plan_type) }}
+Non-guest user count: {{ user_data.non_guest_user_count }}
+Guest user count: {{ user_data.guest_user_count }}
diff --git a/templates/corporate/support/realm_details.html b/templates/corporate/support/realm_details.html
index 5f4a848ab4..7604e092b6 100644
--- a/templates/corporate/support/realm_details.html
+++ b/templates/corporate/support/realm_details.html
@@ -33,9 +33,17 @@
+
{% else %}
First human user:
+
{% endif %}
+
+ {% with %}
+ {% set realm = realm %}
+ {% set user_data = realm_support_data[realm.id].user_data %}
+ {% include 'corporate/support/basic_realm_data.html' %}
+ {% endwith %}