Пример #1
0
 private DateTime GetLastEndDate(IEnumerable<Installment> schedule, ITrancheConfiguration trancheConfiguration)
 {
     var installment = (from i in schedule
                        where i.ExpectedDate <= trancheConfiguration.StartDate
                        select i).LastOrDefault();
     if (installment == null) return schedule.First().StartDate;
     return installment.ExpectedDate;
 }
Пример #2
0
        public List<Installment> BuildTranche(IEnumerable<Installment> schedule, IScheduleBuilder scheduleBuilder, IScheduleConfiguration scheduleConfiguration, ITrancheConfiguration trancheConfiguration)
        {
            var rhc = (IScheduleConfiguration)scheduleConfiguration.Clone();
            rhc.Amount = trancheConfiguration.Amount;
            rhc.NumberOfInstallments = trancheConfiguration.NumberOfInstallments;
            rhc.GracePeriod = trancheConfiguration.GracePeriod;
            rhc.InterestRate = trancheConfiguration.InterestRate;
            rhc.StartDate = trancheConfiguration.StartDate;
            rhc.PreferredFirstInstallmentDate = trancheConfiguration.PreferredFirstInstallmentDate;

            var lhc = (IScheduleConfiguration)rhc.Clone();
            lhc.Amount = schedule.Sum(i => i.CapitalRepayment.Value - i.PaidCapital.Value);
            if (!trancheConfiguration.ApplyNewInterestRateToOlb)
            {
                lhc.InterestRate = scheduleConfiguration.InterestRate;
            }

            var lhs = scheduleBuilder.BuildSchedule(lhc);
            var rhs = scheduleBuilder.BuildSchedule(rhc);

            var result = new List<Installment>();

            // Merge the two schedules
            var max = Math.Max(lhs.Count, rhs.Count);
            for (var i = 0; i < max; i++)
            {
                var lhi = i >= lhs.Count ? null : lhs[i];
                var rhi = i >= rhs.Count ? null : rhs[i];

                Installment installment;

                if (lhi == null)
                {
                    installment = rhi;
                }
                else if (rhi == null)
                {
                    installment = lhi;
                }
                else
                {
                    installment = new Installment
                    {
                        Number = lhi.Number,
                        StartDate = lhi.StartDate,
                        ExpectedDate = lhi.ExpectedDate,
                        //RepaymentDate = lhi.RepaymentDate,
                        CapitalRepayment = lhi.CapitalRepayment + rhi.CapitalRepayment,
                        InterestsRepayment = lhi.InterestsRepayment + rhi.InterestsRepayment,
                        OLB = lhi.OLB + rhi.OLB,
                    };
                }
                result.Add(installment);
            }

            result[0].InterestsRepayment += GetExtraInterest(schedule, scheduleConfiguration, trancheConfiguration);
            return result;
        }
Пример #3
0
 private decimal GetExtraInterest(IEnumerable<Installment> schedule,
                                  IScheduleConfiguration scheduleConfiguration,
                                  ITrancheConfiguration trancheConfiguration)
 {
     var days = (trancheConfiguration.StartDate - GetLastEndDate(schedule, trancheConfiguration)).Days;
     var daysInYear = scheduleConfiguration.YearPolicy.GetNumberOfDays(trancheConfiguration.StartDate);
     var olb = schedule.Sum(i => i.CapitalRepayment.Value - i.PaidCapital.Value);
     var interest = olb * scheduleConfiguration.InterestRate / 100 * days / daysInYear;
     return scheduleConfiguration.RoundingPolicy.Round(interest);
 }
Пример #4
0
        private decimal GetExtraInterest(IEnumerable <Installment> schedule,
                                         IScheduleConfiguration scheduleConfiguration,
                                         ITrancheConfiguration trancheConfiguration)
        {
            var days       = (trancheConfiguration.StartDate - GetLastEndDate(schedule, trancheConfiguration)).Days;
            var daysInYear = scheduleConfiguration.YearPolicy.GetNumberOfDays(trancheConfiguration.StartDate);
            var olb        = schedule.Sum(i => i.CapitalRepayment.Value - i.PaidCapital.Value);
            var interest   = olb * scheduleConfiguration.InterestRate / 100 * days / daysInYear;

            return(scheduleConfiguration.RoundingPolicy.Round(interest));
        }
Пример #5
0
        private DateTime GetLastEndDate(IEnumerable <Installment> schedule, ITrancheConfiguration trancheConfiguration)
        {
            var installment = (from i in schedule
                               where i.ExpectedDate <= trancheConfiguration.StartDate
                               select i).LastOrDefault();

            if (installment == null)
            {
                return(schedule.First().StartDate);
            }
            return(installment.ExpectedDate);
        }
Пример #6
0
        public Loan AddTranche(Loan loan, IClient client, ITrancheConfiguration trancheConfiguration, IList<LoanEntryFee> entryFees, PaymentMethod paymentMethod)
        {
            using (var connection = _loanManager.GetConnection())
            using (var transaction = connection.BeginTransaction())
            {
                try
                {
                    CheckTranche(trancheConfiguration.StartDate, loan, trancheConfiguration.Amount);

                    var copyOfLoan = SimulateTranche(loan, trancheConfiguration);
                    var startInstallment =
                        copyOfLoan.InstallmentList
                                  .FindAll(i => i.ExpectedDate <= trancheConfiguration.StartDate)
                                  .LastOrDefault();
                    var trancheEvent = new TrancheEvent
                        {
                            Amount = trancheConfiguration.Amount,
                            ApplyNewInterest = trancheConfiguration.ApplyNewInterestRateToOlb,
                            Maturity = trancheConfiguration.NumberOfInstallments,
                            StartDate = trancheConfiguration.StartDate,
                            Date = trancheConfiguration.StartDate,
                            InterestRate = trancheConfiguration.InterestRate/100,
                            Number = copyOfLoan.GivenTranches.Count,
                            FirstRepaymentDate = trancheConfiguration.PreferredFirstInstallmentDate,
                            GracePeriod = trancheConfiguration.GracePeriod,
                            StartedFromInstallment = startInstallment == null ? 0 : startInstallment.Number,
                            User = _user,
                            PaymentMethod = paymentMethod
                        };

                    trancheEvent.User = _user;

                    //insert into table TrancheEvent
                    _ePs.FireEvent(trancheEvent, copyOfLoan, transaction);
                    copyOfLoan.Events.Add(trancheEvent);

                    CallInterceptor(new Dictionary<string, object>
                    {
                        {"Loan", copyOfLoan},
                        {"Event", trancheEvent},
                        {"SqlTransaction", transaction}
                    });

                    // Add entry fee events
                    foreach (var entryFee in entryFees)
                    {
                        if (entryFee.FeeValue == 0) continue;
                        var entryFeeEvent = new LoanEntryFeeEvent
                        {
                            Fee = entryFee.FeeValue,
                            Code = "LEE" + entryFee.ProductEntryFee.Index,
                            DisbursementEventId = trancheEvent.Id,
                            Cancelable = true,
                            User = User.CurrentUser,
                            Date = trancheEvent.Date
                        };
                        _ePs.FireEvent(entryFeeEvent, copyOfLoan, transaction);
                        copyOfLoan.Events.Add(entryFeeEvent);
                    }

                    var trancheEntryFeeEvent =
                        copyOfLoan.Events.OfType<LoanEntryFeeEvent>()
                                  .First(i => i.DisbursementEventId == trancheEvent.Id);
                    if (trancheEntryFeeEvent != null)
                        CallInterceptor(new Dictionary<string, object>
                        {
                            {"Loan", copyOfLoan},
                            {
                                "Event", new LoanEntryFeeEvent
                                    {
                                        Id = trancheEntryFeeEvent.Id,
                                        Fee = entryFees.Sum(i => i.FeeValue),
                                        Code = "LEE0"
                                    }
                            },
                            {"SqlTransaction", transaction}
                        });

                    ArchiveInstallments(loan, trancheEvent, transaction);

                    //delete all the old installments of the table Installments
                    _instalmentManager.DeleteInstallments(loan.Id, transaction);

                    //insert all the new installments in the table Installments
                    _instalmentManager.AddInstallments(copyOfLoan.InstallmentList, copyOfLoan.Id, transaction);

                    //Activate the contract if it's closed because of new tranch
                    if (copyOfLoan.Closed)
                    {
                        copyOfLoan.ContractStatus = OContractStatus.Active;
                        copyOfLoan.Closed = false;
                        _loanManager.UpdateLoan(copyOfLoan, transaction);
                    }
                    //in the feature might be combine UpdateLoan + UpdateLoanWithinTranche
                    _loanManager.UpdateLoanWithinTranche(
                        trancheConfiguration.InterestRate/100,
                        copyOfLoan.NbOfInstallments,
                        copyOfLoan,
                        transaction);
                    copyOfLoan.GivenTranches.Add(trancheEvent);
                    transaction.Commit();

                    SetClientStatus(copyOfLoan, client);
                    return copyOfLoan;
                }
                catch
                {
                    transaction.Rollback();
                    throw;
                }
            }
        }
Пример #7
0
        public Loan SimulateTranche(Loan loan, ITrancheConfiguration trancheConfiguration)
        {
            var copyOfLoan = loan.Copy();
            var scheduleConfiguration = _configurationFactory
                .Init()
                .WithLoan(copyOfLoan)
                .Finish()
                .GetConfiguration();

            var schedule = Mapper.Map<IEnumerable<Installment>, IEnumerable<IInstallment>>(copyOfLoan.InstallmentList);
            var scheduleBuilder = new ScheduleBuilder();
            var trancheBuilder = new TrancheBuilder();
            var trancheAssembler = new TrancheAssembler();
            var copyOfTrancheConfiguration = (ITrancheConfiguration) trancheConfiguration.Clone();
            copyOfTrancheConfiguration.InterestRate *=
                (decimal) scheduleConfiguration.PeriodPolicy.GetNumberOfPeriodsInYear(
                    copyOfTrancheConfiguration.StartDate,
                    scheduleConfiguration.YearPolicy);

            schedule = trancheAssembler.AssembleTranche(
                schedule,
                scheduleConfiguration,
                copyOfTrancheConfiguration,
                scheduleBuilder,
                trancheBuilder);

            var newSchedule = Mapper.Map<IEnumerable<IInstallment>, List<Installment>>(schedule);

            foreach (var installment in newSchedule)
            {
                var oldInstallment = copyOfLoan.InstallmentList.Find(i => i.Number == installment.Number);
                if (oldInstallment == null) break;

                installment.Comment = oldInstallment.Comment;
                installment.PaidFees = oldInstallment.PaidFees;
                installment.PaidCommissions = oldInstallment.PaidCommissions;
                installment.FeesUnpaid = oldInstallment.FeesUnpaid;
                installment.CommissionsUnpaid = oldInstallment.CommissionsUnpaid;
                installment.IsPending = oldInstallment.IsPending;
                //installment.PaidDate = oldInstallment.PaidDate;
            }
            copyOfLoan.InstallmentList = newSchedule;
            copyOfLoan.NbOfInstallments = newSchedule.Count();
            copyOfLoan.Amount += trancheConfiguration.Amount;
            return copyOfLoan;
        }
Пример #8
0
        private IEnumerable<Installment> BuildTranche(IEnumerable<Installment> schedule,Loan loan, IScheduleConfiguration scheduleConfiguration, ITrancheConfiguration trancheConfiguration)
        {
            var copyOfLoan = loan.Copy();
            loan.Amount = trancheConfiguration.Amount;
            loan.NbOfInstallments = trancheConfiguration.NumberOfInstallments;
            loan.GracePeriod = trancheConfiguration.GracePeriod;
            loan.InterestRate = trancheConfiguration.InterestRate/100;
            loan.StartDate = trancheConfiguration.StartDate;
            loan.FirstInstallmentDate = trancheConfiguration.PreferredFirstInstallmentDate;

            var rhs = SimulateScheduleCreation(loan);

            loan.Amount = schedule.Sum(i => i.CapitalRepayment.Value - i.PaidCapital.Value);
            if (!trancheConfiguration.ApplyNewInterestRateToOlb)
            {
                loan.InterestRate = copyOfLoan.InterestRate;
            }

            var lhs = SimulateScheduleCreation(loan);

            var result = new List<Installment>();

            // Merge the two schedules
            var max = Math.Max(lhs.Count, rhs.Count);
            for (var i = 0; i < max; i++)
            {
                var lhi = i >= lhs.Count ? null : lhs[i];
                var rhi = i >= rhs.Count ? null : rhs[i];

                Installment installment;

                if (lhi == null)
                {
                    installment = rhi;
                }
                else if (rhi == null)
                {
                    installment = lhi;
                }
                else
                {
                    installment = new Installment
                    {
                        Number = lhi.Number,
                        StartDate = lhi.StartDate,
                        ExpectedDate = lhi.ExpectedDate,
                        //RepaymentDate = lhi.RepaymentDate,
                        CapitalRepayment = lhi.CapitalRepayment + rhi.CapitalRepayment,
                        InterestsRepayment = lhi.InterestsRepayment + rhi.InterestsRepayment,
                        OLB = lhi.OLB + rhi.OLB,
                    };
                }
                result.Add(installment);
            }

            result[0].InterestsRepayment += GetExtraInterest(schedule, scheduleConfiguration, trancheConfiguration);
            return result;
        }
Пример #9
0
        private List<Installment> AssembleTranche(Loan loan, IScheduleConfiguration scheduleConfiguration, ITrancheConfiguration trancheConfiguration)
        {
            var schedule = loan.InstallmentList;
            var trancheSchedule = BuildTranche(schedule, loan, scheduleConfiguration, trancheConfiguration);

            // Get an interested paid in advance, whereas "in advance" means after the new tranche date
            var overpaidInterest = (
                from installment in schedule
                where installment.ExpectedDate > trancheConfiguration.StartDate
                select installment
            ).Sum(installment => installment.PaidInterests.Value);

            // Get the part of the schedule that comes before the tranche date...
            var newSchedule =
                from installment in schedule
                where installment.ExpectedDate <= trancheConfiguration.StartDate
                select installment;

            // ...and force close it (set expected equal to paid)
            var olbDifference = 0m;
            foreach (var installment in newSchedule)
            {
                installment.OLB += olbDifference;
                olbDifference += installment.CapitalRepayment.Value - installment.PaidCapital.Value;
                if (!(installment.CapitalRepayment == installment.PaidCapital && installment.InterestsRepayment == installment.PaidInterests))
                {
                    installment.PaidDate = trancheConfiguration.StartDate;
                }
                installment.CapitalRepayment = installment.PaidCapital;
                installment.InterestsRepayment = installment.PaidInterests;
            }

            // Adjust the new schedule's installment numbers
            var increment = newSchedule.Count();
            foreach (var installment in trancheSchedule)
            {
                installment.Number += increment;
            }
            var result = new List<Installment>();
            result.AddRange(newSchedule);

            // Distribute the overpaid interest
            foreach (var installment in trancheSchedule)
            {
                if (installment.InterestsRepayment < overpaidInterest)
                {
                    installment.PaidInterests = installment.InterestsRepayment;
                    overpaidInterest -= installment.InterestsRepayment.Value;
                }
                else
                {
                    installment.PaidInterests = overpaidInterest;
                    break;
                }
            }

            result.AddRange(trancheSchedule);
            return result;
        }
Пример #10
0
        public Loan SimulateTranche(Loan loan, ITrancheConfiguration trancheConfiguration)
        {
            var copyOfLoan = loan.Copy();
            var scheduleConfiguration = _configurationFactory
                .Init()
                .WithLoan(copyOfLoan)
                .Finish()
                .GetConfiguration();

            var schedule = copyOfLoan.InstallmentList;
            var scheduleBuilder = new ScheduleBuilder();
            var trancheBuilder = new TrancheBuilder();
            var trancheAssembler = new TrancheAssembler();
            var copyOfTrancheConfiguration = (ITrancheConfiguration)trancheConfiguration.Clone();

            var newSchedule = new List<Installment>();
            if (loan.Product.ScriptName == null)
                newSchedule = trancheAssembler.AssembleTranche(
                    schedule,
                    scheduleConfiguration,
                    copyOfTrancheConfiguration,
                    scheduleBuilder,
                    trancheBuilder).ToList();
            else
                newSchedule = AssembleTranche(copyOfLoan, scheduleConfiguration, trancheConfiguration);

            foreach (var installment in newSchedule)
            {
                var oldInstallment = copyOfLoan.InstallmentList.Find(i => i.Number == installment.Number);
                if (oldInstallment == null) break;

                installment.Comment = oldInstallment.Comment;
                installment.PaidFees = oldInstallment.PaidFees;
                installment.PaidCommissions = oldInstallment.PaidCommissions;
                installment.FeesUnpaid = oldInstallment.FeesUnpaid;
                installment.CommissionsUnpaid = oldInstallment.CommissionsUnpaid;
                installment.IsPending = oldInstallment.IsPending;
                //installment.PaidDate = oldInstallment.PaidDate;
            }
            copyOfLoan.InstallmentList = newSchedule;
            copyOfLoan.NbOfInstallments = newSchedule.Count();
            copyOfLoan.Amount += trancheConfiguration.Amount;
            return copyOfLoan;
        }
Пример #11
0
        public IEnumerable <Installment> AssembleTranche(
            IEnumerable <Installment> schedule,
            IScheduleConfiguration scheduleConfiguration,
            ITrancheConfiguration trancheConfiguration,
            IScheduleBuilder scheduleBuilder,
            ITrancheBuilder trancheBuilder)
        {
            // Build a new combined schedule
            var trancheSchedule = trancheBuilder.BuildTranche(schedule, scheduleBuilder, scheduleConfiguration, trancheConfiguration);

            // Get an interested paid in advance, whereas "in advance" means after the new tranche date
            var overpaidInterest = (
                from installment in schedule
                where installment.ExpectedDate > trancheConfiguration.StartDate
                select installment
                ).Sum(installment => installment.PaidInterests.Value);

            // Get the part of the schedule that comes before the tranche date...
            var newSchedule =
                from installment in schedule
                where installment.ExpectedDate <= trancheConfiguration.StartDate
                select installment;

            // ...and force close it (set expected equal to paid)
            var olbDifference = 0m;

            foreach (var installment in newSchedule)
            {
                installment.OLB += olbDifference;
                olbDifference   += installment.CapitalRepayment.Value - installment.PaidCapital.Value;
                if (!(installment.CapitalRepayment == installment.PaidCapital && installment.InterestsRepayment == installment.PaidInterests))
                {
                    installment.PaidDate = trancheConfiguration.StartDate;
                }
                installment.CapitalRepayment   = installment.PaidCapital;
                installment.InterestsRepayment = installment.PaidInterests;
            }

            // Adjust the new schedule's installment numbers
            var increment = newSchedule.Count();

            foreach (var installment in trancheSchedule)
            {
                installment.Number += increment;
            }
            var result = new List <Installment>();

            result.AddRange(newSchedule);

            // Distribute the overpaid interest
            foreach (var installment in trancheSchedule)
            {
                if (installment.InterestsRepayment < overpaidInterest)
                {
                    installment.PaidInterests = installment.InterestsRepayment;
                    overpaidInterest         -= installment.InterestsRepayment.Value;
                }
                else
                {
                    installment.PaidInterests = overpaidInterest;
                    break;
                }
            }

            result.AddRange(trancheSchedule);
            return(result);
        }
Пример #12
0
        public IEnumerable<IInstallment> AssembleTranche(
            IEnumerable<IInstallment> schedule,
            IScheduleConfiguration scheduleConfiguration,
            ITrancheConfiguration trancheConfiguration,
            IScheduleBuilder scheduleBuilder,
            ITrancheBuilder trancheBuilder)
        {
            // Build a new combined schedule
            var trancheSchedule = trancheBuilder.BuildTranche(schedule, scheduleBuilder, scheduleConfiguration, trancheConfiguration);

            // Get an interested paid in advance, whereas "in advance" means after the new tranche date
            var overpaidInterest = (
                from installment in schedule
                where installment.RepaymentDate > trancheConfiguration.StartDate
                select installment
            ).Sum(installment => installment.PaidInterest);

            // Get the part of the schedule that comes before the tranche date...
            var newSchedule =
                from installment in schedule
                where installment.RepaymentDate <= trancheConfiguration.StartDate
                select installment;

            // ...and force close it (set expected equal to paid)
            var olbDifference = 0m;
            foreach (var installment in newSchedule)
            {
                installment.Olb += olbDifference;
                olbDifference += installment.Principal - installment.PaidPrincipal;
                if (!(installment.Principal == installment.PaidPrincipal && installment.Interest == installment.PaidInterest))
                {
                    installment.LastPaymentDate = trancheConfiguration.StartDate;
                }
                installment.Principal = installment.PaidPrincipal;
                installment.Interest = installment.PaidInterest;
            }

            // Adjust the new schedule's installment numbers
            var increment = newSchedule.Count();
            foreach (var installment in trancheSchedule)
            {
                installment.Number += increment;
            }
            var result = new List<IInstallment>();
            result.AddRange(newSchedule);

            // Distribute the overpaid interest
            foreach (var installment in trancheSchedule)
            {
                if (installment.Interest < overpaidInterest)
                {
                    installment.PaidInterest = installment.Interest;
                    overpaidInterest -= installment.Interest;
                }
                else
                {
                    installment.PaidInterest = overpaidInterest;
                    break;
                }
            }

            result.AddRange(trancheSchedule);
            return result;
        }
Пример #13
0
        public List <Installment> BuildTranche(IEnumerable <Installment> schedule, IScheduleBuilder scheduleBuilder, IScheduleConfiguration scheduleConfiguration, ITrancheConfiguration trancheConfiguration)
        {
            var rhc = (IScheduleConfiguration)scheduleConfiguration.Clone();

            rhc.Amount = trancheConfiguration.Amount;
            rhc.NumberOfInstallments          = trancheConfiguration.NumberOfInstallments;
            rhc.GracePeriod                   = trancheConfiguration.GracePeriod;
            rhc.InterestRate                  = trancheConfiguration.InterestRate;
            rhc.StartDate                     = trancheConfiguration.StartDate;
            rhc.PreferredFirstInstallmentDate = trancheConfiguration.PreferredFirstInstallmentDate;

            var lhc = (IScheduleConfiguration)rhc.Clone();

            lhc.Amount = schedule.Sum(i => i.CapitalRepayment.Value - i.PaidCapital.Value);
            if (!trancheConfiguration.ApplyNewInterestRateToOlb)
            {
                lhc.InterestRate = scheduleConfiguration.InterestRate;
            }

            var lhs = scheduleBuilder.BuildSchedule(lhc);
            var rhs = scheduleBuilder.BuildSchedule(rhc);

            var result = new List <Installment>();

            // Merge the two schedules
            var max = Math.Max(lhs.Count, rhs.Count);

            for (var i = 0; i < max; i++)
            {
                var lhi = i >= lhs.Count ? null : lhs[i];
                var rhi = i >= rhs.Count ? null : rhs[i];

                Installment installment;

                if (lhi == null)
                {
                    installment = rhi;
                }
                else if (rhi == null)
                {
                    installment = lhi;
                }
                else
                {
                    installment = new Installment
                    {
                        Number       = lhi.Number,
                        StartDate    = lhi.StartDate,
                        ExpectedDate = lhi.ExpectedDate,
                        //RepaymentDate = lhi.RepaymentDate,
                        CapitalRepayment   = lhi.CapitalRepayment + rhi.CapitalRepayment,
                        InterestsRepayment = lhi.InterestsRepayment + rhi.InterestsRepayment,
                        OLB = lhi.OLB + rhi.OLB,
                    };
                }
                result.Add(installment);
            }

            result[0].InterestsRepayment += GetExtraInterest(schedule, scheduleConfiguration, trancheConfiguration);
            return(result);
        }
Пример #14
0
        public Loan AddTranche(Loan loan, IClient client, ITrancheConfiguration trancheConfiguration)
        {
            using (var connection = _loanManager.GetConnection())
            using (var transaction = connection.BeginTransaction())
            {
                try
                {
                    CheckTranche(trancheConfiguration.StartDate, loan, trancheConfiguration.Amount);

                    var copyOfLoan = SimulateTranche(loan, trancheConfiguration);
                    var startInstallment =
                        copyOfLoan.InstallmentList
                        .FindAll(i => i.ExpectedDate <= trancheConfiguration.StartDate)
                        .LastOrDefault();
                    var trancheEvent = new TrancheEvent
                    {
                        Amount = trancheConfiguration.Amount,
                        ApplyNewInterest = trancheConfiguration.ApplyNewInterestRateToOlb,
                        Maturity = trancheConfiguration.NumberOfInstallments,
                        StartDate = trancheConfiguration.StartDate,
                        Date = trancheConfiguration.StartDate,
                        InterestRate = trancheConfiguration.InterestRate / 100,
                        Number = copyOfLoan.GivenTranches.Count,
                        FirstRepaymentDate = trancheConfiguration.PreferredFirstInstallmentDate,
                        GracePeriod = trancheConfiguration.GracePeriod,
                        StartedFromInstallment = startInstallment == null ? 0 : startInstallment.Number,
                        User = _user,
                    };

                    trancheEvent.User = _user;

                    //insert into table TrancheEvent
                    _ePs.FireEvent(trancheEvent, copyOfLoan, transaction);

                    ArchiveInstallments(loan, trancheEvent, transaction);

                    //delete all the old installments of the table Installments
                    _instalmentManager.DeleteInstallments(loan.Id, transaction);

                    //insert all the new installments in the table Installments
                    _instalmentManager.AddInstallments(copyOfLoan.InstallmentList, copyOfLoan.Id, transaction);

                    //Activate the contract if it's closed because of new tranch
                    if (copyOfLoan.Closed)
                    {
                        copyOfLoan.ContractStatus = OContractStatus.Active;
                        copyOfLoan.Closed = false;
                        _loanManager.UpdateLoan(copyOfLoan, transaction);
                    }
                    //in the feature might be combine UpdateLoan + UpdateLoanWithinTranche
                    _loanManager.UpdateLoanWithinTranche(
                        trancheConfiguration.InterestRate / 100,
                        copyOfLoan.NbOfInstallments,
                        copyOfLoan,
                        transaction);
                    copyOfLoan.Events.Add(trancheEvent);
                    copyOfLoan.GivenTranches.Add(trancheEvent);
                    transaction.Commit();

                    SetClientStatus(copyOfLoan, client);
                    return copyOfLoan;
                }
                catch
                {
                    transaction.Rollback();
                    throw;
                }
            }
        }