"""Payee model.""" from typing import List from uuid import uuid4 from abacus_common_logic.models.base import BaseModel, db from sqlalchemy.inspection import inspect from payee.constants.constants import PAYEE_TYPES from payee.models.payee_collaborator import PayeeCollaborator from payee.utils.exception import GetTypedPayeeException class Payee(BaseModel): """Payee model.""" __tablename__ = 'payee' payee_id = db.Column(db.Integer, primary_key=True, autoincrement=True) reference_payment_type_id = db.Column(db.Integer) payoneer_client_reference_id = db.Column(db.String(255), default=uuid4) payoneer_program_id = db.Column(db.Integer) payoneer_assigned_id = db.Column(db.Integer, nullable=True) payee_name = db.Column(db.String(255), nullable=True) payee_type = db.Column(db.Enum(*PAYEE_TYPES)) @property def entity_id_name(self): """Get payee entity id name.""" return inspect(self.__class__).primary_key[0].name @property def payee_entity_id(self): """Get payee entity id.""" return self.payee_id @classmethod def get_payees_by_collaborator_ids(cls, collaborator_ids: List[int]): return ( db.session.query(cls, PayeeCollaborator) .join(PayeeCollaborator, cls.payee_id == PayeeCollaborator.payee_id) .filter(PayeeCollaborator.collaborator_id.in_(collaborator_ids)) .all() ) @classmethod def get_payee_ids_for_abacus_states(cls, states: list[dict] = []): """Get payee IDs for abacus states.""" or_conditions = [] for state in states: and_conditions = [] if state.get('action_status') is not None: and_conditions.append( db.literal_column('action_status') == state['action_status'] ) if state.get('action_name') is not None: and_conditions.append( db.literal_column('action_name') == state['action_name'] ) if state.get('message') is not None: and_conditions.append(db.literal_column('message') == state['message']) if and_conditions: or_conditions.append(db.and_(*and_conditions)) return ( db.select([db.literal_column('parent_table_id')]) .filter( db.literal_column('parent_table_name') == cls.__tablename__, db.or_(*or_conditions), ) .select_from(db.table('abacus_state')) ) @classmethod def get_payees( cls, limit: int = 100, offset: int = 0, search_term: str | None = None, abacus_states: list = [], account_ids: list = [], payoneer_program_ids: list = [], ): query = db.session.query(cls) if abacus_states: subq = cls.get_payee_ids_for_abacus_states(abacus_states) query = query.filter(cls.payee_id.in_(subq)) if account_ids: subq = db.session.query(PayeeCollaborator.payee_id).filter( PayeeCollaborator.account_id.in_(account_ids) ) query = query.filter(cls.payee_id.in_(subq)) if payoneer_program_ids: query = query.filter(cls.payoneer_program_id.in_(payoneer_program_ids)) if search_term: query = query.filter( db.or_( cls.payee_name.ilike(f'%{search_term}%'), db.cast(cls.payee_id, db.String).ilike(f'%{search_term}%'), ) ) total_count = query.count() query = query.order_by(cls.payee_id) query = query.limit(limit) if offset: query = query.offset(offset) return query.all(), total_count @classmethod def get_payees_by_payoneer_client_reference_id( cls, payoneer_client_reference_ids: List[str] ): return ( db.session.query(cls) .filter(cls.payoneer_client_reference_id.in_(payoneer_client_reference_ids)) .all() ) def get_typed_payee(self): match self.payee_type: case PAYEE_TYPES.COLLABORATOR: (_, payee_collaborator) = ( db.session.query(Payee, PayeeCollaborator) .join( PayeeCollaborator, Payee.payee_id == PayeeCollaborator.payee_id ) .filter(Payee.payee_id == self.payee_id) .first() ) return payee_collaborator @property def account_id(self): typed_payee = self.get_typed_payee() if not typed_payee: raise GetTypedPayeeException( 'Could not get payee subtype for payee {} with subtype: {}'.format( self.payee_id, self.payee_type, ) ) return typed_payee.account_id