Exemple #1
0
		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
Exemple #4
0
 // 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;
 }