first commit
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
using System.Xml.Linq;
|
||||
using CRIF.ACTion.Configuration;
|
||||
|
||||
namespace CRIF.ACTion.Loan
|
||||
{
|
||||
public class AppDetailBankcardSection : AppDetailsSection
|
||||
{
|
||||
public AppDetailBankcardSection(XNamespace sectionNamespace, CrifSettings settings)
|
||||
: base(sectionNamespace, "appDetailBankcard", settings)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
using System.Xml.Linq;
|
||||
using CRIF.ACTion.Common;
|
||||
using CRIF.ACTion.Configuration;
|
||||
using Landmark.OLA.Models.Assets;
|
||||
using Landmark.OLA.Models.Loan;
|
||||
|
||||
namespace CRIF.ACTion.Loan
|
||||
{
|
||||
public class AppDetailHelocSection : AppDetailsSection
|
||||
{
|
||||
private readonly List<XObject> _content;
|
||||
|
||||
private readonly XElement _fieldsElement;
|
||||
|
||||
public AppDetailHelocSection(XNamespace sectionNamespace, CrifSettings settings,
|
||||
string interestRateType = null, string calculationType = null)
|
||||
: base(sectionNamespace, "appDetailHELOC", settings, interestRateType, calculationType)
|
||||
{
|
||||
_content = [];
|
||||
}
|
||||
|
||||
private protected AppDetailHelocSection(XNamespace sectionNamespace, CrifSettings settings,
|
||||
string elementName, string interestRateType = null, string calculationType = null)
|
||||
: base(sectionNamespace, elementName, settings, interestRateType, calculationType)
|
||||
{
|
||||
_content = [];
|
||||
}
|
||||
|
||||
public virtual void AddPropertyDetails(RealEstateBase realEstateBase, bool? mfgHomeIncludesLand = null)
|
||||
{
|
||||
var appDetailPropertiesElement = new XElement(CrifNamespaces.App + "appDetailProperties");
|
||||
|
||||
var propertyType = "RealEstate";
|
||||
var collateralType = CrifConstants.CollateralIds[CrifConstants.Collateral.ResidentialRealEstate];
|
||||
|
||||
string subType;
|
||||
if (mfgHomeIncludesLand.HasValue)
|
||||
{
|
||||
propertyType = "MfgHomeAndLand";
|
||||
collateralType = mfgHomeIncludesLand.Value ?
|
||||
CrifConstants.CollateralIds[CrifConstants.Collateral.ManufacturedHomeAndLand] :
|
||||
CrifConstants.CollateralIds[CrifConstants.Collateral.ManufacturedHome];
|
||||
|
||||
subType = ((ManufacturedHome)realEstateBase).Type.Value.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
subType = ((RealEstate)realEstateBase).Type.Value.ToString();
|
||||
}
|
||||
|
||||
var statusID = "Active";
|
||||
var includeInLTVCalculations = true;
|
||||
|
||||
|
||||
var appDetailPropertyElement = new XElement(CrifNamespaces.App + "appDetailProperty",
|
||||
new XAttribute(CrifNamespaces.Common + "idRef", realEstateBase.GetOrCreateGuid()),
|
||||
new XAttribute(CrifNamespaces.Common + "propertyType", propertyType),
|
||||
new XAttribute(CrifNamespaces.Common + "propertySubType", subType),
|
||||
new XAttribute(CrifNamespaces.App + "isCollateralFL", realEstateBase.IsCollateral),
|
||||
new XAttribute(CrifNamespaces.App + "isTradeInFL", realEstateBase.IsTradeIn),
|
||||
new XAttribute(CrifNamespaces.App + "statusID", statusID),
|
||||
new XAttribute(CrifNamespaces.App + "includeInLTVCalculations", includeInLTVCalculations),
|
||||
new XAttribute(CrifNamespaces.App + "collateralTypeID", collateralType)
|
||||
);
|
||||
|
||||
appDetailPropertiesElement.Add(appDetailPropertyElement);
|
||||
|
||||
_content.Add(appDetailPropertiesElement);
|
||||
}
|
||||
|
||||
public void AddHmdaDisclosed(bool? acceptedDisclosure)
|
||||
{
|
||||
if ((!acceptedDisclosure.HasValue) || !acceptedDisclosure.Value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var hmdaElement = new XElement(CrifNamespaces.App + "appDetailHMDA2018",
|
||||
new XAttribute(CrifNamespaces.App + "isNoticeDisclosedFL", acceptedDisclosure.Value));
|
||||
|
||||
_content.Add(hmdaElement);
|
||||
}
|
||||
|
||||
public override void SetDetails(LoanApplication loanApplication, Guid channelRef, object[] additionalContent = null, XElement fieldsElement = null, XElement vehicleValuationsElement = null)
|
||||
{
|
||||
base.SetDetails(loanApplication, channelRef, [.. _content], _fieldsElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.Xml.Linq;
|
||||
using CRIF.ACTion.Configuration;
|
||||
|
||||
namespace CRIF.ACTion.Loan
|
||||
{
|
||||
public class AppDetailSignatureSection : AppDetailsSection
|
||||
{
|
||||
public AppDetailSignatureSection(XNamespace sectionNamespace, CrifSettings settings)
|
||||
: base(sectionNamespace, "appDetail", settings, "Fixed", "Installment")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
using System.Xml.Linq;
|
||||
using CRIF.ACTion.Common.Builders;
|
||||
using CRIF.ACTion.Common;
|
||||
using CRIF.ACTion.Configuration;
|
||||
using CRIF.ACTion.Services.Landmark;
|
||||
using Landmark.OLA.Models.Loan;
|
||||
using Landmark.OLA.Models.Loan.Enums;
|
||||
|
||||
namespace CRIF.ACTion.Loan
|
||||
{
|
||||
public class AppDetailsSection : CrifRequestSection
|
||||
{
|
||||
private readonly string _elementName;
|
||||
private readonly string _interestRateType;
|
||||
private readonly string _calculationType;
|
||||
private readonly ProductIdService _productIdTranslator;
|
||||
|
||||
protected AppDetailsSection(XNamespace sectionNamespace, string elementName, CrifSettings settings,
|
||||
string interestRateType = null, string calculationType = null)
|
||||
: base(sectionNamespace, "appDetails", settings)
|
||||
{
|
||||
_elementName = elementName;
|
||||
|
||||
_interestRateType = string.IsNullOrWhiteSpace(interestRateType) ? "Variable" : interestRateType;
|
||||
_calculationType = string.IsNullOrWhiteSpace(calculationType) ? "OpenEnd" : calculationType;
|
||||
|
||||
_productIdTranslator = new ProductIdService(settings);
|
||||
|
||||
}
|
||||
|
||||
public static bool IsHMDA(LoanType? loanType)
|
||||
{
|
||||
HMDALoanType hmdaType;
|
||||
try
|
||||
{
|
||||
hmdaType = (HMDALoanType)Enum.Parse(typeof(HMDALoanType), loanType.ToString());
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public virtual void SetDetails(LoanApplication loanApplication, Guid channelRef, object[] additionalContent = null, XElement fieldsElement = null, XElement vehicleValuationsElement = null)
|
||||
{
|
||||
var appDetailElement = new XElement(CrifNamespaces.App + _elementName,
|
||||
new XAttribute(CrifNamespaces.App + "contractRate", 0m), //Per Ben V. at Landmark, we should send in 0 so that CRIF can set the correct rate
|
||||
new XAttribute(CrifNamespaces.App + "financedAmt", loanApplication.RequestedAmount),
|
||||
new XAttribute(CrifNamespaces.App + "termFrequencyCD", "Monthly"),
|
||||
new XAttribute(CrifNamespaces.App + "calculationType", _calculationType),
|
||||
new XAttribute(CrifNamespaces.App + "loanType", "Consumer"),
|
||||
new XAttribute(CrifNamespaces.App + "interestRateType", _interestRateType),
|
||||
new XAttribute(CrifNamespaces.App + "rankNum", 1),
|
||||
new XAttribute(CrifNamespaces.App + "isApplicantRequestedInterestRate", false),
|
||||
new XAttribute(CrifNamespaces.App + "isApplicantRequestedAmountRequested", true),
|
||||
new XAttribute(CrifNamespaces.App + "principal", loanApplication.RequestedAmount), //TODO #234: Why is the loan amount listed twice?
|
||||
new XAttribute(CrifNamespaces.App + "isApplicantRequestedTerm", true),
|
||||
new XAttribute(CrifNamespaces.App + "isHMDAFL", IsHMDA(loanApplication.LoanType))
|
||||
);
|
||||
|
||||
if (loanApplication.TermLengthInMonths.HasValue)
|
||||
{
|
||||
appDetailElement.Add(new XAttribute(CrifNamespaces.App + "termInMonths", loanApplication.TermLengthInMonths.Value));
|
||||
}
|
||||
|
||||
var appDetailParties = new XElement(CrifNamespaces.App + "appDetailParties",
|
||||
new XElement(CrifNamespaces.App + "appDetailParty",
|
||||
new XAttribute(CrifNamespaces.Common + "idRef", channelRef),
|
||||
new XAttribute(CrifNamespaces.Common + "partyType", "Channel"),
|
||||
new XAttribute(CrifNamespaces.App + "appPartyType", "ServicingChannel")));
|
||||
|
||||
var appDetailRequestedAmts = new XElement(CrifNamespaces.App + "appDetailRequestedAmts",
|
||||
new XElement(CrifNamespaces.App + "appDetailRequestedAmt",
|
||||
new XAttribute(CrifNamespaces.App + "requestedAmount", loanApplication.RequestedAmount), //TODO #234: Financed amount is listed 3 times? Are the other 2 from the calculator?
|
||||
new XAttribute(CrifNamespaces.App + "requestedAmountType", "Generic")));
|
||||
|
||||
var product = new XElement(CrifNamespaces.App + "product",
|
||||
new XAttribute(CrifNamespaces.Common + "productID",
|
||||
_productIdTranslator.GetProductId(loanApplication.LoanType.Value)));
|
||||
|
||||
|
||||
var loanPurposes = new XElement(CrifNamespaces.App + "loanPurposes",
|
||||
new XElement(CrifNamespaces.App + "appDetailLoanPurpose",
|
||||
new XAttribute(CrifNamespaces.App + "rank", 1),
|
||||
new XElement(CrifNamespaces.App + "loanPurpose",
|
||||
new XAttribute(CrifNamespaces.Common + "CD", (int)loanApplication.Purpose.Value)
|
||||
)));
|
||||
|
||||
appDetailElement.Add(appDetailParties);
|
||||
|
||||
appDetailElement.Add(additionalContent);
|
||||
|
||||
appDetailElement.Add(appDetailRequestedAmts);
|
||||
appDetailElement.Add(product);
|
||||
|
||||
string productId = _productIdTranslator.GetProductId(loanApplication.LoanType.Value).ToString();
|
||||
|
||||
XElement appFieldsElement = null;
|
||||
|
||||
|
||||
if (_settings.CustomFields != null && _settings.CustomFields.ProductIdToCategoryId.TryGetValue(productId, out string productCategoryId))
|
||||
{
|
||||
CustomPropertyStatusData customPropertyRenovationData = _settings.CustomFields.CustomPropertyRenovationFieldData.Find(x => x.ProductCategoryId == productCategoryId);
|
||||
if (customPropertyRenovationData != null)
|
||||
{
|
||||
bool realEstateNotNullValue = loanApplication.RealEstate?.CurrentlyBeingRemodeledOrImproved ?? false;
|
||||
string propertyRenovationValueCode = realEstateNotNullValue ? customPropertyRenovationData.YesId : customPropertyRenovationData.NoId;
|
||||
appFieldsElement = GetLookupFieldLinkElement(customPropertyRenovationData.CustomFieldId, propertyRenovationValueCode, "AppDetail", appFieldsElement);
|
||||
}
|
||||
|
||||
CustomPropertyStatusData customPropertySaleData = _settings.CustomFields.CustomPropertySaleFieldData.Find(x => x.ProductCategoryId == productCategoryId);
|
||||
if (customPropertySaleData != null)
|
||||
{
|
||||
bool realEstateNotNullValue = loanApplication.RealEstate?.CurrentlyListedForSale ?? false;
|
||||
string propertySaleValueCode = realEstateNotNullValue ? customPropertySaleData.YesId : customPropertySaleData.NoId;
|
||||
appFieldsElement = GetLookupFieldLinkElement(customPropertySaleData.CustomFieldId, propertySaleValueCode, "AppDetail", appFieldsElement);
|
||||
}
|
||||
|
||||
CustomJointCreditData customJointCreditData = _settings.CustomFields.CustomJointCreditFieldData.Find(x => x.ProductCategoryId == productCategoryId);
|
||||
if (customJointCreditData != null)
|
||||
{
|
||||
string jointCreditValueCode = loanApplication.CoApplicant != null ? customJointCreditData.JointlyId : customJointCreditData.IndividuallyId;
|
||||
appFieldsElement = GetLookupFieldLinkElement(customJointCreditData.CustomFieldId, jointCreditValueCode, "ProductCategory", appFieldsElement);
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(loanApplication.PromoCode))
|
||||
{
|
||||
if (_settings.CustomFieldMappings.LoanTypeToPromoId.TryGetValue(productId, out string promoFieldId))
|
||||
{
|
||||
appFieldsElement = GetStringFieldLinkElement(promoFieldId, loanApplication.PromoCode, "ProductCategory", appFieldsElement);
|
||||
}
|
||||
}
|
||||
|
||||
if (loanApplication.Vehicle != null)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(loanApplication.Vehicle.LicensePlateNumber))
|
||||
{
|
||||
if (_settings.CustomFieldMappings.CustomFieldID.TryGetValue("LicensePlateNumber", out string customFieldId))
|
||||
{
|
||||
appFieldsElement = GetStringFieldLinkElement(customFieldId, loanApplication.Vehicle.LicensePlateNumber, "ProductCategory", appFieldsElement);
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(loanApplication.Vehicle.CountyTitled))
|
||||
{
|
||||
if (_settings.CustomFieldMappings.CustomFieldID.TryGetValue("CountyTitled", out string customFieldId))
|
||||
{
|
||||
appFieldsElement = GetStringFieldLinkElement(customFieldId, loanApplication.Vehicle.CountyTitled, "ProductCategory", appFieldsElement);
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(loanApplication.Vehicle.MunicipalityWhereKept))
|
||||
{
|
||||
if (_settings.CustomFieldMappings.CustomFieldID.TryGetValue("MunicipalityWhereKept", out string customFieldId))
|
||||
{
|
||||
appFieldsElement = GetStringFieldLinkElement(customFieldId, loanApplication.Vehicle.MunicipalityWhereKept, "ProductCategory", appFieldsElement);
|
||||
}
|
||||
}
|
||||
|
||||
var municipalityTypeCode = GetMunicipalityTypeCode(loanApplication.Vehicle.MunicipalityType);
|
||||
if (!string.IsNullOrWhiteSpace(municipalityTypeCode))
|
||||
{
|
||||
if (_settings.CustomFieldMappings.CustomFieldID.TryGetValue("MunicipalityType", out string customFieldId))
|
||||
{
|
||||
appFieldsElement = GetLookupFieldLinkElement(customFieldId, municipalityTypeCode, "ProductCategory", appFieldsElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (appFieldsElement != null)
|
||||
{
|
||||
appDetailElement.Add(appFieldsElement); //Order matters for this element.
|
||||
}
|
||||
|
||||
appDetailElement.Add(loanPurposes);
|
||||
appDetailElement.Add(vehicleValuationsElement); //Order matters for this element.
|
||||
|
||||
AddContent(appDetailElement);
|
||||
}
|
||||
|
||||
private static XElement GetStringFieldLinkElement(string customFieldId, string value, string fieldLevel, XElement fieldsElement)
|
||||
{
|
||||
fieldsElement = CreateFieldsElementIfNull(fieldsElement);
|
||||
var stringFieldLinkElement = new XElement(CrifNamespaces.Common + "stringFieldLink",
|
||||
new XAttribute(CrifNamespaces.Common + "value", value));
|
||||
var customFieldElement = new XElement(CrifNamespaces.Common + "customField",
|
||||
new XAttribute(CrifNamespaces.Common + "ID", customFieldId),
|
||||
new XAttribute(CrifNamespaces.Common + "fieldLevel", fieldLevel));
|
||||
fieldsElement.Add(stringFieldLinkElement);
|
||||
stringFieldLinkElement.Add(customFieldElement);
|
||||
return fieldsElement;
|
||||
}
|
||||
|
||||
private static XElement GetLookupFieldLinkElement(string Id, string value, string fieldLevel, XElement fieldsElement)
|
||||
{
|
||||
fieldsElement = CreateFieldsElementIfNull(fieldsElement);
|
||||
var lookupFieldLinkElement = new XElement(CrifNamespaces.Common + "lookupFieldLink",
|
||||
new XAttribute(CrifNamespaces.Common + "value", value),
|
||||
new XElement(CrifNamespaces.Common + "customLookupField",
|
||||
new XAttribute(CrifNamespaces.Common + "ID", Id),
|
||||
new XAttribute(CrifNamespaces.Common + "fieldLevel", fieldLevel)));
|
||||
fieldsElement.Add(lookupFieldLinkElement);
|
||||
return fieldsElement;
|
||||
}
|
||||
|
||||
private static XElement CreateFieldsElementIfNull(XElement fieldsElement)
|
||||
{
|
||||
if (fieldsElement == null)
|
||||
{
|
||||
fieldsElement = new XElement(CrifNamespaces.App + "fields");
|
||||
}
|
||||
return fieldsElement;
|
||||
}
|
||||
|
||||
private string GetMunicipalityTypeCode(string municipalityType)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(municipalityType))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (_settings?.CustomFieldMappings?.MunicipalityTypeCode == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var key = municipalityType.Trim().ToUpperInvariant();
|
||||
return _settings.CustomFieldMappings.MunicipalityTypeCode.TryGetValue(key, out string code)
|
||||
? code
|
||||
: null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System.Xml.Linq;
|
||||
using CRIF.ACTion.Common;
|
||||
using CRIF.ACTion.Common.Builders;
|
||||
using CRIF.ACTion.Configuration;
|
||||
|
||||
namespace CRIF.ACTion.Loan
|
||||
{
|
||||
public class AppNotesSectionBuilder : CrifRequestSection
|
||||
{
|
||||
public AppNotesSectionBuilder(XNamespace sectionNamespace, CrifSettings settings)
|
||||
: base(sectionNamespace, "appNotes", settings)
|
||||
{
|
||||
}
|
||||
|
||||
public void AddAppNote(string appNoteContent)
|
||||
{
|
||||
|
||||
var appNote = new XElement(CrifNamespaces.App + "appNote",
|
||||
new XAttribute(CrifNamespaces.App + "noteEntry", BuilderUtils.FormatCrifData(appNoteContent)),
|
||||
new XAttribute(CrifNamespaces.App + "noteTypeDisplayName", "Application Note"),
|
||||
new XAttribute(CrifNamespaces.App + "noteTypeCategoryDisplayName", "Application Note"));
|
||||
|
||||
var noteType = new XElement(CrifNamespaces.App + "noteType",
|
||||
new XAttribute(CrifNamespaces.Common + "CD", 1));
|
||||
|
||||
var noteTypeCategory = new XElement(CrifNamespaces.App + "noteTypeCategory",
|
||||
new XAttribute(CrifNamespaces.Common + "lookupType", "NoteTypeCategory"),
|
||||
new XAttribute(CrifNamespaces.Common + "CD", 1));
|
||||
|
||||
appNote.Add(noteType, noteTypeCategory);
|
||||
|
||||
AddContent(appNote);
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
using System.Xml.Linq;
|
||||
using CRIF.ACTion.Configuration;
|
||||
using Landmark.OLA.Models.Assets;
|
||||
|
||||
namespace CRIF.ACTion.Loan.Assets
|
||||
{
|
||||
public class AppDetailMfgHomeAndLandSection : AppDetailHelocSection
|
||||
{
|
||||
//AppDetailMfgHomeAndLand is generally similar to AppDetailHeloc.
|
||||
public AppDetailMfgHomeAndLandSection(XNamespace sectionNamespace, CrifSettings settings)
|
||||
: base(sectionNamespace, settings, "appDetailMfgHousingAndLand", "Fixed", "Installment")
|
||||
{
|
||||
}
|
||||
|
||||
public override void AddPropertyDetails(RealEstateBase realEstateBase, bool? mfgHomeIncludesLand = null)
|
||||
{
|
||||
if (!mfgHomeIncludesLand.HasValue)
|
||||
throw new ArgumentException("Manufactured Home Loans must state if the land is included.");
|
||||
|
||||
base.AddPropertyDetails(realEstateBase, mfgHomeIncludesLand);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System.Xml.Linq;
|
||||
using CRIF.ACTion.Configuration;
|
||||
|
||||
namespace CRIF.ACTion.Loan.Assets
|
||||
{
|
||||
public class AppDetailRealEstateSection : AppDetailHelocSection
|
||||
{
|
||||
|
||||
//So far, AppDetailRealEstate is used exactly the same as AppDetailHeloc.
|
||||
//The only difference is the element name and term types.
|
||||
public AppDetailRealEstateSection(XNamespace sectionNamespace, CrifSettings settings)
|
||||
: base(sectionNamespace, settings, "appDetailRealEstate", "Fixed", "Installment")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
using System.Xml.Linq;
|
||||
using CRIF.ACTion.Common;
|
||||
using CRIF.ACTion.Configuration;
|
||||
using Landmark.OLA.Models.Assets;
|
||||
using Landmark.OLA.Models.Loan;
|
||||
|
||||
namespace CRIF.ACTion.Loan.Assets
|
||||
{
|
||||
public class AppDetailVehicleSection : AppDetailsSection
|
||||
{
|
||||
private readonly List<XObject> _content;
|
||||
private XElement _vehicleValuationsElement;
|
||||
|
||||
public AppDetailVehicleSection(XNamespace sectionNamespace, CrifSettings settings)
|
||||
: base(sectionNamespace, "appDetailVehicle", settings, "Fixed", "Installment")
|
||||
{
|
||||
_content = [];
|
||||
}
|
||||
|
||||
public void AddPropertyDetails(Vehicle vehicle)
|
||||
{
|
||||
//If there's no vehicle type, it's likely a preapproval and doesn't need the appDetailProperties element
|
||||
if (vehicle is null || vehicle.Type is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var appDetailPropertiesElement = new XElement(CrifNamespaces.App + "appDetailProperties");
|
||||
|
||||
var propertyValues = PropertyValues.GetPropertyValues(vehicle.Type.Value);
|
||||
|
||||
var isCollateralFL = true;
|
||||
var isTradeInFL = false;
|
||||
var statusID = "Active";
|
||||
var includeInLTVCalculations = true;
|
||||
|
||||
var appDetailPropertyElement = new XElement(CrifNamespaces.App + "appDetailProperty",
|
||||
new XAttribute(CrifNamespaces.Common + "idRef", vehicle.GetOrCreateGuid()),
|
||||
new XAttribute(CrifNamespaces.Common + "propertyType", propertyValues.PropertyType),
|
||||
new XAttribute(CrifNamespaces.Common + "propertySubType", propertyValues.PropertySubType),
|
||||
new XAttribute(CrifNamespaces.App + "isCollateralFL", isCollateralFL),
|
||||
new XAttribute(CrifNamespaces.App + "isTradeInFL", isTradeInFL),
|
||||
new XAttribute(CrifNamespaces.App + "statusID", statusID),
|
||||
new XAttribute(CrifNamespaces.App + "includeInLTVCalculations", includeInLTVCalculations),
|
||||
new XAttribute(CrifNamespaces.App + "collateralTypeID", propertyValues.CollateralId)
|
||||
);
|
||||
|
||||
appDetailPropertiesElement.Add(appDetailPropertyElement);
|
||||
|
||||
_vehicleValuationsElement = new XElement(CrifNamespaces.App + "vehicleValuations",
|
||||
new XElement(CrifNamespaces.App + "appDetailVehicleValuation",
|
||||
new XAttribute(CrifNamespaces.Common + "idRef", vehicle.ValuationId),
|
||||
new XAttribute(CrifNamespaces.App + "valueType", vehicle.ValuationType.Value.ToString())));
|
||||
//TODO: What does valuationType mean?
|
||||
|
||||
_content.Add(appDetailPropertiesElement);
|
||||
}
|
||||
|
||||
public void AddSalesPriceDetails(LoanApplication loanApplication)
|
||||
{
|
||||
_content.Add(new XAttribute(CrifNamespaces.App + "initialSalesPrice", loanApplication.RequestedAmount));
|
||||
}
|
||||
|
||||
public override void SetDetails(LoanApplication loanApplication, Guid channelRef, object[] additionalContent = null, XElement fieldsElement = null, XElement vehicleValuationsElement = null)
|
||||
{
|
||||
base.SetDetails(loanApplication, channelRef, [.. _content], vehicleValuationsElement: _vehicleValuationsElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace CRIF.ACTion.Loan.Assets
|
||||
{
|
||||
public interface IVehicleValuations
|
||||
{
|
||||
VehicleValuationsSection VehicleValuations { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using CRIF.ACTion.Common;
|
||||
using CRIF.ACTion.Configuration;
|
||||
|
||||
namespace CRIF.ACTion.Loan.Assets
|
||||
{
|
||||
public class MfgHousingAndLandAppBuilder : ILoanApplicationRequestBuilder
|
||||
{
|
||||
private readonly CrifSettings _settings;
|
||||
|
||||
public MfgHousingAndLandAppBuilder(CrifSettings settings)
|
||||
{
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public void SetDetails(LoanApplicationRequestBuilder createApp)
|
||||
{
|
||||
createApp.AppDetails = new AppDetailMfgHomeAndLandSection(createApp.CrifRequestSectionNamespace, _settings);
|
||||
|
||||
|
||||
var includesLand = true;
|
||||
if (createApp.LoanApplication.ManufacturedHome?.Lot?.IsRented ?? false)
|
||||
{
|
||||
includesLand = false;
|
||||
}
|
||||
|
||||
|
||||
((AppDetailMfgHomeAndLandSection)createApp.AppDetails).AddPropertyDetails(createApp.LoanApplication.ManufacturedHome, includesLand);
|
||||
((AppDetailMfgHomeAndLandSection)createApp.AppDetails).AddHmdaDisclosed(createApp.LoanApplication.PrimaryBorrower.HmdaValues.HmdaNoticeDisclosed);
|
||||
createApp.Properties.AddProperty(new MfgHousingProperty(createApp.LoanApplication.ManufacturedHome, includesLand));
|
||||
createApp.Addresses.AddAddress(createApp.LoanApplication.ManufacturedHome.Lot, ContactMechanisms.CrifContactMechanism.RealEstateAddress);
|
||||
|
||||
createApp.AppDetails.SetDetails(createApp.LoanApplication,
|
||||
createApp._sourceChannel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using Landmark.OLA.Models.Assets;
|
||||
|
||||
namespace CRIF.ACTion.Loan.Assets
|
||||
{
|
||||
public class MfgHousingProperty : RealEstateProperty
|
||||
{
|
||||
public MfgHousingProperty(ManufacturedHome manufacturedHome, bool includesLand)
|
||||
: base(manufacturedHome, "propertyMfgHousing", "MfgHomeAndLand")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using Landmark.OLA.Models.Assets.Enums;
|
||||
|
||||
namespace CRIF.ACTion.Loan.Assets
|
||||
{
|
||||
public static class PropertyValues
|
||||
{
|
||||
public static (int CollateralId, string PropertyType, string PropertySubType, string elementName) GetPropertyValues(VehicleType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case VehicleType.Automobile:
|
||||
return (CrifConstants.CollateralIds[CrifConstants.Collateral.Vehicle], "Auto", "Automobile", "propertyAuto");
|
||||
case VehicleType.Motorcycle:
|
||||
return (CrifConstants.CollateralIds[CrifConstants.Collateral.Motorcycle], "Motorcycle", "NoneSelected", "propertyAuto");
|
||||
case VehicleType.Boat:
|
||||
return (CrifConstants.CollateralIds[CrifConstants.Collateral.Marine], "Marine", "NoneSelected", "propertyMarine");
|
||||
case VehicleType.ATV:
|
||||
return (CrifConstants.CollateralIds[CrifConstants.Collateral.ATV], "ATV", "NoneSelected", "propertyAuto");
|
||||
case VehicleType.PWC:
|
||||
return (CrifConstants.CollateralIds[CrifConstants.Collateral.Marine], "Marine", "NoneSelected", "propertyMarine");
|
||||
case VehicleType.RecreationalVehicle:
|
||||
return (CrifConstants.CollateralIds[CrifConstants.Collateral.RecreationalVehicle], "RV", "CampingTrailer", "propertyAuto"); //"CampingTrailer" is from CRIF example
|
||||
case VehicleType.Snowmobile:
|
||||
return (CrifConstants.CollateralIds[CrifConstants.Collateral.Snowmobile], "Snowmobile", "NoneSelected", "propertyAuto");
|
||||
case VehicleType.TrailerMotorHome:
|
||||
return (CrifConstants.CollateralIds[CrifConstants.Collateral.RecreationalVehicle], "RV", "Other", "propertyAuto"); //"Other" is from sprint requirements doc
|
||||
default:
|
||||
throw new NotImplementedException("This vehicle type is not implemented.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using CRIF.ACTion.Common;
|
||||
using CRIF.ACTion.Configuration;
|
||||
|
||||
namespace CRIF.ACTion.Loan.Assets
|
||||
{
|
||||
public class RealEstateEquityAppBuilder : ILoanApplicationRequestBuilder
|
||||
{
|
||||
private readonly CrifSettings _settings;
|
||||
|
||||
public RealEstateEquityAppBuilder(CrifSettings settings)
|
||||
{
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public void SetDetails(LoanApplicationRequestBuilder createApp)
|
||||
{
|
||||
createApp.AppDetails = new AppDetailRealEstateSection(createApp.CrifRequestSectionNamespace, _settings);
|
||||
((AppDetailRealEstateSection)createApp.AppDetails).AddPropertyDetails(createApp.LoanApplication.RealEstate);
|
||||
((AppDetailRealEstateSection)createApp.AppDetails).AddHmdaDisclosed(createApp.LoanApplication.PrimaryBorrower.HmdaValues.HmdaNoticeDisclosed);
|
||||
createApp.Properties.AddProperty(new RealEstateProperty(createApp.LoanApplication.RealEstate));
|
||||
createApp.Addresses.AddAddress(createApp.LoanApplication.RealEstate.RealEstateAddress, ContactMechanisms.CrifContactMechanism.RealEstateAddress);
|
||||
|
||||
createApp.AppDetails.SetDetails(createApp.LoanApplication,
|
||||
createApp._sourceChannel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
using System.Xml.Linq;
|
||||
using CRIF.ACTion.Common;
|
||||
using Landmark.OLA.Models.Assets;
|
||||
using Landmark.OLA.Models.Assets.Enums;
|
||||
|
||||
using static CRIF.ACTion.Common.ContactMechanisms;
|
||||
|
||||
namespace CRIF.ACTion.Loan.Assets
|
||||
{
|
||||
public class RealEstateProperty : IProperty
|
||||
{
|
||||
private protected readonly RealEstateBase _realEstateBase;
|
||||
private protected readonly string _elementName;
|
||||
private protected readonly string _propertyType;
|
||||
|
||||
public RealEstateProperty(RealEstateBase realEstateBase, string elementName = "propertyRealEstate",
|
||||
string propertyType = "RealEstate")
|
||||
{
|
||||
_realEstateBase = realEstateBase;
|
||||
_elementName = elementName;
|
||||
_propertyType = propertyType;
|
||||
}
|
||||
|
||||
public XElement Build(params XElement[] content)
|
||||
{
|
||||
var classType = _realEstateBase.GetType();
|
||||
|
||||
if (classType.Equals(typeof(ManufacturedHome)) || classType.IsSubclassOf(typeof(ManufacturedHome)))
|
||||
{
|
||||
var realEstateElement = GetRealEstateElement((ManufacturedHome)_realEstateBase);
|
||||
realEstateElement.Add(
|
||||
new XAttribute(CrifNamespaces.Common + "lienPositionID", LienPositionType.First)
|
||||
);
|
||||
return realEstateElement;
|
||||
}
|
||||
else if (classType.Equals(typeof(RealEstate)) || classType.IsSubclassOf(typeof(RealEstate)))
|
||||
{
|
||||
var realEstateElement = GetRealEstateElement((RealEstate)_realEstateBase);
|
||||
realEstateElement.Add(
|
||||
new XAttribute(CrifNamespaces.Common + "lienPositionID", GetLienPosition(_realEstateBase.LienPosition))
|
||||
);
|
||||
return realEstateElement;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Unexpected object given to constructor for RealEstateProperty");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private XElement GetRealEstateElement(RealEstate realEstate)
|
||||
{
|
||||
return GetRealEstateElement(realEstate, realEstate.Type.Value.ToString());
|
||||
}
|
||||
|
||||
private XElement GetRealEstateElement(ManufacturedHome manufacturedHome)
|
||||
{
|
||||
var element = GetRealEstateElement(manufacturedHome, manufacturedHome.Type.Value.ToString(),
|
||||
manufacturedHome.EstimatedLandValuation, manufacturedHome.EstimatedHomeValuation);
|
||||
//The valuation fields above are suppose to go in totalValue and finalEstimatedValue as written.
|
||||
//It's a little strange but that's how CRIF stores that data.
|
||||
|
||||
// This has to be before propertyLot, otherwise CRIF will complain!
|
||||
if (manufacturedHome.Lot.AnnualPropertyTax.HasValue)
|
||||
{
|
||||
var propertyTaxesElement = new XElement(CrifNamespaces.Common + "propertyTaxes");
|
||||
var propertyTaxElement = new XElement(
|
||||
CrifNamespaces.Common + "propertyTax",
|
||||
new XAttribute(CrifNamespaces.Common + "taxEntity", "IRS"),
|
||||
new XAttribute(CrifNamespaces.Common + "amount", manufacturedHome.Lot.AnnualPropertyTax.Value.ToString()),
|
||||
new XAttribute(CrifNamespaces.Common + "paymentFrequency", "Annually")
|
||||
);
|
||||
propertyTaxesElement.Add(propertyTaxElement);
|
||||
element.Add(propertyTaxesElement);
|
||||
}
|
||||
|
||||
var propertyLotElement = new XElement(CrifNamespaces.Common + "propertyLot");
|
||||
|
||||
if (manufacturedHome.Lot.RentalAmt.HasValue)
|
||||
{
|
||||
propertyLotElement.Add(new XAttribute(CrifNamespaces.Common + "rentalAmt", manufacturedHome.Lot.RentalAmt.Value));
|
||||
}
|
||||
|
||||
element.Add(propertyLotElement);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
private XElement GetRealEstateElement(RealEstateBase realEstateBase, string subtype, decimal? finalEstimatedValue = null, decimal? totalValue = null)
|
||||
{
|
||||
var propertyRealEstateElement = new XElement(CrifNamespaces.Common + _elementName,
|
||||
new XAttribute(CrifNamespaces.Common + "id", realEstateBase.Id),
|
||||
new XAttribute(CrifNamespaces.Common + "propertySubType", subtype),
|
||||
// new XAttribute(CrifNamespaces.Common + "hasClearTitleFL", realEstate.HasClearTitle),
|
||||
new XAttribute(CrifNamespaces.Common + "initialEstimatedValue", realEstateBase.InitialEstimatedValue),
|
||||
new XAttribute(CrifNamespaces.Common + "propertyType", _propertyType),
|
||||
new XAttribute(CrifNamespaces.Common + "ownerOccupiedTypeID", realEstateBase.Use.Value));
|
||||
|
||||
if(finalEstimatedValue.HasValue)
|
||||
{
|
||||
propertyRealEstateElement.Add(new XAttribute(CrifNamespaces.Common + "finalEstimatedValue", finalEstimatedValue));
|
||||
}
|
||||
|
||||
if (totalValue.HasValue)
|
||||
{
|
||||
propertyRealEstateElement.Add(new XAttribute(CrifNamespaces.Common + "totalValue", totalValue));
|
||||
}
|
||||
|
||||
|
||||
var contactMechanismsElement = GetContactMechanisms(realEstateBase);
|
||||
|
||||
propertyRealEstateElement.Add(GetPropertyDetails(realEstateBase));
|
||||
|
||||
propertyRealEstateElement.Add(contactMechanismsElement);
|
||||
|
||||
return propertyRealEstateElement;
|
||||
}
|
||||
|
||||
private static XElement GetContactMechanisms(RealEstateBase realEstateBase)
|
||||
{
|
||||
var contactMechanismType = CrifContactMechanism.RealEstateAddress;
|
||||
var idRef = "";
|
||||
|
||||
var classType = realEstateBase.GetType();
|
||||
if (classType.Equals(typeof(ManufacturedHome)) || classType.IsSubclassOf(typeof(ManufacturedHome)))
|
||||
{
|
||||
contactMechanismType = CrifContactMechanism.ParkContactAddress;
|
||||
idRef = ((ManufacturedHome)realEstateBase).Lot.Id.ToString();
|
||||
}
|
||||
else if (classType.Equals(typeof(RealEstate)) || classType.IsSubclassOf(typeof(RealEstate)))
|
||||
{
|
||||
idRef = ((RealEstate)realEstateBase).RealEstateAddress.Id.ToString();
|
||||
}
|
||||
|
||||
var contactMechanismsElement = new XElement(CrifNamespaces.Common + "contactMechanisms",
|
||||
new XElement(CrifNamespaces.Common + "contactMechanism",
|
||||
new XAttribute(CrifNamespaces.Common + "contactMechanismType", contactMechanismType.ToString()),
|
||||
new XElement(CrifNamespaces.Common + "addressRef",
|
||||
new XAttribute(CrifNamespaces.Common + "idRef", idRef)),
|
||||
new XElement(CrifNamespaces.Common + "contactMechanismCategory",
|
||||
new XAttribute(CrifNamespaces.Common + "CD", (int)GetContactMechanismCategory(contactMechanismType)))
|
||||
));
|
||||
|
||||
return contactMechanismsElement;
|
||||
}
|
||||
|
||||
private static XAttribute[] GetPropertyDetails(RealEstateBase realEstateBase)
|
||||
{
|
||||
var attributeList = new List<XAttribute>();
|
||||
|
||||
if (realEstateBase.HasSpa.HasValue)
|
||||
{
|
||||
attributeList.Add(new XAttribute(CrifNamespaces.Common + "hasSpaFL", realEstateBase.HasSpa.Value));
|
||||
}
|
||||
if (realEstateBase.HasPool.HasValue)
|
||||
{
|
||||
attributeList.Add(new XAttribute(CrifNamespaces.Common + "hasPoolFL", realEstateBase.HasPool.Value));
|
||||
}
|
||||
if (realEstateBase.HasBasement.HasValue)
|
||||
{
|
||||
attributeList.Add(new XAttribute(CrifNamespaces.Common + "hasBasementFL", realEstateBase.HasBasement.Value));
|
||||
}
|
||||
if (realEstateBase.HasCentralAir.HasValue)
|
||||
{
|
||||
attributeList.Add(new XAttribute(CrifNamespaces.Common + "hasCentralAirFL", realEstateBase.HasCentralAir.Value));
|
||||
}
|
||||
if (realEstateBase.HasGarage.HasValue)
|
||||
{
|
||||
attributeList.Add(new XAttribute(CrifNamespaces.Common + "hasGarageFL", realEstateBase.HasGarage.Value));
|
||||
}
|
||||
if (realEstateBase.InFloodZone.HasValue)
|
||||
{
|
||||
attributeList.Add(new XAttribute(CrifNamespaces.Common + "inFloodZoneFL", realEstateBase.InFloodZone.Value));
|
||||
}
|
||||
if (realEstateBase.InEquity.HasValue)
|
||||
{
|
||||
attributeList.Add(new XAttribute(CrifNamespaces.Common + "inEquityFL", realEstateBase.InEquity.Value));
|
||||
}
|
||||
if (realEstateBase.IsPropertyHeldInTrust.HasValue)
|
||||
{
|
||||
attributeList.Add(new XAttribute(CrifNamespaces.Common + "isPropertyHeldInTrust", realEstateBase.IsPropertyHeldInTrust.Value));
|
||||
}
|
||||
|
||||
return [.. attributeList];
|
||||
}
|
||||
|
||||
public static LienPositionType GetLienPosition(LienPosition lienPositionData)
|
||||
{
|
||||
if (lienPositionData.HasFirstMortgage && lienPositionData.HasSecondMortgage)
|
||||
{
|
||||
if (lienPositionData.PayoffFirstMortgage && lienPositionData.PayoffSecondMortgage)
|
||||
{
|
||||
return LienPositionType.First;
|
||||
}
|
||||
else if (!lienPositionData.PayoffFirstMortgage && !lienPositionData.PayoffSecondMortgage)
|
||||
{
|
||||
return LienPositionType.Third;
|
||||
}
|
||||
else if (lienPositionData.PayoffFirstMortgage || lienPositionData.PayoffSecondMortgage)
|
||||
{
|
||||
return LienPositionType.Second;
|
||||
}
|
||||
|
||||
}
|
||||
else if (lienPositionData.HasFirstMortgage || lienPositionData.HasSecondMortgage)
|
||||
{
|
||||
if (lienPositionData.PayoffFirstMortgage || lienPositionData.PayoffSecondMortgage)
|
||||
{
|
||||
return LienPositionType.First;
|
||||
}
|
||||
else
|
||||
{
|
||||
return LienPositionType.Second;
|
||||
}
|
||||
}
|
||||
|
||||
return LienPositionType.First;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using CRIF.ACTion.Common;
|
||||
using CRIF.ACTion.Configuration;
|
||||
using Landmark.OLA.Models.Assets;
|
||||
using Landmark.OLA.Models.Loan.Enums;
|
||||
|
||||
namespace CRIF.ACTion.Loan.Assets
|
||||
{
|
||||
public class VehicleAppBuilder : ILoanApplicationRequestBuilder
|
||||
{
|
||||
private readonly CrifSettings _settings;
|
||||
|
||||
public VehicleAppBuilder(CrifSettings settings)
|
||||
{
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public void SetDetails(LoanApplicationRequestBuilder createApp)
|
||||
{
|
||||
createApp.AppDetails = new AppDetailVehicleSection(createApp.CrifRequestSectionNamespace, _settings);
|
||||
|
||||
if (createApp.LoanApplication.LoanType.Value == LoanType.V_VehiclePreapproval
|
||||
&& createApp.LoanApplication.Vehicle is null)
|
||||
{
|
||||
createApp.LoanApplication.Vehicle = new Vehicle
|
||||
{
|
||||
InitialEstimatedValue = createApp.LoanApplication.RequestedAmount
|
||||
};
|
||||
}
|
||||
|
||||
((AppDetailVehicleSection)createApp.AppDetails).AddPropertyDetails(createApp.LoanApplication.Vehicle);
|
||||
((AppDetailVehicleSection)createApp.AppDetails).AddSalesPriceDetails(createApp.LoanApplication);
|
||||
createApp.Properties.AddProperty(new VehicleProperty(createApp.LoanApplication.Vehicle));
|
||||
createApp.VehicleValuations.AddVehicleValuation(createApp.LoanApplication.Vehicle);
|
||||
|
||||
if (createApp.LoanApplication.LoanType == LoanType.M_Boat &&
|
||||
!(createApp.LoanApplication.Vehicle.BoatAddress is null))
|
||||
{
|
||||
createApp.Addresses.AddAddress(createApp.LoanApplication.Vehicle.BoatAddress, ContactMechanisms.CrifContactMechanism.MarinaAddress);
|
||||
}
|
||||
|
||||
createApp.AppDetails.SetDetails(createApp.LoanApplication,
|
||||
createApp._sourceChannel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
using System.Xml.Linq;
|
||||
using CRIF.ACTion.Common;
|
||||
using CRIF.ACTion.Common.Builders;
|
||||
using Landmark.OLA.Models.Assets;
|
||||
using Landmark.OLA.Models.Loan.Enums;
|
||||
using static CRIF.ACTion.Common.ContactMechanisms;
|
||||
|
||||
namespace CRIF.ACTion.Loan.Assets
|
||||
{
|
||||
public class VehicleProperty : IProperty
|
||||
{
|
||||
private readonly Vehicle _vehicle;
|
||||
|
||||
public VehicleProperty(Vehicle vehicle)
|
||||
{
|
||||
_vehicle = vehicle;
|
||||
}
|
||||
|
||||
public XElement Build(params XElement[] content)
|
||||
{
|
||||
//If there's no vehicle type, it's likely a preapproval and doesn't need this element
|
||||
if (_vehicle is null || _vehicle.Type is null)
|
||||
return null;
|
||||
|
||||
var propertyValues = PropertyValues.GetPropertyValues(_vehicle.Type.Value);
|
||||
|
||||
var propertyElement = new XElement(CrifNamespaces.Common + propertyValues.elementName,
|
||||
new XAttribute(CrifNamespaces.Common + "id", _vehicle.GetOrCreateGuid()),
|
||||
new XAttribute(CrifNamespaces.Common + "propertySubType", propertyValues.PropertySubType),
|
||||
new XAttribute(CrifNamespaces.Common + "yearBuilt", _vehicle.Year.Value),
|
||||
new XAttribute(CrifNamespaces.Common + "initialEstimatedValue", _vehicle.InitialEstimatedValue.Value),
|
||||
new XAttribute(CrifNamespaces.Common + "propertyType", propertyValues.PropertyType));
|
||||
|
||||
if ( _vehicle.Type != Landmark.OLA.Models.Assets.Enums.VehicleType.Automobile ) {
|
||||
propertyElement.Add(new XAttribute(CrifNamespaces.Common + "totalValue",
|
||||
_vehicle.InitialEstimatedValue.Value));
|
||||
}
|
||||
|
||||
if (_vehicle.HasClearTitle.HasValue)
|
||||
{
|
||||
propertyElement.Add(new XAttribute(CrifNamespaces.Common + "hasClearTitleFL",
|
||||
_vehicle.HasClearTitle.Value));
|
||||
}
|
||||
|
||||
if (_vehicle.IsForBusinessUse.HasValue)
|
||||
{
|
||||
var usageType = _vehicle.IsForBusinessUse.Value ? "Business" : "Personal";
|
||||
propertyElement.Add(new XAttribute(CrifNamespaces.Common + "propertyUsageTypeID",
|
||||
usageType));
|
||||
}
|
||||
|
||||
if (_vehicle.IsOwnerOperator.HasValue)
|
||||
{
|
||||
propertyElement.Add(new XAttribute(CrifNamespaces.Common + "isOwnerOperatorFL",
|
||||
_vehicle.IsOwnerOperator.Value));
|
||||
}
|
||||
|
||||
if ((_vehicle.Type == Landmark.OLA.Models.Assets.Enums.VehicleType.PWC || _vehicle.Type == Landmark.OLA.Models.Assets.Enums.VehicleType.Boat)
|
||||
&& !string.IsNullOrWhiteSpace(_vehicle.VIN))
|
||||
{
|
||||
propertyElement.Add(new XAttribute(CrifNamespaces.Common + "hullNum",
|
||||
BuilderUtils.FormatCrifData(_vehicle.VIN)));
|
||||
}
|
||||
|
||||
if (_vehicle.Type == Landmark.OLA.Models.Assets.Enums.VehicleType.Boat && (_vehicle.BoatLength ?? 0) != 0)
|
||||
{
|
||||
propertyElement.Add(new XAttribute(CrifNamespaces.Common + "lengthDesc",
|
||||
_vehicle.BoatLength));
|
||||
}
|
||||
|
||||
// Order matters for elements
|
||||
|
||||
if (_vehicle.Type == Landmark.OLA.Models.Assets.Enums.VehicleType.Boat
|
||||
&& _vehicle.BoatAddress is not null)
|
||||
{
|
||||
var contactMechanisms = new XElement(CrifNamespaces.Common + "contactMechanisms");
|
||||
contactMechanisms.Add(GetAddressContactMechanismElement(_vehicle.BoatAddress.Id, CrifContactMechanism.MarinaAddress));
|
||||
propertyElement.Add(contactMechanisms);
|
||||
}
|
||||
|
||||
var valuationsLinkElement = new XElement(CrifNamespaces.Common + "propertyVehicleValuations",
|
||||
new XElement(CrifNamespaces.Common + "propertyVehicleValuation",
|
||||
new XAttribute(CrifNamespaces.Common + "idRef", _vehicle.ValuationId)));
|
||||
|
||||
propertyElement.Add(valuationsLinkElement);
|
||||
|
||||
if (_vehicle.Type == Landmark.OLA.Models.Assets.Enums.VehicleType.Boat)
|
||||
{
|
||||
propertyElement.Add(CreateMotorElement(_vehicle));
|
||||
propertyElement.Add(CreateTrailerElement(_vehicle));
|
||||
}
|
||||
|
||||
return propertyElement;
|
||||
}
|
||||
|
||||
public static XElement CreateMotorElement(Vehicle vehicle)
|
||||
{
|
||||
var motorElement = new XElement(CrifNamespaces.Common + "motors");
|
||||
|
||||
var propertyMotorElement = new XElement(CrifNamespaces.Common + "propertyMotor",
|
||||
new XAttribute(CrifNamespaces.Common + "motorNum", 1));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(vehicle.MotorMake))
|
||||
{
|
||||
propertyMotorElement.Add(new XAttribute(CrifNamespaces.Common + "make", vehicle.MotorMake));
|
||||
}
|
||||
|
||||
if (vehicle.MotorYear is not null)
|
||||
{
|
||||
propertyMotorElement.Add(new XAttribute(CrifNamespaces.Common + "yearBuilt", vehicle.MotorYear.Value));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(vehicle.MotorModel))
|
||||
{
|
||||
propertyMotorElement.Add(new XAttribute(CrifNamespaces.Common + "model", vehicle.MotorModel));
|
||||
}
|
||||
|
||||
if (vehicle.MotorType is not null)
|
||||
{
|
||||
propertyMotorElement.Add(new XAttribute(CrifNamespaces.Common + "engineTypeID", vehicle.MotorType));
|
||||
}
|
||||
|
||||
motorElement.Add(propertyMotorElement);
|
||||
|
||||
return motorElement;
|
||||
}
|
||||
|
||||
public static XElement CreateTrailerElement(Vehicle vehicle)
|
||||
{
|
||||
var trailerElement = new XElement(CrifNamespaces.Common + "trailer",
|
||||
new XAttribute(CrifNamespaces.Common + "registrationState", "WI"));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(vehicle.TrailerType))
|
||||
{
|
||||
trailerElement.Add(new XAttribute(CrifNamespaces.Common + "propertySubType", vehicle.TrailerType));
|
||||
}
|
||||
|
||||
if (vehicle.TrailerYear is not null)
|
||||
{
|
||||
trailerElement.Add(new XAttribute(CrifNamespaces.Common + "yearBuild", vehicle.TrailerYear.Value));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(vehicle.TrailerMake))
|
||||
{
|
||||
trailerElement.Add(new XAttribute(CrifNamespaces.Common + "make", vehicle.TrailerMake));
|
||||
}
|
||||
|
||||
return trailerElement;
|
||||
}
|
||||
|
||||
public static XElement GetAddressContactMechanismElement(Guid addressRef, CrifContactMechanism contactMechanismType)
|
||||
{
|
||||
|
||||
var contactMechanism = new XElement(CrifNamespaces.Common + "contactMechanism",
|
||||
new XAttribute(CrifNamespaces.Common + "contactMechanismType", contactMechanismType),
|
||||
new XElement(CrifNamespaces.Common + "addressRef",
|
||||
new XAttribute(CrifNamespaces.Common + "idRef", addressRef)
|
||||
),
|
||||
new XElement(CrifNamespaces.Common + "contactMechanismCategory",
|
||||
new XAttribute(CrifNamespaces.Common + "CD", 2)
|
||||
)
|
||||
);
|
||||
|
||||
return contactMechanism;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using System.Xml.Linq;
|
||||
using CRIF.ACTion.Common;
|
||||
using CRIF.ACTion.Common.Builders;
|
||||
using CRIF.ACTion.Configuration;
|
||||
using Landmark.OLA.Models.Assets;
|
||||
|
||||
namespace CRIF.ACTion.Loan.Assets
|
||||
{
|
||||
public class VehicleValuationsSection : CrifRequestSection
|
||||
{
|
||||
public VehicleValuationsSection(XNamespace sectionNamespace, CrifSettings settings)
|
||||
: base(sectionNamespace, "vehicleValuations", settings)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void AddVehicleValuation(Vehicle vehicle)
|
||||
{
|
||||
//If there's no vehicle type, it's likely a preapproval and doesn't need this element
|
||||
if (vehicle is null || vehicle.Type is null)
|
||||
return;
|
||||
|
||||
var valuationElement = new XElement(CrifNamespaces.Common + "vehicleValuation",
|
||||
new XAttribute(CrifNamespaces.Common + "id", vehicle.ValuationId),
|
||||
new XAttribute(CrifNamespaces.Common + "valuationType", "Manual"),
|
||||
new XAttribute(CrifNamespaces.Common + "make", BuilderUtils.FormatCrifData(vehicle.Make)),
|
||||
new XAttribute(CrifNamespaces.Common + "model", BuilderUtils.FormatCrifData(vehicle.Model)),
|
||||
new XAttribute(CrifNamespaces.Common + "year", vehicle.Year.Value),
|
||||
new XAttribute(CrifNamespaces.Common + "newUsed", vehicle.Condition.Value.ToString()),
|
||||
new XAttribute(CrifNamespaces.Common + "estimatedValue", vehicle.InitialEstimatedValue));
|
||||
|
||||
var valuationValueTypesElement = new XElement(CrifNamespaces.Common + "vehicleValuationValueTypes");
|
||||
valuationValueTypesElement.Add(new XElement(CrifNamespaces.Common + "vehicleValuationValueType",
|
||||
new XAttribute(CrifNamespaces.Common + "valueType", "Manual"),
|
||||
new XAttribute(CrifNamespaces.Common + "baseValue", vehicle.InitialEstimatedValue)
|
||||
));
|
||||
|
||||
valuationElement.Add(valuationValueTypesElement);
|
||||
|
||||
if (vehicle.Mileage.HasValue)
|
||||
{
|
||||
valuationElement.Add(new XAttribute(CrifNamespaces.Common + "mileage", vehicle.Mileage.Value));
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(vehicle.Color))
|
||||
{
|
||||
valuationElement.Add(new XAttribute(CrifNamespaces.Common + "color", BuilderUtils.FormatCrifData(vehicle.Color)));
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(vehicle.Body))
|
||||
{
|
||||
valuationElement.Add(new XAttribute(CrifNamespaces.Common + "body", BuilderUtils.FormatCrifData(vehicle.Body)));
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(vehicle.Series))
|
||||
{
|
||||
valuationElement.Add(new XAttribute(CrifNamespaces.Common + "series", BuilderUtils.FormatCrifData(vehicle.Series)));
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(vehicle.Style))
|
||||
{
|
||||
valuationElement.Add(new XAttribute(CrifNamespaces.Common + "style", BuilderUtils.FormatCrifData(vehicle.Style)));
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(vehicle.Trim))
|
||||
{
|
||||
valuationElement.Add(new XAttribute(CrifNamespaces.Common + "trim", BuilderUtils.FormatCrifData(vehicle.Trim)));
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(vehicle.VIN))
|
||||
{
|
||||
if (vehicle.Type != Landmark.OLA.Models.Assets.Enums.VehicleType.PWC)
|
||||
{
|
||||
valuationElement.Add(new XAttribute(CrifNamespaces.Common + "vin", BuilderUtils.FormatCrifData(vehicle.VIN)));
|
||||
}
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(vehicle.StateTitled))
|
||||
{
|
||||
valuationElement.Add(new XAttribute(CrifNamespaces.Common + "state", BuilderUtils.FormatCrifData(vehicle.StateTitled)));
|
||||
}
|
||||
|
||||
AddContent(valuationElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System.Xml.Linq;
|
||||
using CRIF.ACTion.Common;
|
||||
using CRIF.ACTion.Configuration;
|
||||
using Landmark.OLA.Models.Loan.Enums;
|
||||
|
||||
namespace CRIF.ACTion.Loan
|
||||
{
|
||||
public class CreditCardAppBuilder : ILoanApplicationRequestBuilder
|
||||
{
|
||||
private readonly CrifSettings _settings;
|
||||
|
||||
public CreditCardAppBuilder(CrifSettings settings)
|
||||
{
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public void SetDetails(LoanApplicationRequestBuilder createApp)
|
||||
{
|
||||
createApp.AppDetails = new AppDetailBankcardSection(createApp.CrifRequestSectionNamespace, _settings);
|
||||
|
||||
var additionalContent = new List<XElement>();
|
||||
|
||||
if (createApp.LoanApplication.LoanType == LoanType.CC_Secure)
|
||||
{
|
||||
var collateralId = createApp.LoanApplication.SecuredCardCollateralId;
|
||||
|
||||
//per Ben V., all Secure CC loans should have a savings account collateral equal to the CC limit
|
||||
createApp.Properties.AddProperty(new SavingsAccountProperty(collateralId, createApp.LoanApplication.RequestedAmount.Value));
|
||||
|
||||
var appDetailProperties = new XElement(CrifNamespaces.App + "appDetailProperties",
|
||||
new XElement(CrifNamespaces.App + "appDetailProperty",
|
||||
new XAttribute(CrifNamespaces.Common + "idRef", collateralId),
|
||||
new XAttribute(CrifNamespaces.Common + "propertyType", "CD"), //from CRIF example
|
||||
new XAttribute(CrifNamespaces.Common + "propertySubType", "NoneSelected"), //from CRIF example
|
||||
new XAttribute(CrifNamespaces.App + "statusID", "Active"), //from CRIF example
|
||||
new XAttribute(CrifNamespaces.App + "collateralTypeID", CrifConstants.CollateralIds[CrifConstants.Collateral.CDsOrSavings])));
|
||||
|
||||
additionalContent.Add(appDetailProperties);
|
||||
}
|
||||
|
||||
createApp.AppDetails.SetDetails(createApp.LoanApplication,
|
||||
createApp._sourceChannel, additionalContent: additionalContent.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System.Xml.Linq;
|
||||
using CRIF.ACTion.Common;
|
||||
using CRIF.ACTion.Common.Builders;
|
||||
using CRIF.ACTion.Configuration;
|
||||
|
||||
namespace CRIF.ACTion.Loan
|
||||
{
|
||||
public class DealershipRequestBuilder : BuilderBase
|
||||
{
|
||||
|
||||
public readonly string applicationId;
|
||||
|
||||
public DealershipRequestBuilder(string applicationId,
|
||||
CrifSettings settings)
|
||||
: base(CrifNamespaces.App.Namespace, settings)
|
||||
{
|
||||
this.applicationId = applicationId;
|
||||
}
|
||||
|
||||
public override XElement Build(params XElement[] content)
|
||||
{
|
||||
var createAppElement = GetAppElement(applicationId);
|
||||
|
||||
return base.Build(createAppElement);
|
||||
}
|
||||
|
||||
public static XElement GetAppElement(string applicationId)
|
||||
{
|
||||
var element = new XElement(CrifNamespaces.Empty + "getApplication");
|
||||
element.SetAttributeValue("applicationID", applicationId);
|
||||
|
||||
return element;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
using System.Xml.Linq;
|
||||
using CRIF.ACTion.Common.Parsers;
|
||||
using Landmark.OLA.Models.Loan;
|
||||
|
||||
namespace CRIF.ACTion.Loan
|
||||
{
|
||||
public class DealershipResponseParser : IResponseParser<DealershipAuthRequest>
|
||||
{
|
||||
public DealershipAuthRequest Parse(XElement xdoc)
|
||||
{
|
||||
try
|
||||
{
|
||||
var application = xdoc.Descendants(Common.CrifNamespaces.App + "application").GetEnumerator();
|
||||
application.MoveNext();
|
||||
|
||||
if(application.Current == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var applicationId = application.Current.Attribute(Common.CrifNamespaces.App + "applicationID")?.Value;
|
||||
|
||||
var primaryBorrower = xdoc.Descendants(Common.CrifNamespaces.App + "primaryBorrower").GetEnumerator();
|
||||
primaryBorrower.MoveNext();
|
||||
var primaryBorrowerRef = primaryBorrower.Current.Attribute(Common.CrifNamespaces.Common + "idRef").Value;
|
||||
|
||||
string applicantLastName = null;
|
||||
var individual = xdoc.Descendants(Common.CrifNamespaces.Common + "individual").GetEnumerator();
|
||||
while(individual.MoveNext())
|
||||
{
|
||||
if(individual.Current.Attribute(Common.CrifNamespaces.Common + "id").Value.Equals(primaryBorrowerRef))
|
||||
{
|
||||
applicantLastName = individual.Current.Attribute(Common.CrifNamespaces.Common + "lastName")?.Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (applicantLastName == null)
|
||||
{
|
||||
// Check for Company as primary applicant
|
||||
var company = xdoc.Descendants(Common.CrifNamespaces.Common + "company").GetEnumerator();
|
||||
while (company.MoveNext())
|
||||
{
|
||||
if (company.Current.Attribute(Common.CrifNamespaces.Common + "id").Value.Equals(primaryBorrowerRef))
|
||||
{
|
||||
applicantLastName = company.Current.Attribute(Common.CrifNamespaces.Common + "tradeName").Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*if (applicantLastName == null)
|
||||
{
|
||||
// Check for DBA/Trust Name as primary applicant
|
||||
var company = xdoc.Descendants(Common.CrifNamespaces.Common + "company").GetEnumerator();
|
||||
while (company.MoveNext())
|
||||
{
|
||||
if (company.Current.Attribute(Common.CrifNamespaces.Common + "id").Value.Equals(primaryBorrowerRef))
|
||||
{
|
||||
applicantLastName = company.Current.Attribute(Common.CrifNamespaces.Common + "code").Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
var channel = xdoc.Descendants(Common.CrifNamespaces.Common + "channel");
|
||||
var channelEnum = channel.GetEnumerator();
|
||||
channelEnum.MoveNext();
|
||||
var dealershipCode = channelEnum.Current.Attribute(Common.CrifNamespaces.Common + "code")?.Value;
|
||||
var dealershipName = channelEnum.Current.Attribute(Common.CrifNamespaces.Common + "dbaName")?.Value;
|
||||
var dealershipPassword = channelEnum.Current.Attribute(Common.CrifNamespaces.Common + "costCenterCode")?.Value;
|
||||
|
||||
var isActiveFlag = channelEnum.Current.Attribute(Common.CrifNamespaces.Common + "isActiveFL")?.Value;
|
||||
if(isActiveFlag == "false")
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var classificationItems = channel.Descendants(Common.CrifNamespaces.Common + "channelClassificationItem").GetEnumerator();
|
||||
while (classificationItems.MoveNext())
|
||||
{
|
||||
if(string.Equals(classificationItems.Current.Attribute(Common.CrifNamespaces.Common + "name").Value, "Dealer", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return new DealershipAuthRequest(dealershipCode, dealershipName, dealershipPassword, applicantLastName, applicationId);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new FormatException("CRIF XML is in an unexpected layout.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using CRIF.ACTion.Common;
|
||||
using CRIF.ACTion.Configuration;
|
||||
using CRIF.ACTion.Loan.Assets;
|
||||
|
||||
namespace CRIF.ACTion.Loan
|
||||
{
|
||||
public class HelocFlexAppBuilder : ILoanApplicationRequestBuilder
|
||||
{
|
||||
private readonly CrifSettings _settings;
|
||||
|
||||
public HelocFlexAppBuilder(CrifSettings settings)
|
||||
{
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public void SetDetails(LoanApplicationRequestBuilder createApp)
|
||||
{
|
||||
createApp.AppDetails = new AppDetailHelocSection(createApp.CrifRequestSectionNamespace, _settings);
|
||||
((AppDetailHelocSection)createApp.AppDetails).AddPropertyDetails(createApp.LoanApplication.RealEstate);
|
||||
((AppDetailHelocSection)createApp.AppDetails).AddHmdaDisclosed(createApp.LoanApplication.PrimaryBorrower.HmdaValues.HmdaNoticeDisclosed);
|
||||
createApp.Properties.AddProperty(new RealEstateProperty(createApp.LoanApplication.RealEstate));
|
||||
createApp.Addresses.AddAddress(createApp.LoanApplication.RealEstate.RealEstateAddress, ContactMechanisms.CrifContactMechanism.RealEstateAddress);
|
||||
|
||||
createApp.AppDetails.SetDetails(createApp.LoanApplication,
|
||||
createApp._sourceChannel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace CRIF.ACTion.Loan
|
||||
{
|
||||
public interface IAppDetails
|
||||
{
|
||||
AppDetailsSection AppDetails { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace CRIF.ACTion.Loan
|
||||
{
|
||||
public interface IAppNotes
|
||||
{
|
||||
AppNotesSectionBuilder AppNotes { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace CRIF.ACTion.Loan
|
||||
{
|
||||
public interface ILoanApplicationRequestBuilder
|
||||
{
|
||||
void SetDetails(LoanApplicationRequestBuilder createApp);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace CRIF.ACTion.Loan
|
||||
{
|
||||
public interface IOrg
|
||||
{
|
||||
OrgSection Org { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace CRIF.ACTion.Loan
|
||||
{
|
||||
public interface IProperties
|
||||
{
|
||||
PropertiesSection Properties { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using CRIF.ACTion.Common.Builders;
|
||||
|
||||
namespace CRIF.ACTion.Loan
|
||||
{
|
||||
public interface IProperty : IBuildable
|
||||
{
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
using System.Xml.Linq;
|
||||
using CRIF.ACTion.Common;
|
||||
using CRIF.ACTion.Common.Builders;
|
||||
using CRIF.ACTion.Configuration;
|
||||
using Landmark.OLA.Models.Addresses;
|
||||
using Landmark.OLA.Models.Individuals;
|
||||
|
||||
namespace CRIF.ACTion.Loan.Individuals
|
||||
{
|
||||
public class AddIndividualRequestBuilder : BuilderBase, IAppParties, IParties, IAddresses
|
||||
{
|
||||
private readonly IApplicant Individual;
|
||||
|
||||
private readonly string ApplicationId;
|
||||
|
||||
public AppPartiesSection AppParties { get; set; }
|
||||
|
||||
public PartiesSection Parties { get; set; }
|
||||
|
||||
public AddressesSection Addresses { get; set; }
|
||||
|
||||
public AddIndividualRequestBuilder(string applicationId, IApplicant individual, CrifSettings settings)
|
||||
: base(CrifNamespaces.Empty, settings)
|
||||
{
|
||||
Individual = individual;
|
||||
ApplicationId = applicationId;
|
||||
|
||||
AppParties = new AppPartiesSection(CrifRequestSectionNamespace, _settings);
|
||||
Parties = new PartiesSection(CrifRequestSectionNamespace, _settings);
|
||||
Addresses = new AddressesSection(CrifRequestSectionNamespace, _settings);
|
||||
}
|
||||
|
||||
public override XElement Build(params XElement[] content)
|
||||
{
|
||||
|
||||
Parties.AddApplicant(Individual);
|
||||
AppParties.AddIndividualParty(Individual, AppPartiesSection.PartyType.borrower, Individual.HasOptedOutTCPA);
|
||||
|
||||
Addresses.AddAddress(Individual.Address, ContactMechanisms.CrifContactMechanism.CurrentAddress);
|
||||
|
||||
if (Individual.MailingAddress is not null)
|
||||
{
|
||||
Addresses.AddAddress(Individual.MailingAddress, ContactMechanisms.CrifContactMechanism.MailingAddress);
|
||||
}
|
||||
|
||||
if (Individual.PreviousAddresses?.Count > 0)
|
||||
{
|
||||
foreach (Address previousAddress in Individual.PreviousAddresses)
|
||||
{
|
||||
Addresses.AddAddress(previousAddress, ContactMechanisms.CrifContactMechanism.PreviousAddress);
|
||||
}
|
||||
}
|
||||
|
||||
var addIndividualElement = new XElement(CrifNamespaces.Empty + "addIndividual",
|
||||
new XAttribute("applicationID", ApplicationId),
|
||||
AppParties.Build(),
|
||||
Parties.Build(),
|
||||
Addresses.Build());
|
||||
|
||||
var baseElement = base.Build(addIndividualElement);
|
||||
|
||||
return baseElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
using System.Xml.Linq;
|
||||
using System.Xml.XPath;
|
||||
using CRIF.ACTion.Common;
|
||||
using CRIF.ACTion.Common.Parsers;
|
||||
using Landmark.OLA.Models.Individuals;
|
||||
|
||||
namespace CRIF.ACTion.Loan.Individuals
|
||||
{
|
||||
public class AddIndividualResponseParser: IResponseParser<Individual>
|
||||
{
|
||||
public Individual Parse(XElement xElement)
|
||||
{
|
||||
CheckErrors(xElement);
|
||||
|
||||
return ParseIndividual(xElement);
|
||||
}
|
||||
|
||||
private static void CheckErrors(XElement xElement)
|
||||
{
|
||||
var error = xElement.XPathSelectElement("/actionAPI/addIndividual/errors/error",
|
||||
CrifNamespaces.GetNamespaceManager(xElement));
|
||||
|
||||
if (error != null)
|
||||
{
|
||||
throw new Exception(error.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public static Individual ParseIndividual(XElement xElement)
|
||||
{
|
||||
var individual = xElement.XPathSelectElement("/actionAPI/addIndividual/msg:appImportResponse/msg:applications/app:application/app:parties/common:individual",
|
||||
CrifNamespaces.GetNamespaceManager(xElement));
|
||||
|
||||
var parsedIndividual = new Individual
|
||||
{
|
||||
FirstName = individual.Attribute(CrifNamespaces.Common + "firstName").Value
|
||||
};
|
||||
|
||||
return parsedIndividual;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
using System.Xml.Linq;
|
||||
using CRIF.ACTion.Common;
|
||||
using CRIF.ACTion.Common.Builders;
|
||||
using CRIF.ACTion.Configuration;
|
||||
using Landmark.OLA.Models;
|
||||
using Landmark.OLA.Models.Addresses;
|
||||
using Landmark.OLA.Models.Residences;
|
||||
using static CRIF.ACTion.Common.ContactMechanisms;
|
||||
|
||||
namespace CRIF.ACTion.Loan.Individuals
|
||||
{
|
||||
public class AddressesSection : CrifRequestSection
|
||||
{
|
||||
public AddressesSection(XNamespace sectionNamespace, CrifSettings settings)
|
||||
: base(sectionNamespace, "addresses", settings)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void AddAddress(IAddress address, CrifContactMechanism contactMechanismType)
|
||||
{
|
||||
ModelValidator.Validate(address);
|
||||
|
||||
var isCurrentAddress = contactMechanismType == CrifContactMechanism.CurrentAddress
|
||||
? true : false;
|
||||
|
||||
var addressElement = new XElement(CrifNamespaces.Common + "address",
|
||||
new XAttribute(CrifNamespaces.Common + "id", address.Id),
|
||||
new XAttribute(CrifNamespaces.Common + "street1", BuilderUtils.FormatCrifData(address.Address1)),
|
||||
new XAttribute(CrifNamespaces.Common + "cityName", BuilderUtils.FormatCrifData(address.City)),
|
||||
new XAttribute(CrifNamespaces.Common + "state", address.State),
|
||||
new XAttribute(CrifNamespaces.Common + "postalCode", address.PostalCode),
|
||||
new XAttribute(CrifNamespaces.Common + "country", address.Country));
|
||||
|
||||
var addressType = address.GetType();
|
||||
if (addressType.Equals(typeof(ResidenceAddress)) || addressType.IsSubclassOf(typeof(ResidenceAddress)))
|
||||
{
|
||||
var residence = (ResidenceAddress)address;
|
||||
|
||||
addressElement.Add(
|
||||
new XAttribute(CrifNamespaces.Common + "isCurrentResFL", isCurrentAddress),
|
||||
new XAttribute(CrifNamespaces.Common + "monthsResided", residence.MonthsResided));
|
||||
|
||||
var typeCode = CrifResidenceType.GetCrifResidenceTypeCode(residence.ResidenceType.Value);
|
||||
|
||||
if (typeCode != null)
|
||||
{
|
||||
var residenceTypeElement = new XElement(CrifNamespaces.Common + "residenceType",
|
||||
new XAttribute(CrifNamespaces.Common + "CD", typeCode));
|
||||
|
||||
addressElement.Add(residenceTypeElement);
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(address.Address2))
|
||||
{
|
||||
addressElement.Add(new XAttribute(CrifNamespaces.Common + "street2", BuilderUtils.FormatCrifData(address.Address2)));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(address.PostalCodeExt))
|
||||
{
|
||||
addressElement.Add(new XAttribute(CrifNamespaces.Common + "zipExt", address.PostalCodeExt));
|
||||
}
|
||||
|
||||
AddContent(addressElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
using System.Xml.Linq;
|
||||
using CRIF.ACTion.Common;
|
||||
using CRIF.ACTion.Common.Builders;
|
||||
using CRIF.ACTion.Configuration;
|
||||
using Landmark.OLA.Models;
|
||||
|
||||
namespace CRIF.ACTion.Loan.Individuals
|
||||
{
|
||||
public class AppPartiesSection : CrifRequestSection
|
||||
{
|
||||
public AppPartiesSection(XNamespace sectionNamespace, CrifSettings settings)
|
||||
: base(sectionNamespace, "appParties", settings)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void AddIndividualParty(IReferenceable individual, PartyType partyType, bool hasOptedOutTCPA = false)
|
||||
{
|
||||
var borrowerTypeString = partyType == PartyType.primaryBorrower ? "primaryBorrower" : "borrower";
|
||||
|
||||
var individualParty = new XElement(CrifNamespaces.App + borrowerTypeString,
|
||||
new XAttribute(CrifNamespaces.Common + "idRef", individual.Id),
|
||||
new XAttribute(CrifNamespaces.Common + "partyType", "Individual"),
|
||||
new XAttribute(CrifNamespaces.App + "isCollateralGrantorFL", false)
|
||||
);
|
||||
|
||||
individualParty.Add(GetCustomField(partyType, hasOptedOutTCPA));
|
||||
|
||||
AddContent(individualParty);
|
||||
}
|
||||
|
||||
private XElement GetTCPACustomField()
|
||||
{
|
||||
var customField = GetBoolFieldLinkElement(CrifConstants.TCPA_Opt_Out_Field_Id,
|
||||
true, "IndividualApplicant");
|
||||
|
||||
return customField;
|
||||
}
|
||||
|
||||
private XElement GetCustomField(PartyType type, bool includeTCPAOptOut)
|
||||
{
|
||||
var fieldValue = type switch
|
||||
{
|
||||
PartyType.NonSigningSpouseMarriedToCoBorrower => CrifConstants.Borrower_IsApplicantNonSigningSpouse_Field_NonSigningMarriedToCo,
|
||||
PartyType.NonSigningSpouseMarriedToPrimary => CrifConstants.Borrower_IsApplicantNonSigningSpouse_Field_NonSigningMarriedToPrimary,
|
||||
_ => CrifConstants.Borrower_IsApplicantNonSigningSpouse_Field_Borrower,
|
||||
};
|
||||
var customField = GetLookupFieldLinkElement(CrifConstants.Borrower_IsApplicantNonSigningSpouse_Field_Id,
|
||||
fieldValue, "IndividualApplicant");
|
||||
|
||||
if (includeTCPAOptOut)
|
||||
{
|
||||
var tcpaField = GetTCPACustomField();
|
||||
var fieldsElementWithTCPA = new XElement(CrifNamespaces.App + "fields", customField, tcpaField);
|
||||
return fieldsElementWithTCPA;
|
||||
}
|
||||
|
||||
var fieldsElement = new XElement(CrifNamespaces.App + "fields", customField);
|
||||
|
||||
return fieldsElement;
|
||||
}
|
||||
|
||||
public void SetSourceChannel(Guid channelId)
|
||||
{
|
||||
var sourceChannel = new XElement(CrifNamespaces.App + "sourceChannel",
|
||||
new XAttribute(CrifNamespaces.Common + "idRef", channelId),
|
||||
new XAttribute(CrifNamespaces.Common + "partyType", "Channel"));
|
||||
|
||||
AddContent(sourceChannel);
|
||||
}
|
||||
|
||||
public void SetServicingChannel(Guid channelId)
|
||||
{
|
||||
var servicingChannel = new XElement(CrifNamespaces.App + "servicingChannel",
|
||||
new XAttribute(CrifNamespaces.Common + "idRef", channelId),
|
||||
new XAttribute(CrifNamespaces.Common + "partyType", "Channel"));
|
||||
|
||||
AddContent(servicingChannel);
|
||||
}
|
||||
|
||||
private static XElement GetLookupFieldLinkElement(int Id, int value, string fieldLevel)
|
||||
{
|
||||
var lookupFieldLinkElement = new XElement(CrifNamespaces.Common + "lookupFieldLink",
|
||||
new XAttribute(CrifNamespaces.Common + "value", value),
|
||||
new XElement(CrifNamespaces.Common + "customLookupField",
|
||||
new XAttribute(CrifNamespaces.Common + "ID", Id),
|
||||
new XAttribute(CrifNamespaces.Common + "fieldLevel", fieldLevel)));
|
||||
|
||||
return lookupFieldLinkElement;
|
||||
}
|
||||
|
||||
private static XElement GetBoolFieldLinkElement(int Id, bool value, string fieldLevel)
|
||||
{
|
||||
var lookupFieldLinkElement = new XElement(CrifNamespaces.Common + "boolFieldLink",
|
||||
new XAttribute(CrifNamespaces.Common + "value", value),
|
||||
new XElement(CrifNamespaces.Common + "customLookupField",
|
||||
new XAttribute(CrifNamespaces.Common + "ID", Id),
|
||||
new XAttribute(CrifNamespaces.Common + "fieldLevel", fieldLevel)));
|
||||
|
||||
return lookupFieldLinkElement;
|
||||
}
|
||||
|
||||
public enum PartyType
|
||||
{
|
||||
primaryBorrower,
|
||||
borrower,
|
||||
NonSigningSpouseMarriedToPrimary,
|
||||
NonSigningSpouseMarriedToCoBorrower,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using Landmark.OLA.Models.Addresses.Enums;
|
||||
|
||||
namespace CRIF.ACTion.Loan.Individuals
|
||||
{
|
||||
public static class CrifResidenceType
|
||||
{
|
||||
public static string GetCrifResidenceTypeCode(ResidenceTypeOption residenceTypeOption)
|
||||
{
|
||||
return residenceTypeOption switch
|
||||
{
|
||||
ResidenceTypeOption.Own => "N",
|
||||
ResidenceTypeOption.Rent => "R",
|
||||
ResidenceTypeOption.Other => "O",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(residenceTypeOption), "Unexpected ResidenceTypeOptions value"),
|
||||
};
|
||||
}
|
||||
|
||||
public static string GetCrifResidenceTypeName(ResidenceTypeOption residenceTypeOption)
|
||||
{
|
||||
return residenceTypeOption switch
|
||||
{
|
||||
ResidenceTypeOption.Own => "Own",
|
||||
ResidenceTypeOption.Rent => "Rent",
|
||||
ResidenceTypeOption.Other => "Other",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(residenceTypeOption), "Unexpected ResidenceTypeOptions value"),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace CRIF.ACTion.Loan.Individuals
|
||||
{
|
||||
public interface IAddresses
|
||||
{
|
||||
AddressesSection Addresses { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace CRIF.ACTion.Loan.Individuals
|
||||
{
|
||||
public interface IAppParties
|
||||
{
|
||||
AppPartiesSection AppParties { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace CRIF.ACTion.Loan.Individuals
|
||||
{
|
||||
public interface IParties
|
||||
{
|
||||
PartiesSection Parties { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Xml.Linq;
|
||||
using CRIF.ACTion.Common;
|
||||
using CRIF.ACTion.Common.Builders;
|
||||
using Landmark.OLA.Models.Individuals;
|
||||
|
||||
namespace CRIF.ACTion.Loan.Individuals
|
||||
{
|
||||
public class IncomeSectionBuilder
|
||||
{
|
||||
private readonly Income _income;
|
||||
|
||||
public IncomeSectionBuilder(Income income)
|
||||
{
|
||||
_income = income;
|
||||
}
|
||||
|
||||
public XElement Build()
|
||||
{
|
||||
var incomeElement = new XElement(CrifNamespaces.Common + "income",
|
||||
new XAttribute(CrifNamespaces.Common + "IncomeTypeCD", _income.IncomeTypeCD),
|
||||
new XAttribute(CrifNamespaces.Common + "frequency", _income.Frequency),
|
||||
new XAttribute(CrifNamespaces.Common + "amountPerPeriod", _income.AmountPerPeriod),
|
||||
new XAttribute(CrifNamespaces.Common + "incomeStatus", _income.IncomeStatus),
|
||||
new XAttribute(CrifNamespaces.Common + "incomeAdjustmentPercentage", 1m),
|
||||
new XAttribute(CrifNamespaces.Common + "adjustedIncome", _income.AmountPerPeriod),
|
||||
new XAttribute(CrifNamespaces.Common + "sourceName", BuilderUtils.FormatCrifData(_income.SourceName)));
|
||||
|
||||
if (_income.HoursPerWeek.HasValue)
|
||||
{
|
||||
incomeElement.Add(new XAttribute(CrifNamespaces.Common + "hoursPerWeek", _income.HoursPerWeek.Value));
|
||||
}
|
||||
|
||||
return incomeElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
namespace CRIF.ACTion.Loan.Individuals
|
||||
{
|
||||
public static class MaritalStatus
|
||||
{
|
||||
public static string GetMaritalStatusCode(bool isMarried)
|
||||
{
|
||||
if (isMarried)
|
||||
{
|
||||
return "M";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "U";
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetMaritalStatusName(bool isMarried)
|
||||
{
|
||||
if (isMarried)
|
||||
{
|
||||
return "Married";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Unmarried";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,788 @@
|
||||
using System.Xml.Linq;
|
||||
using CRIF.ACTion.Common;
|
||||
using CRIF.ACTion.Common.Builders;
|
||||
using CRIF.ACTion.Configuration;
|
||||
using CRIF.ACTion.Services.Landmark.DistributionChannel;
|
||||
using CRIF.ACTion.Services.Landmark.SourceChannel;
|
||||
using Landmark.OLA.Models;
|
||||
using Landmark.OLA.Models.Addresses;
|
||||
using Landmark.OLA.Models.Individuals;
|
||||
using Landmark.OLA.Models.Individuals.Enums;
|
||||
using Landmark.OLA.Models.Loan.Enums;
|
||||
using static CRIF.ACTion.Common.ContactMechanisms;
|
||||
|
||||
namespace CRIF.ACTion.Loan.Individuals
|
||||
{
|
||||
public class PartiesSection : CrifRequestSection
|
||||
{
|
||||
|
||||
private enum CrifGender
|
||||
{
|
||||
NoneSelected,
|
||||
Female,
|
||||
NotProvided,
|
||||
Male,
|
||||
NotApplicable,
|
||||
MaleFemale,
|
||||
}
|
||||
|
||||
private readonly IDistributionChannelLookupService _distributionChannelLookupService;
|
||||
|
||||
|
||||
public PartiesSection(XNamespace sectionNamespace,
|
||||
CrifSettings settings,
|
||||
IDistributionChannelLookupService distributionChannelLookupService = null)
|
||||
: base(sectionNamespace, "parties", settings)
|
||||
{
|
||||
_distributionChannelLookupService = distributionChannelLookupService ??
|
||||
new LandmarkDistributionChannelLookupService(settings);
|
||||
}
|
||||
|
||||
public void AddNonApplicant(INonApplicant individual, bool isMarried = false)
|
||||
{
|
||||
var individualElement = GetNonApplicantElement(individual, isMarried);
|
||||
|
||||
AddContent(individualElement);
|
||||
}
|
||||
|
||||
public void AddApplicant(IApplicant individual,
|
||||
Guid? externalSpouseId = null,
|
||||
PropertyLot mfgHomeLot = null)
|
||||
{
|
||||
XElement partyRelationships = null;
|
||||
|
||||
if (externalSpouseId.HasValue ||
|
||||
individual.HasAnyNonApplicantSpouse() ||
|
||||
individual.Employers?.Count > 0)
|
||||
{
|
||||
partyRelationships = GetApplicantPartyRelationshipsSectionElement(individual, externalSpouseId);
|
||||
}
|
||||
|
||||
var individualElement = GetInitialIndividualElement(individual, partyRelationships, mfgHomeLot);
|
||||
|
||||
SetHmdaData(individual, individualElement);
|
||||
|
||||
//this must occur last within the individual element
|
||||
var maritalStatusElement = GetMaritalStatusElement(individual.IsMarried ?? false);
|
||||
individualElement.Add(maritalStatusElement);
|
||||
|
||||
AddContent(individualElement);
|
||||
}
|
||||
|
||||
public void AddHistory(IIndividualHistory individual, bool isMarried = false, bool requiresHMDA = false)
|
||||
{
|
||||
XElement partyRelationships = null;
|
||||
|
||||
if (individual.Employers?.Count > 0)
|
||||
{
|
||||
partyRelationships = GetHistoryPartyRelationshipsSectionElement(individual);
|
||||
}
|
||||
|
||||
var individualElement = GetInitialIndividualElement(individual, partyRelationships);
|
||||
if (requiresHMDA)
|
||||
{
|
||||
AddNonApplicantHmdaDetermination(individualElement);
|
||||
}
|
||||
//this must occur last within the individual element
|
||||
var maritalStatusElement = GetMaritalStatusElement(isMarried);
|
||||
individualElement.Add(maritalStatusElement);
|
||||
|
||||
AddContent(individualElement);
|
||||
}
|
||||
|
||||
public static void AddNonApplicantHmdaDetermination(XElement individualElement)
|
||||
{
|
||||
var ethnicityDeterminationElement = new XElement(CrifNamespaces.Common + "ethnicityDetermination",
|
||||
new XAttribute(CrifNamespaces.Common + "lookupType", "GMIDetermination"),
|
||||
new XAttribute(CrifNamespaces.Common + "CD", "T"),
|
||||
new XAttribute(CrifNamespaces.Common + "name", "No Co-Applicant"),
|
||||
new XAttribute(CrifNamespaces.Common + "isActive", true),
|
||||
new XAttribute(CrifNamespaces.Common + "externalSystemCode", "3"));
|
||||
individualElement.Add(ethnicityDeterminationElement);
|
||||
var raceDeterminationElement = new XElement(CrifNamespaces.Common + "raceDetermination",
|
||||
new XAttribute(CrifNamespaces.Common + "lookupType", "GMIDetermination"),
|
||||
new XAttribute(CrifNamespaces.Common + "CD", "T"),
|
||||
new XAttribute(CrifNamespaces.Common + "name", "No Co-Applicant"),
|
||||
new XAttribute(CrifNamespaces.Common + "isActive", true),
|
||||
new XAttribute(CrifNamespaces.Common + "externalSystemCode", "3"));
|
||||
individualElement.Add(raceDeterminationElement);
|
||||
var sexDeterminationElement = new XElement(CrifNamespaces.Common + "sexDetermination",
|
||||
new XAttribute(CrifNamespaces.Common + "lookupType", "GMIDetermination"),
|
||||
new XAttribute(CrifNamespaces.Common + "CD", "T"),
|
||||
new XAttribute(CrifNamespaces.Common + "name", "No Co-Applicant"),
|
||||
new XAttribute(CrifNamespaces.Common + "isActive", true),
|
||||
new XAttribute(CrifNamespaces.Common + "externalSystemCode", "3"));
|
||||
individualElement.Add(sexDeterminationElement);
|
||||
var applicationTakenMethodElement = new XElement(CrifNamespaces.Common + "applicationTakenMethod",
|
||||
new XAttribute(CrifNamespaces.Common + "lookupType", "ApplicationTakenMethod"),
|
||||
new XAttribute(CrifNamespaces.Common + "CD", "2"),
|
||||
new XAttribute(CrifNamespaces.Common + "name", "Internet"),
|
||||
new XAttribute(CrifNamespaces.Common + "isActive", true),
|
||||
new XAttribute(CrifNamespaces.Common + "description", "Internet"));
|
||||
individualElement.Add(applicationTakenMethodElement);
|
||||
}
|
||||
|
||||
private XElement GetNonApplicantElement(INonApplicant individual, bool isMarried = false)
|
||||
{
|
||||
var individualElement = new XElement(CrifNamespaces.Common + "individual",
|
||||
new XAttribute(CrifNamespaces.Common + "id", individual.Id),
|
||||
new XAttribute(CrifNamespaces.Common + "languageID", individual.Language.Value),
|
||||
new XAttribute(CrifNamespaces.Common + "firstName", BuilderUtils.FormatCrifData(individual.FirstName)),
|
||||
new XAttribute(CrifNamespaces.Common + "lastName", BuilderUtils.FormatCrifData(individual.LastName)),
|
||||
new XAttribute(CrifNamespaces.Common + "ssn", individual.SSN ?? "")
|
||||
);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(individual.MiddleInitial))
|
||||
{
|
||||
individualElement.Add(new XAttribute(CrifNamespaces.Common + "middleName", BuilderUtils.FormatCrifData(individual.MiddleInitial)));
|
||||
}
|
||||
|
||||
var contact = new XElement(CrifNamespaces.Common + "contactMechanisms");
|
||||
var currentAddress = GetAddressContactMechanismElement(individual.MailingAddress.Id, CrifContactMechanism.CurrentAddress);
|
||||
|
||||
contact.Add(currentAddress);
|
||||
individualElement.Add(contact);
|
||||
|
||||
//this must occur last within the individual element
|
||||
var maritalStatusElement = GetMaritalStatusElement(isMarried);
|
||||
individualElement.Add(maritalStatusElement);
|
||||
|
||||
return individualElement;
|
||||
}
|
||||
|
||||
private XElement GetInitialIndividualElement(IIndividualHistory individual,
|
||||
XElement partyRelationshipElement = null,
|
||||
PropertyLot mfgHomeLot = null)
|
||||
{
|
||||
ModelValidator.Validate(individual);
|
||||
|
||||
var individualElement = new XElement(CrifNamespaces.Common + "individual",
|
||||
new XAttribute(CrifNamespaces.Common + "id", individual.Id),
|
||||
new XAttribute(CrifNamespaces.Common + "languageID", individual.Language.Value),
|
||||
new XAttribute(CrifNamespaces.Common + "firstName", BuilderUtils.FormatCrifData(individual.FirstName)),
|
||||
new XAttribute(CrifNamespaces.Common + "lastName", BuilderUtils.FormatCrifData(individual.LastName)),
|
||||
new XAttribute(CrifNamespaces.Common + "dob", Dates.GetFormattedDOB(individual.DOB.Value)),
|
||||
new XAttribute(CrifNamespaces.Common + "ssn", individual.SSN),
|
||||
new XAttribute(CrifNamespaces.Common + "customerNum", individual.CustomerNumber)
|
||||
);
|
||||
|
||||
if (individual.IsLandmarkEmployee.HasValue)
|
||||
{
|
||||
individualElement.Add(new XAttribute(CrifNamespaces.Common + "isEmployeeFL", individual.IsLandmarkEmployee.Value));
|
||||
}
|
||||
|
||||
var contact = GetContactMechanismsSectionElement(individual);
|
||||
individualElement.Add(contact);
|
||||
|
||||
individualElement.Add(partyRelationshipElement); //order matters for this element
|
||||
|
||||
if (individual.Employers?.Count > 0 || individual.OtherIncomes?.Count > 0)
|
||||
{
|
||||
var incomes = GetIncomesSectionElement(individual);
|
||||
individualElement.Add(incomes);;
|
||||
}
|
||||
|
||||
var tradesElement = GetTradesElement(individual, mfgHomeLot);
|
||||
individualElement.Add(tradesElement);
|
||||
|
||||
if (individual.Suffix != null)
|
||||
{
|
||||
var suffixElement = GetSuffixElement(individual);
|
||||
individualElement.Add(suffixElement);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(individual.MiddleInitial))
|
||||
{
|
||||
individualElement.Add(new XAttribute(CrifNamespaces.Common + "middleName", BuilderUtils.FormatCrifData(individual.MiddleInitial)));
|
||||
}
|
||||
|
||||
return individualElement;
|
||||
}
|
||||
|
||||
private void SetHmdaData(IApplicant individual, XElement individualElement)
|
||||
{
|
||||
var racesDetermination = false;
|
||||
if (individual.HmdaValues.Races != null && individual.HmdaValues.Races.Count > 0)
|
||||
{
|
||||
var racesElement = GetRacesElement(individual);
|
||||
individualElement.Add(racesElement);
|
||||
|
||||
racesDetermination = true;
|
||||
}
|
||||
|
||||
var ethnicitiesDetermination = false;
|
||||
if (individual.HmdaValues.Ethnicities != null && individual.HmdaValues.Ethnicities.Count > 0)
|
||||
{
|
||||
var ethnicitiesElement = GetEthnicitiesElement(individual);
|
||||
individualElement.Add(ethnicitiesElement);
|
||||
|
||||
ethnicitiesDetermination = true;
|
||||
}
|
||||
|
||||
if (ethnicitiesDetermination)
|
||||
{
|
||||
if (!(individual.HmdaValues.Ethnicities.Count == 1 && individual.HmdaValues.Ethnicities.Contains(Ethnicity.NotProvided)))
|
||||
{
|
||||
var ethnicityDeterminationElement = new XElement(CrifNamespaces.Common + "ethnicityDetermination",
|
||||
new XAttribute(CrifNamespaces.Common + "lookupType", "GMIDetermination"),
|
||||
new XAttribute(CrifNamespaces.Common + "CD", "N"),
|
||||
new XAttribute(CrifNamespaces.Common + "name", "Not Collected on the Basis of Visual Observation or Surname"),
|
||||
new XAttribute(CrifNamespaces.Common + "isActive", true),
|
||||
new XAttribute(CrifNamespaces.Common + "externalSystemCode", "3"));
|
||||
individualElement.Add(ethnicityDeterminationElement);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (racesDetermination)
|
||||
{
|
||||
if (!(individual.HmdaValues.Races.Count == 1 && individual.HmdaValues.Races.Contains(Race.NotProvided)))
|
||||
{
|
||||
var raceDeterminationElement = new XElement(CrifNamespaces.Common + "raceDetermination",
|
||||
new XAttribute(CrifNamespaces.Common + "lookupType", "GMIDetermination"),
|
||||
new XAttribute(CrifNamespaces.Common + "CD", "N"),
|
||||
new XAttribute(CrifNamespaces.Common + "name", "Not Collected on the Basis of Visual Observation or Surname"),
|
||||
new XAttribute(CrifNamespaces.Common + "isActive", true),
|
||||
new XAttribute(CrifNamespaces.Common + "externalSystemCode", "3"));
|
||||
individualElement.Add(raceDeterminationElement);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (individual.HmdaValues.Sexes != null && individual.HmdaValues.Sexes.Count > 0)
|
||||
{
|
||||
var sexElements = GetSexAttributes(individual);
|
||||
individualElement.Add(sexElements);
|
||||
|
||||
if (!(individual.HmdaValues.Sexes.Count == 1 && individual.HmdaValues.Sexes.Contains(Sex.NotProvided)))
|
||||
{
|
||||
var sexDeterminationElement = new XElement(CrifNamespaces.Common + "sexDetermination",
|
||||
new XAttribute(CrifNamespaces.Common + "lookupType", "GMIDetermination"),
|
||||
new XAttribute(CrifNamespaces.Common + "CD", "N"),
|
||||
new XAttribute(CrifNamespaces.Common + "name", "Not Collected on the Basis of Visual Observation or Surname"),
|
||||
new XAttribute(CrifNamespaces.Common + "isActive", true),
|
||||
new XAttribute(CrifNamespaces.Common + "externalSystemCode", "3"));
|
||||
individualElement.Add(sexDeterminationElement);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
var applicationTakenMethodElement = GetApplicationTakenMethodElement(individual);
|
||||
individualElement.Add(applicationTakenMethodElement);
|
||||
}
|
||||
|
||||
public XElement GetApplicationTakenMethodElement(IApplicant individual)
|
||||
{
|
||||
if (!GetApplicationTakenMethodElementRequired(individual))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var applicationTakenMethodElement = new XElement(CrifNamespaces.Common + "applicationTakenMethod",
|
||||
new XAttribute(CrifNamespaces.Common + "lookupType", "ApplicationTakenMethod"),
|
||||
new XAttribute(CrifNamespaces.Common + "CD", "2"),
|
||||
new XAttribute(CrifNamespaces.Common + "name", "Internet"),
|
||||
new XAttribute(CrifNamespaces.Common + "isActive", true),
|
||||
new XAttribute(CrifNamespaces.Common + "description", "Internet"));
|
||||
|
||||
return applicationTakenMethodElement;
|
||||
}
|
||||
|
||||
public static XElement GetSuffixElement(IIndividualHistory individual)
|
||||
{
|
||||
var suffixType = SuffixMap.GetSuffixType(individual.Suffix);
|
||||
|
||||
var suffixElement = new XElement(CrifNamespaces.Common + "suffix",
|
||||
new XAttribute(CrifNamespaces.Common + "lookupType", "Suffix"),
|
||||
new XAttribute(CrifNamespaces.Common + "CD", suffixType.CD),
|
||||
new XAttribute(CrifNamespaces.Common + "name", suffixType.Name),
|
||||
new XAttribute(CrifNamespaces.Common + "isActive", true));
|
||||
|
||||
return suffixElement;
|
||||
|
||||
}
|
||||
|
||||
public static XElement GetTradesElement(IIndividualHistory individual, PropertyLot mfgHomeLot)
|
||||
{
|
||||
var tradesElement = new XElement(CrifNamespaces.Common + "trades");
|
||||
|
||||
var mortgageOrRentTradeElement = new XElement(CrifNamespaces.Common + "trade",
|
||||
new XAttribute(CrifNamespaces.Common + "accountTypeCD", "RealEstateMortgage"),
|
||||
new XAttribute(CrifNamespaces.Common + "tradeTypeID", "Mortgage"),
|
||||
new XAttribute(CrifNamespaces.Common + "creditorName", "Rent - Mortgage"),
|
||||
new XAttribute(CrifNamespaces.Common + "debtStatusCD", "Include"),
|
||||
new XAttribute(CrifNamespaces.Common + "ecoaCD", "Individual"),
|
||||
new XAttribute(CrifNamespaces.Common + "isCurrResidenceRentMortgage", true),
|
||||
new XAttribute(CrifNamespaces.Common + "monthlyPayment", individual.Address.MonthlyPayment),
|
||||
|
||||
new XElement(CrifNamespaces.Common + "kindOfBusiness",
|
||||
new XAttribute(CrifNamespaces.Common + "lookupType", "KOB"),
|
||||
new XAttribute(CrifNamespaces.Common + "CD", "FM")));
|
||||
|
||||
tradesElement.Add(mortgageOrRentTradeElement);
|
||||
|
||||
if ((!(mfgHomeLot is null)) && mfgHomeLot.RentalAmt.HasValue)
|
||||
{
|
||||
var mfgHomeLotRentalElement = new XElement(CrifNamespaces.Common + "trade",
|
||||
new XAttribute(CrifNamespaces.Common + "tradeTypeID", "Mortgage"),
|
||||
new XAttribute(CrifNamespaces.Common + "creditorName", "Lot Rent"),
|
||||
new XAttribute(CrifNamespaces.Common + "debtStatusCD", "Include"),
|
||||
new XAttribute(CrifNamespaces.Common + "ecoaCD", "Individual"),
|
||||
new XAttribute(CrifNamespaces.Common + "monthlyPayment", mfgHomeLot.RentalAmt.Value),
|
||||
|
||||
new XElement(CrifNamespaces.Common + "kindOfBusiness",
|
||||
new XAttribute(CrifNamespaces.Common + "lookupType", "KOB"),
|
||||
new XAttribute(CrifNamespaces.Common + "CD", "FM")));
|
||||
|
||||
tradesElement.Add(mfgHomeLotRentalElement);
|
||||
}
|
||||
|
||||
if (individual.OtherIncomes?.Count > 0)
|
||||
{
|
||||
foreach (var income in individual.OtherIncomes)
|
||||
{
|
||||
if (income.IncomeTypeCD == IncomeType.Alimony)
|
||||
{
|
||||
double monthlyAlimony = (double)income.AmountPerPeriod / 12;
|
||||
var alimonyElement = new XElement(CrifNamespaces.Common + "trade",
|
||||
new XAttribute(CrifNamespaces.Common + "tradeTypeID", "Open"),
|
||||
new XAttribute(CrifNamespaces.Common + "creditorName", "Alimony/Child Support - Payment"),
|
||||
new XAttribute(CrifNamespaces.Common + "debtStatusCD", "Include"),
|
||||
new XAttribute(CrifNamespaces.Common + "ecoaCD", "Individual"),
|
||||
new XAttribute(CrifNamespaces.Common + "monthlyPayment", monthlyAlimony),
|
||||
new XElement(CrifNamespaces.Common + "kindOfBusiness",
|
||||
new XAttribute(CrifNamespaces.Common + "lookupType", "KOB"),
|
||||
new XAttribute(CrifNamespaces.Common + "CD", "VK")));
|
||||
tradesElement.Add(alimonyElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return tradesElement;
|
||||
}
|
||||
|
||||
private static bool GetApplicationTakenMethodElementRequired(IApplicant individual)
|
||||
{
|
||||
var hasRaces = individual.HmdaValues.Races != null && individual.HmdaValues.Races.Count > 0;
|
||||
var hasEthnicities = individual.HmdaValues.Ethnicities != null && individual.HmdaValues.Ethnicities.Count > 0;
|
||||
var hasSexes = individual.HmdaValues.Sexes != null && individual.HmdaValues.Sexes.Count > 0;
|
||||
|
||||
return hasRaces || hasEthnicities || hasSexes;
|
||||
}
|
||||
|
||||
public static XAttribute[] GetSexAttributes(IApplicant individual)
|
||||
{
|
||||
var attributeList = new List<XAttribute>();
|
||||
|
||||
var hasMale = individual.HmdaValues.Sexes.Contains(Sex.Male);
|
||||
var hasFemale = individual.HmdaValues.Sexes.Contains(Sex.Female);
|
||||
var isNotProvided = individual.HmdaValues.Sexes.Contains(Sex.NotProvided);
|
||||
|
||||
var genderCDValue = CrifGender.NoneSelected;
|
||||
|
||||
if (isNotProvided && !hasMale && !hasFemale)
|
||||
{
|
||||
attributeList.Add(new XAttribute(CrifNamespaces.Common + "genderCD", Sex.NotProvided));
|
||||
return [.. attributeList];
|
||||
}
|
||||
|
||||
if (hasMale)
|
||||
{
|
||||
if (hasFemale)
|
||||
{
|
||||
genderCDValue = CrifGender.MaleFemale;
|
||||
}
|
||||
else
|
||||
{
|
||||
genderCDValue = CrifGender.Male;
|
||||
}
|
||||
}
|
||||
else if (hasFemale)
|
||||
{
|
||||
genderCDValue = CrifGender.Female;
|
||||
}
|
||||
|
||||
if (genderCDValue != CrifGender.NoneSelected)
|
||||
{
|
||||
attributeList.Add(new XAttribute(CrifNamespaces.Common + "genderCD", genderCDValue.ToString()));
|
||||
}
|
||||
|
||||
//Yes, you both could provide an answer and say that you don't wish to provide an answer
|
||||
//Validation will likely restrict that
|
||||
//Ignore Not Provided if Other Values are Selected
|
||||
attributeList.Add(new XAttribute(CrifNamespaces.Common + "refusedToFurnishGenderFL", false));
|
||||
return [.. attributeList];
|
||||
}
|
||||
|
||||
public static XElement GetRacesElement(IApplicant individual)
|
||||
{
|
||||
var racesElement = new XElement(CrifNamespaces.Common + "races");
|
||||
|
||||
if (individual.HmdaValues.Races.Count == 1 && individual.HmdaValues.Races.Contains(Race.NotProvided)){
|
||||
var raceElement = new XElement(CrifNamespaces.Common + "race",
|
||||
new XAttribute(CrifNamespaces.Common + "isCheckedFL", true),
|
||||
new XAttribute(CrifNamespaces.Common + "race", Race.NotProvided.ToString()));
|
||||
|
||||
racesElement.RemoveNodes();
|
||||
racesElement.Add(raceElement);
|
||||
return racesElement;
|
||||
}
|
||||
|
||||
foreach (Race raceOption in (Race[])Enum.GetValues(typeof(Race)))
|
||||
{
|
||||
var isChecked = individual.HmdaValues.Races.Contains(raceOption);
|
||||
|
||||
bool isNotProvided = (raceOption == Race.NotProvided);
|
||||
|
||||
string otherRaceInfoValue = null;
|
||||
switch (raceOption)
|
||||
{
|
||||
case Race.AmericanIndianAlaskaNative:
|
||||
otherRaceInfoValue = individual.HmdaValues.AmericanIndianAlaskaNativeTribe;
|
||||
break;
|
||||
case Race.OtherAsian:
|
||||
otherRaceInfoValue = individual.HmdaValues.OtherAsianRace;
|
||||
break;
|
||||
case Race.OtherPacificIslander:
|
||||
otherRaceInfoValue = individual.HmdaValues.OtherPacificIslanderRace;
|
||||
break;
|
||||
}
|
||||
var hasOtherValue = !string.IsNullOrWhiteSpace(otherRaceInfoValue);
|
||||
|
||||
//Ignore not provided if it is not the only ethnicity selected
|
||||
if ( (isChecked || hasOtherValue) && !isNotProvided)
|
||||
{
|
||||
|
||||
var raceElement = new XElement(CrifNamespaces.Common + "race",
|
||||
new XAttribute(CrifNamespaces.Common + "isCheckedFL", isChecked),
|
||||
new XAttribute(CrifNamespaces.Common + "race", raceOption.ToString()));
|
||||
|
||||
if (hasOtherValue)
|
||||
{
|
||||
raceElement.Add(new XAttribute(CrifNamespaces.Common + "otherRaceInfo", BuilderUtils.FormatCrifData(otherRaceInfoValue)));
|
||||
}
|
||||
|
||||
racesElement.Add(raceElement);
|
||||
}
|
||||
}
|
||||
|
||||
return racesElement;
|
||||
}
|
||||
|
||||
public static XElement GetEthnicitiesElement(IApplicant individual)
|
||||
{
|
||||
var ethnicitiesElement = new XElement(CrifNamespaces.Common + "ethnicities");
|
||||
|
||||
if (individual.HmdaValues.Ethnicities.Count == 1 && individual.HmdaValues.Ethnicities.Contains(Ethnicity.NotProvided)){
|
||||
var ethnicityElement = new XElement(CrifNamespaces.Common + "ethnicity",
|
||||
new XAttribute(CrifNamespaces.Common + "isCheckedFL", true),
|
||||
new XAttribute(CrifNamespaces.Common + "ethnicity", Ethnicity.NotProvided.ToString()));
|
||||
|
||||
ethnicitiesElement.RemoveNodes();
|
||||
ethnicitiesElement.Add(ethnicityElement);
|
||||
return ethnicitiesElement;
|
||||
}
|
||||
|
||||
foreach (Ethnicity ethnicityOption in (Ethnicity[])Enum.GetValues(typeof(Ethnicity)))
|
||||
{
|
||||
var isChecked = individual.HmdaValues.Ethnicities.Contains(ethnicityOption);
|
||||
|
||||
bool isNotProvided = (ethnicityOption == Ethnicity.NotProvided);
|
||||
|
||||
string otherEthnicityInfo = null;
|
||||
switch (ethnicityOption)
|
||||
{
|
||||
case Ethnicity.OtherHispanicLatino:
|
||||
otherEthnicityInfo = individual.HmdaValues.OtherHispanicLatinoEthnicity;
|
||||
break;
|
||||
}
|
||||
var hasOtherValue = !string.IsNullOrWhiteSpace(otherEthnicityInfo);
|
||||
|
||||
//Ignore not provided if it is not the only ethnicity selected
|
||||
if ( (isChecked || hasOtherValue) && !isNotProvided)
|
||||
{
|
||||
var ethnicityElement = new XElement(CrifNamespaces.Common + "ethnicity",
|
||||
new XAttribute(CrifNamespaces.Common + "isCheckedFL", isChecked),
|
||||
new XAttribute(CrifNamespaces.Common + "ethnicity", ethnicityOption.ToString()));
|
||||
|
||||
if (hasOtherValue)
|
||||
{
|
||||
ethnicityElement.Add(new XAttribute(CrifNamespaces.Common + "otherEthnicityInfo", BuilderUtils.FormatCrifData(otherEthnicityInfo)));
|
||||
}
|
||||
|
||||
ethnicitiesElement.Add(ethnicityElement);
|
||||
}
|
||||
}
|
||||
|
||||
return ethnicitiesElement;
|
||||
}
|
||||
|
||||
public static XElement GetIncomesSectionElement(IIndividualHistory individual)
|
||||
{
|
||||
var incomesElement = new XElement(CrifNamespaces.Common + "incomes");
|
||||
if (individual.Employers?.Count > 0)
|
||||
{
|
||||
foreach (var employer in individual.Employers)
|
||||
{
|
||||
var income = employer.Income;
|
||||
|
||||
ModelValidator.Validate(income);
|
||||
|
||||
var incomeElement = new IncomeSectionBuilder(income).Build();
|
||||
|
||||
var employerRefElement = new XElement(CrifNamespaces.Common + "employerRef",
|
||||
new XAttribute(CrifNamespaces.Common + "idRef", employer.GetOrCreateGuid()));
|
||||
incomeElement.Add(employerRefElement);
|
||||
incomesElement.Add(incomeElement);
|
||||
}
|
||||
}
|
||||
if (individual.OtherIncomes?.Count > 0)
|
||||
{
|
||||
foreach (var income in individual.OtherIncomes)
|
||||
{
|
||||
if (income.IncomeTypeCD != IncomeType.Alimony)
|
||||
{
|
||||
var incomeElement = new IncomeSectionBuilder(income).Build();
|
||||
incomesElement.Add(incomeElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
return incomesElement;
|
||||
}
|
||||
|
||||
public static XElement GetHistoryPartyRelationshipsSectionElement(IIndividualHistory individual)
|
||||
{
|
||||
var prElement = new XElement(CrifNamespaces.Common + "partyRelationships");
|
||||
if (individual.Employers?.Count > 0)
|
||||
{
|
||||
foreach (var employer in individual.Employers)
|
||||
{
|
||||
ModelValidator.Validate(employer);
|
||||
|
||||
var employmentType = employer.EmploymentType;
|
||||
|
||||
var employmentElement = new XElement(CrifNamespaces.Common + "employment",
|
||||
new XAttribute(CrifNamespaces.Common + "relationshipType", "Employment"));
|
||||
var partyRefElement = new XElement(CrifNamespaces.Common + "partyRef",
|
||||
new XAttribute(CrifNamespaces.XSI + "type", $"{CrifNamespaces.Common.Prefix}:EmployerRef"),
|
||||
new XAttribute(CrifNamespaces.Common + "idRef", employer.GetOrCreateGuid()),
|
||||
new XAttribute(CrifNamespaces.Common + "partyType", "Employer"));
|
||||
var employmentSubRelElement = new XElement(CrifNamespaces.Common + "employmentSubRel",
|
||||
new XAttribute(CrifNamespaces.Common + "isCurrentFL", employer.CurrentEmployer),
|
||||
new XAttribute(CrifNamespaces.Common + "title", BuilderUtils.FormatCrifData(employer.Title)),
|
||||
new XAttribute(CrifNamespaces.Common + "monthsEmployed", employer.MonthsEmployed),
|
||||
new XAttribute(CrifNamespaces.Common + "isSelfEmployed", false), //TODO #239: is this always false?
|
||||
new XAttribute(CrifNamespaces.Common + "employmentType", employmentType));
|
||||
var userEmploymentTypeElement = new XElement(CrifNamespaces.Common + "userEmploymentType",
|
||||
new XAttribute(CrifNamespaces.Common + "lookupType", "UserEmploymentType"), //TODO #240: Does this have other values?
|
||||
new XAttribute(CrifNamespaces.Common + "CD", UserEmploymentType.GetCrifUserEmploymentTypeIndex(employmentType)), //TODO #240
|
||||
new XAttribute(CrifNamespaces.Common + "name", UserEmploymentType.GetCrifUserEmploymentTypeName(employmentType)));
|
||||
|
||||
employmentSubRelElement.Add(userEmploymentTypeElement);
|
||||
employmentElement.Add(partyRefElement);
|
||||
employmentElement.Add(employmentSubRelElement);
|
||||
prElement.Add(employmentElement);
|
||||
}
|
||||
}
|
||||
|
||||
return prElement;
|
||||
}
|
||||
|
||||
public static XElement GetApplicantPartyRelationshipsSectionElement(IApplicant individual,
|
||||
Guid? externalSpouseId = null)
|
||||
{
|
||||
var prElement = GetHistoryPartyRelationshipsSectionElement(individual);
|
||||
|
||||
prElement.Add(GetMarriageElement(individual, externalSpouseId));
|
||||
|
||||
return prElement;
|
||||
}
|
||||
|
||||
private static XElement GetMarriageElement(IApplicant individual, Guid? externalSpouseId = null)
|
||||
{
|
||||
if (!(individual.HasAnyNonApplicantSpouse() || externalSpouseId.HasValue))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Guid spouseId;
|
||||
|
||||
if (externalSpouseId.HasValue)
|
||||
{
|
||||
spouseId = externalSpouseId.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (individual.NonApplicantSpouse is not null)
|
||||
{
|
||||
spouseId = individual.NonApplicantSpouse.Id;
|
||||
}
|
||||
else
|
||||
{
|
||||
spouseId = individual.DetailedNonApplicantSpouse.Id;
|
||||
}
|
||||
}
|
||||
|
||||
var partyRef = new XElement(CrifNamespaces.Common + "partyRef",
|
||||
new XAttribute(CrifNamespaces.XSI + "type", $"{CrifNamespaces.Common.Prefix}:IndividualRef"),
|
||||
new XAttribute(CrifNamespaces.Common + "idRef", spouseId),
|
||||
new XAttribute(CrifNamespaces.Common + "partyType", "Individual"));
|
||||
|
||||
var marriageRelationshipElement = new XElement(CrifNamespaces.Common + "partyRelationship",
|
||||
new XAttribute(CrifNamespaces.Common + "relationshipType", "Marriage"),
|
||||
partyRef);
|
||||
|
||||
return marriageRelationshipElement;
|
||||
}
|
||||
|
||||
public static XElement GetMaritalStatusElement(bool isMarried)
|
||||
{
|
||||
var maritalStatusElement = new XElement(CrifNamespaces.Common + "maritalStatus",
|
||||
new XAttribute(CrifNamespaces.Common + "lookupType", "MaritalStatus"),
|
||||
new XAttribute(CrifNamespaces.Common + "CD", MaritalStatus.GetMaritalStatusCode(isMarried)),
|
||||
new XAttribute(CrifNamespaces.Common + "name", MaritalStatus.GetMaritalStatusName(isMarried)));
|
||||
|
||||
return maritalStatusElement;
|
||||
}
|
||||
|
||||
public static XElement GetContactMechanismsSectionElement(IIndividualHistory individual)
|
||||
{
|
||||
var contact = new XElement(CrifNamespaces.Common + "contactMechanisms");
|
||||
|
||||
var mechanismType = ContactMechanisms.GetPhoneType(individual.PhoneType.Value);
|
||||
var primaryPhone = GetContactMechanismElement(individual.Phone, mechanismType);
|
||||
|
||||
var email = GetContactMechanismElement(individual.Email, ContactMechanisms.CrifContactMechanism.EMail);
|
||||
|
||||
var currentAddress = GetAddressContactMechanismElement(individual.Address.Id, ContactMechanisms.CrifContactMechanism.CurrentAddress);
|
||||
|
||||
contact.Add(primaryPhone);
|
||||
contact.Add(email);
|
||||
contact.Add(currentAddress);
|
||||
|
||||
if (individual.SecondaryPhone?.Length > 0)
|
||||
{
|
||||
mechanismType = ContactMechanisms.GetPhoneType(individual.SecondaryPhoneType.Value);
|
||||
var secondaryPhone = GetContactMechanismElement(individual.SecondaryPhone, mechanismType);
|
||||
|
||||
contact.Add(secondaryPhone);
|
||||
}
|
||||
|
||||
if (individual.MailingAddress is not null)
|
||||
{
|
||||
var mailingAddressElement = GetAddressContactMechanismElement(individual.MailingAddress.Id, ContactMechanisms.CrifContactMechanism.MailingAddress);
|
||||
contact.Add(mailingAddressElement);
|
||||
}
|
||||
else
|
||||
{
|
||||
var mailingAddressElement = GetAddressContactMechanismElement(individual.Address.Id,ContactMechanisms.CrifContactMechanism.MailingAddress);
|
||||
contact.Add(mailingAddressElement);
|
||||
}
|
||||
|
||||
if (individual.PreviousAddresses?.Count > 0)
|
||||
{
|
||||
foreach (var previousAddress in individual.PreviousAddresses)
|
||||
{
|
||||
var previousAddressElement = GetAddressContactMechanismElement(previousAddress.Id, ContactMechanisms.CrifContactMechanism.PreviousAddress);
|
||||
contact.Add(previousAddressElement);
|
||||
}
|
||||
}
|
||||
|
||||
return contact;
|
||||
}
|
||||
|
||||
public static XElement GetAddressContactMechanismElement(Guid addressRef, ContactMechanisms.CrifContactMechanism contactMechanismType)
|
||||
{
|
||||
var contactMechanismCategory = ContactMechanisms.GetContactMechanismCategory(contactMechanismType);
|
||||
|
||||
var contactMechanism = new XElement(CrifNamespaces.Common + "contactMechanism",
|
||||
new XAttribute(CrifNamespaces.Common + "contactMechanismType", contactMechanismType),
|
||||
new XElement(CrifNamespaces.Common + "addressRef",
|
||||
new XAttribute(CrifNamespaces.Common + "idRef", addressRef)
|
||||
),
|
||||
new XElement(CrifNamespaces.Common + "contactMechanismCategory",
|
||||
new XAttribute(CrifNamespaces.Common + "CD", (int)contactMechanismCategory)
|
||||
)
|
||||
);
|
||||
|
||||
return contactMechanism;
|
||||
}
|
||||
|
||||
public static XElement GetEmployerContactMechanismsSectionElement(Employer employer)
|
||||
{
|
||||
var contact = new XElement(CrifNamespaces.Common + "contactMechanisms");
|
||||
if (!string.IsNullOrWhiteSpace(employer.WorkPhone))
|
||||
{
|
||||
contact.Add(GetContactMechanismElement(employer.WorkPhone, CrifContactMechanism.WorkPhone));
|
||||
}
|
||||
return contact;
|
||||
}
|
||||
|
||||
public static XElement GetContactMechanismElement(string contactString, CrifContactMechanism contactMechanismType)
|
||||
{
|
||||
var contactMechanismCategory = GetContactMechanismCategory(contactMechanismType);
|
||||
|
||||
var contactMechanism = new XElement(CrifNamespaces.Common + "contactMechanism",
|
||||
new XAttribute(CrifNamespaces.Common + "contactMechanismType", contactMechanismType),
|
||||
new XAttribute(CrifNamespaces.Common + "contactString", BuilderUtils.FormatCrifData(contactString)),
|
||||
new XElement(CrifNamespaces.Common + "contactMechanismCategory",
|
||||
new XAttribute(CrifNamespaces.Common + "CD", (int)contactMechanismCategory)
|
||||
)
|
||||
);
|
||||
|
||||
return contactMechanism;
|
||||
}
|
||||
|
||||
public void AddOrganizationParty(Guid orgId)
|
||||
{
|
||||
var organization = new XElement(CrifNamespaces.Common + "organization",
|
||||
new XAttribute(CrifNamespaces.Common + "id", orgId),
|
||||
new XAttribute(CrifNamespaces.Common + "partyID", 4)); //Per CRIF Documentation
|
||||
|
||||
AddContent(organization);
|
||||
}
|
||||
|
||||
public void AddSourceChannelParty(Guid channelId, LoanType loanType)
|
||||
{
|
||||
var channelLookup = new LandmarkSourceChannelLookupService(_settings);
|
||||
|
||||
int partyId = channelLookup.GetSourceChannelByLoanType(loanType);
|
||||
|
||||
AddChannelParty(channelId, partyId);
|
||||
}
|
||||
|
||||
public void AddServicingChannelParty(Guid channelId, string zipCode)
|
||||
{
|
||||
var partyId = _distributionChannelLookupService.GetDistributionChannelByZipCode(zipCode);
|
||||
|
||||
AddChannelParty(channelId, partyId);
|
||||
}
|
||||
|
||||
private void AddChannelParty(Guid channelId, int partyId)
|
||||
{
|
||||
var channel = new XElement(CrifNamespaces.Common + "channel",
|
||||
new XAttribute(CrifNamespaces.Common + "id", channelId),
|
||||
new XAttribute(CrifNamespaces.Common + "partyID", partyId));
|
||||
|
||||
AddContent(channel);
|
||||
}
|
||||
|
||||
public void AddEmployer(Employer employer)
|
||||
{
|
||||
ModelValidator.Validate(employer);
|
||||
|
||||
var employerElement = new XElement(CrifNamespaces.Common + "employer",
|
||||
new XAttribute(CrifNamespaces.Common + "id", employer.GetOrCreateGuid()),
|
||||
new XAttribute(CrifNamespaces.Common + "name", BuilderUtils.FormatCrifData(employer.Name)),
|
||||
new XAttribute(CrifNamespaces.Common + "languageID", employer.Language));
|
||||
|
||||
var contact = GetEmployerContactMechanismsSectionElement(employer);
|
||||
|
||||
employerElement.Add(contact);
|
||||
AddContent(employerElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using Landmark.OLA.Models.Individuals.Enums;
|
||||
|
||||
namespace CRIF.ACTion.Loan.Individuals
|
||||
{
|
||||
public static class UserEmploymentType
|
||||
{
|
||||
|
||||
public static string GetCrifUserEmploymentTypeIndex(EmploymentTypeOption userEmploymentTypeOption)
|
||||
{
|
||||
return userEmploymentTypeOption switch
|
||||
{
|
||||
EmploymentTypeOption.NoneSelected => "0",
|
||||
EmploymentTypeOption.Contract => "1",
|
||||
EmploymentTypeOption.FullTime => "2",
|
||||
EmploymentTypeOption.PartTime => "3",
|
||||
EmploymentTypeOption.SelfEmployed => "4",
|
||||
EmploymentTypeOption.Retired => "5",
|
||||
EmploymentTypeOption.Temporary => "6",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(userEmploymentTypeOption), "Unexpected UserEmploymentType value"),
|
||||
};
|
||||
}
|
||||
|
||||
public static string GetCrifUserEmploymentTypeName(EmploymentTypeOption userEmploymentTypeOption)
|
||||
{
|
||||
return userEmploymentTypeOption switch
|
||||
{
|
||||
EmploymentTypeOption.NoneSelected => "None Selected",
|
||||
EmploymentTypeOption.Contract => "Contract",
|
||||
EmploymentTypeOption.FullTime => "Full Time",
|
||||
EmploymentTypeOption.PartTime => "Part Time",
|
||||
EmploymentTypeOption.SelfEmployed => "Self Employed",
|
||||
EmploymentTypeOption.Retired => "Retired",
|
||||
EmploymentTypeOption.Temporary => "Temporary",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(userEmploymentTypeOption), "Unexpected UserEmploymentType value"),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,384 @@
|
||||
using System.Xml.Linq;
|
||||
using CRIF.ACTion.Common;
|
||||
using CRIF.ACTion.Common.Builders;
|
||||
using CRIF.ACTion.Configuration;
|
||||
using CRIF.ACTion.Services.Landmark.DistributionChannel;
|
||||
using CRIF.ACTion.Loan.Assets;
|
||||
using CRIF.ACTion.Loan.Individuals;
|
||||
using Landmark.OLA.Models.Addresses;
|
||||
using Landmark.OLA.Models.Individuals;
|
||||
using Landmark.OLA.Models.Loan;
|
||||
using Landmark.OLA.Models.Loan.Enums;
|
||||
|
||||
namespace CRIF.ACTion.Loan
|
||||
{
|
||||
public class LoanApplicationRequestBuilder : BuilderBase, IParties, IAppDetails, IAppParties,
|
||||
IAddresses, IOrg, IProperties, IVehicleValuations, IAppNotes
|
||||
{
|
||||
public readonly LoanApplication LoanApplication;
|
||||
private readonly Guid OrgRef;
|
||||
public readonly Guid _sourceChannel;
|
||||
public readonly Guid _servicingChannel;
|
||||
|
||||
public AppPartiesSection AppParties { get; set; }
|
||||
|
||||
public PartiesSection Parties { get; set; }
|
||||
|
||||
public AppDetailsSection AppDetails { get; set; }
|
||||
|
||||
public AddressesSection Addresses { get; set; }
|
||||
|
||||
public AppNotesSectionBuilder AppNotes { get; set; }
|
||||
|
||||
public OrgSection Org { get; set; }
|
||||
|
||||
public PropertiesSection Properties { get; set; }
|
||||
|
||||
public VehicleValuationsSection VehicleValuations { get; set; }
|
||||
|
||||
public LoanApplicationRequestBuilder(LoanApplication loanApplication,
|
||||
CrifSettings settings,
|
||||
Guid? orgRef = null,
|
||||
Guid? sourceChannel = null,
|
||||
Guid? servicingChannel = null,
|
||||
IDistributionChannelLookupService distributionChannelLookupService = null)
|
||||
: base(CrifNamespaces.App.Namespace, settings)
|
||||
{
|
||||
LoanApplication = loanApplication;
|
||||
|
||||
OrgRef = orgRef ?? Guid.NewGuid();
|
||||
_sourceChannel = sourceChannel ?? Guid.NewGuid();
|
||||
_servicingChannel = servicingChannel ?? Guid.NewGuid();
|
||||
|
||||
AppParties = new AppPartiesSection(CrifRequestSectionNamespace, settings);
|
||||
Parties = new PartiesSection(CrifRequestSectionNamespace, settings, distributionChannelLookupService);
|
||||
Addresses = new AddressesSection(CrifRequestSectionNamespace, settings);
|
||||
AppNotes = new AppNotesSectionBuilder(CrifRequestSectionNamespace, settings);
|
||||
Org = new OrgSection(CrifRequestSectionNamespace, settings);
|
||||
Properties = new PropertiesSection(CrifRequestSectionNamespace, settings);
|
||||
VehicleValuations = new VehicleValuationsSection(CrifRequestSectionNamespace, settings);
|
||||
}
|
||||
|
||||
public override XElement Build(params XElement[] content)
|
||||
{
|
||||
Org.SetOrgId(OrgRef);
|
||||
|
||||
Parties.AddOrganizationParty(OrgRef);
|
||||
|
||||
Parties.AddSourceChannelParty(_sourceChannel, LoanApplication.LoanType.Value);
|
||||
|
||||
Parties.AddServicingChannelParty(_servicingChannel, LoanApplication?.PrimaryBorrower?.Address?.PostalCode ?? "");
|
||||
|
||||
AppParties.SetSourceChannel(_sourceChannel);
|
||||
|
||||
AppParties.SetServicingChannel(_servicingChannel);
|
||||
|
||||
AddApplicationNotes();
|
||||
|
||||
var productDetails = CreateProductDetails(LoanApplication.LoanType, _settings);
|
||||
productDetails.SetDetails(this);
|
||||
|
||||
Guid? externalSpouseId = null;
|
||||
if (LoanApplication.CoApplicant is not null && LoanApplication.CoApplicant.IsMarriedToPrimaryBorrower)
|
||||
{
|
||||
externalSpouseId = LoanApplication.CoApplicant.Id;
|
||||
}
|
||||
|
||||
|
||||
PropertyLot mfgHomeLot = null;
|
||||
|
||||
if (!(LoanApplication.ManufacturedHome?.Lot?.RentalAmt is null))
|
||||
{
|
||||
//needed to pass long possible Lot rent amount
|
||||
mfgHomeLot = LoanApplication.ManufacturedHome.Lot;
|
||||
}
|
||||
|
||||
ProcessIndividual(LoanApplication.PrimaryBorrower,
|
||||
AppPartiesSection.PartyType.primaryBorrower,
|
||||
externalSpouseId,
|
||||
mfgHomeLot);
|
||||
|
||||
if (LoanApplication.CoApplicant is not null)
|
||||
{
|
||||
ProcessIndividual(LoanApplication.CoApplicant, AppPartiesSection.PartyType.borrower);
|
||||
|
||||
CheckForAndProcessSpouses(LoanApplication.CoApplicant);
|
||||
}
|
||||
|
||||
CheckForAndProcessSpouses(LoanApplication.PrimaryBorrower, true);
|
||||
|
||||
var createAppElement = GetCreateAppElement(LoanApplication.Date,
|
||||
AppParties.Build(),
|
||||
Parties.Build(),
|
||||
AppDetails.Build(),
|
||||
Properties.Build(),
|
||||
Addresses.Build(),
|
||||
AppNotes.Build(),
|
||||
Org.Build(),
|
||||
VehicleValuations.Build());
|
||||
|
||||
var baseElement = base.Build(createAppElement);
|
||||
|
||||
return baseElement;
|
||||
}
|
||||
|
||||
private void AddApplicationNotes()
|
||||
{
|
||||
AppNotes.AddAppNote("IP: " + LoanApplication.IPAddress + ", DISCLOSURE DATE: " + ConvertUtcToCentral(LoanApplication.DisclosureDate));
|
||||
if (!string.IsNullOrWhiteSpace(LoanApplication.PrimaryContactMethod))
|
||||
{
|
||||
AppNotes.AddAppNote("PRIMARY CONTACT METHOD: " + LoanApplication.PrimaryContactMethod);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(LoanApplication.PromoCode))
|
||||
{
|
||||
AppNotes.AddAppNote("PROMO CODE: " + LoanApplication.PromoCode);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(LoanApplication.Note))
|
||||
{
|
||||
AppNotes.AddAppNote(LoanApplication.Note);
|
||||
}
|
||||
|
||||
if (LoanApplication.RealEstate is not null && LoanApplication.RealEstate.LienPosition is not null &&
|
||||
LoanApplication.LoanTitle != "Heloc Rate Modification")
|
||||
{
|
||||
if (LoanApplication.RealEstate.LienPosition.PayoffFirstMortgage)
|
||||
{
|
||||
AppNotes.AddAppNote("I INTEND TO PAYOFF MY FIRST MORTGAGE WITH THIS LOAN.");
|
||||
}
|
||||
if (LoanApplication.RealEstate.LienPosition.PayoffSecondMortgage)
|
||||
{
|
||||
AppNotes.AddAppNote("I INTEND TO PAYOFF MY SECOND MORTGAGE WITH THIS LOAN.");
|
||||
}
|
||||
}
|
||||
|
||||
if (LoanApplication.LoanType == LoanType.S_Special)
|
||||
{
|
||||
AppNotes.AddAppNote("Special Loan: " + LoanApplication.LoanTitle);
|
||||
AppNotes.AddAppNote("Client Message: " + LoanApplication.ClientMessage);
|
||||
}
|
||||
|
||||
if (LoanApplication.LoanType == LoanType.S_Signature && !string.IsNullOrWhiteSpace(LoanApplication.PurposeOfLoanSignature))
|
||||
{
|
||||
AppNotes.AddAppNote("PURPOSE OF LOAN: " + LoanApplication.PurposeOfLoanSignature);
|
||||
}
|
||||
|
||||
if (LoanApplication.LoanType == LoanType.EQ_HELOC_Flex) {
|
||||
if (!string.IsNullOrWhiteSpace(LoanApplication.ModFeeAccount))
|
||||
{
|
||||
AppNotes.AddAppNote("MOD FEE ACCOUNT: " + LoanApplication.ModFeeAccount);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(LoanApplication.PrimaryBorrower.PrimaryApplicantEmail))
|
||||
{
|
||||
AppNotes.AddAppNote("PRIMARY APPLICANT EMAIL (E-DOC SIGNATURE): " + LoanApplication.PrimaryBorrower.PrimaryApplicantEmail);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(LoanApplication.PrimaryBorrower.CoApplicantEmail))
|
||||
{
|
||||
AppNotes.AddAppNote("CO-APPLICANT EMAIL (E-DOC SIGNATURE): " + LoanApplication.PrimaryBorrower.CoApplicantEmail);
|
||||
}
|
||||
}
|
||||
|
||||
if (LoanApplication.Vehicle != null)
|
||||
{
|
||||
if (LoanApplication.Vehicle.Type == Landmark.OLA.Models.Assets.Enums.VehicleType.Motorcycle
|
||||
&& !string.IsNullOrWhiteSpace(LoanApplication.Vehicle.StateTitled))
|
||||
{
|
||||
AppNotes.AddAppNote("State of Registration: " + LoanApplication.Vehicle.StateTitled);
|
||||
}
|
||||
|
||||
if (LoanApplication.Vehicle.Lien == "yes")
|
||||
{
|
||||
AppNotes.AddAppNote("Vehicle has a lien");
|
||||
}
|
||||
|
||||
var seller = LoanApplication.Vehicle?.Seller;
|
||||
|
||||
if (seller != null)
|
||||
{
|
||||
|
||||
var sellerStr = "INTERESTED IN BUYING FROM A " + seller.Value;
|
||||
sellerStr = sellerStr.Replace('_', ' ');
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(LoanApplication.Vehicle.DealerName) || !string.IsNullOrWhiteSpace(LoanApplication.Vehicle.DealerPhone))
|
||||
{
|
||||
bool bothSeller = !string.IsNullOrWhiteSpace(LoanApplication.Vehicle.DealerName) && !string.IsNullOrWhiteSpace(LoanApplication.Vehicle.DealerPhone);
|
||||
|
||||
sellerStr += ":";
|
||||
sellerStr += !string.IsNullOrWhiteSpace(LoanApplication.Vehicle.DealerName) ? " " + LoanApplication.Vehicle.DealerName : "";
|
||||
sellerStr += bothSeller ? " - " : "";
|
||||
sellerStr += !string.IsNullOrWhiteSpace(LoanApplication.Vehicle.DealerPhone) ? " " + String.Format("{0:(###) ###-####}", LoanApplication.Vehicle.DealerPhone) : "";
|
||||
}
|
||||
|
||||
AppNotes.AddAppNote(sellerStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckForAndProcessSpouses(IApplicant individual, bool isPrimaryBorrowerSpouse = false)
|
||||
{
|
||||
var partyType = isPrimaryBorrowerSpouse ? AppPartiesSection.PartyType.NonSigningSpouseMarriedToPrimary
|
||||
: AppPartiesSection.PartyType.NonSigningSpouseMarriedToCoBorrower;
|
||||
|
||||
//Validation can esnure that only one of these holds data
|
||||
|
||||
if (individual.NonApplicantSpouse is not null)
|
||||
{
|
||||
ProcessIndividual(individual.NonApplicantSpouse, partyType);
|
||||
}
|
||||
|
||||
if (individual.DetailedNonApplicantSpouse is not null)
|
||||
{
|
||||
ProcessIndividual(individual.DetailedNonApplicantSpouse, partyType);
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessIndividual(INonApplicant individual, AppPartiesSection.PartyType partyType)
|
||||
{
|
||||
var isMarried = partyType == AppPartiesSection.PartyType.NonSigningSpouseMarriedToCoBorrower
|
||||
|| partyType == AppPartiesSection.PartyType.NonSigningSpouseMarriedToPrimary;
|
||||
|
||||
Parties.AddNonApplicant(individual, isMarried);
|
||||
|
||||
Addresses.AddAddress(individual.MailingAddress,
|
||||
ContactMechanisms.CrifContactMechanism.CurrentAddress);
|
||||
}
|
||||
|
||||
private void ProcessIndividual(IApplicant individual,
|
||||
AppPartiesSection.PartyType partyType,
|
||||
Guid? externalSpouseId = null,
|
||||
PropertyLot mfgHomeLot = null)
|
||||
{
|
||||
Parties.AddApplicant(individual, externalSpouseId, mfgHomeLot);
|
||||
|
||||
ProcessHistory(individual, partyType);
|
||||
}
|
||||
|
||||
private void ProcessIndividual(IIndividualHistory individual, AppPartiesSection.PartyType partyType)
|
||||
{
|
||||
var isMarried = partyType == AppPartiesSection.PartyType.NonSigningSpouseMarriedToCoBorrower
|
||||
|| partyType == AppPartiesSection.PartyType.NonSigningSpouseMarriedToPrimary;
|
||||
|
||||
bool requiresHMDA = IsHMDARequired(LoanApplication.LoanType.ToString());
|
||||
Parties.AddHistory(individual, isMarried, requiresHMDA);
|
||||
|
||||
ProcessHistory(individual, partyType);
|
||||
}
|
||||
|
||||
public static bool IsHMDARequired(string loanType)
|
||||
{
|
||||
HMDALoanType parsedLoanType;
|
||||
if (Enum.TryParse(loanType, out parsedLoanType))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessHistory(IIndividualHistory individual, AppPartiesSection.PartyType partyType)
|
||||
{
|
||||
AddHistory(individual, partyType);
|
||||
|
||||
if (individual.Employers?.Count > 0)
|
||||
{
|
||||
foreach (var employer in individual.Employers)
|
||||
{
|
||||
Parties.AddEmployer(employer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static XElement GetCreateAppElement(DateTime date, params XElement[] content)
|
||||
{
|
||||
var element = new XElement(CrifNamespaces.Empty + "createApp",
|
||||
new XElement(CrifNamespaces.App + "application",
|
||||
new XAttribute(CrifNamespaces.App + "appReceivedDate",
|
||||
Dates.GetFormattedApplicationDate(date)),
|
||||
new XAttribute(CrifNamespaces.App + "appInitiatedDate",
|
||||
Dates.GetFormattedApplicationDate(date)),
|
||||
new XAttribute(CrifNamespaces.App + "priorityCD", "High"), //Per vendor examples
|
||||
content));
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
private void AddHistory(IIndividualHistory individual, AppPartiesSection.PartyType partyType)
|
||||
{
|
||||
AppParties.AddIndividualParty(individual, partyType, individual.HasOptedOutTCPA);
|
||||
|
||||
Addresses.AddAddress(individual.Address,
|
||||
ContactMechanisms.CrifContactMechanism.CurrentAddress);
|
||||
|
||||
if (!(individual.MailingAddress is null))
|
||||
{
|
||||
Addresses.AddAddress(individual.MailingAddress, ContactMechanisms.CrifContactMechanism.MailingAddress);
|
||||
}
|
||||
|
||||
if (individual.PreviousAddresses?.Count > 0)
|
||||
{
|
||||
foreach (var previousAddress in individual.PreviousAddresses)
|
||||
{
|
||||
Addresses.AddAddress(previousAddress, ContactMechanisms.CrifContactMechanism.PreviousAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ILoanApplicationRequestBuilder CreateProductDetails(LoanType? loanType, CrifSettings settings)
|
||||
{
|
||||
if (!loanType.HasValue)
|
||||
throw new ArgumentException("LoanType must have a value.");
|
||||
|
||||
if (settings == null)
|
||||
throw new ArgumentException("Product Details requires CrifSettings");
|
||||
|
||||
ILoanApplicationRequestBuilder appBuilder = null;
|
||||
|
||||
switch (loanType.Value)
|
||||
{
|
||||
case LoanType.CC_CashBack:
|
||||
case LoanType.CC_Rewards:
|
||||
case LoanType.CC_Student:
|
||||
case LoanType.CC_Secure:
|
||||
appBuilder = new CreditCardAppBuilder(settings);
|
||||
break;
|
||||
case LoanType.EQ_HELOC_Flex:
|
||||
appBuilder = new HelocFlexAppBuilder(settings);
|
||||
break;
|
||||
case LoanType.EQ_Mtg_Refi_Express:
|
||||
case LoanType.EQ_Home_Equity_Fixed:
|
||||
appBuilder = new RealEstateEquityAppBuilder(settings);
|
||||
break;
|
||||
case LoanType.EQ_Mfg_Home_With_or_Without_Land:
|
||||
appBuilder = new MfgHousingAndLandAppBuilder(settings);
|
||||
break;
|
||||
case LoanType.V_VehiclePreapproval:
|
||||
case LoanType.V_Vehicle:
|
||||
case LoanType.M_Boat:
|
||||
case LoanType.P_Powersport:
|
||||
case LoanType.T_TrailerMotorhome:
|
||||
appBuilder = new VehicleAppBuilder(settings);
|
||||
break;
|
||||
case LoanType.S_Special:
|
||||
case LoanType.S_Signature:
|
||||
appBuilder = new SignatureAppBuilder(settings);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(loanType), $"The requested loan type {loanType.Value} is not implemented.");
|
||||
}
|
||||
|
||||
return appBuilder;
|
||||
}
|
||||
|
||||
private static string ConvertUtcToCentral(DateTime date)
|
||||
{
|
||||
TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
|
||||
DateTime centralDate = TimeZoneInfo.ConvertTimeFromUtc(date.ToUniversalTime(), timeZone);
|
||||
return centralDate.ToString("g");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Xml.Linq;
|
||||
using CRIF.ACTion.Common.Parsers;
|
||||
using Landmark.OLA.Models.Loan;
|
||||
|
||||
namespace CRIF.ACTion.Loan
|
||||
{
|
||||
public class LoanApplicationResponseParser : IResponseParser<LoanApplication>
|
||||
{
|
||||
public LoanApplication Parse(XElement xdoc)
|
||||
{
|
||||
try
|
||||
{
|
||||
//TODO: This entire parser should be rewritten to use proper XPath-style lookups
|
||||
|
||||
var idElement = (XElement)((XElement)((XElement)((XElement)xdoc.FirstNode).FirstNode).FirstNode).NextNode;
|
||||
|
||||
return new LoanApplication(loanId: idElement.Value);
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new FormatException("CRIF XML is in an unexpected layout.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Xml.Linq;
|
||||
using CRIF.ACTion.Common;
|
||||
using CRIF.ACTion.Common.Builders;
|
||||
using CRIF.ACTion.Configuration;
|
||||
|
||||
namespace CRIF.ACTion.Loan
|
||||
{
|
||||
public class OrgSection : CrifRequestSection
|
||||
{
|
||||
public OrgSection(XNamespace sectionNamespace, CrifSettings settings)
|
||||
: base(sectionNamespace, "org", settings)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void SetOrgId(Guid orgId)
|
||||
{
|
||||
var orgAttribute = new XAttribute(CrifNamespaces.Common + "idRef", orgId);
|
||||
|
||||
AddContent(orgAttribute);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.Xml.Linq;
|
||||
using CRIF.ACTion.Common.Builders;
|
||||
using CRIF.ACTion.Configuration;
|
||||
|
||||
namespace CRIF.ACTion.Loan
|
||||
{
|
||||
public class PropertiesSection : CrifRequestSection
|
||||
{
|
||||
public PropertiesSection(XNamespace sectionNamespace, CrifSettings settings)
|
||||
: base(sectionNamespace, "properties", settings)
|
||||
{
|
||||
}
|
||||
|
||||
public void AddProperty(IProperty property)
|
||||
{
|
||||
AddContent(property.Build());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System.Xml.Linq;
|
||||
using CRIF.ACTion.Common;
|
||||
|
||||
namespace CRIF.ACTion.Loan
|
||||
{
|
||||
public class SavingsAccountProperty : IProperty
|
||||
{
|
||||
private readonly Guid _Id;
|
||||
private readonly decimal _Value;
|
||||
|
||||
public SavingsAccountProperty(Guid id, decimal value)
|
||||
{
|
||||
_Id = id;
|
||||
_Value = value;
|
||||
}
|
||||
|
||||
|
||||
public XElement Build(params XElement[] content)
|
||||
{
|
||||
var element = new XElement(CrifNamespaces.Common + "propertyStocksAndBonds",
|
||||
new XAttribute(CrifNamespaces.Common + "id", _Id.ToString()),
|
||||
new XAttribute(CrifNamespaces.Common + "finalEstimatedValue", _Value),
|
||||
new XAttribute(CrifNamespaces.Common + "propertyType", "CD"), //from CRIF Example
|
||||
new XAttribute(CrifNamespaces.Common + "description", "CDs or Savings")); //from CRIF Example
|
||||
|
||||
return element;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System.Xml.Linq;
|
||||
using CRIF.ACTion.Configuration;
|
||||
|
||||
namespace CRIF.ACTion.Loan
|
||||
{
|
||||
public class SignatureAppBuilder : ILoanApplicationRequestBuilder
|
||||
{
|
||||
private readonly CrifSettings _settings;
|
||||
public SignatureAppBuilder(CrifSettings settings)
|
||||
{
|
||||
_settings = settings;
|
||||
}
|
||||
public void SetDetails(LoanApplicationRequestBuilder createApp)
|
||||
{
|
||||
createApp.AppDetails = new AppDetailSignatureSection(createApp.CrifRequestSectionNamespace, _settings);
|
||||
var additionalContent = new List<XElement>();
|
||||
createApp.AppDetails.SetDetails(createApp.LoanApplication,
|
||||
createApp._sourceChannel, additionalContent: [.. additionalContent]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user