diff --git a/corporate/lib/registration.py b/corporate/lib/registration.py index 248770e981..c5ba390de8 100644 --- a/corporate/lib/registration.py +++ b/corporate/lib/registration.py @@ -60,13 +60,13 @@ def send_user_unable_to_signup_group_direct_message_to_admins( realm: Realm, user_email: str ) -> None: message = _( - "A new member ({email}) was unable to join your organization because all Zulip licenses " - "are in use. Please [increase the number of licenses]({billing_page_link}) or " - "[deactivate inactive users]({deactivate_user_help_page_link}) to allow new members to join." + "A new user ({email}) was unable to join because your organization does not have enough " + "Zulip licenses. To allow new users to join, make sure that the [number of licenses for " + "the current and next billing period]({billing_page_link}) is greater than the current " + "number of users." ).format( email=user_email, billing_page_link="/billing/", - deactivate_user_help_page_link="/help/deactivate-or-reactivate-a-user", ) send_group_direct_message_to_admins( @@ -77,9 +77,12 @@ def send_user_unable_to_signup_group_direct_message_to_admins( def check_spare_licenses_available( realm: Realm, plan: CustomerPlan, extra_non_guests_count: int = 0, extra_guests_count: int = 0 ) -> None: - if plan.licenses() < get_seat_count( + seat_count = get_seat_count( realm, extra_non_guests_count=extra_non_guests_count, extra_guests_count=extra_guests_count - ): + ) + current_licenses = plan.licenses() + renewal_licenses = plan.licenses_at_next_renewal() + if current_licenses < seat_count or (renewal_licenses and renewal_licenses < seat_count): raise LicenseLimitError @@ -105,7 +108,6 @@ def check_spare_licenses_available_for_registering_new_user( def check_spare_licenses_available_for_inviting_new_users( realm: Realm, extra_non_guests_count: int = 0, extra_guests_count: int = 0 ) -> None: - num_invites = extra_non_guests_count + extra_guests_count plan = get_plan_if_manual_license_management_enforced(realm) if plan is None: return @@ -113,10 +115,7 @@ def check_spare_licenses_available_for_inviting_new_users( try: check_spare_licenses_available(realm, plan, extra_non_guests_count, extra_guests_count) except LicenseLimitError: - if num_invites == 1: - message = _("All Zulip licenses for this organization are currently in use.") - else: - message = _( - "Your organization does not have enough unused Zulip licenses to invite {num_invites} users." - ).format(num_invites=num_invites) + message = _( + "Your organization does not have enough Zulip licenses. Invitations were not sent." + ) raise InvitationError(message, [], sent_invitations=False, license_limit_reached=True) diff --git a/zerver/tests/test_invite.py b/zerver/tests/test_invite.py index 24610f0863..0071250cda 100644 --- a/zerver/tests/test_invite.py +++ b/zerver/tests/test_invite.py @@ -535,19 +535,24 @@ class InviteUserTest(InviteUserBase): result = self.invite(self.nonreg_email("alice"), ["Denmark"]) self.assert_json_success(result) - ledger.licenses_at_next_renewal = 5 + ledger.licenses_at_next_renewal = get_latest_seat_count(user.realm) ledger.save(update_fields=["licenses_at_next_renewal"]) with self.settings(BILLING_ENABLED=True): result = self.invite(self.nonreg_email("bob"), ["Denmark"]) - self.assert_json_success(result) + self.assert_json_error_contains( + result, + "Your organization does not have enough Zulip licenses. Invitations were not sent.", + ) + ledger.licenses_at_next_renewal = 50 ledger.licenses = get_latest_seat_count(user.realm) + 1 - ledger.save(update_fields=["licenses"]) + ledger.save(update_fields=["licenses", "licenses_at_next_renewal"]) with self.settings(BILLING_ENABLED=True): invitee_emails = self.nonreg_email("bob") + "," + self.nonreg_email("alice") result = self.invite(invitee_emails, ["Denmark"]) self.assert_json_error_contains( - result, "Your organization does not have enough unused Zulip licenses to invite 2 users" + result, + "Your organization does not have enough Zulip licenses. Invitations were not sent.", ) ledger.licenses = get_latest_seat_count(user.realm) @@ -555,7 +560,8 @@ class InviteUserTest(InviteUserBase): with self.settings(BILLING_ENABLED=True): result = self.invite(self.nonreg_email("bob"), ["Denmark"]) self.assert_json_error_contains( - result, "All Zulip licenses for this organization are currently in use" + result, + "Your organization does not have enough Zulip licenses. Invitations were not sent.", ) with self.settings(BILLING_ENABLED=True): diff --git a/zerver/tests/test_signup.py b/zerver/tests/test_signup.py index 01dd7f92e0..694fa1f226 100644 --- a/zerver/tests/test_signup.py +++ b/zerver/tests/test_signup.py @@ -3026,7 +3026,7 @@ class UserSignUpTest(ZulipTestCase): last_message = Message.objects.last() assert last_message is not None self.assertIn( - f"A new member ({self.nonreg_email('test')}) was unable to join your organization because all Zulip", + f"A new user ({self.nonreg_email('test')}) was unable to join because your organization", last_message.content, ) self.assertEqual( @@ -3044,7 +3044,27 @@ class UserSignUpTest(ZulipTestCase): ) ledger.licenses = 50 - ledger.save(update_fields=["licenses"]) + ledger.licenses_at_next_renewal = 5 + ledger.save(update_fields=["licenses", "licenses_at_next_renewal"]) + with self.settings(BILLING_ENABLED=True): + form = HomepageForm({"email": self.nonreg_email("test")}, realm=realm) + self.assertIn( + "New members cannot join this organization because all Zulip licenses", + form.errors["email"][0], + ) + last_message = Message.objects.last() + assert last_message is not None + self.assertIn( + f"A new user ({self.nonreg_email('test')}) was unable to join because your organization", + last_message.content, + ) + self.assertEqual( + set(get_direct_message_group_user_ids(last_message.recipient)), + expected_group_direct_message_user_ids, + ) + + ledger.licenses_at_next_renewal = 50 + ledger.save(update_fields=["licenses_at_next_renewal"]) with self.settings(BILLING_ENABLED=True): form = HomepageForm({"email": self.nonreg_email("test")}, realm=realm) self.assertEqual(form.errors, {})