ApplicantPortal/app/applicant/model.py
2025-03-12 20:43:26 -06:00

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)