"""Logic for payee.""" from functools import wraps from http import HTTPStatus import logging from typing import List from abacus_common_logic.connectors.database import db from flask import g from payee.connectors import ows_collaborator from payee.connectors.ows_abacus_state import create_payee_states_by_parent_table from payee.constants.constants import ( ACTION_STATUSES, KYC_NOTIFICATION_MESSAGE, PAYEE_TYPES, ) from payee.models.account_payee import AccountPayee from payee.models.payee import Payee from payee.models.payee_collaborator import PayeeCollaborator from payee.utils.exception import PayeeCreateException logger = logging.getLogger('payee') def map_payee_id(f): @wraps(f) def wrapper(*args, **kwargs): if payee := ( Payee.get_by_id(kwargs.pop('payee_id', None)) or AccountPayee.get_by_id(kwargs.pop('account_payee_id', None)) ): g.payee_flow = payee.__class__.__name__ return f(*args, payee=payee, **kwargs) return {'error': 'Payee not found'}, HTTPStatus.BAD_REQUEST return wrapper def create_payee_collaborator(params) -> 'Payee': """Create a payee and payee_collaborator.""" try: # a payee cannot be created without access to this resource, # since ows-collaborator performs an access check for this action. collaborator_id = params.get('collaborator_id') collaborator = ows_collaborator.get_collaborator(collaborator_id) account_payee = AccountPayee.get_payee_by_account_id(collaborator['vendor_id']) if account_payee is None: raise PayeeCreateException('Account payee data not found') if account_payee.payoneer_program_id is None: raise PayeeCreateException('payoneer_program_id not found') payee = Payee.build( reference_payment_type_id=params.get('reference_payment_type_id'), payoneer_program_id=account_payee.payoneer_program_id, payee_name=collaborator['name'], payee_type=PAYEE_TYPES.COLLABORATOR, ) db.session.flush() PayeeCollaborator.create( collaborator_id=collaborator_id, account_id=collaborator['vendor_id'], payee_id=payee.payee_id, ) create_payee_states_by_parent_table(payee.payee_id, 'payee') db.session.commit() return payee except Exception as exc: db.session.rollback() logger.error(f'Error when creating payee: {str(exc)}') raise exc def get_payees_by_collaborator_ids(collaborator_ids: List[int]) -> 'dict': """Get payees by collaborator IDs.""" payees = Payee.get_payees_by_collaborator_ids(collaborator_ids) payee_map = { payee_collaborator.collaborator_id: payee for (payee, payee_collaborator) in payees } return payee_map def _get_payees_by_payoneer_client_reference_ids( payoneer_client_reference_ids: List[int], ) -> 'dict': """Get payees by payoneer client reference IDs.""" payees = Payee.get_payees_by_payoneer_client_reference_id( payoneer_client_reference_ids ) payee_map = {payee.payoneer_client_reference_id: payee for payee in payees} return payee_map def get_payees_paginated( limit: int, offset: int = 0, requires_review: bool | None = None, search_term: str | None = None, abacus_states: list | None = None, account_ids: list | None = None, payoneer_program_ids: list | None = None, ) -> dict: """Get paginated list of payees.""" if abacus_states is None: abacus_states = [] if requires_review: abacus_states.append( { 'action_status': ACTION_STATUSES.RUNNING, 'message': KYC_NOTIFICATION_MESSAGE, } ) payees, payee_count = Payee.get_payees( limit=limit, offset=offset, abacus_states=abacus_states, account_ids=account_ids, payoneer_program_ids=payoneer_program_ids, search_term=search_term, ) return {'items': payees, 'total_count': payee_count} def get_payee_collaborators_paginated( limit: int, offset: int = 0, payee_ids: List[int] = None ) -> dict: """Get paginated list of payees.""" payees_collabs, total_count = PayeeCollaborator.get_payee_collaborators( limit=limit, offset=offset, payee_ids=payee_ids ) return {'items': payees_collabs, 'total_count': total_count} def get_payees_dataloader( collaborator_ids: List[int], payoneer_client_reference_ids: List[int], ) -> 'dict': if not collaborator_ids and not payoneer_client_reference_ids: raise ValueError( 'Either collaborator_ids or payoneer_client_reference_ids must be provided.' ) ids, payee_map = ( (collaborator_ids, get_payees_by_collaborator_ids(collaborator_ids)) if collaborator_ids else ( payoneer_client_reference_ids, _get_payees_by_payoneer_client_reference_ids(payoneer_client_reference_ids), ) ) return {'payees': [{'data': payee_map.get(collab_id)} for collab_id in ids]}