http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelDisbursementPeriod.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelDisbursementPeriod.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelDisbursementPeriod.java index acb33a8..87d2332 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelDisbursementPeriod.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelDisbursementPeriod.java @@ -19,8 +19,10 @@ package org.apache.fineract.portfolio.loanaccount.loanschedule.domain; import java.math.BigDecimal; +import java.util.List; import org.apache.fineract.organisation.monetary.domain.Money; +import org.apache.fineract.portfolio.loanaccount.domain.LoanInterestRecalcualtionAdditionalDetails; import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePeriodData; import org.joda.time.LocalDate; @@ -122,4 +124,8 @@ public final class LoanScheduleModelDisbursementPeriod implements LoanScheduleMo public void addInterestAmount(@SuppressWarnings("unused") Money principalDue) { return; } + @Override + public List<LoanInterestRecalcualtionAdditionalDetails> getLoanCompoundingDetails() { + return null; + } } \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelPeriod.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelPeriod.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelPeriod.java index 7792416..db67677 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelPeriod.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelPeriod.java @@ -19,8 +19,10 @@ package org.apache.fineract.portfolio.loanaccount.loanschedule.domain; import java.math.BigDecimal; +import java.util.List; import org.apache.fineract.organisation.monetary.domain.Money; +import org.apache.fineract.portfolio.loanaccount.domain.LoanInterestRecalcualtionAdditionalDetails; import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePeriodData; import org.joda.time.LocalDate; @@ -51,4 +53,5 @@ public interface LoanScheduleModelPeriod { void addPrincipalAmount(Money principalDue); void addInterestAmount(Money interestDue); + List<LoanInterestRecalcualtionAdditionalDetails> getLoanCompoundingDetails(); } http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelRepaymentPeriod.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelRepaymentPeriod.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelRepaymentPeriod.java index 5b8208e..201e7ca 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelRepaymentPeriod.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelRepaymentPeriod.java @@ -19,8 +19,11 @@ package org.apache.fineract.portfolio.loanaccount.loanschedule.domain; import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; import org.apache.fineract.organisation.monetary.domain.Money; +import org.apache.fineract.portfolio.loanaccount.domain.LoanInterestRecalcualtionAdditionalDetails; import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePeriodData; import org.joda.time.LocalDate; @@ -40,6 +43,7 @@ public final class LoanScheduleModelRepaymentPeriod implements LoanScheduleModel private Money penaltyChargesDue; private Money totalDue; private final boolean recalculatedInterestComponent; + private final List<LoanInterestRecalcualtionAdditionalDetails> loanCompoundingDetails = new ArrayList<>(); public static LoanScheduleModelRepaymentPeriod repayment(final int periodNumber, final LocalDate startDate, final LocalDate scheduledDueDate, final Money principalDue, final Money outstandingLoanBalance, final Money interestDue, @@ -154,4 +158,8 @@ public final class LoanScheduleModelRepaymentPeriod implements LoanScheduleModel this.interestDue = this.interestDue.plus(interestDue); this.totalDue = this.totalDue.plus(principalDue); } + @Override + public List<LoanInterestRecalcualtionAdditionalDetails> getLoanCompoundingDetails() { + return this.loanCompoundingDetails; + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ScheduledDateGenerator.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ScheduledDateGenerator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ScheduledDateGenerator.java index 3761ce0..c82301d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ScheduledDateGenerator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ScheduledDateGenerator.java @@ -18,6 +18,7 @@ */ package org.apache.fineract.portfolio.loanaccount.loanschedule.domain; +import org.apache.fineract.portfolio.calendar.domain.Calendar; import org.apache.fineract.portfolio.common.domain.DayOfWeekType; import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType; import org.apache.fineract.portfolio.loanaccount.data.HolidayDetailDTO; @@ -28,7 +29,8 @@ public interface ScheduledDateGenerator { LocalDate getLastRepaymentDate(LoanApplicationTerms loanApplicationTerms, final HolidayDetailDTO holidayDetailDTO); LocalDate idealDisbursementDateBasedOnFirstRepaymentDate(PeriodFrequencyType repaymentPeriodFrequencyType, int repaidEvery, - final LocalDate firstRepaymentDate); + final LocalDate firstRepaymentDate, final Calendar loanCalendar, final HolidayDetailDTO holidayDetailDTO, + final LoanApplicationTerms loanApplicationTerms); LocalDate generateNextRepaymentDate(LocalDate lastRepaymentDate, LoanApplicationTerms loanApplicationTerms, boolean isFirstRepayment, final HolidayDetailDTO holidayDetailDTO); http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java index 56248ec..b86f2a7 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java @@ -68,6 +68,7 @@ import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper; import org.apache.fineract.portfolio.common.domain.DayOfWeekType; import org.apache.fineract.portfolio.common.domain.DaysInMonthType; import org.apache.fineract.portfolio.common.domain.DaysInYearType; +import org.apache.fineract.portfolio.common.domain.NthDayType; import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType; import org.apache.fineract.portfolio.floatingrates.data.FloatingRateDTO; import org.apache.fineract.portfolio.floatingrates.data.FloatingRatePeriodData; @@ -115,7 +116,6 @@ import org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations; import org.apache.fineract.useradministration.domain.AppUser; import org.joda.time.Days; import org.joda.time.LocalDate; -import org.joda.time.LocalTime; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -256,6 +256,12 @@ public class LoanScheduleAssembler { final PeriodFrequencyType meetingPeriodFrequency = CalendarUtils.getMeetingPeriodFrequencyType(calendar.getRecurrence()); validateRepaymentFrequencyIsSameAsMeetingFrequency(meetingPeriodFrequency.getValue(), repaymentFrequencyType, CalendarUtils.getInterval(calendar.getRecurrence()), repaymentEvery); + } else { + if (repaymentPeriodFrequencyType == PeriodFrequencyType.MONTHS && nthDay != null && nthDay != NthDayType.INVALID.getValue()) { + LocalDate calendarStartDate = repaymentsStartingFromDate; + if (calendarStartDate == null) calendarStartDate = expectedDisbursementDate; + calendar = createLoanCalendar(calendarStartDate, repaymentEvery, CalendarFrequencyType.MONTHLY, dayOfWeek, nthDay); + } } /* @@ -306,7 +312,8 @@ public class LoanScheduleAssembler { final Integer graceOnInterestPayment = this.fromApiJsonHelper.extractIntegerWithLocaleNamed("graceOnInterestPayment", element); final Integer graceOnInterestCharged = this.fromApiJsonHelper.extractIntegerWithLocaleNamed("graceOnInterestCharged", element); final LocalDate interestChargedFromDate = this.fromApiJsonHelper.extractLocalDateNamed("interestChargedFromDate", element); - final Boolean isInterestChargedFromDateSameAsDisbursalDateEnabled = this.configurationDomainService.isInterestChargedFromDateSameAsDisbursementDate(); + final Boolean isInterestChargedFromDateSameAsDisbursalDateEnabled = this.configurationDomainService + .isInterestChargedFromDateSameAsDisbursementDate(); final Integer graceOnArrearsAgeing = this.fromApiJsonHelper.extractIntegerWithLocaleNamed( LoanProductConstants.graceOnArrearsAgeingParameterName, element); @@ -334,39 +341,47 @@ public class LoanScheduleAssembler { CalendarInstance restCalendarInstance = null; RecalculationFrequencyType compoundingFrequencyType = null; CalendarInstance compoundingCalendarInstance = null; + InterestRecalculationCompoundingMethod compoundingMethod = null; + boolean allowCompoundingOnEod = false; if (isInterestRecalculationEnabled) { LoanProductInterestRecalculationDetails loanProductInterestRecalculationDetails = loanProduct .getProductInterestRecalculationDetails(); recalculationFrequencyType = loanProductInterestRecalculationDetails.getRestFrequencyType(); + Integer repeatsOnDay = null; + Integer recalculationFrequencyNthDay = loanProductInterestRecalculationDetails.getRestFrequencyOnDay(); + if (recalculationFrequencyNthDay == null) { + recalculationFrequencyNthDay = loanProductInterestRecalculationDetails.getRestFrequencyNthDay(); + repeatsOnDay = loanProductInterestRecalculationDetails.getRestFrequencyWeekday(); + } + Integer frequency = loanProductInterestRecalculationDetails.getRestInterval(); if (recalculationFrequencyType.isSameAsRepayment()) { restCalendarInstance = createCalendarForSameAsRepayment(repaymentEvery, repaymentPeriodFrequencyType, expectedDisbursementDate); } else { - LocalDate calendarStartDate = this.fromApiJsonHelper.extractLocalDateNamed( - LoanProductConstants.recalculationRestFrequencyDateParamName, element); - if (calendarStartDate == null) { - calendarStartDate = expectedDisbursementDate; - } + LocalDate calendarStartDate = expectedDisbursementDate; restCalendarInstance = createInterestRecalculationCalendarInstance(calendarStartDate, recalculationFrequencyType, - loanProductInterestRecalculationDetails.getRestInterval()); + frequency, recalculationFrequencyNthDay, repeatsOnDay); } - InterestRecalculationCompoundingMethod compoundingMethod = InterestRecalculationCompoundingMethod - .fromInt(loanProductInterestRecalculationDetails.getInterestRecalculationCompoundingMethod()); + compoundingMethod = InterestRecalculationCompoundingMethod.fromInt(loanProductInterestRecalculationDetails + .getInterestRecalculationCompoundingMethod()); if (compoundingMethod.isCompoundingEnabled()) { + Integer compoundingRepeatsOnDay = null; + Integer recalculationCompoundingFrequencyNthDay = loanProductInterestRecalculationDetails.getCompoundingFrequencyOnDay(); + if (recalculationCompoundingFrequencyNthDay == null) { + recalculationCompoundingFrequencyNthDay = loanProductInterestRecalculationDetails.getCompoundingFrequencyNthDay(); + compoundingRepeatsOnDay = loanProductInterestRecalculationDetails.getCompoundingFrequencyWeekday(); + } compoundingFrequencyType = loanProductInterestRecalculationDetails.getCompoundingFrequencyType(); if (compoundingFrequencyType.isSameAsRepayment()) { compoundingCalendarInstance = createCalendarForSameAsRepayment(repaymentEvery, repaymentPeriodFrequencyType, expectedDisbursementDate); } else { - LocalDate calendarStartDate = this.fromApiJsonHelper.extractLocalDateNamed( - LoanProductConstants.recalculationCompoundingFrequencyDateParamName, element); - if (calendarStartDate == null) { - calendarStartDate = expectedDisbursementDate; - } + LocalDate calendarStartDate = expectedDisbursementDate; compoundingCalendarInstance = createInterestRecalculationCalendarInstance(calendarStartDate, compoundingFrequencyType, - loanProductInterestRecalculationDetails.getCompoundingInterval()); + loanProductInterestRecalculationDetails.getCompoundingInterval(), recalculationCompoundingFrequencyNthDay, + compoundingRepeatsOnDay); } - + allowCompoundingOnEod = loanProductInterestRecalculationDetails.allowCompoundingOnEod(); } } @@ -405,6 +420,21 @@ public class LoanScheduleAssembler { } } + final Long clientId = this.fromApiJsonHelper.extractLongNamed("clientId", element); + Client client = null; + Long officeId = null; + if (clientId != null) { + client = this.clientRepository.findOneWithNotFoundDetection(clientId); + officeId = client.getOffice().getId(); + } else if (groupId != null) { + group = this.groupRepository.findOneWithNotFoundDetection(groupId); + officeId = group.getOffice().getId(); + } + final boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled(); + final List<Holiday> holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(officeId, expectedDisbursementDate.toDate(), + HolidayStatusType.ACTIVE.getValue()); + final WorkingDays workingDays = this.workingDaysRepository.findOne(); + HolidayDetailDTO detailDTO = new HolidayDetailDTO(isHolidayEnabled, holidays, workingDays); return LoanApplicationTerms.assembleFrom(applicationCurrency, loanTermFrequency, loanTermPeriodFrequencyType, numberOfRepayments, repaymentEvery, repaymentPeriodFrequencyType, nthDay, weekDayType, amortizationMethod, interestMethod, interestRatePerPeriod, interestRatePeriodFrequencyType, annualNominalInterestRate, interestCalculationPeriodMethod, @@ -412,21 +442,24 @@ public class LoanScheduleAssembler { calculatedRepaymentsStartingFromDate, graceOnPrincipalPayment, recurringMoratoriumOnPrincipalPeriods, graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, inArrearsToleranceMoney, loanProduct.isMultiDisburseLoan(), emiAmount, disbursementDatas, maxOutstandingBalance, graceOnArrearsAgeing, daysInMonthType, daysInYearType, isInterestRecalculationEnabled, - recalculationFrequencyType, restCalendarInstance, compoundingCalendarInstance, compoundingFrequencyType, + recalculationFrequencyType, restCalendarInstance, compoundingMethod, compoundingCalendarInstance, compoundingFrequencyType, principalThresholdForLastInstalment, installmentAmountInMultiplesOf, loanProduct.preCloseInterestCalculationStrategy(), - calendar, BigDecimal.ZERO, loanTermVariations, isInterestChargedFromDateSameAsDisbursalDateEnabled,numberOfDays, isSkipMeetingOnFirstDay); + calendar, BigDecimal.ZERO, loanTermVariations, isInterestChargedFromDateSameAsDisbursalDateEnabled,numberOfDays, isSkipMeetingOnFirstDay, detailDTO, + allowCompoundingOnEod); } private CalendarInstance createCalendarForSameAsRepayment(final Integer repaymentEvery, final PeriodFrequencyType repaymentPeriodFrequencyType, final LocalDate expectedDisbursementDate) { - + final Integer recalculationFrequencyNthDay = null; + final Integer repeatsOnDay = expectedDisbursementDate.getDayOfWeek(); CalendarInstance restCalendarInstance = createInterestRecalculationCalendarInstance(expectedDisbursementDate, repaymentEvery, - CalendarFrequencyType.from(repaymentPeriodFrequencyType)); + CalendarFrequencyType.from(repaymentPeriodFrequencyType), recalculationFrequencyNthDay, repeatsOnDay); return restCalendarInstance; } private CalendarInstance createInterestRecalculationCalendarInstance(final LocalDate calendarStartDate, - final RecalculationFrequencyType recalculationFrequencyType, final Integer frequency) { + final RecalculationFrequencyType recalculationFrequencyType, final Integer frequency, + final Integer recalculationFrequencyNthDay, final Integer repeatsOnDay) { CalendarFrequencyType calendarFrequencyType = CalendarFrequencyType.INVALID; switch (recalculationFrequencyType) { @@ -443,18 +476,26 @@ public class LoanScheduleAssembler { break; } - return createInterestRecalculationCalendarInstance(calendarStartDate, frequency, calendarFrequencyType); + return createInterestRecalculationCalendarInstance(calendarStartDate, frequency, calendarFrequencyType, + recalculationFrequencyNthDay, repeatsOnDay); } private CalendarInstance createInterestRecalculationCalendarInstance(final LocalDate calendarStartDate, final Integer frequency, - CalendarFrequencyType calendarFrequencyType) { - final Integer repeatsOnDay = calendarStartDate.getDayOfWeek(); + CalendarFrequencyType calendarFrequencyType, final Integer recalculationFrequencyNthDay, final Integer repeatsOnDay) { final String title = "loan_recalculation_detail"; final Calendar calendar = Calendar.createRepeatingCalendar(title, calendarStartDate, CalendarType.COLLECTION.getValue(), - calendarFrequencyType, frequency, repeatsOnDay); + calendarFrequencyType, frequency, repeatsOnDay, recalculationFrequencyNthDay); return CalendarInstance.from(calendar, null, CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue()); } + private Calendar createLoanCalendar(final LocalDate calendarStartDate, final Integer frequency, + CalendarFrequencyType calendarFrequencyType, final Integer repeatsOnDay, final Integer repeatsOnNthDayOfMonth) { + final String title = "loan_schedule"; + final Calendar calendar = Calendar.createRepeatingCalendar(title, calendarStartDate, CalendarType.COLLECTION.getValue(), + calendarFrequencyType, frequency, repeatsOnDay, repeatsOnNthDayOfMonth); + return calendar; + } + private List<DisbursementData> fetchDisbursementData(final JsonObject command) { final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(command); final String dateFormat = this.fromApiJsonHelper.extractDateFormatParameter(command); @@ -559,7 +600,7 @@ public class LoanScheduleAssembler { validateDisbursementDateIsOnNonWorkingDay(loanApplicationTerms.getExpectedDisbursementDate(), workingDays); validateDisbursementDateIsOnHoliday(loanApplicationTerms.getExpectedDisbursementDate(), isHolidayEnabled, holidays); - + Set<LoanDisbursementDetails> loanDisbursementDetails = this.loanUtilService.fetchDisbursementData(element.getAsJsonObject()); return assembleLoanScheduleFrom(loanApplicationTerms, isHolidayEnabled, holidays, workingDays, element, loanDisbursementDetails); @@ -996,10 +1037,10 @@ public class LoanScheduleAssembler { final LocalDate dateBasedOnMinimumDaysBetweenDisbursalAndFirstRepayment = expectedDisbursementDate .plusDays(minimumDaysBetweenDisbursalAndFirstRepayment); - if ((loanType.isJLGAccount() || loanType.isGroupAccount()) && calendar != null) { + if (calendar != null) { final LocalDate refernceDateForCalculatingFirstRepaymentDate = expectedDisbursementDate; - derivedFirstRepayment = deriveFirstRepaymentDateForJLGLoans(repaymentEvery, expectedDisbursementDate, + derivedFirstRepayment = deriveFirstRepaymentDateForLoans(repaymentEvery, expectedDisbursementDate, refernceDateForCalculatingFirstRepaymentDate, repaymentPeriodFrequencyType, minimumDaysBetweenDisbursalAndFirstRepayment, calendar); @@ -1027,7 +1068,7 @@ public class LoanScheduleAssembler { return derivedFirstRepayment; } - private LocalDate deriveFirstRepaymentDateForJLGLoans(final Integer repaymentEvery, final LocalDate expectedDisbursementDate, + private LocalDate deriveFirstRepaymentDateForLoans(final Integer repaymentEvery, final LocalDate expectedDisbursementDate, final LocalDate refernceDateForCalculatingFirstRepaymentDate, final PeriodFrequencyType repaymentPeriodFrequencyType, final Integer minimumDaysBetweenDisbursalAndFirstRepayment, final Calendar calendar) { boolean isMeetingSkipOnFirstDayOfMonth = configurationDomainService.isSkippingMeetingOnFirstDayOfMonthEnabled(); @@ -1036,7 +1077,7 @@ public class LoanScheduleAssembler { final LocalDate derivedFirstRepayment = CalendarUtils.getFirstRepaymentMeetingDate(calendar, refernceDateForCalculatingFirstRepaymentDate, repaymentEvery, frequency, isMeetingSkipOnFirstDayOfMonth, numberOfDays); final LocalDate minimumFirstRepaymentDate = expectedDisbursementDate.plusDays(minimumDaysBetweenDisbursalAndFirstRepayment); - return minimumFirstRepaymentDate.isBefore(derivedFirstRepayment) ? derivedFirstRepayment : deriveFirstRepaymentDateForJLGLoans( + return minimumFirstRepaymentDate.isBefore(derivedFirstRepayment) ? derivedFirstRepayment : deriveFirstRepaymentDateForLoans( repaymentEvery, expectedDisbursementDate, derivedFirstRepayment, repaymentPeriodFrequencyType, minimumDaysBetweenDisbursalAndFirstRepayment, calendar); } http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java index 9ab13ee..3a008ab 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java @@ -63,6 +63,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.DefaultLoanLifecycleStat import org.apache.fineract.portfolio.loanaccount.domain.Loan; import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge; import org.apache.fineract.portfolio.loanaccount.domain.LoanInstallmentCharge; +import org.apache.fineract.portfolio.loanaccount.domain.LoanInterestRecalcualtionAdditionalDetails; import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository; @@ -370,13 +371,13 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche final Collection<LoanRescheduleModelRepaymentPeriod> periods = loanRescheduleModel.getPeriods(); List<LoanRepaymentScheduleInstallment> repaymentScheduleInstallments = loan.getRepaymentScheduleInstallments(); Collection<LoanCharge> waiveLoanCharges = new ArrayList<>(); - + final List<LoanInterestRecalcualtionAdditionalDetails> compoundingDetails = null; for (LoanRescheduleModelRepaymentPeriod period : periods) { if (period.isNew()) { LoanRepaymentScheduleInstallment repaymentScheduleInstallment = new LoanRepaymentScheduleInstallment(loan, period.periodNumber(), period.periodFromDate(), period.periodDueDate(), period.principalDue(), - period.interestDue(), BigDecimal.ZERO, BigDecimal.ZERO, false); + period.interestDue(), BigDecimal.ZERO, BigDecimal.ZERO, false, compoundingDetails); repaymentScheduleInstallments.add(repaymentScheduleInstallment); } http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonHelper.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonHelper.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonHelper.java index 48a5c51..a03fe9b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonHelper.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonHelper.java @@ -46,18 +46,29 @@ public final class CalculateLoanScheduleQueryFromApiJsonHelper { /** * The parameters supported for this command. */ - final Set<String> supportedParameters = new HashSet<>(Arrays.asList("id", "clientId", "groupId", "loanType", "calendarId", "productId", - "accountNo", "externalId", "fundId", "loanOfficerId", "loanPurposeId", "transactionProcessingStrategyId", "principal", - "inArrearsTolerance", "interestRatePerPeriod", "repaymentEvery", "numberOfRepayments", "loanTermFrequency", - "loanTermFrequencyType", "repaymentFrequencyType", "amortizationType", "interestType", "interestCalculationPeriodType", - LoanProductConstants.allowPartialPeriodInterestCalcualtionParamName, "interestRateFrequencyType", "expectedDisbursementDate", - "repaymentsStartingFromDate", "graceOnPrincipalPayment", "recurringMoratoriumOnPrincipalPeriods", "graceOnInterestPayment", "graceOnInterestCharged", - "interestChargedFromDate", "submittedOnDate", "submittedOnNote", "locale", "dateFormat", "charges", "collateral", - "syncDisbursementWithMeeting", "linkAccountId", LoanApiConstants.disbursementDataParameterName, + final Set<String> supportedParameters = new HashSet<>(Arrays.asList(LoanApiConstants.idParameterName, + LoanApiConstants.clientIdParameterName, LoanApiConstants.groupIdParameterName, LoanApiConstants.loanTypeParameterName, + LoanApiConstants.calendarIdParameterName, LoanApiConstants.productIdParameterName, LoanApiConstants.accountNoParameterName, + LoanApiConstants.externalIdParameterName, LoanApiConstants.fundIdParameterName, LoanApiConstants.loanOfficerIdParameterName, + LoanApiConstants.loanPurposeIdParameterName, LoanApiConstants.transactionProcessingStrategyIdParameterName, + LoanApiConstants.principalParamName, LoanApiConstants.inArrearsToleranceParameterName, + LoanApiConstants.interestRatePerPeriodParameterName, LoanApiConstants.repaymentEveryParameterName, + LoanApiConstants.numberOfRepaymentsParameterName, LoanApiConstants.loanTermFrequencyParameterName, + LoanApiConstants.loanTermFrequencyTypeParameterName, LoanApiConstants.repaymentFrequencyTypeParameterName, + LoanApiConstants.amortizationTypeParameterName, LoanApiConstants.interestTypeParameterName, + LoanApiConstants.interestCalculationPeriodTypeParameterName, + LoanProductConstants.allowPartialPeriodInterestCalcualtionParamName, LoanApiConstants.interestRateFrequencyTypeParameterName, + LoanApiConstants.disbursementDateParameterName, LoanApiConstants.repaymentsStartingFromDateParameterName, + LoanApiConstants.graceOnPrincipalPaymentParameterName, LoanApiConstants.graceOnInterestPaymentParameterName, + LoanApiConstants.graceOnInterestChargedParameterName, LoanApiConstants.interestChargedFromDateParameterName, + LoanApiConstants.submittedOnDateParameterName, LoanApiConstants.submittedOnNoteParameterName, + LoanApiConstants.localeParameterName, LoanApiConstants.dateFormatParameterName, LoanApiConstants.chargesParameterName, + LoanApiConstants.collateralParameterName, LoanApiConstants.syncDisbursementWithMeetingParameterName, + LoanApiConstants.linkAccountIdParameterName, LoanApiConstants.disbursementDataParameterName, LoanApiConstants.emiAmountParameterName, LoanApiConstants.maxOutstandingBalanceParameterName, - LoanProductConstants.graceOnArrearsAgeingParameterName, LoanProductConstants.recalculationRestFrequencyDateParamName, - "createStandingInstructionAtDisbursement", LoanApiConstants.isFloatingInterestRateParameterName, - LoanApiConstants.interestRateDifferentialParameterName)); + LoanProductConstants.graceOnArrearsAgeingParameterName, LoanApiConstants.createStandingInstructionAtDisbursementParameterName, + LoanApiConstants.isFloatingInterestRateParameterName, LoanApiConstants.interestRateDifferentialParameterName, + LoanApiConstants.repaymentFrequencyNthDayTypeParameterName, LoanApiConstants.repaymentFrequencyDayOfWeekTypeParameterName)); private final FromJsonHelper fromApiJsonHelper; http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java index 6b2c4c4..0eaf4af 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java @@ -36,10 +36,10 @@ import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidati import org.apache.fineract.infrastructure.core.exception.UnsupportedParameterException; import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; import org.apache.fineract.portfolio.accountdetails.domain.AccountType; +import org.apache.fineract.portfolio.calendar.service.CalendarUtils; import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants; import org.apache.fineract.portfolio.loanaccount.domain.Loan; import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge; -import org.apache.fineract.portfolio.loanaccount.domain.LoanInterestRecalculationDetails; import org.apache.fineract.portfolio.loanproduct.LoanProductConstants; import org.apache.fineract.portfolio.loanproduct.domain.InterestCalculationPeriodMethod; import org.apache.fineract.portfolio.loanproduct.domain.InterestMethod; @@ -60,34 +60,38 @@ public final class LoanApplicationCommandFromApiJsonHelper { /** * The parameters supported for this command. */ - final Set<String> supportedParameters = new HashSet<>(Arrays.asList("dateFormat", "locale", "id", "clientId", "groupId", "loanType", - "productId", "principal", "loanTermFrequency", "loanTermFrequencyType", "numberOfRepayments", "repaymentEvery", - "repaymentFrequencyType", "repaymentFrequencyNthDayType", "repaymentFrequencyDayOfWeekType", "interestRatePerPeriod", - "amortizationType", "interestType", LoanApiConstants.isFloatingInterestRate, LoanApiConstants.interestRateDifferential, - "interestCalculationPeriodType", LoanProductConstants.allowPartialPeriodInterestCalcualtionParamName, - "interestRateFrequencyType", "expectedDisbursementDate", "repaymentsStartingFromDate", - "graceOnPrincipalPayment", - "recurringMoratoriumOnPrincipalPeriods", - "graceOnInterestPayment", - "graceOnInterestCharged", - "interestChargedFromDate", - "submittedOnDate", - "submittedOnNote", - "accountNo", - "externalId", - "fundId", - "loanOfficerId", // optional - "loanPurposeId", - "inArrearsTolerance", - "charges", - "collateral", // optional - "transactionProcessingStrategyId", // settings - "calendarId", // optional - "syncDisbursementWithMeeting",// optional - "linkAccountId", LoanApiConstants.disbursementDataParameterName, LoanApiConstants.emiAmountParameterName, - LoanApiConstants.maxOutstandingBalanceParameterName, LoanProductConstants.graceOnArrearsAgeingParameterName, - LoanProductConstants.recalculationRestFrequencyDateParamName, - LoanProductConstants.recalculationCompoundingFrequencyDateParamName, "createStandingInstructionAtDisbursement")); + final Set<String> supportedParameters = new HashSet<>(Arrays.asList(LoanApiConstants.dateFormatParameterName, + LoanApiConstants.localeParameterName, LoanApiConstants.idParameterName, LoanApiConstants.clientIdParameterName, + LoanApiConstants.groupIdParameterName, LoanApiConstants.loanTypeParameterName, LoanApiConstants.productIdParameterName, + LoanApiConstants.principalParamName, LoanApiConstants.loanTermFrequencyParameterName, + LoanApiConstants.loanTermFrequencyTypeParameterName, LoanApiConstants.numberOfRepaymentsParameterName, + LoanApiConstants.repaymentEveryParameterName, LoanApiConstants.repaymentFrequencyTypeParameterName, + LoanApiConstants.repaymentFrequencyNthDayTypeParameterName, LoanApiConstants.repaymentFrequencyDayOfWeekTypeParameterName, + LoanApiConstants.interestRatePerPeriodParameterName, LoanApiConstants.amortizationTypeParameterName, + LoanApiConstants.interestTypeParameterName, LoanApiConstants.isFloatingInterestRate, LoanApiConstants.interestRateDifferential, + LoanApiConstants.interestCalculationPeriodTypeParameterName, + LoanProductConstants.allowPartialPeriodInterestCalcualtionParamName, LoanApiConstants.interestRateFrequencyTypeParameterName, + LoanApiConstants.disbursementDateParameterName, LoanApiConstants.repaymentsStartingFromDateParameterName, + LoanApiConstants.graceOnPrincipalPaymentParameterName, + LoanApiConstants.graceOnInterestPaymentParameterName, + LoanApiConstants.graceOnInterestChargedParameterName, + LoanApiConstants.interestChargedFromDateParameterName, + LoanApiConstants.submittedOnDateParameterName, + LoanApiConstants.submittedOnNoteParameterName, + LoanApiConstants.accountNoParameterName, + LoanApiConstants.externalIdParameterName, + LoanApiConstants.fundIdParameterName, + LoanApiConstants.loanOfficerIdParameterName, // optional + LoanApiConstants.loanPurposeIdParameterName, + LoanApiConstants.inArrearsToleranceParameterName, + LoanApiConstants.chargesParameterName, + LoanApiConstants.collateralParameterName, // optional + LoanApiConstants.transactionProcessingStrategyIdParameterName, // settings + LoanApiConstants.calendarIdParameterName, // optional + LoanApiConstants.syncDisbursementWithMeetingParameterName,// optional + LoanApiConstants.linkAccountIdParameterName, LoanApiConstants.disbursementDataParameterName, + LoanApiConstants.emiAmountParameterName, LoanApiConstants.maxOutstandingBalanceParameterName, + LoanProductConstants.graceOnArrearsAgeingParameterName, LoanApiConstants.createStandingInstructionAtDisbursementParameterName)); private final FromJsonHelper fromApiJsonHelper; private final CalculateLoanScheduleQueryFromApiJsonHelper apiJsonHelper; @@ -214,6 +218,10 @@ public final class LoanApplicationCommandFromApiJsonHelper { baseDataValidator.reset().parameter(repaymentEveryFrequencyTypeParameterName).value(repaymentEveryType).notNull() .inMinMaxRange(0, 3); + final String repaymentFrequencyNthDayTypeParameterName = "repaymentFrequencyNthDayType"; + final String repaymentFrequencyDayOfWeekTypeParameterName = "repaymentFrequencyDayOfWeekType"; + CalendarUtils.validateNthDayOfMonthFrequency(baseDataValidator, repaymentFrequencyNthDayTypeParameterName, + repaymentFrequencyDayOfWeekTypeParameterName, element, this.fromApiJsonHelper); final String interestTypeParameterName = "interestType"; final Integer interestType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(interestTypeParameterName, element); baseDataValidator.reset().parameter(interestTypeParameterName).value(interestType).notNull().inMinMaxRange(0, 1); @@ -591,6 +599,10 @@ public final class LoanApplicationCommandFromApiJsonHelper { element); baseDataValidator.reset().parameter(repaymentEveryTypeParameterName).value(repaymentEveryType).notNull().inMinMaxRange(0, 3); } + final String repaymentFrequencyNthDayTypeParameterName = "repaymentFrequencyNthDayType"; + final String repaymentFrequencyDayOfWeekTypeParameterName = "repaymentFrequencyDayOfWeekType"; + CalendarUtils.validateNthDayOfMonthFrequency(baseDataValidator, repaymentFrequencyNthDayTypeParameterName, + repaymentFrequencyDayOfWeekTypeParameterName, element, this.fromApiJsonHelper); final String interestTypeParameterName = "interestType"; Integer interestType = null; @@ -1095,14 +1107,6 @@ public final class LoanApplicationCommandFromApiJsonHelper { } - public void validateRecalcuationFrequency(final LocalDate recalculationFrequencyDate, final LocalDate expectedDisbursementDate, - final List<ApiParameterError> dataValidationErrors, final String paramName) { - - final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan"); - baseDataValidator.reset().parameter(paramName).value(recalculationFrequencyDate).notNull() - .validateDateBeforeOrEqual(expectedDisbursementDate); - } - public void validateLoanCharges(final Set<LoanCharge> charges, final List<ApiParameterError> dataValidationErrors) { if (charges == null) { return; } final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan"); @@ -1139,32 +1143,11 @@ public final class LoanApplicationCommandFromApiJsonHelper { public void validateLoanForInterestRecalculation(final Loan loan) { final List<ApiParameterError> dataValidationErrors = new ArrayList<>(); - LoanInterestRecalculationDetails interestRecalculationDetails = loan.loanInterestRecalculationDetails(); - if (!interestRecalculationDetails.getRestFrequencyType().isSameAsRepayment()) { - String paramName = LoanProductConstants.recalculationRestFrequencyDateParamName; - validateRecalcuationFrequency(interestRecalculationDetails.getRestFrequencyLocalDate(), loan.getExpectedDisbursedOnLocalDate(), - dataValidationErrors, paramName); - } - - if (interestRecalculationDetails.getInterestRecalculationCompoundingMethod().isCompoundingEnabled() - && !interestRecalculationDetails.getCompoundingFrequencyType().isSameAsRepayment()) { - String paramName = LoanProductConstants.recalculationCompoundingFrequencyDateParamName; - validateCompoundingFrequency(interestRecalculationDetails.getCompoundingFrequencyLocalDate(), - loan.getExpectedDisbursedOnLocalDate(), dataValidationErrors, paramName); - } validateLoanCharges(loan.charges(), dataValidationErrors); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } - public void validateCompoundingFrequency(final LocalDate recalculationFrequencyDate, final LocalDate expectedDisbursementDate, - final List<ApiParameterError> dataValidationErrors, final String paramName) { - - final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan"); - baseDataValidator.reset().parameter(paramName).value(recalculationFrequencyDate).notNull() - .validateDateForEqual(expectedDisbursementDate); - } - private void validatePartialPeriodSupport(final Integer interestCalculationPeriodType, final DataValidatorBuilder baseDataValidator, final JsonElement element, final LoanProduct loanProduct) { if (interestCalculationPeriodType != null) { http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformService.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformService.java index 8f48eeb..277fdd8 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformService.java @@ -33,5 +33,6 @@ public interface LoanAccrualPlatformService { void addAccrualAccounting() throws JobExecutionException; void addPeriodicAccruals() throws JobExecutionException; + void addPeriodicAccrualsForLoansWithIncomePostedAsTransactions() throws JobExecutionException; } http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformServiceImpl.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformServiceImpl.java index a790f4e..7365d15 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformServiceImpl.java @@ -117,4 +117,24 @@ public class LoanAccrualPlatformServiceImpl implements LoanAccrualPlatformServic return sb.toString(); } + @Override + @CronTarget(jobName = JobName.ADD_PERIODIC_ACCRUAL_ENTRIES_FOR_LOANS_WITH_INCOME_POSTED_AS_TRANSACTIONS) + public void addPeriodicAccrualsForLoansWithIncomePostedAsTransactions() throws JobExecutionException { + Collection<Long> loanIds = this.loanReadPlatformService.retrieveLoanIdsWithPendingIncomePostingTransactions(); + if(loanIds != null && loanIds.size() > 0){ + StringBuilder sb = new StringBuilder(); + for (Long loanId : loanIds) { + try { + this.loanAccrualWritePlatformService.addIncomeAndAccrualTransactions(loanId); + } catch (Exception e) { + Throwable realCause = e; + if (e.getCause() != null) { + realCause = e.getCause(); + } + sb.append("failed to add income and accrual transaction for loan " + loanId + " with message " + realCause.getMessage()); + } + } + if (sb.length() > 0) { throw new JobExecutionException(sb.toString()); } + } + } } http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformService.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformService.java index 1e63a7c..1044279 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformService.java @@ -29,4 +29,5 @@ public interface LoanAccrualWritePlatformService { void addPeriodicAccruals(LocalDate tilldate, Long loanId, Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas) throws Exception; + void addIncomeAndAccrualTransactions(Long loanId) throws Exception; } http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformServiceImpl.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformServiceImpl.java index 79c54ff..5ac0b64 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformServiceImpl.java @@ -32,15 +32,22 @@ import javax.sql.DataSource; import org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlatformService; import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.core.service.RoutingDataSource; +import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency; +import org.apache.fineract.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper; +import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency; import org.apache.fineract.organisation.monetary.domain.MoneyHelper; import org.apache.fineract.portfolio.loanaccount.data.LoanChargeData; import org.apache.fineract.portfolio.loanaccount.data.LoanInstallmentChargeData; import org.apache.fineract.portfolio.loanaccount.data.LoanScheduleAccrualData; import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionData; import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionEnumData; +import org.apache.fineract.portfolio.loanaccount.domain.Loan; +import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository; import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType; +import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException; import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePeriodData; import org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations; +import org.apache.fineract.useradministration.domain.AppUserRepositoryWrapper; import org.joda.time.Days; import org.joda.time.LocalDate; import org.springframework.beans.factory.annotation.Autowired; @@ -56,16 +63,23 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat private final JdbcTemplate jdbcTemplate; private final DataSource dataSource; private final JournalEntryWritePlatformService journalEntryWritePlatformService; + private final AppUserRepositoryWrapper userRepository; + private final LoanRepository loanRepository; + private final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepository; @Autowired public LoanAccrualWritePlatformServiceImpl(final RoutingDataSource dataSource, final LoanReadPlatformService loanReadPlatformService, final JournalEntryWritePlatformService journalEntryWritePlatformService, - final LoanChargeReadPlatformService loanChargeReadPlatformService) { + final LoanChargeReadPlatformService loanChargeReadPlatformService, final AppUserRepositoryWrapper userRepository, + final LoanRepository loanRepository, final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepository) { this.loanReadPlatformService = loanReadPlatformService; this.dataSource = dataSource; this.jdbcTemplate = new JdbcTemplate(this.dataSource); this.journalEntryWritePlatformService = journalEntryWritePlatformService; this.loanChargeReadPlatformService = loanChargeReadPlatformService; + this.userRepository = userRepository; + this.loanRepository = loanRepository; + this.applicationCurrencyRepository = applicationCurrencyRepository; } @Override @@ -469,4 +483,29 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat accrualData.updateAccruableIncome(interestIncome); } + @Override + @Transactional + public void addIncomeAndAccrualTransactions(Long loanId) throws Exception { + if (loanId != null) { + Loan loan = this.loanRepository.findOne(loanId); + if (loan == null) { throw new LoanNotFoundException(loanId); } + final List<Long> existingTransactionIds = new ArrayList<>(); + final List<Long> existingReversedTransactionIds = new ArrayList<>(); + existingTransactionIds.addAll(loan.findExistingTransactionIds()); + existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds()); + loan.processIncomeTransactions(this.userRepository.fetchSystemUser()); + this.loanRepository.saveAndFlush(loan); + postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds); + } + } + + private void postJournalEntries(final Loan loan, final List<Long> existingTransactionIds, + final List<Long> existingReversedTransactionIds) { + final MonetaryCurrency currency = loan.getCurrency(); + final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency); + boolean isAccountTransfer = false; + final Map<String, Object> accountingBridgeData = loan.deriveAccountingBridgeData(applicationCurrency.toData(), + existingTransactionIds, existingReversedTransactionIds, isAccountTransfer); + this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData); + } } http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java index 8d5ce19..0bcdd09 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java @@ -55,6 +55,7 @@ import org.apache.fineract.portfolio.calendar.domain.CalendarInstanceRepository; import org.apache.fineract.portfolio.calendar.domain.CalendarRepository; import org.apache.fineract.portfolio.calendar.domain.CalendarType; import org.apache.fineract.portfolio.calendar.exception.CalendarNotFoundException; +import org.apache.fineract.portfolio.calendar.service.CalendarReadPlatformService; import org.apache.fineract.portfolio.charge.domain.Charge; import org.apache.fineract.portfolio.client.domain.AccountNumberGenerator; import org.apache.fineract.portfolio.client.domain.Client; @@ -64,6 +65,7 @@ import org.apache.fineract.portfolio.collateral.domain.LoanCollateral; import org.apache.fineract.portfolio.collateral.service.CollateralAssembler; import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_ENTITY; import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_EVENTS; +import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType; import org.apache.fineract.portfolio.common.service.BusinessEventNotifierService; import org.apache.fineract.portfolio.fund.domain.Fund; import org.apache.fineract.portfolio.group.domain.Group; @@ -88,6 +90,7 @@ import org.apache.fineract.portfolio.loanaccount.exception.LoanApplicationNotInS import org.apache.fineract.portfolio.loanaccount.exception.LoanApplicationNotInSubmittedAndPendingApprovalStateCannotBeModified; import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException; import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.AprCalculator; +import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms; import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModel; import org.apache.fineract.portfolio.loanaccount.loanschedule.service.LoanScheduleAssembler; import org.apache.fineract.portfolio.loanaccount.loanschedule.service.LoanScheduleCalculationPlatformService; @@ -108,7 +111,6 @@ import org.apache.fineract.portfolio.savings.domain.SavingsAccount; import org.apache.fineract.portfolio.savings.domain.SavingsAccountAssembler; import org.apache.fineract.useradministration.domain.AppUser; import org.joda.time.LocalDate; -import org.joda.time.LocalTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -153,6 +155,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa private final ConfigurationDomainService configurationDomainService; private final LoanScheduleAssembler loanScheduleAssembler; private final LoanUtilService loanUtilService; + private final CalendarReadPlatformService calendarReadPlatformService; @Autowired public LoanApplicationWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final FromJsonHelper fromJsonHelper, @@ -171,7 +174,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa final LoanReadPlatformService loanReadPlatformService, final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository, final BusinessEventNotifierService businessEventNotifierService, final ConfigurationDomainService configurationDomainService, - final LoanScheduleAssembler loanScheduleAssembler, final LoanUtilService loanUtilService) { + final LoanScheduleAssembler loanScheduleAssembler, final LoanUtilService loanUtilService, + final CalendarReadPlatformService calendarReadPlatformService) { this.context = context; this.fromJsonHelper = fromJsonHelper; this.loanApplicationTransitionApiJsonValidator = loanApplicationTransitionApiJsonValidator; @@ -201,6 +205,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa this.configurationDomainService = configurationDomainService; this.loanScheduleAssembler = loanScheduleAssembler; this.loanUtilService = loanUtilService; + this.calendarReadPlatformService = calendarReadPlatformService; } private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() { @@ -288,6 +293,26 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa final CalendarInstance calendarInstance = new CalendarInstance(calendar, newLoanApplication.getId(), CalendarEntityType.LOANS.getValue()); this.calendarInstanceRepository.save(calendarInstance); + } else { + final LoanApplicationTerms loanApplicationTerms = this.loanScheduleAssembler.assembleLoanTerms(command.parsedJson()); + final Integer repaymentFrequencyNthDayType = command.integerValueOfParameterNamed("repaymentFrequencyNthDayType"); + if (loanApplicationTerms.getRepaymentPeriodFrequencyType() == PeriodFrequencyType.MONTHS + && repaymentFrequencyNthDayType != null) { + final String title = "loan_schedule_" + newLoanApplication.getId(); + LocalDate calendarStartDate = loanApplicationTerms.getRepaymentsStartingFromLocalDate(); + if (calendarStartDate == null) calendarStartDate = loanApplicationTerms.getExpectedDisbursementDate(); + final CalendarFrequencyType calendarFrequencyType = CalendarFrequencyType.MONTHLY; + final Integer frequency = loanApplicationTerms.getRepaymentEvery(); + final Integer repeatsOnDay = loanApplicationTerms.getWeekDayType().getValue(); + final Integer repeatsOnNthDayOfMonth = loanApplicationTerms.getNthDay(); + final Integer calendarEntityType = CalendarEntityType.LOANS.getValue(); + final Calendar loanCalendar = Calendar.createRepeatingCalendar(title, calendarStartDate, + CalendarType.COLLECTION.getValue(), calendarFrequencyType, frequency, repeatsOnDay, repeatsOnNthDayOfMonth); + this.calendarRepository.save(loanCalendar); + final CalendarInstance calendarInstance = CalendarInstance.from(loanCalendar, newLoanApplication.getId(), + calendarEntityType); + this.calendarInstanceRepository.save(calendarInstance); + } } // Save linked account information @@ -357,43 +382,49 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa private void createAndPersistCalendarInstanceForInterestRecalculation(final Loan loan) { - LocalDate calendarStartDate = loan.loanInterestRecalculationDetails().getRestFrequencyLocalDate(); - if (calendarStartDate == null) { - calendarStartDate = loan.getExpectedDisbursedOnLocalDate(); - } - final Integer repeatsOnDay = calendarStartDate.getDayOfWeek(); + LocalDate calendarStartDate = loan.getExpectedDisbursedOnLocalDate(); + Integer repeatsOnDay = null; final RecalculationFrequencyType recalculationFrequencyType = loan.loanInterestRecalculationDetails().getRestFrequencyType(); + Integer recalculationFrequencyNthDay = loan.loanInterestRecalculationDetails().getRestFrequencyOnDay(); + if (recalculationFrequencyNthDay == null) { + recalculationFrequencyNthDay = loan.loanInterestRecalculationDetails().getRestFrequencyNthDay(); + repeatsOnDay = loan.loanInterestRecalculationDetails().getRestFrequencyWeekday(); + } Integer frequency = loan.loanInterestRecalculationDetails().getRestInterval(); CalendarEntityType calendarEntityType = CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL; final String title = "loan_recalculation_detail_" + loan.loanInterestRecalculationDetails().getId(); - createCalendar(loan, calendarStartDate, repeatsOnDay, recalculationFrequencyType, frequency, calendarEntityType, title); + createCalendar(loan, calendarStartDate, recalculationFrequencyNthDay, repeatsOnDay, recalculationFrequencyType, frequency, + calendarEntityType, title); if (loan.loanInterestRecalculationDetails().getInterestRecalculationCompoundingMethod().isCompoundingEnabled()) { - LocalDate compoundingStartDate = loan.loanInterestRecalculationDetails().getCompoundingFrequencyLocalDate(); - if (compoundingStartDate == null) { - compoundingStartDate = loan.getExpectedDisbursedOnLocalDate(); - } - final Integer compoundingRepeatsOnDay = compoundingStartDate.getDayOfWeek(); + LocalDate compoundingStartDate = loan.getExpectedDisbursedOnLocalDate(); + Integer compoundingRepeatsOnDay = null; final RecalculationFrequencyType recalculationCompoundingFrequencyType = loan.loanInterestRecalculationDetails() .getCompoundingFrequencyType(); + Integer recalculationCompoundingFrequencyNthDay = loan.loanInterestRecalculationDetails().getCompoundingFrequencyOnDay(); + if (recalculationCompoundingFrequencyNthDay == null) { + recalculationCompoundingFrequencyNthDay = loan.loanInterestRecalculationDetails().getCompoundingFrequencyNthDay(); + compoundingRepeatsOnDay = loan.loanInterestRecalculationDetails().getCompoundingFrequencyWeekday(); + } Integer compoundingFrequency = loan.loanInterestRecalculationDetails().getCompoundingInterval(); CalendarEntityType compoundingCalendarEntityType = CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL; final String compoundingCalendarTitle = "loan_recalculation_detail_compounding_frequency" + loan.loanInterestRecalculationDetails().getId(); - createCalendar(loan, compoundingStartDate, compoundingRepeatsOnDay, recalculationCompoundingFrequencyType, - compoundingFrequency, compoundingCalendarEntityType, compoundingCalendarTitle); + createCalendar(loan, compoundingStartDate, recalculationCompoundingFrequencyNthDay, compoundingRepeatsOnDay, + recalculationCompoundingFrequencyType, compoundingFrequency, compoundingCalendarEntityType, compoundingCalendarTitle); } } - private void createCalendar(final Loan loan, LocalDate calendarStartDate, final Integer repeatsOnDay, - final RecalculationFrequencyType recalculationFrequencyType, Integer frequency, CalendarEntityType calendarEntityType, - final String title) { + private void createCalendar(final Loan loan, LocalDate calendarStartDate, Integer recalculationFrequencyNthDay, + final Integer repeatsOnDay, final RecalculationFrequencyType recalculationFrequencyType, Integer frequency, + CalendarEntityType calendarEntityType, final String title) { CalendarFrequencyType calendarFrequencyType = CalendarFrequencyType.INVALID; + Integer updatedRepeatsOnDay = repeatsOnDay; switch (recalculationFrequencyType) { case DAILY: calendarFrequencyType = CalendarFrequencyType.DAILY; @@ -405,6 +436,9 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa frequency = loan.repaymentScheduleDetail().getRepayEvery(); calendarFrequencyType = CalendarFrequencyType.from(loan.repaymentScheduleDetail().getRepaymentPeriodFrequencyType()); calendarStartDate = loan.getExpectedDisbursedOnLocalDate(); + if (updatedRepeatsOnDay == null) { + updatedRepeatsOnDay = calendarStartDate.getDayOfWeek(); + } break; case WEEKLY: calendarFrequencyType = CalendarFrequencyType.WEEKLY; @@ -414,71 +448,12 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa } final Calendar calendar = Calendar.createRepeatingCalendar(title, calendarStartDate, CalendarType.COLLECTION.getValue(), - calendarFrequencyType, frequency, repeatsOnDay); + calendarFrequencyType, frequency, updatedRepeatsOnDay, recalculationFrequencyNthDay); final CalendarInstance calendarInstance = CalendarInstance.from(calendar, loan.loanInterestRecalculationDetails().getId(), calendarEntityType.getValue()); this.calendarInstanceRepository.save(calendarInstance); } - private void updateRestCalendarDetailsForInterestRecalculation(final CalendarInstance calendarInstance, final Loan loan) { - - Calendar interestRecalculationRecurrings = calendarInstance.getCalendar(); - LocalDate calendarStartDate = loan.loanInterestRecalculationDetails().getRestFrequencyLocalDate(); - if (calendarStartDate == null) { - calendarStartDate = loan.getExpectedDisbursedOnLocalDate(); - } - final Integer repeatsOnDay = calendarStartDate.getDayOfWeek(); - final RecalculationFrequencyType recalculationFrequencyType = loan.loanInterestRecalculationDetails().getRestFrequencyType(); - - Integer frequency = loan.loanInterestRecalculationDetails().getRestInterval(); - - updateCalendar(loan, interestRecalculationRecurrings, calendarStartDate, repeatsOnDay, recalculationFrequencyType, frequency); - - } - - private void updateCompoundingCalendarDetailsForInterestRecalculation(final CalendarInstance calendarInstance, final Loan loan) { - - Calendar interestRecalculationRecurrings = calendarInstance.getCalendar(); - LocalDate calendarStartDate = loan.loanInterestRecalculationDetails().getCompoundingFrequencyLocalDate(); - if (calendarStartDate == null) { - calendarStartDate = loan.getExpectedDisbursedOnLocalDate(); - } - final Integer repeatsOnDay = calendarStartDate.getDayOfWeek(); - final RecalculationFrequencyType recalculationFrequencyType = loan.loanInterestRecalculationDetails().getCompoundingFrequencyType(); - - Integer frequency = loan.loanInterestRecalculationDetails().getCompoundingInterval(); - - updateCalendar(loan, interestRecalculationRecurrings, calendarStartDate, repeatsOnDay, recalculationFrequencyType, frequency); - - } - - private void updateCalendar(final Loan loan, Calendar interestRecalculationRecurrings, LocalDate calendarStartDate, - final Integer repeatsOnDay, final RecalculationFrequencyType recalculationFrequencyType, Integer frequency) { - CalendarFrequencyType calendarFrequencyType = CalendarFrequencyType.INVALID; - switch (recalculationFrequencyType) { - case DAILY: - calendarFrequencyType = CalendarFrequencyType.DAILY; - break; - - case MONTHLY: - calendarFrequencyType = CalendarFrequencyType.MONTHLY; - break; - case SAME_AS_REPAYMENT_PERIOD: - calendarStartDate = loan.getExpectedDisbursedOnLocalDate(); - frequency = loan.repaymentScheduleDetail().getRepayEvery(); - calendarFrequencyType = CalendarFrequencyType.from(loan.repaymentScheduleDetail().getRepaymentPeriodFrequencyType()); - break; - case WEEKLY: - calendarFrequencyType = CalendarFrequencyType.WEEKLY; - break; - default: - break; - } - - interestRecalculationRecurrings.updateRepeatingCalendar(calendarStartDate, calendarFrequencyType, frequency, repeatsOnDay); - this.calendarRepository.save(interestRecalculationRecurrings); - } - @Transactional @Override public CommandProcessingResult modifyApplication(final Long loanId, final JsonCommand command) { @@ -551,7 +526,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa } } } - + final Set<LoanCollateral> possiblyModifedLoanCollateralItems = this.loanCollateralAssembler .fromParsedJson(command.parsedJson()); @@ -700,6 +675,11 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa // loan if (ciList != null && !ciList.isEmpty()) { final CalendarInstance calendarInstance = ciList.get(0); + final boolean isCalendarAssociatedWithEntity = this.calendarReadPlatformService.isCalendarAssociatedWithEntity(calendarInstance + .getEntityId(), calendarInstance.getCalendar().getId(), CalendarEntityType.LOANS.getValue().longValue()); + if (isCalendarAssociatedWithEntity) { + this.calendarRepository.delete(calendarInstance.getCalendar()); + } if (calendarInstance.getCalendar().getId() != calendar.getId()) { calendarInstance.updateCalendar(calendar); this.calendarInstanceRepository.saveAndFlush(calendarInstance); @@ -711,9 +691,65 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa this.calendarInstanceRepository.save(calendarInstance); } - } else if (ciList != null && !ciList.isEmpty()) { - final CalendarInstance calendarInstance = ciList.get(0); - this.calendarInstanceRepository.delete(calendarInstance); + } else { + if (ciList != null && !ciList.isEmpty()) { + final CalendarInstance existingCalendarInstance = ciList.get(0); + final boolean isCalendarAssociatedWithEntity = this.calendarReadPlatformService.isCalendarAssociatedWithEntity( + existingCalendarInstance.getEntityId(), existingCalendarInstance.getCalendar().getId(), + CalendarEntityType.GROUPS.getValue().longValue()); + if (isCalendarAssociatedWithEntity) { + this.calendarInstanceRepository.delete(existingCalendarInstance); + } + } + if (changes.containsKey("repaymentFrequencyNthDayType") || changes.containsKey("repaymentFrequencyDayOfWeekType")) { + if (changes.get("repaymentFrequencyNthDayType") == null) { + if (ciList != null && !ciList.isEmpty()) { + final CalendarInstance calendarInstance = ciList.get(0); + final boolean isCalendarAssociatedWithEntity = this.calendarReadPlatformService.isCalendarAssociatedWithEntity( + calendarInstance.getEntityId(), calendarInstance.getCalendar().getId(), CalendarEntityType.LOANS.getValue().longValue()); + if (isCalendarAssociatedWithEntity) { + this.calendarInstanceRepository.delete(calendarInstance); + this.calendarRepository.delete(calendarInstance.getCalendar()); + } + } + } else { + Integer repaymentFrequencyTypeInt = command.integerValueOfParameterNamed("repaymentFrequencyType"); + if (repaymentFrequencyTypeInt != null) { + if (PeriodFrequencyType.fromInt(repaymentFrequencyTypeInt) == PeriodFrequencyType.MONTHS) { + final String title = "loan_schedule_" + existingLoanApplication.getId(); + final Integer typeId = CalendarType.COLLECTION.getValue(); + final CalendarFrequencyType repaymentFrequencyType = CalendarFrequencyType.MONTHLY; + final Integer interval = command.integerValueOfParameterNamed("repaymentEvery"); + LocalDate startDate = command.localDateValueOfParameterNamed("repaymentsStartingFromDate"); + if (startDate == null) startDate = command.localDateValueOfParameterNamed("expectedDisbursementDate"); + final Calendar newCalendar = Calendar.createRepeatingCalendar(title, startDate, typeId, + repaymentFrequencyType, interval, (Integer) changes.get("repaymentFrequencyDayOfWeekType"), + (Integer) changes.get("repaymentFrequencyNthDayType")); + if (ciList != null && !ciList.isEmpty()) { + final CalendarInstance calendarInstance = ciList.get(0); + final boolean isCalendarAssociatedWithEntity = this.calendarReadPlatformService.isCalendarAssociatedWithEntity( + calendarInstance.getEntityId(), calendarInstance.getCalendar().getId(), CalendarEntityType.LOANS.getValue().longValue()); + if (isCalendarAssociatedWithEntity) { + final Calendar existingCalendar = calendarInstance.getCalendar(); + if (existingCalendar != null) { + String existingRecurrence = existingCalendar.getRecurrence(); + if (!existingRecurrence.equals(newCalendar.getRecurrence())) { + existingCalendar.setRecurrence(newCalendar.getRecurrence()); + this.calendarRepository.save(existingCalendar); + } + } + } + } else { + this.calendarRepository.save(newCalendar); + final Integer calendarEntityType = CalendarEntityType.LOANS.getValue(); + final CalendarInstance calendarInstance = new CalendarInstance(newCalendar, + existingLoanApplication.getId(), calendarEntityType); + this.calendarInstanceRepository.save(calendarInstance); + } + } + } + } + } } // Save linked account information @@ -776,20 +812,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa this.fromApiJsonDeserializer.validateLoanForInterestRecalculation(existingLoanApplication); if (changes.containsKey(LoanProductConstants.isInterestRecalculationEnabledParameterName)) { createAndPersistCalendarInstanceForInterestRecalculation(existingLoanApplication); - } else { - if (changes.containsKey(LoanProductConstants.recalculationRestFrequencyDateParamName)) { - CalendarInstance calendarInstance = this.calendarInstanceRepository.findByEntityIdAndEntityTypeIdAndCalendarTypeId( - existingLoanApplication.loanInterestRecalculationDetailId(), - CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue(), CalendarType.COLLECTION.getValue()); - updateRestCalendarDetailsForInterestRecalculation(calendarInstance, existingLoanApplication); - } - if (changes.containsKey(LoanProductConstants.recalculationCompoundingFrequencyDateParamName)) { - CalendarInstance calendarInstance = this.calendarInstanceRepository.findByEntityIdAndEntityTypeIdAndCalendarTypeId( - existingLoanApplication.loanInterestRecalculationDetailId(), - CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue(), CalendarType.COLLECTION.getValue()); - updateCompoundingCalendarDetailsForInterestRecalculation(calendarInstance, existingLoanApplication); - } } } http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java index 755a751..93df756 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java @@ -70,7 +70,6 @@ import org.apache.fineract.portfolio.loanaccount.exception.MultiDisbursementData import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms; import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModel; import org.apache.fineract.portfolio.loanaccount.loanschedule.service.LoanScheduleAssembler; -import org.apache.fineract.portfolio.loanproduct.LoanProductConstants; import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct; import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRelatedDetail; import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository; @@ -82,6 +81,7 @@ import org.apache.fineract.useradministration.domain.AppUser; import org.joda.time.LocalDate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; + import com.google.gson.JsonElement; @Service @@ -282,10 +282,6 @@ public class LoanAssembler { } } - final LocalDate recalculationRestFrequencyDate = this.fromApiJsonHelper.extractLocalDateNamed( - LoanProductConstants.recalculationRestFrequencyDateParamName, element); - final LocalDate recalculationCompoundingFrequencyDate = this.fromApiJsonHelper.extractLocalDateNamed( - LoanProductConstants.recalculationCompoundingFrequencyDateParamName, element); final LoanApplicationTerms loanApplicationTerms = this.loanScheduleAssembler.assembleLoanTerms(element); final boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled(); @@ -297,8 +293,7 @@ public class LoanAssembler { final LoanScheduleModel loanScheduleModel = this.loanScheduleAssembler.assembleLoanScheduleFrom(loanApplicationTerms, isHolidayEnabled, holidays, workingDays, element,disbursementDetails); loanApplication.loanApplicationSubmittal(currentUser, loanScheduleModel, loanApplicationTerms, defaultLoanLifecycleStateMachine(), - submittedOnDate, externalId, allowTransactionsOnHoliday, holidays, workingDays, allowTransactionsOnNonWorkingDay, - recalculationRestFrequencyDate, recalculationCompoundingFrequencyDate); + submittedOnDate, externalId, allowTransactionsOnHoliday, holidays, workingDays, allowTransactionsOnNonWorkingDay); return loanApplication; } http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java index e41860d..f6df4e4 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java @@ -126,4 +126,5 @@ public interface LoanReadPlatformService { LoanTransactionData retrieveRefundByCashTemplate(Long loanId); Collection<InterestRatePeriodData> retrieveLoanInterestRatePeriodData(Long loanId); + Collection<Long> retrieveLoanIdsWithPendingIncomePostingTransactions(); } \ No newline at end of file
