Skip to content

Commit 66fc624

Browse files
authored
Merge pull request #1571 from GSA/fix_message_ratio_endpoint
Fix message ratio endpoint
2 parents b12216d + a834da4 commit 66fc624

File tree

9 files changed

+71
-35
lines changed

9 files changed

+71
-35
lines changed

app/dao/notifications_dao.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,44 @@ def dao_get_notification_count_for_service(*, service_id):
279279
return db.session.execute(stmt).scalar()
280280

281281

282+
def dao_get_notification_count_for_service_message_ratio(service_id, current_year):
283+
start_date = datetime(current_year, 1, 1)
284+
end_date = datetime(current_year + 1, 1, 1)
285+
stmt1 = (
286+
select(func.count())
287+
.select_from(Notification)
288+
.where(
289+
Notification.service_id == service_id,
290+
Notification.status
291+
not in [
292+
NotificationStatus.CANCELLED,
293+
NotificationStatus.CREATED,
294+
NotificationStatus.SENDING,
295+
],
296+
Notification.created_at >= start_date,
297+
Notification.created_at < end_date,
298+
)
299+
)
300+
stmt2 = (
301+
select(func.count())
302+
.select_from(NotificationHistory)
303+
.where(
304+
NotificationHistory.service_id == service_id,
305+
NotificationHistory.status
306+
not in [
307+
NotificationStatus.CANCELLED,
308+
NotificationStatus.CREATED,
309+
NotificationStatus.SENDING,
310+
],
311+
NotificationHistory.created_at >= start_date,
312+
NotificationHistory.created_at < end_date,
313+
)
314+
)
315+
recent_count = db.session.execute(stmt1).scalar_one()
316+
old_count = db.session.execute(stmt2).scalar_one()
317+
return recent_count + old_count
318+
319+
282320
def dao_get_failed_notification_count():
283321
stmt = select(func.count(Notification.id)).where(
284322
Notification.status == NotificationStatus.FAILED

app/job/rest.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
from zoneinfo import ZoneInfo
2+
13
import dateutil
2-
import pytz
34
from flask import Blueprint, current_app, jsonify, request
45

56
from app.aws.s3 import (
@@ -225,7 +226,7 @@ def get_scheduled_job_stats(service_id):
225226
jsonify(
226227
count=count,
227228
soonest_scheduled_for=(
228-
soonest_scheduled_for.replace(tzinfo=pytz.UTC).isoformat()
229+
soonest_scheduled_for.replace(tzinfo=ZoneInfo("UTC")).isoformat()
229230
if soonest_scheduled_for
230231
else None
231232
),

app/service/rest.py

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import itertools
22
from datetime import datetime, timedelta
3+
from zoneinfo import ZoneInfo
34

45
from flask import Blueprint, current_app, jsonify, request
56
from sqlalchemy import select
67
from sqlalchemy.exc import IntegrityError
78
from sqlalchemy.orm.exc import NoResultFound
89
from werkzeug.datastructures import MultiDict
910

10-
from app import db, redis_store
11+
from app import db
1112
from app.aws.s3 import get_personalisation_from_s3, get_phone_number_from_s3
1213
from app.config import QueueNames
1314
from app.dao import fact_notification_status_dao, notifications_dao
@@ -28,7 +29,10 @@
2829
fetch_stats_for_all_services_by_date_range,
2930
)
3031
from app.dao.inbound_numbers_dao import dao_allocate_number_for_service
31-
from app.dao.notifications_dao import dao_get_notification_count_for_service
32+
from app.dao.notifications_dao import (
33+
dao_get_notification_count_for_service,
34+
dao_get_notification_count_for_service_message_ratio,
35+
)
3236
from app.dao.organization_dao import dao_get_organization_by_service_id
3337
from app.dao.service_data_retention_dao import (
3438
fetch_service_data_retention,
@@ -109,7 +113,6 @@
109113
from app.service.utils import get_guest_list_objects
110114
from app.user.users_schema import post_set_permissions_schema
111115
from app.utils import get_prev_next_pagination_links, utc_now
112-
from notifications_utils.clients.redis import total_limit_cache_key
113116

114117
service_blueprint = Blueprint("service", __name__)
115118

@@ -1145,20 +1148,24 @@ def modify_service_data_retention(service_id, data_retention_id):
11451148
def get_service_message_ratio():
11461149
service_id = request.args.get("service_id")
11471150

1151+
current_year = datetime.now(tz=ZoneInfo("UTC")).year
11481152
my_service = dao_fetch_service_by_id(service_id)
1149-
1150-
cache_key = total_limit_cache_key(service_id)
1151-
messages_sent = redis_store.get(cache_key)
1152-
if messages_sent is None:
1153-
messages_sent = 0
1154-
current_app.logger.warning(
1155-
f"Messages sent was not being tracked for service {service_id}"
1153+
messages_sent = dao_get_notification_count_for_service_message_ratio(
1154+
service_id, current_year
1155+
)
1156+
messages_remaining = my_service.total_message_limit - messages_sent
1157+
1158+
if my_service.total_message_limit - messages_sent < 0:
1159+
raise Exception(
1160+
f"Math error get_service_message_ratio(), \
1161+
total {my_service.total_message_limit} \
1162+
messages_sent {messages_sent} remaining {messages_remaining} \
1163+
service_id {service_id} current_year {current_year}"
11561164
)
1157-
else:
1158-
messages_sent = int(messages_sent)
11591165

11601166
return {
11611167
"messages_sent": messages_sent,
1168+
"messages_remaining": messages_remaining,
11621169
"total_message_limit": my_service.total_message_limit,
11631170
}, 200
11641171

notifications_utils/timezones.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import os
2+
from zoneinfo import ZoneInfo
23

3-
import pytz
44
from dateutil import parser
55

6-
local_timezone = pytz.timezone(os.getenv("TIMEZONE", "America/New_York"))
6+
local_timezone = os.getenv("TIMEZONE", ZoneInfo("America/New_York"))
77

88

99
def utc_string_to_aware_gmt_datetime(date):
@@ -12,5 +12,5 @@ def utc_string_to_aware_gmt_datetime(date):
1212
Returns an aware local datetime, essentially the time you'd see on your clock
1313
"""
1414
date = parser.parse(date)
15-
forced_utc = date.replace(tzinfo=pytz.utc)
15+
forced_utc = date.replace(tzinfo=ZoneInfo("UTC"))
1616
return forced_utc.astimezone(local_timezone)

poetry.lock

Lines changed: 1 addition & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ numpy = "^1.26.4"
5656
ordered-set = "^4.1.0"
5757
phonenumbers = "^8.13.42"
5858
python-json-logger = "^2.0.7"
59-
pytz = "^2024.1"
6059
regex = "^2024.7.24"
6160
shapely = "^2.0.5"
6261
smartypants = "^2.0.1"

tests/app/conftest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import json
22
import uuid
33
from datetime import datetime, timedelta
4+
from zoneinfo import ZoneInfo
45

56
import pytest
6-
import pytz
77
import requests_mock
88
from flask import current_app, url_for
99
from sqlalchemy import delete, select
@@ -988,4 +988,4 @@ def delete(endpoint, _expected_status=204, **endpoint_kwargs):
988988

989989

990990
def datetime_in_past(days=0, seconds=0):
991-
return datetime.now(tz=pytz.utc) - timedelta(days=days, seconds=seconds)
991+
return datetime.now(tz=ZoneInfo("UTC")) - timedelta(days=days, seconds=seconds)

tests/app/job/test_rest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
import uuid
33
from datetime import date, datetime, timedelta
44
from unittest.mock import ANY
5+
from zoneinfo import ZoneInfo
56

67
import pytest
7-
import pytz
88
from freezegun import freeze_time
99

1010
import app.celery.tasks
@@ -183,7 +183,7 @@ def test_create_scheduled_job(client, sample_template, mocker, fake_uuid):
183183
assert resp_json["data"]["id"] == fake_uuid
184184
assert (
185185
resp_json["data"]["scheduled_for"]
186-
== datetime(2016, 1, 5, 11, 59, 0, tzinfo=pytz.UTC).isoformat()
186+
== datetime(2016, 1, 5, 11, 59, 0, tzinfo=ZoneInfo("UTC")).isoformat()
187187
)
188188
assert resp_json["data"]["job_status"] == JobStatus.SCHEDULED
189189
assert resp_json["data"]["template"] == str(sample_template.id)

tests/app/service/test_rest.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1668,7 +1668,9 @@ def test_remove_user_from_service(client, sample_user_service_permission):
16681668
def test_get_service_message_ratio(mocker, client, sample_user_service_permission):
16691669
service = sample_user_service_permission.service
16701670

1671-
mock_redis = mocker.patch("app.service.rest.redis_store.get")
1671+
mock_redis = mocker.patch(
1672+
"app.service.rest.dao_get_notification_count_for_service_message_ratio"
1673+
)
16721674
mock_redis.return_value = 1
16731675

16741676
endpoint = url_for(

0 commit comments

Comments
 (0)