"""Delete banking details processor.""" import csv from sentry_sdk import capture_message from config import app_logger as logger from src.connectors.ows_abacus_account import get_payees_by_accounts from src.connectors.ows_abacus_state import get_abacus_state from src.connectors.ows_payee import delete_banking_details from src.processors.base import Processor from src.processors.exceptions import ProcessingError class PurgeBankingDetailsProcessor(Processor): """ Processor to delete banking details. Expects the CSV file with the following columns: - vendor_id/account_id (int) The first row is a header. """ _account_ids: list[int] _account_id_to_payee_id: dict[int, int] _account_payee_ids: list[int] def process(self) -> None: """Run main logic.""" self._load_csv_accounts() self._load_payees_by_accounts() self._validate_payees() self._purge_banking_details() @staticmethod def capture_error(message: str) -> None: """Send error to sentry and log.""" logger.error(message) capture_message(message, level='error') def _load_csv_accounts(self) -> None: """Load data from file.""" logger.info('Loading data from csv file') try: raw_data = list(self.csv_dict_reader) except Exception as e: raise ProcessingError(f'Unable to read the file: {e}') try: self._account_ids = [int(item['vendor_id']) for item in raw_data] except Exception as e: raise ProcessingError(f'Invalid file content: {e}') if not self._account_ids: raise ProcessingError('No items in file to post') logger.info(f'Loaded {len(self._account_ids)} items.') def _load_payees_by_accounts(self) -> None: """Get account payee IDs by account IDs.""" self._account_id_to_payee_id = get_payees_by_accounts(self._account_ids) missing_account_ids = ( set(self._account_ids) - self._account_id_to_payee_id.keys() ) if missing_account_ids: self.capture_error(f'Accounts not found: {missing_account_ids}') def _validate_payees(self) -> None: """Validate that payees do not have banking_details_review status.""" self._account_payee_ids = [] payee_id_to_state = {} for account_payee_id in self._account_id_to_payee_id.values(): state = get_abacus_state(account_payee_id, 'banking_details_review') if state: payee_id_to_state[account_payee_id] = state.action_status else: self._account_payee_ids.append(account_payee_id) if payee_id_to_state: self.capture_error( f'Account payees have banking_details_review state {payee_id_to_state}' ) def _purge_banking_details(self) -> None: """Delete banking details.""" for account_payee_id in self._account_payee_ids: delete_banking_details(account_payee_id)