From a233b4861fb77ba58e666050bafa71f456ff5aa1 Mon Sep 17 00:00:00 2001 From: Matthew Elwell Date: Thu, 30 Jan 2025 15:31:11 +0000 Subject: [PATCH 1/3] Use relative delta and months, instead of days --- api/organisations/tasks.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/api/organisations/tasks.py b/api/organisations/tasks.py index 25efa8911804..7ce6828cedf6 100644 --- a/api/organisations/tasks.py +++ b/api/organisations/tasks.py @@ -3,6 +3,7 @@ from datetime import timedelta from app_analytics.influxdb_wrapper import get_current_api_usage +from dateutil.relativedelta import relativedelta from django.conf import settings from django.core.mail import send_mail from django.db.models import F, Max, Q @@ -154,7 +155,7 @@ def charge_for_api_call_count_overages(): # Get the period where we're interested in any new API usage # notifications for the relevant billing period (ie, this month). - api_usage_notified_at = now - timedelta(days=30) + api_usage_notified_at = now - relativedelta(months=1) # Since we're only interested in monthly billed accounts, set a wide # threshold to catch as many billing periods that could be roughly @@ -210,7 +211,7 @@ def charge_for_api_call_count_overages(): continue subscription_cache = organisation.subscription_information_cache - api_usage = get_current_api_usage(organisation.id) + api_usage = get_current_api_usage(7201) # Grace period for organisations < 200% of usage. if ( From 2527ff5480751cf845b2bb0802c6de147ea2efae Mon Sep 17 00:00:00 2001 From: Matthew Elwell Date: Thu, 30 Jan 2025 15:47:22 +0000 Subject: [PATCH 2/3] Remove hardcoded org id --- api/organisations/tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/organisations/tasks.py b/api/organisations/tasks.py index 7ce6828cedf6..e4132b5509ae 100644 --- a/api/organisations/tasks.py +++ b/api/organisations/tasks.py @@ -211,7 +211,7 @@ def charge_for_api_call_count_overages(): continue subscription_cache = organisation.subscription_information_cache - api_usage = get_current_api_usage(7201) + api_usage = get_current_api_usage(organisation.id) # Grace period for organisations < 200% of usage. if ( From 82b6967d118238b58470e30e87bc09ce3f4dabc5 Mon Sep 17 00:00:00 2001 From: Matthew Elwell Date: Tue, 11 Feb 2025 11:31:27 +0000 Subject: [PATCH 3/3] Update existing test --- .../organisations/test_unit_organisations_tasks.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/api/tests/unit/organisations/test_unit_organisations_tasks.py b/api/tests/unit/organisations/test_unit_organisations_tasks.py index a96d7c6ce1f6..4f8d7d081053 100644 --- a/api/tests/unit/organisations/test_unit_organisations_tasks.py +++ b/api/tests/unit/organisations/test_unit_organisations_tasks.py @@ -5,6 +5,7 @@ import pytest from core.helpers import get_current_site_url +from dateutil.relativedelta import relativedelta from django.core.mail.message import EmailMultiAlternatives from django.template.loader import render_to_string from django.utils import timezone @@ -834,10 +835,19 @@ def test_charge_for_api_call_count_overages_scale_up( organisation.subscription.subscription_id = "fancy_sub_id23" organisation.subscription.plan = "scale-up-v2" organisation.subscription.save() + + # In order to cover an edge case found in production use, we make the + # notification date just outside the previous 30 days, because we want + # to make sure that we cover the case where someone with very high usage + # is notified in the first day of their subscription period (in a 31-day + # month). + notification_date = now - (timedelta(days=30) + timedelta(minutes=30)) + assert notification_date > now - relativedelta(months=1) + OrganisationAPIUsageNotification.objects.create( organisation=organisation, percent_usage=100, - notified_at=now, + notified_at=notification_date, ) mocker.patch("organisations.chargebee.chargebee.chargebee.Subscription.retrieve")