Skip to content

Commit

Permalink
Updated recipients.csv to accept both lang (#245)
Browse files Browse the repository at this point in the history
* Updated recipients.csv to accept both lang
- EN FR headings are now allowed for sms and email
- Your error message will be in the language of your choice

* add a further test

* fix

* tester

* fixes

* add comment and simplify code
  • Loading branch information
jzbahrai authored Oct 3, 2023
1 parent eba49e3 commit cfb132e
Show file tree
Hide file tree
Showing 3 changed files with 241 additions and 97 deletions.
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
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(
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

0 comments on commit cfb132e

Please sign in to comment.