Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Handle cancellation date for api usage #4672

Merged
merged 3 commits into from
Sep 30, 2024
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
7 changes: 5 additions & 2 deletions api/organisations/task_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,12 @@ def _send_api_usage_notification(
def handle_api_usage_notification_for_organisation(organisation: Organisation) -> None:
now = timezone.now()

if organisation.subscription.is_free_plan:
if (
organisation.subscription.is_free_plan
or organisation.subscription.cancellation_date is not None
):
allowed_api_calls = organisation.subscription.max_api_calls
# Default to a rolling month for free accounts
# Default to a rolling month for free accounts or canceled subscriptions.
days = 30
period_starts_at = now - timedelta(days)
elif not organisation.has_subscription_information_cache():
Expand Down
3 changes: 2 additions & 1 deletion api/organisations/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,8 @@ def charge_for_api_call_count_overages():
- month_window_end,
)
.exclude(
subscription__plan=FREE_PLAN_ID,
Q(subscription__plan=FREE_PLAN_ID)
| Q(subscription__cancellation_date__isnull=False),
)
.select_related(
"subscription_information_cache",
Expand Down
71 changes: 71 additions & 0 deletions api/tests/unit/organisations/test_unit_organisations_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,33 @@ def test_handle_api_usage_notification_for_organisation_when_billing_starts_at_i
]


def test_handle_api_usage_notification_for_organisation_when_cancellation_date_is_set(
organisation: Organisation,
inspecting_handler: logging.Handler,
mocker: MockerFixture,
) -> None:
# Given
organisation.subscription.plan = SCALE_UP
organisation.subscription.subscription_id = "fancy_id"
organisation.subscription.cancellation_date = timezone.now()
organisation.subscription.save()
mock_api_usage = mocker.patch("organisations.task_helpers.get_current_api_usage")
mock_api_usage.return_value = 25
from organisations.task_helpers import logger

logger.addHandler(inspecting_handler)

# When
result = handle_api_usage_notification_for_organisation(organisation)

# Then
assert result is None
assert OrganisationAPIUsageNotification.objects.count() == 0

# Check to ensure that error messages haven't been set.
assert inspecting_handler.messages == []


@pytest.mark.freeze_time("2023-01-19T09:09:47.325132+00:00")
def test_handle_api_usage_notifications_when_feature_flag_is_off(
mocker: MockerFixture,
Expand Down Expand Up @@ -855,6 +882,50 @@ def test_charge_for_api_call_count_overages_scale_up(
assert api_billing.billed_at == now


@pytest.mark.freeze_time("2023-01-19T09:09:47.325132+00:00")
def test_charge_for_api_call_count_overages_cancellation_date(
organisation: Organisation,
mocker: MockerFixture,
) -> None:
# Given
now = timezone.now()
OrganisationSubscriptionInformationCache.objects.create(
organisation=organisation,
allowed_seats=10,
allowed_projects=3,
allowed_30d_api_calls=100_000,
chargebee_email="[email protected]",
current_billing_term_starts_at=now - timedelta(days=30),
current_billing_term_ends_at=now + timedelta(minutes=30),
)
organisation.subscription.subscription_id = "fancy_sub_id23"
organisation.subscription.plan = "scale-up-v2"
organisation.subscription.cancellation_date = timezone.now()
organisation.subscription.save()
OrganisationAPIUsageNotification.objects.create(
organisation=organisation,
percent_usage=100,
notified_at=now,
)

get_client_mock = mocker.patch("organisations.tasks.get_client")
client_mock = MagicMock()
get_client_mock.return_value = client_mock

mock_api_usage = mocker.patch(
"organisations.tasks.get_current_api_usage",
)
assert OrganisationAPIBilling.objects.count() == 0

# When
charge_for_api_call_count_overages()

# Then
assert OrganisationAPIBilling.objects.count() == 0
mock_api_usage.assert_not_called()
client_mock.get_identity_flags.assert_not_called()


@pytest.mark.freeze_time("2023-01-19T09:09:47.325132+00:00")
def test_charge_for_api_call_count_overages_scale_up_when_flagsmith_client_sets_is_enabled_to_false(
organisation: Organisation,
Expand Down
Loading