From 8f71e4b83f91906b08d62bdc208bd42116d9bf91 Mon Sep 17 00:00:00 2001 From: RulaKhaled Date: Thu, 30 Jan 2025 14:38:00 +0100 Subject: [PATCH 1/7] Add new developer plan --- shared/billing/__init__.py | 1 + ...065_alter_account_plan_alter_owner_plan.py | 23 +++ shared/django_apps/codecov_auth/models.py | 4 +- shared/plan/constants.py | 48 +++++- shared/plan/service.py | 6 +- tests/unit/billing/test_enum_definitions.py | 4 +- .../codecov_auth/test_codecov_auth_models.py | 24 +-- tests/unit/plan/test_plan.py | 158 +++++++++--------- tests/unit/test_router.py | 3 + 9 files changed, 168 insertions(+), 103 deletions(-) create mode 100644 shared/django_apps/codecov_auth/migrations/0065_alter_account_plan_alter_owner_plan.py diff --git a/shared/billing/__init__.py b/shared/billing/__init__.py index 3010b6d02..cd9728d15 100644 --- a/shared/billing/__init__.py +++ b/shared/billing/__init__.py @@ -23,6 +23,7 @@ class BillingPlan(Enum): users_yearly = PlanName.CODECOV_PRO_YEARLY_LEGACY.value enterprise_cloud_monthly = PlanName.ENTERPRISE_CLOUD_MONTHLY.value enterprise_cloud_yearly = PlanName.ENTERPRISE_CLOUD_YEARLY.value + users_developer = PlanName.USERS_DEVELOPER.value def __init__(self, db_name): self.db_name = db_name diff --git a/shared/django_apps/codecov_auth/migrations/0065_alter_account_plan_alter_owner_plan.py b/shared/django_apps/codecov_auth/migrations/0065_alter_account_plan_alter_owner_plan.py new file mode 100644 index 000000000..febe170bd --- /dev/null +++ b/shared/django_apps/codecov_auth/migrations/0065_alter_account_plan_alter_owner_plan.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.16 on 2025-01-30 13:24 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('codecov_auth', '0064_plan_stripe_id'), + ] + + operations = [ + migrations.AlterField( + model_name='account', + name='plan', + field=models.CharField(choices=[('users-basic', 'BASIC_PLAN_NAME'), ('users-trial', 'TRIAL_PLAN_NAME'), ('users-pr-inappm', 'CODECOV_PRO_MONTHLY'), ('users-pr-inappy', 'CODECOV_PRO_YEARLY'), ('users-sentrym', 'SENTRY_MONTHLY'), ('users-sentryy', 'SENTRY_YEARLY'), ('users-teamm', 'TEAM_MONTHLY'), ('users-teamy', 'TEAM_YEARLY'), ('users', 'GHM_PLAN_NAME'), ('users-free', 'FREE_PLAN_NAME'), ('users-inappm', 'CODECOV_PRO_MONTHLY_LEGACY'), ('users-inappy', 'CODECOV_PRO_YEARLY_LEGACY'), ('users-enterprisem', 'ENTERPRISE_CLOUD_MONTHLY'), ('users-enterprisey', 'ENTERPRISE_CLOUD_YEARLY'), ('users-developer', 'USERS_DEVELOPER')], default='users-developer', max_length=50), + ), + migrations.AlterField( + model_name='owner', + name='plan', + field=models.TextField(blank=True, default='users-developer', null=True), + ), + ] diff --git a/shared/django_apps/codecov_auth/models.py b/shared/django_apps/codecov_auth/models.py index 393fc6238..3a6b74360 100644 --- a/shared/django_apps/codecov_auth/models.py +++ b/shared/django_apps/codecov_auth/models.py @@ -146,7 +146,7 @@ class Account(BaseModel): max_length=50, choices=PlanName.choices(), null=False, - default=PlanName.BASIC_PLAN_NAME.value, + default=PlanName.USERS_DEVELOPER.value, ) plan_seat_count = models.SmallIntegerField(default=1, null=False, blank=True) free_seat_count = models.SmallIntegerField(default=0, null=False, blank=True) @@ -317,7 +317,7 @@ class Meta: cache = models.JSONField(null=True) # Really an ENUM in db plan = models.TextField( - null=True, default=PlanName.BASIC_PLAN_NAME.value, blank=True + null=True, default=PlanName.USERS_DEVELOPER.value, blank=True ) plan_provider = models.TextField( null=True, choices=PlanProviders.choices, blank=True diff --git a/shared/plan/constants.py b/shared/plan/constants.py index 6823ef850..e27343c62 100644 --- a/shared/plan/constants.py +++ b/shared/plan/constants.py @@ -6,7 +6,7 @@ class MonthlyUploadLimits(enum.Enum): CODECOV_BASIC_PLAN = 250 CODECOV_TEAM_PLAN = 2500 - + CODECOV_DEVELOPER_PLAN = 250 class TrialDaysAmount(enum.Enum): CODECOV_SENTRY = 14 @@ -21,6 +21,7 @@ class PlanMarketingName(enum.Enum): BASIC = "Developer" TRIAL = "Developer" TEAM = "Team" + DEVELOPER = "Developer" class PlanName(enum.Enum): @@ -39,6 +40,7 @@ class PlanName(enum.Enum): CODECOV_PRO_YEARLY_LEGACY = "users-inappy" ENTERPRISE_CLOUD_MONTHLY = "users-enterprisem" ENTERPRISE_CLOUD_YEARLY = "users-enterprisey" + USERS_DEVELOPER = "users-developer" @classmethod def choices(cls): @@ -73,6 +75,26 @@ class TierName(enum.Enum): TEAM = "team" PRO = "pro" ENTERPRISE = "enterprise" + SENTRY = "sentry" + TRIAL = "trial" + + +def convert_to_DTO(plan) -> dict: + return { + "marketing_name": plan.marketing_name, + "value": plan.name, + "billing_rate": plan.billing_rate, + "base_unit_price": plan.base_unit_price, + "benefits": plan.benefits, + "tier_name": plan.tier.tier_name, + "monthly_uploads_limit": plan.monthly_uploads_limit, + "is_free_plan": not plan.paid_plan, + "is_pro_plan": plan.tier.tier_name == TierName.PRO.value, + "is_team_plan": plan.tier.tier_name == TierName.TEAM.value, + "is_enterprise_plan": plan.tier.tier_name == TierName.ENTERPRISE.value, + "is_trial_plan": plan.tier.tier_name == TierName.TRIAL.value, + "is_sentry_plan": plan.tier.tier_name == TierName.SENTRY.value, + } @dataclass(repr=False) @@ -99,7 +121,6 @@ def convert_to_DTO(self) -> dict: "benefits": self.benefits, "tier_name": self.tier_name, "monthly_uploads_limit": self.monthly_uploads_limit, - "trial_days": self.trial_days, "is_free_plan": self.tier_name == TierName.BASIC.value, "is_pro_plan": self.tier_name == TierName.PRO.value, "is_team_plan": self.tier_name == TierName.TEAM.value, @@ -189,7 +210,7 @@ def convert_to_DTO(self) -> dict: "Unlimited private repositories", "Priority Support", ], - tier_name=TierName.PRO.value, + tier_name=TierName.SENTRY.value, trial_days=TrialDaysAmount.CODECOV_SENTRY.value, monthly_uploads_limit=None, ), @@ -205,7 +226,7 @@ def convert_to_DTO(self) -> dict: "Unlimited private repositories", "Priority Support", ], - tier_name=TierName.PRO.value, + tier_name=TierName.SENTRY.value, trial_days=TrialDaysAmount.CODECOV_SENTRY.value, monthly_uploads_limit=None, ), @@ -292,9 +313,25 @@ def convert_to_DTO(self) -> dict: monthly_uploads_limit=None, ) +DEVELOPER_PLAN = PlanData( + marketing_name=PlanMarketingName.DEVELOPER.value, + value=PlanName.USERS_DEVELOPER.value, + billing_rate=None, + base_unit_price=PlanPrice.CODECOV_FREE.value, + benefits=[ + "Up to 1 user", + "Unlimited public repositories", + "Unlimited private repositories", + ], + tier_name=TierName.TEAM.value, + trial_days=None, + monthly_uploads_limit=None, +) + FREE_PLAN_REPRESENTATIONS = { PlanName.FREE_PLAN_NAME.value: FREE_PLAN, PlanName.BASIC_PLAN_NAME.value: BASIC_PLAN, + PlanName.USERS_DEVELOPER.value: DEVELOPER_PLAN, } TEAM_PLAN_REPRESENTATIONS = { @@ -342,7 +379,7 @@ def convert_to_DTO(self) -> dict: "Unlimited private repositories", "Priority Support", ], - tier_name=TierName.PRO.value, + tier_name=TierName.TRIAL.value, trial_days=None, monthly_uploads_limit=None, ), @@ -370,6 +407,7 @@ def convert_to_DTO(self) -> dict: } PLANS_THAT_CAN_TRIAL = [ + PlanName.USERS_DEVELOPER.value, PlanName.FREE_PLAN_NAME.value, PlanName.BASIC_PLAN_NAME.value, PlanName.CODECOV_PRO_MONTHLY.value, diff --git a/shared/plan/service.py b/shared/plan/service.py index cf0b8b23b..862a6318b 100644 --- a/shared/plan/service.py +++ b/shared/plan/service.py @@ -7,7 +7,7 @@ from shared.django_apps.codecov.commands.exceptions import ValidationError from shared.django_apps.codecov_auth.models import Owner, Service from shared.plan.constants import ( - BASIC_PLAN, + DEVELOPER_PLAN, ENTERPRISE_CLOUD_USER_PLAN_REPRESENTATIONS, FREE_PLAN, FREE_PLAN_REPRESENTATIONS, @@ -77,7 +77,7 @@ def current_org(self) -> Owner: def set_default_plan_data(self) -> None: """Sets the organization to the default basic plan.""" log.info(f"Setting plan to users-basic for owner {self.current_org.ownerid}") - self.current_org.plan = PlanName.BASIC_PLAN_NAME.value + self.current_org.plan = PlanName.USERS_DEVELOPER.value self.current_org.plan_activated_users = None self.current_org.plan_user_count = 1 self.current_org.stripe_subscription_id = None @@ -165,7 +165,7 @@ def tier_name(self) -> str: def available_plans(self, owner: Owner) -> List[PlanData]: """Returns the available plans for the owner and organization.""" - available_plans = [BASIC_PLAN] + available_plans = [DEVELOPER_PLAN] if self.plan_name == FREE_PLAN.value: available_plans.append(FREE_PLAN) diff --git a/tests/unit/billing/test_enum_definitions.py b/tests/unit/billing/test_enum_definitions.py index 8893d012a..004188870 100644 --- a/tests/unit/billing/test_enum_definitions.py +++ b/tests/unit/billing/test_enum_definitions.py @@ -72,7 +72,7 @@ def test_billing_enums(): assert BillingPlan.enterprise_cloud_monthly.db_name == "users-enterprisem" assert BillingPlan.team_monthly.db_name == "users-teamm" assert BillingPlan.team_yearly.db_name == "users-teamy" - + assert BillingPlan.users_developer.db_name == "users-developer" def test_get_from_string(): assert BillingPlan.from_str("users-inappm") == BillingPlan.users_monthly @@ -90,7 +90,7 @@ def test_get_from_string(): ) assert BillingPlan.from_str("users-teamm") == BillingPlan.team_monthly assert BillingPlan.from_str("users-teamy") == BillingPlan.team_yearly - + assert BillingPlan.from_str("users-developer") == BillingPlan.users_developer def test_is_enterprise_cloud_plan(): assert not is_enterprise_cloud_plan(BillingPlan.pr_monthly) diff --git a/tests/unit/django_apps/codecov_auth/test_codecov_auth_models.py b/tests/unit/django_apps/codecov_auth/test_codecov_auth_models.py index b4f822c44..ee44648b0 100644 --- a/tests/unit/django_apps/codecov_auth/test_codecov_auth_models.py +++ b/tests/unit/django_apps/codecov_auth/test_codecov_auth_models.py @@ -36,7 +36,7 @@ ) from shared.django_apps.core.tests.factories import RepositoryFactory from shared.plan.constants import ( - BASIC_PLAN, + DEVELOPER_PLAN, ENTERPRISE_CLOUD_USER_PLAN_REPRESENTATIONS, PlanName, ) @@ -378,11 +378,11 @@ def test_can_activate_user_cannot_activate_account(self): def test_fields_that_account_overrides(self): to_activate = OwnerFactory() - self.owner.plan = PlanName.BASIC_PLAN_NAME.value + self.owner.plan = PlanName.USERS_DEVELOPER.value self.owner.plan_user_count = 1 self.owner.save() self.assertTrue(self.owner.can_activate_user(to_activate)) - org_pretty_plan = asdict(BASIC_PLAN) + org_pretty_plan = asdict(DEVELOPER_PLAN) org_pretty_plan.update({"quantity": 1}) self.assertEqual(self.owner.pretty_plan, org_pretty_plan) @@ -524,8 +524,8 @@ def test_has_yaml(self): class TestOrganizationLevelTokenModel(TransactionTestCase): - def test_can_save_org_token_for_org_basic_plan(self): - owner = OwnerFactory(plan="users-basic") + def test_can_save_org_token_for_org_developer_plan(self): + owner = OwnerFactory(plan="users-developer") owner.save() token = OrganizationLevelToken(owner=owner) token.save() @@ -543,7 +543,7 @@ def test_token_is_deleted_when_changing_user_plan( owner.save() org_token.save() assert OrganizationLevelToken.objects.filter(owner=owner).count() == 1 - owner.plan = "users-basic" + owner.plan = "users-developer" owner.save() assert OrganizationLevelToken.objects.filter(owner=owner).count() == 0 @@ -756,7 +756,7 @@ def test_account_with_users(self): self.assertEqual(account.activated_student_count, 0) self.assertEqual(account.total_seat_count, 1) self.assertEqual(account.available_seat_count, 0) - pretty_plan = asdict(BASIC_PLAN) + pretty_plan = asdict(DEVELOPER_PLAN) pretty_plan.update({"quantity": 1}) self.assertEqual(account.pretty_plan, pretty_plan) @@ -768,21 +768,21 @@ def test_create_account_for_enterprise_experience(self): user_for_owner_1 = UserFactory(email="hello@email.com", name="Luigi") owner_1 = OwnerFactory( username="codecov-1", - plan=PlanName.BASIC_PLAN_NAME.value, + plan=PlanName.USERS_DEVELOPER.value, plan_user_count=1, organizations=[], user_id=user_for_owner_1.id, # has user ) owner_2 = OwnerFactory( username="codecov-sentry", - plan=PlanName.BASIC_PLAN_NAME.value, + plan=PlanName.USERS_DEVELOPER.value, plan_user_count=1, organizations=[], user_id=None, # no user ) owner_3 = OwnerFactory( username="sentry-1", - plan=PlanName.BASIC_PLAN_NAME.value, + plan=PlanName.USERS_DEVELOPER.value, plan_user_count=1, organizations=[], user_id=None, # no user @@ -806,7 +806,7 @@ def test_create_account_for_enterprise_experience(self): username="codecov-org", stripe_customer_id=stripe_customer_id, stripe_subscription_id=stripe_subscription_id, - plan=PlanName.BASIC_PLAN_NAME.value, + plan=PlanName.USERS_DEVELOPER.value, plan_user_count=50, plan_activated_users=[owner_1.ownerid, owner_2.ownerid], free=10, @@ -926,7 +926,7 @@ def test_create_account_for_enterprise_experience(self): self.assertEqual(enterprise_account.activated_student_count, 0) self.assertEqual(enterprise_account.total_seat_count, 60) self.assertEqual(enterprise_account.available_seat_count, 57) - pretty_plan = asdict(BASIC_PLAN) + pretty_plan = asdict(DEVELOPER_PLAN) pretty_plan.update({"quantity": 50}) self.assertEqual(enterprise_account.pretty_plan, pretty_plan) diff --git a/tests/unit/plan/test_plan.py b/tests/unit/plan/test_plan.py index c1258f4eb..7421abe35 100644 --- a/tests/unit/plan/test_plan.py +++ b/tests/unit/plan/test_plan.py @@ -8,7 +8,7 @@ from shared.django_apps.codecov_auth.models import Service from shared.django_apps.codecov_auth.tests.factories import OwnerFactory from shared.plan.constants import ( - BASIC_PLAN, + DEVELOPER_PLAN, FREE_PLAN, FREE_PLAN_REPRESENTATIONS, PR_AUTHOR_PAID_USER_PLAN_REPRESENTATIONS, @@ -26,7 +26,7 @@ @freeze_time("2023-06-19") class PlanServiceTests(TestCase): def test_plan_service_trial_status_not_started(self): - current_org = OwnerFactory(plan=PlanName.BASIC_PLAN_NAME.value) + current_org = OwnerFactory(plan=PlanName.USERS_DEVELOPER.value) plan_service = PlanService(current_org=current_org) assert plan_service.trial_status == TrialStatus.NOT_STARTED.value @@ -35,7 +35,7 @@ def test_plan_service_trial_status_expired(self): trial_start_date = datetime.utcnow() trial_end_date_expired = trial_start_date - timedelta(days=1) current_org = OwnerFactory( - plan=PlanName.BASIC_PLAN_NAME.value, + plan=PlanName.USERS_DEVELOPER.value, trial_start_date=trial_start_date, trial_end_date=trial_end_date_expired, trial_status=TrialStatus.EXPIRED.value, @@ -62,7 +62,7 @@ def test_plan_service_expire_trial_when_upgrading_successful_if_trial_is_not_sta self, ): current_org_with_ongoing_trial = OwnerFactory( - plan=PlanName.BASIC_PLAN_NAME.value, + plan=PlanName.USERS_DEVELOPER.value, trial_start_date=None, trial_end_date=None, trial_status=TrialStatus.NOT_STARTED.value, @@ -80,7 +80,7 @@ def test_plan_service_expire_trial_when_upgrading_successful_if_trial_is_ongoing trial_start_date = datetime.utcnow() trial_end_date_ongoing = trial_start_date + timedelta(days=5) current_org_with_ongoing_trial = OwnerFactory( - plan=PlanName.BASIC_PLAN_NAME.value, + plan=PlanName.USERS_DEVELOPER.value, trial_start_date=trial_start_date, trial_end_date=trial_end_date_ongoing, trial_status=TrialStatus.ONGOING.value, @@ -99,7 +99,7 @@ def test_plan_service_expire_trial_users_pretrial_users_count_if_existing( trial_end_date_ongoing = trial_start_date + timedelta(days=5) pretrial_users_count = 5 current_org_with_ongoing_trial = OwnerFactory( - plan=PlanName.BASIC_PLAN_NAME.value, + plan=PlanName.USERS_DEVELOPER.value, trial_start_date=trial_start_date, trial_end_date=trial_end_date_ongoing, trial_status=TrialStatus.ONGOING.value, @@ -118,7 +118,7 @@ def test_plan_service_start_trial_errors_if_status_is_ongoing(self): days=TrialDaysAmount.CODECOV_SENTRY.value ) current_org = OwnerFactory( - plan=PlanName.BASIC_PLAN_NAME.value, + plan=PlanName.USERS_DEVELOPER.value, trial_start_date=trial_start_date, trial_end_date=trial_end_date, trial_status=TrialStatus.ONGOING.value, @@ -133,7 +133,7 @@ def test_plan_service_start_trial_errors_if_status_is_expired(self): trial_start_date = datetime.utcnow() trial_end_date = trial_start_date + timedelta(days=-1) current_org = OwnerFactory( - plan=PlanName.BASIC_PLAN_NAME.value, + plan=PlanName.USERS_DEVELOPER.value, trial_start_date=trial_start_date, trial_end_date=trial_end_date, trial_status=TrialStatus.EXPIRED.value, @@ -146,7 +146,7 @@ def test_plan_service_start_trial_errors_if_status_is_expired(self): def test_plan_service_start_trial_errors_if_status_is_cannot_trial(self): current_org = OwnerFactory( - plan=PlanName.BASIC_PLAN_NAME.value, + plan=PlanName.USERS_DEVELOPER.value, trial_start_date=None, trial_end_date=None, trial_status=TrialStatus.CANNOT_TRIAL.value, @@ -175,7 +175,7 @@ def test_plan_service_start_trial_succeeds_if_trial_has_not_started(self): trial_end_date = None plan_user_count = 5 current_org = OwnerFactory( - plan=PlanName.BASIC_PLAN_NAME.value, + plan=PlanName.USERS_DEVELOPER.value, trial_start_date=trial_start_date, trial_end_date=trial_end_date, trial_status=TrialStatus.NOT_STARTED.value, @@ -201,7 +201,7 @@ def test_plan_service_start_trial_manually(self): trial_end_date = None plan_user_count = 5 current_org = OwnerFactory( - plan=PlanName.BASIC_PLAN_NAME.value, + plan=PlanName.USERS_DEVELOPER.value, trial_start_date=trial_start_date, trial_end_date=trial_end_date, trial_status=TrialStatus.NOT_STARTED.value, @@ -237,32 +237,32 @@ def test_plan_service_start_trial_manually_already_on_paid_plan(self): current_owner=current_owner, end_date="2024-01-01 00:00:00" ) - def test_plan_service_returns_plan_data_for_non_trial_basic_plan(self): + def test_plan_service_returns_plan_data_for_non_trial_developer_plan(self): trial_start_date = None trial_end_date = None current_org = OwnerFactory( - plan=PlanName.BASIC_PLAN_NAME.value, + plan=PlanName.USERS_DEVELOPER.value, trial_start_date=trial_start_date, trial_end_date=trial_end_date, ) plan_service = PlanService(current_org=current_org) - basic_plan = FREE_PLAN_REPRESENTATIONS[PlanName.BASIC_PLAN_NAME.value] + developer_plan = FREE_PLAN_REPRESENTATIONS[PlanName.USERS_DEVELOPER.value] assert plan_service.current_org == current_org assert plan_service.trial_status == TrialStatus.NOT_STARTED.value - assert plan_service.marketing_name == basic_plan.marketing_name - assert plan_service.plan_name == basic_plan.value - assert plan_service.tier_name == basic_plan.tier_name - assert plan_service.billing_rate == basic_plan.billing_rate - assert plan_service.base_unit_price == basic_plan.base_unit_price - assert plan_service.benefits == basic_plan.benefits + assert plan_service.marketing_name == developer_plan.marketing_name + assert plan_service.plan_name == developer_plan.value + assert plan_service.tier_name == developer_plan.tier_name + assert plan_service.billing_rate == developer_plan.billing_rate + assert plan_service.base_unit_price == developer_plan.base_unit_price + assert plan_service.benefits == developer_plan.benefits assert ( - plan_service.monthly_uploads_limit == basic_plan.monthly_uploads_limit + plan_service.monthly_uploads_limit == developer_plan.monthly_uploads_limit ) # should be 250 assert ( plan_service.monthly_uploads_limit == 250 ) # should be 250 since not trialing - assert plan_service.trial_total_days == basic_plan.trial_days + assert plan_service.trial_total_days == developer_plan.trial_days def test_plan_service_returns_plan_data_for_trialing_user_trial_plan(self): trial_start_date = datetime.utcnow() @@ -301,7 +301,7 @@ def test_plan_service_sets_default_plan_data_values_correctly(self): plan_service = PlanService(current_org=current_org) plan_service.set_default_plan_data() - assert current_org.plan == PlanName.BASIC_PLAN_NAME.value + assert current_org.plan == PlanName.USERS_DEVELOPER.value assert current_org.plan_user_count == 1 assert current_org.plan_activated_users is None assert current_org.stripe_subscription_id is None @@ -349,13 +349,13 @@ def test_plan_service_gitlab_with_root_org(self): class AvailablePlansBeforeTrial(TestCase): """ - - users-basic, no trial -> users-pr-inappm/y, users-basic - - users-free, no trial -> users-pr-inappm/y, users-basic, users-free - - users-teamm/y, no trial -> users-pr-inappm/y, users-basic, users-teamm/y - - users-pr-inappm/y, no trial -> users-pr-inappm/y, users-basic - - sentry customer, users-basic, no trial -> users-pr-inappm/y, users-sentrym/y, users-basic - - sentry customer, users-teamm/y, no trial -> users-pr-inappm/y, users-sentrym/y, users-basic, users-teamm/y - - sentry customer, users-sentrym/y, no trial -> users-pr-inappm/y, users-sentrym/y, users-basic + - users-developer, no trial -> users-pr-inappm/y, users-developer + - users-free, no trial -> users-pr-inappm/y, users-developer, users-free + - users-teamm/y, no trial -> users-pr-inappm/y, users-developer, users-teamm/y + - users-pr-inappm/y, no trial -> users-pr-inappm/y, users-developer + - sentry customer, users-developer, no trial -> users-pr-inappm/y, users-sentrym/y, users-developer + - sentry customer, users-teamm/y, no trial -> users-pr-inappm/y, users-sentrym/y, users-developer, users-teamm/y + - sentry customer, users-sentrym/y, no trial -> users-pr-inappm/y, users-sentrym/y, users-developer """ def setUp(self): @@ -366,16 +366,16 @@ def setUp(self): ) self.owner = OwnerFactory() - def test_available_plans_for_basic_plan_non_trial( + def test_available_plans_for_developer_plan_non_trial( self, ): - self.current_org.plan = PlanName.BASIC_PLAN_NAME.value + self.current_org.plan = PlanName.USERS_DEVELOPER.value self.current_org.save() plan_service = PlanService(current_org=self.current_org) expected_result = [] - expected_result.append(BASIC_PLAN) + expected_result.append(DEVELOPER_PLAN) expected_result += PR_AUTHOR_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result += TEAM_PLAN_REPRESENTATIONS.values() expected_result = [result.convert_to_DTO() for result in expected_result] @@ -391,7 +391,7 @@ def test_available_plans_for_free_plan_non_trial( plan_service = PlanService(current_org=self.current_org) expected_result = [] - expected_result.append(BASIC_PLAN) + expected_result.append(DEVELOPER_PLAN) expected_result.append(FREE_PLAN) expected_result += PR_AUTHOR_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result += TEAM_PLAN_REPRESENTATIONS.values() @@ -408,7 +408,7 @@ def test_available_plans_for_team_plan_non_trial( plan_service = PlanService(current_org=self.current_org) expected_result = [] - expected_result.append(BASIC_PLAN) + expected_result.append(DEVELOPER_PLAN) expected_result += PR_AUTHOR_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result += TEAM_PLAN_REPRESENTATIONS.values() expected_result = [result.convert_to_DTO() for result in expected_result] @@ -422,7 +422,7 @@ def test_available_plans_for_pro_plan_non_trial(self): plan_service = PlanService(current_org=self.current_org) expected_result = [] - expected_result.append(BASIC_PLAN) + expected_result.append(DEVELOPER_PLAN) expected_result += PR_AUTHOR_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result += TEAM_PLAN_REPRESENTATIONS.values() expected_result = [result.convert_to_DTO() for result in expected_result] @@ -430,17 +430,17 @@ def test_available_plans_for_pro_plan_non_trial(self): assert plan_service.available_plans(owner=self.owner) == expected_result @patch("shared.plan.service.is_sentry_user") - def test_available_plans_for_sentry_customer_basic_plan_non_trial( + def test_available_plans_for_sentry_customer_developer_plan_non_trial( self, is_sentry_user ): is_sentry_user.return_value = True - self.current_org.plan = PlanName.BASIC_PLAN_NAME.value + self.current_org.plan = PlanName.USERS_DEVELOPER.value self.current_org.save() plan_service = PlanService(current_org=self.current_org) expected_result = [] - expected_result.append(BASIC_PLAN) + expected_result.append(DEVELOPER_PLAN) expected_result += PR_AUTHOR_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result += SENTRY_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result += TEAM_PLAN_REPRESENTATIONS.values() @@ -459,7 +459,7 @@ def test_available_plans_for_sentry_customer_team_plan_non_trial( plan_service = PlanService(current_org=self.current_org) expected_result = [] - expected_result.append(BASIC_PLAN) + expected_result.append(DEVELOPER_PLAN) expected_result += PR_AUTHOR_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result += SENTRY_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result += TEAM_PLAN_REPRESENTATIONS.values() @@ -476,7 +476,7 @@ def test_available_plans_for_sentry_plan_non_trial(self, is_sentry_user): plan_service = PlanService(current_org=self.current_org) expected_result = [] - expected_result.append(BASIC_PLAN) + expected_result.append(DEVELOPER_PLAN) expected_result += PR_AUTHOR_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result += SENTRY_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result += TEAM_PLAN_REPRESENTATIONS.values() @@ -488,12 +488,12 @@ def test_available_plans_for_sentry_plan_non_trial(self, is_sentry_user): @freeze_time("2023-06-19") class AvailablePlansExpiredTrialLessThanTenUsers(TestCase): """ - - users-basic, has trialed, less than 10 users -> users-pr-inappm/y, users-basic, users-teamm/y - - users-teamm/y, has trialed, less than 10 users -> users-pr-inappm/y, users-basic, users-teamm/y - - users-pr-inappm/y, has trialed, less than 10 users -> users-pr-inappm/y, users-basic, users-teamm/y - - sentry customer, users-basic, has trialed, less than 10 users -> users-pr-inappm/y, users-sentrym/y, users-basic, users-teamm/y - - sentry customer, users-teamm/y, has trialed, less than 10 users -> users-pr-inappm/y, users-sentrym/y, users-basic, users-teamm/y - - sentry customer, users-sentrym/y, has trialed, less than 10 users -> users-pr-inappm/y, users-sentrym/y, users-basic, users-teamm/y + - users-developer, has trialed, less than 10 users -> users-pr-inappm/y, users-developer, users-teamm/y + - users-teamm/y, has trialed, less than 10 users -> users-pr-inappm/y, users-developer, users-teamm/y + - users-pr-inappm/y, has trialed, less than 10 users -> users-pr-inappm/y, users-developer, users-teamm/y + - sentry customer, users-developer, has trialed, less than 10 users -> users-pr-inappm/y, users-sentrym/y, users-developer, users-teamm/y + - sentry customer, users-teamm/y, has trialed, less than 10 users -> users-pr-inappm/y, users-sentrym/y, users-developer, users-teamm/y + - sentry customer, users-sentrym/y, has trialed, less than 10 users -> users-pr-inappm/y, users-sentrym/y, users-developer, users-teamm/y """ def setUp(self): @@ -505,16 +505,16 @@ def setUp(self): ) self.owner = OwnerFactory() - def test_available_plans_for_basic_plan_expired_trial_less_than_10_users( + def test_available_plans_for_developer_plan_expired_trial_less_than_10_users( self, ): - self.current_org.plan = PlanName.BASIC_PLAN_NAME.value + self.current_org.plan = PlanName.USERS_DEVELOPER.value self.current_org.save() plan_service = PlanService(current_org=self.current_org) expected_result = [] - expected_result.append(BASIC_PLAN) + expected_result.append(DEVELOPER_PLAN) expected_result += PR_AUTHOR_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result += TEAM_PLAN_REPRESENTATIONS.values() expected_result = [result.convert_to_DTO() for result in expected_result] @@ -530,7 +530,7 @@ def test_available_plans_for_team_plan_expired_trial_less_than_10_users( plan_service = PlanService(current_org=self.current_org) expected_result = [] - expected_result.append(BASIC_PLAN) + expected_result.append(DEVELOPER_PLAN) expected_result += PR_AUTHOR_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result += TEAM_PLAN_REPRESENTATIONS.values() expected_result = [result.convert_to_DTO() for result in expected_result] @@ -544,7 +544,7 @@ def test_available_plans_for_pro_plan_expired_trial_less_than_10_users(self): plan_service = PlanService(current_org=self.current_org) expected_result = [] - expected_result.append(BASIC_PLAN) + expected_result.append(DEVELOPER_PLAN) expected_result += PR_AUTHOR_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result += TEAM_PLAN_REPRESENTATIONS.values() expected_result = [result.convert_to_DTO() for result in expected_result] @@ -552,17 +552,17 @@ def test_available_plans_for_pro_plan_expired_trial_less_than_10_users(self): assert plan_service.available_plans(owner=self.owner) == expected_result @patch("shared.plan.service.is_sentry_user") - def test_available_plans_for_sentry_customer_basic_plan_expired_trial_less_than_10_users( + def test_available_plans_for_sentry_customer_developer_plan_expired_trial_less_than_10_users( self, is_sentry_user ): is_sentry_user.return_value = True - self.current_org.plan = PlanName.BASIC_PLAN_NAME.value + self.current_org.plan = PlanName.USERS_DEVELOPER.value self.current_org.save() plan_service = PlanService(current_org=self.current_org) expected_result = [] - expected_result.append(BASIC_PLAN) + expected_result.append(DEVELOPER_PLAN) expected_result += PR_AUTHOR_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result += SENTRY_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result += TEAM_PLAN_REPRESENTATIONS.values() @@ -581,7 +581,7 @@ def test_available_plans_for_sentry_customer_team_plan_expired_trial_less_than_1 plan_service = PlanService(current_org=self.current_org) expected_result = [] - expected_result.append(BASIC_PLAN) + expected_result.append(DEVELOPER_PLAN) expected_result += PR_AUTHOR_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result += SENTRY_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result += TEAM_PLAN_REPRESENTATIONS.values() @@ -600,7 +600,7 @@ def test_available_plans_for_sentry_plan_expired_trial_less_than_10_users( plan_service = PlanService(current_org=self.current_org) expected_result = [] - expected_result.append(BASIC_PLAN) + expected_result.append(DEVELOPER_PLAN) expected_result += PR_AUTHOR_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result += SENTRY_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result += TEAM_PLAN_REPRESENTATIONS.values() @@ -612,9 +612,9 @@ def test_available_plans_for_sentry_plan_expired_trial_less_than_10_users( @freeze_time("2023-06-19") class AvailablePlansExpiredTrialMoreThanTenActivatedUsers(TestCase): """ - - users-pr-inappm/y, has trialed, more than 10 activated users -> users-pr-inappm/y, users-basic - - sentry customer, users-basic, has trialed, more than 10 activated users -> users-pr-inappm/y, users-sentrym/y, users-basic - - sentry customer, users-sentrym/y, has trialed, more than 10 activated users -> users-pr-inappm/y, users-sentrym/y, users-basic + - users-pr-inappm/y, has trialed, more than 10 activated users -> users-pr-inappm/y, users-developer + - sentry customer, users-developer, has trialed, more than 10 activated users -> users-pr-inappm/y, users-sentrym/y, users-developer + - sentry customer, users-sentrym/y, has trialed, more than 10 activated users -> users-pr-inappm/y, users-sentrym/y, users-developer """ def setUp(self): @@ -634,24 +634,24 @@ def test_available_plans_for_pro_plan_expired_trial_more_than_10_users(self): plan_service = PlanService(current_org=self.current_org) expected_result = [] - expected_result.append(BASIC_PLAN) + expected_result.append(DEVELOPER_PLAN) expected_result += PR_AUTHOR_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result = [result.convert_to_DTO() for result in expected_result] assert plan_service.available_plans(owner=self.owner) == expected_result @patch("shared.plan.service.is_sentry_user") - def test_available_plans_for_sentry_customer_basic_plan_expired_trial_more_than_10_users( + def test_available_plans_for_sentry_customer_developer_plan_expired_trial_more_than_10_users( self, is_sentry_user ): is_sentry_user.return_value = True - self.current_org.plan = PlanName.BASIC_PLAN_NAME.value + self.current_org.plan = PlanName.USERS_DEVELOPER.value self.current_org.save() plan_service = PlanService(current_org=self.current_org) expected_result = [] - expected_result.append(BASIC_PLAN) + expected_result.append(DEVELOPER_PLAN) expected_result += PR_AUTHOR_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result += SENTRY_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result = [result.convert_to_DTO() for result in expected_result] @@ -669,7 +669,7 @@ def test_available_plans_for_sentry_plan_expired_trial_more_than_10_users( plan_service = PlanService(current_org=self.current_org) expected_result = [] - expected_result.append(BASIC_PLAN) + expected_result.append(DEVELOPER_PLAN) expected_result += PR_AUTHOR_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result += SENTRY_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result = [result.convert_to_DTO() for result in expected_result] @@ -685,7 +685,7 @@ class AvailablePlansExpiredTrialMoreThanTenSeatsLessThanTenActivatedUsers(TestCa def setUp(self): self.expected_result = [] - self.expected_result.append(BASIC_PLAN) + self.expected_result.append(DEVELOPER_PLAN) self.expected_result += PR_AUTHOR_PAID_USER_PLAN_REPRESENTATIONS.values() self.expected_result += TEAM_PLAN_REPRESENTATIONS.values() self.expected_result = [ @@ -745,7 +745,7 @@ def test_trial_not_started(self): self.plan_service = PlanService(current_org=self.current_org) self.expected_result = [] - self.expected_result.append(BASIC_PLAN) + self.expected_result.append(DEVELOPER_PLAN) self.expected_result += PR_AUTHOR_PAID_USER_PLAN_REPRESENTATIONS.values() self.expected_result += TEAM_PLAN_REPRESENTATIONS.values() self.expected_result = [ @@ -761,11 +761,11 @@ def test_trial_not_started(self): class AvailablePlansOngoingTrial(TestCase): """ Non Sentry User is trialing - when <=10 activated seats -> users-pr-inappm/y, users-basic, users-teamm/y - when > 10 activated seats -> users-pr-inappm/y, users-basic + when <=10 activated seats -> users-pr-inappm/y, users-developer, users-teamm/y + when > 10 activated seats -> users-pr-inappm/y, users-developer Sentry User is trialing - when <=10 activated seats -> users-pr-inappm/y, users-sentrym/y, users-basic, users-teamm/y - when > 10 activated seats -> users-pr-inappm/y, users-sentrym/y, users-basic + when <=10 activated seats -> users-pr-inappm/y, users-sentrym/y, users-developer, users-teamm/y + when > 10 activated seats -> users-pr-inappm/y, users-sentrym/y, users-developer """ def setUp(self): @@ -781,9 +781,9 @@ def setUp(self): self.plan_service = PlanService(current_org=self.current_org) def test_non_sentry_user(self): - # [Basic, Pro Monthly, Pro Yearly, Team Monthly, Team Yearly] + # [developer, Pro Monthly, Pro Yearly, Team Monthly, Team Yearly] expected_result = [] - expected_result.append(BASIC_PLAN) + expected_result.append(DEVELOPER_PLAN) expected_result += PR_AUTHOR_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result += TEAM_PLAN_REPRESENTATIONS.values() expected_result = [result.convert_to_DTO() for result in expected_result] @@ -800,9 +800,9 @@ def test_non_sentry_user(self): self.current_org.plan_activated_users = [i for i in range(11)] self.current_org.save() - # [Basic, Pro Monthly, Pro Yearly, Team Monthly, Team Yearly] + # [developer, Pro Monthly, Pro Yearly, Team Monthly, Team Yearly] expected_result = [] - expected_result.append(BASIC_PLAN) + expected_result.append(DEVELOPER_PLAN) expected_result += PR_AUTHOR_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result = [result.convert_to_DTO() for result in expected_result] @@ -813,9 +813,9 @@ def test_non_sentry_user(self): def test_sentry_user(self, is_sentry_user): is_sentry_user.return_value = True - # [Basic, Pro Monthly, Pro Yearly, Sentry Monthly, Sentry Yearly, Team Monthly, Team Yearly] + # [developer, Pro Monthly, Pro Yearly, Sentry Monthly, Sentry Yearly, Team Monthly, Team Yearly] expected_result = [] - expected_result.append(BASIC_PLAN) + expected_result.append(DEVELOPER_PLAN) expected_result += PR_AUTHOR_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result += SENTRY_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result += TEAM_PLAN_REPRESENTATIONS.values() @@ -833,9 +833,9 @@ def test_sentry_user(self, is_sentry_user): self.current_org.plan_activated_users = [i for i in range(11)] self.current_org.save() - # [Basic, Pro Monthly, Pro Yearly, Sentry Monthly, Sentry Yearly] + # [developer, Pro Monthly, Pro Yearly, Sentry Monthly, Sentry Yearly] expected_result = [] - expected_result.append(BASIC_PLAN) + expected_result.append(DEVELOPER_PLAN) expected_result += PR_AUTHOR_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result += SENTRY_PAID_USER_PLAN_REPRESENTATIONS.values() expected_result = [result.convert_to_DTO() for result in expected_result] diff --git a/tests/unit/test_router.py b/tests/unit/test_router.py index c5b5a60a6..ae1e2fd93 100644 --- a/tests/unit/test_router.py +++ b/tests/unit/test_router.py @@ -9,6 +9,9 @@ def test_route_tasks_based_on_user_plan_defaults(): assert route_tasks_based_on_user_plan( upload_task_name, BillingPlan.users_basic.db_name ) == {"queue": "celery", "extra_config": {}} + assert route_tasks_based_on_user_plan( + upload_task_name, BillingPlan.users_developer.db_name + ) == {"queue": "celery", "extra_config": {}} assert route_tasks_based_on_user_plan( upload_task_name, BillingPlan.enterprise_cloud_monthly.db_name ) == {"queue": "enterprise_celery", "extra_config": {}} From d4193dd353da22f69ab7353b1521fbe1aa4c0309 Mon Sep 17 00:00:00 2001 From: RulaKhaled Date: Thu, 30 Jan 2025 16:25:51 +0100 Subject: [PATCH 2/7] fix enum issue --- ...065_alter_account_plan_alter_owner_plan.py | 53 ++++++++++++++++--- ...9_reportsession_upload_storage_path_idx.py | 1 + shared/plan/constants.py | 1 + tests/unit/billing/test_enum_definitions.py | 4 +- 4 files changed, 51 insertions(+), 8 deletions(-) diff --git a/shared/django_apps/codecov_auth/migrations/0065_alter_account_plan_alter_owner_plan.py b/shared/django_apps/codecov_auth/migrations/0065_alter_account_plan_alter_owner_plan.py index febe170bd..e4eb9feb8 100644 --- a/shared/django_apps/codecov_auth/migrations/0065_alter_account_plan_alter_owner_plan.py +++ b/shared/django_apps/codecov_auth/migrations/0065_alter_account_plan_alter_owner_plan.py @@ -4,20 +4,59 @@ class Migration(migrations.Migration): + """ + BEGIN; + -- + -- Alter field plan on account + -- + -- (no-op) + -- + -- Raw SQL operation + -- + ALTER TYPE plans ADD VALUE IF NOT EXISTS 'users-developer'; + -- + -- Alter field plan on owner + -- + -- (no-op) + COMMIT; + """ dependencies = [ - ('codecov_auth', '0064_plan_stripe_id'), + ("codecov_auth", "0064_plan_stripe_id"), ] operations = [ migrations.AlterField( - model_name='account', - name='plan', - field=models.CharField(choices=[('users-basic', 'BASIC_PLAN_NAME'), ('users-trial', 'TRIAL_PLAN_NAME'), ('users-pr-inappm', 'CODECOV_PRO_MONTHLY'), ('users-pr-inappy', 'CODECOV_PRO_YEARLY'), ('users-sentrym', 'SENTRY_MONTHLY'), ('users-sentryy', 'SENTRY_YEARLY'), ('users-teamm', 'TEAM_MONTHLY'), ('users-teamy', 'TEAM_YEARLY'), ('users', 'GHM_PLAN_NAME'), ('users-free', 'FREE_PLAN_NAME'), ('users-inappm', 'CODECOV_PRO_MONTHLY_LEGACY'), ('users-inappy', 'CODECOV_PRO_YEARLY_LEGACY'), ('users-enterprisem', 'ENTERPRISE_CLOUD_MONTHLY'), ('users-enterprisey', 'ENTERPRISE_CLOUD_YEARLY'), ('users-developer', 'USERS_DEVELOPER')], default='users-developer', max_length=50), + model_name="account", + name="plan", + field=models.CharField( + choices=[ + ("users-basic", "BASIC_PLAN_NAME"), + ("users-trial", "TRIAL_PLAN_NAME"), + ("users-pr-inappm", "CODECOV_PRO_MONTHLY"), + ("users-pr-inappy", "CODECOV_PRO_YEARLY"), + ("users-sentrym", "SENTRY_MONTHLY"), + ("users-sentryy", "SENTRY_YEARLY"), + ("users-teamm", "TEAM_MONTHLY"), + ("users-teamy", "TEAM_YEARLY"), + ("users", "GHM_PLAN_NAME"), + ("users-free", "FREE_PLAN_NAME"), + ("users-inappm", "CODECOV_PRO_MONTHLY_LEGACY"), + ("users-inappy", "CODECOV_PRO_YEARLY_LEGACY"), + ("users-enterprisem", "ENTERPRISE_CLOUD_MONTHLY"), + ("users-enterprisey", "ENTERPRISE_CLOUD_YEARLY"), + ("users-developer", "USERS_DEVELOPER"), + ], + default="users-developer", + max_length=50, + ), + ), + migrations.RunSQL( + "ALTER TYPE plans ADD VALUE IF NOT EXISTS 'users-developer';" ), migrations.AlterField( - model_name='owner', - name='plan', - field=models.TextField(blank=True, default='users-developer', null=True), + model_name="owner", + name="plan", + field=models.TextField(blank=True, default="users-developer", null=True), ), ] diff --git a/shared/django_apps/reports/migrations/0039_reportsession_upload_storage_path_idx.py b/shared/django_apps/reports/migrations/0039_reportsession_upload_storage_path_idx.py index 3c0db4075..7b1e43c49 100644 --- a/shared/django_apps/reports/migrations/0039_reportsession_upload_storage_path_idx.py +++ b/shared/django_apps/reports/migrations/0039_reportsession_upload_storage_path_idx.py @@ -1,6 +1,7 @@ # Generated by Django 4.2.16 on 2025-01-28 15:28 from django.db import migrations, models + from shared.django_apps.migration_utils import RiskyAddIndex """ diff --git a/shared/plan/constants.py b/shared/plan/constants.py index e27343c62..8c7e796dd 100644 --- a/shared/plan/constants.py +++ b/shared/plan/constants.py @@ -8,6 +8,7 @@ class MonthlyUploadLimits(enum.Enum): CODECOV_TEAM_PLAN = 2500 CODECOV_DEVELOPER_PLAN = 250 + class TrialDaysAmount(enum.Enum): CODECOV_SENTRY = 14 diff --git a/tests/unit/billing/test_enum_definitions.py b/tests/unit/billing/test_enum_definitions.py index 004188870..0dc293670 100644 --- a/tests/unit/billing/test_enum_definitions.py +++ b/tests/unit/billing/test_enum_definitions.py @@ -74,6 +74,7 @@ def test_billing_enums(): assert BillingPlan.team_yearly.db_name == "users-teamy" assert BillingPlan.users_developer.db_name == "users-developer" + def test_get_from_string(): assert BillingPlan.from_str("users-inappm") == BillingPlan.users_monthly assert BillingPlan.from_str("users-inappy") == BillingPlan.users_yearly @@ -90,7 +91,8 @@ def test_get_from_string(): ) assert BillingPlan.from_str("users-teamm") == BillingPlan.team_monthly assert BillingPlan.from_str("users-teamy") == BillingPlan.team_yearly - assert BillingPlan.from_str("users-developer") == BillingPlan.users_developer + assert BillingPlan.from_str("users-developer") == BillingPlan.users_developer + def test_is_enterprise_cloud_plan(): assert not is_enterprise_cloud_plan(BillingPlan.pr_monthly) From 8f62e532f3882a5503e15f0b09bdc251df9d8688 Mon Sep 17 00:00:00 2001 From: RulaKhaled Date: Fri, 31 Jan 2025 14:21:12 +0100 Subject: [PATCH 3/7] Resolve tests --- shared/plan/constants.py | 2 +- shared/plan/service.py | 6 ++++-- tests/helper.py | 15 +++++++++++++++ tests/unit/plan/test_plan.py | 7 ++----- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/shared/plan/constants.py b/shared/plan/constants.py index 8c7e796dd..eba890d9d 100644 --- a/shared/plan/constants.py +++ b/shared/plan/constants.py @@ -326,7 +326,7 @@ def convert_to_DTO(self) -> dict: ], tier_name=TierName.TEAM.value, trial_days=None, - monthly_uploads_limit=None, + monthly_uploads_limit=250, ) FREE_PLAN_REPRESENTATIONS = { diff --git a/shared/plan/service.py b/shared/plan/service.py index 59e442fd0..692742545 100644 --- a/shared/plan/service.py +++ b/shared/plan/service.py @@ -69,8 +69,10 @@ def current_org(self) -> Owner: return self.current_org def set_default_plan_data(self) -> None: - """Sets the organization to the default basic plan.""" - log.info(f"Setting plan to users-basic for owner {self.current_org.ownerid}") + """Sets the organization to the default developer plan.""" + log.info( + f"Setting plan to users-developer for owner {self.current_org.ownerid}" + ) self.current_org.plan = PlanName.USERS_DEVELOPER.value self.current_org.plan_activated_users = None self.current_org.plan_user_count = 1 diff --git a/tests/helper.py b/tests/helper.py index a065ed883..a8e637368 100644 --- a/tests/helper.py +++ b/tests/helper.py @@ -217,3 +217,18 @@ def mock_all_plans_and_tiers(): "Priority Support", ], ) + + PlanFactory( + name=PlanName.USERS_DEVELOPER.value, + tier=team_tier, + marketing_name="Developer", + billing_rate=None, + base_unit_price=0, + paid_plan=False, + monthly_uploads_limit=250, + benefits=[ + "Up to 1 user", + "Unlimited public repositories", + "Unlimited private repositories", + ], + ) diff --git a/tests/unit/plan/test_plan.py b/tests/unit/plan/test_plan.py index 9ca91ae14..d695982ff 100644 --- a/tests/unit/plan/test_plan.py +++ b/tests/unit/plan/test_plan.py @@ -265,10 +265,7 @@ def test_plan_service_returns_plan_data_for_non_trial_developer_plan(self): assert ( plan_service.monthly_uploads_limit == developer_plan.monthly_uploads_limit ) # should be 250 - assert ( - plan_service.monthly_uploads_limit == 250 - ) # should be 250 since not trialing - assert plan_service.trial_total_days == developer_plan.trial_days + assert plan_service.monthly_uploads_limit == 250 def test_plan_service_returns_plan_data_for_trialing_user_trial_plan(self): trial_start_date = datetime.utcnow() @@ -928,7 +925,7 @@ def setUpClass(cls): def setUp(self): self.current_org = OwnerFactory( - plan=PlanName.BASIC_PLAN_NAME.value, + plan=PlanName.USERS_DEVELOPER.value, trial_start_date=datetime.utcnow(), trial_end_date=datetime.utcnow() + timedelta(days=14), trial_status=TrialStatus.ONGOING.value, From c04d7730163215ef7729855405baad3b16b9fb26 Mon Sep 17 00:00:00 2001 From: RulaKhaled Date: Fri, 31 Jan 2025 16:59:20 +0100 Subject: [PATCH 4/7] create a new default const for plans --- shared/plan/constants.py | 7 +- shared/plan/service.py | 7 +- tests/helper.py | 3 +- tests/unit/billing/test_enum_definitions.py | 5 +- .../codecov_auth/test_codecov_auth_models.py | 15 ++- tests/unit/plan/test_plan.py | 123 +++++++++--------- 6 files changed, 83 insertions(+), 77 deletions(-) diff --git a/shared/plan/constants.py b/shared/plan/constants.py index eba890d9d..c8150ae0b 100644 --- a/shared/plan/constants.py +++ b/shared/plan/constants.py @@ -2,6 +2,7 @@ from dataclasses import dataclass from typing import List, Optional +DEFAULT_FREE_PLAN = "users-developer" class MonthlyUploadLimits(enum.Enum): CODECOV_BASIC_PLAN = 250 @@ -316,7 +317,7 @@ def convert_to_DTO(self) -> dict: DEVELOPER_PLAN = PlanData( marketing_name=PlanMarketingName.DEVELOPER.value, - value=PlanName.USERS_DEVELOPER.value, + value=DEFAULT_FREE_PLAN, billing_rate=None, base_unit_price=PlanPrice.CODECOV_FREE.value, benefits=[ @@ -332,7 +333,7 @@ def convert_to_DTO(self) -> dict: FREE_PLAN_REPRESENTATIONS = { PlanName.FREE_PLAN_NAME.value: FREE_PLAN, PlanName.BASIC_PLAN_NAME.value: BASIC_PLAN, - PlanName.USERS_DEVELOPER.value: DEVELOPER_PLAN, + DEFAULT_FREE_PLAN: DEVELOPER_PLAN, } TEAM_PLAN_REPRESENTATIONS = { @@ -408,7 +409,7 @@ def convert_to_DTO(self) -> dict: } PLANS_THAT_CAN_TRIAL = [ - PlanName.USERS_DEVELOPER.value, + DEFAULT_FREE_PLAN, PlanName.FREE_PLAN_NAME.value, PlanName.BASIC_PLAN_NAME.value, PlanName.CODECOV_PRO_MONTHLY.value, diff --git a/shared/plan/service.py b/shared/plan/service.py index 692742545..a441a14a3 100644 --- a/shared/plan/service.py +++ b/shared/plan/service.py @@ -8,6 +8,7 @@ from shared.django_apps.codecov.commands.exceptions import ValidationError from shared.django_apps.codecov_auth.models import Owner, Plan, Service from shared.plan.constants import ( + DEFAULT_FREE_PLAN, TEAM_PLAN_MAX_USERS, TRIAL_PLAN_SEATS, PlanBillingRate, @@ -71,9 +72,9 @@ def current_org(self) -> Owner: def set_default_plan_data(self) -> None: """Sets the organization to the default developer plan.""" log.info( - f"Setting plan to users-developer for owner {self.current_org.ownerid}" + f"Setting plan to {DEFAULT_FREE_PLAN} for owner {self.current_org.ownerid}" ) - self.current_org.plan = PlanName.USERS_DEVELOPER.value + self.current_org.plan = DEFAULT_FREE_PLAN self.current_org.plan_activated_users = None self.current_org.plan_user_count = 1 self.current_org.stripe_subscription_id = None @@ -157,7 +158,7 @@ def tier_name(self) -> TierName: def available_plans(self, owner: Owner) -> List[Plan]: """Returns the available plans for the owner and organization.""" available_plans = { - Plan.objects.select_related("tier").get(name=PlanName.USERS_DEVELOPER.value) + Plan.objects.select_related("tier").get(name=DEFAULT_FREE_PLAN) } curr_plan = self.plan_data if not curr_plan.paid_plan: diff --git a/tests/helper.py b/tests/helper.py index a8e637368..8975ddff3 100644 --- a/tests/helper.py +++ b/tests/helper.py @@ -3,6 +3,7 @@ from shared.django_apps.codecov_auth.models import BillingRate from shared.django_apps.codecov_auth.tests.factories import PlanFactory, TierFactory from shared.plan.constants import ( + DEFAULT_FREE_PLAN, PlanName, PlanPrice, TierName, @@ -219,7 +220,7 @@ def mock_all_plans_and_tiers(): ) PlanFactory( - name=PlanName.USERS_DEVELOPER.value, + name=DEFAULT_FREE_PLAN, tier=team_tier, marketing_name="Developer", billing_rate=None, diff --git a/tests/unit/billing/test_enum_definitions.py b/tests/unit/billing/test_enum_definitions.py index 0dc293670..c752404a5 100644 --- a/tests/unit/billing/test_enum_definitions.py +++ b/tests/unit/billing/test_enum_definitions.py @@ -3,6 +3,7 @@ from shared.billing import BillingPlan, is_enterprise_cloud_plan, is_pr_billing_plan from shared.django_apps.codecov_auth.tests.factories import OwnerFactory +from shared.plan.constants import DEFAULT_FREE_PLAN @pytest.fixture @@ -72,7 +73,7 @@ def test_billing_enums(): assert BillingPlan.enterprise_cloud_monthly.db_name == "users-enterprisem" assert BillingPlan.team_monthly.db_name == "users-teamm" assert BillingPlan.team_yearly.db_name == "users-teamy" - assert BillingPlan.users_developer.db_name == "users-developer" + assert BillingPlan.users_developer.db_name == DEFAULT_FREE_PLAN def test_get_from_string(): @@ -91,7 +92,7 @@ def test_get_from_string(): ) assert BillingPlan.from_str("users-teamm") == BillingPlan.team_monthly assert BillingPlan.from_str("users-teamy") == BillingPlan.team_yearly - assert BillingPlan.from_str("users-developer") == BillingPlan.users_developer + assert BillingPlan.from_str(DEFAULT_FREE_PLAN) == BillingPlan.users_developer def test_is_enterprise_cloud_plan(): diff --git a/tests/unit/django_apps/codecov_auth/test_codecov_auth_models.py b/tests/unit/django_apps/codecov_auth/test_codecov_auth_models.py index 0fa29ff3c..5121c928c 100644 --- a/tests/unit/django_apps/codecov_auth/test_codecov_auth_models.py +++ b/tests/unit/django_apps/codecov_auth/test_codecov_auth_models.py @@ -39,6 +39,7 @@ DEVELOPER_PLAN, ENTERPRISE_CLOUD_USER_PLAN_REPRESENTATIONS, PlanName, + DEFAULT_FREE_PLAN, ) from shared.utils.test_utils import mock_config_helper from tests.helper import mock_all_plans_and_tiers @@ -380,7 +381,7 @@ def test_can_activate_user_cannot_activate_account(self): def test_fields_that_account_overrides(self): mock_all_plans_and_tiers() to_activate = OwnerFactory() - self.owner.plan = PlanName.USERS_DEVELOPER.value + self.owner.plan = DEFAULT_FREE_PLAN self.owner.plan_user_count = 1 self.owner.save() self.assertTrue(self.owner.can_activate_user(to_activate)) @@ -527,7 +528,7 @@ def test_has_yaml(self): class TestOrganizationLevelTokenModel(TestCase): def test_can_save_org_token_for_org_basic_plan(self): - owner = OwnerFactory(plan="users-developer") + owner = OwnerFactory(plan=DEFAULT_FREE_PLAN) owner.save() token = OrganizationLevelToken(owner=owner) token.save() @@ -545,7 +546,7 @@ def test_token_is_deleted_when_changing_user_plan( owner.save() org_token.save() assert OrganizationLevelToken.objects.filter(owner=owner).count() == 1 - owner.plan = "users-developer" + owner.plan = DEFAULT_FREE_PLAN owner.save() assert OrganizationLevelToken.objects.filter(owner=owner).count() == 0 @@ -772,21 +773,21 @@ def test_create_account_for_enterprise_experience(self): user_for_owner_1 = UserFactory(email="hello@email.com", name="Luigi") owner_1 = OwnerFactory( username="codecov-1", - plan=PlanName.USERS_DEVELOPER.value, + plan=DEFAULT_FREE_PLAN, plan_user_count=1, organizations=[], user_id=user_for_owner_1.id, # has user ) owner_2 = OwnerFactory( username="codecov-sentry", - plan=PlanName.USERS_DEVELOPER.value, + plan=DEFAULT_FREE_PLAN, plan_user_count=1, organizations=[], user_id=None, # no user ) owner_3 = OwnerFactory( username="sentry-1", - plan=PlanName.USERS_DEVELOPER.value, + plan=DEFAULT_FREE_PLAN, plan_user_count=1, organizations=[], user_id=None, # no user @@ -810,7 +811,7 @@ def test_create_account_for_enterprise_experience(self): username="codecov-org", stripe_customer_id=stripe_customer_id, stripe_subscription_id=stripe_subscription_id, - plan=PlanName.USERS_DEVELOPER.value, + plan=DEFAULT_FREE_PLAN, plan_user_count=50, plan_activated_users=[owner_1.ownerid, owner_2.ownerid], free=10, diff --git a/tests/unit/plan/test_plan.py b/tests/unit/plan/test_plan.py index d695982ff..7d6ef5090 100644 --- a/tests/unit/plan/test_plan.py +++ b/tests/unit/plan/test_plan.py @@ -12,6 +12,7 @@ TierFactory, ) from shared.plan.constants import ( + DEFAULT_FREE_PLAN, FREE_PLAN_REPRESENTATIONS, TRIAL_PLAN_REPRESENTATION, TRIAL_PLAN_SEATS, @@ -32,7 +33,7 @@ def setUpClass(cls): mock_all_plans_and_tiers() def test_plan_service_trial_status_not_started(self): - current_org = OwnerFactory(plan=PlanName.USERS_DEVELOPER.value) + current_org = OwnerFactory(plan=DEFAULT_FREE_PLAN) plan_service = PlanService(current_org=current_org) assert plan_service.trial_status == TrialStatus.NOT_STARTED.value @@ -41,7 +42,7 @@ def test_plan_service_trial_status_expired(self): trial_start_date = datetime.utcnow() trial_end_date_expired = trial_start_date - timedelta(days=1) current_org = OwnerFactory( - plan=PlanName.USERS_DEVELOPER.value, + plan=DEFAULT_FREE_PLAN, trial_start_date=trial_start_date, trial_end_date=trial_end_date_expired, trial_status=TrialStatus.EXPIRED.value, @@ -68,7 +69,7 @@ def test_plan_service_expire_trial_when_upgrading_successful_if_trial_is_not_sta self, ): current_org_with_ongoing_trial = OwnerFactory( - plan=PlanName.USERS_DEVELOPER.value, + plan=DEFAULT_FREE_PLAN, trial_start_date=None, trial_end_date=None, trial_status=TrialStatus.NOT_STARTED.value, @@ -86,7 +87,7 @@ def test_plan_service_expire_trial_when_upgrading_successful_if_trial_is_ongoing trial_start_date = datetime.utcnow() trial_end_date_ongoing = trial_start_date + timedelta(days=5) current_org_with_ongoing_trial = OwnerFactory( - plan=PlanName.USERS_DEVELOPER.value, + plan=DEFAULT_FREE_PLAN, trial_start_date=trial_start_date, trial_end_date=trial_end_date_ongoing, trial_status=TrialStatus.ONGOING.value, @@ -105,7 +106,7 @@ def test_plan_service_expire_trial_users_pretrial_users_count_if_existing( trial_end_date_ongoing = trial_start_date + timedelta(days=5) pretrial_users_count = 5 current_org_with_ongoing_trial = OwnerFactory( - plan=PlanName.USERS_DEVELOPER.value, + plan=DEFAULT_FREE_PLAN, trial_start_date=trial_start_date, trial_end_date=trial_end_date_ongoing, trial_status=TrialStatus.ONGOING.value, @@ -124,7 +125,7 @@ def test_plan_service_start_trial_errors_if_status_is_ongoing(self): days=TrialDaysAmount.CODECOV_SENTRY.value ) current_org = OwnerFactory( - plan=PlanName.USERS_DEVELOPER.value, + plan=DEFAULT_FREE_PLAN, trial_start_date=trial_start_date, trial_end_date=trial_end_date, trial_status=TrialStatus.ONGOING.value, @@ -139,7 +140,7 @@ def test_plan_service_start_trial_errors_if_status_is_expired(self): trial_start_date = datetime.utcnow() trial_end_date = trial_start_date + timedelta(days=-1) current_org = OwnerFactory( - plan=PlanName.USERS_DEVELOPER.value, + plan=DEFAULT_FREE_PLAN, trial_start_date=trial_start_date, trial_end_date=trial_end_date, trial_status=TrialStatus.EXPIRED.value, @@ -152,7 +153,7 @@ def test_plan_service_start_trial_errors_if_status_is_expired(self): def test_plan_service_start_trial_errors_if_status_is_cannot_trial(self): current_org = OwnerFactory( - plan=PlanName.USERS_DEVELOPER.value, + plan=DEFAULT_FREE_PLAN, trial_start_date=None, trial_end_date=None, trial_status=TrialStatus.CANNOT_TRIAL.value, @@ -181,7 +182,7 @@ def test_plan_service_start_trial_succeeds_if_trial_has_not_started(self): trial_end_date = None plan_user_count = 5 current_org = OwnerFactory( - plan=PlanName.USERS_DEVELOPER.value, + plan=DEFAULT_FREE_PLAN, trial_start_date=trial_start_date, trial_end_date=trial_end_date, trial_status=TrialStatus.NOT_STARTED.value, @@ -207,7 +208,7 @@ def test_plan_service_start_trial_manually(self): trial_end_date = None plan_user_count = 5 current_org = OwnerFactory( - plan=PlanName.USERS_DEVELOPER.value, + plan=DEFAULT_FREE_PLAN, trial_start_date=trial_start_date, trial_end_date=trial_end_date, trial_status=TrialStatus.NOT_STARTED.value, @@ -247,13 +248,13 @@ def test_plan_service_returns_plan_data_for_non_trial_developer_plan(self): trial_start_date = None trial_end_date = None current_org = OwnerFactory( - plan=PlanName.USERS_DEVELOPER.value, + plan=DEFAULT_FREE_PLAN, trial_start_date=trial_start_date, trial_end_date=trial_end_date, ) plan_service = PlanService(current_org=current_org) - developer_plan = FREE_PLAN_REPRESENTATIONS[PlanName.USERS_DEVELOPER.value] + developer_plan = FREE_PLAN_REPRESENTATIONS[DEFAULT_FREE_PLAN] assert plan_service.current_org == current_org assert plan_service.trial_status == TrialStatus.NOT_STARTED.value assert plan_service.marketing_name == developer_plan.marketing_name @@ -303,7 +304,7 @@ def test_plan_service_sets_default_plan_data_values_correctly(self): plan_service = PlanService(current_org=current_org) plan_service.set_default_plan_data() - assert current_org.plan == PlanName.USERS_DEVELOPER.value + assert current_org.plan == DEFAULT_FREE_PLAN assert current_org.plan_user_count == 1 assert current_org.plan_activated_users is None assert current_org.stripe_subscription_id is None @@ -351,13 +352,13 @@ def test_plan_service_gitlab_with_root_org(self): class AvailablePlansBeforeTrial(TestCase): """ - - users-developer, no trial -> users-pr-inappm/y, users-developer - - users-free, no trial -> users-pr-inappm/y, users-developer, users-free - - users-teamm/y, no trial -> users-pr-inappm/y, users-developer, users-teamm/y - - users-pr-inappm/y, no trial -> users-pr-inappm/y, users-developer - - sentry customer, users-developer, no trial -> users-pr-inappm/y, users-sentrym/y, users-developer - - sentry customer, users-teamm/y, no trial -> users-pr-inappm/y, users-sentrym/y, users-developer, users-teamm/y - - sentry customer, users-sentrym/y, no trial -> users-pr-inappm/y, users-sentrym/y, users-developer + - DEFAULT_FREE_PLAN, no trial -> users-pr-inappm/y, DEFAULT_FREE_PLAN + - users-free, no trial -> users-pr-inappm/y, DEFAULT_FREE_PLAN, users-free + - users-teamm/y, no trial -> users-pr-inappm/y, DEFAULT_FREE_PLAN, users-teamm/y + - users-pr-inappm/y, no trial -> users-pr-inappm/y, DEFAULT_FREE_PLAN + - sentry customer, DEFAULT_FREE_PLAN, no trial -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN + - sentry customer, users-teamm/y, no trial -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN, users-teamm/y + - sentry customer, users-sentrym/y, no trial -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN """ @classmethod @@ -376,13 +377,13 @@ def setUp(self): def test_available_plans_for_developer_plan_non_trial( self, ): - self.current_org.plan = PlanName.USERS_DEVELOPER.value + self.current_org.plan = DEFAULT_FREE_PLAN self.current_org.save() plan_service = PlanService(current_org=self.current_org) expected_result = { - PlanName.USERS_DEVELOPER.value, + DEFAULT_FREE_PLAN, PlanName.CODECOV_PRO_MONTHLY.value, PlanName.CODECOV_PRO_YEARLY.value, PlanName.TEAM_MONTHLY.value, @@ -405,7 +406,7 @@ def test_available_plans_for_free_plan_non_trial( plan_service = PlanService(current_org=self.current_org) expected_result = { - PlanName.USERS_DEVELOPER.value, + DEFAULT_FREE_PLAN, PlanName.FREE_PLAN_NAME.value, PlanName.CODECOV_PRO_MONTHLY.value, PlanName.CODECOV_PRO_YEARLY.value, @@ -429,7 +430,7 @@ def test_available_plans_for_team_plan_non_trial( plan_service = PlanService(current_org=self.current_org) expected_result = { - PlanName.USERS_DEVELOPER.value, + DEFAULT_FREE_PLAN, PlanName.CODECOV_PRO_MONTHLY.value, PlanName.CODECOV_PRO_YEARLY.value, PlanName.TEAM_MONTHLY.value, @@ -450,7 +451,7 @@ def test_available_plans_for_pro_plan_non_trial(self): plan_service = PlanService(current_org=self.current_org) expected_result = { - PlanName.USERS_DEVELOPER.value, + DEFAULT_FREE_PLAN, PlanName.CODECOV_PRO_MONTHLY.value, PlanName.CODECOV_PRO_YEARLY.value, PlanName.TEAM_MONTHLY.value, @@ -469,13 +470,13 @@ def test_available_plans_for_sentry_customer_developer_plan_non_trial( self, is_sentry_user ): is_sentry_user.return_value = True - self.current_org.plan = PlanName.USERS_DEVELOPER.value + self.current_org.plan = DEFAULT_FREE_PLAN self.current_org.save() plan_service = PlanService(current_org=self.current_org) expected_result = { - PlanName.USERS_DEVELOPER.value, + DEFAULT_FREE_PLAN, PlanName.CODECOV_PRO_MONTHLY.value, PlanName.CODECOV_PRO_YEARLY.value, PlanName.SENTRY_MONTHLY.value, @@ -502,7 +503,7 @@ def test_available_plans_for_sentry_customer_team_plan_non_trial( plan_service = PlanService(current_org=self.current_org) expected_result = { - PlanName.USERS_DEVELOPER.value, + DEFAULT_FREE_PLAN, PlanName.CODECOV_PRO_MONTHLY.value, PlanName.CODECOV_PRO_YEARLY.value, PlanName.SENTRY_MONTHLY.value, @@ -526,7 +527,7 @@ def test_available_plans_for_sentry_plan_non_trial(self, is_sentry_user): plan_service = PlanService(current_org=self.current_org) expected_result = { - PlanName.USERS_DEVELOPER.value, + DEFAULT_FREE_PLAN, PlanName.CODECOV_PRO_MONTHLY.value, PlanName.CODECOV_PRO_YEARLY.value, PlanName.SENTRY_MONTHLY.value, @@ -546,12 +547,12 @@ def test_available_plans_for_sentry_plan_non_trial(self, is_sentry_user): @freeze_time("2023-06-19") class AvailablePlansExpiredTrialLessThanTenUsers(TestCase): """ - - users-developer, has trialed, less than 10 users -> users-pr-inappm/y, users-developer, users-teamm/y - - users-teamm/y, has trialed, less than 10 users -> users-pr-inappm/y, users-developer, users-teamm/y - - users-pr-inappm/y, has trialed, less than 10 users -> users-pr-inappm/y, users-developer, users-teamm/y - - sentry customer, users-developer, has trialed, less than 10 users -> users-pr-inappm/y, users-sentrym/y, users-developer, users-teamm/y - - sentry customer, users-teamm/y, has trialed, less than 10 users -> users-pr-inappm/y, users-sentrym/y, users-developer, users-teamm/y - - sentry customer, users-sentrym/y, has trialed, less than 10 users -> users-pr-inappm/y, users-sentrym/y, users-developer, users-teamm/y + - { DEFAULT_FREE_PLAN}, has trialed, less than 10 users -> users-pr-inappm/y, DEFAULT_FREE_PLAN, users-teamm/y + - users-teamm/y, has trialed, less than 10 users -> users-pr-inappm/y, DEFAULT_FREE_PLAN, users-teamm/y + - users-pr-inappm/y, has trialed, less than 10 users -> users-pr-inappm/y, DEFAULT_FREE_PLAN, users-teamm/y + - sentry customer, DEFAULT_FREE_PLAN, has trialed, less than 10 users -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN, users-teamm/y + - sentry customer, users-teamm/y, has trialed, less than 10 users -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN, users-teamm/y + - sentry customer, users-sentrym/y, has trialed, less than 10 users -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN, users-teamm/y """ @classmethod @@ -571,13 +572,13 @@ def setUp(self): def test_available_plans_for_developer_plan_expired_trial_less_than_10_users( self, ): - self.current_org.plan = PlanName.USERS_DEVELOPER.value + self.current_org.plan = DEFAULT_FREE_PLAN self.current_org.save() plan_service = PlanService(current_org=self.current_org) expected_result = { - PlanName.USERS_DEVELOPER.value, + DEFAULT_FREE_PLAN, PlanName.CODECOV_PRO_MONTHLY.value, PlanName.CODECOV_PRO_YEARLY.value, PlanName.TEAM_MONTHLY.value, @@ -599,7 +600,7 @@ def test_available_plans_for_team_plan_expired_trial_less_than_10_users( plan_service = PlanService(current_org=self.current_org) expected_result = { - PlanName.USERS_DEVELOPER.value, + DEFAULT_FREE_PLAN, PlanName.CODECOV_PRO_MONTHLY.value, PlanName.CODECOV_PRO_YEARLY.value, PlanName.TEAM_MONTHLY.value, @@ -619,7 +620,7 @@ def test_available_plans_for_pro_plan_expired_trial_less_than_10_users(self): plan_service = PlanService(current_org=self.current_org) expected_result = { - PlanName.USERS_DEVELOPER.value, + DEFAULT_FREE_PLAN, PlanName.CODECOV_PRO_MONTHLY.value, PlanName.CODECOV_PRO_YEARLY.value, PlanName.TEAM_MONTHLY.value, @@ -638,13 +639,13 @@ def test_available_plans_for_sentry_customer_developer_plan_expired_trial_less_t self, is_sentry_user ): is_sentry_user.return_value = True - self.current_org.plan = PlanName.USERS_DEVELOPER.value + self.current_org.plan = DEFAULT_FREE_PLAN self.current_org.save() plan_service = PlanService(current_org=self.current_org) expected_result = { - PlanName.USERS_DEVELOPER.value, + DEFAULT_FREE_PLAN, PlanName.CODECOV_PRO_MONTHLY.value, PlanName.CODECOV_PRO_YEARLY.value, PlanName.SENTRY_MONTHLY.value, @@ -670,7 +671,7 @@ def test_available_plans_for_sentry_customer_team_plan_expired_trial_less_than_1 plan_service = PlanService(current_org=self.current_org) expected_result = { - PlanName.USERS_DEVELOPER.value, + DEFAULT_FREE_PLAN, PlanName.CODECOV_PRO_MONTHLY.value, PlanName.CODECOV_PRO_YEARLY.value, PlanName.SENTRY_MONTHLY.value, @@ -697,7 +698,7 @@ def test_available_plans_for_sentry_plan_expired_trial_less_than_10_users( plan_service = PlanService(current_org=self.current_org) expected_result = { - PlanName.USERS_DEVELOPER.value, + DEFAULT_FREE_PLAN, PlanName.CODECOV_PRO_MONTHLY.value, PlanName.CODECOV_PRO_YEARLY.value, PlanName.SENTRY_MONTHLY.value, @@ -717,9 +718,9 @@ def test_available_plans_for_sentry_plan_expired_trial_less_than_10_users( @freeze_time("2023-06-19") class AvailablePlansExpiredTrialMoreThanTenActivatedUsers(TestCase): """ - - users-pr-inappm/y, has trialed, more than 10 activated users -> users-pr-inappm/y, users-developer - - sentry customer, users-developer, has trialed, more than 10 activated users -> users-pr-inappm/y, users-sentrym/y, users-developer - - sentry customer, users-sentrym/y, has trialed, more than 10 activated users -> users-pr-inappm/y, users-sentrym/y, users-developer + - users-pr-inappm/y, has trialed, more than 10 activated users -> users-pr-inappm/y, DEFAULT_FREE_PLAN + - sentry customer, DEFAULT_FREE_PLAN, has trialed, more than 10 activated users -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN + - sentry customer, users-sentrym/y, has trialed, more than 10 activated users -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN """ @classmethod @@ -744,7 +745,7 @@ def test_available_plans_for_pro_plan_expired_trial_more_than_10_users(self): plan_service = PlanService(current_org=self.current_org) expected_result = { - PlanName.USERS_DEVELOPER.value, + DEFAULT_FREE_PLAN, PlanName.CODECOV_PRO_MONTHLY.value, PlanName.CODECOV_PRO_YEARLY.value, } @@ -761,13 +762,13 @@ def test_available_plans_for_sentry_customer_developer_plan_expired_trial_more_t self, is_sentry_user ): is_sentry_user.return_value = True - self.current_org.plan = PlanName.USERS_DEVELOPER.value + self.current_org.plan = DEFAULT_FREE_PLAN self.current_org.save() plan_service = PlanService(current_org=self.current_org) expected_result = { - PlanName.USERS_DEVELOPER.value, + DEFAULT_FREE_PLAN, PlanName.CODECOV_PRO_MONTHLY.value, PlanName.CODECOV_PRO_YEARLY.value, PlanName.SENTRY_MONTHLY.value, @@ -791,7 +792,7 @@ def test_available_plans_for_sentry_plan_expired_trial_more_than_10_users( plan_service = PlanService(current_org=self.current_org) expected_result = { - PlanName.USERS_DEVELOPER.value, + DEFAULT_FREE_PLAN, PlanName.CODECOV_PRO_MONTHLY.value, PlanName.CODECOV_PRO_YEARLY.value, PlanName.SENTRY_MONTHLY.value, @@ -819,7 +820,7 @@ def setUpClass(cls): def setUp(self): self.expected_result = { - PlanName.USERS_DEVELOPER.value, + DEFAULT_FREE_PLAN, PlanName.CODECOV_PRO_MONTHLY.value, PlanName.CODECOV_PRO_YEARLY.value, PlanName.TEAM_MONTHLY.value, @@ -891,7 +892,7 @@ def test_trial_not_started(self): self.plan_service = PlanService(current_org=self.current_org) self.expected_result = { - PlanName.USERS_DEVELOPER.value, + DEFAULT_FREE_PLAN, PlanName.CODECOV_PRO_MONTHLY.value, PlanName.CODECOV_PRO_YEARLY.value, PlanName.TEAM_MONTHLY.value, @@ -911,11 +912,11 @@ def test_trial_not_started(self): class AvailablePlansOngoingTrial(TestCase): """ Non Sentry User is trialing - when <=10 activated seats -> users-pr-inappm/y, users-developer, users-teamm/y - when > 10 activated seats -> users-pr-inappm/y, users-developer + when <=10 activated seats -> users-pr-inappm/y, DEFAULT_FREE_PLAN, users-teamm/y + when > 10 activated seats -> users-pr-inappm/y, DEFAULT_FREE_PLAN Sentry User is trialing - when <=10 activated seats -> users-pr-inappm/y, users-sentrym/y, users-developer, users-teamm/y - when > 10 activated seats -> users-pr-inappm/y, users-sentrym/y, users-developer + when <=10 activated seats -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN, users-teamm/y + when > 10 activated seats -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN """ @classmethod @@ -925,7 +926,7 @@ def setUpClass(cls): def setUp(self): self.current_org = OwnerFactory( - plan=PlanName.USERS_DEVELOPER.value, + plan=DEFAULT_FREE_PLAN, trial_start_date=datetime.utcnow(), trial_end_date=datetime.utcnow() + timedelta(days=14), trial_status=TrialStatus.ONGOING.value, @@ -938,7 +939,7 @@ def setUp(self): def test_non_sentry_user(self): # [Developer, Pro Monthly, Pro Yearly, Team Monthly, Team Yearly] expected_result = { - PlanName.USERS_DEVELOPER.value, + DEFAULT_FREE_PLAN, PlanName.CODECOV_PRO_YEARLY.value, PlanName.CODECOV_PRO_MONTHLY.value, PlanName.TEAM_MONTHLY.value, @@ -971,7 +972,7 @@ def test_non_sentry_user(self): # [Developer, Pro Monthly, Pro Yearly] expected_result = { - PlanName.USERS_DEVELOPER.value, + DEFAULT_FREE_PLAN, PlanName.CODECOV_PRO_YEARLY.value, PlanName.CODECOV_PRO_MONTHLY.value, } @@ -994,7 +995,7 @@ def test_sentry_user(self, is_sentry_user): # [Developer, Pro Monthly, Pro Yearly, Sentry Monthly, Sentry Yearly, Team Monthly, Team Yearly] expected_result = { - PlanName.USERS_DEVELOPER.value, + DEFAULT_FREE_PLAN, PlanName.CODECOV_PRO_YEARLY.value, PlanName.CODECOV_PRO_MONTHLY.value, PlanName.SENTRY_MONTHLY.value, @@ -1028,7 +1029,7 @@ def test_sentry_user(self, is_sentry_user): # [Developer, Pro Monthly, Pro Yearly, Sentry Monthly, Sentry Yearly] expected_result = { - PlanName.USERS_DEVELOPER.value, + DEFAULT_FREE_PLAN, PlanName.CODECOV_PRO_YEARLY.value, PlanName.CODECOV_PRO_MONTHLY.value, PlanName.SENTRY_MONTHLY.value, From 59674dc2744d75a387ef256d26b473c976cf936d Mon Sep 17 00:00:00 2001 From: RulaKhaled Date: Fri, 31 Jan 2025 17:34:29 +0100 Subject: [PATCH 5/7] fix lint issues --- shared/plan/constants.py | 1 + tests/unit/django_apps/codecov_auth/test_codecov_auth_models.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/shared/plan/constants.py b/shared/plan/constants.py index c8150ae0b..dd0cd851d 100644 --- a/shared/plan/constants.py +++ b/shared/plan/constants.py @@ -4,6 +4,7 @@ DEFAULT_FREE_PLAN = "users-developer" + class MonthlyUploadLimits(enum.Enum): CODECOV_BASIC_PLAN = 250 CODECOV_TEAM_PLAN = 2500 diff --git a/tests/unit/django_apps/codecov_auth/test_codecov_auth_models.py b/tests/unit/django_apps/codecov_auth/test_codecov_auth_models.py index 5121c928c..7c17982c2 100644 --- a/tests/unit/django_apps/codecov_auth/test_codecov_auth_models.py +++ b/tests/unit/django_apps/codecov_auth/test_codecov_auth_models.py @@ -36,10 +36,10 @@ ) from shared.django_apps.core.tests.factories import RepositoryFactory from shared.plan.constants import ( + DEFAULT_FREE_PLAN, DEVELOPER_PLAN, ENTERPRISE_CLOUD_USER_PLAN_REPRESENTATIONS, PlanName, - DEFAULT_FREE_PLAN, ) from shared.utils.test_utils import mock_config_helper from tests.helper import mock_all_plans_and_tiers From 8bb5d10d71adaed70bc0eea8304283a274f69fd5 Mon Sep 17 00:00:00 2001 From: RulaKhaled Date: Mon, 3 Feb 2025 10:42:27 +0100 Subject: [PATCH 6/7] remove developer new enum key --- shared/plan/constants.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/shared/plan/constants.py b/shared/plan/constants.py index dd0cd851d..b1a992136 100644 --- a/shared/plan/constants.py +++ b/shared/plan/constants.py @@ -6,9 +6,8 @@ class MonthlyUploadLimits(enum.Enum): - CODECOV_BASIC_PLAN = 250 + CODECOV_FREE_PLAN = 250 CODECOV_TEAM_PLAN = 2500 - CODECOV_DEVELOPER_PLAN = 250 class TrialDaysAmount(enum.Enum): @@ -24,7 +23,6 @@ class PlanMarketingName(enum.Enum): BASIC = "Developer" TRIAL = "Developer" TEAM = "Team" - DEVELOPER = "Developer" class PlanName(enum.Enum): @@ -297,7 +295,7 @@ def convert_to_DTO(self) -> dict: "Unlimited private repositories", ], tier_name=TierName.BASIC.value, - monthly_uploads_limit=MonthlyUploadLimits.CODECOV_BASIC_PLAN.value, + monthly_uploads_limit=MonthlyUploadLimits.CODECOV_FREE_PLAN.value, trial_days=None, ) @@ -317,7 +315,7 @@ def convert_to_DTO(self) -> dict: ) DEVELOPER_PLAN = PlanData( - marketing_name=PlanMarketingName.DEVELOPER.value, + marketing_name=PlanMarketingName.FREE.value, value=DEFAULT_FREE_PLAN, billing_rate=None, base_unit_price=PlanPrice.CODECOV_FREE.value, From b7bb7504e8f1a87e5737aa4c6eb47bc24f1e18f0 Mon Sep 17 00:00:00 2001 From: RulaKhaled Date: Mon, 3 Feb 2025 11:03:30 +0100 Subject: [PATCH 7/7] remove deprecated --- shared/billing/__init__.py | 1 - shared/plan/constants.py | 5 +-- tests/helper.py | 11 ------ tests/unit/billing/test_enum_definitions.py | 3 -- tests/unit/plan/test_plan.py | 38 ++++++++++----------- tests/unit/test_router.py | 3 -- 6 files changed, 22 insertions(+), 39 deletions(-) diff --git a/shared/billing/__init__.py b/shared/billing/__init__.py index cd9728d15..3010b6d02 100644 --- a/shared/billing/__init__.py +++ b/shared/billing/__init__.py @@ -23,7 +23,6 @@ class BillingPlan(Enum): users_yearly = PlanName.CODECOV_PRO_YEARLY_LEGACY.value enterprise_cloud_monthly = PlanName.ENTERPRISE_CLOUD_MONTHLY.value enterprise_cloud_yearly = PlanName.ENTERPRISE_CLOUD_YEARLY.value - users_developer = PlanName.USERS_DEVELOPER.value def __init__(self, db_name): self.db_name = db_name diff --git a/shared/plan/constants.py b/shared/plan/constants.py index b1a992136..1c9288741 100644 --- a/shared/plan/constants.py +++ b/shared/plan/constants.py @@ -2,8 +2,6 @@ from dataclasses import dataclass from typing import List, Optional -DEFAULT_FREE_PLAN = "users-developer" - class MonthlyUploadLimits(enum.Enum): CODECOV_FREE_PLAN = 250 @@ -25,6 +23,9 @@ class PlanMarketingName(enum.Enum): TEAM = "Team" +DEFAULT_FREE_PLAN = "users-developer" + + class PlanName(enum.Enum): # If you add or remove, make a migration for Account table BASIC_PLAN_NAME = "users-basic" diff --git a/tests/helper.py b/tests/helper.py index 8975ddff3..b92739ed7 100644 --- a/tests/helper.py +++ b/tests/helper.py @@ -73,17 +73,6 @@ def mock_all_plans_and_tiers(): ) basic_tier = TierFactory(tier_name=TierName.BASIC.value) - PlanFactory( - name=PlanName.BASIC_PLAN_NAME.value, - tier=basic_tier, - marketing_name="Developer", - benefits=[ - "Up to 1 user", - "Unlimited public repositories", - "Unlimited private repositories", - ], - monthly_uploads_limit=250, - ) PlanFactory( name=PlanName.FREE_PLAN_NAME.value, tier=basic_tier, diff --git a/tests/unit/billing/test_enum_definitions.py b/tests/unit/billing/test_enum_definitions.py index c752404a5..8893d012a 100644 --- a/tests/unit/billing/test_enum_definitions.py +++ b/tests/unit/billing/test_enum_definitions.py @@ -3,7 +3,6 @@ from shared.billing import BillingPlan, is_enterprise_cloud_plan, is_pr_billing_plan from shared.django_apps.codecov_auth.tests.factories import OwnerFactory -from shared.plan.constants import DEFAULT_FREE_PLAN @pytest.fixture @@ -73,7 +72,6 @@ def test_billing_enums(): assert BillingPlan.enterprise_cloud_monthly.db_name == "users-enterprisem" assert BillingPlan.team_monthly.db_name == "users-teamm" assert BillingPlan.team_yearly.db_name == "users-teamy" - assert BillingPlan.users_developer.db_name == DEFAULT_FREE_PLAN def test_get_from_string(): @@ -92,7 +90,6 @@ def test_get_from_string(): ) assert BillingPlan.from_str("users-teamm") == BillingPlan.team_monthly assert BillingPlan.from_str("users-teamy") == BillingPlan.team_yearly - assert BillingPlan.from_str(DEFAULT_FREE_PLAN) == BillingPlan.users_developer def test_is_enterprise_cloud_plan(): diff --git a/tests/unit/plan/test_plan.py b/tests/unit/plan/test_plan.py index 7d6ef5090..7bd7781b6 100644 --- a/tests/unit/plan/test_plan.py +++ b/tests/unit/plan/test_plan.py @@ -352,13 +352,13 @@ def test_plan_service_gitlab_with_root_org(self): class AvailablePlansBeforeTrial(TestCase): """ - - DEFAULT_FREE_PLAN, no trial -> users-pr-inappm/y, DEFAULT_FREE_PLAN - - users-free, no trial -> users-pr-inappm/y, DEFAULT_FREE_PLAN, users-free - - users-teamm/y, no trial -> users-pr-inappm/y, DEFAULT_FREE_PLAN, users-teamm/y + - DEFAULT_FREE_PLAN, no trial -> users-pr-inappm/y, DEFAULT_FREE_PLAN + - users-free, no trial -> users-pr-inappm/y, DEFAULT_FREE_PLAN, users-free + - users-teamm/y, no trial -> users-pr-inappm/y, DEFAULT_FREE_PLAN, users-teamm/y - users-pr-inappm/y, no trial -> users-pr-inappm/y, DEFAULT_FREE_PLAN - - sentry customer, DEFAULT_FREE_PLAN, no trial -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN - - sentry customer, users-teamm/y, no trial -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN, users-teamm/y - - sentry customer, users-sentrym/y, no trial -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN + - sentry customer, DEFAULT_FREE_PLAN, no trial -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN + - sentry customer, users-teamm/y, no trial -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN, users-teamm/y + - sentry customer, users-sentrym/y, no trial -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN """ @classmethod @@ -547,12 +547,12 @@ def test_available_plans_for_sentry_plan_non_trial(self, is_sentry_user): @freeze_time("2023-06-19") class AvailablePlansExpiredTrialLessThanTenUsers(TestCase): """ - - { DEFAULT_FREE_PLAN}, has trialed, less than 10 users -> users-pr-inappm/y, DEFAULT_FREE_PLAN, users-teamm/y - - users-teamm/y, has trialed, less than 10 users -> users-pr-inappm/y, DEFAULT_FREE_PLAN, users-teamm/y - - users-pr-inappm/y, has trialed, less than 10 users -> users-pr-inappm/y, DEFAULT_FREE_PLAN, users-teamm/y - - sentry customer, DEFAULT_FREE_PLAN, has trialed, less than 10 users -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN, users-teamm/y - - sentry customer, users-teamm/y, has trialed, less than 10 users -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN, users-teamm/y - - sentry customer, users-sentrym/y, has trialed, less than 10 users -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN, users-teamm/y + - {DEFAULT_FREE_PLAN}, has trialed, less than 10 users -> users-pr-inappm/y, DEFAULT_FREE_PLAN, users-teamm/y + - users-teamm/y, has trialed, less than 10 users -> users-pr-inappm/y, DEFAULT_FREE_PLAN, users-teamm/y + - users-pr-inappm/y, has trialed, less than 10 users -> users-pr-inappm/y, DEFAULT_FREE_PLAN, users-teamm/y + - sentry customer, DEFAULT_FREE_PLAN, has trialed, less than 10 users -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN, users-teamm/y + - sentry customer, users-teamm/y, has trialed, less than 10 users -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN, users-teamm/y + - sentry customer, users-sentrym/y, has trialed, less than 10 users -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN, users-teamm/y """ @classmethod @@ -718,9 +718,9 @@ def test_available_plans_for_sentry_plan_expired_trial_less_than_10_users( @freeze_time("2023-06-19") class AvailablePlansExpiredTrialMoreThanTenActivatedUsers(TestCase): """ - - users-pr-inappm/y, has trialed, more than 10 activated users -> users-pr-inappm/y, DEFAULT_FREE_PLAN - - sentry customer, DEFAULT_FREE_PLAN, has trialed, more than 10 activated users -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN - - sentry customer, users-sentrym/y, has trialed, more than 10 activated users -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN + - users-pr-inappm/y, has trialed, more than 10 activated users -> users-pr-inappm/y, DEFAULT_FREE_PLAN + - sentry customer, DEFAULT_FREE_PLAN, has trialed, more than 10 activated users -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN + - sentry customer, users-sentrym/y, has trialed, more than 10 activated users -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN """ @classmethod @@ -912,11 +912,11 @@ def test_trial_not_started(self): class AvailablePlansOngoingTrial(TestCase): """ Non Sentry User is trialing - when <=10 activated seats -> users-pr-inappm/y, DEFAULT_FREE_PLAN, users-teamm/y - when > 10 activated seats -> users-pr-inappm/y, DEFAULT_FREE_PLAN + when <=10 activated seats -> users-pr-inappm/y, DEFAULT_FREE_PLAN, users-teamm/y + when > 10 activated seats -> users-pr-inappm/y, DEFAULT_FREE_PLAN Sentry User is trialing - when <=10 activated seats -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN, users-teamm/y - when > 10 activated seats -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN + when <=10 activated seats -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN, users-teamm/y + when > 10 activated seats -> users-pr-inappm/y, users-sentrym/y, DEFAULT_FREE_PLAN """ @classmethod diff --git a/tests/unit/test_router.py b/tests/unit/test_router.py index ae1e2fd93..c5b5a60a6 100644 --- a/tests/unit/test_router.py +++ b/tests/unit/test_router.py @@ -9,9 +9,6 @@ def test_route_tasks_based_on_user_plan_defaults(): assert route_tasks_based_on_user_plan( upload_task_name, BillingPlan.users_basic.db_name ) == {"queue": "celery", "extra_config": {}} - assert route_tasks_based_on_user_plan( - upload_task_name, BillingPlan.users_developer.db_name - ) == {"queue": "celery", "extra_config": {}} assert route_tasks_based_on_user_plan( upload_task_name, BillingPlan.enterprise_cloud_monthly.db_name ) == {"queue": "enterprise_celery", "extra_config": {}}