"""Unit tests for payment_group_payment_account schemas.""" from marshmallow import ValidationError import pytest from payment.constants.constants import ( DEFAULT_PAGE_LIMIT, DEFAULT_PAGE_OFFSET, DEFAULT_SORT_BY, DEFAULT_SORT_ORDER, PAYMENT_ACCOUNT_SORTABLE_COLUMNS, ) from payment.constants.error import ERROR_INVALID_SORT_BY, ERROR_INVALID_SORT_ORDER from payment.schemas.payment_group_payment_account import ( ContractsPayableSchema, PaymentGroupPaymentAccountFilterKeySchema, PaymentGroupPaymentAccountListSchema, PaymentGroupPaymentAccountPaginationSchema, PaymentGroupPaymentAccountPutSchema, PaymentGroupPaymentAccountSchema, ) def test_contracts_payable_schema(): """Test contracts payable schema.""" body = {'contract_id': 123, 'current_balance': '100.00', 'currency_code': 'USD'} res = ContractsPayableSchema().dump(body) assert res assert res == body def test_payment_group_payment_account_list_schema(): """Test list schema.""" body = { 'account_id': 123, 'account_name': 'Account Name', 'account_payee_id': 123, 'contracts_payable': [ {'contract_id': 123, 'current_balance': '100.00', 'currency_code': 'USD'} ], 'currency_code': 'USD', 'currency_name': 'US Dollars', 'current_balance': 100.00, 'last_payment': 500.00, 'payment_difference': -400.00, 'percent_difference': -80.00, 'payment_group_payment_account_id': 1, 'payment_group_payment_id': 2, 'payoneer_payee_id': 4, 'payoneer_program_id': 1234, } res = PaymentGroupPaymentAccountListSchema(many=True).dump([body]) assert res assert res[0] == { 'account_id': body.get('account_id'), 'account_name': body.get('account_name'), 'account_payee_id': body.get('account_payee_id'), 'contracts_payable': body.get('contracts_payable'), 'currency_code': body.get('currency_code'), 'currency_name': body.get('currency_name'), 'current_balance': str(body.get('current_balance')), 'last_payment': str(body.get('last_payment')), 'payment_difference': str(body.get('payment_difference')), 'percent_difference': '{0:.2f}'.format(body.get('percent_difference')), 'payment_group_payment_account_id': body.get( 'payment_group_payment_account_id' ), 'payment_group_payment_id': body.get('payment_group_payment_id'), 'payoneer_payee_id': body.get('payoneer_payee_id'), 'payoneer_program_id': body.get('payoneer_program_id'), } def test_payment_group_payment_account_put_schema(): """Test PUT schema.""" body = {'note': 'blah'} res = PaymentGroupPaymentAccountPutSchema().dump(body) assert res assert res.get('note') == body.get('note') def test_payment_group_payment_account_detail_schema(): """Test detail schema.""" body = { 'account_id': 123, 'contracts_payable': [ {'contract_id': 123, 'current_balance': '99.00', 'currency_code': 'USD'}, {'contract_id': 123, 'current_balance': '1.00', 'currency_code': 'USD'}, ], 'currency_code': 'USD', 'current_balance': 100.00, 'vat_amount': 10.01, 'tax_withholding': -11.01, 'last_payment': 0.00, 'note': 'blah', 'payment_group_payment_account_id': 1, 'payment_group_payment_id': 2, } res = PaymentGroupPaymentAccountSchema().dump(body) assert res assert res.get('account_id') == body.get('account_id') assert res.get('contracts_payable') == body.get('contracts_payable') assert res.get('currency_code') == body.get('currency_code') assert res.get('current_balance') == str(body.get('current_balance')) assert res.get('last_payment') == str(body.get('last_payment')) assert res.get('note') == body.get('note') assert res.get('payment_group_payment_id') == body.get('payment_group_payment_id') assert res.get('payment_group_payment_account_id') == body.get( 'payment_group_payment_account_id' ) assert res.get('vat_amount') == str(body.get('vat_amount')) assert res.get('tax_withholding') == str(body.get('tax_withholding')) def test_payment_group_payment_account_filter_key_schema_split(): """Test splitting comma-separated strings into lists with trimming.""" data = { 'account_ids': '1, 2 ,3,', 'contract_ids': '4,5', 'payment_statuses': 'posted, pending , ,failed', } res = PaymentGroupPaymentAccountFilterKeySchema().load(data) assert res assert res['account_ids'] == [1, 2, 3] assert res['contract_ids'] == [4, 5] assert res['payment_statuses'] == ['posted', 'pending', 'failed'] def test_payment_group_payment_account_filter_key_schema_no_split(): """Test that pre-parsed lists remain unchanged.""" data = { 'account_ids': [10, 11], 'contract_ids': [20, 21], 'payment_statuses': ['posted'], } res = PaymentGroupPaymentAccountFilterKeySchema().load(data) assert res == data def test_sort_schema_defaults(): """Test default values for sort_by and sort_order.""" data = {} res = PaymentGroupPaymentAccountPaginationSchema().load(data) assert res['sort_by'] == DEFAULT_SORT_BY assert res['sort_order'] == DEFAULT_SORT_ORDER def test_sort_schema_valid_values(): """Test valid sort_by and sort_order values.""" for col in PAYMENT_ACCOUNT_SORTABLE_COLUMNS: for order in ['asc', 'desc', 'ASC', 'DESC']: data = {'sort_by': col, 'sort_order': order} res = PaymentGroupPaymentAccountPaginationSchema().load(data) assert res['sort_by'] == col assert res['sort_order'].lower() == order.lower() def test_sort_schema_invalid_sort_by(): """Test invalid sort_by value.""" data = {'sort_by': 'invalid_column'} with pytest.raises(ValidationError) as exc: PaymentGroupPaymentAccountPaginationSchema().load(data) assert 'sort_by' in exc.value.messages assert ( ERROR_INVALID_SORT_BY.format(sort_by='invalid_column') in exc.value.messages['sort_by'][0] ) def test_sort_schema_invalid_sort_order(): """Test invalid sort_order value.""" data = {'sort_order': 'invalid_order'} with pytest.raises(ValidationError) as exc: PaymentGroupPaymentAccountPaginationSchema().load(data) assert 'sort_order' in exc.value.messages assert ERROR_INVALID_SORT_ORDER in exc.value.messages['sort_order'][0] def test_sort_schema_with_search_term(): """Test schema with search_term.""" data = {'search_term': 'test'} res = PaymentGroupPaymentAccountPaginationSchema().load(data) assert res['search_term'] == 'test' def test_pagination_schema_limit_default(): data = {} res = PaymentGroupPaymentAccountPaginationSchema().load(data) assert res['limit'] == DEFAULT_PAGE_LIMIT def test_pagination_schema_offset_default(): data = {} res = PaymentGroupPaymentAccountPaginationSchema().load(data) assert res['offset'] == DEFAULT_PAGE_OFFSET def test_pagination_schema_limit_valid(): data = {'limit': 10} res = PaymentGroupPaymentAccountPaginationSchema().load(data) assert res['limit'] == 10 def test_pagination_schema_offset_valid(): data = {'offset': 5} res = PaymentGroupPaymentAccountPaginationSchema().load(data) assert res['offset'] == 5 def test_pagination_schema_limit_too_low(): data = {'limit': 0} with pytest.raises(ValidationError) as exc: PaymentGroupPaymentAccountPaginationSchema().load(data) assert 'limit' in exc.value.messages def test_pagination_schema_limit_too_high(): data = {'limit': 5001} with pytest.raises(ValidationError) as exc: PaymentGroupPaymentAccountPaginationSchema().load(data) assert 'limit' in exc.value.messages def test_pagination_schema_offset_negative(): data = {'offset': -1} with pytest.raises(ValidationError) as exc: PaymentGroupPaymentAccountPaginationSchema().load(data) assert 'offset' in exc.value.messages def test_pagination_schema_limit_max(): """Test that max allowed limit (5000) is accepted.""" data = {'limit': 5000} res = PaymentGroupPaymentAccountPaginationSchema().load(data) assert res['limit'] == 5000 def test_pagination_schema_limit_above_max(): """Test that limit above max (5001) raises ValidationError.""" data = {'limit': 5001} with pytest.raises(ValidationError) as exc: PaymentGroupPaymentAccountPaginationSchema().load(data) assert 'limit' in exc.value.messages