"""Test contract reserve logic.""" from unittest.mock import patch import pytest from abacus_contract.constants.error import ERROR_INVALID_RELEASE_SCHEDULE from abacus_contract.constants.error import ERROR_RESERVE_MUST_BE_ACTIVE_TO_UPDATE from abacus_contract.logic import contract_reserve as logic from tests.utils.factories import ContractFactory from tests.utils.factories import ContractReserveFactory @patch('abacus_contract.logic.contract_reserve.models') def test_create_reserve_without_release_schedule(mock_models): """Test successful creation of contract_reserve without release_schedule.""" # noqa: E501 contract = ContractFactory.create() mock_models.Contract.get_by_id_or_error.return_value = contract mock_models.ContractReserve.create.return_value = contract params = { 'contract_id': contract.contract_id, 'reserve_rate': 50, 'reserve_release_offset_in_months': 1, 'installments_in_months': 2 } res = logic.create_contract_reserve(**params) assert res.status == 201 mock_models.ContractReserve.create.assert_called_once_with( contract_id=1, reserve_rate=50, reserve_release_offset_in_months=1, installments_in_months=2, release_schedule=['0.500000000000', '0.500000000000'] ) @patch('abacus_contract.logic.contract_reserve.models') def test_create_reserve_with_release_schedule(mock_models): """Test successful creation of contract_reserve with release_schedule.""" contract = ContractFactory.create() mock_models.Contract.get_by_id_or_error.return_value = contract mock_models.ContractReserve.create.return_value = contract params = { 'contract_id': contract.contract_id, 'reserve_rate': 50, 'reserve_release_offset_in_months': 1, 'installments_in_months': 2, 'release_schedule': ['0.25', '0.75'] } res = logic.create_contract_reserve(**params) assert res.status == 201 mock_models.ContractReserve.create.assert_called_once_with( contract_id=1, reserve_rate=50, reserve_release_offset_in_months=1, installments_in_months=2, release_schedule=['0.25', '0.75'] ) @patch('abacus_contract.logic.contract_reserve.models') def test_update_contract_reserve_by_contract_id(mock_models): """Test successful update of contract_reserve by contract_id.""" contract_reserve = ContractReserveFactory.create() mock_models.Contract.get_by_id_or_error.return_value = contract_reserve.contract mock_models.ContractReserve.create.return_value = ContractReserveFactory.create( contract=contract_reserve.contract) params = { 'contract_id': contract_reserve.contract_id, 'reserve_rate': 50, 'reserve_release_offset_in_months': 1, 'installments_in_months': 2, 'release_schedule': ['0.25', '0.75'] } res = logic.update_contract_reserve_by_contract_id(**params) assert res.status == 201 mock_models.ContractReserve.delete_by_id_or_error.assert_called_once_with( contract_reserve.contract_reserve_id, soft_delete=True ) mock_models.ContractReserve.create.assert_called_once_with( contract_id=contract_reserve.contract_id, reserve_rate=50, reserve_release_offset_in_months=1, installments_in_months=2, release_schedule=['0.25', '0.75'] ) @patch('abacus_contract.logic.contract_reserve.models') def test_update_missing_contract_reserve_by_contract_id_(mock_models): """Test unsuccessful update of contract_reserve by contract_id.""" contract = ContractFactory.create() mock_models.Contract.get_by_id_or_error.return_value = contract params = { 'contract_id': contract.contract_id, 'reserve_rate': 50, 'reserve_release_offset_in_months': 1, 'installments_in_months': 2, 'release_schedule': ['0.25', '0.75'] } res = logic.update_contract_reserve_by_contract_id(**params) assert res.status == 400 assert res.errors['message'] == ERROR_RESERVE_MUST_BE_ACTIVE_TO_UPDATE assert not mock_models.ContractReserve.delete_by_id_or_error.called assert not mock_models.ContractReserve.create.called @patch('abacus_contract.logic.contract_reserve.models') def test_get_reserve_by_contract_id(mock_models): """Test get contract_reserve for a specified contract.""" contract = ContractFactory.create() ContractReserveFactory.create(contract=contract) mock_models.Contract.get_by_id_or_error.return_value = contract res = logic.get_reserve_by_contract_id(contract.contract_id) assert res.status == 200 assert res.message == { 'release_schedule': ['0.250000000000', '0.250000000000', '0.250000000000', '0.250000000000'], 'contract_reserve_id': 1, 'installments_in_months': 4, 'reserve_release_offset_in_months': 2, 'reserve_rate': '80.00', 'contract_id': 1 } mock_models.Contract.get_by_id_or_error \ .assert_called_once_with(contract.contract_id) def test_calculate_release_schedule(): """Test _calculate_release_schedule function.""" installments_in_months = 7 res = logic._calculate_release_schedule(installments_in_months) assert res == [ '0.142857142857', '0.142857142857', '0.142857142857', '0.142857142857', '0.142857142857', '0.142857142857', '0.142857142858' ] def test_validate_release_schedule_success(): """Test _validate_release_schedule function for valid release_schedule values.""" res = logic._validate_release_schedule(['0.7774', '0.2226']) assert res == ['0.7774', '0.2226'] def test_validate_release_schedule_error(): """Test _validate_release_schedule function for invalid release_schedule values.""" with pytest.raises( Exception, match=ERROR_INVALID_RELEASE_SCHEDULE ): logic._validate_release_schedule(['10', '0.1']) @patch('abacus_contract.logic.contract_reserve.models') def test_get_contract_reserves_by_ids(mock_models): """Test get_contract_reserves_by_ids function.""" contracts = ContractFactory.create_batch(2) contract_reserves = [ ContractReserveFactory.create(contract=contract) for contract in contracts ] contract_reserve_ids = [cr.contract_reserve_id for cr in contract_reserves] mock_models.ContractReserve.get_by_ids.return_value = contract_reserves res = logic.get_contract_reserves_by_ids(contract_reserve_ids) assert res.status == 200 assert len(res.message) == len(contract_reserves) mock_models.ContractReserve.get_by_ids.assert_called_once_with(contract_reserve_ids) @patch('abacus_contract.logic.contract_reserve.models') def test_get_contract_reserves_by_contract_ids(mock_models): """Test get_contract_reserves_by_contract_ids function.""" contracts = ContractFactory.create_batch(2) contract_reserves = [ ContractReserveFactory.create(contract=contract) for contract in contracts ] contract_ids = [c.contract_id for c in contracts] mock_models.ContractReserve.get_by_contract_ids.return_value = contract_reserves res = logic.get_contract_reserves_by_contract_ids(contract_ids) assert res.status == 200 assert len(res.message) == len(contract_reserves) mock_models.ContractReserve.get_by_contract_ids.assert_called_once_with( contract_ids )