"""Unit tests for payment search schemas.""" import datetime from payment.constants.error import ERROR_PAYMENTS_SEARCH_REQUIRED_FILTERS from payment.schemas.payment_search import ( PaymentSearchFilterParamsPostSchema, PaymentSearchItemSchema, PaymentSearchListSchema, ) from tests.utils.factories import PaymentSearchItemFactory class TestPaymentSearchFilterParamsPostSchema: def test_load_empty_filters_returns_validation_error(self): errors = PaymentSearchFilterParamsPostSchema().validate({'filters': {}}) assert 'filters' in errors assert ERROR_PAYMENTS_SEARCH_REQUIRED_FILTERS in str(errors['filters']) def test_load_all_filters(self): data = { 'filters': { 'account': '10863', 'contract': '87653', 'payment_types': ['balance_payment', 'advance_payment'], 'payment_statuses': ['successful', 'cancelled'], 'payment_release_date_from': '2025-01-01', 'payment_release_date_to': '2025-03-31', 'payment_created_date_from': '2025-01-01', 'payment_created_date_to': '2025-03-31', } } result = PaymentSearchFilterParamsPostSchema().load(data) filters = result['filters'] assert filters['account'] == '10863' assert filters['contract'] == '87653' assert filters['payment_types'] == ['balance_payment', 'advance_payment'] assert filters['payment_statuses'] == ['successful', 'cancelled'] assert filters['payment_release_date_from'] == datetime.date(2025, 1, 1) assert filters['payment_release_date_to'] == datetime.date(2025, 3, 31) assert filters['payment_created_date_from'] == datetime.date(2025, 1, 1) assert filters['payment_created_date_to'] == datetime.date(2025, 3, 31) def test_load_single_account_filter(self): result = PaymentSearchFilterParamsPostSchema().load( {'filters': {'account': '10863'}} ) assert result == {'filters': {'account': '10863'}} def test_load_all_valid_payment_types(self): data = { 'filters': { 'payment_types': [ 'balance_payment', 'advance_payment', 'custom_payment', ] } } result = PaymentSearchFilterParamsPostSchema().load(data) assert result['filters']['payment_types'] == [ 'balance_payment', 'advance_payment', 'custom_payment', ] def test_load_all_valid_payment_statuses(self): statuses = [ 'pending_acceptance', 'accepted', 'failure', 'successful', 'cancelled', 'not_paid', ] data = {'filters': {'payment_statuses': statuses}} result = PaymentSearchFilterParamsPostSchema().load(data) assert result['filters']['payment_statuses'] == statuses def test_load_invalid_date_returns_validation_error(self): errors = PaymentSearchFilterParamsPostSchema().validate( {'filters': {'payment_release_date_from': 'not-a-date'}} ) assert 'filters' in errors def test_load_invalid_created_date_returns_validation_error(self): errors = PaymentSearchFilterParamsPostSchema().validate( {'filters': {'payment_created_date_to': '31-12-2025'}} ) assert 'filters' in errors def test_load_invalid_payment_type_returns_validation_error(self): errors = PaymentSearchFilterParamsPostSchema().validate( {'filters': {'payment_types': ['invalid_type']}} ) assert 'filters' in errors def test_load_invalid_payment_status_returns_validation_error(self): errors = PaymentSearchFilterParamsPostSchema().validate( {'filters': {'payment_statuses': ['invalid_status']}} ) assert 'filters' in errors def test_payment_release_date_from_after_payment_release_date_to_returns_validation_error( self, ): errors = PaymentSearchFilterParamsPostSchema().validate( { 'filters': { 'payment_release_date_from': '2025-03-31', 'payment_release_date_to': '2025-01-01', } } ) assert 'filters' in errors def test_payment_created_date_from_after_payment_created_date_to_returns_validation_error( self, ): errors = PaymentSearchFilterParamsPostSchema().validate( { 'filters': { 'payment_created_date_from': '2025-12-31', 'payment_created_date_to': '2025-01-01', } } ) assert 'filters' in errors def test_payment_release_date_from_equal_to_payment_release_date_to_is_valid(self): result = PaymentSearchFilterParamsPostSchema().load( { 'filters': { 'payment_release_date_from': '2025-06-15', 'payment_release_date_to': '2025-06-15', } } ) assert result['filters']['payment_release_date_from'] == datetime.date( 2025, 6, 15 ) assert result['filters']['payment_release_date_to'] == datetime.date( 2025, 6, 15 ) def test_payment_created_date_from_equal_to_payment_created_date_to_is_valid(self): result = PaymentSearchFilterParamsPostSchema().load( { 'filters': { 'payment_created_date_from': '2025-06-15', 'payment_created_date_to': '2025-06-15', } } ) assert result['filters']['payment_created_date_from'] == datetime.date( 2025, 6, 15 ) assert result['filters']['payment_created_date_to'] == datetime.date( 2025, 6, 15 ) def test_only_payment_release_date_from_provided_is_valid(self): result = PaymentSearchFilterParamsPostSchema().load( {'filters': {'payment_release_date_from': '2025-01-01'}} ) assert result['filters']['payment_release_date_from'] == datetime.date( 2025, 1, 1 ) def test_only_payment_created_date_to_provided_is_valid(self): result = PaymentSearchFilterParamsPostSchema().load( {'filters': {'payment_created_date_to': '2025-12-31'}} ) assert result['filters']['payment_created_date_to'] == datetime.date( 2025, 12, 31 ) class TestPaymentSearchItemSchema: def test_dump_serializes_decimal_amounts_as_strings(self): mock_item = PaymentSearchItemFactory() result = PaymentSearchItemSchema().dump(mock_item) assert result['post_tax_amount'] == mock_item['post_tax_amount'] assert result['pre_tax_amount'] == mock_item['pre_tax_amount'] def test_dump_none_dates_remain_null(self): mock_item = PaymentSearchItemFactory() result = PaymentSearchItemSchema().dump(mock_item) assert result['payment_created_date'] is None assert result['payment_release_date'] is None def test_dump_empty_string_payment_created_date_serializes_to_none(self): mock_item = PaymentSearchItemFactory(payment_created_date='') result = PaymentSearchItemSchema().dump(mock_item) assert result['payment_created_date'] is None def test_dump_empty_string_payment_release_date_serializes_to_none(self): mock_item = PaymentSearchItemFactory(payment_release_date='') result = PaymentSearchItemSchema().dump(mock_item) assert result['payment_release_date'] is None def test_dump_iso_string_payment_created_date_serializes_correctly(self): mock_item = PaymentSearchItemFactory(payment_created_date='2025-03-15T10:30:00') result = PaymentSearchItemSchema().dump(mock_item) assert result['payment_created_date'] is not None assert '2025-03-15' in result['payment_created_date'] def test_dump_iso_string_payment_release_date_serializes_correctly(self): mock_item = PaymentSearchItemFactory(payment_release_date='2025-06-01T00:00:00') result = PaymentSearchItemSchema().dump(mock_item) assert result['payment_release_date'] is not None assert '2025-06-01' in result['payment_release_date'] def test_dump_allow_none_fields(self): mock_item = PaymentSearchItemFactory() result = PaymentSearchItemSchema().dump(mock_item) assert result['error_message'] is None def test_dump_all_fields_present(self): mock_item = PaymentSearchItemFactory() result = PaymentSearchItemSchema().dump(mock_item) assert result['_id'] == mock_item['_id'] assert result['account_id'] == mock_item['account_id'] assert result['account_name'] == mock_item['account_name'] assert result['contract_id'] == mock_item['contract_id'] assert result['contract_name'] == mock_item['contract_name'] assert result['currency'] == mock_item['currency'] assert result['payment_id'] == mock_item['payment_id'] assert result['payment_name'] == mock_item['payment_name'] assert result['payment_status'] == mock_item['payment_status'] assert result['payment_type'] == mock_item['payment_type'] assert result['statement_period_id'] == mock_item['statement_period_id'] assert result['statement_period_name'] == mock_item['statement_period_name'] assert ( result['sent_statement_period_id'] == mock_item['sent_statement_period_id'] ) assert ( result['sent_statement_period_name'] == mock_item['sent_statement_period_name'] ) def test_dump_payment_id_is_integer(self): mock_item = PaymentSearchItemFactory() result = PaymentSearchItemSchema().dump(mock_item) assert isinstance(result['payment_id'], int) def test_dump_statement_period_id_is_integer(self): mock_item = PaymentSearchItemFactory() result = PaymentSearchItemSchema().dump(mock_item) assert isinstance(result['statement_period_id'], int) def test_dump_normalizes_empty_string_sent_statement_period_id_to_none(self): mock_item = PaymentSearchItemFactory(sent_statement_period_id='') result = PaymentSearchItemSchema().dump(mock_item) assert result['sent_statement_period_id'] is None def test_dump_normalizes_empty_string_sent_statement_period_name_to_none(self): mock_item = PaymentSearchItemFactory(sent_statement_period_name='') result = PaymentSearchItemSchema().dump(mock_item) assert result['sent_statement_period_name'] is None def test_dump_normalizes_empty_string_error_message_to_none(self): mock_item = PaymentSearchItemFactory(error_message='') result = PaymentSearchItemSchema().dump(mock_item) assert result['error_message'] is None def test_dump_preserves_none_sent_statement_period_id(self): mock_item = PaymentSearchItemFactory(sent_statement_period_id=None) result = PaymentSearchItemSchema().dump(mock_item) assert result['sent_statement_period_id'] is None class TestPaymentSearchListSchema: def test_dump_returns_items_and_total_count(self): mock_item = PaymentSearchItemFactory() data = {'items': [mock_item], 'total_count': 1} result = PaymentSearchListSchema().dump(data) assert result['total_count'] == 1 assert len(result['items']) == 1 assert result['items'][0]['_id'] == mock_item['_id'] def test_dump_empty_items(self): data = {'items': [], 'total_count': 0} result = PaymentSearchListSchema().dump(data) assert result['total_count'] == 0 assert result['items'] == [] def test_dump_multiple_items(self): mock_item = PaymentSearchItemFactory() second_item = {**mock_item, '_id': '99999', 'account_id': 20000} data = {'items': [mock_item, second_item], 'total_count': 2} result = PaymentSearchListSchema().dump(data) assert result['total_count'] == 2 assert len(result['items']) == 2 assert result['items'][1]['_id'] == '99999'