Skip to content

Commit 23fc45c

Browse files
logoutdhavalDhaval Maniyar
authored andcommitted
FINERACT-1746: Random Installments Generation Issue (#2629)
Co-authored-by: Dhaval Maniyar <dhavalmaniyar@Dhavals-MacBook-Pro.local>
1 parent 783c484 commit 23fc45c

5 files changed

Lines changed: 350 additions & 35 deletions

File tree

fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/LoanScheduleParams.java

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.List;
2626
import java.util.Map;
2727
import java.util.TreeMap;
28+
import lombok.Getter;
2829
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
2930
import org.apache.fineract.organisation.monetary.domain.Money;
3031
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
@@ -40,6 +41,8 @@ public final class LoanScheduleParams {
4041

4142
private LocalDate periodStartDate;
4243
private LocalDate actualRepaymentDate;
44+
@Getter
45+
private LocalDate originalRepaymentDate;
4346

4447
// variables for cumulative totals
4548
private Money totalCumulativePrincipal;
@@ -100,20 +103,21 @@ public void setCompoundedInLastInstallment(Money compoundedInLastInstallment) {
100103
private final boolean applyInterestRecalculation;
101104

102105
private LoanScheduleParams(final int periodNumber, final int instalmentNumber, int loanTermInDays, LocalDate periodStartDate,
103-
final LocalDate actualRepaymentDate, final Money totalCumulativePrincipal, final Money totalCumulativeInterest,
104-
final Money totalFeeChargesCharged, final Money totalPenaltyChargesCharged, final Money totalRepaymentExpected,
105-
Money totalOutstandingInterestPaymentDueToGrace, final Money reducePrincipal, final Map<LocalDate, Money> principalPortionMap,
106-
final Map<LocalDate, Money> latePaymentMap, final Map<LocalDate, Money> compoundingMap, final Money unCompoundedAmount,
107-
final Map<LocalDate, Money> disburseDetailMap, Money principalToBeScheduled, final Money outstandingBalance,
108-
final Money outstandingBalanceAsPerRest, final List<LoanRepaymentScheduleInstallment> installments,
109-
final Collection<RecalculationDetail> recalculationDetails,
106+
final LocalDate actualRepaymentDate, final LocalDate originalRepaymentDate, final Money totalCumulativePrincipal,
107+
final Money totalCumulativeInterest, final Money totalFeeChargesCharged, final Money totalPenaltyChargesCharged,
108+
final Money totalRepaymentExpected, Money totalOutstandingInterestPaymentDueToGrace, final Money reducePrincipal,
109+
final Map<LocalDate, Money> principalPortionMap, final Map<LocalDate, Money> latePaymentMap,
110+
final Map<LocalDate, Money> compoundingMap, final Money unCompoundedAmount, final Map<LocalDate, Money> disburseDetailMap,
111+
Money principalToBeScheduled, final Money outstandingBalance, final Money outstandingBalanceAsPerRest,
112+
final List<LoanRepaymentScheduleInstallment> installments, final Collection<RecalculationDetail> recalculationDetails,
110113
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor, final LocalDate scheduleTillDate,
111114
final boolean partialUpdate, final MonetaryCurrency currency, final boolean applyInterestRecalculation) {
112115
this.periodNumber = periodNumber;
113116
this.instalmentNumber = instalmentNumber;
114117
this.loanTermInDays = loanTermInDays;
115118
this.periodStartDate = periodStartDate;
116119
this.actualRepaymentDate = actualRepaymentDate;
120+
this.originalRepaymentDate = originalRepaymentDate;
117121
this.totalCumulativePrincipal = totalCumulativePrincipal;
118122
this.totalCumulativeInterest = totalCumulativeInterest;
119123
this.totalFeeChargesCharged = totalFeeChargesCharged;
@@ -142,22 +146,22 @@ private LoanScheduleParams(final int periodNumber, final int instalmentNumber, i
142146
}
143147

144148
public static LoanScheduleParams createLoanScheduleParamsForPartialUpdate(final int periodNumber, final int instalmentNumber,
145-
int loanTermInDays, LocalDate periodStartDate, final LocalDate actualRepaymentDate, final Money totalCumulativePrincipal,
146-
final Money totalCumulativeInterest, final Money totalFeeChargesCharged, final Money totalPenaltyChargesCharged,
147-
final Money totalRepaymentExpected, Money totalOutstandingInterestPaymentDueToGrace, final Money reducePrincipal,
148-
final Map<LocalDate, Money> principalPortionMap, final Map<LocalDate, Money> latePaymentMap,
149+
int loanTermInDays, LocalDate periodStartDate, final LocalDate actualRepaymentDate, final LocalDate originalRepaymentDate,
150+
final Money totalCumulativePrincipal, final Money totalCumulativeInterest, final Money totalFeeChargesCharged,
151+
final Money totalPenaltyChargesCharged, final Money totalRepaymentExpected, Money totalOutstandingInterestPaymentDueToGrace,
152+
final Money reducePrincipal, final Map<LocalDate, Money> principalPortionMap, final Map<LocalDate, Money> latePaymentMap,
149153
final Map<LocalDate, Money> compoundingMap, Money unCompoundedAmount, final Map<LocalDate, Money> disburseDetailMap,
150154
final Money principalToBeScheduled, final Money outstandingBalance, final Money outstandingBalanceAsPerRest,
151155
final List<LoanRepaymentScheduleInstallment> installments, final Collection<RecalculationDetail> recalculationDetails,
152156
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor, final LocalDate scheduleTillDate,
153157
final MonetaryCurrency currency, final boolean applyInterestRecalculation) {
154158
final boolean partialUpdate = true;
155159
return new LoanScheduleParams(periodNumber, instalmentNumber, loanTermInDays, periodStartDate, actualRepaymentDate,
156-
totalCumulativePrincipal, totalCumulativeInterest, totalFeeChargesCharged, totalPenaltyChargesCharged,
157-
totalRepaymentExpected, totalOutstandingInterestPaymentDueToGrace, reducePrincipal, principalPortionMap, latePaymentMap,
158-
compoundingMap, unCompoundedAmount, disburseDetailMap, principalToBeScheduled, outstandingBalance,
159-
outstandingBalanceAsPerRest, installments, recalculationDetails, loanRepaymentScheduleTransactionProcessor,
160-
scheduleTillDate, partialUpdate, currency, applyInterestRecalculation);
160+
originalRepaymentDate, totalCumulativePrincipal, totalCumulativeInterest, totalFeeChargesCharged,
161+
totalPenaltyChargesCharged, totalRepaymentExpected, totalOutstandingInterestPaymentDueToGrace, reducePrincipal,
162+
principalPortionMap, latePaymentMap, compoundingMap, unCompoundedAmount, disburseDetailMap, principalToBeScheduled,
163+
outstandingBalance, outstandingBalanceAsPerRest, installments, recalculationDetails,
164+
loanRepaymentScheduleTransactionProcessor, scheduleTillDate, partialUpdate, currency, applyInterestRecalculation);
161165
}
162166

163167
public static LoanScheduleParams createLoanScheduleParamsForCompleteUpdate(final Collection<RecalculationDetail> recalculationDetails,
@@ -167,6 +171,7 @@ public static LoanScheduleParams createLoanScheduleParamsForCompleteUpdate(final
167171
final int instalmentNumber = 1;
168172
final LocalDate periodStartDate = null;
169173
final LocalDate actualRepaymentDate = null;
174+
final LocalDate originalRepaymentDate = null;
170175
final Money totalCumulativePrincipal = null;
171176
final Money totalCumulativeInterest = null;
172177
final Money totalFeeChargesCharged = null;
@@ -187,11 +192,11 @@ public static LoanScheduleParams createLoanScheduleParamsForCompleteUpdate(final
187192
final MonetaryCurrency currency = null;
188193
final Money unCompoundedAmount = null;
189194
return new LoanScheduleParams(periodNumber, instalmentNumber, loanTermInDays, periodStartDate, actualRepaymentDate,
190-
totalCumulativePrincipal, totalCumulativeInterest, totalFeeChargesCharged, totalPenaltyChargesCharged,
191-
totalRepaymentExpected, totalOutstandingInterestPaymentDueToGrace, reducePrincipal, principalPortionMap, latePaymentMap,
192-
compoundingMap, unCompoundedAmount, disburseDetailMap, principalToBeScheduled, outstandingBalance,
193-
outstandingBalanceAsPerRest, installments, recalculationDetails, loanRepaymentScheduleTransactionProcessor,
194-
scheduleTillDate, partialUpdate, currency, applyInterestRecalculation);
195+
originalRepaymentDate, totalCumulativePrincipal, totalCumulativeInterest, totalFeeChargesCharged,
196+
totalPenaltyChargesCharged, totalRepaymentExpected, totalOutstandingInterestPaymentDueToGrace, reducePrincipal,
197+
principalPortionMap, latePaymentMap, compoundingMap, unCompoundedAmount, disburseDetailMap, principalToBeScheduled,
198+
outstandingBalance, outstandingBalanceAsPerRest, installments, recalculationDetails,
199+
loanRepaymentScheduleTransactionProcessor, scheduleTillDate, partialUpdate, currency, applyInterestRecalculation);
195200
}
196201

197202
public static LoanScheduleParams createLoanScheduleParams(final MonetaryCurrency currency, final Money chargesDueAtTimeOfDisbursement,
@@ -202,6 +207,7 @@ public static LoanScheduleParams createLoanScheduleParams(final MonetaryCurrency
202207
final Money totalCumulativePrincipal = Money.zero(currency);
203208
final Money totalCumulativeInterest = Money.zero(currency);
204209
final Money totalOutstandingInterestPaymentDueToGrace = Money.zero(currency);
210+
final LocalDate originalRepaymentDate = periodStartDate;
205211
final LocalDate actualRepaymentDate = periodStartDate;
206212
final Money totalFeeChargesCharged = chargesDueAtTimeOfDisbursement;
207213
final Money totalPenaltyChargesCharged = Money.zero(currency);
@@ -221,11 +227,11 @@ public static LoanScheduleParams createLoanScheduleParams(final MonetaryCurrency
221227
final boolean applyInterestRecalculation = false;
222228
final Money unCompoundedAmount = Money.zero(currency);
223229
return new LoanScheduleParams(periodNumber, instalmentNumber, loanTermInDays, periodStartDate, actualRepaymentDate,
224-
totalCumulativePrincipal, totalCumulativeInterest, totalFeeChargesCharged, totalPenaltyChargesCharged,
225-
totalRepaymentExpected, totalOutstandingInterestPaymentDueToGrace, reducePrincipal, principalPortionMap, latePaymentMap,
226-
compoundingMap, unCompoundedAmount, disburseDetailMap, principalToBeScheduled, outstandingBalance,
227-
outstandingBalanceAsPerRest, installments, recalculationDetails, loanRepaymentScheduleTransactionProcessor,
228-
scheduleTillDate, partialUpdate, currency, applyInterestRecalculation);
230+
originalRepaymentDate, totalCumulativePrincipal, totalCumulativeInterest, totalFeeChargesCharged,
231+
totalPenaltyChargesCharged, totalRepaymentExpected, totalOutstandingInterestPaymentDueToGrace, reducePrincipal,
232+
principalPortionMap, latePaymentMap, compoundingMap, unCompoundedAmount, disburseDetailMap, principalToBeScheduled,
233+
outstandingBalance, outstandingBalanceAsPerRest, installments, recalculationDetails,
234+
loanRepaymentScheduleTransactionProcessor, scheduleTillDate, partialUpdate, currency, applyInterestRecalculation);
229235
}
230236

231237
public static LoanScheduleParams createLoanScheduleParams(final MonetaryCurrency currency, final Money chargesDueAtTimeOfDisbursement,
@@ -236,6 +242,7 @@ public static LoanScheduleParams createLoanScheduleParams(final MonetaryCurrency
236242
final Money totalCumulativePrincipal = Money.zero(currency);
237243
final Money totalCumulativeInterest = Money.zero(currency);
238244
final Money totalOutstandingInterestPaymentDueToGrace = Money.zero(currency);
245+
final LocalDate originalRepaymentDate = periodStartDate;
239246
final LocalDate actualRepaymentDate = periodStartDate;
240247
final Money totalFeeChargesCharged = chargesDueAtTimeOfDisbursement;
241248
final Money totalPenaltyChargesCharged = Money.zero(currency);
@@ -255,11 +262,11 @@ public static LoanScheduleParams createLoanScheduleParams(final MonetaryCurrency
255262
final boolean applyInterestRecalculation = loanScheduleParams.applyInterestRecalculation;
256263
final Money unCompoundedAmount = Money.zero(currency);
257264
return new LoanScheduleParams(periodNumber, instalmentNumber, loanTermInDays, periodStartDate, actualRepaymentDate,
258-
totalCumulativePrincipal, totalCumulativeInterest, totalFeeChargesCharged, totalPenaltyChargesCharged,
259-
totalRepaymentExpected, totalOutstandingInterestPaymentDueToGrace, reducePrincipal, principalPortionMap, latePaymentMap,
260-
compoundingMap, unCompoundedAmount, disburseDetailMap, principalToBeScheduled, outstandingBalance,
261-
outstandingBalanceAsPerRest, installments, recalculationDetails, loanRepaymentScheduleTransactionProcessor,
262-
scheduleTillDate, partialUpdate, currency, applyInterestRecalculation);
265+
originalRepaymentDate, totalCumulativePrincipal, totalCumulativeInterest, totalFeeChargesCharged,
266+
totalPenaltyChargesCharged, totalRepaymentExpected, totalOutstandingInterestPaymentDueToGrace, reducePrincipal,
267+
principalPortionMap, latePaymentMap, compoundingMap, unCompoundedAmount, disburseDetailMap, principalToBeScheduled,
268+
outstandingBalance, outstandingBalanceAsPerRest, installments, recalculationDetails,
269+
loanRepaymentScheduleTransactionProcessor, scheduleTillDate, partialUpdate, currency, applyInterestRecalculation);
263270
}
264271

265272
public int getPeriodNumber() {
@@ -390,6 +397,10 @@ public void setActualRepaymentDate(LocalDate actualRepaymentDate) {
390397
this.actualRepaymentDate = actualRepaymentDate;
391398
}
392399

400+
public void setOriginalRepaymentDate(LocalDate originalRepaymentDate) {
401+
this.originalRepaymentDate = originalRepaymentDate;
402+
}
403+
393404
public void setReducePrincipal(Money reducePrincipal) {
394405
this.reducePrincipal = reducePrincipal;
395406
}

fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2129,6 +2129,7 @@ private LoanScheduleDTO rescheduleNextInstallments(final MathContext mc, final L
21292129
if (loanApplicationTerms.isInterestRecalculationEnabled()) {
21302130
lastRestDate = getNextRestScheduleDate(currentDate.minusDays(1), loanApplicationTerms, holidayDetailDTO);
21312131
}
2132+
21322133
LocalDate actualRepaymentDate = loanApplicationTerms.getExpectedDisbursementDate();
21332134
boolean isFirstRepayment = true;
21342135

@@ -2144,6 +2145,7 @@ private LoanScheduleDTO rescheduleNextInstallments(final MathContext mc, final L
21442145
// Actual period Number plus interest only repayments
21452146
int instalmentNumber = 1;
21462147
LocalDate lastInstallmentDate = actualRepaymentDate;
2148+
LocalDate originalRepaymentDate = lastInstallmentDate;
21472149
LocalDate periodStartDate = loanApplicationTerms.getExpectedDisbursementDate();
21482150
// Set fixed Amortization Amounts(either EMI or Principal )
21492151
updateAmortization(mc, loanApplicationTerms, periodNumber, outstandingBalance);
@@ -2193,23 +2195,27 @@ private LoanScheduleDTO rescheduleNextInstallments(final MathContext mc, final L
21932195
actualRepaymentDate = this.scheduledDateGenerator.generateNextRepaymentDate(actualRepaymentDate,
21942196
loanApplicationTerms, isFirstRepayment);
21952197
if (actualRepaymentDate.isAfter(rescheduleFrom) || actualRepaymentDate.isEqual(rescheduleFrom)) {
2196-
actualRepaymentDate = lastInstallmentDate;
2198+
actualRepaymentDate = originalRepaymentDate;
21972199
}
21982200
isFirstRepayment = false;
21992201
LocalDate prevLastInstDate = lastInstallmentDate;
2202+
originalRepaymentDate = actualRepaymentDate.plusMonths(1);
22002203
lastInstallmentDate = this.scheduledDateGenerator
22012204
.adjustRepaymentDate(actualRepaymentDate, loanApplicationTerms, holidayDetailDTO).getChangedScheduleDate();
22022205
LocalDate modifiedLastInstDate = null;
22032206
LoanTermVariationsData variation1 = null;
2207+
2208+
boolean hasDueDateVariation = false;
22042209
while (loanApplicationTerms.getLoanTermVariations().hasDueDateVariation(lastInstallmentDate)) {
2210+
hasDueDateVariation = true;
22052211
LoanTermVariationsData variation = loanApplicationTerms.getLoanTermVariations().nextDueDateVariation();
22062212
if (!variation.isSpecificToInstallment()) {
22072213
modifiedLastInstDate = variation.getDateValue();
22082214
variation1 = variation;
22092215
}
22102216
}
22112217

2212-
if (!lastInstallmentDate.isEqual(installment.getDueDate())
2218+
if (hasDueDateVariation && !lastInstallmentDate.isEqual(installment.getDueDate())
22132219
&& !installment.getDueDate().equals(modifiedLastInstDate)) {
22142220
lastInstallmentDate = prevLastInstDate;
22152221
actualRepaymentDate = lastInstallmentDate;
@@ -2347,15 +2353,16 @@ private LoanScheduleDTO rescheduleNextInstallments(final MathContext mc, final L
23472353
if (!newRepaymentScheduleInstallments.isEmpty() && totalCumulativeInterest.isGreaterThanZero()) {
23482354
Money totalOutstandingInterestPaymentDueToGrace = Money.zero(currency);
23492355
loanScheduleParams = LoanScheduleParams.createLoanScheduleParamsForPartialUpdate(periodNumber, instalmentNumber,
2350-
loanTermInDays, periodStartDate, actualRepaymentDate, totalCumulativePrincipal, totalCumulativeInterest,
2351-
totalFeeChargesCharged, totalPenaltyChargesCharged, totalRepaymentExpected,
2356+
loanTermInDays, periodStartDate, actualRepaymentDate, originalRepaymentDate, totalCumulativePrincipal,
2357+
totalCumulativeInterest, totalFeeChargesCharged, totalPenaltyChargesCharged, totalRepaymentExpected,
23522358
totalOutstandingInterestPaymentDueToGrace, reducePrincipal, principalPortionMap, latePaymentMap, compoundingMap,
23532359
uncompoundedAmount, disburseDetailMap, principalToBeScheduled, outstandingBalance, outstandingBalanceAsPerRest,
23542360
newRepaymentScheduleInstallments, recalculationDetails, loanRepaymentScheduleTransactionProcessor, scheduleTillDate,
23552361
currency, applyInterestRecalculation);
23562362
retainedInstallments.addAll(newRepaymentScheduleInstallments);
23572363
loanScheduleParams.getCompoundingDateVariations().putAll(compoundingDateVariations);
23582364
loanApplicationTerms.updateTotalInterestDue(Money.of(currency, loan.getLoanSummary().getTotalInterestCharged()));
2365+
loanScheduleParams.setOriginalRepaymentDate(originalRepaymentDate);
23592366
} else {
23602367
loanApplicationTerms.getLoanTermVariations().resetVariations();
23612368
}

0 commit comments

Comments
 (0)