} // ToString public void Update( InterestData oDelta, InterestFreezePeriods ifp, BadPeriods bp, bool bAccountingMode, DateTime?oWriteOffDate ) { if (bAccountingMode) { if (oWriteOffDate.HasValue) { this.Interest = (this.Date < oWriteOffDate.Value) ? GetIfpInterest(ifp, oDelta) : 0; } else { this.Interest = GetIfpInterest(ifp, oDelta); } } else // i.e. normal mode { if (bp == null) { this.Interest = GetIfpInterest(ifp, oDelta); } else { this.Interest = bp.Contains(this.Date) ? 0 : GetIfpInterest(ifp, oDelta); } } // if } // Update
} // Update private decimal GetIfpInterest(InterestFreezePeriods ifp, InterestData oDelta) { if (ifp == null) { return(oDelta.Interest); } return(ifp.GetInterest(this.Date) ?? oDelta.Interest); } // GetIfpInterest
} // constructor /// <summary> /// Earned interest is a SUM(Pj * Ij) where the sum is taken on all the days during /// requested period when a loan could produce interest, Pj is a loan principal on /// specific day, Ij is an interest on that day. /// </summary> /// <param name="oDateStart">Requested period start date, inclusive.</param> /// <param name="oDateEnd">Requested period end date, exclusive.</param> /// <param name="ifp">Interest rate freeze periods.</param> /// <param name="bVerboseLogging">Log verbosity level.</param> /// <param name="nMode">Interest calculation mode.</param> /// <param name="bAccountingMode">How bad statuses and Write Off are treated.</param> /// <param name="oWriteOffDate">Date of the first customer's WriteOff status.</param> /// <param name="bp">List of customer's bad periods (i.e. when customer was in one of the bad statuses).</param> /// <returns>Earned interest for the period.</returns> public decimal Calculate( DateTime oDateStart, DateTime oDateEnd, InterestFreezePeriods ifp, bool bVerboseLogging, Reports.EarnedInterest.EarnedInterest.WorkingMode nMode, bool bAccountingMode, BadPeriods bp, DateTime?oWriteOffDate ) { DateTime oFirstIncomeDay = this.IssueDate.AddDays(1); // A loan starts to produce interest on the next day. DateTime oDayOne = (oDateStart < oFirstIncomeDay) ? oFirstIncomeDay : oDateStart; // List of all the dates during requested period when a loan could produce interest. var oDaysList = new List <PrInterest>(); for (DateTime d = oDayOne; d < oDateEnd; d = d.AddDays(1)) { oDaysList.Add(new PrInterest(d, this.Amount)); } if (oDaysList.Count == 0) { return(0); } DateTime oPrevDate = this.IssueDate; foreach (InterestData ida in this.Schedule.Values) { ida.PeriodLength = (ida.Date - oPrevDate).Days; oPrevDate = ida.Date; } // for each schedule oDaysList.ForEach(pri => { foreach (TransactionData t in this.Repayments.Values) { pri.Update(t); } }); // for each day PrInterest[] days = oDaysList.Where(pri => pri.Principal > 0).ToArray(); if (days.Length == 0) { LogAllDetails( 0, "no dates found when the loan produced interest during report period", days, ifp, bp, bVerboseLogging, bAccountingMode, oWriteOffDate ); return(0); } // if InterestData[] aryDates = this.Schedule.Values.ToArray(); foreach (PrInterest pri in days) { InterestData oCurDayData = pri.Date > aryDates[aryDates.Length - 1].Date ? aryDates[aryDates.Length - 1] : aryDates.First(cdd => pri.Date <= cdd.Date); pri.Update(oCurDayData, ifp, bp, bAccountingMode, oWriteOffDate); } // for decimal nEarnedInterest = days.Sum(pri => pri.Principal * pri.Interest); LogAllDetails( nEarnedInterest, "full details are below", days, ifp, bp, bVerboseLogging, bAccountingMode, oWriteOffDate ); return(nEarnedInterest); } // Calculate