Restructured the query to be adhering to SQLAlchemy 2.0.

Signed-off-by: Cliff Hill <Clifford.hill@gsa.gov>
This commit is contained in:
Cliff Hill
2024-08-22 14:04:22 -04:00
parent 5d5ff72ca2
commit 05e27c7f3b

View File

@@ -1,9 +1,10 @@
from datetime import date, timedelta
from sqlalchemy import Date, case, func
from sqlalchemy import Date, case, func, select, union_all, cast
from sqlalchemy.dialects.postgresql import insert
from sqlalchemy.orm import aliased
from sqlalchemy.sql.expression import extract, literal
from sqlalchemy.types import DateTime, Integer
from sqlalchemy.types import DateTime, Integer, Text
from app import db
from app.dao.dao_utils import autocommit
@@ -126,83 +127,96 @@ def fetch_notification_status_for_service_for_day(fetch_day, service_id):
def fetch_notification_status_for_service_for_today_and_7_previous_days(
service_id, by_template=False, limit_days=7
):
service_id: str,
by_template: bool = False,
limit_days: int = 7
) -> list[dict | None]:
start_date = midnight_n_days_ago(limit_days)
now = utc_now()
stats_for_7_days = db.session.query(
FactNotificationStatus.notification_type.cast(db.Text).label(
"notification_type"
),
FactNotificationStatus.notification_status.cast(db.Text).label("status"),
# Query for the last 7 days
stats_for_7_days = select(
cast(FactNotificationStatus.notification_type, Text).label("notification_type"),
cast(FactNotificationStatus.notification_status, Text).label("status"),
*(
[
FactNotificationStatus.template_id.label("template_id"),
FactNotificationStatus.local_date.label("last_used"),
]
if by_template
else []
FactNotificationStatus.local_date.label("date_used"),
] if by_template else []
),
FactNotificationStatus.notification_count.label("count"),
).filter(
).where(
FactNotificationStatus.service_id == service_id,
FactNotificationStatus.local_date >= start_date,
FactNotificationStatus.key_type != KeyType.TEST,
)
stats_for_today = (
db.session.query(
Notification.notification_type.cast(db.Text),
Notification.status.cast(db.Text),
*(
[
Notification.template_id,
literal(date.today()).label("last_used"),
]
if by_template
else []
),
func.count().label("count"),
)
.filter(
Notification.created_at >= get_midnight_in_utc(now),
Notification.service_id == service_id,
Notification.key_type != KeyType.TEST,
)
.group_by(
Notification.notification_type,
*([Notification.template_id] if by_template else []),
Notification.status,
)
# Query for today's stats
stats_for_today = select(
cast(Notification.notification_type, Text),
cast(Notification.status, Text),
*(
[
Notification.template_id,
literal(date.today()).label("date_used"),
] if by_template else []
),
func.count().label("count"),
).where(
Notification.created_at >= get_midnight_in_utc(now),
Notification.service_id == service_id,
Notification.key_type != KeyType.TEST,
).group_by(
Notification.notification_type,
*([Notification.template_id] if by_template else []),
Notification.status,
)
all_stats_table = stats_for_7_days.union_all(stats_for_today).subquery()
# Combine the queries using union_all
all_stats_union = union_all(stats_for_7_days, stats_for_today).subquery()
all_stats_alias = aliased(all_stats_union)
query = db.session.query(
# Final query with optional template joins
query = select(
*(
[
Template.name.label("template_name"),
False, # TODO: this is related to is_precompiled_letter
all_stats_table.c.template_id,
Template.folder.name.label("folder"),
Template.created_by.name.label("created_by"),
]
if by_template
else []
False, # TODO: Handle `is_precompiled_letter`
all_stats_alias.c.template_id,
Template.folder.label("folder"),
Template.created_by.label("created_by"),
func.max(all_stats_alias.c.date_used).label("last_used"), # Get the most recent date
] if by_template else []
),
all_stats_table.c.notification_type,
all_stats_table.c.status,
func.cast(func.sum(all_stats_table.c.count), Integer).label("count"),
all_stats_alias.c.notification_type,
all_stats_alias.c.status,
cast(func.sum(all_stats_alias.c.count), Integer).label("count"),
)
if by_template:
query = query.filter(all_stats_table.c.template_id == Template.id)
query = query.join(Template, all_stats_alias.c.template_id == Template.id)
return query.group_by(
*([Template.name, all_stats_table.c.template_id] if by_template else []),
all_stats_table.c.notification_type,
all_stats_table.c.status,
).all()
# Group by all necessary fields except date_used
query = query.group_by(
*(
[
Template.name,
all_stats_alias.c.template_id,
Template.folder,
Template.created_by,
] if by_template else []
),
all_stats_alias.c.notification_type,
all_stats_alias.c.status,
)
print("*"*79)
print(query)
print("*"*79)
# Execute the query using Flask-SQLAlchemy's session
result = db.session.execute(query)
return result.mappings().all()
def fetch_notification_status_totals_for_all_services(start_date, end_date):