""" Accounting statement export Model ================================= This is a model class for prod_accounting_statement_export table in dynamodb. """ from ows_accounting import config from ows_accounting import response from ows_accounting.constants import pagination from ows_accounting.utils import dynamodb class AccountingStatementExport(object): def __init__(self): """Initialize table """ self.table = dynamodb.get_table( config.ACCOUNTING_STATEMENT_EXPORT_TABLE) def _add_pagination(self, records, page_offset, page_limit): """Wrap pagination information around records.. Args: records (list): list of report dictionaries. page_offset (int): page offset. page_limit (int): total number of records per page. Return: dict: dictionary contains list of accounting statement export records and pagination information. Example: """ return { 'items': records[ page_offset * page_limit: page_offset * page_limit + page_limit ], 'pagination': { 'type': 'standard', 'offset': page_offset, 'limit': page_limit, 'total_records': len(records) } } def _filter_out_records(self, records, filters): """Filter out records that have specified attribute value in filter. Args: records (list): list of dictionary records. filters (dict): dictionary with attribute key and attribute value. Returns: records (list): list of filtered dictionary records. """ if len(filters) == 0: return records filtered_records = [] for record in records: match = 0 for key, value in filters.items(): if record.get(key) == value: match += 1 if len(filters) == match: continue filtered_records.append(record) return filtered_records def get_records( self, period_ids, account_id, user_type, filter={}, page_offset=0, page_limit=pagination.PAGE_LIMIT_DEFAULT): """Get report items from accounting_statement_export table in dynamodb. @todo(pkuong): rename this to get_items so that it is consistent with other methods. Args: period_ids (list): list of period ids corresponding to statement accounting period. account_id (int): optional param for external clients. user_type (str): "L" for account_type vendor or "S" for subaccount. filter (dict): specify attribute key and value for items to be filtered out. page_offset (int): optional corresponds to page number, starting with 0. page_limit (int, optional): max items per page.account_id. Returns: dict: dictionary contains list of accounting statement export records and pagination information. Example: { 'items': [{ 'generation_start': '2016-05-25 13:56:00', 'requested_by': 'The Artist Forever Known As Prince', 'period_ids': '202,203,204', 'transaction_types': 'AEA,AEV,AL,AS,AV,CE', 'file_type': 'txt', 'number_format': 'us', 's3_url': 's3://public.theorchard.com/reports/123', 'status': 'GENERATED'}], 'pagination': { 'type': 'standard', 'offset': 0, 'limit': 10, 'total_records': 1 } } """ user_id_type = '{}{}'.format(account_id, user_type) period_ids = ','.join(str(i) for i in period_ids) records = dynamodb.query_items( self.table, 'user_id_type', user_id_type, period_ids=period_ids) records = self._filter_out_records(records, filter) records = sorted( records, key=lambda k: k.get('requested_datetime') or '', reverse=True) return self._add_pagination(records, page_offset, page_limit) def get_item( self, user_id_type, periods, transaction_types, file_format, number_format): """Get an item for a statement export with specified parameters. Args: user_id_type (str): partition key constructed from account id and account type. Example: 18805L. periods (str): sorted comma delimited string of period ids. transaction_types (str): sorted comma delimited string of transaction type codes. file_format (str): file format either 'xls' or 'txt'. number_format (str): locale code. Example: en_US, es_ES. Returns: response.Response: Response object with message which contains an item. Return a 404 Response object if item is not found. """ items = dynamodb.query_items( self.table, 'user_id_type', user_id_type, period_ids=periods, transaction_types=transaction_types, file_type=file_format, number_format=number_format) if not items: return response.create_error_response( code=response.ERROR_CODE_NOT_FOUND, message=config.STATUS_DOESNOTEXIST) item = items.pop() return response.Response(message=item) def put_item(self, user_id_type, user_params, **attributes): """Put new item on dynamodb table Args: user_id_type (str): partition key of accounting statement export table. user_params (str): range key of accounting statement export table. attributes (dict): attributes of the item. Returns: response.Response: Response object with message from put_item call. """ item = dict( user_id_type=user_id_type, user_params=user_params) item.update(attributes) message = self.table.put_item(Item=item) return response.Response(message=message) def get_avro_item(self, user_id_type, periods): """Get an item for a statement export with file type equals to AVRO. Args: user_id_type (str): partition key constructed from account id and account type. Example: 18805L. periods (str): sorted comma delimited string of period ids. Returns: response.Response: Response object with message which contains an item. Return a 404 Response object if item is not found. """ items = dynamodb.query_items( self.table, 'user_id_type', user_id_type, period_ids=periods, file_type='AVRO') if not items: return response.create_error_response( code=response.ERROR_CODE_NOT_FOUND, message=config.STATUS_DOESNOTEXIST) item = items.pop() return response.Response(message=item)