} // ReBuild private AgreementModel GenerateAgreementModel(Customer customer, Loan loan, DateTime now, double apr) { var model = new AgreementModel(); model.Schedule = loan.Schedule.Select(LoanScheduleExtention.FromLoanScheduleItem).ToList(); model.CustomerEmail = customer.Name; model.FullName = customer.PersonalInfo.Fullname; model.TypeOfBusinessName = customer.PersonalInfo.TypeOfBusinessName; var businessType = customer.PersonalInfo.TypeOfBusiness; var company = customer.Company; CustomerAddress companyAddress = null; if (company != null) { switch (businessType.Reduce()) { case TypeOfBusinessReduced.Limited: model.CompanyNumber = company.ExperianRefNum ?? company.CompanyNumber; goto case TypeOfBusinessReduced.NonLimited; case TypeOfBusinessReduced.NonLimited: model.CompanyName = company.ExperianCompanyName ?? company.CompanyName; var experianCompanyAddress = company.ExperianCompanyAddress.LastOrDefault(); if (experianCompanyAddress != null && !String.IsNullOrEmpty(experianCompanyAddress.Postcode)) { companyAddress = company.ExperianCompanyAddress.LastOrDefault(); } else { companyAddress = company.CompanyAddress.LastOrDefault(); } break; } } model.CompanyAdress = companyAddress.GetFormatted(); model.PersonAddress = customer.AddressInfo.PersonalAddress.FirstOrDefault().GetFormatted(); CalculateTotal(loan.SetupFee, loan.Schedule.ToList(), model); model.CurentDate = FormattingUtils.FormatDateTimeToString(now); model.CurrentDate = now; model.FormattedSchedules = CreateSchedule(loan.Schedule.ToList()).ToList(); model.InterestRate = loan.InterestRate * 100; model.SetupFee = FormattingUtils.NumericFormats(loan.SetupFee); model.LatePaymentCharge = String.Format("{0:0.00}", Convert.ToInt32(ConfigManager.CurrentValues.Instance.LatePaymentCharge.Value)); model.AdministrationCharge = String.Format("{0:0.00}", Convert.ToInt32(ConfigManager.CurrentValues.Instance.AdministrationCharge.Value)); // According to new logic the setup fee is always percent and min setup fee is amount SetupFeeFixed decimal manualSetupFeePct; decimal brokerSetupFeePct; GetSetupFees(customer, loan, out manualSetupFeePct, out brokerSetupFeePct); bool shouldHaveSetupFee = (!loan.CashRequest.SpreadSetupFee.HasValue || !loan.CashRequest.SpreadSetupFee.Value) && ((manualSetupFeePct > 0) || (brokerSetupFeePct > 0)); this.log.Debug( "Customer {0} agreement model: spread setup fee '{1}', manual {2}, broker {3}.", customer.Id, loan.CashRequest.SpreadSetupFee == null ? "null" : (loan.CashRequest.SpreadSetupFee.Value ? "spread" : "no"), manualSetupFeePct.ToString("P2"), brokerSetupFeePct.ToString("P2") ); if (shouldHaveSetupFee) { decimal setupFeePercent = manualSetupFeePct + brokerSetupFeePct; model.SetupFeePercent = (setupFeePercent * 100).ToString(CultureInfo.InvariantCulture); model.SetupFeeAmount = FormattingUtils.NumericFormats((int)CurrentValues.Instance.SetupFeeFixed); } else { model.SetupFeePercent = "0"; model.SetupFeeAmount = FormattingUtils.NumericFormats(0); } // if model.IsBrokerFee = false; model.IsManualSetupFee = false; model.APR = apr; // var start = loan.Schedule.First().Date.AddMonths(-1); // var end = loan.Schedule.Last().Date; // var days = (end - start).TotalDays; //model.InterestRatePerDay = (model.Schedule.Count * model.InterestRate) / (decimal)days; model.InterestRatePerDay = model.Schedule[1].InterestRate / 30; // For first month model.InterestRatePerDayFormatted = string.Format("{0:0.00}", model.InterestRatePerDay); model.InterestRatePerYearFormatted = string.Format("{0:0.00}", model.InterestRate * 12); var loanType = customer.LastCashRequest.LoanType ?? new StandardLoanType(); model.LoanType = loanType.Type; model.TermOnlyInterest = loan.Schedule.Count(s => s.LoanRepayment == 0); model.TermOnlyInterestWords = FormattingUtils.ConvertToWord(model.TermOnlyInterest).ToLower(); model.TermInterestAndPrincipal = loan.Schedule.Count(s => s.LoanRepayment != 0 && s.Interest != 0); model.TermInterestAndPrincipalWords = FormattingUtils.ConvertToWord(model.TermInterestAndPrincipal).ToLower(); model.isHalwayLoan = loanType.IsHalwayLoan; model.CountRepayment = this.repaymentCalculator.CalculateCountRepayment(loan); model.Term = this.repaymentCalculator.CalculateCountRepayment(loan); model.TotalPrincipalWithSetupFee = FormattingUtils.NumericFormats(loan.Schedule.Sum(a => a.LoanRepayment) - loan.SetupFee); return model; } // GenerateAgreementModel
} // CalculateTotal /// <exception cref="OverflowException">The number of elements in is larger than <see cref="F:System.Int32.MaxValue" />.</exception> /// <exception cref="NullReferenceException"><paramref /> is null. </exception> /// <exception cref="NoScheduleException">Condition. </exception> public AgreementModel NL_BuildAgreementModel(Customer customer, NL_Model nlModel) { // fill in loan+history with offer data nlModel = this.serviceClient.Instance.BuildLoanFromOffer(this.context != null ? this.context.UserId : customer.Id, nlModel.CustomerID, nlModel).Value; ALoanCalculator nlCalculator = null; // 2. get Schedule and Fees try { // init calculator nlCalculator = new LegacyLoanCalculator(nlModel); // model should contain Schedule and Fees after this invocation nlCalculator.CreateSchedule(); // create primary dates/p/r/f distribution of schedules (P/n) and setup/servicing fees. 7 September - fully completed schedule + fee + amounts due, without payments. } catch (NoInitialDataException noDataException) { this.log.Alert("CreateSchedule failed: {0}", noDataException.Message); } catch (InvalidInitialAmountException amountException) { this.log.Alert("CreateSchedule failed: {0}", amountException.Message); } catch (InvalidInitialInterestRateException interestRateException) { this.log.Alert("CreateSchedule failed: {0}", interestRateException.Message); } catch (InvalidInitialRepaymentCountException paymentsException) { this.log.Alert("CreateSchedule failed: {0}", paymentsException.Message); } catch (Exception ex) { this.log.Alert("Failed to create Schedule for customer {0}, err: {1}", nlModel.CustomerID, ex); } finally { if (nlCalculator == null) { this.log.Alert("failed to get nlCalculator for customer: {0}", nlModel.CustomerID); } // if } // try var history = nlModel.Loan.LastHistory(); // no Schedule if (history.Schedule.Count == 0) { this.log.Alert("No Schedule. Customer: {0}", nlModel.CustomerID); return null; } var model = new AgreementModel() { Schedule = new List<LoanScheduleItemModel>() }; // fill in AgreementModel schedules list foreach (NL_LoanSchedules s in history.Schedule) { var item = new LoanScheduleItemModel { Id = s.LoanScheduleID, AmountDue = s.AmountDue, Date = s.PlannedDate, Interest = s.Interest, Status = Enum.GetName(typeof(NLScheduleStatuses), s.LoanScheduleStatusID).DescriptionAttr(), LoanRepayment = s.Principal, Balance = s.Balance, Fees = s.Fees, InterestRate = s.InterestRate }; item.StatusDescription = item.Status; model.Schedule.Add(item); } // for each model.CustomerEmail = customer.Name; model.FullName = customer.PersonalInfo.Fullname; model.TypeOfBusinessName = customer.PersonalInfo.TypeOfBusinessName; var businessType = customer.PersonalInfo.TypeOfBusiness; var company = customer.Company; CustomerAddress companyAddress = null; if (company != null) { switch (businessType.Reduce()) { case TypeOfBusinessReduced.Limited: model.CompanyNumber = company.ExperianRefNum ?? company.CompanyNumber; goto case TypeOfBusinessReduced.NonLimited; case TypeOfBusinessReduced.NonLimited: model.CompanyName = company.ExperianCompanyName ?? company.CompanyName; companyAddress = company.ExperianCompanyAddress.LastOrDefault() ?? company.CompanyAddress.LastOrDefault(); break; } // switch } // if model.CompanyAdress = companyAddress.GetFormatted(); model.PersonAddress = customer.AddressInfo.PersonalAddress.FirstOrDefault().GetFormatted(); // collect all setup/servicing "spreaded" fees List<NL_LoanFees> loanSetupFees = nlModel.Loan.Fees.Where(f => f.LoanFeeTypeID == (int)NLFeeTypes.SetupFee || f.LoanFeeTypeID == (int)NLFeeTypes.ServicingFee).ToList(); // get fees sum decimal totalFees = 0m; loanSetupFees.ForEach(f => totalFees += f.Amount); decimal totalPrincipal = model.Schedule.Sum(a => a.LoanRepayment); // formatted totals model.TotalAmount = FormattingUtils.NumericFormats(model.Schedule.Sum(a => a.AmountDue)); model.TotalPrincipal = FormattingUtils.NumericFormats(totalPrincipal); model.TotalInterest = FormattingUtils.NumericFormats(model.Schedule.Sum(a => a.Interest)); model.TotalAmoutOfCredit = model.TotalPrincipal; //FormattingUtils.NumericFormats(model.Schedule.Sum(a => a.LoanRepayment)); model.TotalFees = FormattingUtils.NumericFormats(totalFees); decimal currencyRate = GetUSDCurrencyRate(); model.TotalPrincipalUsd = "$ " + (CurrentValues.Instance.AlibabaCurrencyConversionCoefficient * currencyRate * totalPrincipal).ToString("N", CultureInfo.CreateSpecificCulture("en-gb")); model.CurentDate = FormattingUtils.FormatDateTimeToString(DateTime.UtcNow); model.CurrentDate = DateTime.UtcNow; model.FormattedSchedules = model.Schedule.Select((installment, i) => new FormattedSchedule { AmountDue = FormattingUtils.NumericFormats(installment.AmountDue), Principal = FormattingUtils.NumericFormats(installment.LoanRepayment), Interest = FormattingUtils.NumericFormats(installment.Interest), Fees = FormattingUtils.NumericFormats(installment.Fees), Date = FormattingUtils.FormatDateToString(installment.Date), StringNumber = FormattingUtils.ConvertingNumberToWords(i + 1), InterestRate = string.Format("{0:0.00}", installment.InterestRate * 100), Iterration = i + 1, }).ToList(); // TODO update from history? model.InterestRate = history.InterestRate * 100; model.SetupFee = FormattingUtils.NumericFormats(totalFees); model.SetupFeeAmount = FormattingUtils.NumericFormats((int)CurrentValues.Instance.SetupFeeFixed); model.SetupFeePercent = CurrentValues.Instance.SetupFeePercent; //// FEES TODO ////According to new logic the setup fee is always percent and min setup fee is amount SetupFeeFixed ???? if ((totalFees > 0) || (nlModel.Offer.BrokerSetupFeePercent.HasValue && nlModel.Offer.BrokerSetupFeePercent.Value > 0)) { decimal setupFeePercent = totalFees + nlModel.Offer.BrokerSetupFeePercent ?? 0M; model.SetupFeePercent = (setupFeePercent * 100).ToString(CultureInfo.InvariantCulture); } // if // TODO was is das? model.IsBrokerFee = false; model.IsManualSetupFee = false; if (nlCalculator != null) model.APR = nlCalculator.CalculateApr(history.EventTime); model.InterestRatePerDay = model.Schedule[1].InterestRate / 30; // For first month model.InterestRatePerDayFormatted = string.Format("{0:0.00}", model.InterestRatePerDay); model.InterestRatePerYearFormatted = string.Format("{0:0.00}", model.InterestRate * 12); model.LoanType = Enum.GetName(typeof(NLLoanTypes), nlModel.Loan.LoanTypeID); model.TermOnlyInterest = model.Schedule.Count(s => s.LoanRepayment == 0); model.TermOnlyInterestWords = FormattingUtils.ConvertToWord(model.TermOnlyInterest).ToLower(); model.TermInterestAndPrincipal = model.Schedule.Count(s => s.LoanRepayment != 0 && s.Interest != 0); model.TermInterestAndPrincipalWords = FormattingUtils.ConvertToWord(model.TermInterestAndPrincipal).ToLower(); model.isHalwayLoan = Enum.GetName(typeof(NLLoanTypes), nlModel.Loan.LoanTypeID) == NLLoanTypes.HalfWayLoanType.ToString(); model.CountRepayment = model.Schedule.Count; model.Term = model.Schedule.Count; model.TotalPrincipalWithSetupFee = FormattingUtils.NumericFormats(totalPrincipal - totalFees); return model; } // NL_BuildAgreementModel