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

Updated recipients.csv to accept both lang #245

Merged
merged 7 commits into from
Oct 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
30 changes: 27 additions & 3 deletions notifications_utils/columns.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,15 @@ def __init__(
recipient_column_headers,
placeholders,
template,
template_type=None,
):
self.index = index
self.recipient_column_headers = recipient_column_headers
self.placeholders = placeholders
self.template_type = template_type
self.recipient_column_hearders_lang_check = (
["email address", "adresse courriel"] if self.template_type == "email" else ["phone number", "numéro de téléphone"]
)

if template:
template.values = row_dict
Expand All @@ -69,16 +74,35 @@ def has_error(self):

@property
def has_bad_recipient(self):
return any(self.get(recipient_column).recipient_error for recipient_column in self.recipient_column_headers)
"""
If the column has an error in the recipient field we want
to return True, otherwise False

The recipient field is the first column in the csv.
"""
for column in self.recipient_column_hearders_lang_check:
if self.get(column).recipient_error is True:
return True
return False

@property
def has_missing_data(self):
return any(cell.error == Cell.missing_field_error for cell in self.values())

@property
def recipient(self):
columns = [self.get(column).data for column in self.recipient_column_headers]
return columns[0] if len(columns) == 1 else columns
"""
We want to return the recipient from the first column in the csv
The reason we use self.recipient_column_hearders_lang_check is because
we want to check for the column name in both english and french.

The recipient field is the first column in the csv. The column name
might be in english even though we are in french context and vice versa.
This is why we need to check both languages.
"""
for column in self.recipient_column_hearders_lang_check:
if self.get(column).data is not None:
return self.get(column).data

@property
def personalisation(self):
Expand Down
87 changes: 73 additions & 14 deletions notifications_utils/recipients.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,38 @@
region_code = os.getenv("PHONE_REGION_CODE", "US")

first_column_headings = {
"email": ["email address"],
"sms": ["phone number"],
"en": {
"email": ["email address"],
"sms": ["phone number"],
# For backwards compatibility
"letter": [
"address line 1",
"address line 2",
"address line 3",
"address line 4",
"address line 5",
"address line 6",
"postcode",
],
},
"fr": {
"email": ["adresse courriel"],
"sms": ["numéro de téléphone"],
# For backwards compatibility
"letter": [
"address line 1",
"address line 2",
"address line 3",
"address line 4",
"address line 5",
"address line 6",
"postcode",
],
},
"email": ["email address"], # left this for backwards compatibility
"sms": ["phone number"], # left this for backwards compatibility
"email_both": ["email address", "adresse courriel"],
"sms_both": ["phone number", "numéro de téléphone"],
"letter": [
"address line 1",
"address line 2",
Expand Down Expand Up @@ -60,7 +90,9 @@ def __init__(
remaining_messages=sys.maxsize,
international_sms=False,
max_rows=50000,
user_language="en",
):
self.user_language = user_language
self.file_data = strip_whitespace(file_data, extra_characters=",")
self.template_type = template_type
self.placeholders = placeholders
Expand Down Expand Up @@ -106,6 +138,9 @@ def placeholders(self, value):
self.recipient_column_headers_as_column_keys = [
Columns.make_key(placeholder) for placeholder in self.recipient_column_headers
]
self.recipient_column_headers_lang_check_as_column_keys = [
Columns.make_key(placeholder) for placeholder in self.recipient_column_headers_lang_check # type: ignore
]

@property
def template_type(self):
Expand All @@ -114,7 +149,10 @@ def template_type(self):
@template_type.setter
def template_type(self, value):
self._template_type = value
self.recipient_column_headers = first_column_headings[self.template_type]
self.recipient_column_headers = first_column_headings[self.user_language][self.template_type] # type: ignore
self.recipient_column_headers_lang_check = (
first_column_headings.get("email_both") if self.template_type == "email" else first_column_headings.get("sms_both")
)

@property
def has_errors(self):
Expand Down Expand Up @@ -163,8 +201,7 @@ def get_rows(self):

for column_name, column_value in zip(column_headers, row):
column_value = strip_and_remove_obscure_whitespace(column_value)

if Columns.make_key(column_name) in self.recipient_column_headers_as_column_keys:
if Columns.make_key(column_name) in self.recipient_column_headers_lang_check_as_column_keys:
output_dict[column_name] = column_value or None
else:
insert_or_append_to_dict(output_dict, column_name, column_value or None)
Expand All @@ -185,6 +222,7 @@ def get_rows(self):
recipient_column_headers=self.recipient_column_headers,
placeholders=self.placeholders_as_column_keys,
template=self.template,
template_type=self.template_type,
)
else:
yield None
Expand Down Expand Up @@ -263,11 +301,31 @@ def column_headers_as_column_keys(self):

@property
def missing_column_headers(self):
return set(
key
for key in self.placeholders
if (Columns.make_key(key) not in self.column_headers_as_column_keys and not self.is_optional_address_column(key))
)
"""
Missing headers must return the following in each case:

Eg 1: file: []
placeholders: [phone number, name]
missing: [phone number, name]

Eg 2: file: [adresse courriel]
placeholders: [email address]
missing: []

"""
result = set()
for key in self.placeholders:
# If the key has a different heading due to language, then we need to check that the column_headers
# in the file have either the same or other language. This is only for email address / phone number
if key in self.recipient_column_headers_lang_check: # type: ignore
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So do we allow FR column headers when the request is in EN and vice versa? What exactly is the intersection method doing here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes we allow FR heading and EN request and vice versa.

The intersection says - if the headings that english/french are not in column headers of the file:
Add that header to the result - we know that it is "missing"

if not set(map(Columns.make_key, self.recipient_column_headers_lang_check)).intersection( # type: ignore
set(self.column_headers_as_column_keys)
):
result.add(key)
continue
elif Columns.make_key(key) not in self.column_headers_as_column_keys and not self.is_optional_address_column(key):
result.add(key)
return result

@property
def duplicate_recipient_column_headers(self):
Expand All @@ -290,13 +348,14 @@ def is_optional_address_column(self, key):

@property
def has_recipient_columns(self):
return (
"""
This is used to check if the first column in the csv is a recipient column
"""
return set([list(self.column_headers_as_column_keys)[0]]).issubset(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this do? Should we have a comment here maybe?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

set(
Columns.make_key(recipient_column)
for recipient_column in self.recipient_column_headers
if not self.is_optional_address_column(recipient_column)
for recipient_column in self.recipient_column_headers_lang_check # type: ignore
)
<= self.column_headers_as_column_keys
)

def _get_error_for_field(self, key, value): # noqa: C901
Expand Down
Loading