"""Unit tests for payment search logic.""" import datetime from unittest.mock import call, MagicMock, patch import pytest from payment.constants.constants import ( PAYMENT_SEARCH_COLUMNS, PAYMENT_SEARCH_LIMIT, PAYMENT_SEARCH_QUERY, ) from payment.constants.error import ERROR_PAYMENTS_SEARCH_REQUIRED_FILTERS from payment.logic import payment_search as logic from payment.logic.exceptions import LogicError from payment.models.generic import Items @pytest.fixture def mock_client(): with patch('payment.logic.payment_search.get_client') as mock_get_client: client = MagicMock() mock_get_client.return_value = client yield client def test_search_payments_no_filters_raises_logic_error(mock_client): with pytest.raises(LogicError, match=ERROR_PAYMENTS_SEARCH_REQUIRED_FILTERS): logic.search_payments() mock_client.search.assert_not_called() def test_search_payments_returns_items_with_total_count(mock_client): mock_items = [{'_id': '1'}, {'_id': '2'}] mock_client.search.return_value = mock_items result = logic.search_payments(account='100') assert result == Items(mock_items, 2) assert result.total_count == 2 assert result.items == mock_items def test_search_payments_passes_correct_query_and_limit(mock_client): mock_client.search.return_value = [] logic.search_payments(account='100') assert mock_client.search.call_args_list == [ call( query=PAYMENT_SEARCH_QUERY, columns=list(PAYMENT_SEARCH_COLUMNS), limit=PAYMENT_SEARCH_LIMIT, query_filter={ '@or': [ {'@eq': {PAYMENT_SEARCH_COLUMNS.ACCOUNT_ID: '100'}}, {'@eq': {PAYMENT_SEARCH_COLUMNS.ACCOUNT_NAME: '100'}}, ] }, ) ] def test_search_payments_account_filter(mock_client): mock_client.search.return_value = [] logic.search_payments(account='10863') assert mock_client.search.call_args_list == [ call( query=PAYMENT_SEARCH_QUERY, columns=list(PAYMENT_SEARCH_COLUMNS), limit=PAYMENT_SEARCH_LIMIT, query_filter={ '@or': [ {'@eq': {PAYMENT_SEARCH_COLUMNS.ACCOUNT_ID: '10863'}}, {'@eq': {PAYMENT_SEARCH_COLUMNS.ACCOUNT_NAME: '10863'}}, ] }, ) ] def test_search_payments_contract_filter(mock_client): mock_client.search.return_value = [] logic.search_payments(contract='87653') assert mock_client.search.call_args_list == [ call( query=PAYMENT_SEARCH_QUERY, columns=list(PAYMENT_SEARCH_COLUMNS), limit=PAYMENT_SEARCH_LIMIT, query_filter={ '@or': [ {'@eq': {PAYMENT_SEARCH_COLUMNS.CONTRACT_ID: '87653'}}, {'@eq': {PAYMENT_SEARCH_COLUMNS.CONTRACT_NAME: '87653'}}, ] }, ) ] def test_search_payments_payment_types_single_value(mock_client): mock_client.search.return_value = [] logic.search_payments(payment_types=['balance_payment']) assert mock_client.search.call_args_list == [ call( query=PAYMENT_SEARCH_QUERY, columns=list(PAYMENT_SEARCH_COLUMNS), limit=PAYMENT_SEARCH_LIMIT, query_filter={ '@or': [ {'@eq': {PAYMENT_SEARCH_COLUMNS.PAYMENT_TYPE: 'balance_payment'}} ] }, ) ] def test_search_payments_payment_types_multiple_values_uses_or(mock_client): mock_client.search.return_value = [] logic.search_payments(payment_types=['balance_payment', 'advance_payment']) assert mock_client.search.call_args_list == [ call( query=PAYMENT_SEARCH_QUERY, columns=list(PAYMENT_SEARCH_COLUMNS), limit=PAYMENT_SEARCH_LIMIT, query_filter={ '@or': [ {'@eq': {PAYMENT_SEARCH_COLUMNS.PAYMENT_TYPE: 'balance_payment'}}, {'@eq': {PAYMENT_SEARCH_COLUMNS.PAYMENT_TYPE: 'advance_payment'}}, ] }, ) ] def test_search_payments_payment_statuses_multiple_values_uses_or(mock_client): mock_client.search.return_value = [] logic.search_payments(payment_statuses=['successful', 'cancelled']) assert mock_client.search.call_args_list == [ call( query=PAYMENT_SEARCH_QUERY, columns=list(PAYMENT_SEARCH_COLUMNS), limit=PAYMENT_SEARCH_LIMIT, query_filter={ '@or': [ {'@eq': {PAYMENT_SEARCH_COLUMNS.PAYMENT_STATUS: 'successful'}}, {'@eq': {PAYMENT_SEARCH_COLUMNS.PAYMENT_STATUS: 'cancelled'}}, ] }, ) ] def test_search_payments_payment_release_date_from_filter(mock_client): mock_client.search.return_value = [] logic.search_payments(payment_release_date_from=datetime.date(2025, 1, 1)) assert mock_client.search.call_args_list == [ call( query=PAYMENT_SEARCH_QUERY, columns=list(PAYMENT_SEARCH_COLUMNS), limit=PAYMENT_SEARCH_LIMIT, query_filter={ '@gte': {PAYMENT_SEARCH_COLUMNS.PAYMENT_RELEASE_DATE: '2025-01-01'} }, ) ] def test_search_payments_payment_release_date_to_filter(mock_client): mock_client.search.return_value = [] logic.search_payments(payment_release_date_to=datetime.date(2025, 3, 31)) assert mock_client.search.call_args_list == [ call( query=PAYMENT_SEARCH_QUERY, columns=list(PAYMENT_SEARCH_COLUMNS), limit=PAYMENT_SEARCH_LIMIT, query_filter={ '@lte': {PAYMENT_SEARCH_COLUMNS.PAYMENT_RELEASE_DATE: '2025-03-31'} }, ) ] def test_search_payments_payment_created_date_from_filter(mock_client): mock_client.search.return_value = [] logic.search_payments(payment_created_date_from=datetime.date(2025, 1, 1)) assert mock_client.search.call_args_list == [ call( query=PAYMENT_SEARCH_QUERY, columns=list(PAYMENT_SEARCH_COLUMNS), limit=PAYMENT_SEARCH_LIMIT, query_filter={ '@gte': {PAYMENT_SEARCH_COLUMNS.PAYMENT_CREATED_DATE: '2025-01-01'} }, ) ] def test_search_payments_payment_created_date_to_filter(mock_client): mock_client.search.return_value = [] logic.search_payments(payment_created_date_to=datetime.date(2025, 3, 31)) assert mock_client.search.call_args_list == [ call( query=PAYMENT_SEARCH_QUERY, columns=list(PAYMENT_SEARCH_COLUMNS), limit=PAYMENT_SEARCH_LIMIT, query_filter={ '@lte': {PAYMENT_SEARCH_COLUMNS.PAYMENT_CREATED_DATE: '2025-03-31'} }, ) ] def test_search_payments_payment_release_date_range_wraps_in_and(mock_client): mock_client.search.return_value = [] logic.search_payments( payment_release_date_from=datetime.date(2025, 1, 1), payment_release_date_to=datetime.date(2025, 3, 31), ) assert mock_client.search.call_args_list == [ call( query=PAYMENT_SEARCH_QUERY, columns=list(PAYMENT_SEARCH_COLUMNS), limit=PAYMENT_SEARCH_LIMIT, query_filter={ '@and': [ { '@gte': { PAYMENT_SEARCH_COLUMNS.PAYMENT_RELEASE_DATE: '2025-01-01' } }, { '@lte': { PAYMENT_SEARCH_COLUMNS.PAYMENT_RELEASE_DATE: '2025-03-31' } }, ] }, ) ] def test_search_payments_payment_created_date_range_wraps_in_and(mock_client): mock_client.search.return_value = [] logic.search_payments( payment_created_date_from=datetime.date(2025, 1, 1), payment_created_date_to=datetime.date(2025, 3, 31), ) assert mock_client.search.call_args_list == [ call( query=PAYMENT_SEARCH_QUERY, columns=list(PAYMENT_SEARCH_COLUMNS), limit=PAYMENT_SEARCH_LIMIT, query_filter={ '@and': [ { '@gte': { PAYMENT_SEARCH_COLUMNS.PAYMENT_CREATED_DATE: '2025-01-01' } }, { '@lte': { PAYMENT_SEARCH_COLUMNS.PAYMENT_CREATED_DATE: '2025-03-31' } }, ] }, ) ] def test_search_payments_multiple_filters_wraps_in_and(mock_client): mock_client.search.return_value = [] logic.search_payments(account='100', contract='456') query_filter = mock_client.search.call_args_list[0].kwargs['query_filter'] assert '@and' in query_filter assert len(query_filter['@and']) == 2 def test_search_payments_all_filters(mock_client): mock_client.search.return_value = [] logic.search_payments( account='10863', contract='87653', payment_types=['balance_payment', 'advance_payment'], payment_statuses=['successful', 'cancelled'], payment_release_date_from=datetime.date(2025, 1, 1), payment_release_date_to=datetime.date(2025, 3, 31), payment_created_date_from=datetime.date(2025, 1, 1), payment_created_date_to=datetime.date(2025, 3, 31), ) query_filter = mock_client.search.call_args_list[0].kwargs['query_filter'] assert '@and' in query_filter assert len(query_filter['@and']) == 8