Skip to content
This repository was archived by the owner on Jun 13, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions api/internal/owner/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,13 @@ def retrieve(self, *args, **kwargs):
return res

@stripe_safe
def update(self, *args, **kwargs):
return super().update(*args, **kwargs)
def update(self, request, *args, **kwargs):
# # Temporary fix. Remove once Gazebo uses the new free plan
# plan_value = request.data.get("plan", {}).get("value")
# if plan_value == "users-basic":
# request.data["plan"]["value"] = DEFAULT_FREE_PLAN

return super().update(request, *args, **kwargs)

def destroy(self, request, *args, **kwargs):
if self.owner.ownerid != request.current_owner.ownerid:
Expand Down
26 changes: 13 additions & 13 deletions api/internal/tests/views/test_account_viewset.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
OwnerFactory,
UserFactory,
)
from shared.plan.constants import PlanName, TrialStatus
from shared.plan.constants import DEFAULT_FREE_PLAN, PlanName, TrialStatus
from stripe import StripeError

from api.internal.tests.test_utils import GetAdminProviderAdapter
Expand Down Expand Up @@ -164,7 +164,7 @@ def test_retrieve_account_gets_account_fields(self):
"inactive_user_count": 1,
"plan": {
"marketing_name": "Developer",
"value": PlanName.BASIC_PLAN_NAME.value,
"value": DEFAULT_FREE_PLAN,
"billing_rate": None,
"base_unit_price": 0,
"benefits": [
Expand Down Expand Up @@ -249,7 +249,7 @@ def test_retrieve_account_gets_account_fields_when_there_are_scheduled_details(
"plan_provider": owner.plan_provider,
"plan": {
"marketing_name": "Developer",
"value": PlanName.BASIC_PLAN_NAME.value,
"value": DEFAULT_FREE_PLAN,
"billing_rate": None,
"base_unit_price": 0,
"benefits": [
Expand Down Expand Up @@ -346,7 +346,7 @@ def test_retrieve_account_returns_last_phase_when_more_than_one_scheduled_phases
"inactive_user_count": 1,
"plan": {
"marketing_name": "Developer",
"value": PlanName.BASIC_PLAN_NAME.value,
"value": DEFAULT_FREE_PLAN,
"billing_rate": None,
"base_unit_price": 0,
"benefits": [
Expand Down Expand Up @@ -420,7 +420,7 @@ def test_retrieve_account_gets_none_for_schedule_details_when_schedule_is_nonexi
"inactive_user_count": 1,
"plan": {
"marketing_name": "Developer",
"value": PlanName.BASIC_PLAN_NAME.value,
"value": DEFAULT_FREE_PLAN,
"billing_rate": None,
"base_unit_price": 0,
"benefits": [
Expand Down Expand Up @@ -488,13 +488,13 @@ def test_retrieve_account_gets_account_students(self):
}

def test_account_with_free_user_plan(self):
self.current_owner.plan = PlanName.BASIC_PLAN_NAME.value
self.current_owner.plan = DEFAULT_FREE_PLAN
self.current_owner.save()
response = self._retrieve()
assert response.status_code == status.HTTP_200_OK
assert response.data["plan"] == {
"marketing_name": "Developer",
"value": PlanName.BASIC_PLAN_NAME.value,
"value": DEFAULT_FREE_PLAN,
"billing_rate": None,
"base_unit_price": 0,
"benefits": [
Expand Down Expand Up @@ -690,7 +690,7 @@ def test_update_can_set_plan_auto_activate_on_org_with_account(self):
assert self.current_owner.plan_auto_activate is False
assert response.data["plan_auto_activate"] is False

def test_update_can_set_plan_to_users_basic(self):
def test_update_can_set_plan_to_users_developer_should_set_to_developer(self):
self.current_owner.plan = PlanName.CODECOV_PRO_YEARLY.value
self.current_owner.save()

Expand All @@ -699,14 +699,14 @@ def test_update_can_set_plan_to_users_basic(self):
"service": self.current_owner.service,
"owner_username": self.current_owner.username,
},
data={"plan": {"value": PlanName.BASIC_PLAN_NAME.value}},
data={"plan": {"value": DEFAULT_FREE_PLAN}},
)

assert response.status_code == status.HTTP_200_OK

self.current_owner.refresh_from_db()

assert self.current_owner.plan == PlanName.BASIC_PLAN_NAME.value
assert self.current_owner.plan == DEFAULT_FREE_PLAN
assert self.current_owner.plan_activated_users is None
assert self.current_owner.plan_user_count == 1
assert response.data["plan_auto_activate"] is True
Expand Down Expand Up @@ -963,7 +963,7 @@ def test_update_must_fail_if_quantity_and_plan_are_equal_to_the_owners_current_o
)

def test_update_team_plan_must_fail_if_too_many_activated_users_during_trial(self):
self.current_owner.plan = PlanName.BASIC_PLAN_NAME.value
self.current_owner.plan = DEFAULT_FREE_PLAN
self.current_owner.plan_user_count = 1
self.current_owner.trial_status = TrialStatus.ONGOING.value
self.current_owner.plan_activated_users = list(range(11))
Expand All @@ -987,7 +987,7 @@ def test_update_team_plan_must_fail_if_too_many_activated_users_during_trial(sel
assert response.json() == {
"plan": {
"value": [
f"Invalid value for plan: {desired_plan['value']}; must be one of ['users-basic', 'users-pr-inappm', 'users-pr-inappy']"
f"Invalid value for plan: {desired_plan['value']}; must be one of ['users-pr-inappm', '{DEFAULT_FREE_PLAN}', 'users-pr-inappy']"
]
}
}
Expand Down Expand Up @@ -1567,7 +1567,7 @@ def test_update_sentry_plan_non_sentry_user(
assert res.json() == {
"plan": {
"value": [
"Invalid value for plan: users-sentrym; must be one of ['users-basic', 'users-pr-inappm', 'users-pr-inappy', 'users-teamm', 'users-teamy']"
f"Invalid value for plan: users-sentrym; must be one of ['users-pr-inappm', 'users-pr-inappy', 'users-teamm', 'users-teamy', '{DEFAULT_FREE_PLAN}']"
]
}
}
Expand Down
28 changes: 16 additions & 12 deletions billing/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from django.db.models import QuerySet
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 PlanName, PlanPrice, TierName
from shared.plan.constants import DEFAULT_FREE_PLAN, PlanName, PlanPrice, TierName

from codecov_auth.models import Owner, Plan

Expand Down Expand Up @@ -42,17 +42,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,
Expand Down Expand Up @@ -187,3 +176,18 @@ def mock_all_plans_and_tiers():
"Priority Support",
],
)

PlanFactory(
name=DEFAULT_FREE_PLAN,
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",
],
)
14 changes: 7 additions & 7 deletions billing/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from rest_framework.reverse import reverse
from rest_framework.test import APIRequestFactory, APITestCase
from shared.django_apps.core.tests.factories import OwnerFactory, RepositoryFactory
from shared.plan.constants import PlanName
from shared.plan.constants import DEFAULT_FREE_PLAN, PlanName

from billing.helpers import mock_all_plans_and_tiers

Expand Down Expand Up @@ -494,7 +494,7 @@ def test_customer_subscription_deleted_sets_plan_to_free(self):
)
self.owner.refresh_from_db()

assert self.owner.plan == PlanName.BASIC_PLAN_NAME.value
assert self.owner.plan == DEFAULT_FREE_PLAN
assert self.owner.plan_user_count == 1
assert self.owner.plan_activated_users is None
assert self.owner.stripe_subscription_id is None
Expand Down Expand Up @@ -523,12 +523,12 @@ def test_customer_subscription_deleted_sets_plan_to_free_mutliple_owner(self):
self.owner.refresh_from_db()
self.other_owner.refresh_from_db()

assert self.owner.plan == PlanName.BASIC_PLAN_NAME.value
assert self.owner.plan == DEFAULT_FREE_PLAN
assert self.owner.plan_user_count == 1
assert self.owner.plan_activated_users is None
assert self.owner.stripe_subscription_id is None

assert self.other_owner.plan == PlanName.BASIC_PLAN_NAME.value
assert self.other_owner.plan == DEFAULT_FREE_PLAN
assert self.other_owner.plan_user_count == 1
assert self.other_owner.plan_activated_users is None
assert self.other_owner.stripe_subscription_id is None
Expand Down Expand Up @@ -874,7 +874,7 @@ def test_customer_subscription_updated_sets_free_and_deactivates_all_repos_if_in
)
self.owner.refresh_from_db()

assert self.owner.plan == PlanName.BASIC_PLAN_NAME.value
assert self.owner.plan == DEFAULT_FREE_PLAN
assert self.owner.plan_user_count == 1
assert self.owner.plan_auto_activate == False
assert self.owner.stripe_subscription_id is None
Expand Down Expand Up @@ -969,14 +969,14 @@ def test_customer_subscription_updated_sets_free_and_deactivates_all_repos_if_in
self.owner.refresh_from_db()
self.other_owner.refresh_from_db()

assert self.owner.plan == PlanName.BASIC_PLAN_NAME.value
assert self.owner.plan == DEFAULT_FREE_PLAN
assert self.owner.plan_user_count == 1
assert self.owner.plan_auto_activate == False
assert self.owner.stripe_subscription_id is None
assert (
self.owner.repository_set.filter(active=True, activated=True).count() == 0
)
assert self.other_owner.plan == PlanName.BASIC_PLAN_NAME.value
assert self.other_owner.plan == DEFAULT_FREE_PLAN
assert self.other_owner.plan_user_count == 1
assert self.other_owner.plan_auto_activate == False
assert self.other_owner.stripe_subscription_id is None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from shared.django_apps.codecov.commands.exceptions import ValidationError
from shared.django_apps.codecov_auth.tests.factories import PlanFactory, TierFactory
from shared.django_apps.core.tests.factories import OwnerFactory
from shared.plan.constants import PlanName, TierName, TrialStatus
from shared.plan.constants import DEFAULT_FREE_PLAN, PlanName, TierName, TrialStatus

from codecov.commands.exceptions import Unauthorized
from codecov.commands.exceptions import ValidationError as CodecovValidationError
Expand All @@ -18,7 +18,7 @@

class CancelTrialInteractorTest(TransactionTestCase):
def setUp(self):
self.tier = TierFactory(tier_name=TierName.BASIC.value)
self.tier = TierFactory(tier_name=DEFAULT_FREE_PLAN)
self.plan = PlanFactory(tier=self.tier)

@async_to_sync
Expand Down Expand Up @@ -103,7 +103,7 @@ def test_cancel_trial_starts_trial_for_org_that_has_trial_ongoing(self):
now = datetime.now()
assert current_user.trial_end_date == now
assert current_user.trial_status == TrialStatus.EXPIRED.value
assert current_user.plan == PlanName.BASIC_PLAN_NAME.value
assert current_user.plan == DEFAULT_FREE_PLAN
assert current_user.plan_activated_users is None
assert current_user.plan_user_count == 1
assert current_user.stripe_subscription_id is None
34 changes: 17 additions & 17 deletions codecov_auth/tests/test_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
)
from shared.django_apps.core.tests.factories import PullFactory, RepositoryFactory
from shared.plan.constants import (
DEFAULT_FREE_PLAN,
ENTERPRISE_CLOUD_USER_PLAN_REPRESENTATIONS,
PlanName,
)
Expand Down Expand Up @@ -74,10 +75,8 @@ def test_owner_admin_detail_page(self):
self.assertEqual(response.status_code, 200)

def test_owner_admin_impersonate_owner(self):
owner_to_impersonate = OwnerFactory(
service="bitbucket", plan=PlanName.BASIC_PLAN_NAME.value
)
other_owner = OwnerFactory(plan=PlanName.BASIC_PLAN_NAME.value)
owner_to_impersonate = OwnerFactory(service="bitbucket", plan=DEFAULT_FREE_PLAN)
other_owner = OwnerFactory(plan=DEFAULT_FREE_PLAN)

with self.subTest("more than one user selected"):
response = self.client.post(
Expand Down Expand Up @@ -111,7 +110,7 @@ def test_owner_admin_impersonate_owner(self):

@patch("codecov_auth.admin.TaskService.delete_owner")
def test_delete_queryset(self, delete_mock):
user_to_delete = OwnerFactory(plan=PlanName.BASIC_PLAN_NAME.value)
user_to_delete = OwnerFactory(plan=DEFAULT_FREE_PLAN)
ownerid = user_to_delete.ownerid
queryset = MagicMock()
queryset.__iter__.return_value = [user_to_delete]
Expand All @@ -122,14 +121,14 @@ def test_delete_queryset(self, delete_mock):

@patch("codecov_auth.admin.TaskService.delete_owner")
def test_delete_model(self, delete_mock):
user_to_delete = OwnerFactory(plan=PlanName.BASIC_PLAN_NAME.value)
user_to_delete = OwnerFactory(plan=DEFAULT_FREE_PLAN)
ownerid = user_to_delete.ownerid
self.owner_admin.delete_model(MagicMock(), user_to_delete)
delete_mock.assert_called_once_with(ownerid=ownerid)

@patch("codecov_auth.admin.admin.ModelAdmin.get_deleted_objects")
def test_confirmation_deleted_objects(self, mocked_deleted_objs):
user_to_delete = OwnerFactory(plan=PlanName.BASIC_PLAN_NAME.value)
user_to_delete = OwnerFactory(plan=DEFAULT_FREE_PLAN)
deleted_objs = [
'Owner: <a href="/admin/codecov_auth/owner/{}/change/">{};</a>'.format(
user_to_delete.ownerid, user_to_delete
Expand All @@ -149,7 +148,7 @@ def test_confirmation_deleted_objects(self, mocked_deleted_objs):

@patch("codecov_auth.admin.admin.ModelAdmin.log_change")
def test_prev_and_new_values_in_log_entry(self, mocked_super_log_change):
owner = OwnerFactory(staff=True, plan=PlanName.BASIC_PLAN_NAME.value)
owner = OwnerFactory(staff=True, plan=DEFAULT_FREE_PLAN)
owner.save()
owner.staff = False
form = MagicMock()
Expand All @@ -169,7 +168,7 @@ def test_prev_and_new_values_in_log_entry(self, mocked_super_log_change):
]

def test_inline_orgwide_tokens_display(self):
owner = OwnerFactory(plan=PlanName.BASIC_PLAN_NAME.value)
owner = OwnerFactory(plan=DEFAULT_FREE_PLAN)
request_url = reverse("admin:codecov_auth_owner_change", args=[owner.ownerid])
request = RequestFactory().get(request_url)
request.user = self.staff_user
Expand Down Expand Up @@ -202,7 +201,7 @@ def test_inline_orgwide_permissions(self):
def test_inline_orgwide_add_token_permission_no_token_and_user_in_enterprise_cloud_plan(
self,
):
owner = OwnerFactory(plan=PlanName.BASIC_PLAN_NAME.value)
owner = OwnerFactory(plan=DEFAULT_FREE_PLAN)
assert owner.plan not in ENTERPRISE_CLOUD_USER_PLAN_REPRESENTATIONS
assert OrganizationLevelToken.objects.filter(owner=owner).count() == 0
request_url = reverse("admin:codecov_auth_owner_change", args=[owner.ownerid])
Expand Down Expand Up @@ -305,7 +304,7 @@ def test_org_token_request_doesnt_call_service_to_refresh_token(self, mock_refre
mock_refresh.assert_not_called()

def test_start_trial_ui_display(self):
owner = OwnerFactory(plan=PlanName.BASIC_PLAN_NAME.value)
owner = OwnerFactory(plan=DEFAULT_FREE_PLAN)

res = self.client.post(
reverse("admin:codecov_auth_owner_changelist"),
Expand All @@ -320,7 +319,7 @@ def test_start_trial_ui_display(self):
@patch("shared.plan.service.PlanService.start_trial_manually")
def test_start_trial_action(self, mock_start_trial_service):
mock_start_trial_service.return_value = None
org_to_be_trialed = OwnerFactory(plan=PlanName.BASIC_PLAN_NAME.value)
org_to_be_trialed = OwnerFactory(plan=DEFAULT_FREE_PLAN)

res = self.client.post(
reverse("admin:codecov_auth_owner_changelist"),
Expand All @@ -337,7 +336,7 @@ def test_start_trial_action(self, mock_start_trial_service):
@patch("shared.plan.service.PlanService._start_trial_helper")
def test_extend_trial_action(self, mock_start_trial_service):
mock_start_trial_service.return_value = None
org_to_be_trialed = OwnerFactory(plan=PlanName.BASIC_PLAN_NAME.value)
org_to_be_trialed = OwnerFactory(plan=DEFAULT_FREE_PLAN)
org_to_be_trialed.plan = PlanName.TRIAL_PLAN_NAME.value
org_to_be_trialed.save()

Expand All @@ -360,7 +359,7 @@ def test_start_trial_paid_plan(self, mock_start_trial_service):
"Cannot trial from a paid plan"
)

org_to_be_trialed = OwnerFactory(plan=PlanName.BASIC_PLAN_NAME.value)
org_to_be_trialed = OwnerFactory(plan=DEFAULT_FREE_PLAN)

res = self.client.post(
reverse("admin:codecov_auth_owner_changelist"),
Expand Down Expand Up @@ -581,7 +580,8 @@ def test_detail_page(self):
self.assertEqual(res.status_code, 200)
decoded_res = res.content.decode("utf-8")
self.assertIn(
'<option value="users-basic" selected>BASIC_PLAN_NAME</option>', decoded_res
'<option value="users-developer" selected>USERS_DEVELOPER</option>',
decoded_res,
)
self.assertIn("Organizations (read only)", decoded_res)
self.assertIn("Stripe Billing (click save to commit changes)", decoded_res)
Expand Down Expand Up @@ -910,7 +910,7 @@ def setUp(self):
admin_site.register(Plan)

self.tier = TierFactory()
self.plan = PlanFactory(name=PlanName.BASIC_PLAN_NAME.value, tier=self.tier)
self.plan = PlanFactory(name=DEFAULT_FREE_PLAN, tier=self.tier)

def test_plan_admin_modal_display(self):
response = self.client.get(
Expand Down Expand Up @@ -1016,7 +1016,7 @@ def setUp(self):
admin_site.register(Tier)

self.tier = TierFactory()
self.plan = PlanFactory(name=PlanName.BASIC_PLAN_NAME.value, tier=self.tier)
self.plan = PlanFactory(name=DEFAULT_FREE_PLAN, tier=self.tier)

def test_tier_modal_plans_display(self):
response = self.client.get(
Expand Down
Loading
Loading