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.')