first commit

This commit is contained in:
Zeeshaun
2026-03-11 11:18:25 -05:00
commit f3cb730f3b
472 changed files with 53651 additions and 0 deletions
@@ -0,0 +1,24 @@
using System.Xml.Linq;
using CRIF.ACTion.Common;
using CRIF.ACTion.Common.Builders;
namespace CRIF.ACTion.Configuration
{
public class ConfigurationRequestBuilder : BuilderBase
{
private readonly string SettingName;
public ConfigurationRequestBuilder(string settingName, CrifSettings settings)
: base(CrifNamespaces.Empty, settings)
{
SettingName = settingName;
}
public override XElement Build(params XElement[] content)
{
var retrieveCriffConfigurationElement = new XElement(CrifNamespaces.Empty + SettingName);
return base.Build(retrieveCriffConfigurationElement);
}
}
}
@@ -0,0 +1,78 @@
using System.Xml.Linq;
using Serilog;
using CRIF.ACTion.Common;
using CRIF.ACTion.Common.Parsers;
namespace CRIF.ACTion.Configuration
{
public class ConfigurationRequestResponseParser : IResponseParser<SortedList<int, string>>
{
private const string _channelsPath = "/actionAPI/getChannels/msg:maintExportResponse/msg:maintenanceEntities/maint:parties/common:channel/common:channelClassifications/common:channelClassification/common:channelClassificationItem";
public ConfigurationRequestResponseParser()
{
}
public SortedList<int, string> Parse(XElement xElement)
{
SortedList<int, string> mappingList = [];
try
{
var namespaceManager = CrifNamespaces.GetNamespaceManager(xElement);
IEnumerable<XElement> channelNodeList = xElement.XElementXPathSelectElements(_channelsPath, namespaceManager);
foreach (XElement channelNode in channelNodeList)
{
try
{
string nodeAttributeValue = StandardizedStringValue(channelNode.Attribute(CrifNamespaces.Common + "name").Value);
if (ChannelIsActive(nodeAttributeValue))
{
string partyIdString = channelNode.Parent.Parent.Parent.Attribute(CrifNamespaces.Common + "partyID").Value;
string name = channelNode.Parent.Parent.Parent.Attribute(CrifNamespaces.Common + "name").Value;
_ = int.TryParse(partyIdString, out int partyId);
mappingList.Add(partyId, name);
}
}
catch (Exception ex)
{
Log.Error("Error trying to parse CRIF BranchName Configuration Response", ex.Message, ex.StackTrace);
}
}
}
catch (Exception ex)
{
Log.Error("Error trying to parse CRIF BranchName Configuration Response", ex.Message, ex.StackTrace);
}
return mappingList;
}
private static bool ChannelIsActive(string nodeAttributeValue)
{
bool channelIsActive = false;
if (!string.IsNullOrWhiteSpace(nodeAttributeValue))
{
channelIsActive =
(
nodeAttributeValue.Equals("BRANCH") ||
nodeAttributeValue.Equals("INTERNET") ||
nodeAttributeValue.Equals("ON-LINE")
);
}
return channelIsActive;
}
private static string StandardizedStringValue(string InputString)
{
string standardizedString = "";
if (!string.IsNullOrWhiteSpace(InputString))
{
standardizedString = InputString.Trim().ToUpper();
}
return standardizedString;
}
}
}
@@ -0,0 +1,86 @@
namespace CRIF.ACTion
{
/************
This file should be migrated to appsettings.json and the CrifSettings class
*************/
public class CrifConstants
{
public static TimeSpan SubmissionTimeoutInMinutes => new(0, 2, 0);
public static int EQ_ListedForSale_Field_Id = -110;
public static int EQ_ListedForSale_Field_True = 272;
public static int EQ_ListedForSale_Field_False = 271;
public static int EQ_CurrentlyBeingRemodeledOrImproved_Field_Id = -109;
public static int EQ_CurrentlyBeingRemodeledOrImproved_Field_True = 270;
public static int EQ_CurrentlyBeingRemodeledOrImproved_Field_False = 269;
public static int Borrower_IsApplicantNonSigningSpouse_Field_Id = -73;
public static int Borrower_IsApplicantNonSigningSpouse_Field_Borrower = 85;
public static int Borrower_IsApplicantNonSigningSpouse_Field_NonSigningMarriedToPrimary = 84;
public static int Borrower_IsApplicantNonSigningSpouse_Field_NonSigningMarriedToCo = 83;
public static int TCPA_Opt_Out_Field_Id = -112;
public static Dictionary<Collateral, int> CollateralIds = new Dictionary<Collateral, int>
{
//Take from CRIF database: select * from v_RptLuCollateralType_v001
{Collateral.Vehicle, 1},
{Collateral.ResidentialRealEstate, 2},
{Collateral.Marine, 3},
{Collateral.ManufacturedHome, 4},
{Collateral.RecreationalVehicle, 5},
{Collateral.Stocks, 6},
{Collateral.Bonds, 7},
{Collateral.Insurance, 8},
{Collateral.CDs, 9},
{Collateral.CDsOrSavings, 18},
{Collateral.Collateral401k, 10},
{Collateral.CommercialRealEstate, 11},
{Collateral.AccountsReceivable, 12},
{Collateral.SecuredOther, 13},
{Collateral.ManufacturedHomeAndLand, 14},
{Collateral.Motorcycle, 15},
{Collateral.ATV, 16},
{Collateral.Snowmobile, 17},
};
public static int SpecialHandlingCode_OneBorrower_with_NonapplicantSpouse = 8;
public static Dictionary<int, string> StipulationsToShow = new Dictionary<int, string>
{
//matches occur by int ID. Text is only used to easily identify stipulations.
{20, "A Personal Guaranty form is required for all business loans" },
{92, "Cards can only be issued to business owner and owner's spouse"},
{58, "Final Approval is dependent on Appraisal, Title, and Flood"},
{82, "Landmark Business savings account must be established."},
{85, "Must show proof borrower is a current student."},
{59, "Two years of income verification is required"},
};
public enum Collateral
{
//These enum int values have no relation to CRIF's int values. Use the dictionary above instead.
Vehicle,
ResidentialRealEstate,
Marine,
ManufacturedHome,
RecreationalVehicle,
Stocks,
Bonds,
Insurance,
CDs,
CDsOrSavings,
Collateral401k, //enums must start with a letter
CommercialRealEstate,
AccountsReceivable,
SecuredOther,
ManufacturedHomeAndLand,
Motorcycle,
ATV,
Snowmobile,
};
}
}
@@ -0,0 +1,106 @@
namespace CRIF.ACTion.Configuration
{
public class CrifSettings
{
public ApiConnectionSettings ApiSettings { get; set; }
public SourceChannelSettings SourceChannels { get; set; }
public ProductIdSettings ProductIds { get; set; }
public ServicingChannelSettings ServicingChannels { get; set; }
public CustomFieldMappings CustomFieldMappings { get; set; }
public CustomFieldConfigs CustomFields { get; set; }
public FormatCategorySettings FormatCategoryMappings { get; set; }
}
public class CustomJointCreditData
{
public string CustomFieldId { get; set; }
public string ProductCategoryId { get; set; }
public string SortOrder { get; set; }
public string IndividuallyId { get; set; }
public string JointlyId { get; set; }
}
public class CustomPropertyStatusData
{
public string CustomFieldId { get; set; }
public string ProductCategoryId { get; set; }
public string SortOrder { get; set; }
public string YesId { get; set; }
public string NoId { get; set; }
public string NaId { get; set; }
}
public class CustomFieldConfigs
{
public List<CustomPropertyStatusData> CustomPropertyRenovationFieldData { get; set; }
public List<CustomPropertyStatusData> CustomPropertySaleFieldData { get; set; }
public List<CustomJointCreditData> CustomJointCreditFieldData { get; set; }
public Dictionary<string, string> ProductIdToCategoryId { get; set; }
}
public class CustomFieldMappings
{
public Dictionary<string, string> LoanTypeToPromoId { get; set; }
public Dictionary<string, string> CustomFieldID { get; set; }
public Dictionary<string, string> MunicipalityTypeCode { get; set; }
}
public class CustomFieldIDMappings
{
public Dictionary<string, string> CustomFieldID { get; set; }
}
public class ApiConnectionSettings
{
public string EndpointUrl { get; set; }
public string Username { get; set; }
public int InterfaceId { get; set; }
public string OrgCode { get; set; }
public int OrgId { get; set; }
}
public class SourceChannelSettings
{
public int DefaultSourceChannelId { get; set; }
public int CreditCardSourceChannelId { get; set; }
}
public class ProductIdSettings
{
public int CC_CashBack { get; set; }
public int CC_Rewards { get; set; }
public int CC_Student { get; set; }
public int CC_Secure { get; set; }
public int EQ_HELOC_Flex { get; set; }
public int EQ_Home_Equity_Fixed { get; set; }
public int EQ_Mtg_Refi_Express { get; set; }
public int EQ_Mfg_Home_And_Land { get; set; }
public int V_Vehicle { get; set; }
public int V_VehiclePreapproval { get; set; }
public int M_Boat { get; set; }
public int P_Powersport { get; set; }
public int T_TrailerMotorhome { get; set; }
public int S_Signature { get; set; }
}
public class FormatCategorySettings
{
public Dictionary<string, int> Categories { get; set; }
public Dictionary<string, string> DocumentToCategory { get; set; }
}
public class ServicingChannelSettings
{
public int DefaultServicingChannel { get; set; }
}
}
@@ -0,0 +1,222 @@
using System.Xml.Linq;
using Serilog;
using CRIF.ACTion.Common;
using CRIF.ACTion.Common.Parsers;
namespace CRIF.ACTion.Configuration
{
public class CustomFieldRequestResponseParser : IResponseParser<CustomFieldConfigs>
{
private const string _customFieldsPath = "/actionAPI/getCustomFields/msg:maintExportResponse/msg:maintenanceEntities/maint:maintenanceEntity/maint:fields/common:customLookupField";
public CustomFieldRequestResponseParser()
{
}
public CustomFieldConfigs Parse(XElement xElement)
{
CustomFieldConfigs customFieldConfig = new();
try
{
var namespaceManager = CrifNamespaces.GetNamespaceManager(xElement);
IEnumerable<XElement> customFieldNodeList = xElement.XElementXPathSelectElements(_customFieldsPath, namespaceManager);
List<string> RenovationMatchCriteria = ["IS THE PROPERTY CURRENTLY BEING REMODELED OR IMPROVED?"];
List<string> SaleMatchCriteria = ["IS THE PROPERTY CURRENTLY LISTED FOR SALE?"];
List<string> JointMatchCriteria = ["INTENT FOR JOINT CREDIT"];
customFieldConfig.CustomPropertyRenovationFieldData = ParseCustomPropertyStatusData(customFieldNodeList, RenovationMatchCriteria);
customFieldConfig.CustomPropertySaleFieldData = ParseCustomPropertyStatusData(customFieldNodeList, SaleMatchCriteria);
customFieldConfig.CustomJointCreditFieldData = ParseCustomJointCreditData(customFieldNodeList, JointMatchCriteria);
}
catch (Exception ex)
{
Log.Error("Error trying to parse CRIF Custom Field Configuration Response", ex.Message, ex.StackTrace);
}
return customFieldConfig;
}
private List<CustomJointCreditData> ParseCustomJointCreditData(IEnumerable<XElement> customFieldNodeList, List<string> MatchCriteria)
{
List<CustomJointCreditData> customDataSet = [];
foreach (XElement node in customFieldNodeList)
{
try
{
string nodeAttributeValue = node.Attribute(CrifNamespaces.Common + "name").Value;
if (CustomFieldIsActive(nodeAttributeValue, MatchCriteria))
{
string individuallyId = "";
string jointlyId = "";
string productCategoryId = "";
IEnumerable<XElement> childNodes = node.Descendants().Elements();
foreach (XElement option in childNodes)
{
if (option.Name.LocalName.Equals("FIELDSELECTION", StringComparison.CurrentCultureIgnoreCase))
{
var attributes = option.Attributes();
foreach (var attribute in attributes)
{
string idValue = "";
string nameValue = "";
if (attribute.Name.LocalName.Equals("FIELDSELECTIONID", StringComparison.CurrentCultureIgnoreCase))
{
idValue = attribute.Value;
nameValue = attribute.NextAttribute.Value.ToUpper();
switch (nameValue)
{
case "INDIVIDUALLY":
individuallyId = idValue;
break;
case "JOINTLY":
jointlyId = idValue;
break;
default:
break;
}
}
}
}
else if (option.Name.LocalName.ToUpper() == "PRODUCTCATEGORY")
{
productCategoryId = option.LastAttribute.Value;
}
}
CustomJointCreditData data = new()
{
CustomFieldId = node.Attribute(CrifNamespaces.Common + "ID").Value,
ProductCategoryId = productCategoryId,
SortOrder = node.Attribute(CrifNamespaces.Common + "sortOrder").Value,
JointlyId = jointlyId,
IndividuallyId = individuallyId
};
customDataSet.Add(data);
}
}
catch (Exception ex)
{
Log.Error("Error trying to parse CRIF Custom Field Configuration Response", ex.Message, ex.StackTrace);
}
}
return customDataSet;
}
private List<CustomPropertyStatusData> ParseCustomPropertyStatusData(IEnumerable<XElement> customFieldNodeList, List<string> MatchCriteria)
{
List<CustomPropertyStatusData> customDataSet = [];
foreach (XElement node in customFieldNodeList)
{
try
{
string nodeAttributeValue = node.Attribute(CrifNamespaces.Common + "name").Value;
if (CustomFieldIsActive(nodeAttributeValue, MatchCriteria))
{
string yesId = "";
string noId = "";
string naId = "";
string productCategoryId = "";
IEnumerable<XElement> childNodes = node.Descendants().Elements();
foreach (XElement option in childNodes)
{
if (option.Name.LocalName.Equals("FIELDSELECTION", StringComparison.CurrentCultureIgnoreCase))
{
var attributes = option.Attributes();
foreach (var attribute in attributes)
{
string idValue = "";
string nameValue = "";
if (attribute.Name.LocalName.ToUpper() == "FIELDSELECTIONID")
{
idValue = attribute.Value;
nameValue = attribute.NextAttribute.Value.ToUpper();
switch (nameValue)
{
case "YES":
yesId = idValue;
break;
case "NO":
noId = idValue;
break;
case "N/A (FLEX FIXED DRAWS ONLY)":
naId = idValue;
break;
default:
break;
}
}
}
}
else if (option.Name.LocalName.ToUpper() == "PRODUCTCATEGORY")
{
productCategoryId = option.LastAttribute.Value;
}
}
CustomPropertyStatusData data = new CustomPropertyStatusData
{
CustomFieldId = node.Attribute(CrifNamespaces.Common + "ID").Value,
ProductCategoryId = productCategoryId,
SortOrder = node.Attribute(CrifNamespaces.Common + "sortOrder").Value,
NoId = noId,
YesId = yesId,
NaId = naId
};
customDataSet.Add(data);
}
}
catch (Exception ex)
{
Log.Error("Error trying to parse CRIF Custom Field Configuration Response", ex.Message, ex.StackTrace);
}
}
return customDataSet;
}
private bool CustomFieldIsActive(string NodeAttributeValue, List<string> ActiveMatchCriteria)
{
bool isActive = false;
foreach (string compare in ActiveMatchCriteria)
{
string standardizedNodeString = StandardizedStringValue(NodeAttributeValue);
string standardizedCompareString = StandardizedStringValue(compare);
bool validCompareInput = !string.IsNullOrWhiteSpace(standardizedNodeString) && !string.IsNullOrWhiteSpace(compare);
if (validCompareInput && !isActive)
{
isActive =
(
standardizedNodeString.Equals(standardizedCompareString)
);
}
}
return isActive;
}
private string StandardizedStringValue(string InputString)
{
string standardizedString = "";
if (!string.IsNullOrWhiteSpace(InputString))
{
standardizedString = InputString.Trim().ToUpper();
}
return standardizedString;
}
}
}
@@ -0,0 +1,47 @@
using System.Xml.Linq;
using Serilog;
using CRIF.ACTion.Common;
using CRIF.ACTion.Common.Parsers;
namespace CRIF.ACTion.Configuration
{
public class ProductDetailsResponseParser : IResponseParser<Dictionary<string, string>>
{
private const string _productDetailsPath = "/actionAPI/getProducts/msg:maintExportResponse/msg:maintenanceEntities/maint:maintenanceEntity/maint:products/common:product/common:productCategory";
public ProductDetailsResponseParser()
{
}
public Dictionary<string, string> Parse(XElement xElement)
{
Dictionary<string, string> mappingList = [];
try
{
var namespaceManager = CrifNamespaces.GetNamespaceManager(xElement);
IEnumerable<XElement> channelNodeList = xElement.XElementXPathSelectElements(_productDetailsPath, namespaceManager);
foreach (XElement channelNode in channelNodeList)
{
try
{
string productId = channelNode.Parent.Attribute(CrifNamespaces.Common + "productID").Value;
string categoryId = channelNode.Attribute(CrifNamespaces.Common + "productCategoryID").Value;
mappingList.Add(productId, categoryId);
}
catch (Exception ex)
{
Log.Error("Error trying to parse CRIF Product information from node in Configuration Response", ex.Message, ex.StackTrace);
}
}
}
catch (Exception ex)
{
Log.Error("Error trying to parse CRIF Products Configuration Response", ex.Message, ex.StackTrace);
}
return mappingList;
}
}
}