"""Tests for account_payment_term handlers.""" import datetime from unittest.mock import MagicMock, patch from abacus_common_logic.utils.dates import safe_format_datetime from flask.testing import FlaskClient from owsresponse import response from owsresponse.adaptors.flask import flaskify import pytest from abacus_account.constants import constants from abacus_account.constants import error from tests.utils.factories import AccountFactory @pytest.mark.parametrize( ( 'profile_type', 'profile_role', 'authorize_return', 'permissions_return', 'expected_status', ), [ pytest.param( 'DocumentsProfile', 'payee_management', None, True, 200, id='Standalone check OK, Permissions check OK' ), pytest.param( 'DocumentsProfile', 'payee_management', None, False, 403, id='Standalone check OK, Permissions check not OK' ), pytest.param( 'Account360Profile', 'account360', True, True, 200, id='Standalone check not OK, PDP check OK' ), pytest.param( 'Account360Profile', 'account360', False, True, 403, id='Standalone check not OK, PDP check not OK' ), ], ) @patch('abacus_account.blueprints.account.ows_client') @patch('abacus_account.blueprints.account.permissions_authorize_many_accounts') @patch('abacus_account.blueprints.account.authorize_many_accounts') @patch('abacus_account.logic.account.get_payment_eligibility_status') def test_get_payment_eligibility_status_( mock_logic: MagicMock, mock_authorize_many_accounts: MagicMock, mock_permissions_authorize_many_accounts: MagicMock, mock_ows_client: MagicMock, fixture_client: FlaskClient, profile_type: str, profile_role: str, authorize_return: bool | None, permissions_return: bool | None, expected_status: int ): """Test GET endpoint to get payment_eligibility_status by an account id.""" mock_response = {'eligibility_status': constants.ELIGIBILITY_STATUSES.ON_HOLD} mock_logic.return_value = response.Response(message=mock_response, status=200) mock_authorize_many_accounts.return_value = authorize_return mock_permissions_authorize_many_accounts.return_value = permissions_return account_id = 1234 res = fixture_client.get( f'/account/{account_id}/payment-eligibility-status/', headers={ 'Orchard-Requestor-Service': 'graphql-abacus', 'Orchard-Profile-Type': profile_type, 'Orchard-Profile-Id': '1234', 'Orchard-Roles': profile_role, 'Orchard-Identity-Id': '1234' } ) if expected_status == 200: mock_logic.assert_called_once_with(account_id) assert res.json == mock_response if authorize_return is not None: mock_authorize_many_accounts.assert_called_once_with([1234]) else: mock_authorize_many_accounts.assert_not_called() if authorize_return is not False: mock_permissions_authorize_many_accounts.assert_called_once_with( mock_ows_client, profile_type, '1234', [account_id] ) @patch('abacus_account.logic.account.get_sap_formatted_account_info') def test_get_sap_formatted_account_info(mock_logic, fixture_client): """Test GET endpoint to get sap formatted account info by an account id.""" account_id = 1234 mock_response = { 'AccountId': 1, 'AcctName': 'Test Account', 'Kunnr': None, 'Lifnr': None, 'Zzfield1': None, 'Zzfield2': None } mock_logic.return_value = response.Response(message=mock_response, status=200) res = fixture_client.get(f'/account/{account_id}/sap/') assert res.status_code == 200 assert res.json == mock_response mock_logic.assert_called_once_with(account_id) @patch('abacus_account.logic.account.update_account') def test_update_account(mock_logic, fixture_client): """Test PUT endpoint to update account info.""" mock_account = AccountFactory.create() put_body = {'sap_created_at': safe_format_datetime(datetime.date(2022, 2, 1))} mock_logic.return_value = response.Response(message='ok', status=200) res = fixture_client.put(f'/account/{mock_account.account_id}', json=put_body) assert res.status_code == 200 mock_logic.assert_called() @patch('abacus_account.blueprints.account.dataload_accounts_by_ids') def test_dataloader_accounts_by_ids_error_params(mock_get_payees, fixture_client): """Test for the account dataloader handler. Error on wrong params. """ mock_response = response.Response(message='error', status=400) mock_get_payees.return_value = mock_response post_data = [1, 'str'] res = fixture_client.post( '/account/dataloader', json=post_data) assert res.status_code == 400 assert res.json['code'] == 'error' assert res.json['message'] == error.ERROR_INVALID_IDS.format(object='Account') @pytest.mark.parametrize( ( 'profile_type', 'authorize_return', 'permissions_return', 'expected_status', ), [ pytest.param( 'MoneyhubProfile', None, True, 200, id='Standalone check OK, Permissions check OK' ), pytest.param( 'MoneyhubProfile', None, False, 403, id='Standalone check OK, Permissions check not OK' ), pytest.param( 'Account360Profile', True, True, 200, id='Standalone check not OK, PDP check OK' ), pytest.param( 'Account360Profile', False, True, 403, id='Standalone check not OK, PDP check not OK' ), ], ) @patch('abacus_account.blueprints.account.ows_client') @patch('abacus_account.blueprints.account.permissions_authorize_many_accounts') @patch('abacus_account.blueprints.account.authorize_many_accounts') @patch('abacus_account.blueprints.account.dataload_accounts_by_ids') def test_dataloader_accounts_by_ids( mock_get_accounts: MagicMock, mock_authorize_many_accounts: MagicMock, mock_permissions_authorize_many_accounts: MagicMock, mock_ows_client: MagicMock, fixture_client: FlaskClient, profile_type: str, authorize_return: bool | None, permissions_return: bool | None, expected_status: int, ) -> None: """Test for the account dataloader handler.""" mock_authorize_many_accounts.return_value = authorize_return mock_permissions_authorize_many_accounts.return_value = permissions_return mock_response = response.Response( message={'items': [ {'data': { 'account_payee_id': 1, 'account_name': 'account_name', 'account_payment_term_id': None, 'created_by': '', 'account_id': 10, 'sap_created_at': None }}, {'data': None}, ]}, status=200 ) mock_get_accounts.return_value = mock_response post_data = [1, 2] res = fixture_client.post( '/account/dataloader', json=post_data, headers={ 'Orchard-Requestor-Service': 'graphql-abacus', 'Orchard-Profile-Type': profile_type, 'Orchard-Profile-Id': '1234', 'Orchard-Roles': 'administrator', 'Orchard-Identity-Id': '1234' }) assert res.status_code == expected_status if expected_status == 200: assert res.json == mock_response.message mock_get_accounts.assert_called_once_with(post_data) else: mock_get_accounts.assert_not_called() if authorize_return is not None: mock_authorize_many_accounts.assert_called_once_with([1,2]) else: mock_authorize_many_accounts.assert_not_called() if authorize_return is not False: mock_permissions_authorize_many_accounts.assert_called_once_with( mock_ows_client, profile_type, '1234', [1,2] ) @pytest.mark.parametrize( ( 'profile_type', 'authorize_return', 'expected_status' ), [ pytest.param( 'AbacusProfile', None, 200, id='standalone check' ), pytest.param( 'Account360Profile', True, 200, id='pdp check, authorized' ), pytest.param( 'Account360Profile', False, 403, id='pdp check, unauthorized' ), ], ) @patch('abacus_account.blueprints.account.authorize_many_accounts') @patch('abacus_account.blueprints.account.get_accounts_by_ids') def test_post_accounts( mock_get_accounts: MagicMock, mock_authorize_many_accounts: MagicMock, fixture_client: FlaskClient, profile_type: str, authorize_return: bool, expected_status: int, ) -> None: """Test for the account dataloader handler.""" if authorize_return is not None: mock_authorize_many_accounts.return_value = authorize_return mock_accounts = [ { 'account_id': 1, 'account_name': 'account_name', 'created_by': 'admin', 'account_payment_term_id': 10, 'sap_created_at': None }, { 'account_id': 2, 'account_name': 'account_name2', 'created_by': 'admin', 'account_payment_term_id': None, 'sap_created_at': datetime.datetime(2025, 1, 1) } ] mock_get_accounts.return_value = (mock_accounts, 2) post_data = {'account_ids': [1, 2]} res = fixture_client.post( '/accounts', json=post_data, headers={ 'Orchard-Requestor-Service': 'graphql-abacus', 'Orchard-Profile-Type': profile_type, 'Orchard-Profile-Id': '1234', 'Orchard-Roles': 'administrator', 'Orchard-Identity-Id': '1234' }) assert res.status_code == expected_status if expected_status == 200: expected_accounts = [ { 'account_id': 1, 'account_name': 'account_name', 'created_by': 'admin', 'account_payment_term_id': 10, 'sap_created_at': None }, { 'account_id': 2, 'account_name': 'account_name2', 'created_by': 'admin', 'account_payment_term_id': None, 'sap_created_at': '2025-01-01T00:00:00.000000Z' } ] assert res.json == {'items': expected_accounts, 'total_count': 2} mock_get_accounts.assert_called_once_with(post_data) if authorize_return is not None: mock_authorize_many_accounts.assert_called_once_with([1,2]) else: mock_authorize_many_accounts.assert_not_called() @pytest.mark.parametrize( ( 'profile_type', 'profile_role', 'authorize_return', 'permissions_return', 'expected_status', ), [ pytest.param( 'MoneyhubProfile', 'administrator', None, True, 200, id='Standalone check OK, Permissions check OK' ), pytest.param( 'MoneyhubProfile', 'administrator', None, False, 403, id='Standalone check OK, Permissions check not OK' ), pytest.param( 'Account360Profile', 'account360', True, True, 200, id='Standalone check not OK, PDP check OK' ), pytest.param( 'Account360Profile', 'account360', False, True, 403, id='Standalone check not OK, PDP check not OK' ), ], ) @patch('abacus_account.blueprints.account.ows_client') @patch('abacus_account.blueprints.account.permissions_authorize_many_accounts') @patch('abacus_account.blueprints.account.authorize_many_accounts') @patch('abacus_account.blueprints.account.ItemView.get') def test_get_account_by_id( mock_super_get: MagicMock, mock_authorize_many_accounts: MagicMock, mock_permissions_authorize_many_accounts: MagicMock, mock_ows_client: MagicMock, fixture_client: FlaskClient, profile_type: str, profile_role: str, authorize_return: bool | None, permissions_return: bool | None, expected_status: int, ): """Test for getting an account by id.""" mock_response = flaskify(response.Response( message={ 'account_id': 1, 'account_name': 'Test Account', 'created_by': 'test', 'sap_created_at': '2022-02-01T00:00:00', 'account_payee_id': 1, 'account_payment_term_id': 1 }, status=200 )) mock_super_get.return_value = mock_response mock_authorize_many_accounts.return_value = authorize_return mock_permissions_authorize_many_accounts.return_value = permissions_return res = fixture_client.get( '/account/1', headers={ 'Orchard-Requestor-Service': 'graphql-abacus', 'Orchard-Profile-Type': profile_type, 'Orchard-Profile-Id': '1234', 'Orchard-Roles': profile_role, 'Orchard-Identity-Id': '1234' } ) if expected_status == 200: assert res.json == mock_response.json if authorize_return is not None: mock_authorize_many_accounts.assert_called_once_with([1]) else: mock_authorize_many_accounts.assert_not_called() if authorize_return is not False: mock_permissions_authorize_many_accounts.assert_called_once_with( mock_ows_client, profile_type, '1234', [1] )