"""Ledger accounting run vat model.""" from sqlalchemy import Column from sqlalchemy import DateTime from sqlalchemy import ForeignKey from sqlalchemy import Integer from sqlalchemy import Numeric from sqlalchemy import String from sqlalchemy.engine import Row from sqlalchemy.sql import literal_column from moneyhub.models.abacus_event import AbacusEvent from moneyhub.models.account_contract import AccountContract from moneyhub.models.account_payment_term import AccountPaymentTerm from moneyhub.models.accounting_period import AccountingPeriod from moneyhub.models.accounting_run import AccountingRun from moneyhub.models.ledger_account_contract import LedgerAccountContract from moneyhub.models.mysql_base import BaseModel class LedgerAccountingRunVat(BaseModel): """Ledger accounting run vat model.""" __tablename__ = 'ledger_accounting_run_vat' ledger_accounting_run_vat_id = Column(Integer, primary_key=True) accounting_run_id = Column(Integer, nullable=False) abacus_event_id = Column(Integer, ForeignKey(AbacusEvent.abacus_event_id)) contract_id = Column(Integer, nullable=False) currency_code = Column(String(3), nullable=True) country_of_tax_residence = Column(String(3), nullable=True) gross_revenue = Column(Numeric(20, 2), nullable=True) net_revenue = Column(Numeric(20, 2), nullable=True) distribution_fee = Column(Numeric(20, 2), nullable=True) gross_vat_rate = Column(Numeric(5, 2), nullable=True) distribution_vat_rate = Column(Numeric(5, 2), nullable=True) gross_vat = Column(Numeric(20, 2), nullable=True) distribution_vat = Column(Numeric(20, 2), nullable=True) adjusted_net_revenue = Column(Numeric(20, 2), nullable=True) exempt_reason = Column(String(180), nullable=True) created_by = Column(String(255), nullable=True) created_at = Column(DateTime, nullable=True) last_modified_by = Column(String(255), nullable=True) last_modified = Column(DateTime, nullable=True) @classmethod def get_by_statement_period(cls, statement_period_id: int) -> list: """Get entries by statement period. Args: statement_period_id (int): Statement period to get entries for. Returns: list: Entries made during a statement period. """ return cls.query \ .join(AbacusEvent) \ .filter(AbacusEvent.statement_period_id == statement_period_id) \ .all() @classmethod def get_committed_for_account( cls, account_id: int, contract_id: int | None = None, statement_period_ids: list[int] | None = None ) -> list: """Get committed VAT ledger entries for a given account (and contract). Args: account_id (int): ID of the account contract_id (int): Optional ID of the contract statement_period_ids (list): Optional list of statement period IDs Returns: list: List of VAT entries """ filters = [ literal_column('account_contract.account_id') == account_id, literal_column('accounting_run.run_status') == 'Committed', ] if contract_id: filters.append(LedgerAccountingRunVat.contract_id == contract_id) if statement_period_ids and len(statement_period_ids) != 0: filters.append( literal_column('accounting_period.statement_period_id').in_(statement_period_ids)) with_entities = [ literal_column('accounting_period.statement_period_id').label('statement_period_id'), # noqa: E501 literal_column('account_contract.account_id').label('account_id'), cls.ledger_accounting_run_vat_id, cls.contract_id, cls.currency_code, cls.gross_revenue, cls.net_revenue, cls.distribution_fee, cls.gross_vat_rate, cls.distribution_vat_rate, cls.gross_vat, cls.distribution_vat, cls.adjusted_net_revenue, ] return cls.query.with_entities(*with_entities)\ .join( AccountContract, cls.contract_id == AccountContract.contract_id) \ .join( AccountingRun, cls.accounting_run_id == AccountingRun.accounting_run_id) \ .join( AccountingPeriod, AccountingRun.accounting_period_id == AccountingPeriod.accounting_period_id) \ .filter(*filters) \ .order_by(cls.ledger_accounting_run_vat_id.asc()).all() @classmethod def get_by_payment_entity_and_statement_period( cls, payment_entity_id, statement_period_id ) -> Row: """Get VAT ledger entries for a given payment entity and statement period. Args: payment_entity_id (int): ID of the reference_payment_entity statement_period_id (int): ID of the statement period Returns: dict: vat entry """ filter_condition = [AccountPaymentTerm.payment_entity_id == payment_entity_id] return cls.query\ .join( LedgerAccountContract, LedgerAccountContract.contract_id == cls.contract_id) \ .join( AccountPaymentTerm, AccountPaymentTerm.account_id == LedgerAccountContract.account_id) \ .join( AccountingRun, AccountingRun.accounting_run_id == cls.accounting_run_id) \ .join( AccountingPeriod, AccountingPeriod.accounting_period_id == AccountingRun.accounting_period_id) \ .filter( *filter_condition, AccountingPeriod.statement_period_id == statement_period_id)\ .first()