"""Test Abacus State functional.""" from unittest.mock import patch import pytest from abacus_common_logic.utils import dates from abacus_state.constants import constants, error from abacus_state.constants.constants import ( ACTION_STATUSES, ACTIONS_BY_PARENT_TABLE, AUTO_GENERATED_STATEMENT_PERIOD_ADJUSTMENT_FILE_ACTION_NAMES, DOCUMENTS_PROFILE_ACCOUNT_PAYEE_ACTION_NAMES, DOCUMENTS_PROFILE_ALLOWED_STATUSES_BY_PARENT_TABLE_BY_ACTION_NAMES, DOCUMENTS_PROFILE_PAYEE_ACTION_NAMES, PARENT_TABLE_NAMES, STATEMENT_PERIOD_ACTION_NAMES, STATEMENT_PERIOD_ADJUSTMENT_FILE_ACTION_NAMES, ) from abacus_state.constants.error import ( ERROR_DONT_HAVE_PERMISSIONS, ERROR_PREVIOUS_ACTIONS_STATUS, ) from tests.utils.factories import AbacusStateFactory pytestmark = [pytest.mark.db('mysql')] def test_create_abacus_states(fixture_client): """Test new abacus states creation.""" post_data = [ { 'action_name': 'deliver_sales_files', 'parent_table_name': 'accounting_period', 'parent_table_id': '1', } ] res = fixture_client.post('/abacus-states', json=post_data) assert res.status_code == 201 assert res.json[0]['action_name'] == post_data[0]['action_name'] assert res.json[0]['action_status'] == 'init' @pytest.mark.parametrize( 'parent_table_name, action_name', [ (parent_table, action) for parent_table, actions in ACTIONS_BY_PARENT_TABLE.items() for action in actions if action not in DOCUMENTS_PROFILE_ACCOUNT_PAYEE_ACTION_NAMES and action not in DOCUMENTS_PROFILE_PAYEE_ACTION_NAMES ], ) def test_create_abacus_states_for_documents_profile_failure( fixture_client, parent_table_name, action_name ): """Test new abacus states creation for DocumentsProfile.""" post_data = [ { 'action_name': action_name, 'parent_table_name': parent_table_name, 'parent_table_id': '1', } ] headers = {'Orchard-Profile-Type': 'DocumentsProfile'} res = fixture_client.post('/abacus-states', json=post_data, headers=headers) expected_error_message = f'Profile type DocumentsProfile is forbidden to create state for {parent_table_name} {action_name}' assert res.status_code == 400 assert res.json.get('code') == 'error' assert res.json.get('message') == expected_error_message @pytest.mark.parametrize( 'parent_table_name, action_name', [ (parent_table, action) for parent_table, actions in ACTIONS_BY_PARENT_TABLE.items() for action in actions ], ) def test_create_abacus_states_for_abacus_profile_success( fixture_client, parent_table_name, action_name ): """Test new abacus states creation for DocumentsProfile.""" post_data = [ { 'action_name': action_name, 'parent_table_name': parent_table_name, 'parent_table_id': '1', } ] headers = {'Orchard-Profile-Type': 'AbacusProfile'} res = fixture_client.post('/abacus-states', json=post_data, headers=headers) assert res.status_code == 201 assert res.json[0]['action_name'] == post_data[0]['action_name'] assert res.json[0]['parent_table_name'] == post_data[0]['parent_table_name'] assert res.json[0]['action_status'] == 'init' @patch( 'abacus_state.utils.permissions.validate_record_owner_access_checks', return_value=True, ) def test_create_abacus_acc_payee_states_for_documents_profile_success( mock_perm, fixture_client ): """Test new abacus states creation for DocumentsProfile.""" post_data = [ { 'action_name': 'banking_details_review', 'parent_table_name': 'account_payee', 'parent_table_id': '1', } ] headers = {'Orchard-Profile-Type': 'DocumentsProfile', 'Orchard-Profile-Id': '1234'} res = fixture_client.post('/abacus-states', json=post_data, headers=headers) assert res.status_code == 201 assert res.json[0]['action_name'] == post_data[0]['action_name'] assert res.json[0]['parent_table_name'] == post_data[0]['parent_table_name'] assert res.json[0]['action_status'] == 'init' @patch( 'abacus_state.utils.permissions.validate_record_owner_access_checks', return_value=False, ) def test_create_abacus_acc_payee_states_for_documents_profile_failure( mock_perm, fixture_client ): """Test new abacus states creation for DocumentsProfile.""" post_data = [ { 'action_name': 'banking_details_review', 'parent_table_name': 'account_payee', 'parent_table_id': '1', } ] headers = {'Orchard-Profile-Type': 'DocumentsProfile', 'Orchard-Profile-Id': '1234'} res = fixture_client.post('/abacus-states', json=post_data, headers=headers) assert res.status_code == 401 assert res.json.get('code') == 'error' assert res.json.get('message') == ERROR_DONT_HAVE_PERMISSIONS def test_create_abacus_states_by_parent_table_account_payee(fixture_client): """Test POST /abacus-states///.""" parent_table_name = 'account-payee' parent_table_id = 123 res = fixture_client.post(f'abacus-states/{parent_table_name}/{parent_table_id}') assert res.status_code == 201 assert len(res.json) == len(constants.ACCOUNT_PAYEE_ACTION_NAMES) def test_create_abacus_states_by_parent_table_dist_accounting_period(fixture_client): """Test POST /abacus-states///.""" parent_table_name = constants.PARENT_TABLE_NAMES.ACCOUNTING_PERIOD parent_table_id = 123 contract_type = constants.CONTRACT_TYPES.DISTRIBUTION res = fixture_client.post( '/abacus-states/{0}/{1}?contract_type={2}'.format( parent_table_name, parent_table_id, contract_type ) ) assert res.status_code == 201 assert len(res.json) == len(constants.ACCOUNTING_PERIOD_ACTION_NAMES) def test_create_abacus_states_by_parent_table_nr_accounting_period(fixture_client): """Test creation of NR accounting_period action states.""" parent_table_name = constants.PARENT_TABLE_NAMES.ACCOUNTING_PERIOD parent_table_id = 123 contract_type = constants.CONTRACT_TYPES.NEIGHBOURING_RIGHTS res = fixture_client.post( '/abacus-states/{0}/{1}?contract_type={2}'.format( parent_table_name, parent_table_id, contract_type ) ) assert res.status_code == 201 assert len(res.json) < len(constants.ACCOUNTING_PERIOD_ACTION_NAMES) action_names = [action.get('action_name') for action in res.json] assert ( constants.ACCOUNTING_PERIOD_ACTION_NAMES.PREP_MECHANICAL_DEDUCTIONS not in action_names ) def test_create_abacus_states_by_parent_table_payment_group_payment(fixture_client): """Test POST /abacus-states///.""" parent_table_name = 'payment-group-payment' parent_table_id = 123 res = fixture_client.post(f'/abacus-states/{parent_table_name}/{parent_table_id}') assert res.status_code == 201 assert len(res.json) == len(constants.PAYMENT_GROUP_PAYMENT_ACTION_NAMES) def test_create_abacus_states_by_parent_table_payment_group_payment_account( fixture_client, ): """Test POST /abacus-states///.""" parent_table_name = 'payment-group-payment-account' parent_table_id = 1 res = fixture_client.post(f'/abacus-states/{parent_table_name}/{parent_table_id}') assert res.status_code == 201 assert len(res.json) == len(constants.PAYMENT_GROUP_PAYMENT_ACCOUNT_ACTION_NAMES) def test_create_abacus_states_by_parent_table_payment_group_payment_batch( fixture_client, ): """Test POST /abacus-states///.""" parent_table_name = 'payment-group-payment-batch' parent_table_id = 1 res = fixture_client.post(f'/abacus-states/{parent_table_name}/{parent_table_id}') assert res.status_code == 201 assert len(res.json) == len(constants.PAYMENT_GROUP_PAYMENT_BATCH_ACTION_NAMES) def test_create_abacus_states_by_parent_table_sales_file(fixture_client): """Test POST /abacus-states///.""" parent_table_name = 'sales-file' parent_table_id = 123 res = fixture_client.post(f'/abacus-states/{parent_table_name}/{parent_table_id}') assert res.status_code == 201 assert len(res.json) == len(constants.SALES_FILES_ACTION_NAMES) def test_create_abacus_states_by_parent_table_name_invalid_table(fixture_client): """Test error is raised when invalid parent_table_name is used.""" parent_table_name = 'parent-table' parent_table_id = 123 res = fixture_client.post(f'/abacus-states/{parent_table_name}/{parent_table_id}') assert res.status_code == 400 assert res.json.get('code') == 'error' assert res.json.get('message') == error.ERROR_INVALID_PARENT_TABLE_NAME def test_create_abacus_states_by_parent_table_name_already_exist(fixture_client): """Test error is raised when parent table name already has abacus states.""" abacus_state = AbacusStateFactory.create( parent_table_name='sales_file', action_name='blah', action_status='init' ) parent_table_name = abacus_state.parent_table_name parent_table_id = abacus_state.parent_table_id res = fixture_client.post(f'/abacus-states/{parent_table_name}/{parent_table_id}') assert res.status_code == 400 assert res.json.get('code') == 'error' assert res.json.get('message') == error.ERROR_ACTION_STATES_ALREADY_EXIST.format( parent_table_name=parent_table_name, parent_table_id=parent_table_id ) def test_get_abacus_state_action_list(fixture_client): """Test endpoint passes request body to logic layer.""" abacus_state = AbacusStateFactory.create( parent_table_name='accounting_period', parent_table_id=1, action_name='deliver_sales_files', action_status='complete', ) res = fixture_client.get('/abacus-state/accounting-period/1') assert res.status_code == 200 assert res.json == [ { 'action_name': 'deliver_sales_files', 'action_status': 'complete', 'abacus_state_id': 1, 'message': None, 'parent_table_name': 'accounting_period', 'parent_table_id': 1, 'created_at': dates.safe_format_datetime(abacus_state.created_at), 'created_by': abacus_state.created_by, 'last_modified': dates.safe_format_datetime(abacus_state.last_modified), 'last_modified_by': abacus_state.last_modified_by, } ] def test_update_abacus_state(fixture_client, create_mock_accounting_run): """Test endpoint to update abacus state by id.""" actions = constants.ACCOUNTING_PERIOD_ACTION_NAMES abacus_states = [ AbacusStateFactory.create( action_name=status, action_status='complete' if index < len(actions) - 1 else 'init', parent_table_id=1, ) for index, status in enumerate(actions) ] abacus_state_id = abacus_states[len(actions) - 1].abacus_state_id mock_put_request = {'action_status': 'complete', 'message': 'testing'} res = fixture_client.put(f'/abacus-state/{abacus_state_id}', json=mock_put_request) expected_state = abacus_states[len(actions) - 1] assert res.status_code == 200 assert res.json == { 'action_name': expected_state.action_name, 'action_status': constants.ACTION_STATUSES.COMPLETE, 'abacus_state_id': abacus_state_id, 'message': mock_put_request.get('message'), 'parent_table_name': 'accounting_period', 'parent_table_id': 1, 'created_at': dates.safe_format_datetime(expected_state.created_at), 'created_by': expected_state.created_by, 'last_modified': dates.safe_format_datetime(expected_state.last_modified), 'last_modified_by': expected_state.last_modified_by, } def test_update_abacus_state_null_message(fixture_client, create_mock_accounting_run): """Test endpoint to update abacus state by id.""" actions = constants.ACCOUNTING_PERIOD_ACTION_NAMES abacus_states = [ AbacusStateFactory.create( action_name=status, action_status='complete' if index < len(actions) - 1 else 'init', parent_table_id=1, ) for index, status in enumerate(actions) ] abacus_state_id = abacus_states[len(actions) - 1].abacus_state_id mock_put_request = {'action_status': 'complete', 'message': None} res = fixture_client.put(f'/abacus-state/{abacus_state_id}', json=mock_put_request) expected_state = abacus_states[len(actions) - 1] assert res.status_code == 200 assert res.json == { 'action_name': expected_state.action_name, 'action_status': constants.ACTION_STATUSES.COMPLETE, 'abacus_state_id': abacus_state_id, 'message': None, 'parent_table_name': 'accounting_period', 'parent_table_id': 1, 'created_at': dates.safe_format_datetime(expected_state.created_at), 'created_by': expected_state.created_by, 'last_modified': dates.safe_format_datetime(expected_state.last_modified), 'last_modified_by': expected_state.last_modified_by, } def test_update_abacus_state_empty_message(fixture_client, create_mock_accounting_run): """Test endpoint to update abacus state by id.""" actions = constants.ACCOUNTING_PERIOD_ACTION_NAMES abacus_states = [ AbacusStateFactory.create( action_name=status, action_status='complete' if index < len(actions) - 1 else 'init', parent_table_id=1, ) for index, status in enumerate(actions) ] abacus_state_id = abacus_states[len(actions) - 1].abacus_state_id mock_put_request = {'action_status': 'complete', 'message': ''} res = fixture_client.put(f'/abacus-state/{abacus_state_id}', json=mock_put_request) expected_state = abacus_states[len(actions) - 1] assert res.status_code == 200 assert res.json == { 'action_name': expected_state.action_name, 'action_status': constants.ACTION_STATUSES.COMPLETE, 'abacus_state_id': abacus_state_id, 'message': None, 'parent_table_name': 'accounting_period', 'parent_table_id': 1, 'created_at': dates.safe_format_datetime(expected_state.created_at), 'created_by': expected_state.created_by, 'last_modified': dates.safe_format_datetime(expected_state.last_modified), 'last_modified_by': expected_state.last_modified_by, } def test_update_abacus_state_by_id_payment_group_payment_account(fixture_client): """Test for updating payment group payment account state by id.""" action_state = AbacusStateFactory.create( parent_table_name='payment_group_payment_account', parent_table_id=1, action_name='send_payment', action_status='init', ) mock_put_request = {'action_status': 'running', 'message': 'some message'} result = fixture_client.put( f'/abacus-state/{action_state.abacus_state_id}', json=mock_put_request ) assert result.status_code == 200 assert result.json == { 'action_name': action_state.action_name, 'action_status': mock_put_request['action_status'], 'abacus_state_id': action_state.abacus_state_id, 'message': mock_put_request['message'], 'parent_table_name': 'payment_group_payment_account', 'parent_table_id': 1, 'created_at': dates.safe_format_datetime(action_state.created_at), 'created_by': action_state.created_by, 'last_modified': dates.safe_format_datetime(action_state.last_modified), 'last_modified_by': action_state.last_modified_by, } def test_update_abacus_state_for_statement_period_(fixture_client, request_engine): """Test successfully updating statement_period abacus state.""" action = AbacusStateFactory.create( parent_table_name='statement_period', parent_table_id=1, action_name=STATEMENT_PERIOD_ACTION_NAMES.UPLOAD_EXCHANGE_RATES, action_status='init', ) AbacusStateFactory.create( parent_table_name='statement_period', parent_table_id=1, action_name=STATEMENT_PERIOD_ACTION_NAMES.RELEASE_RESERVES, action_status='init', ) AbacusStateFactory.create( parent_table_name='statement_period', parent_table_id=1, action_name=STATEMENT_PERIOD_ACTION_NAMES.STATEMENT_PERIOD_CLOSE, action_status='init', ) request_engine['ows-royalties'].add_spec( 'GET', '/statement-period/1/', status=200, ) update_payload = {'action_status': 'complete', 'message': 'testing'} res = fixture_client.put( f'/abacus-state/{action.abacus_state_id}', json=update_payload ) assert res.status_code == 200 def test_update_abacus_state_for_statement_period_failure( fixture_client, request_engine ): """Test for error when updating statement_period abacus state.""" AbacusStateFactory.create( parent_table_name='statement_period', parent_table_id=1, action_name=STATEMENT_PERIOD_ACTION_NAMES.UPLOAD_EXCHANGE_RATES, action_status='init', ) action = AbacusStateFactory.create( parent_table_name='statement_period', parent_table_id=1, action_name=STATEMENT_PERIOD_ACTION_NAMES.RELEASE_RESERVES, action_status='init', ) AbacusStateFactory.create( parent_table_name='statement_period', parent_table_id=1, action_name=STATEMENT_PERIOD_ACTION_NAMES.STATEMENT_PERIOD_CLOSE, action_status='init', ) request_engine['ows-royalties'].add_spec( 'GET', '/statement-period/1/', status=200, ) update_payload = {'action_status': 'complete', 'message': 'testing'} res = fixture_client.put( f'/abacus-state/{action.abacus_state_id}', json=update_payload ) message = ( "Can't update action release_reserves, as earlier actions are not " + 'completed. OR Not all adjustments have been applied.' ) assert res.status_code == 400 assert res.json == {'code': 'error', 'message': message} def test_update_close_statement_period_abacus_state(fixture_client, request_engine): """Test updating close_statement_period statement_period abacus state.""" AbacusStateFactory.create( parent_table_name='statement_period', parent_table_id=1, action_name=STATEMENT_PERIOD_ACTION_NAMES.UPLOAD_EXCHANGE_RATES, action_status='complete', ) AbacusStateFactory.create( parent_table_name='statement_period', parent_table_id=1, action_name=STATEMENT_PERIOD_ACTION_NAMES.RELEASE_RESERVES, action_status='complete', ) action = AbacusStateFactory.create( parent_table_name='statement_period', parent_table_id=1, action_name=STATEMENT_PERIOD_ACTION_NAMES.STATEMENT_PERIOD_CLOSE, action_status='init', ) request_engine['ows-royalties'].add_spec( 'GET', '/statement-period/1/', status=200, ) update_payload = {'action_status': 'running', 'message': 'testing'} res = fixture_client.put( f'/abacus-state/{action.abacus_state_id}', json=update_payload ) assert res.status_code == 200 def test_update_abacus_state_error( fixture_client, mock_accounting_runs, request_engine ): """Test endpoint to update abacus state for close period. where earlier actions are completed and one of the accounting run status is running. """ actions = constants.ACCOUNTING_PERIOD_ACTION_NAMES abacus_states = [ AbacusStateFactory.create( action_name=status, action_status='complete' if index < len(actions) - 1 else 'init', ) for index, status in enumerate(actions) ] action = list( filter(lambda x: x.action_name == actions.CLOSE_PERIOD, abacus_states) ) abacus_state_id = action[0].abacus_state_id abacus_action_name = action[0].action_name period_id = abacus_states[0].parent_table_id mock_accounting_runs.append( {'accounting_run_id': 2, 'accounting_run_status': 'Running'} ) mock_accounting_period = { 'accounting_period_id': period_id, 'accounting_period_name': 'Test accounting period', 'contract_type': 'distribution', } request_engine['ows-royalties'].add_spec( 'GET', f'/accounting-period/{period_id}/accounting-runs', status=200, response={'items': mock_accounting_runs}, ) request_engine['ows-royalties'].add_spec( 'GET', f'/accounting-period/{period_id}', status=200, response=mock_accounting_period, ) mock_put_request = {'action_status': 'complete', 'message': 'testing'} res = fixture_client.put(f'/abacus-state/{abacus_state_id}', json=mock_put_request) assert res.status_code == 400 assert res.json['message'] == error.ERROR_PREVIOUS_ACTIONS_STATUS.format( abacus_action_name ) def test_create_abacus_states_by_statement_period_adjustment_file(fixture_client): """Test POST /abacus-states///.""" parent_table_name = 'statement_period_adjustment_file' parent_table_id = 123 res = fixture_client.post(f'/abacus-states/{parent_table_name}/{parent_table_id}') assert res.status_code == 201 assert len(res.json) == len(STATEMENT_PERIOD_ADJUSTMENT_FILE_ACTION_NAMES) def test_dataloader_states_by_ids(fixture_client): """Test abacus state dataloader endpoint.""" state = AbacusStateFactory.create() state_ids = [state.abacus_state_id, 999] res = fixture_client.post('/abacus-state/dataloader', json=state_ids) assert res.status_code == 200 assert res.json == { 'items': [ { 'data': { 'action_name': state.action_name, 'action_status': state.action_status, 'abacus_state_id': state.abacus_state_id, 'message': state.message, 'parent_table_name': state.parent_table_name, 'parent_table_id': state.parent_table_id, 'created_at': dates.safe_format_datetime(state.created_at), 'created_by': state.created_by, 'last_modified': dates.safe_format_datetime(state.last_modified), 'last_modified_by': state.last_modified_by, } }, {'data': None}, ] } @pytest.mark.parametrize( 'action_data', [ item for item in DOCUMENTS_PROFILE_ALLOWED_STATUSES_BY_PARENT_TABLE_BY_ACTION_NAMES.items() if item[0][0] != PARENT_TABLE_NAMES.PAYEE ], ) @patch( 'abacus_state.utils.permissions.validate_record_owner_access_checks', return_value=True, ) def test_update_abacus_state_document_profile_success( mock_perm, action_data, fixture_client, create_mock_accounting_run ): """Test endpoint to update abacus state by id.""" (parent_table_name, action_name), action_statuses = action_data state = AbacusStateFactory.create( parent_table_name=parent_table_name, action_name=action_name, ) for action_status in action_statuses: res = fixture_client.put( f'/abacus-state/{state.abacus_state_id}', json={'action_status': action_status, 'message': 'test'}, headers={ 'Orchard-Profile-Type': 'DocumentsProfile', 'Orchard-Profile-Id': '1234', }, ) assert res.status_code == 200 assert res.json == { 'action_name': state.action_name, 'action_status': action_status, 'abacus_state_id': state.abacus_state_id, 'message': 'test', 'parent_table_name': parent_table_name, 'parent_table_id': state.parent_table_id, 'created_at': dates.safe_format_datetime(state.created_at), 'created_by': state.created_by, 'last_modified': dates.safe_format_datetime(state.last_modified), 'last_modified_by': state.last_modified_by, } @pytest.mark.parametrize( 'action_data', DOCUMENTS_PROFILE_ALLOWED_STATUSES_BY_PARENT_TABLE_BY_ACTION_NAMES.items(), ) def test_update_abacus_state_document_profile_failure_bad_table( action_data, fixture_client, create_mock_accounting_run ): """Test endpoint to update abacus state by id.""" (_, action_name), action_statuses = action_data parent_table_name = 'wrong_table' state = AbacusStateFactory.create( parent_table_name=parent_table_name, action_name=action_name, ) for action_status in action_statuses: res = fixture_client.put( f'/abacus-state/{state.abacus_state_id}', json={'action_status': action_status, 'message': 'test'}, headers={'Orchard-Profile-Type': 'DocumentsProfile'}, ) assert res.status_code == 400 @pytest.mark.parametrize( 'action_data', DOCUMENTS_PROFILE_ALLOWED_STATUSES_BY_PARENT_TABLE_BY_ACTION_NAMES.items(), ) def test_update_abacus_state_document_profile_failure_bad_action( action_data, fixture_client, create_mock_accounting_run ): """Test endpoint to update abacus state by id.""" (parent_table_name, _), action_statuses = action_data action_name = 'wrong_action' state = AbacusStateFactory.create( parent_table_name=parent_table_name, action_name=action_name, ) for action_status in action_statuses: res = fixture_client.put( f'/abacus-state/{state.abacus_state_id}', json={'action_status': action_status, 'message': 'test'}, headers={'Orchard-Profile-Type': 'DocumentsProfile'}, ) assert res.status_code == 400 @pytest.mark.parametrize( 'action_data', DOCUMENTS_PROFILE_ALLOWED_STATUSES_BY_PARENT_TABLE_BY_ACTION_NAMES.items(), ) def test_update_abacus_state_document_profile_failure_bad_action_state( action_data, fixture_client, create_mock_accounting_run ): """Test endpoint to update abacus state by id.""" (parent_table_name, action_name), action_statuses = action_data action_statuses = set(ACTION_STATUSES) - set(action_statuses) state = AbacusStateFactory.create( parent_table_name=parent_table_name, action_name=action_name, ) for action_status in action_statuses: res = fixture_client.put( f'/abacus-state/{state.abacus_state_id}', json={'action_status': action_status, 'message': 'test'}, headers={'Orchard-Profile-Type': 'DocumentsProfile'}, ) assert res.status_code == 400 @patch('abacus_state.logic.abacus_state.is_abacus_flowthrough_automation_enabled') def test_create_abacus_states_by_auto_adjustment_file( mock_feature_enabled, create_mock_statement_period_adjustment_file, fixture_client ): """Test to create the action states for auto generated adjustment file.""" mock_feature_enabled.return_value = True parent_table_name = 'statement_period_adjustment_file' parent_table_id = 4 res = fixture_client.post(f'/abacus-states/{parent_table_name}/{parent_table_id}') assert res.status_code == 201 assert len(res.json) == len( AUTO_GENERATED_STATEMENT_PERIOD_ADJUSTMENT_FILE_ACTION_NAMES ) @patch('abacus_state.logic.abacus_state.is_abacus_flowthrough_automation_enabled') def test_create_abacus_states_by_adjustment_file( mock_feature_enabled, create_mock_statement_period_adjustment_file, fixture_client ): """Test to create the action states for adjustment file upload.""" mock_feature_enabled.return_value = True parent_table_name = 'statement_period_adjustment_file' parent_table_id = 2 res = fixture_client.post(f'/abacus-states/{parent_table_name}/{parent_table_id}') assert res.status_code == 201 assert len(res.json) == len(STATEMENT_PERIOD_ADJUSTMENT_FILE_ACTION_NAMES) @patch( 'abacus_state.logic.statement_period_adjustment_file_state.is_abacus_flowthrough_automation_enabled' ) def test_update_abacus_state_for_auto_ajdustment_file( mock_feature_enabled, create_mock_statement_period_adjustment_file, fixture_client ): """Test successfully updating auto statement_period_adjustment_file abacus states.""" mock_feature_enabled.return_value = True AbacusStateFactory.create( parent_table_name=PARENT_TABLE_NAMES.STATEMENT_PERIOD_ADJUSTMENT_FILE, parent_table_id=4, action_name=AUTO_GENERATED_STATEMENT_PERIOD_ADJUSTMENT_FILE_ACTION_NAMES.UPLOAD_FILE, action_status='complete', ) action = AbacusStateFactory.create( parent_table_name=PARENT_TABLE_NAMES.STATEMENT_PERIOD_ADJUSTMENT_FILE, parent_table_id=4, action_name=AUTO_GENERATED_STATEMENT_PERIOD_ADJUSTMENT_FILE_ACTION_NAMES.VALIDATE_FILE, action_status='init', ) update_payload = {'action_status': 'complete', 'message': 'testing'} res = fixture_client.put( f'/abacus-state/{action.abacus_state_id}', json=update_payload ) assert res.status_code == 200 assert res.json['action_status'] == 'complete' @patch( 'abacus_state.logic.statement_period_adjustment_file_state.is_abacus_flowthrough_automation_enabled' ) def test_update_abacus_state_for_auto_ajdustment_file_error( mock_feature_enabled, create_mock_statement_period_adjustment_file, fixture_client ): """Test throws an error when updating auto statement_period_adjustment_file abacus states.""" mock_feature_enabled.return_value = True action_states = [ AbacusStateFactory.create( parent_table_name=PARENT_TABLE_NAMES.STATEMENT_PERIOD_ADJUSTMENT_FILE, parent_table_id=4, action_name=action, action_status='init', ) for action in AUTO_GENERATED_STATEMENT_PERIOD_ADJUSTMENT_FILE_ACTION_NAMES ] update_payload = {'action_status': 'complete', 'message': 'testing'} res = fixture_client.put( f'/abacus-state/{action_states[1].abacus_state_id}', json=update_payload ) assert res.status_code == 400 assert res.json == { 'code': 'error', 'message': ERROR_PREVIOUS_ACTIONS_STATUS.format(action_states[1].action_name), } def test_reset_abacus_state_actions(fixture_client): """Test to reset all abacus states for specified table and id.""" parent_table_name = 'statement_period_adjustment_file' parent_table_id = 9999 ( AbacusStateFactory.create( parent_table_name=parent_table_name, parent_table_id=parent_table_id, action_name='upload_file', action_status=ACTION_STATUSES.COMPLETE, ), ) AbacusStateFactory.create( parent_table_name=parent_table_name, parent_table_id=parent_table_id, action_name='validate_file', action_status=ACTION_STATUSES.ERROR, ) result = fixture_client.put( f'/abacus-state/{parent_table_name}/{parent_table_id}/reset' ) assert result.status_code == 200 assert ( all([state['action_status'] == ACTION_STATUSES.INIT for state in result.json]) is True ) @patch('abacus_state.blueprints.abacus_state.authorization_backend.is_authorized') @patch( 'abacus_state.blueprints.abacus_state.flask_request.verify_rules_access_standalone' ) def test_reset_abacus_state_actions_forbidden( mock_verify_rules, mock_is_authorized, fixture_client ): """Test that 403 is returned when the user is not authorized to reset states.""" parent_table_name = 'statement-period-adjustment-file' parent_table_id = 9999 mock_verify_rules.return_value = False mock_is_authorized.return_value = False result = fixture_client.put( f'/abacus-state/{parent_table_name}/{parent_table_id}/reset' ) assert result.status_code == 403 assert result.json['message'] == 'Unauthorized' mock_is_authorized.assert_called_once() args, kwargs = mock_is_authorized.call_args assert kwargs['parent_table_name'] == 'statement_period_adjustment_file' def test_reset_abacus_state_actions_empty(fixture_client): """Test to ensure 200 OK is returned even if no rows exist for the given parent.""" parent_table_name = 'statement_period_adjustment_file' parent_table_id = 8888 result = fixture_client.put( f'/abacus-state/{parent_table_name}/{parent_table_id}/reset' ) assert result.status_code == 200 assert len(result.json) == 0