297 lines
12 KiB
Python
297 lines
12 KiB
Python
from datetime import datetime
|
|
from dateutil.relativedelta import relativedelta
|
|
from app.util.datatypes.enum import BaseEnum
|
|
from bson import json_util
|
|
from app.auth.model import User, UserIDField
|
|
from ..database import db, EmbeddedDocumentBase, DocumentBase
|
|
from app.database.fields import QuarterDateField, QuarterYearField
|
|
|
|
|
|
class MarriageStatus(BaseEnum):
|
|
SINGLE = 'single'
|
|
MARRIED = 'married'
|
|
DIVORCED = 'divorced'
|
|
WIDOWED = 'windowed'
|
|
SEPARATED = 'separated'
|
|
|
|
|
|
class OwnOrRent(BaseEnum):
|
|
OWN = 'own'
|
|
RENT = 'rent'
|
|
|
|
|
|
class FilingTypes(BaseEnum):
|
|
SINGLE = 'single'
|
|
JOINT = 'joint'
|
|
|
|
|
|
class Property(EmbeddedDocumentBase):
|
|
original_cost = db.FloatField(required=False)
|
|
home_price = db.FloatField(required=False)
|
|
address1 = db.StringField(required=False)
|
|
address2 = db.StringField(required=False)
|
|
city = db.StringField(required=False)
|
|
state = db.StringField(required=False)
|
|
zip = db.StringField(required=False)
|
|
number_of_units = db.IntField(required=False)
|
|
funding_purpose = db.StringField(required=False, default='purchase')
|
|
property_purpose = db.StringField(required=False)
|
|
year_acquired = QuarterYearField(required=False)
|
|
year_built = QuarterYearField(required=False)
|
|
existing_liens = db.EmbeddedDocumentListField('AssetExpense', required=False)
|
|
title_holders = db.StringField(required=False)
|
|
tax_amount = db.FloatField(required=False)
|
|
hoa_amount = db.FloatField(required=False)
|
|
downpayment_source = db.StringField(required=False)
|
|
property_type = db.StringField(required=False)
|
|
|
|
|
|
class Job(EmbeddedDocumentBase):
|
|
employer_info = db.StringField(required=False)
|
|
self_employed = db.BooleanField(required=False)
|
|
date_from = QuarterDateField(required=False)
|
|
date_to = QuarterDateField(required=False, default=datetime.today())
|
|
monthly_income = db.FloatField(required=False)
|
|
position_title = db.StringField(required=False)
|
|
bus_phone = db.StringField(required=False)
|
|
naics = db.StringField(required=False)
|
|
|
|
def _get_date_delta_on_job(self, time_scale='years'):
|
|
if self.date_to and self.date_from:
|
|
date_from = QuarterDateField.make_datetime(self.date_to)
|
|
date_to = QuarterDateField.make_datetime(self.date_from)
|
|
return getattr(relativedelta(date_from, date_to), time_scale)
|
|
return 0
|
|
|
|
@classmethod
|
|
def ignore_from_json(cls):
|
|
result = super().ignore_from_json()
|
|
result.append('years_moths_on_job')
|
|
return result
|
|
|
|
@property
|
|
def years_on_job(self):
|
|
return self._get_date_delta_on_job('years')
|
|
|
|
@property
|
|
def months_on_job(self):
|
|
return self._get_date_delta_on_job('months')
|
|
|
|
@property
|
|
def years_months_on_job(self):
|
|
years = self.years_on_job
|
|
extra_months = self.months_on_job
|
|
return f'{years} Year(s), {extra_months} Month(s)'
|
|
|
|
@classmethod
|
|
def additional_fields(cls):
|
|
res = super().additional_fields()
|
|
res.append('years_months_on_job')
|
|
return res
|
|
|
|
|
|
class PrevAddress(EmbeddedDocumentBase):
|
|
address1 = db.StringField(required=False)
|
|
address2 = db.StringField(required=False)
|
|
city = db.StringField(required=False)
|
|
state = db.StringField(required=False)
|
|
zip = db.StringField(required=False)
|
|
own_or_rent = db.EnumField(OwnOrRent, required=False)
|
|
years = db.IntField(required=False)
|
|
|
|
|
|
class AssetBase(EmbeddedDocumentBase):
|
|
meta = {'allow_inheritance': True}
|
|
value = db.FloatField(required=False, default=0)
|
|
|
|
|
|
class AssetExpense(AssetBase):
|
|
meta = {'allow_inheritance': True}
|
|
description = db.StringField(required=False, default='')
|
|
|
|
|
|
class CheckingSavings(AssetBase):
|
|
bank_sl_cu = db.StringField(required=False)
|
|
acct_number = db.StringField(required=False)
|
|
|
|
|
|
class LifeInsurance(AssetBase):
|
|
face_amount = db.FloatField(required=False, default=None)
|
|
|
|
|
|
class Expense(EmbeddedDocumentBase):
|
|
base_emp_inc = db.FloatField(required=False)
|
|
over_time = db.FloatField(required=False)
|
|
bonuses = db.FloatField(required=False)
|
|
commissions = db.FloatField(required=False)
|
|
dividends_interest = db.FloatField(required=False)
|
|
net_rental_income = db.FloatField(required=False)
|
|
other = db.EmbeddedDocumentField('AssetExpense', required=False)
|
|
|
|
|
|
class ScheduleOfRealEstate(EmbeddedDocumentBase):
|
|
address1 = db.StringField(required=False)
|
|
address2 = db.StringField(required=False)
|
|
city = db.StringField(required=False)
|
|
state = db.StringField(required=False)
|
|
zip = db.StringField(required=False)
|
|
status = db.StringField(required=False)
|
|
type = db.StringField(required=False)
|
|
present_market_value = db.FloatField(required=False)
|
|
amount_of_mortgages = db.FloatField(required=False)
|
|
gross_rental_income = db.FloatField(required=False)
|
|
mortgage_payments = db.FloatField(required=False)
|
|
insurance_main_taxes_misc = db.FloatField(required=False)
|
|
net_rental_income = db.FloatField(required=False)
|
|
|
|
|
|
class Declarations(EmbeddedDocumentBase):
|
|
any_judgements = db.BooleanField(required=False)
|
|
declared_bankruptcy = db.BooleanField(required=False)
|
|
property_foreclosed = db.BooleanField(required=False)
|
|
party_to_lawsuit = db.BooleanField(required=False)
|
|
obligated_loan_foreclosure = db.BooleanField(required=False)
|
|
delinquent_or_default = db.BooleanField(required=False)
|
|
alimony_child_support_maintenance = db.BooleanField(required=False)
|
|
down_payment_borrowed = db.BooleanField(required=False)
|
|
comaker_or_endorser = db.BooleanField(required=False)
|
|
intend_primary_residence = db.BooleanField(Required=False)
|
|
|
|
|
|
class AcknowledgeAgree(EmbeddedDocumentBase):
|
|
signature = db.StringField(required=False)
|
|
date = QuarterDateField(required=False)
|
|
|
|
|
|
class GovernmentInfo(EmbeddedDocumentBase):
|
|
will_not_furnish = db.BooleanField(required=False)
|
|
ethnicity = db.BooleanField(required=False)
|
|
sex = db.StringField(required=False)
|
|
race = db.StringField(required=False)
|
|
|
|
|
|
class GeneralAssets(AssetExpense):
|
|
deposit_held_by = db.StringField(required=False, default='')
|
|
|
|
|
|
class Assets(EmbeddedDocumentBase):
|
|
assets = db.EmbeddedDocumentListField('GeneralAssets', required=False, default=[GeneralAssets()])
|
|
checking_savings = db.EmbeddedDocumentListField('CheckingSavings', required=False, default=[])
|
|
stocks_bonds = db.EmbeddedDocumentListField('AssetExpense', required=False, default=[])
|
|
life_insurance = db.EmbeddedDocumentListField('LifeInsurance', required=False, default=[])
|
|
retirement_funds = db.EmbeddedDocumentListField('AssetExpense', required=False, default=[])
|
|
vehicles_owned = db.EmbeddedDocumentListField('AssetExpense', required=False, default=[])
|
|
property_owned = db.EmbeddedDocumentListField('ScheduleOfRealEstate', required=False, default=[])
|
|
owned_real_estate_value = db.FloatField(required=False, default=None)
|
|
vested_interest_retirement_fund = db.FloatField(required=False, default=None)
|
|
net_worth_bus_owned = db.FloatField(required=False, default=None)
|
|
autos_owned_value = db.FloatField(required=False, default=None)
|
|
other_assets = db.StringField(required=False, default='')
|
|
|
|
|
|
class Applicant(EmbeddedDocumentBase):
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
user = None
|
|
if 'email' in kwargs:
|
|
user = User.objects(email=kwargs['email']).first()
|
|
elif 'user_id' in kwargs:
|
|
user = User.objects(user_id=kwargs['user_id']).first()
|
|
|
|
if user:
|
|
kwargs['user'] = user
|
|
kwargs['user_id'] = user.user_id
|
|
|
|
user.date_of_birth = kwargs.get('date_of_birth') or user.date_of_birth
|
|
user.first_name = kwargs.get('first_name') or user.first_name
|
|
user.middle_init_or_name = kwargs.get('middle_init_or_name') or user.middle_init_or_name
|
|
user.last_name = kwargs.get('last_name') or user.last_name
|
|
user.address1 = kwargs.get('address1') or user.address1
|
|
user.address2 = kwargs.get('address2') or user.address2
|
|
user.city = kwargs.get('city') or user.city
|
|
user.state = kwargs.get('state') or user.state
|
|
user.zip = kwargs.get('zip') or user.zip
|
|
user.phone_number = kwargs.get('phone_number') or user.phone_number
|
|
user.save()
|
|
|
|
if 'user' in kwargs:
|
|
kwargs['email'] = kwargs['user'].email
|
|
kwargs['first_name'] = kwargs['user'].first_name
|
|
kwargs['middle_init_or_name'] = kwargs['user'].middle_init_or_name
|
|
kwargs['last_name'] = kwargs['user'].last_name
|
|
kwargs['address1'] = kwargs['user'].address1
|
|
kwargs['address2'] = kwargs['user'].address2
|
|
kwargs['city'] = kwargs['user'].city
|
|
kwargs['state'] = kwargs['user'].state
|
|
kwargs['zip'] = kwargs['user'].zip
|
|
kwargs['phone_number'] = kwargs['user'].phone_number
|
|
kwargs['date_of_birth'] = kwargs['user'].date_of_birth
|
|
kwargs.pop('user')
|
|
|
|
super().__init__(*args, **kwargs)
|
|
|
|
user = db.ReferenceField('User', required=False)
|
|
user_id = UserIDField(required=False)
|
|
# these properties will be loaded from the user if there is one, if there isn't one, they will be saved here
|
|
email = db.StringField(required=False)
|
|
first_name = db.StringField(required=False)
|
|
middle_init_or_name = db.StringField(required=False, db_field='middle_initial')
|
|
last_name = db.StringField(required=False)
|
|
address1 = db.StringField(required=False)
|
|
address2 = db.StringField(required=False)
|
|
city = db.StringField(required=False)
|
|
state = db.StringField(required=False)
|
|
zip = db.StringField(required=False)
|
|
date_of_birth = QuarterDateField(required=False)
|
|
phone_number = db.StringField(required=False, db_field='home_phone')
|
|
# the applicant specific fields
|
|
role = db.StringField(required=False)
|
|
pin = db.StringField(required=False)
|
|
social_security_number = db.StringField(required=False)
|
|
years_school = db.IntField(required=False)
|
|
degree_earned = db.StringField(required=False)
|
|
school_name = db.StringField(required=False)
|
|
marriage_status = db.EnumField(MarriageStatus, required=False, default=MarriageStatus.SINGLE)
|
|
number_dependents = db.IntField(required=False, default=0)
|
|
ages_dependents = db.ListField(db.IntField(required=False))
|
|
previous_jobs = db.EmbeddedDocumentListField('Job', required=False)
|
|
previous_addresses = db.EmbeddedDocumentListField('PrevAddress', required=False)
|
|
expense_info = db.EmbeddedDocumentField('Expense', required=False)
|
|
other_incomes = db.EmbeddedDocumentListField('AssetExpense', required=False)
|
|
assets = db.EmbeddedDocumentField('Assets', required=False, default=Assets())
|
|
declarations = db.EmbeddedDocumentField('Declarations', required=False)
|
|
liabilities = db.EmbeddedDocumentListField('AssetExpense', required=False)
|
|
acknowledge_and_agree = db.EmbeddedDocumentField('AcknowledgeAgree', required=False)
|
|
auth_borrower = db.EmbeddedDocumentField('AcknowledgeAgree', required=False)
|
|
auth_fcra = db.EmbeddedDocumentField('AcknowledgeAgree', required=False)
|
|
government_info = db.EmbeddedDocumentField('GovernmentInfo')
|
|
|
|
@classmethod
|
|
def ignore_to_json(cls):
|
|
result = super().ignore_to_json()
|
|
result.append('user')
|
|
result.append('user_id')
|
|
return result
|
|
|
|
@classmethod
|
|
def ignore_from_json(cls):
|
|
result = super().ignore_from_json()
|
|
result.append('user_name')
|
|
return result
|
|
|
|
|
|
class Application(DocumentBase):
|
|
filing_type = db.EnumField(FilingTypes, required=False, default=FilingTypes.SINGLE)
|
|
user_id = UserIDField(required=True)
|
|
applicants = db.EmbeddedDocumentListField('Applicant', required=True)
|
|
deposit_held_by = db.StringField(required=False)
|
|
property_info = db.EmbeddedDocumentField('Property', required=False)
|
|
finalized = db.BooleanField(required=True, default=False)
|
|
|
|
def to_json(self, *args, **kwargs):
|
|
use_db_field = kwargs.pop('use_db_field', True)
|
|
result = super().to_mongo(use_db_field=use_db_field)
|
|
for applicant in result.get('applicants', [{}]):
|
|
applicant.pop('user', None)
|
|
return json_util.dumps(result, *args, **kwargs)
|