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; } } }