diff --git a/data_store/messaging/tf_messaging.py b/data_store/messaging/tf_messaging.py index d68fd54c0..c5fd64035 100644 --- a/data_store/messaging/tf_messaging.py +++ b/data_store/messaging/tf_messaging.py @@ -294,10 +294,19 @@ def _wrong_type_failure_message(self, validation_failure: WrongTypeFailure) -> M sheet = self.INTERNAL_TABLE_TO_FORM_SHEET[validation_failure.table] _, section = self.INTERNAL_COLUMN_TO_FORM_COLUMN_AND_SECTION[validation_failure.column] actual_type = self.INTERNAL_TYPE_TO_MESSAGE_FORMAT[validation_failure.actual_type] - cell_index = self._construct_cell_index( - table=validation_failure.table, - column=str(validation_failure.column), - row_index=validation_failure.row_index, + + # if column is a str make it a list + columns = ( + [validation_failure.column] if isinstance(validation_failure.column, str) else validation_failure.column + ) + + cell_index = tuple( + self._construct_cell_index( + table=validation_failure.table, + column=column, + row_index=validation_failure.row_index, + ) + for column in columns ) if sheet == "Outcomes": @@ -305,10 +314,11 @@ def _wrong_type_failure_message(self, validation_failure: WrongTypeFailure) -> M "Financial Year 2022/21 - Financial Year 2029/30", ("Outcome Indicators (excluding " "footfall) and Footfall Indicator"), ) + cell_index = ( - "" - if validation_failure.failed_row is None - else self._get_cell_indexes_for_outcomes(validation_failure.failed_row) + (self._get_cell_indexes_for_outcomes(validation_failure.failed_row),) + if validation_failure.failed_row is not None + else ("",) ) if validation_failure.expected_type == datetime: message = self.msgs.WRONG_TYPE_DATE.format(wrong_type=actual_type) @@ -321,7 +331,7 @@ def _wrong_type_failure_message(self, validation_failure: WrongTypeFailure) -> M else: message = self.msgs.WRONG_TYPE_UNKNOWN - return Message(sheet, section, (cell_index,), message, validation_failure.__class__.__name__) + return Message(sheet, section, cell_index, message, validation_failure.__class__.__name__) def _invalid_enum_value_failure_message(self, validation_failure: InvalidEnumValueFailure) -> Message: sheet = self.INTERNAL_TABLE_TO_FORM_SHEET[validation_failure.table] @@ -334,8 +344,7 @@ def _invalid_enum_value_failure_message(self, validation_failure: InvalidEnumVal # +5 as GeographyIndicator is 5 rows below Footfall Indicator if column == "Geography Indicator": actual_index = validation_failure.row_index + 5 - cell_index = f"C{actual_index}" - return Message(sheet, section, (cell_index,), message, validation_failure.__class__.__name__) + return Message(sheet, section, (f"C{actual_index}",), message, validation_failure.__class__.__name__) # additional logic for risk location if sheet == "Risk Register": @@ -346,13 +355,21 @@ def _invalid_enum_value_failure_message(self, validation_failure: InvalidEnumVal project_number = get_project_number_by_position(validation_failure.row_index, validation_failure.table) section = f"Project Funding Profiles - Project {project_number}" - cell_index = self._construct_cell_index( - table=validation_failure.table, - column=str(validation_failure.column), - row_index=validation_failure.row_index, + # if column is a str make it a list + columns = ( + [validation_failure.column] if isinstance(validation_failure.column, str) else validation_failure.column ) - return Message(sheet, section, (cell_index,), message, validation_failure.__class__.__name__) + cell_index = tuple( + self._construct_cell_index( + table=validation_failure.table, + column=column, + row_index=validation_failure.row_index, + ) + for column in columns + ) + + return Message(sheet, section, cell_index, message, validation_failure.__class__.__name__) def _non_nullable_constraint_failure_message(self, validation_failure: NonNullableConstraintFailure) -> Message: """Generate error message components for NonNullableConstraintFailure. @@ -366,10 +383,18 @@ def _non_nullable_constraint_failure_message(self, validation_failure: NonNullab sheet = self.INTERNAL_TABLE_TO_FORM_SHEET[validation_failure.table] column, section = self.INTERNAL_COLUMN_TO_FORM_COLUMN_AND_SECTION[validation_failure.column] - cell_index = self._construct_cell_index( - table=validation_failure.table, - column=str(validation_failure.column), - row_index=validation_failure.row_index, + # if column is a str make it a list + columns = ( + [validation_failure.column] if isinstance(validation_failure.column, str) else validation_failure.column + ) + + cell_index = tuple( + self._construct_cell_index( + table=validation_failure.table, + column=column, + row_index=validation_failure.row_index, + ) + for column in columns ) message = self.msgs.BLANK @@ -385,16 +410,16 @@ def _non_nullable_constraint_failure_message(self, validation_failure: NonNullab section = "Outcome Indicators (excluding footfall) / Footfall Indicator" message = self.msgs.BLANK_ZERO cell_index = ( - "" - if validation_failure.failed_row is None - else self._get_cell_indexes_for_outcomes(validation_failure.failed_row) + (self._get_cell_indexes_for_outcomes(validation_failure.failed_row),) + if validation_failure.failed_row is not None + else ("",) ) elif sheet == "Funding Profiles": message = self.msgs.BLANK_ZERO elif section == "Programme-Wide Progress Summary": message = self.msgs.BLANK - return Message(sheet, section, (cell_index,), message, validation_failure.__class__.__name__) + return Message(sheet, section, cell_index, message, validation_failure.__class__.__name__) def _unauthorised_submission_failure(self, validation_failure: UnauthorisedSubmissionFailure) -> Message: places_or_funds = join_as_string(validation_failure.expected_values) @@ -404,18 +429,23 @@ def _unauthorised_submission_failure(self, validation_failure: UnauthorisedSubmi return Message(None, None, None, message, validation_failure.__class__.__name__) def _generic_failure(self, validation_failure: GenericFailure) -> Message: - if not validation_failure.cell_index: + if validation_failure.cell_index is not None: + cell_indexes = (validation_failure.cell_index,) + elif validation_failure.column is not None: validation_failure.cell_index = self._construct_cell_index( - validation_failure.table, - str(validation_failure.column), - validation_failure.row_index or 0, + table=validation_failure.table, + column=validation_failure.column, + row_index=validation_failure.row_index or 0, ) - sheet = self.INTERNAL_TABLE_TO_FORM_SHEET[validation_failure.table] + + cell_indexes = (validation_failure.cell_index,) + else: + cell_indexes = None return Message( - sheet, + self.INTERNAL_TABLE_TO_FORM_SHEET[validation_failure.table], validation_failure.section, - (validation_failure.cell_index,), + cell_indexes, validation_failure.message, validation_failure.__class__.__name__, ) diff --git a/tests/data_store_tests/messaging_tests/test_tf_messaging.py b/tests/data_store_tests/messaging_tests/test_tf_messaging.py index cd58d7f05..d6ab6744e 100644 --- a/tests/data_store_tests/messaging_tests/test_tf_messaging.py +++ b/tests/data_store_tests/messaging_tests/test_tf_messaging.py @@ -433,7 +433,8 @@ def test_authorised_submission(): def test_generic_failure(): test_messeger = TFMessenger() - test_messeger._generic_failure( + + message = test_messeger._generic_failure( GenericFailure( table="Project Details", section="A Section", @@ -442,6 +443,30 @@ def test_generic_failure(): ) ) + assert message == Message( + sheet="Project Admin", + section="A Section", + cell_indexes=("C1",), + description="A message", + error_type="GenericFailure", + ) + + +def test_generic_failure_when_column_is_none(): + test_messeger = TFMessenger() + + with pytest.raises(ValueError): + test_messeger._generic_failure( + GenericFailure( + table="Project Details", + section="A Section", + cell_index=None, + message="A message", + column=None, + row_index=None, + ) + ) + def test_failures_to_messages(): failure1 = InvalidEnumValueFailure(