"""Helper functions for tax insertion cross lambda integration tests.""" from decimal import Decimal import logging from typing import Any, Dict, List, Optional from tests.utils import db from tests.utils.csv_helpers import generate_random_filename log = logging.getLogger(__name__) def seed_data() -> dict[str, Any]: return { 'account_id': 73144, 'contract_id': 549403, 'statement_period_id': 312, 'currency_code': 'GBP', 'currency_amount': 1000, 'country_of_tax_residence': 'TUR', 'country_of_tax_policy': 'GBR', } def seed_payment_name(statement_period_status: str) -> str: """Generate a payment name that matches seed data: https://github.com/theorchard/python-rds-utils/blob/989ff0769dad80aea020bb09ed21da1a26c2e7c2/lambda/sanitise_rds_data/scripts/qa-royalty-accounting/08-tax_insertion_data_for_testing.sql#L70.""" formatted_status = statement_period_status.capitalize() return f'Test Tax Insertion Seeding Payment - {formatted_status} Period' def tax_insertion_correction_file_data( statement_period_id: Any, ) -> List[Dict[str, Any]]: note_prefix = generate_random_filename('TaxInsertionCorrection') return [ { 'account_id': 73144, 'contract_id': 549403, 'correction_statement_period_id': statement_period_id, 'correction_type': 'wht', 'amount': 100, 'currency_code': 'GBP', 'note': f'{note_prefix}:tax insertion cross lambda test', }, ] def tax_insertion_vat_file_data(statement_period_id: Any) -> List[Dict[str, Any]]: note_prefix = generate_random_filename('TaxInsertionVAT') return [ { 'statement_period_id': statement_period_id, 'account_id': 73144, 'contract_id': 549403, 'vat_category': 'closing_balance', 'payee_currency_code': 'GBP', 'vat_currency_code': 'GBP', 'base_amount_payee_currency': 1000, 'vat_rate': 20, 'vat_amount_payee_currency': 200, 'vat_amount_vat_currency': 200, 'net_amount_payee_currency': 800, 'note': f'{note_prefix}: tax insertion cross lambda test', }, ] def resolve_statement_period_id(db_session: Any, statement_period_status: str) -> int: if statement_period_status == 'current': table_name = 'statement_period' conditions = {'statement_period_status': 'current'} result = db.get_entity(db_session, table_name, conditions) if result: return int(result['statement_period_id']) raise ValueError("No 'current' statement_period found in the database.") if statement_period_status == 'closed': return int(seed_data()['statement_period_id']) raise ValueError( f"Invalid statement_period_status: '{statement_period_status}'. Expected 'current' or 'closed'." ) def generate_file_data( filename_prefix: str, statement_period_id: int ) -> list[dict[str, Any]]: if 'Correction' in filename_prefix: return tax_insertion_correction_file_data(statement_period_id) elif 'VAT' in filename_prefix: return tax_insertion_vat_file_data(statement_period_id) else: raise ValueError(f'Unsupported filename_prefix: {filename_prefix}') def get_payment_group_payment_id( db_session: Any, statement_period_id: int, statement_period: str ) -> Optional[Any]: """Retrieves the payment_group_payment_id from the database: https://github.com/theorchard/python-rds-utils/blob/989ff0769dad80aea020bb09ed21da1a26c2e7c2/lambda/sanitise_rds_data/scripts/qa-royalty-accounting/08-tax_insertion_data_for_testing.sql#L87-#L93""" payment_conditions = { 'payment_name': seed_payment_name(statement_period), 'statement_period_id': statement_period_id, } payment_group_payment_id = db.get_max_value( db_session, 'payment_group_payment', 'payment_group_payment_id', payment_conditions, ) if not payment_group_payment_id: log.error('Failed to retrieve payment_group_payment_id') return None return payment_group_payment_id def get_abacus_event_id( db_session: Any, statement_period_id: Any, payment_group_payment_id: Any ) -> Optional[Any]: """Retrieves the abacus_event_id from the database.""" abacus_conditions = { 'event_name': 'calculate_payments', 'statement_period_id': statement_period_id, 'target_type': 'payment_group_payment', 'target_id': payment_group_payment_id, } abacus_event_id = db.get_max_value( db_session, 'abacus_event', 'abacus_event_id', abacus_conditions ) if not abacus_event_id: log.error('Failed to retrieve abacus_event_id') return None return abacus_event_id def to_decimal(value: Any, quantize: bool = True) -> Decimal: """Convert to Decimal and optionally quantize to 2 decimal places.""" d = Decimal(value) return d.quantize(Decimal('0.00')) if quantize else d def assert_common_payment_fields(db_result: Dict[str, Any]) -> None: expected_account_id = int(seed_data()['account_id']) expected_currency = seed_data()['currency_code'] expected_amount = to_decimal(seed_data()['currency_amount']) assert ( int(db_result['account_id']) == expected_account_id ), f"account_id mismatch: expected {expected_account_id}, got {db_result['account_id']}" assert ( db_result['currency_code'] == expected_currency ), f"currency_code mismatch: expected {expected_currency}, got {db_result['currency_code']}" assert ( db_result['current_balance'] == expected_amount ), f"current_balance mismatch: expected {expected_amount}, got {db_result['current_balance']}" def assert_payment_vat_data( statement_period_id: int, db_result: Dict[str, Any] ) -> None: """Verify VAT-related fields in payment group account.""" vat_data = tax_insertion_vat_file_data(statement_period_id)[0] expected_vat = to_decimal(vat_data['vat_amount_payee_currency']) expected_balance_after_tax = to_decimal( seed_data()['currency_amount'] + vat_data['vat_amount_payee_currency'] ) assert_common_payment_fields(db_result) assert ( db_result['vat_amount'] == expected_vat ), f"vat_amount mismatch: expected {expected_vat}, got {db_result['vat_amount']}" assert ( db_result['balance_after_tax'] == expected_balance_after_tax ), f"balance_after_tax mismatch: expected {expected_balance_after_tax}, got {db_result['current_balance']}" def assert_payment_correction_data( statement_period_id: int, db_result: Dict[str, Any] ) -> None: """Verify correction-related fields in payment group account.""" correction_data = tax_insertion_correction_file_data(statement_period_id)[0] expected_withholding = to_decimal(correction_data['amount']) expected_balance_after_tax = to_decimal( seed_data()['currency_amount'] + correction_data['amount'] ) assert_common_payment_fields(db_result) assert ( db_result['tax_withholding'] == expected_withholding ), f"tax_withholding mismatch: expected {expected_withholding}, got {db_result['tax_withholding']}" assert ( db_result['balance_after_tax'] == expected_balance_after_tax ), f"balance_after_tax mismatch: expected {expected_balance_after_tax}, got {db_result['balance_after_tax']}"