"""Generate tax form report 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_payee import get_tax_form_info_details_bulk from src.constants import DEFAULT_BATCH_SIZE from src.models import TaxFormInfoDetailsItem from src.processors.base import ReportProcessor from src.processors.exceptions import ProcessingError from src.utils import chunks class GenerateReportTaxFormProcessor(ReportProcessor): """ Processor to generate tax form report. Expects the CSV file with the following columns: - vendor_id (int) The first row is a header. """ _report_type: str = 'tax_forms' _output_columns = ['vendor_id'] + list(TaxFormInfoDetailsItem.model_fields.keys()) _account_ids: list[int] _account_payee_id_account_id: dict[int, int] def process(self) -> None: """Run main logic.""" self._load_csv_accounts() self._load_payees_by_accounts() self._load_tax_form_data() @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 process') logger.info(f'Loaded {len(self._account_ids)} items.') def _load_payees_by_accounts(self) -> None: """Get account payee IDs by account IDs.""" account_id_to_account_payee_id = get_payees_by_accounts(self._account_ids) self._account_payee_id_account_id = { account_payee_id: account_id for account_id, account_payee_id in account_id_to_account_payee_id.items() } missing_account_ids = ( set(self._account_ids) - account_id_to_account_payee_id.keys() ) if missing_account_ids: self.capture_error(f'Accounts not found: {missing_account_ids}') def _load_tax_form_data(self) -> None: """Get tax form details data for account payees.""" self._output_data = [] for chunk_items in chunks( list(self._account_payee_id_account_id.keys()), DEFAULT_BATCH_SIZE ): result = get_tax_form_info_details_bulk( chunk_items, limit=DEFAULT_BATCH_SIZE ) for tax_form in result.items: self._output_data.append( { 'vendor_id': self._account_payee_id_account_id[ tax_form.account_payee_id ], **dict(tax_form), } )