"""Tests for SyncContractProcessor class.""" from types import SimpleNamespace from unittest.mock import MagicMock, patch import pytest from config import ACTION_STATES from sync_contract.error_handling import OwsServiceException from sync_contract.processor import SyncContractProcessor def test_format_vendor_contract_distribution_type(mock_event): """Test _format_vendor_contract_distribution_type function.""" vendor_contract_id = 1267 distribution_type_id = 1 new_store_default = 'N' processor = SyncContractProcessor(mock_event) response = processor._format_vendor_contract_distribution_type( distribution_type_id, new_store_default, vendor_contract_id ) assert response == { 'distribution_type_id': distribution_type_id, 'new_store_default': new_store_default, 'vendor_contract_id': vendor_contract_id, } def test_format_legacy_contract(mock_event): """Test _format_legacy_contract function.""" mock_contract_details = SimpleNamespace( account_id='1', contract_type='distribution', currency_code='USD', country_exclusions=['RUS'], pay_after=None, payment_interval=None, store_exclusion=['1'], term_end='2027-10-10', term_rate=1, term_start='2024-09-10', ) processor = SyncContractProcessor(mock_event) response = processor._format_legacy_contract(mock_contract_details) assert response == { 'vendor_id': '1', 'cont_start': '2024-09-10', 'cont_end': None, 'is_automatic_rollover': 'Y', 'payment_interval': None, 'pay_after': None, 'digital_split': '1', 'currency_code': 'USD', 'country_exclusion': ['RUS'], 'store_exclusion': ['1'], 'distribution_type_id': 1, } @patch('sync_contract.processor.create_vendor_contract_distribution_types') def test_create_legacy_vendor_contract_distribution_types( mock_create_vendor_contract_distribution_types, mock_event ): """Test create_legacy_vendor_contract_distribution_type function.""" mock_create_vendor_contract_distribution_types.return_value = [ {'vendor_contract_distribution_type_id': 1} ] vendor_contract_id = 1267 contract_type = 'distribution' processor = SyncContractProcessor(mock_event) processor.create_legacy_vendor_contract_distribution_types( contract_type, vendor_contract_id ) mock_create_vendor_contract_distribution_types.assert_called_once_with( [ { 'distribution_type_id': 1, 'new_store_default': 'N', 'vendor_contract_id': vendor_contract_id, }, { 'distribution_type_id': 2, 'new_store_default': 'N', 'vendor_contract_id': vendor_contract_id, }, { 'distribution_type_id': 3, 'new_store_default': 'N', 'vendor_contract_id': vendor_contract_id, }, { 'distribution_type_id': 6, 'new_store_default': 'N', 'vendor_contract_id': vendor_contract_id, }, ] ) @patch('sync_contract.processor.update_contract_state') def test_update_contract_status(mock_update_state, mock_contract_states, mock_event): """Test updating contract status.""" mock_legacy_sync_state = mock_contract_states[0] processor = SyncContractProcessor(mock_event) processor.update_contract_status(mock_legacy_sync_state, ACTION_STATES.COMPLETE) mock_update_state.assert_called_once_with( mock_legacy_sync_state['abacus_state_id'], ACTION_STATES.COMPLETE ) @patch('sync_contract.processor.app_logger') @patch('sync_contract.processor.raise_service_error') @patch('sync_contract.processor.AbacusContractInfo') def test_processor_success( mock_abacus_contract_info, mock_raise_error, mock_logger, mock_event, mock_contract_states, mock_contract_details, mock_account_contracts, mock_legacy_contract_body, ): """Test main processor method succeeds.""" abacus_contract_id = mock_event.get('target_id') oa_contract_id = 123 legacy_contract_id = 1 mock_abacus_contract_info.return_value = MagicMock( return_value=mock_contract_details ) mock_abacus_contract_info.return_value.load_data_from_ows.return_value = None mock_abacus_contract_info.return_value.oa_contract_id = None mock_abacus_contract_info.return_value.contract_type = 'distribution' mock_abacus_contract_info.return_value.legacy_sync_state = mock_contract_states[0] mock_abacus_contract_info.return_value.abacus_account_contracts = ( mock_account_contracts['items'] ) SyncContractProcessor._format_legacy_contract = MagicMock( return_value=mock_legacy_contract_body ) SyncContractProcessor.create_legacy_contract = MagicMock( return_value=oa_contract_id ) SyncContractProcessor.create_legacy_vendor_contract_distribution_types = MagicMock() SyncContractProcessor.update_contract_status = MagicMock() SyncContractProcessor.create_abacus_legacy_contract = MagicMock( return_value=dict(legacy_contract_id=legacy_contract_id) ) SyncContractProcessor(mock_event).process() mock_logger.info.assert_called_once() mock_raise_error.assert_not_called() mock_abacus_contract_info.assert_called_once_with(abacus_contract_id) mock_abacus_contract_info.return_value.load_data_from_ows.assert_called_once() SyncContractProcessor._format_legacy_contract.assert_called_once() SyncContractProcessor.create_legacy_contract.assert_called_once_with( mock_legacy_contract_body ) SyncContractProcessor.create_legacy_vendor_contract_distribution_types.assert_called_once_with( 'distribution', oa_contract_id ) SyncContractProcessor.update_contract_status.assert_called_once_with( mock_contract_states[0], ACTION_STATES.COMPLETE ) SyncContractProcessor.create_abacus_legacy_contract.assert_called_once_with( oa_contract_id ) @patch('sync_contract.processor.app_logger') @patch('sync_contract.processor.raise_service_error') @patch('sync_contract.processor.AbacusContractInfo') def test_processor_service_exception( mock_abacus_contract_info, mock_raise_error, mock_logger, mock_event, mock_contract_states, mock_contract_details, mock_legacy_contract_body, ): """Test main processor method updates contract_status to "error" on failure.""" abacus_contract_id = mock_event.get('target_id') oa_contract_id = 123 mock_abacus_contract_info.return_value = MagicMock( return_value=mock_contract_details ) mock_abacus_contract_info.return_value.load_data_from_ows.side_effect = ( OwsServiceException('Nope') ) mock_abacus_contract_info.return_value.legacy_sync_state = mock_contract_states[0] SyncContractProcessor._format_legacy_contract = MagicMock( return_value=mock_legacy_contract_body ) SyncContractProcessor.create_legacy_contract = MagicMock( return_value=oa_contract_id ) SyncContractProcessor.create_legacy_vendor_contract_distribution_type = MagicMock() SyncContractProcessor.update_contract_status = MagicMock() SyncContractProcessor.create_abacus_legacy_contract = MagicMock() with pytest.raises(OwsServiceException): SyncContractProcessor(mock_event).process() mock_logger.info.assert_called_once() mock_raise_error.assert_not_called() mock_abacus_contract_info.assert_called_once_with(abacus_contract_id) mock_abacus_contract_info.return_value.load_data_from_ows.assert_called_once() SyncContractProcessor._format_legacy_contract.assert_not_called() SyncContractProcessor.create_legacy_contract.assert_not_called() SyncContractProcessor.create_legacy_vendor_contract_distribution_type.assert_not_called() SyncContractProcessor.update_contract_status.assert_called_once_with( mock_contract_states[0], ACTION_STATES.ERROR ) SyncContractProcessor.create_abacus_legacy_contract.assert_not_called() @patch('sync_contract.processor.app_logger') @patch('sync_contract.processor.raise_service_error') @patch('sync_contract.processor.AbacusContractInfo') def test_processor_skip_if_other_contracts_exist( mock_abacus_contract_info, mock_raise_error, mock_logger, mock_event_separate_contract, mock_contract_states, mock_contract_details, mock_account_contracts, mock_legacy_contract_body, ): """Test main processor method to skip sync if account has existing contracts.""" abacus_contract_id = mock_event_separate_contract.get('target_id') oa_contract_id = 123 legacy_contract_id = 1 mock_abacus_contract_info.return_value = MagicMock( return_value=mock_contract_details ) mock_abacus_contract_info.return_value.load_data_from_ows.return_value = None mock_abacus_contract_info.return_value.oa_contract_id = None mock_abacus_contract_info.return_value.contract_type = 'distribution' mock_abacus_contract_info.return_value.legacy_sync_state = mock_contract_states[0] mock_abacus_contract_info.return_value.abacus_account_contracts = ( mock_account_contracts['items'] ) SyncContractProcessor._format_legacy_contract = MagicMock( return_value=mock_legacy_contract_body ) SyncContractProcessor.create_legacy_contract = MagicMock( return_value=oa_contract_id ) SyncContractProcessor.create_legacy_vendor_contract_distribution_type = MagicMock() SyncContractProcessor.update_contract_status = MagicMock() SyncContractProcessor.create_abacus_legacy_contract = MagicMock( return_value=dict(legacy_contract_id=legacy_contract_id) ) SyncContractProcessor(mock_event_separate_contract).process() mock_logger.info.assert_called() mock_raise_error.assert_not_called() mock_abacus_contract_info.assert_called_once_with(abacus_contract_id) mock_abacus_contract_info.return_value.load_data_from_ows.assert_called_once() SyncContractProcessor._format_legacy_contract.assert_not_called() SyncContractProcessor.create_legacy_contract.assert_not_called() SyncContractProcessor.create_legacy_vendor_contract_distribution_type.assert_not_called() SyncContractProcessor.update_contract_status.assert_not_called() SyncContractProcessor.create_abacus_legacy_contract.assert_not_called()