/// <summary>
 /// Initializes a new instance of the <see cref="LoanCalculationOutputStreamWriter"/> class.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="output">The output.</param>
 public LoanCalculationOutputStreamWriter(LoanContext context, LoanCalculationOutput output)
 {
     this.context = context;
     this.output = output;
 }
Esempio n. 2
0
        /// <summary>
        /// Calculates the loan using the context.
        /// </summary>
        /// <returns></returns>
        public LoanCalculationOutput Calculate()
        {
            LoanCalculationOutput result = new LoanCalculationOutput();
            bool firstIteration = true;
            double balance = context.Balance;
            double monthlyInterest = 0.0d;
            DateTime currentDate = context.StartDate;
            // we will calculate interest from the first of the month
            DateTime calcInterestStartDate = new DateTime(currentDate.Year, currentDate.Month, 1);
            result.InterestStartDate = calcInterestStartDate;
            // loop through dates, caculating interest daily etc
            while (true)
            {
                // if min repay day
                if (currentDate.Day == context.MinRepaymentDay && balance > 0.0d)
                {
                    balance = ProcessMinRepayment(balance, context.MinRepaymentAmount, currentDate, monthlyInterest, result);
                }
                // if extra repay day
                if (currentDate.Day == context.ExtraRepaymentDay && context.ExtraRepaymentAmount > 0.0d && balance > 0.0d)
                {
                    balance = ProcessExtraRepayment(balance, context.ExtraRepaymentAmount, currentDate, result);
                }

                // if balance is zero or less - we are done!
                if (balance <= 0.0d)
                {
                    result.LoanEndsDate = currentDate;
                    break;
                }
                // calculate the daily interest
                monthlyInterest += CalculateDailyInterest(balance, context.InterestRate);
                // if this is the first iteration and we did not start on the first of the month
                // let's calculate the interest for the days back to the first
                if (firstIteration && context.StartDate.Day != 1)
                {
                    int daysToMonthStart = currentDate.Day - 1;
                    monthlyInterest += (monthlyInterest * daysToMonthStart);
                    firstIteration = false;
                }
                // if we have reached the max date of DateTime, let's throw back an error
                if((currentDate.Ticks + TimeSpan.TicksPerDay) >= DateTime.MaxValue.Ticks)
                {
                    result.Failure = true;
                    result.FailureMessage = string.Format("Calculations for your loan got to the end-of-time date {0}...and still not paid off. Your situation, sorry to say, is hopeless.", currentDate.ToShortDateString());
                    return (result);
                }
                // move date forward
                DateTime nextDate = currentDate.AddDays(1);
                // if end of month
                if (currentDate.Month != nextDate.Month)
                {
                    balance = ProcessEndOfMonth(currentDate, monthlyInterest, balance, result);
                    // reset interest to zero
                    monthlyInterest = 0.0d;
                }
                currentDate = nextDate;
            }
            SetTargetEndDateAccuracy(result.LoanEndsDate, context.TargetEndDate, result);
            return (result);
        }
Esempio n. 3
0
 /// <summary>
 /// Sets the target end date accuracy.
 /// </summary>
 /// <param name="actualEndDate">The actual end date.</param>
 /// <param name="targetEndDate">The target end date.</param>
 /// <param name="result">The result.</param>
 private void SetTargetEndDateAccuracy(DateTime actualEndDate, DateTime targetEndDate, LoanCalculationOutput result)
 {
     TimeSpan difference = actualEndDate - targetEndDate;
     result.TargetEndDateMissedInDays = Math.Abs((int)difference.TotalDays);
 }
Esempio n. 4
0
 /// <summary>
 /// Processes the minimum repayment.
 /// </summary>
 /// <param name="balance">The balance.</param>
 /// <param name="context">The context.</param>
 /// <param name="currentDate">The current date.</param>
 /// <param name="monthlyInterest">The monthly interest.</param>
 /// <param name="result">The result.</param>
 private double ProcessMinRepayment(double balance, double minRepaymentAmount, DateTime currentDate, double monthlyInterest, LoanCalculationOutput result)
 {
     // add min repay transaction
     if ((balance + monthlyInterest) <= minRepaymentAmount)
     {
         double finalRepayment = 0.0d;
         balance += monthlyInterest;
         finalRepayment = balance;
         balance -= finalRepayment;
         LoanTransaction transaction = new LoanTransaction(currentDate, TransactionType.FinalRepayment, finalRepayment, 0.0d, balance);
         result.Transactions.Add(transaction);
     }
     else
     {
         balance -= minRepaymentAmount;
         LoanTransaction transaction = new LoanTransaction(currentDate, TransactionType.MinimumRepayment, minRepaymentAmount, 0.0d, balance);
         result.Transactions.Add(transaction);
     }
     return (balance);
 }
Esempio n. 5
0
 /// <summary>
 /// Processes the extra repayment.
 /// </summary>
 /// <param name="balance">The balance.</param>
 /// <param name="extraRepaymentAmount">The extra repayment amount.</param>
 /// <param name="currentDate">The current date.</param>
 /// <param name="result">The result.</param>
 private double ProcessExtraRepayment(double balance, double extraRepaymentAmount, DateTime currentDate, LoanCalculationOutput result)
 {
     if(balance >= extraRepaymentAmount)
     {
         // add extra repay transaction (if amount is more than 0)
         balance -= extraRepaymentAmount;
         LoanTransaction transaction = new LoanTransaction(currentDate, TransactionType.ExtraRepayment, extraRepaymentAmount, 0.0d, balance);
         result.Transactions.Add(transaction);
     }
     return (balance);
 }
Esempio n. 6
0
 /// <summary>
 /// Processes the end of month.
 /// </summary>
 /// <param name="currentDate">The current date.</param>
 /// <param name="monthlyInterest">The monthly interest.</param>
 /// <param name="balance">The balance.</param>
 /// <param name="result">The result.</param>
 private double ProcessEndOfMonth(DateTime currentDate, double monthlyInterest, double balance, LoanCalculationOutput result)
 {
     // add interest charged transaction
     balance += monthlyInterest;
     // calculate the total interest paid
     result.TotalInterestPaid += monthlyInterest;
     LoanTransaction transaction = new LoanTransaction(currentDate, TransactionType.InterestCharged, 0.0d, monthlyInterest, balance);
     result.Transactions.Add(transaction);
     return (balance);
 }