"""Requests to ows-payment.""" from typing import Any, Dict, List, Optional, Set from src.connectors.exceptions import OwsPaymentException from src.connectors.requests import delete, get, post, put from src.constants import ( BATCH_SIZE, BATCH_SIZE_REFRESH, PAYABLE_PAYMENT_ALLOCATION_FLOWTHROUGH_STATUSES, TaxCorrectionStatuses, TaxCorrectionTypes, ) from src.models import ( Account, ContractPayableDetails, GetFlowThroughAllocationResponse, GetTaxCorrectionsResponse, GetTaxCorrectionsVATResponse, PaginatedContractCloseBalances, PaginatedPayableBalanceAfterTaxEntries, PaginatedPayableDetailEntries, PayableBalanceAfterTax, PayableBalanceAfterTaxBulkUpdate, PaymentGroup, PaymentGroupPayment, ) SERVICE = 'ows-payment' def delete_balance_entries_after_tax(event_id: int) -> None: """Delete worksheet account contract payable balance after tax.""" path = f'/worksheet-payable-balance-after-tax/event/{event_id}/bulk' response = delete(SERVICE, path) if response.status_code != 204: raise OwsPaymentException( f'ERROR in DELETE {path}', status_code=response.status_code ) def delete_payable_details_entries(event_id: int) -> None: """Delete worksheet account contract payable balance payable details.""" path = f'/worksheet-account-contract-payable-details/event/{event_id}' response = delete(SERVICE, path) if response.status_code != 204: raise OwsPaymentException( f'ERROR in DELETE {path}', status_code=response.status_code ) def delete_payable_details_wht_vat_corrections( worksheet_account_contract_payable_after_tax_ids: List[int], ) -> None: """Soft delete wht/vat correction payable details by worksheet after-tax ids. The endpoint only removes rows with payable_detail_type_id in (4, 5). """ path = '/worksheet-account-contract-payable-details/bulk' body = { 'worksheet_account_contract_payable_after_tax_ids': ( worksheet_account_contract_payable_after_tax_ids ) } response = delete(SERVICE, path, json=body) if response.status_code != 204: raise OwsPaymentException( f'ERROR in DELETE {path}', status_code=response.status_code ) def bulk_create_worksheet_contract_balance_after_tax( event_id: int, statement_period_id: int, body_entries: List[PayableBalanceAfterTax] ) -> None: """Bulk create worksheet account contract payable balance after tax.""" path = f'/worksheet-payable-balance-after-tax/event/{event_id}/statement-period/{statement_period_id}/bulk' # noqa: E501 response = post( SERVICE, path, [entry.model_dump(mode='json') for entry in body_entries] ) # noqa: E501 if response.status_code != 201: raise OwsPaymentException( f'ERROR from POST {path}', status_code=response.status_code, response=response.text, ) def bulk_update_worksheet_contract_balance_after_tax( body_entries: List[PayableBalanceAfterTaxBulkUpdate], ) -> None: """Bulk update worksheet account contract payable balance after tax amounts.""" path = '/worksheet-payable-balance-after-tax/bulk' response = put( SERVICE, path, [entry.model_dump(mode='json') for entry in body_entries] ) if response.status_code != 200: raise OwsPaymentException( f'ERROR from PUT {path}', status_code=response.status_code, response=response.text, ) def bulk_create_contract_payable_details( event_id: int, statement_period_id: int, body_entries: List[ContractPayableDetails] ) -> None: """Bulk create worksheet account contract payable details.""" path = f'/worksheet-account-contract-payable-details/event/{event_id}/statement-period/{statement_period_id}/bulk' # noqa: E501 response = post( SERVICE, path, [entry.model_dump(mode='json') for entry in body_entries] ) # noqa: E501 if response.status_code != 201: raise OwsPaymentException( f'ERROR from POST {path}', status_code=response.status_code, response=response.text, ) def get_payment_group(payment_group_id: int) -> PaymentGroup: """Get the payment_group details.""" path = f'/payment-group/{payment_group_id}/' response = get(SERVICE, path) if response.status_code != 200: raise OwsPaymentException(f'ERROR in GET {path}') return PaymentGroup.model_validate(response.json()) def get_payment_group_payment(payment_group_payment_id: int) -> PaymentGroupPayment: """Get the payment_group_payment details.""" path = f'/payment-group-payment/{payment_group_payment_id}/' response = get(SERVICE, path) if response.status_code != 200: raise OwsPaymentException(f'ERROR in GET {path}') return PaymentGroupPayment.model_validate(response.json()) def get_contract_closing_balance_entries_bulk( worksheet_closing_balance_ids: List[int], limit: int = BATCH_SIZE_REFRESH, offset: int = 0, ) -> PaginatedContractCloseBalances: """Get worksheet account contract closing balances by closing balance ids.""" path = f'/worksheet-account-contract-closing-balance/bulk?limit={limit}&offset={offset}' body: Dict[str, Any] = { 'filters': {'worksheet_closing_balance_ids': worksheet_closing_balance_ids} } response = post(SERVICE, path, body) if response.status_code != 200: raise OwsPaymentException(f'ERROR in POST {path} with body: {body}') return PaginatedContractCloseBalances.model_validate(response.json()) def get_contract_closing_balance_entries( statement_period_id: int, accounts: List[Account], limit: int = 300, offset: int = 0 ) -> PaginatedContractCloseBalances: """Get worksheet account contract closing balance for specific statement period and with provided accounts.""" # noqa: E501 account_ids = ','.join([str(account.account_id) for account in accounts]) path = ( f'/worksheet-account-contract-closing-balance/statement-period/{statement_period_id}/' # noqa: E501 f'?account_ids={account_ids}&limit={limit}&offset={offset}' ) response = get(SERVICE, path) if response.status_code != 200: raise OwsPaymentException(f'ERROR in GET {path}') contract_close_balances = PaginatedContractCloseBalances.model_validate( response.json() ) return contract_close_balances def get_contract_balance_after_tax_entries( event_id: int, limit: int = 300, offset: int = 0, contract_ids: List[int] | None = None, ) -> PaginatedPayableBalanceAfterTaxEntries: """Get worksheet account contract closing balance for specific statement period and with provided accounts.""" # noqa: E501 path = ( f'/worksheet-payable-balance-after-tax/event/{event_id}/' f'?limit={limit}&offset={offset}' ) # this filter works while we are querying for a relatively small number of contracts at a time # if we ever want to query for more we should implement a POST endpoint if contract_ids: path += f'&contract_ids={'&contract_ids='.join(map(str, contract_ids))}' response = get(SERVICE, path) if response.status_code != 200: raise OwsPaymentException(f'ERROR in GET {path}') balances_after_taxes = PaginatedPayableBalanceAfterTaxEntries.model_validate( response.json() ) return balances_after_taxes def get_payable_details_entries( statement_period_id: int, worksheet_payable_after_tax_ids: List[int], detail_groups: List[str], limit: int = BATCH_SIZE, offset: int = 0, ) -> PaginatedPayableDetailEntries: """Get worksheet account contract payable details for after-tax ids and detail groups.""" path = ( f'/worksheet-account-contract-payable-details/statement-period' f'/{statement_period_id}/?limit={limit}&offset={offset}' ) body: Dict[str, Any] = { 'filters': { 'worksheet_payable_after_tax_ids': worksheet_payable_after_tax_ids, 'detail_groups': detail_groups, } } response = post(SERVICE, path, body) if response.status_code != 200: raise OwsPaymentException(f'ERROR in POST {path} with body: {body}') return PaginatedPayableDetailEntries.model_validate(response.json()) def get_tax_corrections( correction_type: TaxCorrectionTypes, correction_status: TaxCorrectionStatuses, correction_statement_period_id: Optional[int], contract_ids: Optional[List[int]], limit: int = BATCH_SIZE, offset: int = 0, ) -> GetTaxCorrectionsResponse: """Get tax corrections.""" path = ( f'/tax-corrections/{correction_type}/{correction_status}' f'/?limit={limit}&offset={offset}' ) body: Dict[str, Any] = {'filters': {}} if correction_statement_period_id: body['filters']['correction_statement_period_id'] = ( correction_statement_period_id ) if contract_ids: body['filters']['contract_ids'] = contract_ids response = post(SERVICE, path, body) if response.status_code != 200: raise OwsPaymentException(f'ERROR in POST {path} with body: {body}') return GetTaxCorrectionsResponse.model_validate(response.json()) def get_tax_corrections_vat( correction_status: TaxCorrectionStatuses, correction_statement_period_id: Optional[int], contract_ids: Optional[List[int]], limit: int = BATCH_SIZE, offset: int = 0, ) -> GetTaxCorrectionsVATResponse: """Get tax corrections VAT.""" path = f'/tax-corrections/vat/{correction_status}/?limit={limit}&offset={offset}' body: Dict[str, Any] = {'filters': {}} if correction_statement_period_id: body['filters']['correction_statement_period_id'] = ( correction_statement_period_id ) if contract_ids: body['filters']['contract_ids'] = contract_ids response = post(SERVICE, path, body) if response.status_code != 200: raise OwsPaymentException(f'ERROR in POST {path} with body: {body}') return GetTaxCorrectionsVATResponse.model_validate(response.json()) def get_flowthrough_allocation_entries( contract_ids: Set[int], limit: int = BATCH_SIZE, offset: int = 0, ) -> GetFlowThroughAllocationResponse: """Get flowthrough allocation.""" path = f'/payment-allocations/flowthrough/bulk?limit={limit}&offset={offset}' body: Dict[str, Any] = {} body['payment_statuses'] = PAYABLE_PAYMENT_ALLOCATION_FLOWTHROUGH_STATUSES body['contract_ids'] = list(contract_ids) response = post(SERVICE, path, body) if response.status_code != 200: raise OwsPaymentException( f'ERROR in POST {path} with body: {body} {response.text}' ) return GetFlowThroughAllocationResponse.model_validate(response.json())