private void SendMail(string subject, NL_LoanHistory history, List<NL_LoanFees> fees, List<NL_LoanSchedules> schedule, List<NL_LoanAgreements> agreements) { string emailToAddress = CurrentValues.Instance.Environment.Value.Contains("Dev") ? "*****@*****.**" : CurrentValues.Instance.EzbobTechMailTo; string emailFromName = CurrentValues.Instance.MailSenderName; string emailFromAddress = CurrentValues.Instance.MailSenderEmail; string sMsg = string.Format("{0}. cust {1} user {2}, oldloan {3}, LoanID {4} error: {5}", subject, model.CustomerID, model.UserID, model.Loan.OldLoanID, LoanID, string.IsNullOrEmpty(Error) ? "No error" : Error); history.Schedule.Clear(); history.Schedule = schedule; history.Agreements.Clear(); history.Agreements = agreements; model.Loan.Histories.Clear(); model.Loan.Histories.Add(history); model.Loan.Fees.Clear(); model.Loan.Fees = fees; model.Loan.Payments.AddRange(DB.Fill<NL_Payments>("NL_PaymentsGet", CommandSpecies.StoredProcedure, new QueryParameter("@LoanID", LoanID))); if (model.Loan.Payments.Count > 0) { List<NL_LoanFeePayments> fps = DB.Fill<NL_LoanFeePayments>("NL_LoanFeePaymentsGet", CommandSpecies.StoredProcedure, new QueryParameter("@LoanID", LoanID)); List<NL_LoanSchedulePayments> schp = DB.Fill<NL_LoanSchedulePayments>("NL_LoanSchedulePaymentsGet", CommandSpecies.StoredProcedure, new QueryParameter("@LoanID", LoanID)); foreach (NL_Payments p in model.Loan.Payments) { p.SchedulePayments.AddRange(schp.Where(sp => sp.PaymentID == p.PaymentID).ToList()); p.FeePayments.AddRange(fps.Where(fp => fp.PaymentID == p.PaymentID).ToList()); } } var message = string.Format( "<h5>{0}</h5>" + "<h5>Loan</h5> <pre>{1}</pre>" + "<h5>FundTransfer</h5> <pre>{2}</pre>", HttpUtility.HtmlEncode(sMsg) , HttpUtility.HtmlEncode(model.Loan.ToString()) , HttpUtility.HtmlEncode(model.FundTransfer == null ? "no FundTransfer specified" : model.FundTransfer.ToString())); new Mail().Send( emailToAddress, null, // message text message, //html emailFromAddress, // fromEmail emailFromName, // fromName subject ); } // SendMail
} // constructor /// <exception cref="OverflowException">Condition. </exception> public virtual void Execute() { // not accepted rollover if (Calculator.acceptedRollover.Rollover == null) { Log.Alert("RolloverRescheduling: no accepted rollover"); return; } // not accepted rollover if (!Calculator.acceptedRollover.Rollover.IsAccepted || !Calculator.acceptedRollover.Rollover.CustomerActionTime.HasValue) { Log.Alert("RolloverRescheduling: rollover not accepted (paid). {0}", Calculator.acceptedRollover.Rollover); return; } // rollover proceeseed if (Calculator.acceptedRollover.Rollover.CustomerActionTime.Value.Date == Calculator.currentHistory.EventTime.Date || Calculator.acceptedRolloverProcessed) { Log.Debug("RolloverRescheduling: History ({0}) for rollover {1:d}, rolloverID {2} already exists", Calculator.currentHistory.LoanHistoryID, Calculator.acceptedRollover.Rollover.CustomerActionTime.Value, Calculator.acceptedRollover.Rollover.LoanRolloverID); return; } var rolloverPayment = Calculator.events.FirstOrDefault(p => p.Payment != null && p.Payment.PaymentTime.Date.Equals(Calculator.acceptedRollover.Rollover.CustomerActionTime.Value.Date) && p.Payment.PaymentDestination.Equals(NLPaymentDestinations.Rollover.ToString())); // rollover not paid if (rolloverPayment == null) { Log.Alert("RolloverRescheduling: rollover payment not found. {0}", Calculator.acceptedRollover.Rollover); return; } DateTime acceptionTime = Calculator.acceptedRollover.Rollover.CustomerActionTime.Value.Date; NL_LoanHistory lastHistory = WorkingModel.Loan.LastHistory(); // 1. create new history NL_LoanHistory newHistory = new NL_LoanHistory { LoanID = lastHistory.LoanID, LoanLegalID = lastHistory.LoanLegalID, AgreementModel = lastHistory.AgreementModel, Agreements = lastHistory.Agreements, InterestRate = lastHistory.InterestRate, RepaymentIntervalTypeID = lastHistory.RepaymentIntervalTypeID, UserID = WorkingModel.CustomerID, Description = "accept rollover", Amount = Calculator.currentOpenPrincipal, EventTime = acceptionTime }; RepaymentIntervalTypes intervalType = (RepaymentIntervalTypes)lastHistory.RepaymentIntervalTypeID; int removedItems = 0; newHistory.RepaymentDate = DateTime.MinValue; // 2. mark removed schedules + add new schedules foreach (NL_LoanSchedules s in Calculator.schedule.Where(s => s.PlannedDate >= acceptionTime)) { s.SetStatusOnRescheduling(); s.ClosedTime = acceptionTime; removedItems++; DateTime plannedDate = Calculator.AddRepaymentIntervals(1, s.PlannedDate, intervalType); if (newHistory.RepaymentDate.Equals(DateTime.MinValue)) { newHistory.RepaymentDate = plannedDate; } // add new schedule instead of removed NL_LoanSchedules newSchedule = new NL_LoanSchedules() { LoanScheduleID = 0, LoanScheduleStatusID = (int)NLScheduleStatuses.StillToPay, Position = s.Position, PlannedDate = plannedDate, Principal = s.Principal, // (s.Principal - s.PrincipalPaid), InterestRate = s.InterestRate, TwoDaysDueMailSent = false, //s.TwoDaysDueMailSent, FiveDaysDueMailSent = false, //s.FiveDaysDueMailSent }; Log.Debug("schedule {0} replaced by {1}", s, newSchedule); newHistory.Schedule.Add(newSchedule); } newHistory.RepaymentCount = removedItems; WorkingModel.Loan.Histories.Add(newHistory); //List<NL_LoanFees> replacedDistributedFees = new List<NL_LoanFees>(); bool distributedFees = false; // 3. mark removed distributed fees + add new distributed fees foreach (NL_LoanFees fee in Calculator.distributedFeesList.Where(f => f.AssignTime.Date >= acceptionTime)) { fee.DisabledTime = acceptionTime; fee.Notes = "disabled on rollover"; fee.DeletedByUserID = WorkingModel.UserID ?? 1; distributedFees = true; //NL_LoanFees newFee = new NL_LoanFees() { // LoanFeeID = 0, // Amount = fee.Amount, // AssignTime = Calculator.AddRepaymentIntervals(1, fee.AssignTime, intervalType), // LoanID = WorkingModel.Loan.LoanID, // LoanFeeTypeID = fee.LoanFeeTypeID, // AssignedByUserID = fee.AssignedByUserID, // CreatedTime = acceptionTime, // Notes = fee.Notes //}; //Log.Debug("fee {0} replaced by {1}", fee, newFee); //replacedDistributedFees.Add(newFee); } //Calculator.distributedFeesList.AddRange(replacedDistributedFees); //WorkingModel.Loan.Fees.AddRange(replacedDistributedFees); if (distributedFees) { // offer-fees NL_OfferFees offerFees = WorkingModel.Offer.OfferFees.FirstOrDefault(); if (offerFees != null && offerFees.DistributedPartPercent != null && (decimal)offerFees.DistributedPartPercent == 1) { var feeCalculator = new SetupFeeCalculator(offerFees.Percent, null); decimal servicingFeeAmount = feeCalculator.Calculate(newHistory.Amount).Total; decimal servicingFeePaidAmount = WorkingModel.Loan.Fees.Where(f => f.LoanFeeTypeID == (int)NLFeeTypes.ServicingFee).Sum(f => f.PaidAmount); Log.Debug("servicingFeeAmount: {0}, servicingFeePaidAmount: {1}", servicingFeeAmount, servicingFeePaidAmount); // new "spreaded" amount Calculator.AttachDistributedFeesToLoanBySchedule(WorkingModel, (servicingFeeAmount - servicingFeePaidAmount), acceptionTime); } } // TODO could be reseted at all?????????????? // reset paid amount for deleted/closed schedules and disabled distributed fees foreach (NL_Payments p in WorkingModel.Loan.Payments) { foreach (NL_LoanSchedulePayments sp in p.SchedulePayments) { foreach (NL_LoanSchedules s in Calculator.schedule.Where(s => s.IsDeleted())) { if (s.LoanScheduleID == sp.LoanScheduleID) { sp.ResetInterestPaid = sp.PrincipalPaid; sp.ResetPrincipalPaid = sp.PrincipalPaid; sp.PrincipalPaid = 0; sp.InterestPaid = 0; } } } foreach (NL_LoanFeePayments fp in p.FeePayments) { foreach (NL_LoanFees f in Calculator.distributedFeesList.Where(f => f.DisabledTime.Equals(acceptionTime))) { if (f.LoanFeeID == fp.LoanFeeID) { fp.ResetAmount = fp.Amount; fp.Amount = 0; f.PaidAmount -= (decimal)fp.ResetAmount; } } } } Calculator.acceptedRolloverProcessed = true; }
/* ValidateCustomer(cus); // continue (customer's data/status, finish wizard, bank account data) ValidateAmount(loanAmount, cus); // continue (loanAmount > customer.CreditSum) ValidateOffer(cus); // check offer validity dates - in AddLoan strategy ValidateLoanDelay(cus, now, TimeSpan.FromMinutes(1)); // checks if last loan was taken a minute before "now" - ?? to prevent multiple clicking on "create loan" button? ValidateRepaymentPeriodAndInterestRate(cus); */ // all validations moved to SP public override void Execute() { if (!CurrentValues.Instance.NewLoanRun) { NL_AddLog(LogType.Info, "NL disabled by configuration", null, null, null, null); return; } NL_AddLog(LogType.Info, "Strategy Start", this.strategyArgs, Result, Error, null); try { if (Result.CustomerID == 0) { Error = NL_ExceptionCustomerNotFound.DefaultMessage; Log.Error(Error); NL_AddLog(LogType.DataExsistense, "Failed", this.strategyArgs, Result, Error, null); return; } DataForLoan = DB.FillFirst<OfferForLoan>( "NL_SignedOfferForLoan", CommandSpecies.StoredProcedure, new QueryParameter("CustomerID", Result.CustomerID), new QueryParameter("Now", Result.Loan.LastHistory().EventTime) ); NL_AddLog(LogType.Info, "DataForLoan", this.strategyArgs, DataForLoan, Error, null); if (!string.IsNullOrEmpty(DataForLoan.Error)) { Error = DataForLoan.Error; Log.Info(Error); NL_AddLog(LogType.DataExsistense, "Failed", this.strategyArgs, Result, Error, null); return; } if (DataForLoan.OfferID == 0) { Error = NL_ExceptionOfferNotValid.DefaultMessage; Log.Info(Error); NL_AddLog(LogType.DataExsistense, "Failed", this.strategyArgs, Result, Error, null); return; } Log.Debug(DataForLoan.ToString()); if (DataForLoan.AvailableAmount < DataForLoan.LoanLegalAmount) { Error = string.Format("No available credit for current offer. New loan is not allowed. dataForLoan: {0} ", Result); // duplicate of ValidateAmount(loanAmount, cus); (loanAmount > customer.CreditSum) Log.Info(Error); NL_AddLog(LogType.Info, "Strategy Failed - No available credit for current offer. New loan is not allowed", this.strategyArgs, Result, Error, null); return; } /*** //CHECK "Enough Funds" (uncomment WHEN old BE REMOVED from \App\PluginWeb\EzBob.Web\Code\LoanCreator.cs, method CreateLoan method) VerifyEnoughAvailableFunds enoughAvailableFunds = new VerifyEnoughAvailableFunds(model.Loan.InitialLoanAmount); enoughAvailableFunds.Execute(); if (!enoughAvailableFunds.HasEnoughFunds) { Log.Alert("No enough funds for loan: customer {0}; offer {1}", model.CustomerID, dataForLoan.Offer.OfferID); } ****/ // from offer => Loan Result.Loan.OfferID = DataForLoan.OfferID; Result.Loan.LoanTypeID = DataForLoan.LoanTypeID; // if need a string: get description from NLLoanTypes Enum Result.Loan.LoanSourceID = DataForLoan.LoanSourceID; // EzbobBankAccountID - TODO Result.Loan.Position = DataForLoan.LoansCount; NL_LoanHistory history = Result.Loan.LastHistory(); // from offer => history initial/re-scheduling data history.InterestOnlyRepaymentCount = DataForLoan.InterestOnlyRepaymentCount; history.Amount = DataForLoan.LoanLegalAmount; history.RepaymentCount = DataForLoan.LoanLegalRepaymentPeriod; history.RepaymentIntervalTypeID = DataForLoan.RepaymentIntervalTypeID; history.InterestRate = DataForLoan.MonthlyInterestRate; history.LoanLegalID = DataForLoan.LoanLegalID; // from offer => Offer Result.Offer = new NL_Offers { BrokerSetupFeePercent = DataForLoan.BrokerSetupFeePercent, SetupFeeAddedToLoan = DataForLoan.SetupFeeAddedToLoan, OfferID = DataForLoan.OfferID }; // offer-fees Result.Offer.OfferFees = DB.Fill<NL_OfferFees>("NL_OfferFeesGet", CommandSpecies.StoredProcedure, new QueryParameter("OfferID", DataForLoan.OfferID)); //Result.Offer.OfferFees.ForEach(ff => Log.Debug(ff)); // discounts if (DataForLoan.DiscountPlanID > 0) { var discounts = DB.Fill<NL_DiscountPlanEntries>("NL_DiscountPlanEntriesGet", CommandSpecies.StoredProcedure, new QueryParameter("DiscountPlanID", DataForLoan.DiscountPlanID) ); foreach (NL_DiscountPlanEntries dpe in discounts) { Result.Offer.DiscountPlan.Add(Decimal.Parse(dpe.InterestDiscount.ToString(CultureInfo.InvariantCulture))); } //Log.Debug("Discounts");//Result.Offer.DiscountPlan.ForEach(d => Log.Debug(d)); } NL_AddLog(LogType.Info, "Strategy End", this.strategyArgs, Result, Error, null); } catch (Exception ex) { Log.Error(ex.Message); NL_AddLog(LogType.Error, "Failed", this.strategyArgs, Result, ex.ToString(), ex.StackTrace); } } // Execute
// history public LoanEvent(DateTime date, NL_LoanHistory history, int priority = 0) : this(new DateTime(date.Year, date.Month, date.Day, 00, 00, 00), priority) { History = history; }