"""Custom report logic.""" from decimal import Decimal from moneyhub import models def _process_reserve_release_schedules( schedule_items: list[models.LedgerReserveReleaseSchedule], statement_period_id: int) -> list: """Process and aggregate a list of release reserve schedules. Results are sorted from most recent taken_statement_period_id. Note that this method assumes the input is already sorted by ledger_reserve_release_schedule_id in ascending order. Args: schedule_items (list): The list of release reserve schedules Returns: list: List of release schedules with aggregated values """ res = {} for schedule in schedule_items: sch = dict(zip(schedule.keys(), schedule)) \ if not isinstance(schedule, dict) else schedule.copy() if sch['ledger_reserve_taken_id'] not in res: # Index by reserve taken and establish aggregate fields res[sch['ledger_reserve_taken_id']] = sch aggr = res[sch['ledger_reserve_taken_id']] aggr['reserve_total'] = (sch['taken_amount'] * -1) aggr['reserves_remaining'] = aggr['reserve_total'] aggr['prior_period_reserve_total'] = Decimal('0') aggr['current_period_reserve_total'] = Decimal('0') aggr['liquidation_start_period_id'] = sch['release_statement_period_id'] aggr['liquidation_start_period_name'] = sch['release_statement_period_name'] aggr['liquidation_end_period_id'] = sch['release_statement_period_id'] aggr['liquidation_end_period_name'] = sch['release_statement_period_name'] else: aggr = res[sch['ledger_reserve_taken_id']] # If more than one entry taken in schedule, aggregate the totals aggr['liquidation_end_period_id'] = sch['release_statement_period_id'] aggr['liquidation_end_period_name'] = sch['release_statement_period_name'] # Calculate the reserves remaining as the aggregate taken total minus any released if sch['release_statement_period_id'] <= statement_period_id: aggr['reserves_remaining'] = (aggr['reserves_remaining'] - sch['released_amount']) # Calculate cases for schedules before and during the current period if sch['release_statement_period_id'] == statement_period_id: aggr['current_period_reserve_total'] += (sch['released_amount'] * -1) elif sch['release_statement_period_id'] < statement_period_id: aggr['prior_period_reserve_total'] += (sch['released_amount'] * -1) return sorted( list(res.values()), key=lambda d: d['taken_statement_period_id'], reverse=True) def get_reserve_release_schedules(account_id: int, statement_period_id: int) -> list: """Get ledger reserve release schedules by an account_id. Args: account_id (int): The id of an account statement_period_id (int): Statement period to get schedule for Returns: list: list of ledger reserve release schedules """ schedule_items = models.LedgerReserveReleaseSchedule.get_by_account_id_for_statement_period( # noqa: E501 account_id, statement_period_id) return _process_reserve_release_schedules(schedule_items, statement_period_id)