diff --git a/cdisc_rules_engine/services/reporting/sdtm_report_data.py b/cdisc_rules_engine/services/reporting/sdtm_report_data.py index 0073e4cb1..cd0f07751 100644 --- a/cdisc_rules_engine/services/reporting/sdtm_report_data.py +++ b/cdisc_rules_engine/services/reporting/sdtm_report_data.py @@ -266,6 +266,13 @@ def _generate_error_details( if result.get("errors", []) and result.get("executionStatus") == "success": variables = result.get("variables", []) for error in result.get("errors"): + values = [] + for variable in variables: + raw_value = error.get("value", {}).get(variable) + if raw_value is None: + values.append(None) + else: + values.append(str(raw_value)) error_item = { "core_id": validation_result.id, "message": result.get("message"), @@ -274,16 +281,9 @@ def _generate_error_details( "USUBJID": error.get("USUBJID", ""), "row": error.get("row", ""), "SEQ": error.get("SEQ", ""), + "variables": variables, + "values": self.process_values(values), } - values = [] - for variable in variables: - raw_value = error.get("value", {}).get(variable) - if raw_value is None: - values.append(None) - else: - values.append(str(raw_value)) - error_item["variables"] = variables - error_item["values"] = self.process_values(values) errors.append(error_item) return errors diff --git a/cdisc_rules_engine/services/reporting/usdm_report_data.py b/cdisc_rules_engine/services/reporting/usdm_report_data.py index b32e8c9b4..41cb5c21a 100644 --- a/cdisc_rules_engine/services/reporting/usdm_report_data.py +++ b/cdisc_rules_engine/services/reporting/usdm_report_data.py @@ -111,6 +111,7 @@ def get_summary_data(self) -> list[dict]: return [ "Entity", "CORE-ID", + "CDISC RuleID", "Message", "Issues", "Explanation" @@ -128,6 +129,7 @@ def get_summary_data(self) -> list[dict]: "entity": result.get("entity") or (result.get("dataset", "") or "").replace(".json", ""), "core_id": validation_result.id, + "cdisc_rule_id": validation_result.cdisc_rule_id, "message": result.get("message"), "issues": len(result.get("errors")), } @@ -164,7 +166,7 @@ def _generate_error_details( "Entity", "Instance ID", "Path", - "Variable(s)", + "Attributes", "Value(s)" ] """ @@ -173,6 +175,13 @@ def _generate_error_details( if result.get("errors", []) and result.get("executionStatus") == "success": variables = result.get("variables", []) for error in result.get("errors"): + values = [] + for variable in variables: + raw_value = error.get("value", {}).get(variable) + if raw_value is None: + values.append(None) + else: + values.append(str(raw_value)) error_item = { "core_id": validation_result.id, "cdisc_rule_id": validation_result.cdisc_rule_id, @@ -182,16 +191,9 @@ def _generate_error_details( or error.get("dataset", "").replace(".json", ""), "instance_id": error.get("instance_id"), "path": error.get("path"), + "attributes": variables, + "values": self.process_values(values), } - values = [] - for variable in variables: - raw_value = error.get("value", {}).get(variable) - if raw_value is None: - values.append(None) - else: - values.append(str(raw_value)) - error_item["variables"] = variables - error_item["values"] = self.process_values(values) errors.append(error_item) return errors diff --git a/cdisc_rules_engine/utilities/jsonata_processor.py b/cdisc_rules_engine/utilities/jsonata_processor.py index 9a0822fc9..5ea2de073 100644 --- a/cdisc_rules_engine/utilities/jsonata_processor.py +++ b/cdisc_rules_engine/utilities/jsonata_processor.py @@ -55,23 +55,26 @@ def execute_jsonata_rule( f"\n Expected a list, but got: {results}" ) for result in results: + entity = ( + result.get("entity") + or result.get("dataset") + or result.get("instanceType") + ) error_entity = ValidationErrorEntity( value=result, - dataset=result.get("dataset") or "", + dataset=entity, row=result.get("row"), USUBJID=result.get("USUBJID"), SEQ=result.get("SEQ"), - entity=result.get("entity") - # For backwards compatibility. To be removed in the future: - or result.get("dataset") or result.get("instanceType"), + entity=entity, instance_id=result.get("instance_id") or result.get("id"), path=result.get("path") or result.get("_path"), ) - errors[result.get("dataset")].append(error_entity) + errors[entity].append(error_entity) validation_error_container = [ ValidationErrorContainer( - dataset=dataset, - domain=dataset, + dataset=entity, + domain=entity, targets=rule.get("output_variables"), errors=error, message=next(iter(rule.get("actions", [])), {}) @@ -82,9 +85,9 @@ def execute_jsonata_rule( if results else ExecutionStatus.EXECUTION_ERROR.value ), - entity=dataset, + entity=entity, ).to_representation() - for dataset, error in errors.items() + for entity, error in errors.items() ] return validation_error_container diff --git a/resources/templates/usdm-report-template.xlsx b/resources/templates/usdm-report-template.xlsx index f4793e80f..d2b273321 100644 Binary files a/resources/templates/usdm-report-template.xlsx and b/resources/templates/usdm-report-template.xlsx differ diff --git a/tests/unit/test_services/test_reporting/test_usdm_report.py b/tests/unit/test_services/test_reporting/test_usdm_report.py index 1f66c98ce..22a4642d2 100644 --- a/tests/unit/test_services/test_reporting/test_usdm_report.py +++ b/tests/unit/test_services/test_reporting/test_usdm_report.py @@ -50,7 +50,7 @@ def test_get_detailed_data(mock_validation_results): "entity": "", "instance_id": None, "path": None, - "variables": ["AESTDY", "DOMAIN"], + "attributes": ["AESTDY", "DOMAIN"], "values": ["test", "test"], }, { @@ -61,7 +61,7 @@ def test_get_detailed_data(mock_validation_results): "entity": "", "instance_id": None, "path": None, - "variables": ["AESTDY", "DOMAIN"], + "attributes": ["AESTDY", "DOMAIN"], "values": ["test", "test"], }, { @@ -72,7 +72,7 @@ def test_get_detailed_data(mock_validation_results): "entity": "", "instance_id": None, "path": None, - "variables": ["TTVAR1", "TTVAR2"], + "attributes": ["TTVAR1", "TTVAR2"], "values": ["test", "test"], }, ] @@ -98,12 +98,14 @@ def test_get_summary_data(mock_validation_results): { "entity": "", "core_id": mock_validation_results[0].id, + "cdisc_rule_id": mock_validation_results[0].cdisc_rule_id, "message": "AESTDY and DOMAIN are equal to test", "issues": 2, }, { "entity": "", "core_id": mock_validation_results[1].id, + "cdisc_rule_id": mock_validation_results[1].cdisc_rule_id, "message": "TTVARs are wrong", "issues": 1, }, diff --git a/tests/unit/test_utilities/test_jsonata_processor.py b/tests/unit/test_utilities/test_jsonata_processor.py index dbeaf1f20..67d11601e 100644 --- a/tests/unit/test_utilities/test_jsonata_processor.py +++ b/tests/unit/test_utilities/test_jsonata_processor.py @@ -58,7 +58,6 @@ class TestJSONataProcessor(TestCase): "errors": [ { "value": {"row": "", "A": "same value 1", "B": "same value 1"}, - "dataset": "", "row": "", }, { @@ -67,7 +66,6 @@ class TestJSONataProcessor(TestCase): "A": "same value 2", "B": "same value 2", }, - "dataset": "", "row": "/C/C", }, ],