""" Logic for accounting intervals. Provides logic for getting accounting intervals for revenue calculation """ from ows_accounting import config from ows_accounting import response from ows_accounting.constants import db from ows_accounting.constants import error from ows_accounting.models import accounting_period from ows_accounting.models import ows_contracts def _format_interval(contract, accounting_period): """Get properly formatted interval item for response. Args: contract (dict): Booked contracts data accounting_period (dict): Accounting period data Returns: dict: Accounting interval data """ if contract['payment_interval'] == db.PAYMENT_INTERVAL_MONTH: number = accounting_period['month'] else: number = accounting_period['quarter'] return { 'type': contract['payment_interval'], 'number': number, 'year': accounting_period['year'], 'currency_id': contract['currency_id'], 'periods': [contract['period_id']] } def _find_interval_index_by_quarter(intervals, quarter, year): """Get interval index in the list by quarter and year. Args: intervals (list): Accounting intervals list quarter (int): Interval quarter year (int): Interval year Returns: int: List index or None """ for index, interval in enumerate(intervals): if (interval['type'] == db.PAYMENT_INTERVAL_QUARTER and interval['number'] == quarter and interval['year'] == year): return index return None def get_intervals_from_contracts(account_type, account_id, recent_intervals): """Get accounting intervals from booked contracts. Args: account_type (str): account type from GRASS. account_id (int): account id. recent_intervals: number of intervals to get info Returns: response.Response: Accounting intervals info or error. """ intervals = [] contracts_offset = 0 while True: contracts_response = ows_contracts.get_booked_contracts( account_type, account_id, contracts_offset) if not contracts_response: return contracts_response pagination_info = contracts_response.message['pagination'] if pagination_info['limit'] <= 0: return response.response.create_error_response( code=error.ERROR_CODE_OWS_CONTRACTS, message=error.ERROR_MESSAGE_INVALID_PAGINATION) for contract in contracts_response.message['items']: if contract['period_id'] > int(config.ACTIVE_ACCOUNTING_PERIOD): continue period_response = accounting_period.get_period_by_id( contract['period_id']) if not period_response: return period_response period = period_response.message if contract['payment_interval'] == db.PAYMENT_INTERVAL_MONTH: if len(intervals) == recent_intervals: return response.Response(intervals) intervals.append(_format_interval(contract, period)) else: existing_index = _find_interval_index_by_quarter( intervals, period['quarter'], period['year']) if existing_index is not None: intervals[existing_index]['periods'].append( contract['period_id']) elif len(intervals) == recent_intervals: return response.Response(intervals) else: intervals.append(_format_interval(contract, period)) contracts_offset += pagination_info['limit'] if contracts_offset >= pagination_info['total_records']: return response.Response(intervals) def get_period_by_id(period_id): """Get accounting period by id. Args: period_id (int): Period Id. Returns: response.Response: Accounting period data or error in Response object. """ return accounting_period.get_period_by_id(period_id)