mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	models: Add plan_type to Realm.
This commit is contained in:
		@@ -3018,6 +3018,15 @@ def do_change_icon_source(realm: Realm, icon_source: str, log: bool=True) -> Non
 | 
			
		||||
                              icon_url=realm_icon_url(realm))),
 | 
			
		||||
               active_user_ids(realm.id))
 | 
			
		||||
 | 
			
		||||
def do_change_plan_type(user: UserProfile, plan_type: int) -> None:
 | 
			
		||||
    realm = user.realm
 | 
			
		||||
    old_value = realm.plan_type
 | 
			
		||||
    realm.plan_type = plan_type
 | 
			
		||||
    realm.save(update_fields=['plan_type'])
 | 
			
		||||
    RealmAuditLog.objects.create(event_type=RealmAuditLog.REALM_PLAN_TYPE_CHANGED,
 | 
			
		||||
                                 realm=realm, acting_user=user, event_time=timezone_now(),
 | 
			
		||||
                                 extra_data={'old_value': old_value, 'new_value': plan_type})
 | 
			
		||||
 | 
			
		||||
def do_change_default_sending_stream(user_profile: UserProfile, stream: Optional[Stream],
 | 
			
		||||
                                     log: bool=True) -> None:
 | 
			
		||||
    user_profile.default_sending_stream = stream
 | 
			
		||||
@@ -3194,6 +3203,8 @@ def do_create_realm(string_id: str, name: str,
 | 
			
		||||
    kwargs = {}  # type: Dict[str, Any]
 | 
			
		||||
    if emails_restricted_to_domains is not None:
 | 
			
		||||
        kwargs['emails_restricted_to_domains'] = emails_restricted_to_domains
 | 
			
		||||
    if settings.BILLING_ENABLED:
 | 
			
		||||
        kwargs['plan_type'] = Realm.LIMITED
 | 
			
		||||
    realm = Realm(string_id=string_id, name=name, **kwargs)
 | 
			
		||||
    realm.save()
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										22
									
								
								zerver/migrations/0185_realm_plan_type.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								zerver/migrations/0185_realm_plan_type.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
# Generated by Django 1.11.14 on 2018-08-10 21:36
 | 
			
		||||
from __future__ import unicode_literals
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
import zerver.models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('zerver', '0184_rename_custom_field_types'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name='realm',
 | 
			
		||||
            name='plan_type',
 | 
			
		||||
            # Realm.SELF_HOSTED
 | 
			
		||||
            field=models.PositiveSmallIntegerField(default=1),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@@ -223,6 +223,15 @@ class Realm(models.Model):
 | 
			
		||||
    COMMUNITY = 2
 | 
			
		||||
    org_type = models.PositiveSmallIntegerField(default=CORPORATE)  # type: int
 | 
			
		||||
 | 
			
		||||
    # plan_type controls various features around resource/feature
 | 
			
		||||
    # limitations for a Zulip organization on multi-tenant servers
 | 
			
		||||
    # like zulipchat.com.
 | 
			
		||||
    SELF_HOSTED = 1
 | 
			
		||||
    LIMITED = 2
 | 
			
		||||
    PREMIUM = 3
 | 
			
		||||
    PREMIUM_FREE = 4
 | 
			
		||||
    plan_type = models.PositiveSmallIntegerField(default=SELF_HOSTED)  # type: int
 | 
			
		||||
 | 
			
		||||
    # This value is also being used in static/js/settings_bots.bot_creation_policy_values.
 | 
			
		||||
    # On updating it here, update it there as well.
 | 
			
		||||
    BOT_CREATION_EVERYONE = 1
 | 
			
		||||
@@ -2189,6 +2198,7 @@ class RealmAuditLog(models.Model):
 | 
			
		||||
 | 
			
		||||
    REALM_DEACTIVATED = 'realm_deactivated'
 | 
			
		||||
    REALM_REACTIVATED = 'realm_reactivated'
 | 
			
		||||
    REALM_PLAN_TYPE_CHANGED = 'realm_plan_type_changed'
 | 
			
		||||
 | 
			
		||||
    SUBSCRIPTION_CREATED = 'subscription_created'
 | 
			
		||||
    SUBSCRIPTION_ACTIVATED = 'subscription_activated'
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@ from zerver.lib.actions import (
 | 
			
		||||
    do_set_realm_property,
 | 
			
		||||
    do_deactivate_realm,
 | 
			
		||||
    do_deactivate_stream,
 | 
			
		||||
    do_create_realm,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
from zerver.lib.send_email import send_future_email
 | 
			
		||||
@@ -334,6 +335,12 @@ class RealmTest(ZulipTestCase):
 | 
			
		||||
        self.assert_json_success(result)
 | 
			
		||||
        self.assertEqual(get_realm('zulip').video_chat_provider, "Jitsi")
 | 
			
		||||
 | 
			
		||||
    def test_initial_plan_type(self) -> None:
 | 
			
		||||
        with self.settings(BILLING_ENABLED=True):
 | 
			
		||||
            self.assertEqual(Realm.LIMITED, do_create_realm('hosted', 'hosted').plan_type)
 | 
			
		||||
        with self.settings(BILLING_ENABLED=False):
 | 
			
		||||
            self.assertEqual(Realm.SELF_HOSTED, do_create_realm('onpremise', 'onpremise').plan_type)
 | 
			
		||||
 | 
			
		||||
class RealmAPITest(ZulipTestCase):
 | 
			
		||||
 | 
			
		||||
    def setUp(self) -> None:
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,7 @@ from zerver.lib.exceptions import JsonableError
 | 
			
		||||
from zerver.lib.logging_util import log_to_file
 | 
			
		||||
from zerver.lib.timestamp import datetime_to_timestamp, timestamp_to_datetime
 | 
			
		||||
from zerver.lib.utils import generate_random_token
 | 
			
		||||
from zerver.lib.actions import do_change_plan_type
 | 
			
		||||
from zerver.models import Realm, UserProfile, RealmAuditLog
 | 
			
		||||
from zilencer.models import Customer, Plan, BillingProcessor
 | 
			
		||||
from zproject.settings import get_secret
 | 
			
		||||
@@ -228,6 +229,7 @@ def process_initial_upgrade(user: UserProfile, plan: Plan, seat_count: int, stri
 | 
			
		||||
        # TODO: billing address details are passed to us in the request;
 | 
			
		||||
        # use that to calculate taxes.
 | 
			
		||||
        tax_percent=0)
 | 
			
		||||
    do_change_plan_type(user, Realm.PREMIUM)
 | 
			
		||||
 | 
			
		||||
## Process RealmAuditLog
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -50,6 +50,12 @@ def mock_customer_with_cancel_at_period_end_subscription(*args: Any, **kwargs: A
 | 
			
		||||
def mock_upcoming_invoice(*args: Any, **kwargs: Any) -> stripe.Invoice:
 | 
			
		||||
    return stripe.util.convert_to_stripe_object(fixture_data["upcoming_invoice"])
 | 
			
		||||
 | 
			
		||||
# A Kandra is a fictional character that can become anything. Used as a
 | 
			
		||||
# wildcard when testing for equality.
 | 
			
		||||
class Kandra(object):
 | 
			
		||||
    def __eq__(self, other: Any) -> bool:
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
class StripeTest(ZulipTestCase):
 | 
			
		||||
    def setUp(self) -> None:
 | 
			
		||||
        self.token = 'token'
 | 
			
		||||
@@ -103,6 +109,7 @@ class StripeTest(ZulipTestCase):
 | 
			
		||||
        response = self.client_get("/upgrade/")
 | 
			
		||||
        self.assert_in_success_response(['We can also bill by invoice'], response)
 | 
			
		||||
        self.assertFalse(user.realm.has_seat_based_plan)
 | 
			
		||||
        self.assertNotEqual(user.realm.plan_type, Realm.PREMIUM)
 | 
			
		||||
 | 
			
		||||
        # Click "Make payment" in Stripe Checkout
 | 
			
		||||
        self.client_post("/upgrade/", {
 | 
			
		||||
@@ -135,10 +142,12 @@ class StripeTest(ZulipTestCase):
 | 
			
		||||
            (RealmAuditLog.STRIPE_CUSTOMER_CREATED, timestamp_to_datetime(self.customer_created)),
 | 
			
		||||
            (RealmAuditLog.STRIPE_CARD_ADDED, timestamp_to_datetime(self.customer_created)),
 | 
			
		||||
            (RealmAuditLog.STRIPE_PLAN_CHANGED, timestamp_to_datetime(self.subscription_created)),
 | 
			
		||||
            (RealmAuditLog.REALM_PLAN_TYPE_CHANGED, Kandra()),
 | 
			
		||||
        ])
 | 
			
		||||
        # Check that we correctly updated Realm
 | 
			
		||||
        realm = get_realm("zulip")
 | 
			
		||||
        self.assertTrue(realm.has_seat_based_plan)
 | 
			
		||||
        self.assertEqual(realm.plan_type, Realm.PREMIUM)
 | 
			
		||||
        # Check that we can no longer access /upgrade
 | 
			
		||||
        response = self.client_get("/upgrade/")
 | 
			
		||||
        self.assertEqual(response.status_code, 302)
 | 
			
		||||
@@ -202,12 +211,13 @@ class StripeTest(ZulipTestCase):
 | 
			
		||||
        # correctly handled the requires_billing_update field
 | 
			
		||||
        audit_log_entries = list(RealmAuditLog.objects.order_by('-id')
 | 
			
		||||
                                 .values_list('event_type', 'event_time',
 | 
			
		||||
                                              'requires_billing_update')[:4])[::-1]
 | 
			
		||||
                                              'requires_billing_update')[:5])[::-1]
 | 
			
		||||
        self.assertEqual(audit_log_entries, [
 | 
			
		||||
            (RealmAuditLog.STRIPE_CUSTOMER_CREATED, timestamp_to_datetime(self.customer_created), False),
 | 
			
		||||
            (RealmAuditLog.STRIPE_CARD_ADDED, timestamp_to_datetime(self.customer_created), False),
 | 
			
		||||
            (RealmAuditLog.STRIPE_PLAN_CHANGED, timestamp_to_datetime(self.subscription_created), False),
 | 
			
		||||
            (RealmAuditLog.STRIPE_PLAN_QUANTITY_RESET, timestamp_to_datetime(self.subscription_created), True),
 | 
			
		||||
            (RealmAuditLog.REALM_PLAN_TYPE_CHANGED, Kandra(), False),
 | 
			
		||||
        ])
 | 
			
		||||
        self.assertEqual(ujson.loads(RealmAuditLog.objects.filter(
 | 
			
		||||
            event_type=RealmAuditLog.STRIPE_PLAN_QUANTITY_RESET).values_list('extra_data', flat=True).first()),
 | 
			
		||||
@@ -261,7 +271,8 @@ class StripeTest(ZulipTestCase):
 | 
			
		||||
        self.assertEqual(audit_log_entries, [RealmAuditLog.STRIPE_CUSTOMER_CREATED,
 | 
			
		||||
                                             RealmAuditLog.STRIPE_CARD_ADDED,
 | 
			
		||||
                                             RealmAuditLog.STRIPE_CARD_ADDED,
 | 
			
		||||
                                             RealmAuditLog.STRIPE_PLAN_CHANGED])
 | 
			
		||||
                                             RealmAuditLog.STRIPE_PLAN_CHANGED,
 | 
			
		||||
                                             RealmAuditLog.REALM_PLAN_TYPE_CHANGED])
 | 
			
		||||
        # Check that we correctly updated Realm
 | 
			
		||||
        realm = get_realm("zulip")
 | 
			
		||||
        self.assertTrue(realm.has_seat_based_plan)
 | 
			
		||||
 
 | 
			
		||||
@@ -123,3 +123,5 @@ if FAKE_LDAP_MODE:
 | 
			
		||||
THUMBOR_URL = 'http://127.0.0.1:9995'
 | 
			
		||||
 | 
			
		||||
SEARCH_PILLS_ENABLED = os.getenv('SEARCH_PILLS_ENABLED', False)
 | 
			
		||||
 | 
			
		||||
BILLING_ENABLED = True
 | 
			
		||||
 
 | 
			
		||||
@@ -437,6 +437,10 @@ DEFAULT_SETTINGS.update({
 | 
			
		||||
    # DEFAULT_SETTINGS, since it likely isn't usefully user-configurable.
 | 
			
		||||
    'OFFLINE_THRESHOLD_SECS': 5 * 60,
 | 
			
		||||
 | 
			
		||||
    # Enables billing pages and plan-based feature gates. If False, all features
 | 
			
		||||
    # are available to all realms.
 | 
			
		||||
    'BILLING_ENABLED': False,
 | 
			
		||||
 | 
			
		||||
    # Controls whether we run the worker that syncs billing-related updates
 | 
			
		||||
    # into Stripe. Should be True on at most one machine.
 | 
			
		||||
    'BILLING_PROCESSOR_ENABLED': False,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user