"""Tests for account_payment_term handlers.""" from decimal import Decimal from unittest.mock import MagicMock, patch from abacus_common_logic.test_utils.helpers import get_message from flask.testing import FlaskClient from owsresponse import response import pytest from abacus_account.constants import constants from abacus_account.constants import error from abacus_account.schemas.account_payment_term import AccountPaymentTermDetailSchema from tests.utils.factories import AccountFactory from tests.utils.factories import AccountPaymentTermFactory @patch('abacus_account.logic.account_payment_term.create_account_payment_term') def test_post_account_payment_term_success( mock_logic, fixture_client ): """Test successful creation of new account payment term.""" mock_logic.return_value = response.Response(message='ok', status=201) post_body = { 'account_id': 1, 'currency_code': 'USD', 'payment_entity_id': 1, 'payment_minimum': '67', 'payment_schedule': constants.PAYMENT_SCHEDULE.SCHEDULE_30_DAYS_MONTH, } create_params = {**post_body, 'payment_minimum': Decimal('67')} res = fixture_client.post('/account-payment-term/', json=post_body) assert res.status_code == 201 mock_logic.assert_called_once_with(**create_params) @patch('abacus_account.logic.account_payment_term.create_account_payment_term') def test_post_account_payment_term_success_none_values( mock_logic, fixture_client ): """Test successful creation of new account payment term.""" mock_logic.return_value = response.Response(message='ok', status=201) post_body = { 'account_id': 1, 'currency_code': 'USD', 'payment_entity_id': None, 'payment_minimum': None, 'payment_schedule': constants.PAYMENT_SCHEDULE.SCHEDULE_30_DAYS_MONTH, } res = fixture_client.post('/account-payment-term/', json=post_body) assert res.status_code == 201 mock_logic.assert_called_once_with(**post_body) @patch('abacus_account.logic.account_payment_term.create_account_payment_term') def test_post_account_payment_term_error( mock_logic, fixture_client ): """Test failure creating account payment term.""" mock_logic.return_value = response.Response(message='error', status=400) account = AccountFactory.create() post_body = { 'account_id': account.account_id, 'currency_code': 'USD', 'payment_entity_id': 1, 'payment_minimum': '67', 'payment_schedule': constants.PAYMENT_SCHEDULE.SCHEDULE_30_DAYS_MONTH, } create_params = {**post_body, 'payment_minimum': Decimal('67')} res = fixture_client.post('/account-payment-term/', json=post_body) assert res.status_code == 400 mock_logic.assert_called_once_with(**create_params) @patch('abacus_account.logic.account_payment_term.create_account_payment_term') def test_post_account_payment_term_missing_field_error( mock_logic, fixture_client ): """Validate POST request payload.""" # account = AccountFactory.create() post_body = { 'account_id': 1, 'payment_entity_id': 1, 'payment_minimum': '67', 'payment_schedule': constants.PAYMENT_SCHEDULE.SCHEDULE_30_DAYS_MONTH, } res = fixture_client.post('/account-payment-term/', json=post_body) assert get_message(res) == \ {'currency_code': [error.ERROR_FIELD_MISSING]} assert not mock_logic.called @patch('abacus_account.logic.account_payment_term.update_account_payment_term') def test_put_account_payment_term_success( mock_logic, reference_payment_entity_fixture, fixture_client ): """Test successful update of existing account payment term.""" account_payment_term = AccountPaymentTermFactory.create() payment_term_id = account_payment_term.account_payment_term_id mock_logic.return_value = response.Response(message='ok', status=200) put_body = {'currency_code': 'USD'} res = fixture_client.put(f'/account-payment-term/{payment_term_id}/', json=put_body) assert res.status_code == 200 mock_logic.assert_called_once_with(account_payment_term, **put_body) @patch('abacus_account.logic.account_payment_term.update_account_payment_term') def test_put_account_payment_term_error( mock_logic, reference_payment_entity_fixture, fixture_client ): """Test failure updating account payment term.""" account_payment_term = AccountPaymentTermFactory.create() payment_term_id = account_payment_term.account_payment_term_id mock_logic.return_value = response.Response(message='error', status=400) put_body = {'currency_code': 'USD'} res = fixture_client.put(f'/account-payment-term/{payment_term_id}/', json=put_body) assert res.status_code == 400 mock_logic.assert_called_once_with(account_payment_term, **put_body) @patch('abacus_account.logic.account_payment_term.update_account_payment_term') def test_put_account_payment_term_does_not_exist(mock_logic, fixture_client): """Test to update account_payment_term that doesn't exist.""" account_payment_term_id = 1121 put_body = { 'currency_code': 'USD', 'payment_entity_id': 1 } res = fixture_client.put( f'/account-payment-term/{account_payment_term_id}/', json=put_body ) assert res.status_code == 404 assert res.json['message'] == \ error.ERROR_ENTITY_DOES_NOT_EXIST.format( object_type='AccountPaymentTerm', object_id=account_payment_term_id ) assert not mock_logic.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_payment_term.ows_client') @patch('abacus_account.blueprints.account_payment_term.permissions_authorize_many_accounts') # noqa: E501 @patch('abacus_account.blueprints.account_payment_term.authorize_many_accounts') @patch('abacus_account.logic.account_payment_term.get_payment_term_by_account_id') def test_get_account_payment_term_by_account_id( 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, reference_payment_entity_fixture ): """Test GET endpoint to get an account payment term by an account_id.""" account_payment_term = AccountPaymentTermFactory.create() account_id = account_payment_term.account_id expected_response = AccountPaymentTermDetailSchema().dump(account_payment_term) mock_logic.return_value = response.Response(message=expected_response, status=200) mock_authorize_many_accounts.return_value = authorize_return mock_permissions_authorize_many_accounts.return_value = permissions_return res = fixture_client.get( f'/account/{account_id}/account-payment-term/', headers={ 'Orchard-Requestor-Service': 'graphql-abacus', 'Orchard-Profile-Type': profile_type, 'Orchard-Profile-Id': '1234', 'Orchard-Roles': profile_role, 'Orchard-Identity-Id': '1234' } ) assert res.status_code == expected_status if expected_status == 200: assert res.json == expected_response mock_logic.assert_called_once_with(account_id) if authorize_return is not None: mock_authorize_many_accounts.assert_called_once_with([account_id]) 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] ) @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_payment_term.ows_client') @patch('abacus_account.blueprints.account_payment_term.permissions_authorize_many_accounts') # noqa: E501 @patch('abacus_account.blueprints.account_payment_term.authorize_many_accounts') @patch('abacus_account.logic.account_payment_term.get_payment_term_by_account_id_dataloaded') # noqa: E501 def test_get_account_payment_term_by_account_id_dataloaded( 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, reference_payment_entity_fixture ): """Test POST endpoint to get account payment terms dataloaded.""" account_payment_terms = [AccountPaymentTermFactory.create()] account_ids = [1, 2] expected_response = [ { 'data': AccountPaymentTermDetailSchema().dump( account_payment_terms, many=True ) }, {'data': None} ] mock_logic.return_value = response.Response(message=expected_response, status=200) mock_authorize_many_accounts.return_value = authorize_return mock_permissions_authorize_many_accounts.return_value = permissions_return post_data = [1, 2] res = fixture_client.post( '/account/account-payment-term/dataloader', json=post_data, 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 == expected_response mock_logic.assert_called_once_with(account_ids) if authorize_return is not None: mock_authorize_many_accounts.assert_called_once_with(account_ids) 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_ids ) @patch('abacus_account.logic.account_payment_term.account_payment_terms_export') def test_get_account_payment_terms_snapshot_tsv(mock_logic, fixture_client): """Test for account payment terms' export handler.""" data = 'account_payment_term_id\taccount_id\t' \ 'currency_code\tpayment_minimum\tpayment_schedule\n' \ '1\t11\tUSD\t35.00\tthe_orchard\t30_days_after_month_end\n' \ '2\t33\tUSD\t555.55\tthe_orchard\t30_days_after_month_end\n' mock_logic.return_value = data result = fixture_client.post('/account-payment-terms/snapshot', json=[]) assert result.status_code == 200 assert result.data.decode() == data mock_logic.assert_called_once_with(None)