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/buyercall/blueprints/api2/doc/endpoints/credit_checks.py
import logging
import traceback
import json

from flask import (
    Blueprint,
    make_response,
    request,
    jsonify,
    current_app as app)
from buyercall.lib.util_crypto import AESCipher
from flask import Blueprint, jsonify, make_response
from buyercall.blueprints.partnership.models import Partnership, PartnershipAccount, PartnershipAccountCreditTie, \
    PartnershipCreditTie
from buyercall.lib.util_rest import rest_partnership_account, rest_partnership, requires_auth, \
    rest_is_partnership_account, rest_is_partnership
from buyercall.blueprints.form_leads.models import FormLeadField, FormLead
from flask_restx import Resource
<<<<<<< HEAD
from buyercall.blueprints.api2.restx import api
=======
from buyercall.blueprints.api2.restplus import api
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
from buyercall.blueprints.contacts.models import Contact, CreditReports
from sqlalchemy import func, or_, and_, extract

log = logging.getLogger(__name__)
# ns = api.namespace('Pre-Qualified Credit Check', description='Operations related to Pre-qualified credit checks.', path='/accounts')


class CreditVerification:

    @staticmethod
    def all_credit_check_fields_exits(contact):
        """
        Determine whether or not to perform the credit check.
        All fields must be present in order to perform check.

        Returns if valid, the birthdate, the error message

        :return: boolean, string, string
        """
        invalid_message = []
        missing_message = []
        encrypt_key = app.config['CRYPTO_SECRET_KEY']
        cipher = AESCipher(encrypt_key)
        result = True
        error_message = ''
        contact_birthday = ''

        from buyercall.lib.util_credit_reports import validate_name, validate_address_street, \
            validate_address_city, validate_address_state, validate_address_zip, \
            validate_city_state_zip_combo, format_dob_year

        # Check contact birthday
        if contact.birthday is None:
            form_lead = FormLead \
                .query \
                .filter(and_(FormLead.contact_id == contact.id,
                             FormLead.partnership_account_id == contact.partnership_account_id)) \
                .first()
            if form_lead is None:
                missing_message.append('birthday')
            else:
                form_lead_field = FormLeadField \
                    .query \
                    .filter(and_(FormLeadField.lead_id == form_lead.id,
                                 or_(FormLeadField.field_id == 'birthday',
                                     FormLeadField.field_id == 'datepicker'))) \
                    .first()
                if form_lead_field is None or form_lead_field.field_value is None:
                    missing_message.append('birthday')
                else:
                    contact_birthday = cipher.decrypt(form_lead_field.field_value)
        else:
            contact_birthday = contact.birthday
        try:
            contact_birthyear = format_dob_year(contact_birthday)
        except:
            invalid_message.append('birthday')

        # Check contact names
        if contact.firstname and contact.lastname:
            validate_contact_name = validate_name(contact.firstname, contact.lastname)

            if not validate_contact_name:
                invalid_message.append('firstname and lastname')
        else:
            if contact.firstname is None:
                missing_message.append('firstname')

            if contact.lastname is None:
                missing_message.append('lastname')

        # Check contact street
        if contact.address_1:
            validate_contact_street = validate_address_street(contact.address_1)
            if not validate_contact_street:
                invalid_message.append('address_1')
        else:
            missing_message.append('address_1')

        # Check contact city
        if contact.city:
            validate_contact_city = validate_address_city(contact.city)
            if not validate_contact_city:
                invalid_message.append('city')
        else:
            missing_message.append('city')

        # Check contact state
        if contact.state:
            validate_contact_state = validate_address_state(contact.state)
            if not validate_contact_state:
                invalid_message.append('state')
        else:
            missing_message.append('state')

        # Check contact zip
        if contact.zip:
            validate_contact_zip = validate_address_zip(contact.zip)
            if not validate_contact_zip:
                invalid_message.append('zip')
        else:
            missing_message.append('zip')

        # Check contact combo
        if len(invalid_message) == 0:
            validate_contact_combo = validate_city_state_zip_combo(contact.zip, contact.city, contact.state)
            if not validate_contact_combo:
                invalid_message.append('zip, city, state combination')

        if len(invalid_message) > 0:
            count = 1
            error_message = 'The following contact field(s) are invalid: '

            for message in invalid_message:
                append = ', '
                if count == len(invalid_message):
                    append = ''

                error_message += message + append
                count += 1
            error_message += '. '

        if len(missing_message) > 0:
            count = 1
            error_message += 'The following contact field(s) are missing: '

            for message in missing_message:
                append = ', '
                if count == len(missing_message):
                    append = ''

                error_message += message + append
                count += 1
            error_message += '.'

        if len(error_message) > 0:
            result = False
            error_message = 'Error performing pre-qualify credit check. ' + error_message

        return result, contact_birthday, error_message


    @staticmethod
    def get_credit_check_report(contact, contact_birth_day):
        """
        Generates contact credit report and returns the object.

        :return: CreditReport
        """
        service_provider = ''

        credit_credentials = PartnershipAccountCreditTie \
            .partner_account_seven_hundred_credit_info(contact.partnership_account_id, 'prequalify')
        service_provider = '700Credit'

        if not credit_credentials:
            credit_credentials = PartnershipAccountCreditTie \
                .partner_account_finserv_credit_info(contact.partnership_account_id, 'prequalify')
            service_provider = 'Finserv'

        if not credit_credentials:
            partner_account = PartnershipAccount\
                .query\
                .filter(PartnershipAccount.id == contact.partnership_account_id).first()
            try:
                credit_credentials = PartnershipCreditTie \
                    .partner_finserv_credit_info(partner_account.partnership_id, 'prequalify')
            except:
                log.error(
                    "Unable to get credit credentials for partnership account id {} and got error : {}".format(contact.partnership_account_id,
                                                                                                               traceback.format_exc()))
            service_provider = 'Finserv'

        if not credit_credentials:
            return False, None, 'Credit check credentials not found.'
        else:
            try:
                from ....contacts.contact_tasks import pull_prequalify_credit
                if credit_credentials:
                    if credit_credentials.experian_enabled:
                        bureau = 'experian'
                    elif credit_credentials.transunion_enabled:
                        bureau = 'transunion'
                    elif credit_credentials.equifax_enabled:
                        bureau = 'equifax'
                    else:
                        bureau = ''

                    credit_report_id = pull_prequalify_credit(bureau,
                                                              'prequalify',
                                                              contact.id,
                                                              contact.partnership_account_id,
                                                              contact.firstname,
                                                              contact.lastname,
                                                              contact.address_1,
                                                              contact.city,
                                                              contact.state,
                                                              contact.zip,
                                                              service_provider,
                                                              contact_birth_day)

                    if credit_report_id and credit_report_id > 0:
                        credit_report = CreditReports \
                            .query \
                            .filter(and_(CreditReports.id == credit_report_id,
                                         CreditReports.partnership_account_id == contact.partnership_account_id)) \
                            .first()

                        if credit_report:
                            return True, credit_report, ''
                        else:
                            return False, None, 'Error performing pre-qualify credit check. Credit report not generated.'
                    else:
                        return False, None, 'Error performing pre-qualify credit check. Credit report not generated.'
                else:
                    return False, None, 'Error performing pre-qualify credit check. Credit report not generated.'
            except:
                log.error("Cannot check credit on contact {}, partnership account {} and got error : {}".format(contact.id, contact.partnership_account_id,
                                                                                                                traceback.format_exc()))
                return False, None, 'Error performing pre-qualify credit check.'


# @ns.route('/<int:paid>/form/<int:cid>/credit_check')
@api.doc(responses={200: 'OK',
                    400: 'Error performing operation.',
                    401: 'Unauthorized request.'},
         params={'cid': 'The contact Id',
                 'paid': 'The partner account Id'})
class ApiPreQualifiedCreditCheckGet(Resource):
    @requires_auth
    def get(self, paid, cid):
        """
        Retrieves a credit score and all other relevant information for a specific contact and partnership account.

        <p>
        The Pre-Qualify Credit Check API GET endpoint should be used to retrieve credit information for a contact
        associated with a partner account.
        </p>
        <br />
        <p>
        You will require a partner authentication token, a partner account id and a contact id to make a
        successful request. A response will
        be returned, similar to the example below, based
        on a successful request:
        <br />
        <br />
        </p>
        <pre class="code-background" style="color: white">
        {
            "approved": false,
            "score": 750,
            "trades": [
                {
                  "accountNumber": "62063570877071001",
                  "balanceAmount": 20332,
                  "financeType": "Loan",
                  "monthlyPaymentAmount": 449,
                  "numberMonthsRemaining": 0,
                  "subcode": "1638640",
                  "subscriberDisplayName": "CAPITAL ONE AUTO FINAN"
                }
            ]
        }
        </pre>

        """
        if rest_is_partnership and rest_partnership:
            error_message = ''
            partnership_account = PartnershipAccount\
                .query\
                .filter(and_(PartnershipAccount.id == paid,
                             PartnershipAccount.partnership_id == rest_partnership.id))\
                .first()

            if partnership_account:
                contact = Contact\
                    .query\
                    .filter(and_(Contact.id == cid, Contact.partnership_account_id ==paid))\
                    .first()

                if contact is None:
                    return api.abort(400, message='Contact for partnership account not found.')

                valid_contact, valid_birth_day, error_message = CreditVerification.all_credit_check_fields_exits(contact)

                if not valid_contact:
                    return api.abort(400, message=error_message)

                try:
                    credit_report_valid, credit_report, error_message = CreditVerification.get_credit_check_report(contact, valid_birth_day)

                    if not credit_report_valid or not credit_report:
                        return api.abort(400, message=error_message)

                    crypto_key = app.config['CRYPTO_SECRET_KEY']
                    cipher = AESCipher(crypto_key)

                    decrypted_score = cipher.decrypt(credit_report.credit_score)
                    converter_score = 0
                    if decrypted_score:
                        converter_score = int(decrypted_score)
                    if credit_report.trades:
                        decrypted_trades = cipher.decrypt(credit_report.trades)
                        converted_trades = json.loads(decrypted_trades)
                        if 'trades' in converted_trades:
                            converted_trades = converted_trades['trades']
                    else:
                        converted_trades = {}

                    return jsonify(
                        approved=credit_report.is_approved,
                        score=converter_score,
                        trades=converted_trades
                    )
                except:
                    log.error("Cannot check credit on contact {}, partnership account {} and got error : {}".format(cid, paid, traceback.format_exc()))
                    return api.abort(400, message='Error performing pre-qualify credit check.')
            else:
                return api.abort(400, message='Partnership account not found.')
        else:
            return api.abort(401, message='Unauthorized request.')