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

add pending stats to daily stats endpoint #1493

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f4e68d7
add pending stats
heyitsmebev Dec 20, 2024
a520e02
Merge branch 'main' into 2199-add-pending-message-data-to-daily-and-u…
heyitsmebev Dec 20, 2024
67a5662
update pending count
heyitsmebev Dec 31, 2024
1f62b99
Merge branch 'main' into 2199-add-pending-message-data-to-daily-and-u…
heyitsmebev Jan 7, 2025
05055aa
Updated query
xlorepdarkhelm Jan 8, 2025
37fa118
Adding group by clause to outer query for function.
xlorepdarkhelm Jan 9, 2025
8656c44
Make sure join is correct table.
xlorepdarkhelm Jan 9, 2025
b6337ad
updating pending count
heyitsmebev Jan 10, 2025
f1cc6aa
estructuring how to get total_notifications.
xlorepdarkhelm Jan 10, 2025
ef61069
black cleanup.
xlorepdarkhelm Jan 10, 2025
bc80841
Changing the queries again.
xlorepdarkhelm Jan 10, 2025
162823e
Query fixing.
xlorepdarkhelm Jan 10, 2025
9219049
Cleaning up function a bit.
xlorepdarkhelm Jan 10, 2025
b543db4
Moving where the pending calculation is done.
xlorepdarkhelm Jan 10, 2025
467357c
Getting total notifications per day made.
xlorepdarkhelm Jan 10, 2025
3f8c49d
Removing total_notification calculations.
xlorepdarkhelm Jan 10, 2025
7ef8081
pending count
heyitsmebev Jan 11, 2025
30dfc6a
pending count
heyitsmebev Jan 11, 2025
af46a67
cleaningu up pending
heyitsmebev Jan 11, 2025
50a183f
flake
heyitsmebev Jan 11, 2025
2eef7ab
remove comments
heyitsmebev Jan 11, 2025
fa00bd1
isort
heyitsmebev Jan 11, 2025
dd3c277
fix testing
heyitsmebev Jan 11, 2025
b224065
fix testing
heyitsmebev Jan 13, 2025
88c3da5
add testing
heyitsmebev Jan 13, 2025
880237f
fix tuples
heyitsmebev Jan 15, 2025
1fc78d8
Merge branch 'main' into 2199-add-pending-message-data-to-daily-and-u…
heyitsmebev Jan 22, 2025
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
88 changes: 80 additions & 8 deletions app/dao/services_dao.py
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,35 @@ def dao_fetch_stats_for_service_from_days(service_id, start_date, end_date):
start_date = get_midnight_in_utc(start_date)
end_date = get_midnight_in_utc(end_date + timedelta(days=1))

total_substmt = (
select(
func.date_trunc("day", NotificationAllTimeView.created_at).label("day"),
Job.notification_count.label("notification_count"),
)
.join(Job, NotificationAllTimeView.job_id == Job.id)
.where(
NotificationAllTimeView.service_id == service_id,
NotificationAllTimeView.key_type != KeyType.TEST,
NotificationAllTimeView.created_at >= start_date,
NotificationAllTimeView.created_at < end_date,
)
.group_by(
Job.id,
Job.notification_count,
func.date_trunc("day", NotificationAllTimeView.created_at),
)
.subquery()
)

total_stmt = select(
total_substmt.c.day,
func.sum(total_substmt.c.notification_count).label("total_notifications"),
).group_by(total_substmt.c.day)

total_notifications = {
row.day: row.total_notifications for row in db.session.execute(total_stmt).all()
}

stmt = (
select(
NotificationAllTimeView.notification_type,
Expand All @@ -488,7 +517,10 @@ def dao_fetch_stats_for_service_from_days(service_id, start_date, end_date):
func.date_trunc("day", NotificationAllTimeView.created_at),
)
)
return db.session.execute(stmt).all()

data = db.session.execute(stmt).all()
ccostino marked this conversation as resolved.
Show resolved Hide resolved

return total_notifications, data
ccostino marked this conversation as resolved.
Show resolved Hide resolved


def dao_fetch_stats_for_service_from_days_for_user(
Expand All @@ -497,14 +529,43 @@ def dao_fetch_stats_for_service_from_days_for_user(
start_date = get_midnight_in_utc(start_date)
end_date = get_midnight_in_utc(end_date + timedelta(days=1))

total_substmt = (
select(
func.date_trunc("day", NotificationAllTimeView.created_at).label("day"),
Job.notification_count.label("notification_count"),
)
.join(Job, NotificationAllTimeView.job_id == Job.id)
.where(
NotificationAllTimeView.service_id == service_id,
NotificationAllTimeView.key_type != KeyType.TEST,
NotificationAllTimeView.created_at >= start_date,
NotificationAllTimeView.created_at < end_date,
NotificationAllTimeView.created_by_id == user_id,
)
.group_by(
Job.id,
Job.notification_count,
func.date_trunc("day", NotificationAllTimeView.created_at),
)
.subquery()
)

total_stmt = select(
total_substmt.c.day,
func.sum(total_substmt.c.notification_count).label("total_notifications"),
).group_by(total_substmt.c.day)

total_notifications = {
row.day: row.total_notifications for row in db.session.execute(total_stmt).all()
ccostino marked this conversation as resolved.
Show resolved Hide resolved
}

stmt = (
select(
NotificationAllTimeView.notification_type,
NotificationAllTimeView.status,
func.date_trunc("day", NotificationAllTimeView.created_at).label("day"),
func.count(NotificationAllTimeView.id).label("count"),
)
.select_from(NotificationAllTimeView)
.where(
NotificationAllTimeView.service_id == service_id,
NotificationAllTimeView.key_type != KeyType.TEST,
Expand All @@ -518,7 +579,10 @@ def dao_fetch_stats_for_service_from_days_for_user(
func.date_trunc("day", NotificationAllTimeView.created_at),
)
)
return db.session.execute(stmt).scalars().all()

data = db.session.execute(stmt).all()
xlorepdarkhelm marked this conversation as resolved.
Show resolved Hide resolved

return total_notifications, data
xlorepdarkhelm marked this conversation as resolved.
Show resolved Hide resolved


def dao_fetch_todays_stats_for_all_services(
Expand Down Expand Up @@ -734,7 +798,9 @@ def fetch_notification_stats_for_service_by_month_by_user(
return db.session.execute(stmt).all()


def get_specific_days_stats(data, start_date, days=None, end_date=None):
def get_specific_days_stats(
data, start_date, days=None, end_date=None, total_notifications=None
):
if days is not None and end_date is not None:
raise ValueError("Only set days OR set end_date, not both.")
elif days is not None:
Expand All @@ -745,13 +811,19 @@ def get_specific_days_stats(data, start_date, days=None, end_date=None):
raise ValueError("Either days or end_date must be set.")

grouped_data = {date: [] for date in gen_range} | {
day: [row for row in data if row.day.date() == day]
for day in {item.day.date() for item in data}
day: [row for row in data if row.day == day]
for day in {item.day for item in data}
}

stats = {
day.strftime("%Y-%m-%d"): statistics.format_statistics(rows)
day.strftime("%Y-%m-%d"): statistics.format_statistics(
rows,
total_notifications=(
total_notifications.get(day, 0)
if total_notifications is not None
else None
),
)
for day, rows in grouped_data.items()
}

return stats
1 change: 1 addition & 0 deletions app/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,3 +211,4 @@ class StatisticsType(StrEnum):
REQUESTED = "requested"
DELIVERED = "delivered"
FAILURE = "failure"
PENDING = "pending"
31 changes: 23 additions & 8 deletions app/service/rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,9 +232,18 @@ def get_service_statistics_for_specific_days(service_id, start, days=1):
end_date = datetime.strptime(start, "%Y-%m-%d")
start_date = end_date - timedelta(days=days - 1)

results = dao_fetch_stats_for_service_from_days(service_id, start_date, end_date)
total_notifications, results = dao_fetch_stats_for_service_from_days(
service_id,
start_date,
end_date,
)

stats = get_specific_days_stats(results, start_date, days=days)
stats = get_specific_days_stats(
results,
start_date,
days=days,
total_notifications=total_notifications,
)

return stats

Expand All @@ -261,12 +270,16 @@ def get_service_statistics_for_specific_days_by_user(
end_date = datetime.strptime(start, "%Y-%m-%d")
start_date = end_date - timedelta(days=days - 1)

results = dao_fetch_stats_for_service_from_days_for_user(
total_notifications, results = dao_fetch_stats_for_service_from_days_for_user(
service_id, start_date, end_date, user_id
)

stats = get_specific_days_stats(results, start_date, days=days)

stats = get_specific_days_stats(
results,
start_date,
days=days,
total_notifications=total_notifications,
)
return stats


Expand Down Expand Up @@ -676,11 +689,11 @@ def get_single_month_notification_stats_by_user(service_id, user_id):
month_year = datetime(year, month, 10, 00, 00, 00)
start_date, end_date = get_month_start_and_end_date_in_utc(month_year)

results = dao_fetch_stats_for_service_from_days_for_user(
total_notifications, results = dao_fetch_stats_for_service_from_days_for_user(
service_id, start_date, end_date, user_id
)

stats = get_specific_days_stats(results, start_date, end_date=end_date)
stats = get_specific_days_stats(results, start_date, end_date=end_date, total_notifications=total_notifications,)
return jsonify(stats)


Expand All @@ -700,7 +713,9 @@ def get_single_month_notification_stats_for_service(service_id):
month_year = datetime(year, month, 10, 00, 00, 00)
start_date, end_date = get_month_start_and_end_date_in_utc(month_year)

results = dao_fetch_stats_for_service_from_days(service_id, start_date, end_date)
__, results = dao_fetch_stats_for_service_from_days(
ccostino marked this conversation as resolved.
Show resolved Hide resolved
service_id, start_date, end_date
)

stats = get_specific_days_stats(results, start_date, end_date=end_date)
return jsonify(stats)
Expand Down
28 changes: 25 additions & 3 deletions app/service/statistics.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@
from datetime import datetime

from app.dao.date_util import get_months_for_financial_year
from app.enums import KeyType, NotificationStatus, StatisticsType, TemplateType
from app.enums import (
KeyType,
NotificationStatus,
NotificationType,
StatisticsType,
TemplateType,
)


def format_statistics(statistics):
def format_statistics(statistics, total_notifications=None):
# statistics come in a named tuple with uniqueness from 'notification_type', 'status' - however missing
# statuses/notification types won't be represented and the status types need to be simplified/summed up
# so we can return emails/sms * created, sent, and failed
Expand All @@ -14,11 +20,27 @@ def format_statistics(statistics):
# any row could be null, if the service either has no notifications in the notifications table,
# or no historical data in the ft_notification_status table.
if row.notification_type:
_update_statuses_from_row(counts[row.notification_type], row)
_update_statuses_from_row(
counts[row.notification_type],
row,
)

if NotificationType.SMS in counts and total_notifications is not None:
sms_dict = counts[NotificationType.SMS]
delivered_count = sms_dict[StatisticsType.DELIVERED]
failed_count = sms_dict[StatisticsType.FAILURE]
sms_dict[StatisticsType.PENDING] = calculate_pending_stats(
delivered_count, failed_count, total_notifications
)

return counts


def calculate_pending_stats(delivered_count, failed_count, total_notifications):
pending_count = total_notifications - (delivered_count + failed_count)
return max(0, pending_count)


def format_admin_stats(statistics):
counts = create_stats_dict()

Expand Down
Loading
Loading