"""Ledger Vat Summary logic.""" from datetime import datetime from fastapi import HTTPException from moneyhub import models from moneyhub.constants.constants import ABACUS_EVENT_BACKFILL from moneyhub.constants.constants import SYSTEM_TIMEZONE from moneyhub.schemas.ledger_vat_summary import LedgerVatSummaryBackfillSchema from moneyhub.schemas.ledger_vat_summary import PaginatedLedgerVatSummarySchema from moneyhub.utils.request import create_paginated_response from moneyhub.utils.users import get_user_id def backfill_vat_summary_entries( statement_period_id: int, data: list[LedgerVatSummaryBackfillSchema] ) -> list: """Backfill VAT summary entries based on a data payload. Args: statement_period_id (int): Statement period to backfill entries for. data (list): List of VAT summary entries to backfill. Returns: list: List of created VAT summary entries """ existing_entries = models.LedgerVatSummary.get_by_statement_period(statement_period_id) existing_entries = [ f'{e.account_id}-{e.contract_id}-{e.vat_category}-{float(e.base_amount_payee_currency)}' for e in existing_entries ] adjustments = models.WorksheetAdjustment.get_vat_adjustments(statement_period_id) adjustment_event_map = { f'{a.account_id}-{a.contract_id}-{a.adjustment_currency_code}-{float(a.adjustment_amount)}' : a.abacus_event_id # noqa: E501 for a in adjustments } date_now = datetime.now(SYSTEM_TIMEZONE) user_id = get_user_id() new_vat_summary_entries = [] for entry in data: entry_key = f'{entry.account_id}-{entry.contract_id}-{entry.vat_category}-{float(entry.base_amount_payee_currency)}' # noqa: E501 if entry_key in existing_entries: continue adjustment_key = f'{entry.account_id}-{entry.contract_id}-{entry.payee_currency_code}-{float(entry.vat_amount_payee_currency)}' # noqa: E501 if adjustment_key not in adjustment_event_map: raise HTTPException( status_code=400, detail=f'Missing adjustment for key: {adjustment_key}') adjustment_event_id = adjustment_event_map[adjustment_key] abacus_event = models.AbacusEvent.create( statement_period_id=statement_period_id, event_name=ABACUS_EVENT_BACKFILL, target_type='statement_period', target_id=statement_period_id, event_date=date_now, previous_abacus_event_id=adjustment_event_id, created_by=user_id, ) vat_summary_entry = models.LedgerVatSummary.create( statement_period_id=statement_period_id, activity_statement_period_id=statement_period_id, abacus_event_id=abacus_event.abacus_event_id, account_id=entry.account_id, contract_id=entry.contract_id, vat_category=entry.vat_category, payee_currency_code=entry.payee_currency_code, vat_currency_code=entry.vat_currency_code, base_amount_payee_currency=entry.base_amount_payee_currency, vat_rate=entry.vat_rate, vat_amount_payee_currency=entry.vat_amount_payee_currency, vat_amount_vat_currency=entry.vat_amount_vat_currency, wht_amount_payee_currency=entry.wht_amount_payee_currency, wht_amount_vat_currency=entry.wht_amount_vat_currency, wht_rate=entry.wht_rate, net_amount_payee_currency=entry.net_amount_payee_currency, is_reporting_only=True, created_by=user_id, created_at=date_now, last_modified_by=user_id, last_modified=date_now, ) new_vat_summary_entries.append(vat_summary_entry) return new_vat_summary_entries def get_by_account_id( account_id: int, statement_period_id: int, contract_id: int | None, vat_categories: list | None ) -> list: """GET ledger vat summary for a specified account and statement period. Args: account_id (int): The id of an account contract_id (int): the id of a contract statement_period_id (int): the id of a statement period vat_categories (list): vat categories to filter Returns: list: list of ledger vat """ vat_summary = models.LedgerVatSummary.get_by_account_id( account_id=account_id, statement_period_id=statement_period_id, contract_id=contract_id, vat_categories=vat_categories ) return vat_summary def get_activity_by_account_id( account_id: int, statement_period_id: int, contract_id: int | None, vat_categories: list | None ) -> list: """GET ledger vat summary for a specified account and activity statement period. Args: account_id (int): The id of an account contract_id (int): the id of a contract statement_period_id (int): the id of a statement period vat_categories (list): vat categories to filter Returns: list: list of ledger vat """ vat_summary = models.LedgerVatSummary.get_by_account_id( account_id=account_id, activity_statement_period_id=statement_period_id, contract_id=contract_id, vat_categories=vat_categories ) return vat_summary def get_by_vat_summary_file( vat_summary_file_id: int, limit: int, offset: int ) -> PaginatedLedgerVatSummarySchema: """Get the ledger VAT summary entries associated with a VAT summary file. Args: vat_summary_file_id (int): ID of the VAT summary file limit (int): how many entities to retrieve offset (int): the offset (for pagination) Returns: PaginatedLedgerVatSummarySchema: paginated list of ledger VAT summary entries """ (entries, total_records) = models.LedgerVatSummary.get_by_vat_summary_file( vat_summary_file_id, limit, offset) payload = create_paginated_response(entries, total_records) return PaginatedLedgerVatSummarySchema(**payload)