SIENTIAPDE-1172

feat: enhance email notifications and orchestrator activities for reports

- Updated email HTML structure to clearly present errors, warnings, and info notifications.
- Introduced a new method in the Formatters class to filter notification reports based on group configurations.
- Enhanced the Reports workflow to integrate the new filtering functionality and manage notification packages effectively.
- Adjusted SlotManager to store timestamps with mail type specificity for better tracking.
- Improved test coverage for the new filtering functionality in the Formatters class.
This commit is contained in:
vitor-aignosi
2025-07-29 11:42:05 -03:00
parent bc456cc8be
commit 6f6094b2ce
9 changed files with 527 additions and 10 deletions

View File

@@ -765,3 +765,61 @@ async def test_format_log_report(formatters):
)
assert DataFrame(result).equals(expected_result)
@mark.asyncio
async def test_filter_notification_reports(formatters):
input_data = {
**metadata,
'notification_package': [
{
'trigger': 'test_trigger_1',
'notification_id': 'test_notification_id_1'
},
{
'trigger': 'test_trigger_2',
'notification_id': 'test_notification_id_2'
},
{
'trigger': 'test_trigger_3',
'notification_id': 'test_notification_id_3'
}
],
'sending_configs': [
{
'group_name': 'test_group_1',
'contents': ['reports'],
'ignore': ['test_notification_id_1']
},
{
'group_name': 'test_group_2',
'contents': ['core_alerts']
}
]
}
response = await formatters.filter_notification_reports(input_data)
assert response == {
'test_group_1': {
'group_name': 'test_group_1',
'contents': ['reports'],
'ignore': ['test_notification_id_1'],
'notifications': [
{
'trigger': 'test_trigger_2',
'notification_id': 'test_notification_id_2'
},
{
'trigger': 'test_trigger_3',
'notification_id': 'test_notification_id_3'
}
]
},
'test_group_2': {
'group_name': 'test_group_2',
'contents': ['core_alerts'],
'notifications': []
}
}

View File

@@ -0,0 +1,99 @@
from unittest.mock import AsyncMock, patch, ANY, call
from pytest import fixture, mark
from orchestrator.workflows.reports import Reports
from orchestrator.activities.activities import Activities
@fixture
def reports():
return Reports()
metadata = {
'metadata': {
'schedule_name': 'test-schedule-name',
'workflow_name': 'reports',
'model_name': '-',
'model_id': '-',
}
}
@mark.asyncio
@patch("orchestrator.workflows.reports.workflow", new_callable=AsyncMock)
async def test_run_full_flow(workflow_mock, reports):
input_data = {
'schedule_name': 'test-schedule-name',
'notification_ttl': 300,
'sent_ttl': 600
}
await reports.run(input_data)
workflow_mock.execute_child_workflow.assert_has_calls([
call(
'load_notification_package',
{
**input_data,
'metadata': metadata,
'base_data_filter': {}
}
)
])
workflow_mock.execute_child_workflow.assert_has_calls([
call(
'process_notifications',
{
'metadata': metadata,
'mail_type': 'Reports',
'notification_package': workflow_mock.execute_local_activity_method.return_value,
'schema': 'sientia_data',
'table_name': 'log_report'
}
)
])
workflow_mock.execute_local_activity_method.assert_has_calls([
call(
Activities.filter_notification_reports,
{
**metadata,
'notification_package': workflow_mock.execute_child_workflow.return_value['notification_package'],
'sending_configs': workflow_mock.execute_child_workflow.return_value['sending_configs']
},
schedule_to_close_timeout=ANY,
retry_policy=ANY
)
])
@mark.asyncio
@patch("orchestrator.workflows.reports.workflow", new_callable=AsyncMock)
async def test_run_no_data(workflow_mock, reports):
workflow_mock.execute_child_workflow.return_value = {
'last_timestamp': '2023-01-01 12:00:00.000000',
'notification_package': [],
'sending_configs': []
}
input_data = {
'schedule_name': 'test-schedule-name',
'notification_ttl': 300,
'sent_ttl': 600
}
await reports.run(input_data)
workflow_mock.execute_child_workflow.assert_has_calls([
call(
'load_notification_package',
{
**input_data,
'metadata': metadata,
'base_data_filter': {}
}
)
])
workflow_mock.execute_local_activity_method.assert_not_called()