"""Account logic.""" from datetime import date from typing import Type from marshmallow import ValidationError from owsresponse import response from abacus_account import models from abacus_account.constants.constants import ( ELIGIBILITY_STATUSES, SKIP_PAYMENT_TERM_TEMPLATE_CREATION_SOURCES ) from abacus_account.constants.error import ERROR_ACCOUNT_ALREADY_EXISTS from abacus_account.logic.account_payee import create_account_payee from abacus_account.logic.account_payment_term import \ create_account_payment_term from abacus_account.logic.account_payment_term_template \ import create_payment_term_from_template_by_currency_code from abacus_account.logic.account_payment_term_template \ import get_payment_term_template_by_currency_code from abacus_account.logic.account_tax_info import create_account_tax_info from abacus_account.schemas.account import AccountDetailSchema from abacus_account.schemas.account import EligibleAccountListSchema from abacus_account.schemas.account import SAPFormattedAccountDetailSchema from abacus_account.utils.format_error import validation_error from abacus_account.utils.validations import validate_country_code def create_account( account_id: int, account_name: str, currency_code: str = None, country_of_tax_residence: str = None, created_by: str = None, creation_source: str = None ) -> response.Response: """Create an account, account_payee, account_payment_term, and account_tax_info. Args: account_id (int): same as the vendor_id in art_relations, PK of account account_name (str): name of the account currency_code (str): optional currency code used to create account_payment_term record country_of_tax_residence (str): optional alpha-3 iso country code created_by(str): name of account creator, creation_source (str): the source of the account creation """ try: _validate_account_creation( account_id, currency_code, country_of_tax_residence ) new_account = models.Account.create( account_name=account_name, account_id=account_id, created_by=created_by ) if ( currency_code and creation_source not in SKIP_PAYMENT_TERM_TEMPLATE_CREATION_SOURCES ): create_payment_term_from_template_by_currency_code( currency_code, account_id ) elif currency_code: # creating the default payment term with null values # in not mandatory fields to fill them later create_account_payment_term( currency_code=currency_code, account_id=account_id ) create_account_payee(account_id=account_id) create_account_tax_info( account_id=account_id, country_of_tax_residence=country_of_tax_residence ) return response.Response( message=AccountDetailSchema().dump(new_account), status=201 ) except Exception as e: status_code = e.kwargs.get('status_code', 400) \ if isinstance(e, ValidationError) else 400 return validation_error(str(e), status_code=status_code) def get_eligible_accounts_for_group_id(payment_group_id: int): """Return accounts meeting the group_criteria of the specified payment_group. Args: payment_group_id (int): unique identifier of payment_group """ results = models.Account.get_eligible_for_payment(payment_group_id) message = EligibleAccountListSchema(many=True).dump(results) return response.Response(message=message, status=200) def get_payment_eligibility_status(account_id: int) -> response.Response: """Get account's payment eligibility status. Args: account_id (int): id of an account Returns: account's payment eligibility status: "active" or "on_hold" """ account = models.Account.get_by_id_or_error(account_id) eligibility_status = ELIGIBILITY_STATUSES.ACTIVE payment_hold = account.payment_hold today = date.today() if payment_hold and ( (payment_hold.is_on_hold and payment_hold.start_date <= today) or (not payment_hold.is_on_hold and payment_hold.start_date > today) ): eligibility_status = ELIGIBILITY_STATUSES.ON_HOLD return response.Response( message={'eligibility_status': eligibility_status}, status=200 ) def _validate_account_creation( account_id: int, currency_code: str = None, country_of_tax_residence: str = None ): """Check that account creation params are valid. Args: account_id (int): id of account to be created currency_code (str): optional alpha-3 iso currency code country_of_tax_residence (str): optional alpha-3 iso country code """ # specific validation added by AAA team to handle duplicate account creation # (will also prevent silent failures from occurring downstream) --dczinsky if models.Account.get_by_id(account_id): raise ValidationError( ERROR_ACCOUNT_ALREADY_EXISTS.format(account_id=account_id), status_code=409 ) if currency_code: get_payment_term_template_by_currency_code(currency_code) if country_of_tax_residence: validate_country_code(country_of_tax_residence.upper()) def get_sap_formatted_account_info(account_id: int) -> Type[response.Response]: """Get SAP formatted account details. Args: account_id (int): id of an account """ account = models.Account.get_by_id_or_error(account_id) return response.Response( message=SAPFormattedAccountDetailSchema().dump(account), status=200 ) def update_account(account_object: object, **params: dict) -> Type[response.Response]: """Update an account. Args: account_object (object): account object params (dict): dict of fields that needs to be updated Fields - sap_created_at """ try: account_object.update_attributes(**params) models.Account.commit_changes() except Exception as e: return response.create_error_response('error', str(e), status=400) return response.Response( message=AccountDetailSchema().dump(account_object), status=200 )