"""Backfill VAT summary entries.""" import logging import sys from dotenv import load_dotenv load_dotenv() sys.path.append('') logging.basicConfig(level=logging.INFO) from moneyhub.constants.constants import Environment # noqa: I100, E402 from moneyhub.constants.constants import StatementAttachmentStatus # noqa: I100, E402 from moneyhub.constants.constants import StatementAttachmentType # noqa: I100, E402 from moneyhub.models import Account # noqa: I100, E402 from moneyhub.models import StatementAttachment # noqa: I100, E402 from scripts.dataclass import InternalAttachment # noqa: I100, E402 from scripts.dynamodb import get_dynamodb_table # noqa: I100, E402 from scripts.utils import get_env # noqa: I100, E402 def _get_attachments(statement_period_start: str, statement_period_end: str, env: str) -> \ list[object]: """Get all the internal attachments in dynamodb for the given statement period. Args: statement_period_start (str): The beginning statement period statement_period_end (str): The ending statement period Returns: list: list of internal attachments """ env = Environment(env) table = get_dynamodb_table(env) params = { 'FilterExpression': '#pid BETWEEN :start AND :end', 'ExpressionAttributeNames': { '#pid': 'period_ids' }, 'ExpressionAttributeValues': { ':start': statement_period_start, ':end': statement_period_end } } response = table.scan(**params) # Pre-process the first response result_set = list(map(_build_attachments, response.get('Items', []))) # paginate while there is data in the response while 'LastEvaluatedKey' in response: response = table.scan(ExclusiveStartKey=response['LastEvaluatedKey']) result_set.extend(list(map(_build_attachments, response.get('Items', [])))) logging.info(f'🔄 Found {len(result_set)} records. Still paginating...') return result_set def _build_attachments(attachment: dict) -> object: """Transform then build an internal attachment into the statement attachments table.""" global skipped_counter attachment = InternalAttachment(**attachment) statement_period = int(attachment.period_ids) if not int(statement_period_start) <= statement_period <= int(statement_period_end): skipped_counter += 1 logging.info(f'❌ Invalid statement period {statement_period}. Skipping...') return if not Account.exists(attachment.label_id): skipped_counter += 1 logging.info(f'❌ Account {attachment.label_id} not found. Skipping...') return if StatementAttachment.exists(attachment.label_id, statement_period, attachment.file_key): skipped_counter += 1 return return StatementAttachment.build(**{ 'account_id': attachment.label_id, 'statement_period_id': statement_period, 'statement_attachment_status': StatementAttachmentStatus.COMPLETE, 'file_type': attachment.file_type, 'statement_attachment_type': StatementAttachmentType.INTERNAL_UPLOAD, 'file_location': attachment.file_key, 'created_at': attachment.upload_date, 'created_by': 'system_id' }) if __name__ == '__main__': skipped_counter = 0 environment = get_env('Environment', True) statement_periods = get_env('STATEMENT_PERIOD_ID', True).split('-') if len(statement_periods) == 1: statement_period_start = statement_periods[0] statement_period_end = statement_periods[0] else: statement_period_start = statement_periods[0] statement_period_end = statement_periods[1] logging.info('📤 Attempting to backfill attachments...') built_attachments = _get_attachments(statement_period_start, statement_period_end, environment) attachments_count = len(built_attachments) if attachments_count == 0: logging.error(f'No attachments were build for statement period {statement_periods}') exit(1) if built_attachments: StatementAttachment.commit_changes() uploaded_count = attachments_count - skipped_counter if skipped_counter > 0: logging.info(f'✅ {uploaded_count} attachments were backfilled while {skipped_counter} attachment(s) were skipped.') # noqa: E501 else: logging.info(f'✅ {uploaded_count} attachments were backfilled.')