"""Unit tests for worksheet_payable_balance_after_tax handler.""" from decimal import Decimal from unittest.mock import call, patch from payment.models import Items from payment.schemas.worksheet_payable_balance_after_tax import ( WorksheetPayableBalanceAfterTaxDetailSchema, WorksheetPayableBalanceAfterTaxOverviewSchema, ) from payment.utils.format_response import prepare_generic_success_response from tests.utils.factories import WorksheetPayableBalanceAfterTaxFactory @patch('payment.blueprints.worksheet_payable_balance_after_tax.logic.bulk_create') def test_create(mock_logic, fixture_client): """Test bulk create method.""" worksheet_payable_balance_after_tax_1 = ( WorksheetPayableBalanceAfterTaxFactory.build() ) worksheet_payable_balance_after_tax_2 = ( WorksheetPayableBalanceAfterTaxFactory.build() ) post_body = [ { 'worksheet_account_contract_closing_balance_id': worksheet_payable_balance_after_tax_1.worksheet_account_contract_closing_balance_id, # noqa 'contract_id': worksheet_payable_balance_after_tax_1.contract_id, 'account_id': worksheet_payable_balance_after_tax_1.account_id, 'payable_amount_pre_tax': str( worksheet_payable_balance_after_tax_1.payable_amount_pre_tax ), 'tax_withholding_amount': str( worksheet_payable_balance_after_tax_1.tax_withholding_amount ), 'payable_amount_post_tax': str( worksheet_payable_balance_after_tax_1.payable_amount_post_tax ), 'currency_code': worksheet_payable_balance_after_tax_1.currency_code, 'country_of_tax_residence': worksheet_payable_balance_after_tax_1.country_of_tax_residence, # noqa 'country_of_tax_policy': worksheet_payable_balance_after_tax_1.country_of_tax_policy, # noqa }, { 'worksheet_account_contract_closing_balance_id': worksheet_payable_balance_after_tax_2.worksheet_account_contract_closing_balance_id, # noqa 'contract_id': worksheet_payable_balance_after_tax_2.contract_id, 'account_id': worksheet_payable_balance_after_tax_2.account_id, 'payable_amount_pre_tax': str( worksheet_payable_balance_after_tax_2.payable_amount_pre_tax ), 'tax_withholding_amount': str( worksheet_payable_balance_after_tax_2.tax_withholding_amount ), 'payable_amount_post_tax': str( worksheet_payable_balance_after_tax_2.payable_amount_post_tax ), 'currency_code': worksheet_payable_balance_after_tax_2.currency_code, 'country_of_tax_residence': worksheet_payable_balance_after_tax_2.country_of_tax_residence, # noqa 'country_of_tax_policy': worksheet_payable_balance_after_tax_2.country_of_tax_policy, # noqa }, ] mock_logic.return_value = prepare_generic_success_response() event_id = 1 statement_period_id = 1 res = fixture_client.post( f'/worksheet-payable-balance-after-tax/event/{event_id}/statement-period/{statement_period_id}/bulk/', # noqa json=post_body, ) assert res.status_code == 201 assert res.json == prepare_generic_success_response() post_body[0]['payable_amount_pre_tax'] = Decimal( worksheet_payable_balance_after_tax_1.payable_amount_pre_tax ) post_body[0]['tax_withholding_amount'] = Decimal( worksheet_payable_balance_after_tax_1.tax_withholding_amount ) post_body[0]['payable_amount_post_tax'] = Decimal( worksheet_payable_balance_after_tax_1.payable_amount_post_tax ) post_body[1]['payable_amount_pre_tax'] = Decimal( worksheet_payable_balance_after_tax_2.payable_amount_pre_tax ) post_body[1]['tax_withholding_amount'] = Decimal( worksheet_payable_balance_after_tax_2.tax_withholding_amount ) post_body[1]['payable_amount_post_tax'] = Decimal( worksheet_payable_balance_after_tax_2.payable_amount_post_tax ) assert mock_logic.call_args_list == [ call( event_id=event_id, statement_period_id=statement_period_id, create_params=tuple(post_body), ) ] @patch( 'payment.blueprints.worksheet_payable_balance_after_tax.logic' '.bulk_delete_worksheet_payable_balance_after_tax' ) def test_bulk_delete_worksheet_payable_balance_after_tax( mock_logic, fixture_client, faker ): """Test handler bulk_delete_worksheet_payable_balance_after_tax.""" mock_logic.return_value = None test_event_id = faker.pyint() res = fixture_client.delete( f'/worksheet-payable-balance-after-tax/event/{test_event_id}/bulk' ) assert res.status_code == 204 assert mock_logic.call_args_list == [call(test_event_id)] @patch( 'payment.blueprints.worksheet_payable_balance_after_tax.logic' '.get_worksheet_payable_balance_after_tax' ) def test_get_worksheet_payable_balance_after_tax(mock_logic, fixture_client, faker): """Test handler get_worksheet_payable_balance_after_tax.""" mock_logic.return_value = Items([], 0) test_event_id = faker.pyint() test_statement_period_id = faker.pyint() test_limit = faker.pyint(20, 300) test_offset = faker.pyint(1, 10) test_search_term = faker.pystr() test_sort_by = 'contract_id' test_sort_order = 'asc' res = fixture_client.get( f'/worksheet-payable-balance-after-tax/statement-period/' f'{test_statement_period_id}/?limit={test_limit}&offset={test_offset}' ) assert res.status_code == 200 res = fixture_client.get( f'/worksheet-payable-balance-after-tax/event/' f'{test_event_id}/?limit={test_limit}&offset={test_offset}' ) assert res.status_code == 200 res = fixture_client.get( f'/worksheet-payable-balance-after-tax/event/' f'{test_event_id}/?limit={test_limit}&offset={test_offset}' # noqa f'&contract_ids=1&contract_ids=2&contract_ids=3' ) assert res.status_code == 200 res = fixture_client.get( f'/worksheet-payable-balance-after-tax/event/' f'{test_event_id}/?limit={test_limit}&offset={test_offset}' f'&search_term={test_search_term}&sort_by={test_sort_by}&sort_order={test_sort_order}' ) assert res.status_code == 200 assert mock_logic.call_args_list == [ call( event_id=0, statement_period_id=test_statement_period_id, contract_ids=None, limit=test_limit, offset=test_offset, search_term=None, sort_by=None, sort_order=test_sort_order, ), call( event_id=test_event_id, statement_period_id=0, contract_ids=None, limit=test_limit, offset=test_offset, search_term=None, sort_by=None, sort_order=test_sort_order, ), call( event_id=test_event_id, statement_period_id=0, contract_ids=[1, 2, 3], limit=test_limit, offset=test_offset, search_term=None, sort_by=None, sort_order=test_sort_order, ), call( event_id=test_event_id, statement_period_id=0, contract_ids=None, limit=test_limit, offset=test_offset, search_term=test_search_term, sort_by=test_sort_by, sort_order=test_sort_order, ), ] @patch( 'payment.blueprints.worksheet_payable_balance_after_tax.logic' '.get_worksheet_payable_balance_after_tax_overview' ) def test_get_worksheet_payable_balance_after_tax_overview( mock_logic, fixture_client, faker, mocker ): """Test handler get_worksheet_payable_balance_after_tax_overview.""" spy_serialization = mocker.spy( WorksheetPayableBalanceAfterTaxOverviewSchema, 'dump' ) test_event_id = faker.pyint() mock_result = { 'payable_amount_pre_tax': '100.00', 'tax_withholding_amount': '10.00', 'vat_amount': '5.00', 'payable_amount_post_tax': '85.00', } mock_logic.return_value = mock_result res = fixture_client.get( f'/worksheet-payable-balance-after-tax/event/{test_event_id}/overview/' ) assert res.status_code == 200 assert res.json == mock_result assert mock_logic.call_args_list == [call(event_id=test_event_id)] assert spy_serialization.called @patch( 'payment.blueprints.worksheet_payable_balance_after_tax.logic' '.delete_worksheet_payable_balance_after_tax' ) def test_delete_worksheet_payable_balance_after_tax(mock_logic, fixture_client, faker): worksheet_id = faker.pyint() res = fixture_client.delete(f'/worksheet-payable-balance-after-tax/{worksheet_id}/') assert res.status_code == 204 mock_logic.assert_called_once_with(worksheet_id) @patch( 'payment.blueprints.worksheet_payable_balance_after_tax.logic' '.get_worksheet_payable_balance_after_tax_detail' ) def test_get_worksheet_payable_balance_after_tax_detail( mock_logic, fixture_client, faker, mocker ): """Test handler get_worksheet_payable_balance_after_tax_detail.""" spy_serialization = mocker.spy(WorksheetPayableBalanceAfterTaxDetailSchema, 'dump') test_worksheet_id = faker.pyint() mock_result = { 'worksheet_account_contract_closing_balance_id': faker.pyint(), 'contract_id': faker.pyint(), 'account_id': faker.pyint(), 'payable_amount_pre_tax': str(faker.pydecimal()), 'tax_withholding_amount': str(faker.pydecimal()), 'payable_amount_post_tax': str(faker.pydecimal()), 'currency_code': faker.currency_code(), 'country_of_tax_residence': faker.country_code(), 'country_of_tax_policy': faker.country_code(), } mock_logic.return_value = mock_result res = fixture_client.get( f'/worksheet-payable-balance-after-tax/{test_worksheet_id}/' ) assert res.status_code == 200 assert res.json == mock_result assert mock_logic.call_args_list == [call(test_worksheet_id)] assert spy_serialization.called @patch( 'payment.blueprints.worksheet_payable_balance_after_tax.logic' '.bulk_update_worksheet_payable_balance_after_tax' ) def test_bulk_update_worksheet_payable_balance_after_tax( mock_logic, fixture_client, faker ): """Test bulk update handler.""" update_body = [ { 'worksheet_account_contract_payable_after_tax_id': faker.pyint(), 'tax_withholding_amount': str( faker.pydecimal(left_digits=5, right_digits=2, positive=True) ), 'vat_amount': str( faker.pydecimal(left_digits=5, right_digits=2, positive=True) ), 'payable_amount_post_tax': str( faker.pydecimal(left_digits=5, right_digits=2, positive=True) ), }, { 'worksheet_account_contract_payable_after_tax_id': faker.pyint(), 'tax_withholding_amount': str( faker.pydecimal(left_digits=5, right_digits=2, positive=True) ), 'vat_amount': str( faker.pydecimal(left_digits=5, right_digits=2, positive=True) ), 'payable_amount_post_tax': str( faker.pydecimal(left_digits=5, right_digits=2, positive=True) ), }, ] # Mock logic returns list of updated items mock_updated_items = [ { 'worksheet_account_contract_payable_after_tax_id': update_body[0][ 'worksheet_account_contract_payable_after_tax_id' ] }, { 'worksheet_account_contract_payable_after_tax_id': update_body[1][ 'worksheet_account_contract_payable_after_tax_id' ] }, ] mock_logic.return_value = mock_updated_items res = fixture_client.put( '/worksheet-payable-balance-after-tax/bulk', json=update_body, ) assert res.status_code == 200 assert isinstance(res.json, list) assert len(res.json) == 2 assert mock_logic.called