585 lines
26 KiB
C#
585 lines
26 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using LCU.API.Collections.CollectionsApiLib.Models;
|
|
using LCU.API.Collections.RepoApi.DataAccess;
|
|
using LCU.API.Collections.RepoApi.Domain.Processing;
|
|
using LCU.API.Collections.RepoApi.Exceptions;
|
|
using LCU.API.Collections.RepoApi.Models.Results;
|
|
using LCU.Shared.Collections.RepoApiLib.Models;
|
|
using LCU.Shared.Collections.RepoApiLib.Models.Consumer;
|
|
using LCU.Shared.Collections.RepoApiLib.Models.Settings;
|
|
using Serilog;
|
|
|
|
namespace LCU.API.Collections.RepoApi.Services.Producer
|
|
{
|
|
public class RepoAccountProcessorService : IRepoAccountProcessorService
|
|
{
|
|
private const string RedeemedStatus = "REDEEMED";
|
|
private const string PaidSkipStatus = "PSKP";
|
|
private const string RepoCancelledStatus = "RECA";
|
|
public const string WrittenOff = "Written Off";
|
|
public const string SixtyPLusUserAssignedLabel = "SixtyPlus User Assigned";
|
|
private readonly ICoreDao _coreDao;
|
|
private readonly IRedemptionExpiredDateCalculator _redemptionExpiredDateCalculator;
|
|
private readonly IAccountAlertCheckService _accountAlertCheckService;
|
|
private readonly IEventAlertService _eventAlertService;
|
|
private readonly IRepoCompanySelectionService _repoCompanySelectionService;
|
|
|
|
public RepoAccountProcessorService(ICoreDao coreDao,
|
|
IRedemptionExpiredDateCalculator redemptionExpiredDateCalculator,
|
|
IAccountAlertCheckService accountAlertCheckService,
|
|
IEventAlertService eventAlertService, IRepoCompanySelectionService repoCompanySelectionService)
|
|
{
|
|
_coreDao = coreDao;
|
|
_redemptionExpiredDateCalculator = redemptionExpiredDateCalculator;
|
|
_accountAlertCheckService = accountAlertCheckService;
|
|
_eventAlertService = eventAlertService;
|
|
_repoCompanySelectionService = repoCompanySelectionService;
|
|
}
|
|
|
|
// This process determined from the original batch code. (LCU.CollectionRepossessionTracking::IntellecRepoImport)
|
|
// -> A) Get XP/Core/Apex Account
|
|
// -> B) Get XP/Core/Apex Loan
|
|
// -> B.1) Fields needed: Branch, Next due date
|
|
// ---> If it can't find a loan, it does nothing... what do we WANT do?
|
|
// -> C) Get XP/Core/Apex Loan Collateral
|
|
// ---> If there is no collateral, it does nothing... what do we WANT do?
|
|
// -> D) Get XP/Core/Apex Borrowers (Individuals)
|
|
// ---> No borrowers throws an exception? ... what do we WANT do?
|
|
// -> E) Create Repo Account from Loan, Collateral, Borrowers and Temenos Account
|
|
public RepoAccount CreateRepoAccount(TemenosAccount account, TemenosCase recoveryCase, LoanDetail loanDetail)
|
|
{
|
|
var collateralDetailRequest = _coreDao.RetrieveCollateralAsync(account.AccountIdentifier);
|
|
|
|
var collateralDetail = collateralDetailRequest.GetAwaiter().GetResult();
|
|
if (collateralDetail == null || !collateralDetail.Any())
|
|
{
|
|
throw new AccountCreationFailed(
|
|
$"Repo-Account Not Created using Account with AccountNo: {account.AccountIdentifier}. No Collateral.");
|
|
}
|
|
|
|
var borrowers = ConstructRepoAccountBorrowers(loanDetail);
|
|
if (borrowers == null || !borrowers.Any())
|
|
{
|
|
throw new AccountCreationFailed(
|
|
$"Repo-Account Not Created using Account with AccountNo: {account.AccountIdentifier}. No Borrowers.");
|
|
}
|
|
|
|
var repoAccount = ConstructRepoAccountFromParts(loanDetail, account, recoveryCase);
|
|
repoAccount.Borrowers = borrowers;
|
|
repoAccount.Collaterals = ConstructCollateralFromDetails(collateralDetail);
|
|
TryUpdateCollateralRetitleDate(repoAccount, recoveryCase);
|
|
|
|
Log.Information($"Created Repo-Account for Not-Found Account. AccountNo: {account.AccountIdentifier}");
|
|
return repoAccount;
|
|
}
|
|
|
|
public List<Borrower> ConstructRepoAccountBorrowers(LoanDetail coreAccount)
|
|
{
|
|
List<Borrower> borrowers = new List<Borrower>();
|
|
try
|
|
{
|
|
foreach (var coreAccountBorrower in coreAccount.Borrowers)
|
|
{
|
|
var borrower = new Borrower()
|
|
{
|
|
IndividualName = coreAccountBorrower.Name,
|
|
IndividualId = coreAccountBorrower.IndividualId.ToString(),
|
|
OwnershipType = (int)ConvertBorrowerType(coreAccountBorrower.Type)
|
|
};
|
|
borrowers.Add(borrower);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error(ex, "Error in ConstructRepoAccountBorrowers");
|
|
}
|
|
|
|
return borrowers;
|
|
}
|
|
|
|
public List<Collateral> ConstructCollateralFromDetails(IReadOnlyCollection<CollateralDetail> collateralDetail)
|
|
{
|
|
List<Collateral> collateralList = new List<Collateral>();
|
|
foreach (var detail in collateralDetail)
|
|
{
|
|
var collateral = new Collateral()
|
|
{
|
|
BodyStyle = null,
|
|
CollateralTypeId = null,
|
|
Description = detail.Description,
|
|
Inoperable = null,
|
|
RefCollateralId = detail.CollateralId.ToString()
|
|
};
|
|
if (detail.Other != null)
|
|
{
|
|
collateral.Vin = detail.Other.MiscellaneousInformation;
|
|
}
|
|
|
|
if (detail.Vehicle != null)
|
|
{
|
|
collateral.Make = detail.Vehicle.Make;
|
|
collateral.Model = detail.Vehicle.Model;
|
|
collateral.Vin = detail.Vehicle.VIN;
|
|
collateral.Year = detail.Vehicle.Year;
|
|
collateral.BodyStyle = detail.Vehicle.BodyStyle;
|
|
}
|
|
|
|
collateralList.Add(collateral);
|
|
}
|
|
|
|
return collateralList;
|
|
}
|
|
|
|
public RepoAccount ConstructRepoAccountFromParts(LoanDetail coreAccount, TemenosAccount account,
|
|
TemenosCase recoveryCase)
|
|
{
|
|
DateTime? lastPaymentDate = null;
|
|
DateTime? dateFirstDelinquent = null;
|
|
|
|
var lastPaymentResult = GetDateTimeFromString(account.DateLastPaid);
|
|
if (lastPaymentResult.IsSuccess)
|
|
{
|
|
lastPaymentDate = lastPaymentResult.Value;
|
|
}
|
|
else
|
|
{
|
|
Log.Warning(
|
|
$"Construct Repo Account from temenos accountNo: {account.AccountNumber}. Could not parse last payment result : {account.DateLastPaid}.",
|
|
lastPaymentResult, account);
|
|
}
|
|
|
|
|
|
var dateFirstDelinquentResult = GetDateTimeFromString(account.DateFirstDelinquent);
|
|
if (dateFirstDelinquentResult.IsSuccess)
|
|
{
|
|
dateFirstDelinquent = dateFirstDelinquentResult.Value;
|
|
}
|
|
else
|
|
{
|
|
Log.Warning(
|
|
$"Construct Repo Account from temenos accountNo: {account.AccountNumber}. failed parsing dateFirstDelinquent {account.DateFirstDelinquent}",
|
|
dateFirstDelinquentResult, account);
|
|
// This is no longer a "MissingRequirementException", per Bill Johns.
|
|
}
|
|
|
|
var sixtyPlusUserAssignedNumber = GetSixtyPlusUserNumber(account);
|
|
|
|
var repoAccount = new RepoAccount()
|
|
{
|
|
DueToPayDate = coreAccount.NextDueDate,
|
|
Balance = account.Balance,
|
|
AccountTypeCode = account.AccountType.Code,
|
|
OrigAccountTypeCode = account.AccountType.Code,
|
|
LoanNo = long.Parse(account.AccountIdentifier),
|
|
MemberNo = MemberIdFromAccountId(account.AccountIdentifier),
|
|
Branch = account.Branch != null ? int.Parse(account.Branch) : 0,
|
|
AccountNo = account.AccountIdentifier,
|
|
Status = StatusService.ConvertStatus(recoveryCase.RepoStatus),
|
|
O4RDate = recoveryCase.CreatedDate,
|
|
Collector = account.LoanOfficer,
|
|
DateFirstDelinquent = dateFirstDelinquent,
|
|
DelinquentAmount = account.DQAmount,
|
|
CurrentDelinquentAmount = account.DQAmount,
|
|
SubStatus = "",
|
|
DaysDelinquent = account.DaysDq,
|
|
LastPaymentDate = lastPaymentDate,
|
|
LstPmtAmt = account.AmountLastPaid,
|
|
OrigAmount = account.OriginalLoanAmount,
|
|
RequiredPaymentAmount = account.DQAmount,
|
|
PrimaryIndividualId = coreAccount.IndividualId[0].ToString(),
|
|
Bankruptcy = $"{account.BankruptcyFlag}",
|
|
DateFirstIntellect = recoveryCase.CreatedDate,
|
|
ReferenceId = account.AccountId,
|
|
ReferenceCaseId = recoveryCase.CaseId,
|
|
AccountLastProcessed = DateTime.Now,
|
|
ReferenceStatus = account.AccountStatus,
|
|
WrittenOffDate = coreAccount.Status == WrittenOff ? coreAccount.WrittenOffDate : (DateTime?)null,
|
|
SixtyPlusCollectorId = sixtyPlusUserAssignedNumber
|
|
};
|
|
|
|
return repoAccount;
|
|
}
|
|
|
|
public long MemberIdFromAccountId(string accountId)
|
|
{
|
|
return _coreDao.RetrieveMemberAsync(accountId).GetAwaiter().GetResult().MemberId;
|
|
}
|
|
|
|
public RepoAccount UpdateRepoAccountFromParts(RepoAccountProcessingSlip slip)
|
|
{
|
|
RepoAccount originalRepoAccount = slip.ExistingRepoAccount;
|
|
TemenosAccount account = slip.RecoveryAccount;
|
|
TemenosCase recoveryCase = slip.RecoveryCase;
|
|
IReadOnlyCollection<RepoLetter> letters = slip.Letters;
|
|
var redemptionExpiredDate = _redemptionExpiredDateCalculator.CalculateAsync(recoveryCase, letters);
|
|
|
|
DateTime? lastPaymentDate = null;
|
|
DateTime? dateFirstDelinquent = originalRepoAccount.DateFirstDelinquent;
|
|
|
|
var lastPaymentResult = GetDateTimeFromString(account.DateLastPaid);
|
|
if (lastPaymentResult.IsSuccess)
|
|
{
|
|
lastPaymentDate = lastPaymentResult.Value;
|
|
}
|
|
else
|
|
{
|
|
Log.Warning(
|
|
$"Repo account {originalRepoAccount.RepoId} ({originalRepoAccount.AccountNo}). Could not parse last payment result : {account.DateLastPaid}.",
|
|
lastPaymentResult);
|
|
}
|
|
|
|
var dateFirstDelinquentResult = GetDateTimeFromString(account.DateFirstDelinquent);
|
|
if (dateFirstDelinquentResult.IsSuccess)
|
|
{
|
|
dateFirstDelinquent = dateFirstDelinquentResult.Value;
|
|
}
|
|
else
|
|
{
|
|
Log.Error(
|
|
$"Repo account {originalRepoAccount.RepoId} ({originalRepoAccount.AccountNo}) failed parsing dateFirstDelinquent {account.DateFirstDelinquent}",
|
|
dateFirstDelinquentResult);
|
|
// This is no longer a "MissingRequirementException", per Bill Johns.
|
|
}
|
|
|
|
var sixtyPlusUserAssignedNumber = GetSixtyPlusUserNumber(account);
|
|
|
|
var repoAccount = new RepoAccount()
|
|
{
|
|
RepoId = originalRepoAccount.RepoId,
|
|
DueToPayDate = account.DueDate,
|
|
Balance = account.Balance,
|
|
AccountTypeCode = account.AccountType.Code,
|
|
OrigAccountTypeCode = originalRepoAccount.OrigAccountTypeCode,
|
|
LoanNo = originalRepoAccount.LoanNo,
|
|
MemberNo = originalRepoAccount.MemberNo,
|
|
Branch = originalRepoAccount.Branch,
|
|
AccountNo = originalRepoAccount.AccountNo,
|
|
Status = StatusService.ConvertStatus(recoveryCase.RepoStatus),
|
|
O4RDate = originalRepoAccount.O4RDate,
|
|
Collector = account.LoanOfficer,
|
|
DateFirstDelinquent = dateFirstDelinquent,
|
|
DelinquentAmount = account.DQAmount,
|
|
CurrentDelinquentAmount = account.DQAmount,
|
|
SubStatus = "",
|
|
DaysDelinquent = originalRepoAccount.DaysDelinquent, //leave this set to days delinquent when added.
|
|
LastPaymentDate = lastPaymentDate,
|
|
LstPmtAmt = account.AmountLastPaid ?? 0,
|
|
OrigAmount = account.OriginalLoanAmount ?? 0,
|
|
RedemptionExpiredDate = redemptionExpiredDate,
|
|
RequiredPaymentAmount = account.DQAmount,
|
|
PrimaryIndividualId = originalRepoAccount.PrimaryIndividualId,
|
|
Bankruptcy = $"{account.BankruptcyFlag}",
|
|
Collaterals = originalRepoAccount.Collaterals,
|
|
RepoStatusChanges = originalRepoAccount.RepoStatusChanges,
|
|
ManualRedemptionDate = originalRepoAccount.ManualRedemptionDate,
|
|
DateFirstIntellect = originalRepoAccount.DateFirstIntellect,
|
|
Borrowers = originalRepoAccount.Borrowers,
|
|
PaidSkipAmount = originalRepoAccount.PaidSkipAmount,
|
|
RefundStatus = originalRepoAccount.RefundStatus,
|
|
ReferenceId = account.AccountId,
|
|
ReferenceCaseId = recoveryCase.CaseId,
|
|
AccountLastProcessed = DateTime.Now,
|
|
ReferenceStatus = account.AccountStatus,
|
|
WrittenOffDate = slip.Loan.Status == WrittenOff ? slip.Loan.WrittenOffDate : (DateTime?)null,
|
|
SixtyPlusCollectorId = sixtyPlusUserAssignedNumber
|
|
};
|
|
|
|
return repoAccount;
|
|
}
|
|
|
|
/**
|
|
* High Risk function because of string comparison and unknown mapping.
|
|
* The old system got the integer from the database.
|
|
* The new system gets a string from the web service.
|
|
* This maps the new string to the old integer, if borrower types start
|
|
* showing up wrong, look here...
|
|
*/
|
|
public OwnershipType ConvertBorrowerType(string type)
|
|
{
|
|
if (type != null && string.Equals(type.Trim(), "Borrower", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
return OwnershipType.Borrower;
|
|
}
|
|
|
|
if (type != null && string.Equals(type.Trim(), "Co-Borrower", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
return OwnershipType.Coborrower;
|
|
}
|
|
|
|
return OwnershipType.Other;
|
|
}
|
|
|
|
public void CheckForRejectedStatusChange(RepoAccount originalRepoAccount, RepoAccount updatedRepoAccount,
|
|
Settings settings)
|
|
{
|
|
if (!IsStatusMatch(originalRepoAccount, updatedRepoAccount.Status) &&
|
|
!IsStatusChangeAllowed(originalRepoAccount.Status, updatedRepoAccount.Status,
|
|
settings.AllowedStatusChanges))
|
|
{
|
|
Log.Warning(
|
|
$"Status Change Reverted for Account {updatedRepoAccount.AccountNo} from {originalRepoAccount.Status} to {updatedRepoAccount.Status}");
|
|
|
|
_accountAlertCheckService.ManualAlert(new EventAlert()
|
|
{
|
|
RepoId = updatedRepoAccount.RepoId,
|
|
AccountNo = updatedRepoAccount.AccountNo,
|
|
CreatedBy = "Importer",
|
|
DateAdded = DateTime.Now,
|
|
Message = "Collections System Status Does Not Match Repo Management",
|
|
SubMessage =
|
|
$"Invalid Status Change from {originalRepoAccount.Status} to {updatedRepoAccount.Status}"
|
|
});
|
|
updatedRepoAccount.Status = originalRepoAccount.Status;
|
|
}
|
|
}
|
|
|
|
public bool IsStatusChangeAllowed(string oldStatus, string newStatus,
|
|
IEnumerable<AllowedStatusChange> settingsAllowedStatusChanges)
|
|
{
|
|
foreach (var allowedStatusChange in settingsAllowedStatusChanges)
|
|
{
|
|
if (IsStringMatch(allowedStatusChange.CurrentStatus, oldStatus) &&
|
|
IsStringMatch(allowedStatusChange.AllowedChangeStatus, newStatus))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public bool IsStatusMatch(RepoAccount repo, string status)
|
|
{
|
|
if (repo?.Status == null || status == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return string.Equals(repo.Status.Trim(), status.Trim(), StringComparison.OrdinalIgnoreCase);
|
|
}
|
|
|
|
public bool IsStringMatch(string x, string y)
|
|
{
|
|
if (x == null || y == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return string.Equals(x.Trim(), y.Trim(), StringComparison.OrdinalIgnoreCase);
|
|
}
|
|
|
|
public void UpdateRepoAccountDateClosed(RepoAccount repoAccount)
|
|
{
|
|
// Close the account after four days in certain statuses
|
|
if ((repoAccount.Status == PaidSkipStatus || repoAccount.Status == RedeemedStatus || repoAccount.Status == RepoCancelledStatus)
|
|
&& repoAccount.RepoStatusChanges.LastOrDefault(x => x.StatusTo == repoAccount.Status)?.ChangedDate <
|
|
DateTime.Now.AddDays(-3).Date)
|
|
{
|
|
repoAccount.DateClosed = DateTime.Now;
|
|
repoAccount.AccountLastProcessed = DateTime.Now;
|
|
// TODO calling this still has a side effect.
|
|
_eventAlertService.MarkAllAsRead(repoAccount.AccountNo).GetAwaiter().GetResult();
|
|
}
|
|
}
|
|
|
|
public void TryUpdateCollateralRetitleDate(RepoAccount repo, TemenosCase temenosCase)
|
|
{
|
|
DateTime? retitledDate = (temenosCase.TitleOrdered) ? temenosCase.TitleOrderedDate : null;
|
|
|
|
foreach (Collateral collateral in repo.Collaterals)
|
|
{
|
|
collateral.RetitledInLandmarkName = retitledDate;
|
|
}
|
|
}
|
|
|
|
// This exists to update accounts not originally created from Temenos
|
|
public void AddAccountUpdateRecord(RepoAccountProcessingSlip slip)
|
|
{
|
|
slip.ExistingRepoAccount.ReferenceId = slip.RecoveryAccount.AccountId;
|
|
slip.ExistingRepoAccount.ReferenceCaseId = slip.RecoveryCase.CaseId;
|
|
slip.ExistingRepoAccount.AccountLastProcessed = DateTime.Now;
|
|
}
|
|
|
|
public void TryUpdateOrCreateRepoCompanyAssignment(RepoAccount repoAccount, TemenosCase temenosCase,
|
|
Settings settings)
|
|
{
|
|
//Temenos may send blank string instead of null
|
|
var repoCompanyIdFromCase = string.IsNullOrEmpty(temenosCase.RepoAgentId)
|
|
? null
|
|
: MapRepoAgentIdToRepoCompanyId(temenosCase.RepoAgentId, settings.RepoCompanies);
|
|
|
|
foreach (var collateral in repoAccount.Collaterals)
|
|
{
|
|
var mostRecent = collateral.RepoCompanySelections.OrderByDescending(x => x.DateTimeCreated)
|
|
.FirstOrDefault();
|
|
|
|
// TODO, move to Slip, save elsewhere.
|
|
var updated =
|
|
UpdateOrCreateRepoCompanyAssignment(collateral, mostRecent, temenosCase, repoCompanyIdFromCase);
|
|
|
|
// This can no longer happen, but watch for it anyway.
|
|
if (updated.Any(repoCompanySelection =>
|
|
repoCompanySelection.DateRepoed != null &&
|
|
repoCompanySelection.RepoCompanyAssignmentDate == null))
|
|
{
|
|
Log.Error(
|
|
$"Tried to set DateRepoed before RepoCompanyAssignment for accountNo {repoAccount.AccountNo}. Please Investigate.");
|
|
throw new MissingRequirementException(
|
|
$"RepoCompanyAssignment for repo account {repoAccount.AccountNo} Missing RepoCompanyAssignmentDate",
|
|
$"Cannot assign a DateRepoed before a RepoCompanyAssignment Date.");
|
|
}
|
|
|
|
if (updated.Any())
|
|
{
|
|
_repoCompanySelectionService.SaveChangesAsync(updated).GetAwaiter().GetResult();
|
|
}
|
|
}
|
|
}
|
|
|
|
public List<RepoCompanySelection> UpdateOrCreateRepoCompanyAssignment(Collateral collateral, RepoCompanySelection mostRecentSelection,
|
|
TemenosCase temenosCase, int? repoCompanyIdFromCase)
|
|
{
|
|
var selectionUpdates = new List<RepoCompanySelection>();
|
|
//If this is the first repoCompanySelection create when temenos has data
|
|
if (mostRecentSelection == null)
|
|
{
|
|
if (temenosCase.RepoAgentId != null && temenosCase.RepoType != null &&
|
|
temenosCase.DateRepoAssigned != null)
|
|
{
|
|
var newRepoCompanyEntry = CreateNewRepoCompanyAssignment(collateral, temenosCase, repoCompanyIdFromCase);
|
|
collateral.RepoCompanySelections = collateral.RepoCompanySelections.Append(newRepoCompanyEntry).ToList();
|
|
selectionUpdates.Add(newRepoCompanyEntry);
|
|
}
|
|
|
|
return selectionUpdates;
|
|
}
|
|
|
|
//If the repoCompany has changed update with temenos data
|
|
if (mostRecentSelection.RepoCompanyId != repoCompanyIdFromCase ||
|
|
mostRecentSelection.RepoType != temenosCase.RepoType ||
|
|
mostRecentSelection.RepoCompanyAssignmentDate != temenosCase.DateRepoAssigned)
|
|
{
|
|
if (mostRecentSelection.DateRepoed == null)
|
|
{
|
|
mostRecentSelection.DateRepoed = DateTime.Now;
|
|
if (mostRecentSelection.RepoCompanyAssignmentDate == null)
|
|
{
|
|
mostRecentSelection.RepoCompanyAssignmentDate = mostRecentSelection.DateTimeCreated ?? DateTime.Now;
|
|
}
|
|
|
|
selectionUpdates.Add(mostRecentSelection);
|
|
}
|
|
|
|
var newRepoCompanyEntry = CreateNewRepoCompanyAssignment(collateral, temenosCase, repoCompanyIdFromCase);
|
|
collateral.RepoCompanySelections = collateral.RepoCompanySelections.Append(newRepoCompanyEntry).ToList();
|
|
selectionUpdates.Add(newRepoCompanyEntry);
|
|
|
|
return selectionUpdates;
|
|
}
|
|
|
|
//If no need to update or create, sync Repoed Date
|
|
mostRecentSelection.DateRepoed = temenosCase.DateRepossessed;
|
|
selectionUpdates.Add(mostRecentSelection);
|
|
|
|
return selectionUpdates;
|
|
}
|
|
|
|
public RepoCompanySelection CreateNewRepoCompanyAssignment(Collateral collateral, TemenosCase temenosCase, int? newRepoCompanyId)
|
|
{
|
|
// DateRepoAssigned is defaulted to Today. The business (Bill) doesn't want it to throw, if they start having trouble
|
|
// with the dates; change this to throw a MissingRequirementException on the field.
|
|
var newRepoCompanySelection = new RepoCompanySelection()
|
|
{
|
|
RepoCompanyId = newRepoCompanyId,
|
|
RepoType = temenosCase.RepoType ?? RepoType.Unknown,
|
|
RepoCompanyAssignmentDate = temenosCase.DateRepoAssigned ?? DateTime.Now,
|
|
DateRepoed = temenosCase.DateRepossessed,
|
|
CollateralId = collateral.CollateralId,
|
|
DateTimeCreated = DateTime.Now,
|
|
Id = null
|
|
};
|
|
|
|
return newRepoCompanySelection;
|
|
}
|
|
|
|
public int? MapRepoAgentIdToRepoCompanyId(string repoAgentId, IReadOnlyCollection<RepoCompany> repoCompanies)
|
|
{
|
|
try
|
|
{
|
|
var repoCompany =
|
|
repoCompanies.FirstOrDefault(company => company.ReferenceId == int.Parse(repoAgentId));
|
|
|
|
if (repoCompany != null)
|
|
{
|
|
return repoCompany.ID;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error(ex, $"Error when trying to map RepoAgentID: {repoAgentId} to a RepoCompany ReferenceID", repoCompanies);
|
|
}
|
|
|
|
// If you get this error, ensure there is a matching RepoCompany and that it has a RepoAgentID that matches the config call in Collections API.
|
|
throw new MissingRequirementException("RepoCompanyAssignment - RepoCompanyID", $"Ensure a RepoCompany with RepoAgentID: {repoAgentId} is present");
|
|
}
|
|
|
|
public IResult<DateTime?> GetDateTimeFromString(string dtString)
|
|
{
|
|
if (string.IsNullOrEmpty(dtString))
|
|
{
|
|
Log.Error("Cannot parse null or empty date string");
|
|
return new DateTimeResult()
|
|
{
|
|
IsSuccess = false,
|
|
ErrorMessage = "Cannot Parse Empty Date String",
|
|
};
|
|
}
|
|
|
|
try
|
|
{
|
|
return new DateTimeResult()
|
|
{
|
|
IsSuccess = true,
|
|
Value = DateTime.Parse(dtString)
|
|
};
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error(ex, $"Cannot Parse Date String {dtString}");
|
|
return new DateTimeResult()
|
|
{
|
|
IsSuccess = false,
|
|
ErrorMessage = $"There was an Exception when processing the date string: {dtString}"
|
|
};
|
|
}
|
|
}
|
|
|
|
public int? GetSixtyPlusUserNumber(TemenosAccount account)
|
|
{
|
|
try
|
|
{
|
|
account.CustomFieldMap.TryGetValue(SixtyPLusUserAssignedLabel, out string sixtyPlusUser);
|
|
if (String.IsNullOrWhiteSpace(sixtyPlusUser))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
Int32.TryParse(sixtyPlusUser, out int sixtyPlusUserNumber);
|
|
|
|
return sixtyPlusUserNumber;
|
|
}
|
|
catch(NullReferenceException nullEx)
|
|
{
|
|
Log.Warning($"60+ Collector key not found in Temenos Account for Account Number: {account.AccountNumber}. Error: {nullEx}");
|
|
return null;
|
|
}
|
|
catch(Exception ex)
|
|
{
|
|
Log.Error($"Error while attempting to Parse 60+ Collector ID for Account Number: {account.AccountNumber}. Error: {ex}");
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
} |