first commit
This commit is contained in:
@@ -0,0 +1,265 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
using Serilog;
|
||||
using CRIF.ACTion.Common.Parsers;
|
||||
using CRIF.ACTion.Configuration;
|
||||
using CRIF.ACTion.Decisioning;
|
||||
using CRIF.ACTion.Files;
|
||||
using CRIF.ACTion.Loan;
|
||||
using CRIF.ACTion.Loan.Individuals;
|
||||
using CRIF.ACTion.Services.Landmark.DistributionChannel;
|
||||
using Landmark.OLA.Models;
|
||||
using Landmark.OLA.Models.Decisioning;
|
||||
using Landmark.OLA.Models.Decisioning.Enums;
|
||||
using Landmark.OLA.Models.Individuals;
|
||||
using Landmark.OLA.Models.Loan;
|
||||
|
||||
namespace CRIF.ACTion.Services.Crif
|
||||
{
|
||||
public class CrifVendorClient : ICrifVendorClient
|
||||
{
|
||||
private readonly string _getCustomFieldsString = "getCustomFields";
|
||||
private readonly string _getProductDetailsString = "getProducts";
|
||||
private readonly int retryLimit = 6;
|
||||
private readonly ICrifService _crifService;
|
||||
private readonly IResponseParser<Individual> _individualResponseParser;
|
||||
private readonly IResponseParser<LoanApplication> _loanApplicationResponseParser;
|
||||
private readonly IResponseParser<DecisioningState> _decisioningStateResponseParser;
|
||||
private readonly IResponseParser<DecisioningDetails> _decisioningDetailsResponseParser;
|
||||
private readonly IResponseParser<SortedList<int, string>> _configurationResponseParser;
|
||||
private readonly IResponseParser<Dictionary<string, string>> _productDetailsResponseParser;
|
||||
private readonly IResponseParser<CustomFieldConfigs> _customFieldResponseParser;
|
||||
private readonly IResponseParser<DealershipAuthRequest> _dealershipResponseParser;
|
||||
private readonly CrifSettings _settings;
|
||||
|
||||
public CrifVendorClient(ICrifService crifService,
|
||||
IResponseParser<Individual> individualResponseParser,
|
||||
IResponseParser<LoanApplication> loanApplicationResponseParser,
|
||||
IResponseParser<DecisioningState> decisioningStateResponseParser,
|
||||
IResponseParser<DecisioningDetails> decisioningDetailsResponseParser,
|
||||
IResponseParser<SortedList<int, string>> crifConfigurationResponseParser,
|
||||
IResponseParser<Dictionary<string, string>> productDetailsResponseParser,
|
||||
IResponseParser<CustomFieldConfigs> customFieldResponseParser,
|
||||
IResponseParser<DealershipAuthRequest> dealershipResponseParser,
|
||||
IOptions<CrifSettings> settings)
|
||||
{
|
||||
_crifService = crifService;
|
||||
_individualResponseParser = individualResponseParser;
|
||||
_loanApplicationResponseParser = loanApplicationResponseParser;
|
||||
_decisioningStateResponseParser = decisioningStateResponseParser;
|
||||
_decisioningDetailsResponseParser = decisioningDetailsResponseParser;
|
||||
_configurationResponseParser = crifConfigurationResponseParser;
|
||||
_productDetailsResponseParser = productDetailsResponseParser;
|
||||
_customFieldResponseParser = customFieldResponseParser;
|
||||
_dealershipResponseParser = dealershipResponseParser;
|
||||
_settings = settings.Value;
|
||||
_settings.CustomFields = GetCustomFieldConfiguration().GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
public async Task<DealershipAuthRequest> GetDealershipAuthDetails(string applicationId)
|
||||
{
|
||||
var getApp = new DealershipRequestBuilder(applicationId, _settings);
|
||||
|
||||
var xmlApp = getApp.Build();
|
||||
|
||||
try
|
||||
{
|
||||
var response = await _crifService.SendMessage(xmlApp);
|
||||
return _dealershipResponseParser.Parse(response);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Fatal("Error parsing response: " + e.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<LoanApplication> CreateApplication(LoanApplication loanApplication, IDistributionChannelLookupService channelService = null)
|
||||
{
|
||||
Log.Debug("Building Loan Application");
|
||||
|
||||
ModelValidator.Validate(loanApplication);
|
||||
|
||||
var createApp = new LoanApplicationRequestBuilder(loanApplication, _settings, null, null, null, channelService);
|
||||
|
||||
var xmlApp = createApp.Build();
|
||||
|
||||
var response = await _crifService.SendMessage(xmlApp);
|
||||
|
||||
try
|
||||
{
|
||||
return _loanApplicationResponseParser.Parse(response);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Log.Fatal("Error parsing response.");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<string> CreateApplicationAndGetId(LoanApplication loanApplication, IDistributionChannelLookupService channelService = null)
|
||||
{
|
||||
var parsedLoanApplication = await CreateApplication(loanApplication, channelService);
|
||||
return parsedLoanApplication.Id;
|
||||
}
|
||||
|
||||
public async Task<bool> AddFile(string applicationId, LoanApplicationFile file, string fileBase64Value)
|
||||
{
|
||||
try
|
||||
{
|
||||
var addFile = new FileRequestBuilder(applicationId, file, fileBase64Value, _settings);
|
||||
var response = await _crifService.SendMessage(addFile.Build());
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Fatal("Error uploading file to loan application: " + applicationId);
|
||||
Log.Fatal(e.ToString());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Task<Individual> AddIndividual(string applicationId, Individual individual)
|
||||
{
|
||||
ModelValidator.Validate(individual);
|
||||
|
||||
var addIndividual = new AddIndividualRequestBuilder(applicationId, individual, _settings);
|
||||
|
||||
var response = await _crifService.SendMessage(addIndividual.Build());
|
||||
|
||||
try
|
||||
{
|
||||
return _individualResponseParser.Parse(response);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Log.Fatal("Error parsing response.");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> SendToDecisioning(string applicationId)
|
||||
{
|
||||
var sendToDecisioning = new SendToDecisioningRequestBuilder(applicationId, _settings);
|
||||
|
||||
var response = await _crifService.SendMessage(sendToDecisioning.Build());
|
||||
|
||||
//TODO: This cast is not particularly Dependency Injection-y
|
||||
//TODO: Requiring the Application Id is really just a double check, and may not matter all that much
|
||||
((DecisioningStateResponseParser)_decisioningStateResponseParser).SetLoanId(applicationId);
|
||||
|
||||
var result = _decisioningStateResponseParser.Parse(response);
|
||||
|
||||
if (result == DecisioningState.MissingRequiredInformation)
|
||||
{
|
||||
throw new InvalidOperationException("Loan application cannot be sent to decisioning, and is likely missing required information.");
|
||||
}
|
||||
|
||||
if (result == DecisioningState.Requested || result == DecisioningState.Ready)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<DecisioningDetails> GetDecisionStatus(string applicationId)
|
||||
{
|
||||
//TODO: This cast is not particularly Dependency Injection-y
|
||||
//TODO: Requiring the Application Id is really just a double check, and may not matter all that much
|
||||
((GetApplicationProductsResponseParser)_decisioningDetailsResponseParser).SetLoanId(applicationId);
|
||||
|
||||
var result = new DecisioningDetails()
|
||||
{
|
||||
DecisioningState = DecisioningState.Unknown
|
||||
};
|
||||
int retryAttempts = 0;
|
||||
Thread.Sleep(2500);
|
||||
|
||||
do
|
||||
{
|
||||
Thread.Sleep((retryAttempts * 200) + 1500);
|
||||
var getDecisionStatus = new GetApplicationProductsRequestBuilder(applicationId, _settings);
|
||||
var response = await _crifService.SendMessage(getDecisionStatus.Build());
|
||||
result = _decisioningDetailsResponseParser.Parse(response);
|
||||
retryAttempts++;
|
||||
} while (retryAttempts < retryLimit && result.DecisioningState == DecisioningState.Unknown);
|
||||
|
||||
if (retryAttempts >= retryLimit && result.DecisioningState == DecisioningState.Unknown)
|
||||
{
|
||||
result.DecisioningState = DecisioningState.Ready;
|
||||
result.DecisioningResult = DecisioningResult.DecisionStatus_Review;
|
||||
}
|
||||
|
||||
Log.Information($"Application ID: {applicationId}, Number of Attempts to Get DecisionStatus: {retryAttempts}");
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<SortedList<int, string>> GetBranchNameConfiguration(string ConfigurationSectionName)
|
||||
{
|
||||
var configurationRequest = new ConfigurationRequestBuilder(ConfigurationSectionName, _settings);
|
||||
|
||||
var response = await _crifService.SendMessage(configurationRequest.Build());
|
||||
|
||||
var result = _configurationResponseParser.Parse(response);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<CustomFieldConfigs> GetCustomFieldConfiguration()
|
||||
{
|
||||
CustomFieldConfigs customFieldConfig = new CustomFieldConfigs();
|
||||
string municipalityTypeId = null;
|
||||
string municipalityWhereKeptId = null;
|
||||
|
||||
try
|
||||
{
|
||||
var configurationRequest = new ConfigurationRequestBuilder(_getCustomFieldsString, _settings);
|
||||
|
||||
var response = await _crifService.SendMessage(configurationRequest.Build());
|
||||
|
||||
customFieldConfig = _customFieldResponseParser.Parse(response);
|
||||
|
||||
if (_settings?.CustomFieldMappings?.CustomFieldID != null)
|
||||
{
|
||||
_settings.CustomFieldMappings.CustomFieldID.TryGetValue("MunicipalityType", out municipalityTypeId);
|
||||
_settings.CustomFieldMappings.CustomFieldID.TryGetValue("MunicipalityWhereKept", out municipalityWhereKeptId);
|
||||
}
|
||||
|
||||
Log.Information(
|
||||
"CRIF custom field mappings loaded: MunicipalityType={MunicipalityTypeId}, MunicipalityWhereKept={MunicipalityWhereKeptId}",
|
||||
municipalityTypeId ?? "<missing>",
|
||||
municipalityWhereKeptId ?? "<missing>");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Fatal("Error parsing CRIF custom fields configuration response." + ex.StackTrace);
|
||||
}
|
||||
|
||||
customFieldConfig.ProductIdToCategoryId = await GetProductDetailsConfiguration();
|
||||
|
||||
return customFieldConfig;
|
||||
}
|
||||
|
||||
public async Task<Dictionary<string, string>> GetProductDetailsConfiguration()
|
||||
{
|
||||
Dictionary<string, string> mappingList = [];
|
||||
|
||||
try
|
||||
{
|
||||
var configurationRequest = new ConfigurationRequestBuilder(_getProductDetailsString, _settings);
|
||||
|
||||
var response = await _crifService.SendMessage(configurationRequest.Build());
|
||||
|
||||
mappingList = _productDetailsResponseParser.Parse(response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Fatal("Error parsing CRIF custom fields configuration response." + ex.StackTrace);
|
||||
}
|
||||
|
||||
return mappingList;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user