"""Functional tests for adding product_approval activity.""" import json from datetime import datetime from types import SimpleNamespace from unittest.mock import patch import pytest from owsresponse import response from notifications import ( config, handlers, # noqa ) from notifications.logic.collaborators_email import _generate_tracking_url from notifications.validation.schemas.collaborators_statement_period_closed import ( CollaboratorsStatementPeriodClosed, ) ACCOUNTING_URL = ( 'https://moneyhub.qaorch.com?forwardedViaEmailIdentityId={}&forwardedViaEmailStatementId={}' ) MOCK_IDENTIIES = [ {'id': '1', 'email': '1'}, {'id': '2', 'email': '2'}, ] def _make_message(ident, statement_period): return { 'type': 'GeneralNotification', 'subject': 'New Statement Available!', 'to': [ident['email']], 'template': 'collaborators_statement_period_closed', 'lang': 'en', 'sender': 'donotreply@theorchard.com', 'variables': { 'statement_period': statement_period, 'vendor_name': 'Label Name', 'default_brand': 'theorchard', 'accounting_url': ACCOUNTING_URL.format(ident['id'], statement_period['id']), 'tracking_url': _generate_tracking_url(ident['id'], ident['email']), }, } @pytest.mark.parametrize( 'data, expected_result', [ ( { 'items': [ { 'active_collaborator_ids': [], 'statement_period': { 'id': '123', 'name': 'name', 'vendor_id': '123', 'created_date': '2025-08-08T01:23:45', 'updated_date': '2025-08-08T01:23:45', 'status': 'CLOSED', }, }, { 'active_collaborator_ids': [], 'statement_period': { 'id': '456', 'name': 'name', 'vendor_id': '123', 'created_date': '2025-08-08T01:23:45', 'updated_date': '2025-08-08T01:23:45', 'status': 'CLOSED', }, }, ], }, response.Response(status=200), ), ( { 'items': [ { 'active_collaborator_ids': [123, 456], 'statement_period': { 'id': '789', 'name': 'Q1 2025', 'vendor_id': '999', 'created_date': '2026-01-15T10:30:00', 'updated_date': '2026-03-31T23:59:59', 'status': 'CLOSED', 'abacus_statement_period_id': 'extra-field-should-be-ignored', 'some_other_field': 'ignored', }, }, ], }, response.Response(status=200), ), ], ) @patch('notifications.handlers.Neo4jSession.__enter__') @patch('notifications.handlers.Neo4jSession.__exit__') @patch('notifications.logic.collaborators_email.sqs.send_messages') @patch('notifications.logic.collaborators_email._get_following_identities') @patch('notifications.logic.collaborators_email.label.get_name_for_label') @patch('notifications.logic.collaborators_email.label.get_default_brand_for_label') def test_collaborators_bulk_statement_period_closed_email( mock_get_default_brand_for_label, mock_get_name_for_label, mock_get_following_identities, mock_send_messages, neo4j_exit, neo4j_enter, data, expected_result, fixture_client, ): """Test closing a statement period in bulk.""" mock_get_name_for_label.return_value = SimpleNamespace(message='Label Name') mock_get_default_brand_for_label.return_value = SimpleNamespace(message='theorchard') mock_get_following_identities.return_value = MOCK_IDENTIIES url = '/collaborators/bulk-statement-period-closed-email' result = fixture_client.post(url, data=json.dumps(data), content_type='application/json') assert result.status_code == expected_result.status expected_messages = [] for item in data['items']: for identity in MOCK_IDENTIIES: expected_messages.append(_make_message(identity, item['statement_period'])) mock_send_messages.assert_called_with( config.NOTIFICATIONS_DELIVERY_URL, expected_messages, ) def test_collaborators_statement_period_closed_schema_excludes_irrelevant_fields(): """Test that the Marshmallow schema excludes unused fields from the payload.""" payload = { 'active_collaborator_ids': [123, 456], 'statement_period': { 'id': '789', 'name': 'Q1 2026', 'vendor_id': '999', 'created_date': '2026-01-15T10:30:00', 'updated_date': '2026-03-31T23:59:59', 'status': 'CLOSED', 'abacus_statement_period_id': 'extra_id_to_be_ignored', 'extra_field': 'ignored', }, } schema = CollaboratorsStatementPeriodClosed() result = schema.load(payload) assert result == { 'active_collaborator_ids': [123, 456], 'statement_period': { 'statement_period_id': 789, 'name': 'Q1 2026', 'vendor_id': 999, 'created_date': datetime(2026, 1, 15, 10, 30, 0), 'updated_date': datetime(2026, 3, 31, 23, 59, 59), 'status': 'CLOSED', }, }