"""Statement-Based Logic for Physical Reserves.""" from decimal import Decimal from moneyhub import models from moneyhub.schemas.account_statements import AccountStatementsReservesSchema def get_statement_reserves( account_id: int, contract_id: int | None, statement_period_id: int ) -> dict | None: """Get aggregate physical reserve values for an account and statement period. Args: account_id (int): The id of an account contract_id: Optional id of the contract statement_period_id (int): Statement period to get reserves for Returns: dict: Aggregate total taken, released, and the sum total of the two """ visible_periods = models.StatementPeriodPaymentEntity.get_visible_statement_period_ids( account_id) if statement_period_id not in visible_periods: return None released_items = models.LedgerAccountContract\ .get_reserves_released_by_account_and_statement_periods( account_id, contract_id, [statement_period_id]) taken_items = models.LedgerAccountContract\ .get_reserves_taken_by_account_and_statement_periods( account_id, contract_id, [statement_period_id]) res = {} for r in released_items: res['ledger_reserve_release_total'] = \ res.get('ledger_reserve_release_total', Decimal('0')) + r.currency_amount for t in taken_items: res['ledger_reserve_taken_total'] = \ res.get('ledger_reserve_taken_total', Decimal('0')) + t.currency_amount # If either value is set, also include a sum total of the two if any(t in res for t in ('ledger_reserve_release_total', 'ledger_reserve_taken_total')): # noqa: E501 res['ledger_reserve_total'] = ( res.get('ledger_reserve_release_total', Decimal('0')) + res.get('ledger_reserve_taken_total', Decimal('0'))) return res def get_statement_reserves_by_statement_periods( account_id: int, contract_id: int | None, statement_period_ids: list ) -> list[AccountStatementsReservesSchema] | None: """Get aggregate physical reserve values for an account and statement period. Args: account_id (int): The id of an account contract_id: Optional id of the contract statement_period_ids (list): List of statement periods to filter by Returns: dict: Aggregate total taken, released, and the sum total of the two """ visible_periods = models.StatementPeriodPaymentEntity.get_visible_statement_period_ids( account_id) released_items = models.LedgerAccountContract\ .get_reserves_released_by_account_and_statement_periods( account_id, contract_id, statement_period_ids) taken_items = models.LedgerAccountContract\ .get_reserves_taken_by_account_and_statement_periods( account_id, contract_id, statement_period_ids) res = {} for r in released_items: statement_period_id = r['statement_period_id'] if statement_period_id not in visible_periods: # Skip statement periods that aren't visible for this account continue if statement_period_id not in res: res[statement_period_id] = { 'account_id': account_id, 'contract_id': contract_id, 'statement_period_id': statement_period_id, 'ledger_reserve_release_total': Decimal(0), } res[statement_period_id]['ledger_reserve_release_total'] = \ res[statement_period_id].get('ledger_reserve_release_total', Decimal('0')) + r['currency_amount'] for t in taken_items: statement_period_id = t['statement_period_id'] if statement_period_id not in visible_periods: # Skip statement periods that aren't visible for this account continue if statement_period_id not in res: res[statement_period_id] = { 'account_id': account_id, 'contract_id': contract_id, 'statement_period_id': statement_period_id, 'ledger_reserve_taken_total': Decimal(0), } res[statement_period_id]['ledger_reserve_taken_total'] = \ res[statement_period_id].get('ledger_reserve_taken_total', Decimal('0')) + t['currency_amount'] result = [] # If either value is set, also include a sum total of the two for response_item in res.values(): if any(t in response_item for t in ('ledger_reserve_release_total', 'ledger_reserve_taken_total')): # noqa: E501 statement_period_id = response_item['statement_period_id'] response_item['ledger_reserve_total'] = ( response_item.get('ledger_reserve_release_total', Decimal('0')) + response_item.get('ledger_reserve_taken_total', Decimal('0')) ) result.append(AccountStatementsReservesSchema(**response_item)) return result