""" Logic for revenue. Provides logic for calculating accounting revenue """ from ows_accounting import features from ows_accounting import response from ows_accounting.logic import accounting_intervals from ows_accounting.models import currency as currency_model from ows_accounting.models import fact_sales as fact_sales_model from ows_accounting.models import period as period_model from ows_accounting.models import revenue as revenue_model from ows_accounting.presentation import fact_sales as fact_sales_presentation def _get_revenue_from_cache( account_type, account_id, period_id): """Get revenue info by accounting period from cache. Args: account_type (str): account type from GRASS. account_id (int): account id. period_id (int): accounting period id. Returns: dict: Revenue info or None """ cached_response = revenue_model.get(account_type, account_id, period_id) if not cached_response: return None data = cached_response.message return (period_id, data['revenue'], data['num_transactions']) def _get_revenue_by_periods(account_type, account_id, intervals): """Get revenue info by accounting periods from snowflake database or cache. Args: account_type (str): account type from GRASS. account_id (int): account id. intervals (list): accounting intervals list Returns: list: List with formatted revenue data by accounting periods """ revenue_data = [] cached_revenue_data = [] request_periods = [] formatted_revenue_data = [] for interval in intervals: for period in interval['periods']: # cached_data = _get_revenue_from_cache( # account_type, account_id, period) # if cached_data is not None: # cached_revenue_data.append(cached_data) # else: request_periods.append(period) if request_periods: revenue_data = fact_sales_model.get_account_revenue( account_type, account_id, request_periods) for item in revenue_data: formatted = fact_sales_presentation.revenue(item) if features.is_vendor_gross_net_enabled(): revenue_model.save( account_type, account_id, formatted['period_id'], formatted['revenue'], formatted['num_transactions'], formatted['gross_revenue']) else: revenue_model.save( account_type, account_id, formatted['period_id'], formatted['revenue'], formatted['num_transactions']) formatted_revenue_data.append(formatted) formatted_revenue_data.extend( fact_sales_presentation.revenues(cached_revenue_data)) return formatted_revenue_data def _find_revenue_by_period_id(revenue_data, period_id): """Get revenue info from revenue data list by period id. Args: revenue_data (list): Revenue data list from snowflake database period_id (int): Accounting period id Returns: dict: Revenue info or None """ return next( (item for item in revenue_data if item['period_id'] == period_id), None) def _format_revenue(interval, currency): """Get properly formatted revenue item for response. Args: interval (dict): Accounting interval data currency (dict): Currency data Returns: dict: Revenue data """ return { 'min_accounting_period': interval['periods'][-1], 'max_accounting_period': interval['periods'][0], 'interval': { 'type': interval['type'], 'number': interval['number'], 'year': interval['year'] }, 'currency_id': currency['id'], 'currency_symbol': currency['symbol'], 'revenue': 0, 'gross_revenue': 0, 'num_transactions': 0 } def _get_first_statement_period(account_id, account_type, intervals): """Filter revenue intervals based on first statement period. Args: account_id (int): account id. account_type (str): account type from GRASS. intervals (list): list of dictionaries with intervals details Returns: list: list of filtered dictionaries with intervals details. """ period = period_model.get_first_statement_period(account_id, account_type) first_statement_period_intervals = [] if not period: return intervals for interval in intervals: if period.message <= interval['periods'][0]: first_statement_period_intervals.append(interval) return first_statement_period_intervals def get_revenue(account_type, account_id, recent_intervals): """Get account revenue information. Args: account_type (str): account type from GRASS. account_id (int): account id. recent_intervals: number of intervals to get info Returns: response.Response: Revenue info or error. """ intervals_response = accounting_intervals.get_intervals_from_contracts( account_type, account_id, recent_intervals) if not intervals_response: return intervals_response intervals = intervals_response.message intervals = _get_first_statement_period( account_id, account_type, intervals) revenue_data = _get_revenue_by_periods(account_type, account_id, intervals) result = [] for interval in intervals: currency_response = currency_model.get_currency_by_id( interval['currency_id']) if not currency_response: return currency_response revenue_record = _format_revenue(interval, currency_response.message) for period_id in interval['periods']: item = _find_revenue_by_period_id(revenue_data, period_id) if item: revenue_record['revenue'] += item['revenue'] if features.is_vendor_gross_net_enabled(): revenue_record['gross_revenue'] += item['gross_revenue'] revenue_record['num_transactions'] += item['num_transactions'] result.append(revenue_record) return response.Response(result) def get_average_monthly_net_revenue(account_type, account_id): """Get the average monthly net revenue for a vendor/subaccount. Args: account_type (str): The account type (vendor or subaccount). account_id (int): The account id. Returns: response.Response: Containing the average monthly net revenue. """ return fact_sales_model.get_average_monthly_net_revenue( account_type, account_id)