Merge pull request #513 from mifoscontributer/mifosx-554

MIFOSX-554 Adjust repaymentdate for frequent meeting changes
This commit is contained in:
Vishwas Babu A J
2013-08-06 23:14:16 -07:00
2 changed files with 74 additions and 30 deletions
@@ -312,30 +312,41 @@ public class CalendarHelper {
public static LocalDate getNewRepaymentMeetingDate(final String recurringRule, final LocalDate seedDate, final LocalDate oldRepaymentDate, final Integer loanRepaymentInterval, final String frequency, final WorkingDays workingDays){ public static LocalDate getNewRepaymentMeetingDate(final String recurringRule, final LocalDate seedDate, final LocalDate oldRepaymentDate, final Integer loanRepaymentInterval, final String frequency, final WorkingDays workingDays){
final Recur recur = CalendarHelper.getICalRecur(recurringRule); final Recur recur = CalendarHelper.getICalRecur(recurringRule);
if (recur == null) { return null; } if (recur == null) { return null; }
if(isValidRecurringDate(recur, seedDate, oldRepaymentDate)){ if(isValidRecurringDate(recur, seedDate, oldRepaymentDate)){
return oldRepaymentDate; return oldRepaymentDate;
} }
/* Recurring dates should follow loanRepaymentInterval. return getNextRepaymentMeetingDate(recurringRule, seedDate, oldRepaymentDate, loanRepaymentInterval, frequency, workingDays);
e.g. The weekly meeting will have interval of 1, if the loan product with fortnightly frequency will have interval of 2, }
to generate right set of meeting dates reset interval same as loan repayment interval.
*/ public static LocalDate getNextRepaymentMeetingDate(final String recurringRule, final LocalDate seedDate, final LocalDate repaymentDate, final Integer loanRepaymentInterval, final String frequency, final WorkingDays workingDays){
recur.setInterval(loanRepaymentInterval);
final Recur recur = CalendarHelper.getICalRecur(recurringRule);
/*Recurring dates should follow loanRepayment frequency. if (recur == null) { return null; }
//e.g. daily meeting frequency should support all loan products with any type of frequency. LocalDate tmpDate = repaymentDate;
to generate right set of meeting dates reset frequency same as loan repayment frequency. if(isValidRecurringDate(recur, seedDate, repaymentDate)){
*/ tmpDate = repaymentDate.plusDays(1);
if(recur.getFrequency().equals(Recur.DAILY)){ }
recur.setFrequency(frequency); /* Recurring dates should follow loanRepaymentInterval.
} *
e.g. The weekly meeting will have interval of 1, if the loan product with fortnightly frequency will have interval of 2,
LocalDate newRepaymentDate = getNextRecurringDate(recur, seedDate, oldRepaymentDate); to generate right set of meeting dates reset interval same as loan repayment interval.
LocalDate nextRepaymentDate = getNextRecurringDate(recur, seedDate, newRepaymentDate); */
recur.setInterval(loanRepaymentInterval);
newRepaymentDate = WorkingDaysUtil.getOffSetDateIfNonWorkingDay(newRepaymentDate, nextRepaymentDate, workingDays);
/*Recurring dates should follow loanRepayment frequency.
return newRepaymentDate; //e.g. daily meeting frequency should support all loan products with any type of frequency.
to generate right set of meeting dates reset frequency same as loan repayment frequency.
*/
if(recur.getFrequency().equals(Recur.DAILY)){
recur.setFrequency(frequency);
}
LocalDate newRepaymentDate = getNextRecurringDate(recur, seedDate, tmpDate);
LocalDate nextRepaymentDate = getNextRecurringDate(recur, seedDate, newRepaymentDate);
newRepaymentDate = WorkingDaysUtil.getOffSetDateIfNonWorkingDay(newRepaymentDate, nextRepaymentDate, workingDays);
return newRepaymentDate;
} }
public static boolean isFrequencySame(final String oldRRule, final String newRRule) { public static boolean isFrequencySame(final String oldRRule, final String newRRule) {
@@ -2395,23 +2395,33 @@ public class Loan extends AbstractPersistable<Long> {
public void updateLoanRepaymentScheduleDates(final LocalDate meetingStartDate, final String recuringRule, public void updateLoanRepaymentScheduleDates(final LocalDate meetingStartDate, final String recuringRule,
final boolean isHolidayEnabled, final List<Holiday> holidays, final WorkingDays workingDays) { final boolean isHolidayEnabled, final List<Holiday> holidays, final WorkingDays workingDays) {
//update repayment dates of repayment schedule installaments
LocalDate tmpFromDate = this.getDisbursementDate();//first repayment's from date is same as disbursement date. LocalDate tmpFromDate = this.getDisbursementDate();
final PeriodFrequencyType repaymentPeriodFrequencyType = this.loanRepaymentScheduleDetail.getRepaymentPeriodFrequencyType();
final Integer loanRepaymentInterval = this.loanRepaymentScheduleDetail.getRepayEvery();
final String frequency = CalendarHelper.getMeetingFrequencyFromPeriodFrequencyType(repaymentPeriodFrequencyType);
LocalDate newRepaymentDate = null; LocalDate newRepaymentDate = null;
for (LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : this.repaymentScheduleInstallments) { for (LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : this.repaymentScheduleInstallments) {
final LocalDate oldDueDate = loanRepaymentScheduleInstallment.getDueDate(); final LocalDate oldDueDate = loanRepaymentScheduleInstallment.getDueDate();
// FIXME: AA this won't update repayment dates before current date. // FIXME: AA this won't update repayment dates before current date.
if (oldDueDate.isAfter(meetingStartDate) && oldDueDate.isAfter(DateUtils.getLocalDateOfTenant())) { if (oldDueDate.isAfter(meetingStartDate) && oldDueDate.isAfter(DateUtils.getLocalDateOfTenant())) {
final PeriodFrequencyType repaymentPeriodFrequencyType = this.loanRepaymentScheduleDetail.getRepaymentPeriodFrequencyType();
final String frequency = CalendarHelper.getMeetingFrequencyFromPeriodFrequencyType(repaymentPeriodFrequencyType);
final Integer loanRepaymentInterval = this.loanRepaymentScheduleDetail.getRepayEvery();
// reset repayment date with new meeting date newRepaymentDate = CalendarHelper.getNewRepaymentMeetingDate(recuringRule, meetingStartDate, oldDueDate,
newRepaymentDate = CalendarHelper.getNewRepaymentMeetingDate(recuringRule, meetingStartDate, oldDueDate, loanRepaymentInterval, frequency, workingDays); loanRepaymentInterval, frequency, workingDays);
if(isHolidayEnabled){
final LocalDate maxDateLimitForNewRepayment = getMaxDateLimitForNewRepayment(repaymentPeriodFrequencyType,
loanRepaymentInterval, tmpFromDate);
if (newRepaymentDate.isAfter(maxDateLimitForNewRepayment)) {
newRepaymentDate = CalendarHelper.getNextRepaymentMeetingDate(recuringRule, meetingStartDate, tmpFromDate,
loanRepaymentInterval, frequency, workingDays);
}
if (isHolidayEnabled) {
newRepaymentDate = HolidayUtil.getRepaymentRescheduleDateToIfHoliday(newRepaymentDate, holidays); newRepaymentDate = HolidayUtil.getRepaymentRescheduleDateToIfHoliday(newRepaymentDate, holidays);
} }
loanRepaymentScheduleInstallment.updateDueDate(newRepaymentDate); loanRepaymentScheduleInstallment.updateDueDate(newRepaymentDate);
// reset from date to get actual daysInPeriod // reset from date to get actual daysInPeriod
loanRepaymentScheduleInstallment.updateFromDate(tmpFromDate); loanRepaymentScheduleInstallment.updateFromDate(tmpFromDate);
@@ -2423,6 +2433,29 @@ public class Loan extends AbstractPersistable<Long> {
} }
} }
private LocalDate getMaxDateLimitForNewRepayment(final PeriodFrequencyType periodFrequencyType, final Integer loanRepaymentInterval,
final LocalDate startDate) {
LocalDate dueRepaymentPeriodDate = startDate;
final Integer repaidEvery = 2*loanRepaymentInterval;
switch (periodFrequencyType) {
case DAYS:
dueRepaymentPeriodDate = startDate.plusDays(repaidEvery);
break;
case WEEKS:
dueRepaymentPeriodDate = startDate.plusWeeks(repaidEvery);
break;
case MONTHS:
dueRepaymentPeriodDate = startDate.plusMonths(repaidEvery);
break;
case YEARS:
dueRepaymentPeriodDate = startDate.plusYears(repaidEvery);
break;
case INVALID:
break;
}
return dueRepaymentPeriodDate.minusDays(1);//get 2n-1 range date from startDate
}
public void applyHolidayToRepaymentScheduleDates(final Holiday holiday) { public void applyHolidayToRepaymentScheduleDates(final Holiday holiday) {
// first repayment's from date is same as disbursement date. // first repayment's from date is same as disbursement date.
LocalDate tmpFromDate = this.getDisbursementDate(); LocalDate tmpFromDate = this.getDisbursementDate();