"""Contract Term Condition unit tests.""" from unittest.mock import patch from abacus_common_logic.constants.error import ERROR_ENTITY_DOES_NOT_EXIST from abacus_contract.constants.error import ERROR_CANNOT_DELETE_CONTRACT_TERM_CONDITION from abacus_contract.constants.error import ERROR_INVALID_RELATIONSHIP from abacus_contract.logic import contract_term_condition as logic from abacus_contract.utils.format_error import validation_error from tests.utils.factories import ContractTermConditionFactory, ContractTermFactory @patch('abacus_contract.logic.contract_term_condition.models') def test_create_contract_term_conditions(mock_models): """Test create contract term conditions logic.""" new_condition = ContractTermConditionFactory.build() mock_models.ContractTerm.get_by_id_or_error.return_value = \ new_condition.contract_term mock_models.ContractTermCondition.build.return_value = new_condition params = [ { 'conditions': [], 'priority': 1, 'term_rate': 50, 'contract_term_condition_name': 'test condition name' } ] result = logic.create_contract_term_conditions( new_condition.contract_term_id, params ) assert result.status == 201 mock_models.ContractTermCondition.build.assert_called_once_with( contract_term_id=new_condition.contract_term_id, conditions=params[0]['conditions'], priority=params[0]['priority'], term_rate=params[0]['term_rate'], commission=50, contract_term_condition_name=params[0]['contract_term_condition_name'] ) mock_models.ContractTermCondition.commit_changes.assert_called_once() @patch('abacus_contract.logic.contract_term_condition.models') def test_create_contract_term_conditions_with_commission(mock_models): """Test to create contract term conditions logic with commission field .""" new_condition = ContractTermConditionFactory.build() mock_models.ContractTerm.get_by_id_or_error.return_value = \ new_condition.contract_term mock_models.ContractTermCondition.build.return_value = new_condition params = [ { 'conditions': [], 'priority': 1, 'commission': 67.56 } ] result = logic.create_contract_term_conditions( new_condition.contract_term_id, params ) assert result.status == 201 mock_models.ContractTermCondition.build.assert_called_once_with( contract_term_id=new_condition.contract_term_id, conditions=params[0]['conditions'], priority=params[0]['priority'], commission=params[0]['commission'], term_rate=32.44, contract_term_condition_name=None ) mock_models.ContractTermCondition.commit_changes.assert_called_once() @patch('abacus_contract.logic.contract_term_condition.models') def test_get_conditions_by_term_id(mock_models): """Test get contract_term_conditions by contract term id.""" contract_term = ContractTermFactory.create() other_contract_term = ContractTermFactory.create() contract_term_condition = ContractTermConditionFactory.create( contract_term=other_contract_term ) mock_models.ContractTermCondition \ .get_active_term_conditions_with_order_by \ .return_value = [contract_term_condition] res = logic.get_conditions_by_term_id( contract_term.contract_term_id, ) assert res.status == 200 assert res.message[0]['contract_term_id'] == \ contract_term_condition.contract_term_id @patch('abacus_contract.logic.contract_term_condition._reprioritize') @patch('abacus_contract.logic.contract_term_condition._validate_soft_deletion') @patch('abacus_contract.logic.contract_term_condition.models') def test_soft_delete_contract_term_conditions_success( mock_models, mock_validate_deletion, mock_reprioritize): """Successfully soft deleting contract term conditions and reprioritizing.""" contract_term = ContractTermFactory.create() contract_term_conditions = [ ContractTermConditionFactory.create( contract_term=contract_term, priority=priority ) for priority in [1, 2, 3] ] contract_term_condition_ids = \ [condition.contract_term_condition_id for condition in contract_term_conditions] mock_models.ContractTermCondition.get_all_by_id.return_value = \ contract_term_conditions[:1] mock_validate_deletion.return_value = None mock_reprioritize.return_value = None res = logic.soft_delete_contract_term_conditions(contract_term_condition_ids[:1]) assert res.status == 200 mock_validate_deletion.assert_called_once_with( contract_term_conditions[:1], contract_term_condition_ids[:1], [contract_term.contract_term_id] ) mock_reprioritize.assert_called_once_with([contract_term.contract_term_id]) mock_models.ContractTermCondition.commit_changes.assert_called_once() @patch('abacus_contract.logic.contract_term_condition._reprioritize') @patch('abacus_contract.logic.contract_term_condition._validate_soft_deletion') @patch('abacus_contract.logic.contract_term_condition.models') def test_soft_delete_contract_term_conditions_failure( mock_models, mock_validate_deletion, mock_reprioritize): """Test soft deletion returns error on validation failure.""" contract_term = ContractTermFactory.create() contract_term_conditions = [ ContractTermConditionFactory.create( contract_term=contract_term, priority=priority ) for priority in [1, 2, 3] ] contract_term_condition_ids = \ [condition.contract_term_condition_id for condition in contract_term_conditions] mock_models.ContractTermCondition.get_all_by_id.return_value = \ contract_term_conditions mock_validate_deletion.return_value = validation_error('NOPE') res = logic.soft_delete_contract_term_conditions(contract_term_condition_ids) assert res.status == 400 assert res.errors['code'] == 'error' assert res.errors['message'] == 'NOPE' mock_validate_deletion.assert_called_once_with( contract_term_conditions, contract_term_condition_ids, [contract_term.contract_term_id] ) mock_reprioritize.assert_not_called() mock_models.ContractTermCondition.commit_changes.assert_not_called() @patch('abacus_contract.logic.contract_term_condition.models') def test_update_contract_term_conditions_success(mock_models): """Test update one or more contract term conditions successfully.""" contract_term = ContractTermFactory.create() contract_term_condition = ContractTermConditionFactory.create( contract_term=contract_term ) mock_models.ContractTerm.get_by_id_or_error.return_value = contract_term mock_models.ContractTermCondition.get_by_id_or_error.return_value = \ contract_term_condition update_params = [{ 'contract_term_condition_id': contract_term_condition.contract_term_condition_id, # noqa: E501 'conditions': contract_term_condition.conditions, 'priority': contract_term_condition.priority, 'term_rate': 20.20 }] assert not contract_term_condition.term_rate == update_params[0]['term_rate'] res = logic.update_contract_term_conditions( contract_term.contract_term_id, update_params ) assert res.status == 200 assert len(res.message) == len(update_params) mock_models.ContractTermCondition.commit_changes.assert_called_once() assert contract_term_condition.term_rate == update_params[0]['term_rate'] assert contract_term_condition.commission == 79.80 @patch('abacus_contract.logic.contract_term_condition.models') def test_update_contract_term_conditions_for_commission_field(mock_models): """Test to update commission field.""" contract_term = ContractTermFactory.create() contract_term_condition = ContractTermConditionFactory.create( contract_term=contract_term ) mock_models.ContractTerm.get_by_id_or_error.return_value = contract_term mock_models.ContractTermCondition.get_by_id_or_error.return_value = \ contract_term_condition update_params = [{ 'contract_term_condition_id': contract_term_condition.contract_term_condition_id, # noqa: E501 'commission': 11.89 }] res = logic.update_contract_term_conditions( contract_term.contract_term_id, update_params ) assert res.status == 200 assert len(res.message) == len(update_params) mock_models.ContractTermCondition.commit_changes.assert_called_once() assert contract_term_condition.commission == update_params[0]['commission'] assert contract_term_condition.term_rate == 88.11 @patch('abacus_contract.logic.contract_term_condition.models') def test_update_contract_term_conditions_invalid_contract_term(mock_models): """Test updating contract_term_conditions returns error for invalid parent term.""" contract_term = ContractTermFactory.create() other_contract_term = ContractTermFactory.create() contract_term_condition = ContractTermConditionFactory.create( contract_term=other_contract_term ) mock_models.ContractTerm.get_by_id_or_error.return_value = contract_term mock_models.ContractTermCondition.get_by_id_or_error.return_value = \ contract_term_condition update_params = [{ 'contract_term_condition_id': contract_term_condition.contract_term_condition_id, # noqa: E501 'conditions': contract_term_condition.conditions, 'priority': contract_term_condition.priority, 'term_rate': 20.20 }] assert not contract_term_condition.contract_term == contract_term res = logic.update_contract_term_conditions( contract_term.contract_term_id, update_params ) assert res.status == 400 assert res.errors['code'] == 'error' assert res.errors['message'] == ERROR_INVALID_RELATIONSHIP.format( child='contract_term_condition', child_id=contract_term_condition.contract_term_condition_id, parent='contract_term', parent_id=contract_term.contract_term_id ) mock_models.ContractTermCondition.commit_changes.assert_not_called() assert not contract_term_condition.term_rate == update_params[0]['term_rate'] @patch('abacus_contract.logic.contract_term_condition.models') def test_reprioritize(mock_models): """Test active contract_term_conditions are reprioritized.""" remaining_priorities = [3, 4] contract_term = ContractTermFactory.create() contract_term_conditions = [ ContractTermConditionFactory.create( contract_term=contract_term, priority=priority ) for priority in remaining_priorities ] mock_models.ContractTermCondition.get_active_term_conditions_with_order_by \ .return_value = contract_term_conditions logic._reprioritize([contract_term.contract_term_id]) for condition in contract_term_conditions: assert condition.priority not in remaining_priorities assert contract_term_conditions[0].priority == 1 assert contract_term_conditions[1].priority == 2 @patch('abacus_contract.logic.contract_term_condition.models') def test_validate_soft_deletion_condition_does_not_exist(mock_models): """Validation returns error if contract_term_condition_id is invalid.""" contract_term = ContractTermFactory.create() contract_term_conditions = ContractTermConditionFactory.create_batch( 2, contract_term=contract_term ) contract_term_condition_ids = \ [condition.contract_term_condition_id for condition in contract_term_conditions] contract_term_conditions.append(99) mock_models.ContractTermCondition.get_class_name.return_value = \ 'ContractTermCondition' res = logic._validate_soft_deletion( contract_term_conditions, contract_term_condition_ids, [contract_term.contract_term_id] ) assert res.status == 400 assert res.errors['code'] == 'error' assert res.errors['message'] == ERROR_ENTITY_DOES_NOT_EXIST.format( object_type='ContractTermCondition', object_id='' ) def test_validate_soft_deletion_cannot_delete_only_condition(): """Validation returns error when trying to delete only active condition.""" contract_term_condition = ContractTermConditionFactory.create() res = logic._validate_soft_deletion( [contract_term_condition], [contract_term_condition.contract_term_condition_id], [contract_term_condition.contract_term_id] ) assert res.status == 400 assert res.errors['code'] == 'error' assert res.errors['message'] == ERROR_CANNOT_DELETE_CONTRACT_TERM_CONDITION def test_validate_soft_deletion_cannot_delete_all_conditions(): """Validation returns error when trying to delete all active conditions.""" contract_term = ContractTermFactory.create() contract_term_conditions = ContractTermConditionFactory.create_batch( 3, contract_term=contract_term ) contract_term_condition_ids = \ [condition.contract_term_condition_id for condition in contract_term_conditions] res = logic._validate_soft_deletion( contract_term_conditions, contract_term_condition_ids, [contract_term.contract_term_id] ) assert res.status == 400 assert res.errors['code'] == 'error' assert res.errors['message'] == ERROR_CANNOT_DELETE_CONTRACT_TERM_CONDITION