2023-11-16 12:24:27 -08:00
|
|
|
import datetime
|
|
|
|
|
|
|
|
|
|
import pytz
|
2023-11-16 12:47:47 -08:00
|
|
|
from flask_login import current_user
|
2021-06-09 15:15:35 +01:00
|
|
|
|
|
|
|
|
from app.models.spreadsheet import Spreadsheet
|
|
|
|
|
from app.utils.templates import get_sample_template
|
2024-05-16 10:37:37 -04:00
|
|
|
from notifications_utils.recipients import RecipientCSV
|
2021-06-09 15:15:35 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_errors_for_csv(recipients, template_type):
|
|
|
|
|
errors = []
|
|
|
|
|
|
|
|
|
|
if any(recipients.rows_with_bad_recipients):
|
|
|
|
|
number_of_bad_recipients = len(list(recipients.rows_with_bad_recipients))
|
2023-08-25 09:12:23 -07:00
|
|
|
if "sms" == template_type:
|
2021-06-09 15:15:35 +01:00
|
|
|
if 1 == number_of_bad_recipients:
|
|
|
|
|
errors.append("fix 1 phone number")
|
|
|
|
|
else:
|
|
|
|
|
errors.append("fix {} phone numbers".format(number_of_bad_recipients))
|
2023-08-25 09:12:23 -07:00
|
|
|
elif "email" == template_type:
|
2021-06-09 15:15:35 +01:00
|
|
|
if 1 == number_of_bad_recipients:
|
|
|
|
|
errors.append("fix 1 email address")
|
|
|
|
|
else:
|
|
|
|
|
errors.append("fix {} email addresses".format(number_of_bad_recipients))
|
|
|
|
|
|
|
|
|
|
if any(recipients.rows_with_missing_data):
|
|
|
|
|
number_of_rows_with_missing_data = len(list(recipients.rows_with_missing_data))
|
|
|
|
|
if 1 == number_of_rows_with_missing_data:
|
|
|
|
|
errors.append("enter missing data in 1 row")
|
|
|
|
|
else:
|
2023-08-25 09:12:23 -07:00
|
|
|
errors.append(
|
|
|
|
|
"enter missing data in {} rows".format(number_of_rows_with_missing_data)
|
|
|
|
|
)
|
2021-06-09 15:15:35 +01:00
|
|
|
|
|
|
|
|
if any(recipients.rows_with_message_too_long):
|
2023-08-25 09:12:23 -07:00
|
|
|
number_of_rows_with_message_too_long = len(
|
|
|
|
|
list(recipients.rows_with_message_too_long)
|
|
|
|
|
)
|
2021-06-09 15:15:35 +01:00
|
|
|
if 1 == number_of_rows_with_message_too_long:
|
|
|
|
|
errors.append("shorten the message in 1 row")
|
|
|
|
|
else:
|
2023-08-25 09:12:23 -07:00
|
|
|
errors.append(
|
|
|
|
|
"shorten the messages in {} rows".format(
|
|
|
|
|
number_of_rows_with_message_too_long
|
|
|
|
|
)
|
|
|
|
|
)
|
2021-06-09 15:15:35 +01:00
|
|
|
|
|
|
|
|
if any(recipients.rows_with_empty_message):
|
2023-08-25 09:12:23 -07:00
|
|
|
number_of_rows_with_empty_message = len(
|
|
|
|
|
list(recipients.rows_with_empty_message)
|
|
|
|
|
)
|
2021-06-09 15:15:35 +01:00
|
|
|
if 1 == number_of_rows_with_empty_message:
|
|
|
|
|
errors.append("check you have content for the empty message in 1 row")
|
|
|
|
|
else:
|
2023-08-25 09:12:23 -07:00
|
|
|
errors.append(
|
|
|
|
|
"check you have content for the empty messages in {} rows".format(
|
|
|
|
|
number_of_rows_with_empty_message
|
|
|
|
|
)
|
|
|
|
|
)
|
2021-06-09 15:15:35 +01:00
|
|
|
|
|
|
|
|
return errors
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def generate_notifications_csv(**kwargs):
|
|
|
|
|
from app import notification_api_client
|
|
|
|
|
from app.s3_client.s3_csv_client import s3download
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
if "page" not in kwargs:
|
|
|
|
|
kwargs["page"] = 1
|
|
|
|
|
|
2024-02-21 10:30:24 -08:00
|
|
|
# This generates the "batch" csv report
|
2023-08-25 09:12:23 -07:00
|
|
|
if kwargs.get("job_id"):
|
|
|
|
|
original_file_contents = s3download(kwargs["service_id"], kwargs["job_id"])
|
2021-06-09 15:15:35 +01:00
|
|
|
original_upload = RecipientCSV(
|
|
|
|
|
original_file_contents,
|
2023-08-25 09:12:23 -07:00
|
|
|
template=get_sample_template(kwargs["template_type"]),
|
2021-06-09 15:15:35 +01:00
|
|
|
)
|
|
|
|
|
original_column_headers = original_upload.column_headers
|
2024-02-05 12:27:40 -08:00
|
|
|
fieldnames = [
|
2024-02-21 10:30:24 -08:00
|
|
|
"Phone Number",
|
2024-02-05 12:27:40 -08:00
|
|
|
"Template",
|
|
|
|
|
"Sent by",
|
2024-02-14 10:39:52 -08:00
|
|
|
"Batch File",
|
2024-02-05 12:27:40 -08:00
|
|
|
"Carrier Response",
|
|
|
|
|
"Status",
|
|
|
|
|
"Time",
|
|
|
|
|
]
|
|
|
|
|
for header in original_column_headers:
|
2024-02-21 07:45:21 -08:00
|
|
|
if header.lower() != "phone number":
|
|
|
|
|
fieldnames.append(header)
|
2024-02-05 12:27:40 -08:00
|
|
|
|
2021-06-09 15:15:35 +01:00
|
|
|
else:
|
2024-02-21 10:30:24 -08:00
|
|
|
# This generates the "full" csv report
|
2023-08-25 09:12:23 -07:00
|
|
|
fieldnames = [
|
2024-02-21 10:30:24 -08:00
|
|
|
"Phone Number",
|
2023-08-25 09:12:23 -07:00
|
|
|
"Template",
|
|
|
|
|
"Sent by",
|
2024-02-14 10:39:52 -08:00
|
|
|
"Batch File",
|
2023-11-03 10:38:38 -07:00
|
|
|
"Carrier Response",
|
2023-08-25 09:12:23 -07:00
|
|
|
"Status",
|
|
|
|
|
"Time",
|
|
|
|
|
]
|
2021-06-09 15:15:35 +01:00
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
yield ",".join(fieldnames) + "\n"
|
2021-06-09 15:15:35 +01:00
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
while kwargs["page"]:
|
|
|
|
|
notifications_resp = notification_api_client.get_notifications_for_service(
|
|
|
|
|
**kwargs
|
|
|
|
|
)
|
|
|
|
|
for notification in notifications_resp["notifications"]:
|
2023-11-16 12:24:27 -08:00
|
|
|
preferred_tz_created_at = convert_report_date_to_preferred_timezone(
|
|
|
|
|
notification["created_at"]
|
|
|
|
|
)
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
if kwargs.get("job_id"):
|
2024-02-05 12:27:40 -08:00
|
|
|
values = [
|
2024-02-21 07:45:21 -08:00
|
|
|
notification["recipient"],
|
2024-02-05 12:27:40 -08:00
|
|
|
notification["template_name"],
|
|
|
|
|
notification["created_by_name"],
|
|
|
|
|
notification["job_name"],
|
|
|
|
|
notification["provider_response"],
|
|
|
|
|
notification["status"],
|
|
|
|
|
preferred_tz_created_at,
|
|
|
|
|
]
|
|
|
|
|
for header in original_column_headers:
|
2024-02-21 07:45:21 -08:00
|
|
|
if header.lower() != "phone number":
|
|
|
|
|
values.append(
|
|
|
|
|
original_upload[notification["row_number"] - 1]
|
|
|
|
|
.get(header)
|
|
|
|
|
.data
|
|
|
|
|
)
|
2024-02-05 12:27:40 -08:00
|
|
|
|
2021-06-09 15:15:35 +01:00
|
|
|
else:
|
|
|
|
|
values = [
|
2023-08-25 09:12:23 -07:00
|
|
|
notification["recipient"],
|
|
|
|
|
notification["template_name"],
|
|
|
|
|
notification["created_by_name"] or "",
|
|
|
|
|
notification["job_name"] or "",
|
2023-11-03 10:38:38 -07:00
|
|
|
notification["provider_response"],
|
2023-08-25 09:12:23 -07:00
|
|
|
notification["status"],
|
2023-11-16 12:24:27 -08:00
|
|
|
preferred_tz_created_at,
|
2021-06-09 15:15:35 +01:00
|
|
|
]
|
|
|
|
|
yield Spreadsheet.from_rows([map(str, values)]).as_csv_data
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
if notifications_resp["links"].get("next"):
|
|
|
|
|
kwargs["page"] += 1
|
2021-06-09 15:15:35 +01:00
|
|
|
else:
|
|
|
|
|
return
|
|
|
|
|
raise Exception("Should never reach here")
|
2023-11-16 12:24:27 -08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def convert_report_date_to_preferred_timezone(db_date_str_in_utc):
|
2023-11-16 12:47:47 -08:00
|
|
|
"""
|
|
|
|
|
Report dates in the db are in UTC. We need to convert them to the user's default timezone,
|
|
|
|
|
which defaults to "US/Eastern"
|
|
|
|
|
"""
|
2023-11-16 12:24:27 -08:00
|
|
|
date_arr = db_date_str_in_utc.split(" ")
|
|
|
|
|
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())
|
|
|
|
|
preferred_date_obj = utc_date_obj.astimezone(preferred_timezone)
|
2024-01-24 11:03:19 -08:00
|
|
|
preferred_tz_created_at = preferred_date_obj.strftime("%Y-%m-%d %I:%M:%S %p")
|
2023-11-16 12:24:27 -08:00
|
|
|
|
|
|
|
|
return f"{preferred_tz_created_at} {get_user_preferred_timezone()}"
|
2023-11-16 12:47:47 -08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_user_preferred_timezone():
|
|
|
|
|
if current_user and hasattr(current_user, "preferred_timezone"):
|
|
|
|
|
return current_user.preferred_timezone
|
|
|
|
|
|
|
|
|
|
return "US/Eastern"
|