Refactored reports to use pregenerated docs instead (#2831)

* Refactored reports to use pregenerated docs instead

* Fixed e2e test

* Fixed anothr bug

* Cleanup

* Fixed timezone conversion

* Updated ref files

* Updated reference files, refreshed ui/ux for report generation. Buttons toggle on and off based on if report exists

* Fixed linting errors, removed pytz

* Fixed test failure

* e2e test fix

* Speeding up unit tests

* Removed python time library that was causing performance issues with unit tests

* Updated poetry lock

* Unit test improvements

* Made change that ken reccomended
This commit is contained in:
Alex Janousek
2025-08-15 15:02:54 -04:00
committed by GitHub
parent 748c35d2df
commit 8d33f28b76
50 changed files with 632 additions and 204 deletions

View File

@@ -1,6 +1,6 @@
import datetime
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
import pytz
from flask import current_app, json
from flask_login import current_user
@@ -188,17 +188,33 @@ def convert_report_date_to_preferred_timezone(db_date_str_in_utc):
db_date_str_in_utc = f"{date_arr[0]}T{date_arr[1]}+00:00"
utc_date_obj = datetime.datetime.fromisoformat(db_date_str_in_utc)
utc_date_obj = utc_date_obj.astimezone(pytz.utc)
preferred_timezone = pytz.timezone(get_user_preferred_timezone())
utc_date_obj = utc_date_obj.replace(tzinfo=ZoneInfo("UTC"))
preferred_timezone = get_user_preferred_timezone_obj()
preferred_date_obj = utc_date_obj.astimezone(preferred_timezone)
preferred_tz_created_at = preferred_date_obj.strftime("%Y-%m-%d %I:%M:%S %p")
preferred_tz_created_at = preferred_date_obj.strftime("%Y-%m-%d %H:%M:%S")
return f"{preferred_tz_created_at} {get_user_preferred_timezone()}"
return preferred_tz_created_at
_timezone_cache = {}
def get_user_preferred_timezone():
if current_user and hasattr(current_user, "preferred_timezone"):
tz = current_user.preferred_timezone
if tz in pytz.all_timezones:
# Validate timezone using ZoneInfo - it will raise if invalid
try:
ZoneInfo(tz)
return tz
except ZoneInfoNotFoundError:
# Invalid timezone, fall back to default
pass
return "US/Eastern"
def get_user_preferred_timezone_obj():
"""Get the ZoneInfo object for the user's preferred timezone, cached for performance."""
tz_name = get_user_preferred_timezone()
if tz_name not in _timezone_cache:
_timezone_cache[tz_name] = ZoneInfo(tz_name)
return _timezone_cache[tz_name]

50
app/utils/s3_csv.py Normal file
View File

@@ -0,0 +1,50 @@
import csv
import io
from app.utils.csv import convert_report_date_to_preferred_timezone
def convert_s3_csv_timestamps(csv_content):
if isinstance(csv_content, bytes):
csv_content = csv_content.decode("utf-8")
reader = csv.reader(io.StringIO(csv_content))
time_column_index = None
try:
header = next(reader)
for i, col in enumerate(header):
if col.strip().lower() == "time":
time_column_index = i
break
output = io.StringIO()
writer = csv.writer(output)
writer.writerow(header)
yield output.getvalue()
output.truncate(0)
output.seek(0)
except StopIteration:
return
if time_column_index is None:
for row in reader:
writer.writerow(row)
yield output.getvalue()
output.truncate(0)
output.seek(0)
return
for row in reader:
if len(row) > time_column_index and row[time_column_index]:
try:
row[time_column_index] = convert_report_date_to_preferred_timezone(
row[time_column_index]
)
except Exception: # nosec B110
pass
writer.writerow(row)
yield output.getvalue()
output.truncate(0)
output.seek(0)

View File

@@ -1,13 +1,13 @@
from datetime import datetime
from zoneinfo import ZoneInfo
import pytz
from dateutil import parser
from app.utils.csv import get_user_preferred_timezone
from app.utils.csv import get_user_preferred_timezone_obj
def get_current_financial_year():
preferred_tz = pytz.timezone(get_user_preferred_timezone())
preferred_tz = get_user_preferred_timezone_obj()
now = datetime.now(preferred_tz)
current_year = int(now.strftime("%Y"))
return current_year
@@ -15,7 +15,7 @@ def get_current_financial_year():
def is_less_than_days_ago(date_from_db, number_of_days):
return (
datetime.utcnow().astimezone(pytz.utc) - parser.parse(date_from_db)
datetime.now(ZoneInfo("UTC")) - parser.parse(date_from_db)
).days < number_of_days