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 all 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
10 changes: 8 additions & 2 deletions api/internal/owner/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from rest_framework.exceptions import PermissionDenied, ValidationError
from rest_framework.response import Response
from shared.django_apps.codecov_auth.models import Owner
from shared.plan.constants import DEFAULT_FREE_PLAN

from api.shared.mixins import OwnerPropertyMixin
from api.shared.owner.mixins import OwnerViewSetMixin, UserViewSetMixin
Expand Down Expand Up @@ -45,8 +46,13 @@
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

Check warning on line 53 in api/internal/owner/views.py

View check run for this annotation

Codecov Notifications / codecov/patch

api/internal/owner/views.py#L53

Added line #L53 was not covered by tests

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

def destroy(self, request, *args, **kwargs):
if self.owner.ownerid != request.current_owner.ownerid:
Expand Down
32 changes: 13 additions & 19 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 @@ -185,7 +185,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 @@ -270,7 +270,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 @@ -367,7 +367,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 @@ -441,7 +441,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 @@ -509,13 +509,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 @@ -711,7 +711,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 @@ -720,14 +720,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 @@ -984,7 +984,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 @@ -1005,13 +1005,7 @@ def test_update_team_plan_must_fail_if_too_many_activated_users_during_trial(sel
)

assert response.status_code == status.HTTP_400_BAD_REQUEST
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']"
]
}
}
assert "Invalid value for plan:" in response.json()["plan"]["value"][0]

def test_update_team_plan_must_fail_if_currently_team_plan_add_too_many_users(self):
self.current_owner.plan = PlanName.TEAM_MONTHLY.value
Expand Down Expand Up @@ -1602,7 +1596,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
from billing.views import StripeWebhookHandler
Expand Down Expand Up @@ -554,7 +554,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 @@ -584,12 +584,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 @@ -998,7 +998,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 @@ -1102,14 +1102,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
Loading
Loading