HEX
Server: Apache/2.4.52 (Ubuntu)
System: Linux spn-python 5.15.0-89-generic #99-Ubuntu SMP Mon Oct 30 20:42:41 UTC 2023 x86_64
User: arjun (1000)
PHP: 8.1.2-1ubuntu2.20
Disabled: NONE
Upload Files
File: //home/arjun/projects/buyercall_forms/buyercall/buyercall/lib/util_credit_reports.py
import logging
from buyercall.integrations.seven_hundred_credit import SevenHundredCredit
from buyercall.integrations.finserv import Finserv
from flask import current_app as app
from buyercall.lib.util_crypto import AESCipher
from dateutil.parser import parse
import re
import us
from uszipcode import SearchEngine
from string import punctuation
log = logging.getLogger(__name__)

HOURS = 3600
DAYS = 86400  # The length of a day in seconds


def seven_hundred_credit_client(partnership_account_id, product_type):
    from buyercall.blueprints.partnership.models import PartnershipAccountCreditTie
    # Get the encryption key to decrypt credentials
    encrypt_key = app.config['CRYPTO_SECRET_KEY']
    # Retrieve the 700 credit credit profile for the partnership account
    partner_credit_profile = PartnershipAccountCreditTie.\
        partner_account_seven_hundred_credit_info(partnership_account_id, product_type)
    cipher = AESCipher(encrypt_key)

    # Decrypt the credentials
    decrypted_username = cipher.decrypt(partner_credit_profile.api_username)
    decrypted_password = cipher.decrypt(partner_credit_profile.api_password)
    client = SevenHundredCredit(decrypted_username,
                                decrypted_password,
                                product_type)
    return client


def finserv_credit_client(partnership_account_id, product_type):
    from buyercall.blueprints.partnership.models import PartnershipAccountCreditTie, PartnershipCreditTie
    # Get the encryption key to decrypt credentials
    encrypt_key = app.config['CRYPTO_SECRET_KEY']
    # Retrieve the Finserv credit profile for the partnership account
    partner_credit_profile = PartnershipAccountCreditTie.\
        partner_account_finserv_credit_info(partnership_account_id, product_type)
    if not partner_credit_profile:
        from buyercall.blueprints.partnership.models import PartnershipAccount
        partner_account = PartnershipAccount.query.filter(PartnershipAccount.id == partnership_account_id).first()
        partner_credit_profile = PartnershipCreditTie.partner_finserv_credit_info(partner_account.partnership_id,
                                                                                  product_type)
    cipher = AESCipher(encrypt_key)

    # Decrypt the credentials
    decrypted_username = cipher.decrypt(partner_credit_profile.api_username)
    decrypted_password = cipher.decrypt(partner_credit_profile.api_password)
    decrypted_dealercode = cipher.decrypt(partner_credit_profile.api_account)
    client = Finserv(decrypted_username,
                     decrypted_password,
                     decrypted_dealercode,
                     product_type)
    return client


def validate_ssn(ssn):
    format_ssn = ssn.replace('-', '').replace(' ', '').replace('#', '')
    if len(format_ssn) != 9:
        log.info('the length is {}'.format(len(str(format_ssn))))
        return False
    # Check the ssn number against a pattern to ensure its a valid number
    pattern = re.match(r'\b(?!000|.+0{4})(?:\d{9}|\d{3}-\d{2}-\d{4})\b', str(format_ssn))
    if not pattern:
        return False
    # When in testing ignore 666 otherwise if in production valid for 666 numbers
    if not app.config['DEBUG']:
        if format_ssn[:3] == '666':
            return False
    # Check to make sure the number does not start with 9
    if format_ssn[:1] == '9':
        return False
    # Last check to see the number is not a known spam or fake ssn number
    if format_ssn in ['000000000', '219099999', '111111111', '123456789', '333333333']:
        return False
    return True


def validate_name(firstname, lastname):
    if firstname == '' or firstname == '':
        return False
    # Check to see if the name has numbers
    firstname_numbers = bool(re.search(r'\d', firstname))
    if firstname_numbers:
        return False

    if lastname == '' or lastname == '':
        return False
    # Check to see if the name has numbers
    lastname_numbers = bool(re.search(r'\d', lastname))
    if lastname_numbers:
        return False

    return True


# Format an address to match 700 credit requirements
def format_street(street):
    # Get a list of not-allowed characters required by 700 Credit
    exclude_string = str(punctuation).replace('#', '').replace('-', '').replace('.', '').replace('/', '')

    exclude_list = [char for char in exclude_string]
    for char in exclude_list:
        if char in exclude_list:
            street = street.replace(char, '')
    return street


# Format the full name of lead by removing special characters
def format_full_name(full_name):
    # Get a list of not-allowed characters required by 700 Credit
    exclude_string = str(punctuation).replace('-', '')

    exclude_list = [char for char in exclude_string]
    for char in exclude_list:
        if char in exclude_list:
            full_name = full_name.replace(char, '')
    return full_name


# Format an address to match 700 credit requirements
def format_city(city):
    # Get a list of not-allowed characters required by 700 Credit
    exclude_string = str(punctuation).replace('#', '').replace('-', '').replace('.', '').replace('/', '')
    exclude_list = [char for char in exclude_string]
    exclude_number = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

    for char in exclude_list:
        city = city.replace(char, '')

    for num in exclude_number:
        city = city.replace(num, '')

    return city


def format_state(state):
    # Get a list of not-allowed characters required by 700 Credit
    exclude_string = str(punctuation).replace('#', '').replace('-', '').replace('.', '').replace('/', '')
    exclude_list = [char for char in exclude_string]
    exclude_number = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

    for char in exclude_list:
        state = state.replace(char, '')

    for num in exclude_number:
        state = state.replace(num, '')

    state = state.lower().strip()
    state_lookup = us.states.lookup(state)

    if state_lookup:
        state_abbr = state_lookup.abbr
        return state_abbr

    return None


def format_zip(zip_):
    # Get a list of not-allowed characters required by 700 Credit
    exclude_string = str(punctuation)
    exclude_list = [char for char in exclude_string]
    zip_ = zip_[:5]

    for char in exclude_list:
        zip_ = zip_.replace(char, '')

    zip_ = zip_.replace(' ', '')

    return zip_


def validate_address_street(street):
    if street == '' or street == ' ':
        return False
    return True


def validate_address_city(city):
    if city == '' or city == ' ':
        return False
    return True


def validate_address_state(state):
    if state == '' or state == ' ':
        return False

    formatted_state = format_state(state)
    if not formatted_state:
        return False

    #if not app.config['DEBUG']:
    #    state = (format_state(state)).lower()
    #    state_lookup = us.states.lookup(state)
    #    if not state_lookup:
    #        return False
    return True


def validate_address_zip(zip_):
    if zip_ == '' or zip_ == ' ':
        return False
    # if not app.config['DEBUG']:
    #    search = SearchEngine(simple_zipcode=True, db_file_dir="/tmp/harry")
    #    zip_lookup = search.by_zipcode(format_zip(zip_))
    #    if not zip_lookup:
    #        return False
    return True


def validate_city_state_zip_combo(zip_, city, state):

    # This doesn't seem to work well. There is combination that is real that comes back as false, so lets just ignore
    # this function for now and always return True until package is better and updated

    # if not app.config['DEBUG']:
    #    if zip_ == '' or zip_ == ' ':
    #        return False
    #    elif city == '' or city == ' ':
    #        return False
    #    search = SearchEngine(simple_zipcode=True, db_file_dir="/tmp")
    #    zip_lookup = search.by_zipcode(format_zip(zip_))
    #    zip_to_dict = zip_lookup.to_dict()
    #    zip_city = zip_to_dict['major_city']
    #    zip_state = zip_to_dict['state']
    #    if zip_city.lower() != format_city(city).lower():
    #        return False
    #    if zip_state.lower() != format_state(state).lower():
    #        return False
    return True


# Extract a year from dob field for Finserv
def format_dob_year(dob):
    if dob:
        year = parse(dob, fuzzy=True).year
        return year
    else:
        year = ''
        return year