public int SendNotification(SavingEvent savingEvent, OPaymentMethods paymentMethod) { if (person == null) { throw new ArgumentNullException("client"); } var messageTemplate = GetLocalizedActiveMessageTemplate("Client.LoanDisbursementNotification"); if (messageTemplate == null) { return(0); } SavingBookContract savingsContract = (SavingBookContract)SavingsService.GetSaving(savingEvent.ContracId); //tokens var tokens = new List <Token>(); MessageTokenProvider.AddPersonTokens(tokens, person); MessageTokenProvider.AddSavingEventTokens(tokens, savingEvent, savingsContract); tokens.Add(new Token("Messaging.CurrentDate", DateTime.Now.ToShortDateString())); tokens.Add(new Token("Messaging.CurrentTime", DateTime.Now.ToShortTimeString())); //event notification EventPublisher.MessageTokensAdded(messageTemplate, tokens); var emailAccount = GetEmailAccountOfMessageTemplate(messageTemplate); var toEmail = person.Email; var toName = person.FullName; return(SendNotification(messageTemplate, emailAccount, tokens, toEmail, toName)); }
public bool SetInstallmentAsPending(Installment installment, OPaymentMethods pPaymentMethod) { ClientServices clientServices = new ClientServices(_user); LoanServices loanServices = new LoanServices(_user); var client = clientServices.FindTiers(installment.ClientId, Octopus.Enums.OClientTypes.Person); var loan = loanServices.SelectLoan(installment.ContractId, true, true, true); loanServices.Repay(loan, client, installment.InstallmentNumber, installment.InstallmentDate, installment.InstallmentAmount, false, 0, 0, false, 0, true, pPaymentMethod, "", true); return true; }
private EventStock GenerateRepaymentEvents(CreditContractRepayment cCr, DateTime payDate, OCurrency penaltiesEvent, OCurrency commissionsEvent, OCurrency interestEvent, OCurrency interestPrepayment, OCurrency principalEvent, int pastDueDays, OPaymentType paymentType, bool isPending, int instNumber, OPaymentMethods paymentMethods) { RepaymentEvent rpEvent; EventStock listOfLoanEvents = new EventStock(); #region Event identification ////////////////////////////////////////////////////////////////////////////////////////////////////////// if (cCr.PaidIstallments.Count > 0) { foreach (Installment paidIstallment in cCr.PaidIstallments) { int number = paidIstallment.Number; OCurrency rpeCapital = 0; OCurrency rpeInterests = 0; OCurrency rpeCommission = 0; OCurrency rpePenalty = 0; int overdueDays = paidIstallment.ExpectedDate >= payDate ? 0 : pastDueDays; foreach (RepaymentEvent rpe in Events.GetLoanRepaymentEvents()) { if (rpe.InstallmentNumber == paidIstallment.Number && !rpe.Deleted) { if (rpe.RepaymentType != OPaymentType.PersonTotalPayment) { rpeCapital += rpe.Principal; rpeInterests += rpe.Interests; rpePenalty += rpe.Penalties; } rpeCommission += rpe.Commissions; if (rpe.RepaymentType == OPaymentType.PersonTotalPayment && cCr.LoanOptions.ManualCommissionAmount != 0) rpeCommission -= rpe.Commissions; } } if (rpeCapital > paidIstallment.PaidCapital) rpeCapital = 0; if (rpeInterests < 0) rpeInterests = 0; if (rpeInterests > paidIstallment.InterestsRepayment) { rpeInterests = 0; } OCurrency principalAmount = paidIstallment.CapitalRepayment - (paidIstallment.CapitalRepayment - (paidIstallment.PaidCapital - rpeCapital)); OCurrency interestAmount = paidIstallment.InterestsRepayment - (paidIstallment.InterestsRepayment - (paidIstallment.PaidInterests - rpeInterests)); principalEvent -= principalAmount; interestEvent -= interestAmount; if (principalAmount == 0 && interestAmount == 0 && paidIstallment.PaidCapital == 0) { principalAmount = principalEvent; interestAmount = interestEvent; } if (interestAmount < 0) interestAmount = 0; OCurrency commissionAmount = paidIstallment.CommissionsUnpaid - (paidIstallment.CommissionsUnpaid - (paidIstallment.PaidCommissions - rpeCommission)); OCurrency penaltyAmount = paidIstallment.FeesUnpaid - (paidIstallment.FeesUnpaid - (paidIstallment.PaidFees - rpePenalty)); //just to be sure that we do not have negative in the base penaltyAmount = penaltyAmount < 0 ? 0 : penaltyAmount; rpEvent = CreateRepaymentEvent(number, payDate, penaltyAmount, commissionAmount, interestAmount, interestAmount, principalAmount, overdueDays, _clientType == OClientTypes.Group, paymentType, isPending); rpEvent.PaymentMethod = paymentMethods; listOfLoanEvents.Add(rpEvent); } } else { rpEvent = CreateRepaymentEvent(instNumber, payDate, penaltiesEvent, commissionsEvent, interestEvent, interestPrepayment, principalEvent, pastDueDays, _clientType == OClientTypes.Group, paymentType, isPending); rpEvent.PaymentMethod = paymentMethods; listOfLoanEvents.Add(rpEvent); } #endregion return listOfLoanEvents; }
/// <summary> /// This method manages all the repayment cases implemented in OCTOPUS /// </summary> /// <param name="pNumber">pNumber of the installment paid</param> /// <param name="pDate">pDate of the payment</param> /// <param name="pAmountPaid">amount paid by the client which can be lower, equal or greater than the expected amount for an installment</param> /// <param name="cancelFees">when true, cancel anticipated payment Commission</param> /// <param name="manualFeesAmount">manual amount of commission (when anticipated payment commission are cancelled)</param> /// <returns>A RepaymentEvent or null if : /// - repayment amount lower than 0 /// - repayment amount greater than olb + interestsToPay + commission /// - installment already repaid /// - bad loan and past due days greater than 180 /// </returns> /// <param name="manualCommissionAmount"></param> /// <param name="disableInterests"></param> /// <param name="manualInterests"></param> /// <param name="keepExpectedInstallment"></param> /// <param name="paymentMethod"></param> /// <param name="comment"></param> /// <param name="pending"></param> public RepaymentEvent Repay(int pNumber, DateTime pDate, OCurrency pAmountPaid, bool cancelFees, OCurrency manualFeesAmount, OCurrency manualCommissionAmount, bool disableInterests, OCurrency manualInterests, bool keepExpectedInstallment, OPaymentMethods paymentMethod, string comment, bool pending) { OCurrency anticipatePayment = CalculateAnticipateInteresAmountForClosure(pDate, OPaymentType.PartialPayment) + CalculateTotalNonRepaymentPenalties(pDate); if (anticipatePayment >= pAmountPaid || (anticipatePayment == 0 && GetInstallment(pNumber - 1).ExpectedDate <= pDate)) { keepExpectedInstallment = true; } var cCo = new CreditContractOptions(Product.LoanType, keepExpectedInstallment, cancelFees, manualFeesAmount, manualCommissionAmount, disableInterests, manualInterests, Product.AnticipatedTotalRepaymentPenaltiesBase, Product.IsExotic); var cCr = new CreditContractRepayment(this, cCo, pDate, pNumber, _user, _generalSettings, _nwdS); if (AmountComparer.Compare(pAmountPaid, cCr.MaximumAmountAuthorizeToRepay, pNumber) > 0) { return null; } OCurrency principalEvent = 0; OCurrency interestEvent = 0; OCurrency interestPrepayment = 0; OCurrency penaltiesEvent = 0; OCurrency commissionsEvent = 0; OCurrency manualInterestEvent = cCo.ManualInterestsAmount; int pastDueDays = CalculatePastDueSinceLastRepayment(pDate); OPaymentType paymentType = OPaymentType.StandardPayment; foreach (Installment installment in InstallmentList) { if (!installment.IsRepaid && installment.Number == pNumber && !keepExpectedInstallment) { paymentType = OPaymentType.PartialPayment; } } //we have total repayment for a person if(EscapedMember != null) { paymentType = OPaymentType.PartialPayment; keepExpectedInstallment = false; cCo.KeepExpectedInstallments = false; } if (AmountComparer.Compare(pAmountPaid, cCr.MaximumAmountAuthorizeToRepay, pNumber) == 0 && !keepExpectedInstallment) { paymentType = OPaymentType.TotalPayment; } cCr.Repay(pAmountPaid, ref penaltiesEvent, ref commissionsEvent, ref interestEvent, ref interestPrepayment, ref principalEvent, ref manualInterestEvent, paymentType); //this part of code to correct calculation of principal OCurrency principalAmount = principalEvent; foreach (RepaymentEvent rPayment in Events.GetRepaymentEvents()) { if (!rPayment.Deleted) principalAmount += rPayment.Principal; if (principalAmount > Amount) { principalEvent -= Math.Round(principalAmount.Value, 2) - Amount; } } // when we keep initial schedule and total payment if (AmountComparer.Compare(pAmountPaid, cCr.MaximumAmountAuthorizeToRepay, pNumber) == 0 && (pNumber != InstallmentList.Count) && AllInstallmentsRepaid) { paymentType = OPaymentType.TotalPayment; } ////////////////////////////////////////////////////////////// RepaymentEvent rPe = CreateRepaymentEvent(pNumber, pDate, penaltiesEvent, commissionsEvent, interestEvent, interestPrepayment, principalEvent, pastDueDays, _clientType == OClientTypes.Group, paymentType, pending); if (AllInstallmentsRepaid && !pending) { if (ContractStatus != OContractStatus.WrittenOff) { _closed = true; ContractStatus = OContractStatus.Closed; CloseDate = pDate; } // check if Client has other 'active' loans if so, mark him as active client if (Project != null) foreach (var loan in Project.Credits) Project.Client.Active = loan.ContractStatus == OContractStatus.Active; } //Event identification Events.Add(GenerateRepaymentEvents(cCr, pDate, penaltiesEvent, commissionsEvent, interestEvent, interestPrepayment, principalEvent, pastDueDays, paymentType, pending, pNumber, paymentMethod)); //principal amount correction in case of shit which is taken place when we do big prepayment //please remove it when all shity contracts will be closed OCurrency paidPrincipal = 0; foreach (RepaymentEvent repaymentEvent in Events.GetLoanRepaymentEvents()) { if(repaymentEvent.Deleted == false) { paidPrincipal += repaymentEvent.Principal; } if(paidPrincipal > Amount) { repaymentEvent.Principal += Amount - paidPrincipal; } } ////////////////////////////////////////////////////////////////////////////////////////////// _installmentList.Sort((x, y) => x.ExpectedDate.CompareTo(y.ExpectedDate)); foreach (Installment installment in InstallmentList) { //setup paid date for installments if (installment.IsRepaid && installment.Number > pNumber) { installment.PaidDate = pDate; installment.PaymentMethod = paymentMethod; installment.Comment = comment; installment.IsPending = pending; } else if (installment.Number == pNumber) { installment.PaidDate = pDate; installment.PaymentMethod = paymentMethod; installment.Comment = comment; installment.IsPending = pending; } installment.OLB = CalculateExpectedOlb(installment.Number, keepExpectedInstallment); } EscapedMember = null; return rPe; }
/// <summary> /// This method manages all the repayment cases implemented in OCTOPUS /// </summary> /// <param name="pNumber">pNumber of the installment paid</param> /// <param name="pDate">pDate of the payment</param> /// <param name="pAmountPaid">amount paid by the client which can be lower, equal or greater than the expected amount for an installment</param> /// <param name="cancelFees">when true, cancel anticipated payment Commission</param> /// <param name="manualFeesAmount">manual amount of commission (when anticipated payment commission are cancelled)</param> /// <returns>A RepaymentEvent or null if : /// - repayment amount lower than 0 /// - repayment amount greater than olb + interestsToPay + commission /// - installment already repaid /// - bad loan and past due days greater than 180 /// </returns> /// <param name="manualCommissionAmount"></param> /// <param name="disableInterests"></param> /// <param name="manualInterests"></param> /// <param name="keepExpectedInstallment"></param> /// <param name="isPending"></param> /// <param name="paymentMethod"></param> public RepaymentEvent Repay(int pNumber, DateTime pDate, OCurrency pAmountPaid, bool cancelFees, OCurrency manualFeesAmount, OCurrency manualCommissionAmount, bool disableInterests, OCurrency manualInterests, bool keepExpectedInstallment, bool isPending, OPaymentMethods paymentMethod) { return Repay(pNumber, pDate, pAmountPaid, cancelFees, manualFeesAmount, manualCommissionAmount, disableInterests, manualInterests, keepExpectedInstallment, paymentMethod, null, isPending); }