"""Account Statement Period logic tests.""" from collections import namedtuple import datetime from decimal import Decimal from unittest.mock import patch import pytest from moneyhub.constants.constants import OrderDirection from moneyhub.logic import account_statement_period as logic from moneyhub.schemas.account_statement_period import AccountStatementPeriodBalanceSchema from moneyhub.schemas.account_statement_period import AccountStatementPeriodDetailSchema from moneyhub.schemas.account_statement_period import AccountStatementPeriodVatDetailSchema from moneyhub.schemas.account_statements import PaymentAllocationDetailSchema from tests.utils.factories import FlowthroughPayableBalanceFactory from tests.utils.factories import LedgerAccountContractVatSummaryFactory from tests.utils.factories import LedgerVatSummaryFactory from tests.utils.factories import StatementPeriodFactory ExtendedLedgerAccountingRunBalance = namedtuple( 'ExtendedLedgerAccountingRunBalance', [ 'ledger_accounting_run_balance_id', 'account_id', 'contract_id', 'currency_code', 'total_gross_revenue_amount', 'distribution_fee', 'total_net_revenue_amount', 'mechanical_deduction_total', 'mechanical_deduction_admin_fee_total', 'adjusted_net_revenue', 'statement_period_id', ] ) ExtendedLedgerAccountingRunVat = namedtuple( 'ExtendedLedgerAccountingRunVat', [ 'ledger_accounting_run_vat_id', 'account_id', 'contract_id', 'currency_code', 'statement_period_id', 'gross_revenue', 'net_revenue', 'distribution_fee', 'gross_vat_rate', 'distribution_vat_rate', 'gross_vat', 'distribution_vat', 'adjusted_net_revenue', ] ) LedgerAccountContractEvent = namedtuple( 'LedgerAccountContractEvent', [ 'ledger_account_contract_id', 'account_id', 'contract_id', 'currency_code', 'currency_amount', 'previous_balance', 'current_balance', 'statement_period_id', 'event_name', ] ) LedgerContractFlowthrough = namedtuple( 'LedgerContractFlowthrough', [ 'amount' ] ) LedgerAccountContractPayableBalance = namedtuple( 'LedgerAccountContractPayableBalance', [ 'ledger_account_contract_id', 'account_id', 'contract_id', 'current_balance', ] ) LedgerCorrection = namedtuple( 'LedgerCorrection', [ 'ledger_correction_id', 'account_id', 'contract_id', 'statement_period_id', 'gross_revenue', 'distribution_fee', 'net_revenue', ] ) LedgerSummary = namedtuple( 'LedgerSummary', [ 'account_id', 'statement_period_id', 'contract_id', 'currency_code', 'total_gross_revenue_amount', 'total_net_revenue_amount', 'distribution_fee', 'mechanical_deduction_total', 'mechanical_deduction_admin_fee_total', ] ) AccountStatementPeriodPayment = namedtuple( 'AccountStatementPeriodPayment', [ 'ledger_account_id', 'statement_period_id', 'account_id', 'contract_id', 'action_status', 'currency_code', 'currency_amount', 'created_at', 'event_name', 'withholding_tax_ledger_account_id', 'withholding_tax_currency_code', 'withholding_tax_currency_amount', 'withholding_tax_created_at', ] ) AccountStatementPeriodCombinedPayment = namedtuple( 'AccountStatementPeriodCombinedPayment', [ 'unique_key', 'statement_period_id', 'account_id', 'contract_id', 'action_status', 'currency_code', 'currency_amount', 'created_at', 'event_name', 'withholding_tax_ledger_account_id', 'withholding_tax_currency_code', 'withholding_tax_currency_amount', 'withholding_tax_created_at', ] ) AccountPaymentDetailStatus = namedtuple( 'AccountPaymentDetailStatus', [ 'worksheet_account_contract_closing_balance_id', 'contract_id', 'closing_balance_statement_period', 'closing_balance_amount', 'payable_amount_pre_tax', 'tax_withholding_amount', 'vat_amount', 'payable_amount_post_tax', 'currency_code', 'batch_status', 'individual_payment_status', 'created_at', 'last_modified', ] ) LegacyBalanceEvent = namedtuple( 'LegacyBalanceEvent', [ 'statement_period_id', 'currency', 'opening_balance', 'closing_balance' ] ) WorkstationSummary = namedtuple( 'WorkstationSummary', [ 'statement_period_id', 'currency', 'gross_revenue', 'net_revenue', 'fee', 'mechanicals', 'mechanical_fees', ] ) @patch('moneyhub.logic.account_statement_period.models') def test_get_account_statement_periods_by_account( mock_models): """Test getting account statement periods.""" account_id = 24601 contract_id = 10001 total_records = 3 mock_model = [ StatementPeriodFactory.build( statement_period_id=101 ), StatementPeriodFactory.build( statement_period_id=102 ), StatementPeriodFactory.build( statement_period_id=103 ), ] mock_models.AccountStatementPeriods.get_by_account_id.return_value = (mock_model, total_records) mock_models.WorkstationSummary.get_balances_by_account_id.return_value = [] mock_models.LedgerSummary.get_for_account.return_value = [ LedgerSummary( account_id=account_id, contract_id=contract_id, statement_period_id=101, currency_code='NOK', total_gross_revenue_amount=Decimal(301), total_net_revenue_amount=Decimal(238), distribution_fee=Decimal(47), mechanical_deduction_total=Decimal(0), mechanical_deduction_admin_fee_total=Decimal(0), ), LedgerSummary( account_id=account_id, contract_id=contract_id, statement_period_id=102, currency_code='NOK', total_gross_revenue_amount=Decimal(89), total_net_revenue_amount=Decimal(32), distribution_fee=Decimal(13), mechanical_deduction_total=Decimal(0), mechanical_deduction_admin_fee_total=Decimal(0), ), LedgerSummary( account_id=account_id, contract_id=contract_id, statement_period_id=103, currency_code='NOK', total_gross_revenue_amount=Decimal(100), total_net_revenue_amount=Decimal(80), distribution_fee=Decimal(20), mechanical_deduction_total=Decimal(0), mechanical_deduction_admin_fee_total=Decimal(0), ), ] result = logic.get_account_statement_periods_by_account( account_id, None) actual = { 'items': list(result['items']), 'pagination': result['pagination'] } assert actual == { 'items': [ AccountStatementPeriodDetailSchema( account_id=account_id, contract_id=None, statement_period_id=101, currency_code='NOK', total_gross_revenue_amount=Decimal(301), total_net_revenue_amount=Decimal(238), distribution_fee=Decimal(47), mechanical_deduction_total=Decimal(0), mechanical_deduction_admin_fee_total=Decimal(0), ), AccountStatementPeriodDetailSchema( account_id=account_id, contract_id=None, statement_period_id=102, currency_code='NOK', total_gross_revenue_amount=Decimal(89), total_net_revenue_amount=Decimal(32), distribution_fee=Decimal(13), mechanical_deduction_total=Decimal(0), mechanical_deduction_admin_fee_total=Decimal(0), ), AccountStatementPeriodDetailSchema( account_id=account_id, contract_id=None, statement_period_id=103, currency_code='NOK', total_gross_revenue_amount=Decimal(100), total_net_revenue_amount=Decimal(80), distribution_fee=Decimal(20), mechanical_deduction_total=Decimal(0), mechanical_deduction_admin_fee_total=Decimal(0), ), ], 'pagination': { 'pagination_type': 'standard', 'total_records': 3 } } mock_models.LedgerSummary.get_for_account.assert_called_once_with( account_id, None, [101, 102, 103], OrderDirection.ASC) mock_models.WorkstationSummary.get_revenue_for_account.assert_called_once_with( account_id, None, [101, 102, 103], OrderDirection.ASC) @patch('moneyhub.logic.account_statement_period.models') def test_get_payments_for_account_and_contract_id(mock_models): """Test get_payments_by_account_and_statement_periods.""" account_id = 1 statement_period_id = 3 response_payments = [ AccountStatementPeriodCombinedPayment( unique_key='1', account_id=account_id, contract_id=1, statement_period_id=statement_period_id, action_status='complete', currency_code='GBP', currency_amount=-100, created_at='2022-11-25', event_name='send_payments', withholding_tax_ledger_account_id=None, withholding_tax_currency_code=None, withholding_tax_currency_amount=None, withholding_tax_created_at=None ) ] expected_response = [ { 'ledger_account_id': '1', 'account_id': account_id, 'contract_id': 1, 'statement_period_id': statement_period_id, 'action_status': 'complete', 'currency_code': 'GBP', 'currency_amount': -100, 'created_at': datetime.date(2022, 11, 25), 'event_name': 'send_payments', 'withholding_tax_ledger_account_id': None, 'withholding_tax_currency_code': None, 'withholding_tax_currency_amount': None, 'withholding_tax_created_at': None }, ] mock_models.CombinedPayments.\ get_payments_by_account_and_statement_periods.return_value = \ response_payments res = logic.get_payments_by_account_and_statement_periods(1, 1, [3]) res_dicts = [r.model_dump() for r in res] assert res_dicts == expected_response mock_models.CombinedPayments.get_payments_by_account_and_statement_periods.\ assert_called_once_with(1, [3], 1) @pytest.mark.parametrize('contract_id, expected_contract_ids, account_contract_called', [ (1, [1], False), (None, [1, 2, 3], True) ]) @patch('moneyhub.logic.account_statement_period.models') def test_get_payment_allocation_details( mock_models, contract_id, expected_contract_ids, account_contract_called ): """Test get payment allocation details.""" account_id = 1 statement_period_ids = [3] response = [ PaymentAllocationDetailSchema( reference_adjustment_type_id=1, apply_to_statement_period_id=3, reference_adjustment_type='Flow Through Adjustment', adjustment_amount=361.30, currency_code='GBP', ), PaymentAllocationDetailSchema( reference_adjustment_type_id=2, apply_to_statement_period_id=3, reference_adjustment_type='VAT', adjustment_amount=36.13, currency_code='GBP', ) ] expected_response = [ { 'reference_adjustment_type_id': 1, 'apply_to_statement_period_id': 3, 'reference_adjustment_type': 'Flow Through Adjustment', 'adjustment_amount': 361.30, 'currency_code': 'GBP', }, { 'reference_adjustment_type_id': 2, 'apply_to_statement_period_id': 3, 'reference_adjustment_type': 'VAT', 'adjustment_amount': 36.13, 'currency_code': 'GBP', } ] mock_models.AccountContract.get_by_account.return_value = expected_contract_ids mock_models.PaymentAllocation.get_flowthrough_details.return_value = response res = logic.get_payment_allocation_details(account_id, contract_id, statement_period_ids) res_dicts = [r.model_dump() for r in res] assert res_dicts == expected_response assert mock_models.AccountContract.get_by_account.called == account_contract_called mock_models.PaymentAllocation.get_flowthrough_details. \ assert_called_once_with(expected_contract_ids, statement_period_ids) @patch('moneyhub.logic.account_statement_period.is_feature_enabled') @patch('moneyhub.logic.account_statement_period.models') def test_get_vat_by_account_and_statement_periods_accounting_run( mock_models, mock_is_feature_enabled ): """Test getting accounting run VAT info for an account and statement period.""" account_id = 24601 contract_id = 10001 statement_period_ids = [123, 234] mock_models.LedgerVatSummary.get_visible_by_account_and_statement_periods.return_value = [] mock_models.LedgerAccountingRunVat.get_committed_for_account.return_value = [ ExtendedLedgerAccountingRunVat( ledger_accounting_run_vat_id=1, account_id=account_id, contract_id=contract_id, statement_period_id=statement_period_ids[0], currency_code='NOK', gross_revenue=Decimal(500), net_revenue=Decimal(400), distribution_fee=Decimal(25), gross_vat_rate=Decimal(20), distribution_vat_rate=Decimal(20), gross_vat=Decimal(100), distribution_vat=Decimal(-20), adjusted_net_revenue=Decimal(60), ), ExtendedLedgerAccountingRunVat( ledger_accounting_run_vat_id=1, account_id=account_id, contract_id=contract_id, statement_period_id=statement_period_ids[0], currency_code='NOK', gross_revenue=Decimal(500), net_revenue=Decimal(400), distribution_fee=Decimal(75), gross_vat_rate=Decimal(20), distribution_vat_rate=Decimal(20), gross_vat=Decimal(20), distribution_vat=Decimal(10), adjusted_net_revenue=Decimal(10), ), ExtendedLedgerAccountingRunVat( ledger_accounting_run_vat_id=1, account_id=account_id, contract_id=contract_id, statement_period_id=statement_period_ids[1], currency_code='NOK', gross_revenue=Decimal(200), net_revenue=Decimal(100), distribution_fee=Decimal(50), gross_vat_rate=Decimal(20), distribution_vat_rate=Decimal(20), gross_vat=Decimal(40), distribution_vat=Decimal(20), adjusted_net_revenue=Decimal(20), ) ] mock_is_feature_enabled.return_value = False result = logic.get_vat_by_account_and_statement_periods( account_id, contract_id, statement_period_ids) assert result == [ AccountStatementPeriodVatDetailSchema( statement_period_id=statement_period_ids[0], account_id=account_id, payee_currency_code='NOK', base_amount_payee_currency=Decimal(1000), net_amount_payee_currency=Decimal(70), vat_amount_payee_currency=Decimal(120), currency_code='NOK', gross_revenue=Decimal(1000), net_revenue=Decimal(800), distribution_fee=Decimal(100), gross_vat_rate=Decimal(20), distribution_vat_rate=Decimal(20), gross_vat=Decimal(120), distribution_vat=Decimal(-10), adjusted_net_revenue=Decimal(70), ), AccountStatementPeriodVatDetailSchema( statement_period_id=statement_period_ids[1], account_id=account_id, payee_currency_code='NOK', base_amount_payee_currency=Decimal(200), net_amount_payee_currency=Decimal(20), vat_amount_payee_currency=Decimal(40), currency_code='NOK', gross_revenue=Decimal(200), net_revenue=Decimal(100), distribution_fee=Decimal(50), gross_vat_rate=Decimal(20), distribution_vat_rate=Decimal(20), gross_vat=Decimal(40), distribution_vat=Decimal(20), adjusted_net_revenue=Decimal(20), ) ] mock_models.LedgerVatSummary.get_visible_by_account_and_statement_periods. \ assert_called_once_with(account_id, contract_id, statement_period_ids) mock_models.LedgerAccountingRunVat.get_committed_for_account.assert_called_once_with( account_id, contract_id, statement_period_ids) @patch('moneyhub.logic.account_statement_period.is_feature_enabled') @patch('moneyhub.logic.account_statement_period.models') def test_get_vat_by_account_and_statement_periods_vat_summary(mock_models, mock_is_feature_enabled): """Test getting VAT summary info for an account and statement period.""" account_id = 24601 contract_id = 10001 statement_period_ids = [123, 234] mock_models.LedgerVatSummary.get_visible_by_account_and_statement_periods.return_value = [ LedgerVatSummaryFactory.build( account_id=account_id, contract_id=contract_id, payee_currency_code='NOK', base_amount_payee_currency=Decimal(500), vat_amount_payee_currency=Decimal(60), net_amount_payee_currency=Decimal(35), statement_period_id=statement_period_ids[0], ), LedgerVatSummaryFactory.build( account_id=account_id, contract_id=contract_id, payee_currency_code='NOK', base_amount_payee_currency=Decimal(500), vat_amount_payee_currency=Decimal(60), net_amount_payee_currency=Decimal(35), statement_period_id=statement_period_ids[0], ), LedgerVatSummaryFactory.build( account_id=account_id, contract_id=contract_id, payee_currency_code='NOK', base_amount_payee_currency=Decimal(200), vat_amount_payee_currency=Decimal(40), net_amount_payee_currency=Decimal(20), statement_period_id=statement_period_ids[1], ), ] mock_models.LedgerAccountingRunVat.get_committed_for_account.return_value = [] mock_is_feature_enabled.return_value = False result = logic.get_vat_by_account_and_statement_periods( account_id, contract_id, statement_period_ids) assert result == [ AccountStatementPeriodVatDetailSchema( statement_period_id=statement_period_ids[0], account_id=account_id, payee_currency_code='NOK', base_amount_payee_currency=Decimal(1000), net_amount_payee_currency=Decimal(70), vat_amount_payee_currency=Decimal(120), currency_code='NOK', gross_revenue=None, net_revenue=None, distribution_fee=None, gross_vat_rate=None, distribution_vat_rate=None, gross_vat=None, distribution_vat=None, adjusted_net_revenue=None, ), AccountStatementPeriodVatDetailSchema( statement_period_id=statement_period_ids[1], account_id=account_id, payee_currency_code='NOK', base_amount_payee_currency=Decimal(200), net_amount_payee_currency=Decimal(20), vat_amount_payee_currency=Decimal(40), currency_code='NOK', gross_revenue=None, net_revenue=None, distribution_fee=None, gross_vat_rate=None, distribution_vat_rate=None, gross_vat=None, distribution_vat=None, adjusted_net_revenue=None, ) ] mock_models.LedgerVatSummary.get_visible_by_account_and_statement_periods. \ assert_called_once_with(account_id, contract_id, statement_period_ids) mock_models.LedgerAccountingRunVat.get_committed_for_account. \ assert_called_once_with(account_id, contract_id, statement_period_ids) @patch('moneyhub.logic.account_statement_period.is_feature_enabled') @patch('moneyhub.logic.account_statement_period.models') def test_get_vat_by_account_and_statement_periods_no_data(mock_models, mock_is_feature_enabled): """Test getting the VAT info when no data is available.""" account_id = 24601 contract_id = None statement_period_ids = [123, 234] mock_models.LedgerVatSummary.get_visible_by_account_and_statement_periods.return_value = [] mock_models.LedgerAccountingRunVat.get_committed_for_account.return_value = [] mock_is_feature_enabled.return_value = False result = logic.get_vat_by_account_and_statement_periods( account_id, contract_id, statement_period_ids) assert result == [] mock_models.LedgerVatSummary.get_visible_by_account_and_statement_periods. \ assert_called_once_with(account_id, contract_id, statement_period_ids) mock_models.LedgerAccountingRunVat.get_committed_for_account.assert_called_once_with( account_id, contract_id, statement_period_ids) @patch('moneyhub.logic.account_statement_period.is_feature_enabled') @patch('moneyhub.logic.account_statement_period.models') def test_get_vat_by_account_and_statement_periods_both_methods( mock_models, mock_is_feature_enabled ): """Test getting both types of VAT info for an account and statement period.""" account_id = 24601 contract_id = 10001 statement_period_ids = [123, 234, 235] mock_models.LedgerVatSummary.get_visible_by_account_and_statement_periods.return_value = [ LedgerVatSummaryFactory.build( account_id=account_id, contract_id=contract_id, payee_currency_code='NOK', base_amount_payee_currency=Decimal(500), vat_amount_payee_currency=Decimal(60), net_amount_payee_currency=Decimal(35), statement_period_id=statement_period_ids[0], ), LedgerVatSummaryFactory.build( account_id=account_id, contract_id=contract_id, payee_currency_code='NOK', base_amount_payee_currency=Decimal(500), vat_amount_payee_currency=Decimal(60), net_amount_payee_currency=Decimal(35), statement_period_id=statement_period_ids[0], ), LedgerVatSummaryFactory.build( account_id=account_id, contract_id=contract_id, payee_currency_code='NOK', base_amount_payee_currency=Decimal(200), vat_amount_payee_currency=Decimal(40), net_amount_payee_currency=Decimal(20), statement_period_id=statement_period_ids[1], ), ] mock_models.LedgerAccountingRunVat.get_committed_for_account.return_value = [ ExtendedLedgerAccountingRunVat( ledger_accounting_run_vat_id=1, account_id=account_id, contract_id=contract_id, statement_period_id=statement_period_ids[2], currency_code='NOK', gross_revenue=Decimal(200), net_revenue=Decimal(100), distribution_fee=Decimal(50), gross_vat_rate=Decimal(20), distribution_vat_rate=Decimal(20), gross_vat=Decimal(40), distribution_vat=Decimal(20), adjusted_net_revenue=Decimal(20), ) ] mock_is_feature_enabled.return_value = False result = logic.get_vat_by_account_and_statement_periods( account_id, contract_id, statement_period_ids) assert result == [ AccountStatementPeriodVatDetailSchema( statement_period_id=statement_period_ids[0], account_id=account_id, payee_currency_code='NOK', base_amount_payee_currency=Decimal(1000), net_amount_payee_currency=Decimal(70), vat_amount_payee_currency=Decimal(120), currency_code='NOK', gross_revenue=None, net_revenue=None, distribution_fee=None, gross_vat_rate=None, distribution_vat_rate=None, gross_vat=None, distribution_vat=None, adjusted_net_revenue=None, ), AccountStatementPeriodVatDetailSchema( statement_period_id=statement_period_ids[1], account_id=account_id, payee_currency_code='NOK', base_amount_payee_currency=Decimal(200), net_amount_payee_currency=Decimal(20), vat_amount_payee_currency=Decimal(40), currency_code='NOK', gross_revenue=None, net_revenue=None, distribution_fee=None, gross_vat_rate=None, distribution_vat_rate=None, gross_vat=None, distribution_vat=None, adjusted_net_revenue=None, ), AccountStatementPeriodVatDetailSchema( statement_period_id=statement_period_ids[2], account_id=account_id, payee_currency_code='NOK', base_amount_payee_currency=Decimal(200), net_amount_payee_currency=Decimal(20), vat_amount_payee_currency=Decimal(40), currency_code='NOK', gross_revenue=Decimal(200), net_revenue=Decimal(100), distribution_fee=Decimal(50), gross_vat_rate=Decimal(20), distribution_vat_rate=Decimal(20), gross_vat=Decimal(40), distribution_vat=Decimal(20), adjusted_net_revenue=Decimal(20), ) ] mock_models.LedgerVatSummary.get_visible_by_account_and_statement_periods. \ assert_called_once_with(account_id, contract_id, statement_period_ids) mock_models.LedgerAccountingRunVat.get_committed_for_account. \ assert_called_once_with(account_id, contract_id, statement_period_ids) @patch('moneyhub.logic.account_statement_period.is_feature_enabled') @patch('moneyhub.logic.account_statement_period.models') def test_get_vat_by_account_and_statement_periods_feature_flag( mock_models, mock_is_feature_enabled ): """Test getting VAT summary info with feature flag enabled.""" account_id = 24601 contract_id = 10001 statement_period_ids = [123, 234] mock_models.LedgerAccountContract.get_vat_summaries.return_value = [ LedgerAccountContractVatSummaryFactory.build( account_id=account_id, currency_code='NOK', currency_amount=Decimal(60), statement_period_id=statement_period_ids[0], ), LedgerAccountContractVatSummaryFactory.build( account_id=account_id, currency_code='NOK', currency_amount=Decimal(60), statement_period_id=statement_period_ids[0], ), LedgerAccountContractVatSummaryFactory.build( account_id=account_id, currency_code='NOK', currency_amount=Decimal(40), statement_period_id=statement_period_ids[1], ), ] mock_models.LedgerAccountingRunVat.get_committed_for_account.return_value = [] mock_is_feature_enabled.return_value = True result = logic.get_vat_by_account_and_statement_periods( account_id, contract_id, statement_period_ids) assert result == [ AccountStatementPeriodVatDetailSchema( statement_period_id=statement_period_ids[0], account_id=account_id, payee_currency_code='NOK', base_amount_payee_currency=None, net_amount_payee_currency=None, vat_amount_payee_currency=Decimal(120), currency_code='NOK', gross_revenue=None, net_revenue=None, distribution_fee=None, gross_vat_rate=None, distribution_vat_rate=None, gross_vat=None, distribution_vat=None, adjusted_net_revenue=None, ), AccountStatementPeriodVatDetailSchema( statement_period_id=statement_period_ids[1], account_id=account_id, payee_currency_code='NOK', base_amount_payee_currency=None, net_amount_payee_currency=None, vat_amount_payee_currency=Decimal(40), currency_code='NOK', gross_revenue=None, net_revenue=None, distribution_fee=None, gross_vat_rate=None, distribution_vat_rate=None, gross_vat=None, distribution_vat=None, adjusted_net_revenue=None, ) ] mock_models.LedgerVatSummary.get_visible_by_account_and_statement_periods.assert_not_called() mock_models.LedgerAccountingRunVat.get_committed_for_account. \ assert_called_once_with(account_id, contract_id, statement_period_ids) @patch('moneyhub.logic.account_statement_period.models') def test_get_account_statement_periods_balance( mock_models): """Test getting account statement period balance.""" account_id = 24601 contract_id = 10001 statement_period_ids = [101, 102] mock_models.StatementPeriodPaymentEntity.get_visible_statement_period_ids.return_value = [ 101, 102, 103] mock_models.LedgerAccountContract.get_events_for_account_and_contract.return_value = [ LedgerAccountContractEvent( ledger_account_contract_id=1, account_id=account_id, contract_id=contract_id, currency_code='NOK', currency_amount=Decimal(80), previous_balance=Decimal(0), current_balance=Decimal(80), statement_period_id=102, event_name='commit_royalties', ), LedgerAccountContractEvent( ledger_account_contract_id=1, account_id=account_id, contract_id=contract_id, currency_code='NOK', currency_amount=Decimal(80), previous_balance=Decimal(80), current_balance=Decimal(160), statement_period_id=102, event_name='commit_royalties', ), LedgerAccountContractEvent( ledger_account_contract_id=1, account_id=account_id, contract_id=contract_id, currency_code='NOK', currency_amount=Decimal(80), previous_balance=Decimal(160), current_balance=Decimal(240), statement_period_id=103, event_name='commit_royalties', ) ] mock_models.AccountContract.get_by_account.return_value = [contract_id] mock_models.LedgerContractFlowthrough.get_latest_balances_for_contract.side_effect = [ [LedgerContractFlowthrough(amount=100), LedgerContractFlowthrough(amount=100)], [LedgerContractFlowthrough(amount=300)] ] mock_models.LedgerAccountContract.get_latest_balances_for_account.side_effect = [ [], [ LedgerAccountContractPayableBalance( ledger_account_contract_id=1, account_id=account_id, contract_id=contract_id, current_balance=Decimal(155), ), LedgerAccountContractPayableBalance( ledger_account_contract_id=2, account_id=account_id, contract_id=contract_id + 1, current_balance=Decimal(-100), ), LedgerAccountContractPayableBalance( ledger_account_contract_id=3, account_id=account_id, contract_id=contract_id + 2, current_balance=Decimal(155), ), ] ] mock_models.WorkstationSummary.get_balances_by_account_id.return_value = [ LegacyBalanceEvent( statement_period_id=101, currency='NOK', opening_balance=Decimal(100), closing_balance=Decimal(160) ) ] result = logic.get_balance_by_account_statement_periods( account_id, statement_period_ids, contract_id) assert result == [ AccountStatementPeriodBalanceSchema( currency_code='NOK', opening_balance=Decimal(100), ledger_amount=None, closing_balance=Decimal(160), payable_balance=200, statement_period_id=statement_period_ids[0]), AccountStatementPeriodBalanceSchema( currency_code='NOK', opening_balance=Decimal(0), ledger_amount=Decimal(160), closing_balance=Decimal(160), payable_balance=610, statement_period_id=statement_period_ids[1]), ] mock_models.StatementPeriodPaymentEntity.get_visible_statement_period_ids \ .assert_called_once_with(account_id) mock_models.WorkstationSummary.get_balances_by_account_id \ .assert_called_once_with(account_id, statement_period_ids, contract_id) @patch('moneyhub.logic.account_statement_period.models') def test_get_flowthrough_payable_balances(mock_models): """Test getting flowthrough payable balances for a contract and statement periods.""" contract_ids = [10001] statement_period_ids = [123, 124] expected = [ FlowthroughPayableBalanceFactory.build( amount=123.45, currency_code='NOK', statement_period_id=123), FlowthroughPayableBalanceFactory.build( amount=234.56, currency_code='USD', statement_period_id=124), ] mock_models.LedgerContractFlowthrough.get_latest_balances_for_contract.return_value = expected result = logic.get_flowthrough_payable_balances( contract_ids, statement_period_ids) assert result == expected mock_models.LedgerContractFlowthrough.get_latest_balances_for_contract.assert_called_once_with( contract_ids, statement_period_ids)