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,29 @@
using System.Xml.Linq;
using CRIF.ACTion.Common;
using CRIF.ACTion.Common.Builders;
using CRIF.ACTion.Configuration;
namespace CRIF.ACTion.Decisioning
{
public class DecisionStatusBuilder : BuilderBase
{
private readonly string ApplicationId;
private readonly string AppDetailId;
public DecisionStatusBuilder(string applicationId, string appDetailId, CrifSettings settings)
: base(CrifNamespaces.Empty, settings)
{
ApplicationId = applicationId;
AppDetailId = appDetailId;
}
public override XElement Build(params XElement[] content)
{
var getDecisioningElement = new XElement(CrifNamespaces.Empty + "getDecisionStatus",
new XAttribute(CrifNamespaces.Empty + "applicationID", ApplicationId),
new XAttribute(CrifNamespaces.Empty + "appDetailID", AppDetailId));
return base.Build(getDecisioningElement);
}
}
}
@@ -0,0 +1,47 @@
using System.Xml.Linq;
using Serilog;
using CRIF.ACTion.Common.Parsers;
using Landmark.OLA.Models.Decisioning.Enums;
namespace CRIF.ACTion.Decisioning
{
public class DecisioningStateResponseParser : IResponseParser<DecisioningState>
{
private const string SuccessMessage = "Success";
private const string MissingRequredInformation = "WorkFlowBC::SendToWorkflow::(Decisioning) Process Instances not in correct state Please correct the Process Errors.";
private string ExpectedLoanId;
public DecisioningStateResponseParser()
{
}
public void SetLoanId(string expectedLoanId)
{
ExpectedLoanId = expectedLoanId;
}
public DecisioningState Parse(XElement xElement)
{
if (string.IsNullOrWhiteSpace(ExpectedLoanId))
{
throw new ArgumentException("Must set valid ExpectedLoanId with SetLoanId(expectedLoanId)");
}
if (xElement.Value.Equals(SuccessMessage + ExpectedLoanId))
{
return DecisioningState.Requested;
}
if (xElement.Value.Equals(MissingRequredInformation))
{
Log.Debug("Application {loanId} is likely missing information required for decisioning.", SuccessMessage, ExpectedLoanId);
return DecisioningState.MissingRequiredInformation;
}
else
{
Log.Debug("Did not receive {SuccessMessage} for a SendToDecisioning call for Application {loanId}.", SuccessMessage, ExpectedLoanId);
return DecisioningState.Unknown;
}
}
}
}
@@ -0,0 +1,26 @@
using System.Xml.Linq;
using CRIF.ACTion.Common;
using CRIF.ACTion.Common.Builders;
using CRIF.ACTion.Configuration;
namespace CRIF.ACTion.Decisioning
{
public class GetApplicationProductsRequestBuilder : BuilderBase
{
private readonly string ApplicationId;
public GetApplicationProductsRequestBuilder(string applicationId, CrifSettings settings)
: base(CrifNamespaces.Empty, settings)
{
ApplicationId = applicationId;
}
public override XElement Build(params XElement[] content)
{
var sendToDecisioningElement = new XElement(CrifNamespaces.Empty + "getApplicationProducts",
new XAttribute(CrifNamespaces.Empty + "applicationID", ApplicationId));
return base.Build(sendToDecisioningElement);
}
}
}
@@ -0,0 +1,165 @@
using System.Xml.Linq;
using CRIF.ACTion.Common;
using CRIF.ACTion.Common.Parsers;
using Serilog;
using Landmark.OLA.Models.Decisioning;
using Landmark.OLA.Models.Decisioning.Enums;
namespace CRIF.ACTion.Decisioning
{
public class GetApplicationProductsResponseParser : IResponseParser<DecisioningDetails>
{
private string LoanApplicationId;
private const string ApplicationsPath = "/actionAPI/getApplicationProducts/msg:appExportResponse/msg:applications/app:application";
private const string AppDetailsPath = "/app:application/app:appDetails";
private readonly XName AppDetailStatusesName = CrifNamespaces.App + "appDetailStatuses";
private readonly XName AppDetailStatusName = CrifNamespaces.App + "appDetailStatus";
private readonly XName StatusAttribute = CrifNamespaces.App + "statusType";
private const string DecisionTypeValue = "DecisionStatus";
private readonly XName DecisionResultName = CrifNamespaces.App + "status";
private readonly XName AppDetailStipulationsName = CrifNamespaces.App + "appDetailStipulations";
private readonly XName StipulationName = CrifNamespaces.App + "stipulation";
private readonly XName StipulationIdName = CrifNamespaces.Common + "stipulationID";
public GetApplicationProductsResponseParser()
{
}
public void SetLoanId(string loanApplicationId)
{
LoanApplicationId = loanApplicationId;
}
public DecisioningDetails Parse(XElement xElement)
{
if (string.IsNullOrWhiteSpace(LoanApplicationId))
{
throw new ArgumentException("Must set valid LoanApplicationId with SetLoanId(loanApplicationId)");
}
var namespaceManager = CrifNamespaces.GetNamespaceManager(xElement);
var applicationElement = xElement.XElementXPathSelectElement(ApplicationsPath, namespaceManager);
if (applicationElement == null)
{
//CRIF didn't recognize this application ID
throw new ArgumentException("The Application Id was not recognized by the decisioning system.");
}
if (!applicationElement.Attribute(CrifNamespaces.App + "applicationID").Value.Equals(LoanApplicationId))
{
Log.Fatal("CRIF XML does not match expected loan ID {loanId}", LoanApplicationId);
throw new InvalidOperationException("Unexpected vendor response.");
}
var appDetailElements = applicationElement.XElementXPathSelectElement(AppDetailsPath, namespaceManager).Elements().ToList();
for (int detailIndex = appDetailElements.Count - 1; detailIndex >= 0; detailIndex--)
{
var detail = appDetailElements[detailIndex];
var statuses = GetElementFromElement(detail, AppDetailStatusesName);
var decision = GetElementFromElementWithAttributeIdentifier(statuses, AppDetailStatusName, StatusAttribute, DecisionTypeValue);
if (decision == null)
{
appDetailElements.Remove(detail);
continue;
}
var decisionResult = GetAttributeFromElement(decision, DecisionResultName);
var status = (DecisioningResult)Enum.Parse(typeof(DecisioningResult), decisionResult.Value);
if (status == DecisioningResult.DecisionStatus_Cancelled)
{
appDetailElements.Remove(detail);
}
}
if (appDetailElements.Count != 1)
{
if (appDetailElements.Count == 0)
{
return new DecisioningDetails()
{
DecisioningState = DecisioningState.Unknown
};
}
throw new ArgumentException($"Application contains {appDetailElements.Count} appDetail elements. An appDetailID is required.");
}
var appDetailStatuses = GetElementFromElement(appDetailElements.SingleOrDefault(), AppDetailStatusesName);
var decisionStatus = GetElementFromElementWithAttributeIdentifier(appDetailStatuses, AppDetailStatusName, StatusAttribute, DecisionTypeValue);
var stipulations = GetStipulations(appDetailElements.Single().Element(AppDetailStipulationsName));
if (decisionStatus == null)
{
return new DecisioningDetails(stipulations)
{
DecisioningState = DecisioningState.Unknown,
};
}
else
{
var decisioningResult = GetAttributeFromElement(decisionStatus, DecisionResultName);
var statusResult = (DecisioningResult)Enum.Parse(typeof(DecisioningResult), decisioningResult.Value);
return new DecisioningDetails(stipulations)
{
DecisioningState = DecisioningState.Ready,
DecisioningResult = statusResult,
};
}
}
private ICollection<int> GetStipulations(XElement appDetailStipulations)
{
var stipulations = new List<int>();
if (appDetailStipulations is null)
{
return stipulations;
}
foreach (var stipulationElement in appDetailStipulations.Elements())
{
var appDetailStipulation = stipulationElement.Element(StipulationName);
var stipulationIdString = appDetailStipulation.Attribute(StipulationIdName).Value;
if (int.TryParse(stipulationIdString, out int stipulationId))
{
if (CrifConstants.StipulationsToShow.ContainsKey(stipulationId))
{
stipulations.Add(stipulationId);
}
}
}
return stipulations;
}
private static XElement GetElementFromElement(XElement element, XName elementToFind)
{
return element.Element(elementToFind);
}
private static XElement GetElementFromElementWithAttributeIdentifier(XElement element, XName elementToSearch, XName attribute, string identifier)
{
return element.Elements(elementToSearch).SingleOrDefault(x => x.Attribute(attribute).Value.Equals(identifier));
}
private static XAttribute GetAttributeFromElement(XElement element, XName attribute)
{
return element.Attribute(attribute);
}
}
}
@@ -0,0 +1,26 @@
using CRIF.ACTion.Common;
using CRIF.ACTion.Common.Builders;
using CRIF.ACTion.Configuration;
using System.Xml.Linq;
namespace CRIF.ACTion.Decisioning
{
public class SendToDecisioningRequestBuilder : BuilderBase
{
private readonly string ApplicationId;
public SendToDecisioningRequestBuilder(string applicationId, CrifSettings settings)
: base(CrifNamespaces.Empty, settings)
{
ApplicationId = applicationId;
}
public override XElement Build(params XElement[] content)
{
var sendToDecisioningElement = new XElement(CrifNamespaces.Empty + "sendToDecisioning",
new XAttribute(CrifNamespaces.Empty + "applicationID", ApplicationId));
return base.Build(sendToDecisioningElement);
}
}
}